From aec67d2150f2605998fb4307636ba49f57adc759 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Fri, 19 Jan 2024 19:59:20 +0530 Subject: [PATCH 1/4] Simplify available languages retrieval --- .../org/wikipedia/language/LanguageUtil.kt | 85 +++++++------------ .../wikipedia/language/LanguageUtilTest.java | 2 +- 2 files changed, 33 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt index f73ba6d003c..55e591c12e2 100644 --- a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt +++ b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt @@ -1,32 +1,40 @@ package org.wikipedia.language -import android.content.Context import android.os.Build import android.view.inputmethod.InputMethodManager +import android.view.inputmethod.InputMethodSubtype +import androidx.core.content.getSystemService import androidx.core.os.LocaleListCompat import org.apache.commons.lang3.StringUtils import org.wikipedia.WikipediaApp -import org.wikipedia.util.StringUtil -import java.util.* +import java.util.Locale object LanguageUtil { - private const val HONG_KONG_COUNTRY_CODE = "HK" private const val MACAU_COUNTRY_CODE = "MO" private val TRADITIONAL_CHINESE_COUNTRY_CODES = listOf(Locale.TAIWAN.country, HONG_KONG_COUNTRY_CODE, MACAU_COUNTRY_CODE) - val availableLanguages: List + private val InputMethodSubtype.localeObject: Locale? + get() { + val languageTag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) languageTag else "" + val actualTag = languageTag.ifEmpty { + // The keyboard reports locale variants with underscores ("en_US") whereas + // Locale.forLanguageTag() expects dashes ("en-US"), so convert them. + @Suppress("DEPRECATION") + locale.replace('_', '-') + } + return if (actualTag.isNotEmpty()) Locale.forLanguageTag(actualTag) else null + } + + val availableLanguages: Set get() { - val languages = mutableListOf() + val languages = mutableSetOf() // First, look at languages installed on the system itself. - var localeList = LocaleListCompat.getDefault() + val localeList = LocaleListCompat.getDefault() for (i in 0 until localeList.size()) { localeList[i]?.let { - val languageCode = localeToWikiLanguageCode(it) - if (!languages.contains(languageCode)) { - languages.add(languageCode) - } + languages.add(localeToWikiLanguageCode(it)) } } if (languages.isEmpty()) { @@ -34,52 +42,23 @@ object LanguageUtil { languages.add(localeToWikiLanguageCode(Locale.getDefault())) } - // Query the installed keyboard languages, and add them to the list, if they don't exist. - val imm = WikipediaApp.instance.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - val ims = imm.enabledInputMethodList ?: emptyList() - val langTagList = mutableListOf() - for (method in ims) { - val submethods = imm.getEnabledInputMethodSubtypeList(method, true) ?: emptyList() - for (submethod in submethods) { - if (submethod.mode == "keyboard") { - var langTag = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && submethod.languageTag.isNotEmpty()) submethod.languageTag - else submethod.locale - if (langTag.isEmpty()) { - continue - } - if (langTag.contains("_")) { - // The keyboard reports locale variants with underscores ("en_US") whereas - // Locale.forLanguageTag() expects dashes ("en-US"), so convert them. - langTag = langTag.replace('_', '-') - } - if (!langTagList.contains(langTag)) { - langTagList.add(langTag) - } - // A Pinyin keyboard will report itself as zh-CN (simplified), but we want to add - // both Simplified and Traditional in that case. - if (langTag.lowercase(Locale.getDefault()) == AppLanguageLookUpTable.CHINESE_CN_LANGUAGE_CODE && - !langTagList.contains("zh-TW")) { - langTagList.add("zh-TW") - } - } + // Query the installed keyboard languages, and add them to the set, if they don't exist. + val imm = WikipediaApp.instance.getSystemService()!! + languages += imm.enabledInputMethodList.asSequence() + .flatMap { imm.getEnabledInputMethodSubtypeList(it, true) } + .mapNotNull { it.localeObject } + .flatMap { + // A Pinyin keyboard will report itself as zh-CN (simplified), but we want to add + // both Simplified and Traditional in that case. + if (it == Locale.SIMPLIFIED_CHINESE) listOf(it, Locale.TRADITIONAL_CHINESE) else listOf(it) } - } - if (langTagList.isNotEmpty()) { - localeList = LocaleListCompat.forLanguageTags(StringUtil.listToCsv(langTagList)) - for (i in 0 until localeList.size()) { - localeList[i]?.let { - val langCode = localeToWikiLanguageCode(it) - if (langCode.isNotEmpty() && !languages.contains(langCode) && langCode != "und") { - languages.add(langCode) - } - } - } - } + .distinct() + .map { localeToWikiLanguageCode(it) } + .filter { it.isNotEmpty() && it != "und" } + return languages } - @JvmStatic fun localeToWikiLanguageCode(locale: Locale): String { // Convert deprecated language codes to modern ones. // See https://developer.android.com/reference/java/util/Locale.html diff --git a/app/src/test/java/org/wikipedia/language/LanguageUtilTest.java b/app/src/test/java/org/wikipedia/language/LanguageUtilTest.java index 6d3a4db37ab..a5a87ac2177 100644 --- a/app/src/test/java/org/wikipedia/language/LanguageUtilTest.java +++ b/app/src/test/java/org/wikipedia/language/LanguageUtilTest.java @@ -94,7 +94,7 @@ public abstract static class LanguageCodeToWikiLanguageCodeChinese { void test(@NonNull Locale defaultLocale, @Nullable String expected) { Locale.setDefault(defaultLocale); - String wikiLang = LanguageUtil.localeToWikiLanguageCode(defaultLocale); + String wikiLang = LanguageUtil.INSTANCE.localeToWikiLanguageCode(defaultLocale); assertThat(wikiLang, is(expected)); } } From 32c71f2323bb0de6e71c8ed4e259e41156a81039 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 29 Jan 2024 14:49:57 +0530 Subject: [PATCH 2/4] Add submethod filter step --- app/src/main/java/org/wikipedia/language/LanguageUtil.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt index 55e591c12e2..c7df631eaca 100644 --- a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt +++ b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt @@ -46,6 +46,7 @@ object LanguageUtil { val imm = WikipediaApp.instance.getSystemService()!! languages += imm.enabledInputMethodList.asSequence() .flatMap { imm.getEnabledInputMethodSubtypeList(it, true) } + .filter { it.mode == "keyboard" } .mapNotNull { it.localeObject } .flatMap { // A Pinyin keyboard will report itself as zh-CN (simplified), but we want to add From 5da753e104b88f815e838178c07cb37ead7b8d1f Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 19 May 2024 15:00:08 +0530 Subject: [PATCH 3/4] Query the system and keyboard locales lazily --- .../wikipedia/language/AppLanguageState.kt | 6 +++-- .../org/wikipedia/language/LanguageUtil.kt | 25 ++++++++----------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/wikipedia/language/AppLanguageState.kt b/app/src/main/java/org/wikipedia/language/AppLanguageState.kt index 6889408d8e5..26c2ca9f38d 100644 --- a/app/src/main/java/org/wikipedia/language/AppLanguageState.kt +++ b/app/src/main/java/org/wikipedia/language/AppLanguageState.kt @@ -6,7 +6,7 @@ import org.wikipedia.R import org.wikipedia.WikipediaApp import org.wikipedia.settings.Prefs import org.wikipedia.util.ReleaseUtil -import java.util.* +import java.util.Locale class AppLanguageState(context: Context) { @@ -37,7 +37,9 @@ class AppLanguageState(context: Context) { get() = appLanguageCodes.first() val remainingSuggestedLanguageCodes: List - get() = LanguageUtil.suggestedLanguagesFromSystem.filter { !_appLanguageCodes.contains(it) && appLanguageLookUpTable.isSupportedCode(it) } + get() = LanguageUtil.suggestedLanguagesFromSystem + .filter { it !in _appLanguageCodes && appLanguageLookUpTable.isSupportedCode(it) } + .toList() val systemLanguageCode: String get() { diff --git a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt index 388b4d9bb55..b34e8588995 100644 --- a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt +++ b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt @@ -27,25 +27,19 @@ object LanguageUtil { return if (actualTag.isNotEmpty()) Locale.forLanguageTag(actualTag) else null } - val suggestedLanguagesFromSystem: List + val suggestedLanguagesFromSystem: Sequence get() { - val languages = mutableSetOf() - // First, look at languages installed on the system itself. - val localeList = LocaleListCompat.getDefault() - for (i in 0 until localeList.size()) { - localeList[i]?.let { - languages.add(localeToWikiLanguageCode(it)) + val systemLocales = sequence { + val localeList = LocaleListCompat.getDefault() + for (i in 0 until localeList.size()) { + yield(localeList[i]!!) } } - if (languages.isEmpty()) { - // Always default to at least one system language in the list. - languages.add(localeToWikiLanguageCode(Locale.getDefault())) - } - // Query the installed keyboard languages, and add them to the set, if they don't exist. + // Query the installed keyboard languages lazily. val imm = WikipediaApp.instance.getSystemService()!! - languages += imm.enabledInputMethodList.asSequence() + val keyboardLocales = imm.enabledInputMethodList.asSequence() .flatMap { imm.getEnabledInputMethodSubtypeList(it, true) } .filter { it.mode == "keyboard" } .mapNotNull { it.localeObject } @@ -54,11 +48,12 @@ object LanguageUtil { // both Simplified and Traditional in that case. if (it == Locale.SIMPLIFIED_CHINESE) listOf(it, Locale.TRADITIONAL_CHINESE) else listOf(it) } + + return (systemLocales + keyboardLocales) .distinct() .map { localeToWikiLanguageCode(it) } .filter { it.isNotEmpty() && it != "und" } - - return languages.take(MAX_SUGGESTED_LANGUAGES) + .take(MAX_SUGGESTED_LANGUAGES) } fun localeToWikiLanguageCode(locale: Locale): String { From dff80a2a07c6a3d0477eff67b24395fb4d037fdb Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sun, 19 May 2024 17:02:47 +0530 Subject: [PATCH 4/4] Fix order of sequence operations --- app/src/main/java/org/wikipedia/language/LanguageUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt index b34e8588995..36ca8d47887 100644 --- a/app/src/main/java/org/wikipedia/language/LanguageUtil.kt +++ b/app/src/main/java/org/wikipedia/language/LanguageUtil.kt @@ -50,8 +50,8 @@ object LanguageUtil { } return (systemLocales + keyboardLocales) - .distinct() .map { localeToWikiLanguageCode(it) } + .distinct() .filter { it.isNotEmpty() && it != "und" } .take(MAX_SUGGESTED_LANGUAGES) }