Merge branch 'system-language-names' into 'master'
get language names from system, instead of hard coded list Closes #908 and #858 See merge request !461
This commit is contained in:
commit
78ecba646c
@ -13,7 +13,6 @@ before_script:
|
|||||||
test:
|
test:
|
||||||
script:
|
script:
|
||||||
- cd app
|
- cd app
|
||||||
- ./tools/langs-list-check.py
|
|
||||||
- ./tools/check-string-format.py
|
- ./tools/check-string-format.py
|
||||||
- cd ..
|
- cd ..
|
||||||
- ./gradlew assemble -PdisablePreDex
|
- ./gradlew assemble -PdisablePreDex
|
||||||
|
23
RELEASE_CHECKLIST.md
Normal file
23
RELEASE_CHECKLIST.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
# Release Checklist
|
||||||
|
|
||||||
|
This is the things that need to happen for all releases, alpha or stable:
|
||||||
|
|
||||||
|
* pull translations from Weblate: ./tools/pull-trans.sh
|
||||||
|
|
||||||
|
* rebase Weblate in its web interface, since we squash commits
|
||||||
|
|
||||||
|
* update `versionCode` in _app/build.gradle_
|
||||||
|
|
||||||
|
* make signed tag with version name
|
||||||
|
|
||||||
|
* update _metadata/org.fdroid.fdroid.txt_ in _fdroiddata_
|
||||||
|
|
||||||
|
## Stable releases
|
||||||
|
|
||||||
|
For stable releases, there are a couple more steps to do __before__
|
||||||
|
making the release tag:
|
||||||
|
|
||||||
|
* update CHANGELOG.md
|
||||||
|
|
||||||
|
* run `./tools/trim-incomplete-translations-for-release.py`
|
@ -27,7 +27,6 @@ import android.bluetooth.BluetoothAdapter;
|
|||||||
import android.bluetooth.BluetoothManager;
|
import android.bluetooth.BluetoothManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
@ -36,16 +35,15 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiskCache;
|
import com.nostra13.universalimageloader.cache.disc.impl.LimitedAgeDiskCache;
|
||||||
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
|
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
import org.acra.ACRA;
|
import org.acra.ACRA;
|
||||||
import org.acra.ReportingInteractionMode;
|
import org.acra.ReportingInteractionMode;
|
||||||
import org.acra.annotation.ReportsCrashes;
|
import org.acra.annotation.ReportsCrashes;
|
||||||
@ -59,17 +57,13 @@ import org.fdroid.fdroid.data.Repo;
|
|||||||
import org.fdroid.fdroid.installer.InstallHistoryService;
|
import org.fdroid.fdroid.installer.InstallHistoryService;
|
||||||
import org.fdroid.fdroid.net.ImageLoaderForUIL;
|
import org.fdroid.fdroid.net.ImageLoaderForUIL;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
|
import sun.net.www.protocol.bluetooth.Handler;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLStreamHandler;
|
import java.net.URLStreamHandler;
|
||||||
import java.net.URLStreamHandlerFactory;
|
import java.net.URLStreamHandlerFactory;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import info.guardianproject.netcipher.NetCipher;
|
|
||||||
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
|
||||||
import sun.net.www.protocol.bluetooth.Handler;
|
|
||||||
|
|
||||||
@ReportsCrashes(mailTo = "reports@f-droid.org",
|
@ReportsCrashes(mailTo = "reports@f-droid.org",
|
||||||
mode = ReportingInteractionMode.DIALOG,
|
mode = ReportingInteractionMode.DIALOG,
|
||||||
@ -82,8 +76,6 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
public static final String SYSTEM_DIR_NAME = Environment.getRootDirectory().getAbsolutePath();
|
public static final String SYSTEM_DIR_NAME = Environment.getRootDirectory().getAbsolutePath();
|
||||||
|
|
||||||
private static Locale locale;
|
|
||||||
|
|
||||||
// for the local repo on this device, all static since there is only one
|
// for the local repo on this device, all static since there is only one
|
||||||
public static volatile int port;
|
public static volatile int port;
|
||||||
public static volatile String ipAddressString;
|
public static volatile String ipAddressString;
|
||||||
@ -181,25 +173,10 @@ public class FDroidApp extends Application {
|
|||||||
repo = new Repo();
|
repo = new Repo();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLanguage() {
|
|
||||||
Context ctx = getBaseContext();
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
|
|
||||||
String lang = prefs.getString(Preferences.PREF_LANGUAGE, "");
|
|
||||||
locale = Utils.getLocaleFromAndroidLangTag(lang);
|
|
||||||
applyLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyLanguage() {
|
|
||||||
Context ctx = getBaseContext();
|
|
||||||
Configuration cfg = new Configuration();
|
|
||||||
cfg.locale = locale == null ? Locale.getDefault() : locale;
|
|
||||||
ctx.getResources().updateConfiguration(cfg, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
applyLanguage();
|
Languages.setLanguage(this, Preferences.get().getLangauge(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -215,7 +192,9 @@ public class FDroidApp extends Application {
|
|||||||
.penaltyLog()
|
.penaltyLog()
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
updateLanguage();
|
Preferences.setup(this);
|
||||||
|
Languages.setup(getClass(), R.string.pref_language_default);
|
||||||
|
Languages.setLanguage(this, Preferences.get().getLangauge(), false);
|
||||||
|
|
||||||
ACRA.init(this);
|
ACRA.init(this);
|
||||||
if (isAcraProcess()) {
|
if (isAcraProcess()) {
|
||||||
@ -224,7 +203,6 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
PRNGFixes.apply();
|
PRNGFixes.apply();
|
||||||
|
|
||||||
Preferences.setup(this);
|
|
||||||
curTheme = Preferences.get().getTheme();
|
curTheme = Preferences.get().getTheme();
|
||||||
Preferences.get().configureProxy();
|
Preferences.get().configureProxy();
|
||||||
|
|
||||||
@ -325,13 +303,13 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks if the current process is "org.fdroid.fdroid:acra".
|
* Asks if the current process is "org.fdroid.fdroid:acra".
|
||||||
*
|
* <p>
|
||||||
* This is helpful for bailing out of the {@link FDroidApp#onCreate} method early, preventing
|
* This is helpful for bailing out of the {@link FDroidApp#onCreate} method early, preventing
|
||||||
* problems that arise from executing the code twice. This happens due to the `android:process`
|
* problems that arise from executing the code twice. This happens due to the `android:process`
|
||||||
* statement in AndroidManifest.xml causes another process to be created to run
|
* statement in AndroidManifest.xml causes another process to be created to run
|
||||||
* {@link org.fdroid.fdroid.acra.CrashReportActivity}. This was causing lots of things to be
|
* {@link org.fdroid.fdroid.acra.CrashReportActivity}. This was causing lots of things to be
|
||||||
* started/run twice including {@link CleanCacheService} and {@link WifiStateChangeService}.
|
* started/run twice including {@link CleanCacheService} and {@link WifiStateChangeService}.
|
||||||
*
|
* <p>
|
||||||
* Note that it is not perfect, because some devices seem to not provide a list of running app
|
* Note that it is not perfect, because some devices seem to not provide a list of running app
|
||||||
* processes when asked. In such situations, F-Droid may regress to the behaviour where some
|
* processes when asked. In such situations, F-Droid may regress to the behaviour where some
|
||||||
* services may run twice and thus cause weirdness or slowness. However that is probably better
|
* services may run twice and thus cause weirdness or slowness. However that is probably better
|
||||||
|
285
app/src/main/java/org/fdroid/fdroid/Languages.java
Normal file
285
app/src/main/java/org/fdroid/fdroid/Languages.java
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
public final class Languages {
|
||||||
|
public static final String TAG = "Languages";
|
||||||
|
|
||||||
|
public static final String USE_SYSTEM_DEFAULT = "";
|
||||||
|
|
||||||
|
private static final Locale DEFAULT_LOCALE;
|
||||||
|
private static final Locale TIBETAN = new Locale("bo");
|
||||||
|
private static final Locale CHINESE_HONG_KONG = new Locale("zh", "HK");
|
||||||
|
private static final String DEFAULT_STRING = "System Default";
|
||||||
|
|
||||||
|
private static Locale locale;
|
||||||
|
private static Languages singleton;
|
||||||
|
private static Class<?> clazz;
|
||||||
|
private static int resId;
|
||||||
|
private static Map<String, String> tmpMap = new TreeMap<>();
|
||||||
|
private static Map<String, String> nameMap;
|
||||||
|
|
||||||
|
static {
|
||||||
|
DEFAULT_LOCALE = Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Languages(Activity activity) {
|
||||||
|
AssetManager assets = activity.getAssets();
|
||||||
|
Configuration config = activity.getResources().getConfiguration();
|
||||||
|
// Resources() requires DisplayMetrics, but they are only needed for drawables
|
||||||
|
DisplayMetrics ignored = new DisplayMetrics();
|
||||||
|
activity.getWindowManager().getDefaultDisplay().getMetrics(ignored);
|
||||||
|
Resources resources;
|
||||||
|
Set<Locale> localeSet = new LinkedHashSet<>();
|
||||||
|
for (Locale locale : LOCALES_TO_TEST) {
|
||||||
|
config.locale = locale;
|
||||||
|
resources = new Resources(assets, ignored, config);
|
||||||
|
if (!TextUtils.equals(DEFAULT_STRING, resources.getString(resId))
|
||||||
|
|| locale.equals(Locale.ENGLISH)) {
|
||||||
|
localeSet.add(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Locale locale : localeSet) {
|
||||||
|
if (locale.equals(TIBETAN)) {
|
||||||
|
// include English name for devices without Tibetan font support
|
||||||
|
tmpMap.put(TIBETAN.getLanguage(), "Tibetan བོད་སྐད།"); // Tibetan
|
||||||
|
} else if (locale.equals(Locale.SIMPLIFIED_CHINESE)) {
|
||||||
|
tmpMap.put(Locale.SIMPLIFIED_CHINESE.toString(), "中文 (中国)"); // Chinese (China)
|
||||||
|
} else if (locale.equals(Locale.TRADITIONAL_CHINESE)) {
|
||||||
|
tmpMap.put(Locale.TRADITIONAL_CHINESE.toString(), "中文 (台灣)"); // Chinese (Taiwan)
|
||||||
|
} else if (locale.equals(CHINESE_HONG_KONG)) {
|
||||||
|
tmpMap.put(CHINESE_HONG_KONG.toString(), "中文 (香港)"); // Chinese (Hong Kong)
|
||||||
|
} else {
|
||||||
|
tmpMap.put(locale.getLanguage(), capitalize(locale.getDisplayLanguage(locale)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SYSTEM_DEFAULT is a fake one for displaying in a chooser menu. */
|
||||||
|
localeSet.add(null);
|
||||||
|
tmpMap.put(USE_SYSTEM_DEFAULT, activity.getString(resId));
|
||||||
|
nameMap = Collections.unmodifiableMap(tmpMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the instance of {@link Languages} to work with, providing the
|
||||||
|
* {@link Activity} that is will be working as part of, as well as the
|
||||||
|
* {@code resId} that has the exact string "Use System Default",
|
||||||
|
* i.e. {@code R.string.use_system_default}.
|
||||||
|
* <p/>
|
||||||
|
* That string resource {@code resId} is also used to find the supported
|
||||||
|
* translations: if an included translation has a translated string that
|
||||||
|
* matches that {@code resId}, then that language will be included as a
|
||||||
|
* supported language.
|
||||||
|
*
|
||||||
|
* @param clazz the {@link Class} of the default {@code Activity},
|
||||||
|
* usually the main {@code Activity} from where the
|
||||||
|
* Settings is launched from.
|
||||||
|
* @param resId the string resource ID to for the string "System Default",
|
||||||
|
* e.g. {@code R.string.pref_language_default}
|
||||||
|
*/
|
||||||
|
public static void setup(Class<?> clazz, int resId) {
|
||||||
|
if (Languages.clazz == null) {
|
||||||
|
Languages.clazz = clazz;
|
||||||
|
Languages.resId = resId;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Languages singleton was already initialized, duplicate call to Languages.setup()!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param activity the {@link Activity} this is working as part of
|
||||||
|
* @return the singleton to work with
|
||||||
|
*/
|
||||||
|
public static Languages get(Activity activity) {
|
||||||
|
if (singleton == null) {
|
||||||
|
singleton = new Languages(activity);
|
||||||
|
}
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(17)
|
||||||
|
public static void setLanguage(final ContextWrapper contextWrapper, String language, boolean refresh) {
|
||||||
|
if (locale != null && TextUtils.equals(locale.getLanguage(), language) && (!refresh)) {
|
||||||
|
return; // already configured
|
||||||
|
} else if (language == null || language.equals(USE_SYSTEM_DEFAULT)) {
|
||||||
|
locale = DEFAULT_LOCALE;
|
||||||
|
} else {
|
||||||
|
/* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */
|
||||||
|
String[] localeSplit = language.split("_");
|
||||||
|
if (localeSplit.length > 1) {
|
||||||
|
locale = new Locale(localeSplit[0], localeSplit[1]);
|
||||||
|
} else {
|
||||||
|
locale = new Locale(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Resources resources = contextWrapper.getBaseContext().getResources();
|
||||||
|
Configuration config = resources.getConfiguration();
|
||||||
|
if (Build.VERSION.SDK_INT >= 17) {
|
||||||
|
config.setLocale(locale);
|
||||||
|
} else {
|
||||||
|
config.locale = locale;
|
||||||
|
}
|
||||||
|
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force reload the {@link Activity to make language changes take effect.}
|
||||||
|
*
|
||||||
|
* @param activity the {@code Activity} to force reload
|
||||||
|
*/
|
||||||
|
public static void forceChangeLanguage(Activity activity) {
|
||||||
|
Intent intent = activity.getIntent();
|
||||||
|
if (intent == null) { // when launched as LAUNCHER
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||||
|
activity.finish();
|
||||||
|
activity.overridePendingTransition(0, 0);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
activity.overridePendingTransition(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name of the language based on the locale.
|
||||||
|
*/
|
||||||
|
public String getName(String locale) {
|
||||||
|
String ret = nameMap.get(locale);
|
||||||
|
// if no match, try to return a more general name (i.e. English for en_IN)
|
||||||
|
if (ret == null && locale.contains("_")) {
|
||||||
|
ret = nameMap.get(locale.split("_")[0]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return an array of the names of all the supported languages, sorted to
|
||||||
|
* match what is returned by {@link Languages#getSupportedLocales()}.
|
||||||
|
*/
|
||||||
|
public String[] getAllNames() {
|
||||||
|
return nameMap.values().toArray(new String[nameMap.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPosition(Locale locale) {
|
||||||
|
String localeName = locale.getLanguage();
|
||||||
|
int i = 0;
|
||||||
|
for (String key : nameMap.keySet()) {
|
||||||
|
if (TextUtils.equals(key, localeName)) {
|
||||||
|
return i;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return sorted list of supported locales.
|
||||||
|
*/
|
||||||
|
public String[] getSupportedLocales() {
|
||||||
|
Set<String> keys = nameMap.keySet();
|
||||||
|
return keys.toArray(new String[keys.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String capitalize(final String line) {
|
||||||
|
return Character.toUpperCase(line.charAt(0)) + line.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Locale[] LOCALES_TO_TEST = {
|
||||||
|
Locale.ENGLISH,
|
||||||
|
Locale.FRENCH,
|
||||||
|
Locale.GERMAN,
|
||||||
|
Locale.ITALIAN,
|
||||||
|
Locale.JAPANESE,
|
||||||
|
Locale.KOREAN,
|
||||||
|
Locale.SIMPLIFIED_CHINESE,
|
||||||
|
Locale.TRADITIONAL_CHINESE,
|
||||||
|
CHINESE_HONG_KONG,
|
||||||
|
TIBETAN,
|
||||||
|
new Locale("af"),
|
||||||
|
new Locale("am"),
|
||||||
|
new Locale("ar"),
|
||||||
|
new Locale("az"),
|
||||||
|
new Locale("be"),
|
||||||
|
new Locale("bg"),
|
||||||
|
new Locale("bn"),
|
||||||
|
new Locale("ca"),
|
||||||
|
new Locale("cs"),
|
||||||
|
new Locale("da"),
|
||||||
|
new Locale("el"),
|
||||||
|
new Locale("es"),
|
||||||
|
new Locale("et"),
|
||||||
|
new Locale("eu"),
|
||||||
|
new Locale("fa"),
|
||||||
|
new Locale("fi"),
|
||||||
|
new Locale("gl"),
|
||||||
|
new Locale("hi"),
|
||||||
|
new Locale("hr"),
|
||||||
|
new Locale("hu"),
|
||||||
|
new Locale("hy"),
|
||||||
|
new Locale("in"),
|
||||||
|
new Locale("hy"),
|
||||||
|
new Locale("in"),
|
||||||
|
new Locale("is"),
|
||||||
|
new Locale("it"),
|
||||||
|
new Locale("iw"),
|
||||||
|
new Locale("ka"),
|
||||||
|
new Locale("kk"),
|
||||||
|
new Locale("km"),
|
||||||
|
new Locale("kn"),
|
||||||
|
new Locale("ky"),
|
||||||
|
new Locale("lo"),
|
||||||
|
new Locale("lt"),
|
||||||
|
new Locale("lv"),
|
||||||
|
new Locale("mk"),
|
||||||
|
new Locale("ml"),
|
||||||
|
new Locale("mn"),
|
||||||
|
new Locale("mr"),
|
||||||
|
new Locale("ms"),
|
||||||
|
new Locale("my"),
|
||||||
|
new Locale("nb"),
|
||||||
|
new Locale("ne"),
|
||||||
|
new Locale("nl"),
|
||||||
|
new Locale("pl"),
|
||||||
|
new Locale("pt"),
|
||||||
|
new Locale("rm"),
|
||||||
|
new Locale("ro"),
|
||||||
|
new Locale("ru"),
|
||||||
|
new Locale("si"),
|
||||||
|
new Locale("sk"),
|
||||||
|
new Locale("sl"),
|
||||||
|
new Locale("sn"),
|
||||||
|
new Locale("sr"),
|
||||||
|
new Locale("sv"),
|
||||||
|
new Locale("sw"),
|
||||||
|
new Locale("ta"),
|
||||||
|
new Locale("te"),
|
||||||
|
new Locale("th"),
|
||||||
|
new Locale("tl"),
|
||||||
|
new Locale("tr"),
|
||||||
|
new Locale("uk"),
|
||||||
|
new Locale("ur"),
|
||||||
|
new Locale("uz"),
|
||||||
|
new Locale("vi"),
|
||||||
|
new Locale("zu"),
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -229,6 +229,10 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
.replaceAll(" ", "-");
|
.replaceAll(" ", "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLangauge() {
|
||||||
|
return preferences.getString(Preferences.PREF_LANGUAGE, "");
|
||||||
|
}
|
||||||
|
|
||||||
public String getLocalRepoName() {
|
public String getLocalRepoName() {
|
||||||
return preferences.getString(PREF_LOCAL_REPO_NAME, getDefaultLocalRepoName());
|
return preferences.getString(PREF_LOCAL_REPO_NAME, getDefaultLocalRepoName());
|
||||||
}
|
}
|
||||||
|
@ -12,19 +12,18 @@ import android.preference.Preference;
|
|||||||
import android.preference.PreferenceCategory;
|
import android.preference.PreferenceCategory;
|
||||||
import android.support.v4.preference.PreferenceFragment;
|
import android.support.v4.preference.PreferenceFragment;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import com.geecko.QuickLyric.view.AppCompatListPreference;
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
import org.fdroid.fdroid.AppDetails2;
|
import org.fdroid.fdroid.AppDetails2;
|
||||||
import org.fdroid.fdroid.CleanCacheService;
|
import org.fdroid.fdroid.CleanCacheService;
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.Languages;
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.UpdateService;
|
import org.fdroid.fdroid.UpdateService;
|
||||||
import org.fdroid.fdroid.installer.InstallHistoryService;
|
import org.fdroid.fdroid.installer.InstallHistoryService;
|
||||||
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||||
|
|
||||||
import info.guardianproject.netcipher.NetCipher;
|
|
||||||
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
|
||||||
|
|
||||||
public class PreferencesFragment extends PreferenceFragment
|
public class PreferencesFragment extends PreferenceFragment
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@ -62,6 +61,12 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
enableProxyCheckPref = (CheckBoxPreference) findPreference(Preferences.PREF_ENABLE_PROXY);
|
enableProxyCheckPref = (CheckBoxPreference) findPreference(Preferences.PREF_ENABLE_PROXY);
|
||||||
updateAutoDownloadPref = findPreference(Preferences.PREF_AUTO_DOWNLOAD_INSTALL_UPDATES);
|
updateAutoDownloadPref = findPreference(Preferences.PREF_AUTO_DOWNLOAD_INSTALL_UPDATES);
|
||||||
updatePrivilegedExtensionPref = findPreference(Preferences.PREF_UNINSTALL_PRIVILEGED_APP);
|
updatePrivilegedExtensionPref = findPreference(Preferences.PREF_UNINSTALL_PRIVILEGED_APP);
|
||||||
|
|
||||||
|
AppCompatListPreference languagePref = (AppCompatListPreference) findPreference(Preferences.PREF_LANGUAGE);
|
||||||
|
Languages languages = Languages.get(getActivity());
|
||||||
|
languagePref.setDefaultValue(Languages.USE_SYSTEM_DEFAULT);
|
||||||
|
languagePref.setEntries(languages.getAllNames());
|
||||||
|
languagePref.setEntryValues(languages.getSupportedLocales());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSummary(String key, int resId) {
|
private void checkSummary(String key, int resId) {
|
||||||
@ -136,8 +141,9 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
case Preferences.PREF_LANGUAGE:
|
case Preferences.PREF_LANGUAGE:
|
||||||
entrySummary(key);
|
entrySummary(key);
|
||||||
if (changing) {
|
if (changing) {
|
||||||
// TODO: Ask MainActivity to restart itself.
|
Activity activity = getActivity();
|
||||||
((FDroidApp) getActivity().getApplication()).updateLanguage();
|
Languages.setLanguage(activity, Preferences.get().getLangauge(), false);
|
||||||
|
Languages.forceChangeLanguage(activity);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -44,126 +44,4 @@
|
|||||||
<item>night</item>
|
<item>night</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="languageValues">
|
|
||||||
<item></item>
|
|
||||||
<item>en</item>
|
|
||||||
<item>af</item>
|
|
||||||
<item>ar</item>
|
|
||||||
<item>ast</item>
|
|
||||||
<item>be</item>
|
|
||||||
<item>bg</item>
|
|
||||||
<item>ca</item>
|
|
||||||
<item>cs</item>
|
|
||||||
<item>da</item>
|
|
||||||
<item>de</item>
|
|
||||||
<item>el</item>
|
|
||||||
<item>eo</item>
|
|
||||||
<item>es</item>
|
|
||||||
<item>et</item>
|
|
||||||
<item>eu</item>
|
|
||||||
<item>fa</item>
|
|
||||||
<item>fi</item>
|
|
||||||
<item>fr</item>
|
|
||||||
<item>gl</item>
|
|
||||||
<item>he</item>
|
|
||||||
<item>hi</item>
|
|
||||||
<item>hr</item>
|
|
||||||
<item>hu</item>
|
|
||||||
<item>hy</item>
|
|
||||||
<item>id</item>
|
|
||||||
<item>is</item>
|
|
||||||
<item>it</item>
|
|
||||||
<item>ja</item>
|
|
||||||
<item>ko</item>
|
|
||||||
<item>lt</item>
|
|
||||||
<item>lv</item>
|
|
||||||
<item>mk</item>
|
|
||||||
<item>my</item>
|
|
||||||
<item>nb</item>
|
|
||||||
<item>nl</item>
|
|
||||||
<item>pl</item>
|
|
||||||
<item>pt-rBR</item>
|
|
||||||
<item>pt-rPT</item>
|
|
||||||
<item>ro</item>
|
|
||||||
<item>ru</item>
|
|
||||||
<item>sc</item>
|
|
||||||
<item>sk</item>
|
|
||||||
<item>sl</item>
|
|
||||||
<item>sn</item>
|
|
||||||
<item>sq</item>
|
|
||||||
<item>sr</item>
|
|
||||||
<item>sv</item>
|
|
||||||
<item>ta</item>
|
|
||||||
<item>th</item>
|
|
||||||
<item>tr</item>
|
|
||||||
<item>ug</item>
|
|
||||||
<item>uk</item>
|
|
||||||
<item>ur</item>
|
|
||||||
<item>vi</item>
|
|
||||||
<item>zh-rCN</item>
|
|
||||||
<item>zh-rHK</item>
|
|
||||||
<item>zh-rTW</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="languageNames">
|
|
||||||
<item>@string/pref_language_default</item>
|
|
||||||
<item>English</item>
|
|
||||||
<item>Afrikaans</item>
|
|
||||||
<item>ﺎﻠﻋﺮﺒﻳﺓ</item>
|
|
||||||
<item>Asturian</item>
|
|
||||||
<item>белорусский</item>
|
|
||||||
<item>Български</item>
|
|
||||||
<item>Català</item>
|
|
||||||
<item>Čeština</item>
|
|
||||||
<item>Dansk</item>
|
|
||||||
<item>Deutsch</item>
|
|
||||||
<item>Ελληνικά</item>
|
|
||||||
<item>Esperanto</item>
|
|
||||||
<item>Español</item>
|
|
||||||
<item>Eesti</item>
|
|
||||||
<item>Euskara</item>
|
|
||||||
<item>ﻑﺍﺮﺳی</item>
|
|
||||||
<item>Suomi</item>
|
|
||||||
<item>Français</item>
|
|
||||||
<item>Galego</item>
|
|
||||||
<item>עברית</item>
|
|
||||||
<item>हिन्दी</item>
|
|
||||||
<item>Hrvatski</item>
|
|
||||||
<item>Magyar</item>
|
|
||||||
<item>հայերեն</item>
|
|
||||||
<item>Bahasa Indonesia</item>
|
|
||||||
<item>Íslenska</item>
|
|
||||||
<item>Italiano</item>
|
|
||||||
<item>日本語</item>
|
|
||||||
<item>한국어</item>
|
|
||||||
<item>Lietuvių</item>
|
|
||||||
<item>Latviešu</item>
|
|
||||||
<item>македонски</item>
|
|
||||||
<item>မြန်မာစာ</item>
|
|
||||||
<item>Norsk bokmål</item>
|
|
||||||
<item>Nederlands</item>
|
|
||||||
<item>Polski</item>
|
|
||||||
<item>Português (Brasil)</item>
|
|
||||||
<item>Português (Portugal)</item>
|
|
||||||
<item>Română</item>
|
|
||||||
<item>Русский</item>
|
|
||||||
<item>Sardinian</item>
|
|
||||||
<item>Slovenčina</item>
|
|
||||||
<item>Slovenščina</item>
|
|
||||||
<item>ChiSona</item>
|
|
||||||
<item>Shqip</item>
|
|
||||||
<item>Српски</item>
|
|
||||||
<item>Svenska</item>
|
|
||||||
<item>தமிழ்</item>
|
|
||||||
<item>ไทย</item>
|
|
||||||
<item>Türkçe</item>
|
|
||||||
<item>ﺉۇﻲﻏۇﺭچە</item>
|
|
||||||
<item>Українська</item>
|
|
||||||
<item>اردو</item>
|
|
||||||
<item>Tiếng Việt</item>
|
|
||||||
<item>中文 (中国)</item>
|
|
||||||
<item>中文 (香港)</item>
|
|
||||||
<item>中文 (台湾)</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -43,10 +43,7 @@
|
|||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/display">
|
<PreferenceCategory android:title="@string/display">
|
||||||
<com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/pref_language"
|
<com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/pref_language"
|
||||||
android:key="language"
|
android:key="language"/>
|
||||||
android:defaultValue=""
|
|
||||||
android:entries="@array/languageNames"
|
|
||||||
android:entryValues="@array/languageValues" />
|
|
||||||
<com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/theme"
|
<com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/theme"
|
||||||
android:key="theme"
|
android:key="theme"
|
||||||
android:defaultValue="light"
|
android:defaultValue="light"
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# List supported languages missing from the preference array
|
|
||||||
|
|
||||||
import glob
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
|
|
||||||
prefs = set([''])
|
|
||||||
trans = set(['', 'en'])
|
|
||||||
|
|
||||||
donottranslate = os.path.join('src', 'main', 'res', 'values', 'donottranslate.xml')
|
|
||||||
|
|
||||||
for e in ElementTree.parse(donottranslate).getroot().findall('.//string-array'):
|
|
||||||
if e.attrib['name'] != 'languageValues':
|
|
||||||
continue
|
|
||||||
for i in e.findall('.//item'):
|
|
||||||
lang = i.text
|
|
||||||
if not lang:
|
|
||||||
continue
|
|
||||||
prefs.add(lang)
|
|
||||||
|
|
||||||
for d in glob.glob(os.path.join('src', 'main', 'res', 'values-*')):
|
|
||||||
lang = d[len(os.path.join('src', 'main', 'res', 'values-')):]
|
|
||||||
if not lang:
|
|
||||||
continue
|
|
||||||
if re.match('^sw[0-9]+dp|v[0-9]+$', lang):
|
|
||||||
continue
|
|
||||||
if lang == 'ldrtl':
|
|
||||||
continue
|
|
||||||
if os.path.islink(d):
|
|
||||||
continue
|
|
||||||
trans.add(lang)
|
|
||||||
|
|
||||||
print("In the settings array: %s" % ' '.join(sorted(prefs)))
|
|
||||||
print("Actually translated: %s" % ' '.join(sorted(trans)))
|
|
||||||
|
|
||||||
missing = []
|
|
||||||
for lang in trans:
|
|
||||||
if lang not in prefs:
|
|
||||||
missing.append(lang)
|
|
||||||
|
|
||||||
if missing:
|
|
||||||
print("Missing:")
|
|
||||||
for lang in missing:
|
|
||||||
print(" %s" % lang)
|
|
||||||
|
|
||||||
extra = []
|
|
||||||
for lang in prefs:
|
|
||||||
if lang not in trans:
|
|
||||||
extra.append(lang)
|
|
||||||
|
|
||||||
if extra:
|
|
||||||
print("Extra:")
|
|
||||||
for lang in extra:
|
|
||||||
print(" %s" % lang)
|
|
||||||
|
|
||||||
if not missing and not extra:
|
|
||||||
print("All good.")
|
|
||||||
else:
|
|
||||||
sys.exit(1)
|
|
42
tools/trim-incomplete-translations-for-release.py
Executable file
42
tools/trim-incomplete-translations-for-release.py
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import csv
|
||||||
|
import git
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
projectbasedir = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
print(projectbasedir)
|
||||||
|
|
||||||
|
repo = git.Repo(projectbasedir)
|
||||||
|
|
||||||
|
msg = 'removing all translations less than 75% complete\n\n'
|
||||||
|
|
||||||
|
url = 'https://hosted.weblate.org/exports/stats/f-droid/f-droid/?format=csv'
|
||||||
|
r = requests.get(url)
|
||||||
|
stats = csv.reader(r.iter_lines(decode_unicode=True), delimiter=',')
|
||||||
|
next(stats) # skip CSV header
|
||||||
|
for row in stats:
|
||||||
|
if len(row) > 4:
|
||||||
|
if float(row[4]) > 75.0:
|
||||||
|
continue
|
||||||
|
locale = row[1]
|
||||||
|
if '_' in locale:
|
||||||
|
codes = locale.split('_')
|
||||||
|
if codes[1] == 'Hans':
|
||||||
|
codes[1] = 'CN'
|
||||||
|
elif codes[1] == 'Hant':
|
||||||
|
codes[1] = 'TW'
|
||||||
|
locale = codes[0] + '-r' + codes[1]
|
||||||
|
translation_file = 'app/src/main/res/values-' + locale + '/strings.xml'
|
||||||
|
percent = str(int(float(row[4]))) + '%'
|
||||||
|
print('Removing incomplete file: (' + percent + ')\t',
|
||||||
|
translation_file)
|
||||||
|
os.remove(os.path.join(projectbasedir, translation_file))
|
||||||
|
repo.index.remove([translation_file, ])
|
||||||
|
if len(percent) == 2:
|
||||||
|
msg += ' '
|
||||||
|
msg += percent + ' ' + row[1] + ' ' + row[0] + '\n'
|
||||||
|
|
||||||
|
repo.index.commit(msg)
|
Loading…
x
Reference in New Issue
Block a user