Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify available languages retrieval #4406

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

Expand Down Expand Up @@ -37,7 +37,9 @@ class AppLanguageState(context: Context) {
get() = appLanguageCodes.first()

val remainingSuggestedLanguageCodes: List<String>
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() {
Expand Down
93 changes: 34 additions & 59 deletions app/src/main/java/org/wikipedia/language/LanguageUtil.kt
Original file line number Diff line number Diff line change
@@ -1,86 +1,61 @@
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.Locale

object LanguageUtil {

private const val MAX_SUGGESTED_LANGUAGES = 8
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 suggestedLanguagesFromSystem: List<String>
private val InputMethodSubtype.localeObject: Locale?
get() {
val languages = mutableListOf<String>()
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 suggestedLanguagesFromSystem: Sequence<String>
get() {
// First, look at languages installed on the system itself.
var localeList = LocaleListCompat.getDefault()
for (i in 0 until localeList.size()) {
localeList[i]?.let {
val languageCode = localeToWikiLanguageCode(it)
if (!languages.contains(languageCode)) {
languages.add(languageCode)
}
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 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<String>()
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 lazily.
val imm = WikipediaApp.instance.getSystemService<InputMethodManager>()!!
val keyboardLocales = 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
// 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)
}
}
}
}
return languages.take(MAX_SUGGESTED_LANGUAGES)

return (systemLocales + keyboardLocales)
.map { localeToWikiLanguageCode(it) }
.distinct()
.filter { it.isNotEmpty() && it != "und" }
.take(MAX_SUGGESTED_LANGUAGES)
}

@JvmStatic
fun localeToWikiLanguageCode(locale: Locale): String {
// Convert deprecated language codes to modern ones.
// See https://developer.android.com/reference/java/util/Locale.html
Expand Down
Loading