consider script when evaluating hint locales

This commit is contained in:
Helium314 2024-02-01 10:56:41 +01:00
parent 9cce029e06
commit 5e5f045495
3 changed files with 27 additions and 73 deletions

View file

@ -914,15 +914,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
// Try switching to a subtype matching the hint language. // Try switching to a subtype matching the hint language.
for (final Locale hintLocale : hintLocales) { for (final Locale hintLocale : hintLocales) {
final InputMethodSubtype newSubtype = mRichImm.findSubtypeByLocale(hintLocale); final InputMethodSubtype newSubtype = mRichImm.findSubtypeForHintLocale(hintLocale);
if (newSubtype == null) continue; if (newSubtype == null) continue;
if (newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype())) if (newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype()))
return; // no need to switch, we already use the correct locale return; // no need to switch, we already use the correct locale
mHandler.postSwitchLanguage(newSubtype); mHandler.postSwitchLanguage(newSubtype);
break;
} }
} }
@SuppressWarnings("deprecation")
void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) { void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
super.onStartInputView(editorInfo, restarting); super.onStartInputView(editorInfo, restarting);

View file

@ -17,6 +17,7 @@ import android.view.inputmethod.InputMethodSubtype;
import helium314.keyboard.annotations.UsedForTesting; import helium314.keyboard.annotations.UsedForTesting;
import helium314.keyboard.compat.ConfigurationCompatKt; import helium314.keyboard.compat.ConfigurationCompatKt;
import helium314.keyboard.latin.common.LocaleUtils;
import helium314.keyboard.latin.settings.Settings; import helium314.keyboard.latin.settings.Settings;
import helium314.keyboard.latin.utils.DeviceProtectedUtils; import helium314.keyboard.latin.utils.DeviceProtectedUtils;
import helium314.keyboard.latin.utils.LanguageOnSpacebarUtils; import helium314.keyboard.latin.utils.LanguageOnSpacebarUtils;
@ -309,82 +310,34 @@ public class RichInputMethodManager {
return null; return null;
} }
public InputMethodSubtype findSubtypeByLocale(final Locale locale) { public InputMethodSubtype findSubtypeForHintLocale(final Locale locale) {
// Find the best subtype based on a straightforward matching algorithm. // Find the best subtype based on a locale matching
final List<InputMethodSubtype> subtypes = final List<InputMethodSubtype> subtypes = getMyEnabledInputMethodSubtypeList(true);
getMyEnabledInputMethodSubtypeList(true /* allowsImplicitlySelectedSubtypes */); InputMethodSubtype bestMatch = LocaleUtils.getBestMatch(locale, subtypes, SubtypeUtilsKt::locale);
final int count = subtypes.size(); if (bestMatch != null) return bestMatch;
// search for exact match
for (int i = 0; i < count; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
if (subtypeLocale.equals(locale)) {
return subtype;
}
}
// search for language + country + variant match
for (int i = 0; i < count; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
if (subtypeLocale.getLanguage().equals(locale.getLanguage()) &&
subtypeLocale.getCountry().equals(locale.getCountry()) &&
subtypeLocale.getVariant().equals(locale.getVariant())) {
return subtype;
}
}
// search for language + country match
for (int i = 0; i < count; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
if (subtypeLocale.getLanguage().equals(locale.getLanguage()) &&
subtypeLocale.getCountry().equals(locale.getCountry())) {
return subtype;
}
}
// search for secondary locale match
final SharedPreferences prefs = DeviceProtectedUtils.getSharedPreferences(mContext);
for (int i = 0; i < count; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
final List<Locale> secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale);
for (final Locale secondaryLocale : secondaryLocales) {
if (secondaryLocale.equals(locale)) {
return subtype;
}
}
}
// search for language match
for (int i = 0; i < count; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
if (subtypeLocale.getLanguage().equals(locale.getLanguage())) {
return subtype;
}
}
// search for secondary language match
for (int i = 0; i < count; ++i) {
final InputMethodSubtype subtype = subtypes.get(i);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
final List<Locale> secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale);
for (final Locale secondaryLocale : secondaryLocales) {
if (secondaryLocale.getLanguage().equals(locale.getLanguage())) {
return subtype;
}
}
}
// extra: if current script is not compatible to current subtype, search for compatible script // search for first secondary language & script match
// this is acceptable only because this function is only used for switching to a certain locale using EditorInfo.hintLocales final int count = subtypes.size();
final SharedPreferences prefs = DeviceProtectedUtils.getSharedPreferences(mContext);
final String language = locale.getLanguage();
final String script = ScriptUtils.script(locale); final String script = ScriptUtils.script(locale);
if (!script.equals(ScriptUtils.script(getCurrentSubtypeLocale()))) { for (int i = 0; i < count; ++i) {
for (int i = 0; i < count; ++i) { final InputMethodSubtype subtype = subtypes.get(i);
final InputMethodSubtype subtype = subtypes.get(i); final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype);
final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); if (!ScriptUtils.script(subtypeLocale).equals(script))
if (ScriptUtils.script(subtypeLocale).equals(script)) { continue; // need compatible script
return subtype; bestMatch = subtype;
final List<Locale> secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale);
for (final Locale secondaryLocale : secondaryLocales) {
if (secondaryLocale.getLanguage().equals(language)) {
return bestMatch;
} }
} }
} }
// if wanted script is not compatible to current subtype, return a subtype with compatible script if possible
if (!script.equals(ScriptUtils.script(getCurrentSubtypeLocale()))) {
return bestMatch;
}
return null; return null;
} }

View file

@ -110,6 +110,7 @@ object LocaleUtils {
else LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER else LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
} }
@JvmStatic
fun <T> getBestMatch(locale: Locale, collection: Collection<T>, toLocale: (T) -> Locale): T? { fun <T> getBestMatch(locale: Locale, collection: Collection<T>, toLocale: (T) -> Locale): T? {
var best: T? = null var best: T? = null
var bestLevel = 0 var bestLevel = 0