Merge branch 'pre-0.103-alpha4-rename' into 'master'
nail down language pref handling for localized index metadata See merge request !496
This commit is contained in:
commit
11c42f6a2f
@ -194,7 +194,7 @@ public class FDroidApp extends Application {
|
|||||||
@Override
|
@Override
|
||||||
public void onConfigurationChanged(Configuration newConfig) {
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
super.onConfigurationChanged(newConfig);
|
super.onConfigurationChanged(newConfig);
|
||||||
Languages.setLanguage(this, Preferences.get().getLangauge(), false);
|
Languages.setLanguage(this, Preferences.get().getLanguage(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -212,7 +212,7 @@ public class FDroidApp extends Application {
|
|||||||
}
|
}
|
||||||
Preferences.setup(this);
|
Preferences.setup(this);
|
||||||
Languages.setup(getClass(), R.string.pref_language_default);
|
Languages.setup(getClass(), R.string.pref_language_default);
|
||||||
Languages.setLanguage(this, Preferences.get().getLangauge(), false);
|
Languages.setLanguage(this, Preferences.get().getLanguage(), false);
|
||||||
|
|
||||||
ACRA.init(this);
|
ACRA.init(this);
|
||||||
if (isAcraProcess()) {
|
if (isAcraProcess()) {
|
||||||
|
@ -117,9 +117,15 @@ public final class Languages {
|
|||||||
|
|
||||||
@TargetApi(17)
|
@TargetApi(17)
|
||||||
public static void setLanguage(final ContextWrapper contextWrapper, String language, boolean refresh) {
|
public static void setLanguage(final ContextWrapper contextWrapper, String language, boolean refresh) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
|
Utils.debugLog(TAG, "Languages.setLanguage() ignored on >= android-24");
|
||||||
|
Preferences.get().clearLanguage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (locale != null && TextUtils.equals(locale.getLanguage(), language) && (!refresh)) {
|
if (locale != null && TextUtils.equals(locale.getLanguage(), language) && (!refresh)) {
|
||||||
return; // already configured
|
return; // already configured
|
||||||
} else if (language == null || language.equals(USE_SYSTEM_DEFAULT)) {
|
} else if (language == null || language.equals(USE_SYSTEM_DEFAULT)) {
|
||||||
|
Preferences.get().clearLanguage();
|
||||||
locale = DEFAULT_LOCALE;
|
locale = DEFAULT_LOCALE;
|
||||||
} else {
|
} else {
|
||||||
/* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */
|
/* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */
|
||||||
@ -147,6 +153,10 @@ public final class Languages {
|
|||||||
* @param activity the {@code Activity} to force reload
|
* @param activity the {@code Activity} to force reload
|
||||||
*/
|
*/
|
||||||
public static void forceChangeLanguage(Activity activity) {
|
public static void forceChangeLanguage(Activity activity) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
|
Utils.debugLog(TAG, "Languages.forceChangeLanguage() ignored on >= android-24");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Intent intent = activity.getIntent();
|
Intent intent = activity.getIntent();
|
||||||
if (intent == null) { // when launched as LAUNCHER
|
if (intent == null) { // when launched as LAUNCHER
|
||||||
return;
|
return;
|
||||||
@ -158,18 +168,6 @@ public final class Languages {
|
|||||||
activity.overridePendingTransition(0, 0);
|
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
|
* @return an array of the names of all the supported languages, sorted to
|
||||||
* match what is returned by {@link Languages#getSupportedLocales()}.
|
* match what is returned by {@link Languages#getSupportedLocales()}.
|
||||||
@ -178,19 +176,6 @@ public final class Languages {
|
|||||||
return nameMap.values().toArray(new String[nameMap.size()]);
|
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.
|
* @return sorted list of supported locales.
|
||||||
*/
|
*/
|
||||||
|
@ -229,8 +229,12 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
.replaceAll(" ", "-");
|
.replaceAll(" ", "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLangauge() {
|
public String getLanguage() {
|
||||||
return preferences.getString(Preferences.PREF_LANGUAGE, "");
|
return preferences.getString(Preferences.PREF_LANGUAGE, Languages.USE_SYSTEM_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearLanguage() {
|
||||||
|
preferences.edit().remove(Preferences.PREF_LANGUAGE).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLocalRepoName() {
|
public String getLocalRepoName() {
|
||||||
|
@ -7,9 +7,12 @@ import android.content.pm.FeatureInfo;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.content.res.XmlResourceParser;
|
import android.content.res.XmlResourceParser;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.os.LocaleList;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
@ -359,64 +362,116 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
|
|||||||
/**
|
/**
|
||||||
* Parses the {@code localized} block in the incoming index metadata,
|
* Parses the {@code localized} block in the incoming index metadata,
|
||||||
* choosing the best match in terms of locale/language while filling as
|
* choosing the best match in terms of locale/language while filling as
|
||||||
* many fields as possible. The first English locale found is loaded, then
|
* many fields as possible. It first sets up a locale list based on user
|
||||||
* {@code en-US} is loaded over that, since that's the most common English
|
* preference and the locales available for this app, then picks the texts
|
||||||
* for software. Then the first language match, and then finally the
|
* based on that list. One thing that makes this tricky is that any given
|
||||||
* current locale for this device, given it precedence over all the others.
|
* locale block in the index might not have all the fields. So when filling
|
||||||
|
* out each value, it needs to go through the whole preference list each time,
|
||||||
|
* rather than just taking the whole block for a specific locale. This is to
|
||||||
|
* ensure that there is something to show, as often as possible.
|
||||||
* <p>
|
* <p>
|
||||||
* It is still possible that the fields will be loaded directly without any
|
* It is still possible that the fields will be loaded directly by Jackson
|
||||||
* locale info. This comes from the old-style {@code .txt} app metadata
|
* without any locale info. This comes from the old-style, inline app metadata
|
||||||
* fields that do not have locale info. They should not be used if the
|
* fields that do not have locale info. They should not be used if the
|
||||||
* {@code Localized} block is specified.
|
* {@code localized} block is included in the index. Also, null strings in
|
||||||
|
* the {@code localized} block should not overwrite Name/Summary/Description
|
||||||
|
* strings with empty/null if they were set directly by Jackson.
|
||||||
|
* <p>
|
||||||
|
* Choosing the locale to use follows two sets of rules, one for Android versions
|
||||||
|
* older than {@code android-24} and the other for {@code android-24} or newer.
|
||||||
|
* The system-wide language preference list was added in {@code android-24}.
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code >= android-24}<ol>
|
||||||
|
* <li>the country variant {@code de-AT} from the user locale list
|
||||||
|
* <li>only the language {@code de} from the above locale
|
||||||
|
* <li>{@code en-US} since its the most common English for software
|
||||||
|
* <li>the first available {@code en} locale
|
||||||
|
* </ol></li>
|
||||||
|
* <li>{@code < android-24}<ol>
|
||||||
|
* <li>the country variant from the user locale: {@code de-AT}
|
||||||
|
* <li>only the language from the above locale: {@code de}
|
||||||
|
* <li>all available locales with the same language: {@code de-BE}
|
||||||
|
* <li>{@code en-US} since its the most common English for software
|
||||||
|
* <li>all available {@code en} locales
|
||||||
|
* </ol></li>
|
||||||
|
* </ul>
|
||||||
|
* On {@code >= android-24}, it is by design that this does not fallback to other
|
||||||
|
* country-specific locales, e.g. {@code fr-CH} does not fall back on {@code fr-FR}.
|
||||||
|
* If someone wants to fallback to {@code fr-FR}, they can add it to the system
|
||||||
|
* language list. There are many cases where it is inappropriate to fallback to a
|
||||||
|
* different country-specific locale, for example {@code de-DE --> de-CH} or
|
||||||
|
* {@code zh-CN --> zh-TW}.
|
||||||
|
* <p>
|
||||||
|
* On {@code < android-24}, the user can only set a single
|
||||||
|
* locale with a country as an option, so here it makes sense to try to fallback
|
||||||
|
* on other country-specific locales, rather than English.
|
||||||
*/
|
*/
|
||||||
@JsonProperty("localized")
|
@JsonProperty("localized")
|
||||||
private void setLocalized(Map<String, Map<String, Object>> localized) { // NOPMD
|
private void setLocalized(Map<String, Map<String, Object>> localized) { // NOPMD
|
||||||
Locale defaultLocale = Locale.getDefault();
|
Locale defaultLocale = Locale.getDefault();
|
||||||
String languageTag = defaultLocale.getLanguage();
|
String languageTag = defaultLocale.getLanguage();
|
||||||
String localeTag = languageTag + "-" + defaultLocale.getCountry();
|
String countryTag = defaultLocale.getCountry();
|
||||||
Set<String> locales = localized.keySet();
|
String localeTag;
|
||||||
Set<String> localesToUse = new LinkedHashSet<>();
|
if (TextUtils.isEmpty(countryTag)) {
|
||||||
|
localeTag = languageTag;
|
||||||
if (locales.contains(localeTag)) {
|
} else {
|
||||||
localesToUse.add(localeTag);
|
localeTag = languageTag + "-" + countryTag;
|
||||||
}
|
}
|
||||||
for (String l : locales) {
|
|
||||||
if (l.startsWith(languageTag)) {
|
Set<String> availableLocales = localized.keySet();
|
||||||
localesToUse.add(l);
|
Set<String> localesToUse = new LinkedHashSet<>();
|
||||||
break;
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
|
LocaleList localeList = Resources.getSystem().getConfiguration().getLocales();
|
||||||
|
for (String toUse : localeList.toLanguageTags().split(",")) {
|
||||||
|
localesToUse.add(toUse);
|
||||||
|
for (String l : availableLocales) {
|
||||||
|
if (l.equals(toUse.split("-")[0])) {
|
||||||
|
localesToUse.add(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (availableLocales.contains(localeTag)) {
|
||||||
|
localesToUse.add(localeTag);
|
||||||
|
}
|
||||||
|
if (availableLocales.contains(languageTag)) {
|
||||||
|
localesToUse.add(languageTag);
|
||||||
|
}
|
||||||
|
for (String l : availableLocales) {
|
||||||
|
if (l.startsWith(languageTag)) {
|
||||||
|
localesToUse.add(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (locales.contains("en-US")) {
|
if (availableLocales.contains("en-US")) {
|
||||||
localesToUse.add("en-US");
|
localesToUse.add("en-US");
|
||||||
}
|
}
|
||||||
for (String l : locales) {
|
for (String l : availableLocales) {
|
||||||
if (l.startsWith("en")) {
|
if (l.startsWith("en")) {
|
||||||
localesToUse.add(l);
|
localesToUse.add(l);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if key starts with Upper case, its set by humans
|
|
||||||
String value = getLocalizedEntry(localized, localesToUse, "Video");
|
whatsNew = getLocalizedEntry(localized, localesToUse, "whatsNew");
|
||||||
|
String value = getLocalizedEntry(localized, localesToUse, "video");
|
||||||
if (!TextUtils.isEmpty(value)) {
|
if (!TextUtils.isEmpty(value)) {
|
||||||
video = value.split("\n", 1)[0];
|
video = value.split("\n", 1)[0];
|
||||||
}
|
}
|
||||||
whatsNew = getLocalizedEntry(localized, localesToUse, "WhatsNew");
|
value = getLocalizedEntry(localized, localesToUse, "name");
|
||||||
// Name, Summary, Description existed before localization so they shouldn't replace
|
|
||||||
// non-localized old data format with a null or blank string
|
|
||||||
value = getLocalizedEntry(localized, localesToUse, "Name");
|
|
||||||
if (!TextUtils.isEmpty(value)) {
|
if (!TextUtils.isEmpty(value)) {
|
||||||
name = value;
|
name = value;
|
||||||
}
|
}
|
||||||
value = getLocalizedEntry(localized, localesToUse, "Summary");
|
value = getLocalizedEntry(localized, localesToUse, "summary");
|
||||||
if (!TextUtils.isEmpty(value)) {
|
if (!TextUtils.isEmpty(value)) {
|
||||||
summary = value;
|
summary = value;
|
||||||
}
|
}
|
||||||
value = getLocalizedEntry(localized, localesToUse, "Description");
|
value = getLocalizedEntry(localized, localesToUse, "description");
|
||||||
if (!TextUtils.isEmpty(value)) {
|
if (!TextUtils.isEmpty(value)) {
|
||||||
description = value;
|
description = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if key starts with lower case, its generated based on finding the files
|
|
||||||
featureGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "featureGraphic");
|
featureGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "featureGraphic");
|
||||||
promoGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "promoGraphic");
|
promoGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "promoGraphic");
|
||||||
tvBanner = getLocalizedGraphicsEntry(localized, localesToUse, "tvBanner");
|
tvBanner = getLocalizedGraphicsEntry(localized, localesToUse, "tvBanner");
|
||||||
|
@ -65,10 +65,15 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
updatePrivilegedExtensionPref = findPreference(Preferences.PREF_UNINSTALL_PRIVILEGED_APP);
|
updatePrivilegedExtensionPref = findPreference(Preferences.PREF_UNINSTALL_PRIVILEGED_APP);
|
||||||
|
|
||||||
AppCompatListPreference languagePref = (AppCompatListPreference) findPreference(Preferences.PREF_LANGUAGE);
|
AppCompatListPreference languagePref = (AppCompatListPreference) findPreference(Preferences.PREF_LANGUAGE);
|
||||||
Languages languages = Languages.get(getActivity());
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
languagePref.setDefaultValue(Languages.USE_SYSTEM_DEFAULT);
|
PreferenceCategory category = (PreferenceCategory) findPreference("pref_category_display");
|
||||||
languagePref.setEntries(languages.getAllNames());
|
category.removePreference(languagePref);
|
||||||
languagePref.setEntryValues(languages.getSupportedLocales());
|
} else {
|
||||||
|
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) {
|
||||||
@ -78,7 +83,9 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
|
|
||||||
private void entrySummary(String key) {
|
private void entrySummary(String key) {
|
||||||
ListPreference pref = (ListPreference) findPreference(key);
|
ListPreference pref = (ListPreference) findPreference(key);
|
||||||
pref.setSummary(pref.getEntry());
|
if (pref != null) {
|
||||||
|
pref.setSummary(pref.getEntry());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void textSummary(String key, int resId) {
|
private void textSummary(String key, int resId) {
|
||||||
@ -150,7 +157,7 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
entrySummary(key);
|
entrySummary(key);
|
||||||
if (changing) {
|
if (changing) {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
Languages.setLanguage(activity, Preferences.get().getLangauge(), false);
|
Languages.setLanguage(activity, Preferences.get().getLanguage(), false);
|
||||||
Languages.forceChangeLanguage(activity);
|
Languages.forceChangeLanguage(activity);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<PreferenceCategory android:title="@string/menu_about">
|
|
||||||
<PreferenceScreen android:title="@string/about_title">
|
<PreferenceScreen android:title="@string/about_title">
|
||||||
<intent
|
<intent
|
||||||
android:action="android.intent.action.MAIN"
|
android:action="android.intent.action.MAIN"
|
||||||
android:targetPackage="org.fdroid.fdroid"
|
android:targetPackage="org.fdroid.fdroid"
|
||||||
android:targetClass="org.fdroid.fdroid.AboutActivity" />
|
android:targetClass="org.fdroid.fdroid.AboutActivity" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
</PreferenceCategory>
|
|
||||||
<PreferenceCategory android:title="@string/preference_category__my_apps">
|
<PreferenceCategory android:title="@string/preference_category__my_apps">
|
||||||
<PreferenceScreen android:title="@string/preference_manage_installed_apps">
|
<PreferenceScreen android:title="@string/preference_manage_installed_apps">
|
||||||
<intent
|
<intent
|
||||||
@ -41,7 +39,8 @@
|
|||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="updateNotify" />
|
android:key="updateNotify" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/display">
|
<PreferenceCategory android:title="@string/display"
|
||||||
|
android:key="pref_category_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"/>
|
||||||
<com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/theme"
|
<com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/theme"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user