Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,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
92 changes: 34 additions & 58 deletions app/src/main/java/org/wikipedia/language/LanguageUtil.kt
Original file line number Diff line number Diff line change
@@ -1,80 +1,56 @@
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

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
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)
}

fun localeToWikiLanguageCode(locale: Locale): String {
Expand Down
Loading