diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java index e8a61688e..f7d04b79a 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/App.java +++ b/app/src/main/java/org/fdroid/fdroid/data/App.java @@ -362,15 +362,49 @@ public class App extends ValueObject implements Comparable, Parcelable { /** * Parses the {@code localized} block in the incoming index metadata, * choosing the best match in terms of locale/language while filling as - * many fields as possible. The first English locale found is loaded, then - * {@code en-US} is loaded over that, since that's the most common English - * for software. Then the first language match, and then finally the - * current locale for this device, given it precedence over all the others. + * many fields as possible. It first sets up a locale list based on user + * preference and the locales available for this app, then picks the texts + * based on that list. One thing that makes this tricky is that any given + * 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. *

- * It is still possible that the fields will be loaded directly without any - * locale info. This comes from the old-style {@code .txt} app metadata + * It is still possible that the fields will be loaded directly by Jackson + * 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 - * {@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. + *

+ * 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}. + *

+ * 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}. + *

+ * 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") private void setLocalized(Map> localized) { // NOPMD @@ -419,14 +453,12 @@ public class App extends ValueObject implements Comparable, Parcelable { break; } } - // if key starts with Upper case, its set by humans + + whatsNew = getLocalizedEntry(localized, localesToUse, "whatsNew"); String value = getLocalizedEntry(localized, localesToUse, "video"); if (!TextUtils.isEmpty(value)) { video = value.split("\n", 1)[0]; } - whatsNew = getLocalizedEntry(localized, localesToUse, "whatsNew"); - // 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)) { name = value; @@ -440,7 +472,6 @@ public class App extends ValueObject implements Comparable, Parcelable { description = value; } - // if key starts with lower case, its generated based on finding the files featureGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "featureGraphic"); promoGraphic = getLocalizedGraphicsEntry(localized, localesToUse, "promoGraphic"); tvBanner = getLocalizedGraphicsEntry(localized, localesToUse, "tvBanner");