diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a231a4efd..5e1efb217 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -59,7 +59,7 @@
-
+
1;
+ final InputMethodSubtype nextSubtype = mRichImm.getNextSubtypeInThisIme(moreThanOneSubtype);
+ if (nextSubtype != null) {
+ switchToSubtype(nextSubtype);
+ } else {
+ // we are at end of the internal subtype list, switch to next input method
+ // (for now) don't care about which input method and subtype exactly, let the system choose
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ switchToNextInputMethod(false);
+ } else {
+ final IBinder token = getWindow().getWindow().getAttributes().token;
+ mRichImm.getInputMethodManager().switchToNextInputMethod(token, false);
+ }
+ }
return;
}
- mSubtypeState.switchSubtype(token, mRichImm);
+ mSubtypeState.switchSubtype(mRichImm);
+ }
+
+ public void switchInputMethodAndSubtype(final InputMethodInfo imi, final InputMethodSubtype subtype) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ switchInputMethod(imi.getId(), subtype);
+ } else {
+ final IBinder token = getWindow().getWindow().getAttributes().token;
+ mRichImm.getInputMethodManager().setInputMethodAndSubtype(token, imi.getId(), subtype);
+ }
}
// TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
@@ -2038,15 +2071,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public boolean shouldSwitchToOtherInputMethods() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
+ return shouldOfferSwitchingToNextInputMethod();
// TODO: Revisit here to reorganize the settings. Probably we can/should use different
// strategy once the implementation of
// {@link InputMethodManager#shouldOfferSwitchingToNextInputMethod} is defined well.
- final boolean fallbackValue = mSettings.getCurrent().mIncludesOtherImesInLanguageSwitchList;
final IBinder token = getWindow().getWindow().getAttributes().token;
if (token == null) {
- return fallbackValue;
+ return mSettings.getCurrent().mIncludesOtherImesInLanguageSwitchList;
}
- return mRichImm.shouldOfferSwitchingToNextInputMethod(token, fallbackValue);
+ return mRichImm.getInputMethodManager().shouldOfferSwitchingToNextInputMethod(token);
}
public boolean shouldShowLanguageSwitchKey() {
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/RichInputMethodManager.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/RichInputMethodManager.java
index e0e210074..b1a7eb949 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/RichInputMethodManager.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/RichInputMethodManager.java
@@ -31,6 +31,7 @@ import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
import org.dslul.openboard.inputmethod.compat.InputMethodManagerCompatWrapper;
import org.dslul.openboard.inputmethod.compat.InputMethodSubtypeCompatUtils;
import org.dslul.openboard.inputmethod.latin.settings.Settings;
+import org.dslul.openboard.inputmethod.latin.settings.SubtypeSettingsKt;
import org.dslul.openboard.inputmethod.latin.utils.AdditionalSubtypeUtils;
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
import org.dslul.openboard.inputmethod.latin.utils.LanguageOnSpacebarUtils;
@@ -100,17 +101,16 @@ public class RichInputMethodManager {
mInputMethodInfoCache = new InputMethodInfoCache(
mImmWrapper.mImm, context.getPackageName());
- // Initialize additional subtypes.
+ // Initialize subtype utils.
SubtypeLocaleUtils.init(context);
- final InputMethodSubtype[] additionalSubtypes = getAdditionalSubtypes();
- mImmWrapper.mImm.setAdditionalInputMethodSubtypes(
- getInputMethodIdOfThisIme(), additionalSubtypes);
// Initialize the current input method subtype and the shortcut IME.
refreshSubtypeCaches();
}
- public InputMethodSubtype[] getAdditionalSubtypes() {
+ public InputMethodSubtype[] getAdditionalSubtypes() { // todo: can be removed
+ // todo: this should read the enabled subtypes setting
+ // either use or remove the default additional subtypes
final SharedPreferences prefs = DeviceProtectedUtils.getSharedPreferences(mContext);
final String prefAdditionalSubtypes = Settings.readPrefAdditionalSubtypes(
prefs, mContext.getResources());
@@ -129,7 +129,8 @@ public class RichInputMethodManager {
}
public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) {
- if (mImmWrapper.switchToNextInputMethod(token, onlyCurrentIme)) {
+ // todo: don't want this any more, and actually mImmWrapper.switchToNextInputMethod can be removed
+ if (false && mImmWrapper.switchToNextInputMethod(token, onlyCurrentIme)) {
return true;
}
// Was not able to call {@link InputMethodManager#switchToNextInputMethodIBinder,boolean)}
@@ -140,10 +141,27 @@ public class RichInputMethodManager {
return switchToNextInputMethodAndSubtype(token);
}
+ public @Nullable InputMethodSubtype getNextSubtypeInThisIme(final boolean onlyCurrentIme) {
+ final InputMethodSubtype currentSubtype = getCurrentSubtype().getRawSubtype();
+ final List enabledSubtypes = getMyEnabledInputMethodSubtypeList(true);
+ final int currentIndex = getSubtypeIndexInList(currentSubtype, enabledSubtypes);
+ if (currentIndex == INDEX_NOT_FOUND) {
+ Log.w(TAG, "Can't find current subtype in enabled subtypes: subtype="
+ + SubtypeLocaleUtils.getSubtypeNameForLogging(currentSubtype));
+ if (onlyCurrentIme) return enabledSubtypes.get(0); // just return first enabled subtype
+ else return null;
+ }
+ final int nextIndex = (currentIndex + 1) % enabledSubtypes.size();
+ if (nextIndex <= currentIndex && !onlyCurrentIme) {
+ // The current subtype is the last or only enabled one and it needs to switch to next IME.
+ return null;
+ }
+ return enabledSubtypes.get(nextIndex);
+ }
+
private boolean switchToNextInputSubtypeInThisIme(final IBinder token,
final boolean onlyCurrentIme) {
- final InputMethodManager imm = mImmWrapper.mImm;
- final InputMethodSubtype currentSubtype = imm.getCurrentInputMethodSubtype();
+ final InputMethodSubtype currentSubtype = getCurrentSubtype().getRawSubtype();
final List enabledSubtypes = getMyEnabledInputMethodSubtypeList(
true /* allowsImplicitlySelectedSubtypes */);
final int currentIndex = getSubtypeIndexInList(currentSubtype, enabledSubtypes);
@@ -159,7 +177,7 @@ public class RichInputMethodManager {
return false;
}
final InputMethodSubtype nextSubtype = enabledSubtypes.get(nextIndex);
- setInputMethodAndSubtype(token, nextSubtype);
+ setInputMethodAndSubtype(token, nextSubtype); // todo: not working any more, but switchToNextInputSubtypeInThisIme isn't called anyway...
return true;
}
@@ -266,8 +284,14 @@ public class RichInputMethodManager {
if (cachedList != null) {
return cachedList;
}
- final List result = mImm.getEnabledInputMethodSubtypeList(
- imi, allowsImplicitlySelectedSubtypes);
+ final List result;
+ if (imi == getInputMethodOfThisIme()) {
+ // allowsImplicitlySelectedSubtypes means system should choose if nothing is enabled,
+ // use it to fall back to system locales or en_US to avoid returning an empty list
+ result = SubtypeSettingsKt.getEnabledSubtypes(DeviceProtectedUtils.getSharedPreferences(sInstance.mContext), allowsImplicitlySelectedSubtypes);
+ } else {
+ result = mImm.getEnabledInputMethodSubtypeList(imi, allowsImplicitlySelectedSubtypes);
+ }
cache.put(imi, result);
return result;
}
@@ -309,6 +333,7 @@ public class RichInputMethodManager {
private static int getSubtypeIndexInList(final InputMethodSubtype subtype,
final List subtypes) {
+ // todo: why not simply subtypes.indexOf(subtype)? should do exactly the same, even return the same value -1 if not found
final int count = subtypes.size();
for (int index = 0; index < count; index++) {
final InputMethodSubtype ims = subtypes.get(index);
@@ -470,10 +495,13 @@ public class RichInputMethodManager {
}
public void setInputMethodAndSubtype(final IBinder token, final InputMethodSubtype subtype) {
- mImmWrapper.mImm.setInputMethodAndSubtype(
- token, getInputMethodIdOfThisIme(), subtype);
+ // todo: mImm stuff doesn't work any more, need sth like notifySubtypeChanged to actually trigger a reload
+ // try calling this instead, probably best before loading keyboard
+ // essentially it should do that update thing?
+ onSubtypeChanged(subtype);
}
+ // todo: remove together with additional subtype settings
public void setAdditionalInputMethodSubtypes(final InputMethodSubtype[] subtypes) {
mImmWrapper.mImm.setAdditionalInputMethodSubtypes(
getInputMethodIdOfThisIme(), subtypes);
@@ -482,7 +510,7 @@ public class RichInputMethodManager {
refreshSubtypeCaches();
}
- private List getEnabledInputMethodSubtypeList(final InputMethodInfo imi,
+ public List getEnabledInputMethodSubtypeList(final InputMethodInfo imi,
final boolean allowsImplicitlySelectedSubtypes) {
return mInputMethodInfoCache.getEnabledInputMethodSubtypeList(
imi, allowsImplicitlySelectedSubtypes);
@@ -490,10 +518,12 @@ public class RichInputMethodManager {
public void refreshSubtypeCaches() {
mInputMethodInfoCache.clear();
- updateCurrentSubtype(mImmWrapper.mImm.getCurrentInputMethodSubtype());
+ SharedPreferences prefs = DeviceProtectedUtils.getSharedPreferences(mContext);
+ updateCurrentSubtype(SubtypeSettingsKt.getSelectedSubtype(prefs));
updateShortcutIme();
}
+ // todo: remove
public boolean shouldOfferSwitchingToNextInputMethod(final IBinder binder,
boolean defaultValue) {
// Use the default value instead on Jelly Bean MR2 and previous where
@@ -505,6 +535,7 @@ public class RichInputMethodManager {
return mImmWrapper.shouldOfferSwitchingToNextInputMethod(binder);
}
+ // todo: remove?
public boolean isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes() {
final Locale systemLocale = mContext.getResources().getConfiguration().locale;
final Set enabledSubtypesOfEnabledImes = new HashSet<>();
@@ -530,10 +561,12 @@ public class RichInputMethodManager {
return true;
}
- private void updateCurrentSubtype(@Nullable final InputMethodSubtype subtype) {
+ private void updateCurrentSubtype(final InputMethodSubtype subtype) {
+ SubtypeSettingsKt.setSelectedSubtype(DeviceProtectedUtils.getSharedPreferences(mContext), subtype);
mCurrentRichInputMethodSubtype = RichInputMethodSubtype.getRichInputMethodSubtype(subtype);
}
+ // todo: what is shortcutIme? the voice input? if yes, rename it and other things like mHasShortcutKey
private void updateShortcutIme() {
if (DEBUG) {
Log.d(TAG, "Update shortcut IME from : "
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/SystemBroadcastReceiver.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/SystemBroadcastReceiver.java
index 9ce7c26bc..c6ea51a0a 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/SystemBroadcastReceiver.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/SystemBroadcastReceiver.java
@@ -26,7 +26,6 @@ import android.content.pm.PackageManager;
import android.os.Process;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import org.dslul.openboard.inputmethod.keyboard.KeyboardLayoutSet;
import org.dslul.openboard.inputmethod.latin.settings.Settings;
@@ -66,12 +65,6 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver {
final String intentAction = intent.getAction();
if (Intent.ACTION_MY_PACKAGE_REPLACED.equals(intentAction)) {
Log.i(TAG, "Package has been replaced: " + context.getPackageName());
- // Need to restore additional subtypes because system always clears additional
- // subtypes when the package is replaced.
- RichInputMethodManager.init(context);
- final RichInputMethodManager richImm = RichInputMethodManager.getInstance();
- final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes();
- richImm.setAdditionalInputMethodSubtypes(additionalSubtypes);
toggleAppIcon(context);
} else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) {
Log.i(TAG, "Boot has been completed");
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt
index 960da7235..45b4a595c 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/AppearanceSettingsFragment.kt
@@ -101,8 +101,6 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
super.onResume()
updateThemePreferencesState()
updateAfterPreferenceChanged()
- CustomInputStyleSettingsFragment.updateCustomInputStylesSummary(
- findPreference(Settings.PREF_CUSTOM_INPUT_STYLES))
}
override fun onPause() {
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/DictionarySettingsFragment.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/DictionarySettingsFragment.kt
index 276f04d7b..d7f778bca 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/DictionarySettingsFragment.kt
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/DictionarySettingsFragment.kt
@@ -29,6 +29,7 @@ import java.io.File
import java.io.IOException
import java.util.*
+@Suppress("deprecation")
class DictionarySettingsFragment : SubScreenFragment() {
// dict for which dialog is currently open (if any)
@@ -348,7 +349,7 @@ class DictionarySettingsFragment : SubScreenFragment() {
private const val DICTIONARY_REQUEST_CODE = 96834
private const val DICTIONARY_URL =
"https://codeberg.org/Helium314/aosp-dictionaries"
- private const val USER_DICTIONARY_SUFFIX = "user.dict"
+ const val USER_DICTIONARY_SUFFIX = "user.dict"
private const val DICT_INTERNAL_AND_USER = 2
private const val DICT_INTERNAL_ONLY = 1
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterListPreference.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterListPreference.kt
new file mode 100644
index 000000000..2018c2327
--- /dev/null
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageFilterListPreference.kt
@@ -0,0 +1,146 @@
+package org.dslul.openboard.inputmethod.latin.settings
+
+import android.content.Context
+import android.graphics.Rect
+import android.preference.Preference
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.*
+import androidx.core.view.doOnLayout
+import androidx.core.view.isGone
+import androidx.core.view.isVisible
+import androidx.core.widget.doAfterTextChanged
+import androidx.recyclerview.widget.RecyclerView
+import org.dslul.openboard.inputmethod.latin.R
+import org.dslul.openboard.inputmethod.latin.utils.*
+
+class LanguageFilterListPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
+
+ private var preferenceView: View? = null
+ private val adapter = LanguageAdapter(emptyList(), context)
+ private val sortedSubtypes = mutableListOf>()
+
+ fun setSettingsFragment(newFragment: LanguageSettingsFragment?) {
+ adapter.fragment = newFragment
+ }
+
+ override fun onBindView(view: View?) {
+ super.onBindView(view)
+ preferenceView = view
+ preferenceView?.findViewById(R.id.language_list)?.adapter = adapter
+ val searchField = preferenceView?.findViewById(R.id.search_field)!!
+ searchField.doAfterTextChanged { text ->
+ adapter.list = sortedSubtypes.filter { it.first().displayName.startsWith(text.toString(), ignoreCase = true) }
+ }
+ view?.doOnLayout {
+ // set correct height for recycler view, so there is no scrolling of the outside view happening
+ // not sure how, but probably this can be achieved in xml...
+ val windowFrame = Rect()
+ it.getWindowVisibleDisplayFrame(windowFrame) // rect the app has, we want the bottom (above screen bottom/navbar/keyboard)
+ val globalRect = Rect()
+ it.getGlobalVisibleRect(globalRect) // rect the view takes, we want the top (below the system language preference)
+ val recycler = it.findViewById(R.id.language_list)
+
+ val newHeight = windowFrame.bottom - globalRect.top - it.findViewById(R.id.search_container).height
+ recycler.layoutParams = recycler.layoutParams.apply { height = newHeight }
+ }
+ }
+
+ fun setLanguages(list: Collection>, disableSwitches: Boolean) {
+ sortedSubtypes.clear()
+ sortedSubtypes.addAll(list)
+ adapter.disableSwitches = disableSwitches
+ adapter.list = sortedSubtypes
+ }
+
+}
+
+class LanguageAdapter(list: List> = listOf(), context: Context) :
+ RecyclerView.Adapter() {
+ var disableSwitches = false
+ private val prefs = DeviceProtectedUtils.getSharedPreferences(context)
+ var fragment: LanguageSettingsFragment? = null
+
+ var list: List> = list
+ set(value) {
+ field = value
+ notifyDataSetChanged()
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.onBind(list[position])
+ }
+
+ override fun getItemCount() = list.size
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LanguageAdapter.ViewHolder {
+ val v = LayoutInflater.from(parent.context).inflate(R.layout.language_list_item, parent, false)
+ return ViewHolder(v)
+ }
+
+ inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
+
+ fun onBind(infos: MutableList) {
+ fun setupDetailsTextAndSwitch() {
+ // this is unrelated -> rename it
+ view.findViewById(R.id.language_details).apply {
+ // input styles if more than one in infos
+ val sb = StringBuilder()
+ if (infos.size > 1) {
+ sb.append(infos.joinToString(", ") {// separator ok? because for some languages it might not be...
+ SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(it.subtype)
+ ?: SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(it.subtype)
+ })
+ }
+ val secondaryLocales = Settings.getSecondaryLocales(prefs, infos.first().subtype.locale)
+ if (secondaryLocales.isNotEmpty()) {
+ if (sb.isNotEmpty())
+ sb.append("\n")
+ sb.append(Settings.getSecondaryLocales(prefs, infos.first().subtype.locale)
+ .joinToString(", ") {
+ it.getDisplayName(context.resources.configuration.locale)
+ })
+ }
+ text = sb.toString()
+ if (text.isBlank()) isGone = true
+ else isVisible = true
+ }
+
+ view.findViewById(R.id.language_switch).apply {
+ isEnabled = !disableSwitches && infos.size == 1
+ // take care: isChecked changes if the language is scrolled out of view and comes back!
+ // disable the change listener when setting the checked status on scroll
+ // so it's only triggered on user interactions
+ setOnCheckedChangeListener(null)
+ isChecked = disableSwitches || infos.any { it.isEnabled }
+ setOnCheckedChangeListener { _, b ->
+ if (b) {
+ if (infos.size == 1) {
+ addEnabledSubtype(prefs, infos.first().subtype)
+ infos.single().isEnabled = true
+ } else {
+ LanguageSettingsDialog(view.context, infos, fragment, disableSwitches, { setupDetailsTextAndSwitch() }).show()
+ }
+ } else {
+ if (infos.size == 1) {
+ removeEnabledSubtype(prefs, infos.first().subtype)
+ infos.single().isEnabled = false
+ } else {
+ LanguageSettingsDialog(view.context, infos, fragment, disableSwitches, { setupDetailsTextAndSwitch() }).show()
+ }
+ }
+ }
+ }
+ }
+
+ view.findViewById(R.id.language_name).text = infos.first().displayName
+ view.findViewById(R.id.language_text).setOnClickListener {
+ LanguageSettingsDialog(view.context, infos, fragment, disableSwitches, { setupDetailsTextAndSwitch() }).show()
+ }
+ setupDetailsTextAndSwitch()
+ }
+ }
+}
+
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt
new file mode 100644
index 000000000..61ab0c897
--- /dev/null
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsDialog.kt
@@ -0,0 +1,401 @@
+package org.dslul.openboard.inputmethod.latin.settings
+
+import android.app.AlertDialog
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.text.Html
+import android.text.method.LinkMovementMethod
+import android.view.ContextThemeWrapper
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.*
+import androidx.core.view.isGone
+import androidx.core.view.isVisible
+import org.dslul.openboard.inputmethod.dictionarypack.DictionaryPackConstants
+import org.dslul.openboard.inputmethod.latin.BinaryDictionaryGetter
+import org.dslul.openboard.inputmethod.latin.R
+import org.dslul.openboard.inputmethod.latin.common.FileUtils
+import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
+import org.dslul.openboard.inputmethod.latin.makedict.DictionaryHeader
+import org.dslul.openboard.inputmethod.latin.utils.*
+import java.io.File
+import java.io.IOException
+import java.util.*
+import kotlin.collections.HashSet
+
+@Suppress("deprecation")
+class LanguageSettingsDialog(
+ context: Context,
+ private val subtypes: MutableList,
+ private val fragment: LanguageSettingsFragment?,
+ private val disableSwitches: Boolean,
+ private val onSubtypesChanged: () -> Unit
+) : AlertDialog(ContextThemeWrapper(context, R.style.platformDialogTheme)), LanguageSettingsFragment.Listener {
+ private val context = ContextThemeWrapper(context, R.style.platformDialogTheme)
+ private val prefs = DeviceProtectedUtils.getSharedPreferences(context)!!
+ private val view = LayoutInflater.from(context).inflate(R.layout.locale_settings_dialog, null)
+ private val mainLocaleString = subtypes.first().subtype.locale
+ private val mainLocale = mainLocaleString.toLocale()
+ private val cachedDictionaryFile by lazy { File(context.cacheDir.path + File.separator + "temp_dict") }
+
+ init {
+ setTitle(subtypes.first().displayName)
+ setView(ScrollView(context).apply { addView(view) })
+ setButton(BUTTON_NEGATIVE, context.getString(R.string.dialog_close)) { _, _ ->
+ dismiss()
+ }
+
+ fillSubtypesView(view.findViewById(R.id.subtypes))
+ fillSecondaryLocaleView(view.findViewById(R.id.secondary_languages))
+ fillDictionariesView(view.findViewById(R.id.dictionaries))
+ }
+
+ override fun onStart() {
+ super.onStart()
+ fragment?.setListener(this)
+ }
+
+ override fun onStop() {
+ super.onStop()
+ fragment?.setListener(null)
+ }
+
+ private fun fillSubtypesView(subtypesView: LinearLayout) {
+ if (subtypes.any { it.subtype.isAsciiCapable }) { // currently can only add subtypes for latin keyboards
+ subtypesView.findViewById(R.id.add_subtype).setOnClickListener {
+ val layouts = context.resources.getStringArray(R.array.predefined_layouts)
+ .filterNot { layoutName -> subtypes.any { SubtypeLocaleUtils.getKeyboardLayoutSetName(it.subtype) == layoutName } }
+ val displayNames = layouts.map { SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(it) }
+ Builder(context)
+ .setTitle(R.string.keyboard_layout_set)
+ .setItems(displayNames.toTypedArray()) { di, i ->
+ di.dismiss()
+ val newSubtype = AdditionalSubtypeUtils.createAsciiEmojiCapableAdditionalSubtype(mainLocaleString, layouts[i])
+ val newSubtypeInfo = newSubtype.toSubtypeInfo(mainLocale, context.resources, true) // enabled by default, because why else add them
+ addSubtypeToView(newSubtypeInfo, subtypesView)
+ val oldAdditionalSubtypesString = Settings.readPrefAdditionalSubtypes(prefs, context.resources)
+ val oldAdditionalSubtypes = AdditionalSubtypeUtils.createAdditionalSubtypesArray(oldAdditionalSubtypesString).toHashSet()
+ val newAdditionalSubtypesString = AdditionalSubtypeUtils.createPrefSubtypes((oldAdditionalSubtypes + newSubtype).toTypedArray())
+ Settings.writePrefAdditionalSubtypes(prefs, newAdditionalSubtypesString)
+ addEnabledSubtype(prefs, newSubtype)
+ subtypes.add(newSubtypeInfo)
+ onSubtypesChanged()
+ }
+ .setNegativeButton(android.R.string.cancel, null)
+ .show()
+ }
+ } else
+ subtypesView.findViewById(R.id.add_subtype).isGone = true
+
+ // add subtypes
+ subtypes.sortedBy { it.displayName }.forEach {
+ addSubtypeToView(it, subtypesView)
+ }
+ }
+
+ private fun addSubtypeToView(subtype: SubtypeInfo, subtypesView: LinearLayout) {
+ val row = LayoutInflater.from(context).inflate(R.layout.language_list_item, listView)
+ row.findViewById(R.id.language_name).text =
+ SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(subtype.subtype)
+ ?: SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype.subtype)
+ row.findViewById(R.id.language_details).isGone = true
+ row.findViewById(R.id.language_switch).apply {
+ isChecked = subtype.isEnabled
+ isEnabled = !disableSwitches
+ setOnCheckedChangeListener { _, b ->
+ if (b)
+ addEnabledSubtype(prefs, subtype.subtype)
+ else
+ removeEnabledSubtype(prefs, subtype.subtype)
+ subtype.isEnabled = b
+ onSubtypesChanged()
+ }
+ }
+ if (isAdditionalSubtype(subtype.subtype)) {
+ row.findViewById(R.id.language_switch).isEnabled = true
+ row.findViewById(R.id.delete_button).apply {
+ isVisible = true
+ setOnClickListener {
+ // can be re-added easily, no need for confirmation dialog
+ subtypesView.removeView(row)
+ subtypes.remove(subtype)
+
+ val oldAdditionalSubtypesString = Settings.readPrefAdditionalSubtypes(prefs, context.resources)
+ val oldAdditionalSubtypes = AdditionalSubtypeUtils.createAdditionalSubtypesArray(oldAdditionalSubtypesString)
+ val newAdditionalSubtypes = oldAdditionalSubtypes.filter { it != subtype.subtype }
+ val newAdditionalSubtypesString = AdditionalSubtypeUtils.createPrefSubtypes(newAdditionalSubtypes.toTypedArray())
+ Settings.writePrefAdditionalSubtypes(prefs, newAdditionalSubtypesString)
+ removeEnabledSubtype(prefs, subtype.subtype)
+ onSubtypesChanged()
+ }
+ }
+ }
+ subtypesView.addView(row)
+ }
+
+ private fun fillSecondaryLocaleView(secondaryLocalesView: LinearLayout) {
+ // can only use multilingual typing if there is more than one dictionary available
+ val availableSecondaryLocales = getAvailableDictionaryLocales(
+ context,
+ mainLocaleString,
+ subtypes.first().subtype.isAsciiCapable
+ )
+ val selectedSecondaryLocales = Settings.getSecondaryLocales(prefs, mainLocaleString)
+ selectedSecondaryLocales.forEach {
+ addSecondaryLocaleView(it, secondaryLocalesView)
+ }
+ if (availableSecondaryLocales.isNotEmpty()) {
+ secondaryLocalesView.findViewById(R.id.add_secondary_language).apply {
+ isVisible = true
+ setOnClickListener {
+ val locales = (availableSecondaryLocales - Settings.getSecondaryLocales(prefs, mainLocaleString).map { it.toString() }).sorted()
+ val localeNames = locales.map { it.toLocale().getDisplayName(context.resources.configuration.locale) }.toTypedArray()
+ Builder(context)
+ .setTitle(R.string.language_selection_title)
+ .setItems(localeNames) { di, i ->
+ val locale = locales[i]
+ val localeStrings = Settings.getSecondaryLocales(prefs, mainLocaleString).map { it.toString() }
+ Settings.setSecondaryLocales(prefs, mainLocaleString, localeStrings + locale)
+ addSecondaryLocaleView(locale.toLocale(), secondaryLocalesView)
+ di.dismiss()
+ }
+ .show()
+ }
+ }
+ } else if (selectedSecondaryLocales.isEmpty())
+ secondaryLocalesView.isGone = true
+ }
+
+ private fun addSecondaryLocaleView(locale: Locale, secondaryLocalesView: LinearLayout) {
+ val row = LayoutInflater.from(context).inflate(R.layout.language_list_item, listView)
+ row.findViewById(R.id.language_switch).isGone = true
+ row.findViewById(R.id.language_details).isGone = true
+ row.findViewById(R.id.language_name).text = locale.displayName
+ row.findViewById(R.id.delete_button).apply {
+ isVisible = true
+ setOnClickListener {
+ val localeStrings = Settings.getSecondaryLocales(prefs, mainLocaleString).map { it.toString() }
+ Settings.setSecondaryLocales(prefs, mainLocaleString, localeStrings - locale.toString())
+ secondaryLocalesView.removeView(row)
+ }
+ }
+ secondaryLocalesView.addView(row)
+ }
+
+ private fun fillDictionariesView(dictionariesView: LinearLayout) {
+ dictionariesView.findViewById(R.id.add_dictionary).setOnClickListener {
+ val link = "" + context.getString(R.string.dictionary_link_text) + ""
+ val message = Html.fromHtml(context.getString(R.string.add_dictionary, link))
+ val dialog = Builder(context)
+ .setTitle(R.string.add_new_dictionary_title)
+ .setMessage(message)
+ .setPositiveButton(R.string.user_dict_settings_add_menu_title) { _, _ -> fragment?.requestDictionary() }
+ .setNegativeButton(android.R.string.cancel, null)
+ .create()
+ dialog.show()
+ (dialog.findViewById(android.R.id.message) as? TextView)?.movementMethod = LinkMovementMethod.getInstance()
+ }
+ val (userDicts, hasInternalDict) = getUserAndInternalDictionaries(context, mainLocaleString)
+ if (hasInternalDict) {
+ dictionariesView.addView(TextView(context, null, R.style.PreferenceCategoryTitleText).apply {
+ setText(R.string.internal_dictionary_summary)
+ textSize *= 0.8f
+ setPadding((context.resources.displayMetrics.scaledDensity * 16).toInt(), 0, 0, 0)
+ isEnabled = userDicts.none { it.name == "${DictionaryInfoUtils.MAIN_DICT_PREFIX}${DictionarySettingsFragment.USER_DICTIONARY_SUFFIX}" }
+ })
+ }
+ userDicts.sorted().forEach {
+ addDictionaryToView(it, dictionariesView)
+ }
+ }
+
+ override fun onNewDictionary(uri: Uri?) {
+ if (uri == null)
+ return onDictionaryLoadingError(R.string.dictionary_load_error)
+
+ cachedDictionaryFile.delete()
+ try {
+ FileUtils.copyStreamToNewFile(
+ context.contentResolver.openInputStream(uri),
+ cachedDictionaryFile
+ )
+ } catch (e: IOException) {
+ return onDictionaryLoadingError(R.string.dictionary_load_error)
+ }
+ val newHeader = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(cachedDictionaryFile, 0, cachedDictionaryFile.length())
+ ?: return onDictionaryLoadingError(R.string.dictionary_file_error)
+
+ val locale = newHeader.mLocaleString.toLocale()
+ // ScriptUtils.getScriptFromSpellCheckerLocale may return latin when it should not,
+ // e.g. for Persian or Chinese. But at least fail when dictionary certainly is incompatible
+ if (ScriptUtils.getScriptFromSpellCheckerLocale(locale) != ScriptUtils.getScriptFromSpellCheckerLocale(mainLocale))
+ return onDictionaryLoadingError(R.string.dictionary_file_wrong_script)
+
+ if (locale != mainLocale) {
+ val message = context.resources.getString(
+ R.string.dictionary_file_wrong_locale,
+ locale.getDisplayName(context.resources.configuration.locale),
+ mainLocale.getDisplayName(context.resources.configuration.locale)
+ )
+ Builder(context)
+ .setMessage(message)
+ .setNegativeButton(android.R.string.cancel) { _, _ -> cachedDictionaryFile.delete() }
+ .setPositiveButton(R.string.dictionary_file_wrong_locale_ok) { _, _ ->
+ addDictAndAskToReplace(newHeader)
+ }
+ .show()
+ return
+ }
+ addDictAndAskToReplace(newHeader)
+ }
+
+ private fun addDictAndAskToReplace(header: DictionaryHeader) {
+ val dictionaryType = header.mIdString.substringBefore(":")
+ val dictFilename = DictionaryInfoUtils.getCacheDirectoryForLocale(mainLocaleString, context) +
+ File.separator + dictionaryType + "_" + DictionarySettingsFragment.USER_DICTIONARY_SUFFIX
+ val dictFile = File(dictFilename)
+
+ fun moveDict(replaced: Boolean) {
+ if (!cachedDictionaryFile.renameTo(dictFile)) {
+ return onDictionaryLoadingError(R.string.dictionary_load_error)
+ }
+ if (dictionaryType == DictionaryInfoUtils.DEFAULT_MAIN_DICT) {
+ // replaced main dict, remove the one created from internal data
+ val internalMainDictFilename = DictionaryInfoUtils.getCacheDirectoryForLocale(this.toString(), context) +
+ File.separator + DictionaryInfoUtils.getMainDictFilename(this.toString())
+ File(internalMainDictFilename).delete()
+ }
+ val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
+ fragment?.activity?.sendBroadcast(newDictBroadcast)
+ if (!replaced)
+ addDictionaryToView(dictFile, view.findViewById(R.id.dictionaries))
+ }
+
+ if (!dictFile.exists()) {
+ return moveDict(false)
+ }
+ confirmDialog(context, context.getString(R.string.replace_dictionary_message2, dictionaryType), context.getString(
+ R.string.replace_dictionary)) {
+ moveDict(true)
+ }
+ }
+
+ private fun onDictionaryLoadingError(messageId: Int) = onDictionaryLoadingError(context.getString(messageId))
+
+ private fun onDictionaryLoadingError(message: String) {
+ cachedDictionaryFile.delete()
+ Toast.makeText(context, message, Toast.LENGTH_LONG).show()
+ }
+
+ private fun addDictionaryToView(dictFile: File, dictionariesView: LinearLayout) {
+ val dictType = dictFile.name.substringBefore("_${DictionarySettingsFragment.USER_DICTIONARY_SUFFIX}")
+ val row = LayoutInflater.from(context).inflate(R.layout.language_list_item, listView)
+ row.findViewById(R.id.language_name).text = dictType
+ row.findViewById(R.id.language_details).apply {
+ val header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(dictFile, 0, dictFile.length())
+ if (header?.description == null) {
+ isGone = true
+ } else {
+ // what would potentially be interesting? locale? description? version? timestamp?
+ text = header.description
+ }
+ }
+ row.findViewById(R.id.language_switch).isGone = true
+ row.findViewById(R.id.delete_button).apply {
+ isVisible = true
+ setOnClickListener {
+ confirmDialog(context, context.getString(R.string.remove_dictionary_message2, dictType), context.getString(
+ R.string.delete_dict)) {
+ val parent = dictFile.parentFile
+ dictFile.delete()
+ if (parent?.list()?.isEmpty() == true)
+ parent.delete()
+ val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
+ fragment?.activity?.sendBroadcast(newDictBroadcast)
+ dictionariesView.removeView(row)
+ }
+ }
+ }
+ dictionariesView.addView(row)
+ }
+}
+
+fun confirmDialog(context: Context, message: String, confirmButton: String, onConfirmed: (() -> Unit)) {
+ AlertDialog.Builder(context)
+ .setMessage(message)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(confirmButton) { _, _ -> onConfirmed() }
+ .show()
+}
+
+/** @return list of user dictionary files and whether an internal dictionary exists */
+fun getUserAndInternalDictionaries(context: Context, locale: String): Pair, Boolean> {
+ val localeString = locale.lowercase() // internal files and folders always use lowercase
+ val userDicts = mutableListOf()
+ var hasInternalDict = false
+ val userLocaleDir = File(DictionaryInfoUtils.getWordListCacheDirectory(context), localeString)
+ if (userLocaleDir.exists() && userLocaleDir.isDirectory) {
+ userLocaleDir.listFiles()?.forEach {
+ if (it.name.endsWith(DictionarySettingsFragment.USER_DICTIONARY_SUFFIX))
+ userDicts.add(it)
+ else if (it.name.startsWith(DictionaryInfoUtils.MAIN_DICT_PREFIX))
+ hasInternalDict = true
+ }
+ }
+ if (hasInternalDict)
+ return userDicts to true
+ BinaryDictionaryGetter.getAssetsDictionaryList(context)?.forEach { dictFile ->
+ BinaryDictionaryGetter.extractLocaleFromAssetsDictionaryFile(dictFile)?.let {
+ if (it == localeString)
+ return userDicts to true
+ }
+ }
+ return userDicts to false
+}
+
+// get locales with same script as main locale, but different language
+private fun getAvailableDictionaryLocales(context: Context, mainLocaleString: String, asciiCapable: Boolean): Set {
+ val mainLocale = mainLocaleString.toLocale()
+ val locales = HashSet()
+ val mainScript = if (asciiCapable) ScriptUtils.SCRIPT_LATIN
+ else ScriptUtils.getScriptFromSpellCheckerLocale(mainLocale)
+ // ScriptUtils.getScriptFromSpellCheckerLocale may return latin when it should not
+ // e.g. for persian or chinese
+ // workaround: don't allow secondary locales for these locales
+ if (!asciiCapable && mainScript == ScriptUtils.SCRIPT_LATIN) return locales
+
+ // get cached dictionaries: extracted or user-added dictionaries
+ val cachedDirectoryList = DictionaryInfoUtils.getCachedDirectoryList(context)
+ if (cachedDirectoryList != null) {
+ for (directory in cachedDirectoryList) {
+ if (!directory.isDirectory) continue
+ val dirLocale = DictionaryInfoUtils.getWordListIdFromFileName(directory.name)
+ if (dirLocale == mainLocaleString) continue
+ val locale = dirLocale.toLocale()
+ if (locale.language == mainLocale.language) continue
+ val localeScript = ScriptUtils.getScriptFromSpellCheckerLocale(locale)
+ if (localeScript != mainScript) continue
+ locales.add(locale.toString())
+ }
+ }
+ // get assets dictionaries
+ val assetsDictionaryList = BinaryDictionaryGetter.getAssetsDictionaryList(context)
+ if (assetsDictionaryList != null) {
+ for (dictionary in assetsDictionaryList) {
+ val dictLocale =
+ BinaryDictionaryGetter.extractLocaleFromAssetsDictionaryFile(dictionary)
+ ?: continue
+ if (dictLocale == mainLocaleString) continue
+ val locale = dictLocale.toLocale()
+ if (locale.language == mainLocale.language) continue
+ val localeScript = ScriptUtils.getScriptFromSpellCheckerLocale(locale)
+ if (localeScript != mainScript) continue
+ locales.add(locale.toString())
+ }
+ }
+ return locales
+}
+
+private fun String.toLocale() = LocaleUtils.constructLocaleFromString(this)
+private const val DICTIONARY_URL = "https://codeberg.org/Helium314/aosp-dictionaries"
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsFragment.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsFragment.kt
new file mode 100644
index 000000000..9eb39ba51
--- /dev/null
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/LanguageSettingsFragment.kt
@@ -0,0 +1,188 @@
+package org.dslul.openboard.inputmethod.latin.settings
+
+import android.app.Activity
+import android.content.Intent
+import android.content.res.Resources
+import android.net.Uri
+import android.os.Bundle
+import android.preference.TwoStatePreference
+import android.view.inputmethod.InputMethodSubtype
+import org.dslul.openboard.inputmethod.latin.R
+import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
+import org.dslul.openboard.inputmethod.latin.utils.DictionaryInfoUtils
+import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils
+import java.util.Locale
+
+
+@Suppress("Deprecation") // yes everything here is deprecated, but only work on this if really necessary
+class LanguageSettingsFragment : SubScreenFragment() {
+
+ private val sortedSubtypes = LinkedHashMap>()
+ private val enabledSubtypes = mutableListOf()
+ private val systemLocales = mutableListOf()
+ private val languageFilterListPreference by lazy { findPreference("pref_language_filter") as LanguageFilterListPreference }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ addPreferencesFromResource(R.xml.prefs_screen_languages);
+ SubtypeLocaleUtils.init(activity)
+
+ enabledSubtypes.addAll(getExplicitlyEnabledSubtypes())
+ systemLocales.addAll(getSystemLocales())
+ val systemLocalesSwitch = findPreference(Settings.PREF_USE_SYSTEM_LOCALES) as TwoStatePreference
+ systemLocalesSwitch.setOnPreferenceChangeListener { _, b ->
+ loadSubtypes(b as Boolean)
+ true
+ }
+ loadSubtypes(systemLocalesSwitch.isChecked)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ languageFilterListPreference.setSettingsFragment(this)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ languageFilterListPreference.setSettingsFragment(null)
+ }
+
+ private fun loadSubtypes(systemOnly: Boolean) {
+ sortedSubtypes.clear()
+ val allSubtypes = getAllAvailableSubtypes().toMutableList()
+ // maybe make use of the map used by SubtypeSettings for performance reasons?
+ fun List.sortedAddToSubtypesAndRemoveFromAllSubtypes() {
+ val subtypesToAdd = mutableListOf()
+ forEach { locale ->
+ val localeString = locale.toString()
+ val iter = allSubtypes.iterator()
+ var added = false
+ while (iter.hasNext()) {
+ val subtype = iter.next()
+ if (subtype.locale == localeString) {
+ subtypesToAdd.add(subtype.toSubtypeInfo(locale))
+ iter.remove()
+ added = true
+ }
+ }
+ if (!added && locale.country.isNotEmpty()) {
+ // try again, but with language only
+ val languageString = locale.language
+ val iter = allSubtypes.iterator()
+ while (iter.hasNext()) {
+ val subtype = iter.next()
+ if (subtype.locale == languageString) {
+ subtypesToAdd.add(subtype.toSubtypeInfo(LocaleUtils.constructLocaleFromString(languageString)))
+ iter.remove()
+ added = true
+ }
+ }
+ }
+ // special treatment for the known languages with _ZZ types
+ // todo: later: make it a bit less weird... and probably faster
+ // consider that more _ZZ languages might be added (e.g. hinglish)
+ if (!added && locale.language == "sr") {
+ val languageString = locale.language
+ val iter = allSubtypes.iterator()
+ while (iter.hasNext()) {
+ val subtype = iter.next()
+ if (subtype.locale.substringBefore("_") == languageString) {
+ subtypesToAdd.add(subtype.toSubtypeInfo(LocaleUtils.constructLocaleFromString(subtype.locale)))
+ iter.remove()
+ }
+ }
+ }
+ }
+ subtypesToAdd.sortedBy { it.displayName }.addToSortedSubtypes()
+ }
+
+ if (systemOnly) {
+ systemLocales.sortedAddToSubtypesAndRemoveFromAllSubtypes()
+ languageFilterListPreference.setLanguages(sortedSubtypes.values, systemOnly)
+ return
+ }
+
+ // add enabled subtypes
+ enabledSubtypes.map { it.toSubtypeInfo(LocaleUtils.constructLocaleFromString(it.locale), true) }
+ .sortedBy { it.displayName }.addToSortedSubtypes()
+ allSubtypes.removeAll(enabledSubtypes)
+
+ // add subtypes that have a dictionary
+ val localesWithDictionary = DictionaryInfoUtils.getCachedDirectoryList(activity)?.mapNotNull { dir ->
+ if (!dir.isDirectory)
+ return@mapNotNull null
+ if (dir.list()?.any { it.endsWith(DictionarySettingsFragment.USER_DICTIONARY_SUFFIX) } == true)
+ LocaleUtils.constructLocaleFromString(dir.name)
+ else null
+ }
+ localesWithDictionary?.sortedAddToSubtypesAndRemoveFromAllSubtypes()
+
+ // add subtypes for device locales
+ systemLocales.sortedAddToSubtypesAndRemoveFromAllSubtypes()
+
+ // add the remaining ones
+ allSubtypes.map { it.toSubtypeInfo(LocaleUtils.constructLocaleFromString(it.locale)) }
+ .sortedBy { if (it.subtype.locale.equals("zz", true))
+ "zz" // "No language (Alphabet)" should be last
+ else it.displayName
+ }.addToSortedSubtypes()
+
+ // set languages
+ languageFilterListPreference.setLanguages(sortedSubtypes.values, systemOnly)
+ }
+
+ private fun InputMethodSubtype.toSubtypeInfo(locale: Locale, isEnabled: Boolean = false) =
+ toSubtypeInfo(locale, resources, isEnabled)
+
+ private fun List.addToSortedSubtypes() {
+ forEach {
+ sortedSubtypes.getOrPut(it.displayName) { mutableListOf() }.add(it)
+ }
+ }
+
+ interface Listener {
+ fun onNewDictionary(uri: Uri?)
+ }
+
+ private var listener: Listener? = null
+
+ fun setListener(newListener: Listener?) {
+ listener = newListener
+ }
+
+ fun requestDictionary() {
+ val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType("application/octet-stream")
+ startActivityForResult(intent, DICTIONARY_REQUEST_CODE)
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
+ if (resultCode == Activity.RESULT_OK && requestCode == DICTIONARY_REQUEST_CODE)
+ listener?.onNewDictionary(resultData?.data)
+ }
+
+}
+
+class SubtypeInfo(val displayName: String, val subtype: InputMethodSubtype, var isEnabled: Boolean) {
+ override fun equals(other: Any?): Boolean {
+ if (other !is SubtypeInfo) return false
+ return subtype == other.subtype
+ }
+
+ override fun hashCode(): Int {
+ return subtype.hashCode()
+ }
+}
+
+fun InputMethodSubtype.toSubtypeInfo(locale: Locale, resources: Resources, isEnabled: Boolean): SubtypeInfo {
+ val displayName = if (locale.toString().equals("zz", true)) // no language
+ SubtypeLocaleUtils.getSubtypeLocaleDisplayNameInSystemLocale(locale.toString())
+ else if (locale.toString().endsWith("zz", true)) // serbian (latin), maybe others in the future
+ SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(this)
+ else
+ locale.getDisplayName(resources.configuration.locale)
+ return SubtypeInfo(displayName, this, isEnabled)
+}
+
+private const val DICTIONARY_REQUEST_CODE = 96834
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SecondaryLocaleSettingsFragment.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SecondaryLocaleSettingsFragment.java
index b31076f4d..e3887a079 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SecondaryLocaleSettingsFragment.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SecondaryLocaleSettingsFragment.java
@@ -109,7 +109,7 @@ public final class SecondaryLocaleSettingsFragment extends SubScreenFragment {
locale = "";
final Set encodedLocales = new HashSet<>();
boolean updated = false;
- for (String encodedLocale : getSharedPreferences().getStringSet(Settings.PREF_SECONDARY_LOCALES, new HashSet<>())) {
+ for (String encodedLocale : getSharedPreferences().getStringSet(Settings.PREF_SECONDARY_LOCALES_PREFIX, new HashSet<>())) {
String[] locs = encodedLocale.split("§");
if (locs.length == 2 && locs[0].equals(mainLocale)) {
if (!locale.isEmpty())
@@ -121,7 +121,7 @@ public final class SecondaryLocaleSettingsFragment extends SubScreenFragment {
}
if (!updated)
encodedLocales.add(mainLocale + "§" + locale);
- getSharedPreferences().edit().putStringSet(Settings.PREF_SECONDARY_LOCALES, encodedLocales).apply();
+ getSharedPreferences().edit().putStringSet(Settings.PREF_SECONDARY_LOCALES_PREFIX, encodedLocales).apply();
final Intent newDictBroadcast = new Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
getActivity().sendBroadcast(newDictBroadcast);
resetKeyboardLocales();
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java
index ae76dbce5..83f1b3bd7 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/Settings.java
@@ -43,7 +43,6 @@ import org.dslul.openboard.inputmethod.latin.utils.StatsUtils;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -146,11 +145,13 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_ENABLE_CLIPBOARD_HISTORY = "pref_enable_clipboard_history";
public static final String PREF_CLIPBOARD_HISTORY_RETENTION_TIME = "pref_clipboard_history_retention_time";
- public static final String PREF_SECONDARY_LOCALES = "pref_secondary_locales";
+ public static final String PREF_SECONDARY_LOCALES_PREFIX = "pref_secondary_locales_";
public static final String PREF_ADD_TO_PERSONAL_DICTIONARY = "pref_add_to_personal_dictionary";
public static final String PREF_NAVBAR_COLOR = "pref_navbar_color";
-
public static final String PREF_NARROW_KEY_GAPS = "pref_narrow_key_gaps";
+ public static final String PREF_ENABLED_INPUT_STYLES = "pref_enabled_input_styles";
+ public static final String PREF_SELECTED_INPUT_STYLE = "pref_selected_input_style";
+ public static final String PREF_USE_SYSTEM_LOCALES = "pref_use_system_locales";
// This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
// This is being used only for the backward compatibility.
@@ -219,6 +220,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
} finally {
mSettingsValuesLock.unlock();
}
+ if (key.equals(PREF_CUSTOM_INPUT_STYLES)) {
+ final String additionalSubtypes = readPrefAdditionalSubtypes(prefs, mContext.getResources());
+ SubtypeSettingsKt.updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes));
+ }
}
public void loadSettings(final Context context, final Locale locale,
@@ -544,15 +549,27 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID, defValue);
}
- // todo: adjust for multiple secondary locales
public static List getSecondaryLocales(final SharedPreferences prefs, final String mainLocaleString) {
- final Set encodedLocales = prefs.getStringSet(PREF_SECONDARY_LOCALES, new HashSet<>());
- for (String loc : encodedLocales) {
- String[] locales = loc.split("§");
- if (locales.length == 2 && locales[0].equals(mainLocaleString.toLowerCase(Locale.ENGLISH)))
- return new ArrayList() {{ add(LocaleUtils.constructLocaleFromString(locales[1])); }};
+ final String localesString = prefs.getString(PREF_SECONDARY_LOCALES_PREFIX + mainLocaleString.toLowerCase(Locale.ROOT), "");
+
+ final ArrayList locales = new ArrayList<>();
+ for (String locale : localesString.split(";")) {
+ if (locale.isEmpty()) continue;
+ locales.add(LocaleUtils.constructLocaleFromString(locale));
}
- return new ArrayList<>();
+ return locales;
+ }
+
+ public static void setSecondaryLocales(final SharedPreferences prefs, final String mainLocaleString, final List locales) {
+ if (locales.isEmpty()) {
+ prefs.edit().putString(PREF_SECONDARY_LOCALES_PREFIX + mainLocaleString.toLowerCase(Locale.ROOT), "").apply();
+ return;
+ }
+ final StringBuilder sb = new StringBuilder();
+ for (String locale : locales) {
+ sb.append(";").append(locale);
+ }
+ prefs.edit().putString(PREF_SECONDARY_LOCALES_PREFIX + mainLocaleString.toLowerCase(Locale.ROOT), sb.toString()).apply();
}
public static Colors getColors(final Context context, final SharedPreferences prefs) {
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsFragment.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsFragment.java
index 27e00ea57..1eae0c5ec 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsFragment.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsFragment.java
@@ -29,15 +29,18 @@ import android.provider.Settings.Secure;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.inputmethod.InputMethodSubtype;
import org.dslul.openboard.inputmethod.latin.BuildConfig;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.common.FileUtils;
import org.dslul.openboard.inputmethod.latin.utils.ApplicationUtils;
+import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
import org.dslul.openboard.inputmethod.latin.utils.FeedbackUtils;
import org.dslul.openboard.inputmethod.latin.utils.JniUtils;
import org.dslul.openboard.inputmethodcommon.InputMethodSettingsFragment;
+import java.util.List;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -83,6 +86,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment {
if (actionBar != null && screenTitle != null) {
actionBar.setTitle(screenTitle);
}
+ findPreference("screen_languages").setSummary(getEnabledSubtypesLabel());
if (BuildConfig.DEBUG)
askAboutCrashReports();
}
@@ -129,11 +133,20 @@ public final class SettingsFragment extends InputMethodSettingsFragment {
return Secure.getInt(activity.getContentResolver(), "user_setup_complete", 0) != 0;
}
+ private String getEnabledSubtypesLabel() {
+ final List subtypes = SubtypeSettingsKt.getEnabledSubtypes(DeviceProtectedUtils.getSharedPreferences(getActivity()), true);
+ final StringBuilder sb = new StringBuilder();
+ for (final InputMethodSubtype subtype : subtypes) {
+ if (sb.length() > 0)
+ sb.append(", ");
+ sb.append(subtype.getDisplayName(getActivity(), getActivity().getPackageName(), getActivity().getApplicationInfo()));
+ }
+ return sb.toString();
+
private void askAboutCrashReports() {
// find crash report files
final File dir = getActivity().getExternalFilesDir(null);
if (dir == null) return;
-// final File[] files = dir.listFiles((file, s) -> file.getName().startsWith("crash_report"));
final File[] allFiles = dir.listFiles();
if (allFiles == null) return;
crashReportFiles.clear();
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java
index 83246c084..92162e987 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SettingsValues.java
@@ -252,7 +252,7 @@ public class SettingsValues {
mClipboardHistoryRetentionTime = Settings.readClipboardHistoryRetentionTime(prefs, res);
mOneHandedModeEnabled = Settings.readOneHandedModeEnabled(prefs);
mOneHandedModeGravity = Settings.readOneHandedModeGravity(prefs);
- mSecondaryLocales = Settings.getSecondaryLocales(prefs, RichInputMethodManager.getInstance().getCurrentSubtypeLocale().toString());
+ mSecondaryLocales = Settings.getSecondaryLocales(prefs, SubtypeSettingsKt.getSelectedSubtype(prefs).getLocale());
mColors = Settings.getColors(context, prefs);
mColors.createColorFilters(prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false));
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubtypeSettings.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubtypeSettings.kt
new file mode 100644
index 000000000..e73160328
--- /dev/null
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/settings/SubtypeSettings.kt
@@ -0,0 +1,221 @@
+package org.dslul.openboard.inputmethod.latin.settings
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.content.res.Resources
+import android.os.Build
+import android.view.inputmethod.InputMethodSubtype
+import androidx.core.app.LocaleManagerCompat
+import androidx.core.content.edit
+import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher
+import org.dslul.openboard.inputmethod.latin.BuildConfig
+import org.dslul.openboard.inputmethod.latin.R
+import org.dslul.openboard.inputmethod.latin.RichInputMethodManager
+import org.dslul.openboard.inputmethod.latin.utils.AdditionalSubtypeUtils
+import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils
+import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils
+import org.xmlpull.v1.XmlPullParser
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.collections.LinkedHashMap
+
+/** @return enabled subtypes. If no subtypes are enabled, but a contextForFallback is provided,
+ * subtypes for system locales will be returned, or en_US if none found. */
+fun getEnabledSubtypes(prefs: SharedPreferences, fallback: Boolean = false): List {
+ require(initialized)
+ if (prefs.getBoolean(Settings.PREF_USE_SYSTEM_LOCALES, true))
+ return getDefaultEnabledSubtypes()
+ return getExplicitlyEnabledSubtypes(fallback)
+}
+
+fun getExplicitlyEnabledSubtypes(fallback: Boolean = false): List {
+ require(initialized)
+ if (fallback && enabledSubtypes.isEmpty())
+ return getDefaultEnabledSubtypes()
+ return enabledSubtypes
+}
+
+fun getAllAvailableSubtypes(): List {
+ require(initialized)
+ return resourceSubtypesByLocale.values.flatten() + additionalSubtypes
+}
+
+fun addEnabledSubtype(prefs: SharedPreferences, subtype: InputMethodSubtype) {
+ require(initialized)
+ val subtypeString = subtype.prefString()
+ val oldSubtypeStrings = prefs.getString(Settings.PREF_ENABLED_INPUT_STYLES, "")!!.split(SUBTYPE_SEPARATOR)
+ val newString = (oldSubtypeStrings + subtypeString).filter { it.isNotBlank() }.toSortedSet().joinToString(SUBTYPE_SEPARATOR)
+ prefs.edit { putString(Settings.PREF_ENABLED_INPUT_STYLES, newString) }
+
+ if (subtype !in enabledSubtypes) {
+ enabledSubtypes.add(subtype)
+ enabledSubtypes.sortBy { it.locale } // for consistent order
+ }
+}
+
+/** returns whether subtype was actually removed, does not remove last subtype */
+fun removeEnabledSubtype(prefs: SharedPreferences, subtype: InputMethodSubtype) {
+ require(initialized)
+ val subtypeString = subtype.prefString()
+ val oldSubtypeString = prefs.getString(Settings.PREF_ENABLED_INPUT_STYLES, "")!!
+ val newString = (oldSubtypeString.split(SUBTYPE_SEPARATOR) - subtypeString).joinToString(SUBTYPE_SEPARATOR)
+ if (newString == oldSubtypeString)
+ return // already removed
+ prefs.edit { putString(Settings.PREF_ENABLED_INPUT_STYLES, newString) }
+ if (subtypeString == prefs.getString(Settings.PREF_SELECTED_INPUT_STYLE, "")) {
+ // switch subtype if the currently used one has been disabled
+ val nextSubtype = RichInputMethodManager.getInstance().getNextSubtypeInThisIme(true)
+ if (subtypeString == nextSubtype?.prefString())
+ KeyboardSwitcher.getInstance().switchToSubtype(getDefaultEnabledSubtypes().first())
+ else
+ KeyboardSwitcher.getInstance().switchToSubtype(nextSubtype)
+ }
+ enabledSubtypes.remove(subtype)
+}
+
+fun getSelectedSubtype(prefs: SharedPreferences): InputMethodSubtype {
+ require(initialized)
+ val subtypeString = prefs.getString(Settings.PREF_SELECTED_INPUT_STYLE, "")!!.split(LOCALE_LAYOUT_SEPARATOR)
+ val subtype = enabledSubtypes.firstOrNull { subtypeString.first() == it.locale && subtypeString.last() == SubtypeLocaleUtils.getKeyboardLayoutSetName(it) }
+ ?: enabledSubtypes.firstOrNull()
+ if (subtype == null) {
+ val defaultSubtypes = getDefaultEnabledSubtypes()
+ return defaultSubtypes.firstOrNull { subtypeString.first() == it.locale && subtypeString.last() == SubtypeLocaleUtils.getKeyboardLayoutSetName(it) }
+ ?: defaultSubtypes.firstOrNull { subtypeString.first().substringBefore("_") == it.locale.substringBefore("_") && subtypeString.last() == SubtypeLocaleUtils.getKeyboardLayoutSetName(it) }
+ ?: defaultSubtypes.first()
+ }
+ return subtype
+}
+
+fun setSelectedSubtype(prefs: SharedPreferences, subtype: InputMethodSubtype) {
+ val subtypeString = subtype.prefString()
+ if (subtype.locale.isEmpty() || prefs.getString(Settings.PREF_SELECTED_INPUT_STYLE, "") == subtypeString)
+ return
+ prefs.edit { putString(Settings.PREF_SELECTED_INPUT_STYLE, subtypeString) }
+}
+
+fun isAdditionalSubtype(subtype: InputMethodSubtype): Boolean {
+ return subtype in additionalSubtypes
+}
+
+fun updateAdditionalSubtypes(subtypes: Array) {
+ additionalSubtypes.clear()
+ additionalSubtypes.addAll(subtypes)
+}
+
+fun reloadSystemLocales(context: Context) {
+ systemLocales.clear()
+ val localeList = LocaleManagerCompat.getSystemLocales(context)
+ (0 until localeList.size()).forEach {
+ val locale = localeList[it]
+ if (locale != null) systemLocales.add(locale)
+ }
+}
+
+fun getSystemLocales(): List {
+ require(initialized)
+ return systemLocales
+}
+
+fun init(context: Context) {
+ if (initialized) return
+ SubtypeLocaleUtils.init(context) // necessary to get the correct getKeyboardLayoutSetName
+
+ // necessary to set system locales at start, because for some weird reason (bug?)
+ // LocaleManagerCompat.getSystemLocales(context) sometimes doesn't return all system locales
+ reloadSystemLocales(context)
+
+ loadResourceSubtypes(context.resources)
+ loadAdditionalSubtypes(context)
+ loadEnabledSubtypes(context)
+ initialized = true
+}
+
+private fun getDefaultEnabledSubtypes(): List {
+ val inputMethodSubtypes = systemLocales.mapNotNull { locale ->
+ val localeString = locale.toString()
+ val subtypes = resourceSubtypesByLocale[localeString]
+ ?: resourceSubtypesByLocale[localeString.substringBefore("_")] // fall back to language match
+ subtypes?.firstOrNull() // todo: maybe set default for some languages with multiple resource subtypes?
+ }
+ if (inputMethodSubtypes.isEmpty())
+ // hardcoded fallback for weird cases
+ return listOf(resourceSubtypesByLocale["en_US"]!!.first())
+ return inputMethodSubtypes
+}
+
+private fun InputMethodSubtype.prefString() =
+ locale + LOCALE_LAYOUT_SEPARATOR + SubtypeLocaleUtils.getKeyboardLayoutSetName(this)
+
+private fun loadResourceSubtypes(resources: Resources) {
+ val xml = resources.getXml(R.xml.method)
+ xml.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true)
+ val namespace = "http://schemas.android.com/apk/res/android"
+ var eventType = xml.eventType
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG && xml.name == "subtype") {
+ val icon = xml.getAttributeResourceValue(namespace, "icon", 0)
+ val label = xml.getAttributeResourceValue(namespace, "label", 0)
+ val subtypeId = xml.getAttributeIntValue(namespace, "subtypeId", 0)
+ val locale = xml.getAttributeValue(namespace, "imeSubtypeLocale").intern()
+ val languageTag = xml.getAttributeValue(namespace, "languageTag")
+ val imeSubtypeMode = xml.getAttributeValue(namespace, "imeSubtypeMode")
+ val imeSubtypeExtraValue = xml.getAttributeValue(namespace, "imeSubtypeExtraValue").intern()
+ val isAsciiCapable = xml.getAttributeBooleanValue(namespace, "isAsciiCapable", false)
+ val b = InputMethodSubtype.InputMethodSubtypeBuilder()
+ b.setSubtypeIconResId(icon)
+ b.setSubtypeNameResId(label)
+ if (subtypeId != 0)
+ b.setSubtypeId(subtypeId)
+ b.setSubtypeLocale(locale)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && languageTag != null)
+ b.setLanguageTag(languageTag)
+ b.setSubtypeMode(imeSubtypeMode)
+ b.setSubtypeExtraValue(imeSubtypeExtraValue)
+ b.setIsAsciiCapable(isAsciiCapable)
+ resourceSubtypesByLocale.getOrPut(locale) { ArrayList(2) }.add(b.build())
+ }
+ eventType = xml.next()
+ }
+}
+
+private fun loadAdditionalSubtypes(context: Context) {
+ val prefs = DeviceProtectedUtils.getSharedPreferences(context)
+ val additionalSubtypeString = Settings.readPrefAdditionalSubtypes(prefs, context.resources)
+ val subtypes = AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypeString)
+ additionalSubtypes.addAll(subtypes)
+}
+
+// requires loadResourceSubtypes to be called before
+private fun loadEnabledSubtypes(context: Context) {
+ val prefs = DeviceProtectedUtils.getSharedPreferences(context)
+ val subtypeStrings = prefs.getString(Settings.PREF_ENABLED_INPUT_STYLES, "")!!
+ .split(SUBTYPE_SEPARATOR).filter { it.isNotEmpty() }.map { it.split(LOCALE_LAYOUT_SEPARATOR) }
+
+ for (localeAndLayout in subtypeStrings) {
+ require(localeAndLayout.size == 2)
+ val subtypesForLocale = resourceSubtypesByLocale[localeAndLayout.first()]
+ if (BuildConfig.DEBUG) // should not happen, but should not crash for normal user
+ require(subtypesForLocale != null)
+ else if (subtypesForLocale == null)
+ continue
+
+ val subtype = subtypesForLocale.firstOrNull { SubtypeLocaleUtils.getKeyboardLayoutSetName(it) == localeAndLayout.last() }
+ ?: additionalSubtypes.firstOrNull { it.locale == localeAndLayout.first() && SubtypeLocaleUtils.getKeyboardLayoutSetName(it) == localeAndLayout.last() }
+ if (BuildConfig.DEBUG) // should not happen, but should not crash for normal user
+ require(subtype != null)
+ else if (subtype == null)
+ continue
+
+ enabledSubtypes.add(subtype)
+ }
+}
+
+private var initialized = false
+private val enabledSubtypes = mutableListOf()
+private val resourceSubtypesByLocale = LinkedHashMap>(100)
+private val additionalSubtypes = mutableListOf()
+private val systemLocales = mutableListOf()
+
+private const val SUBTYPE_SEPARATOR = ";"
+private const val LOCALE_LAYOUT_SEPARATOR = ":"
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/setup/SetupWizardActivity.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/setup/SetupWizardActivity.java
index 246bbfde6..40175da51 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/setup/SetupWizardActivity.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/setup/SetupWizardActivity.java
@@ -180,11 +180,14 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL
(TextView)findViewById(R.id.setup_step3_bullet), findViewById(R.id.setup_step3),
R.string.setup_step3_title, R.string.setup_step3_instruction,
0 /* finishedInstruction */, R.drawable.ic_setup_step3,
- R.string.setup_step3_action);
+ R.string.setup_step3_action_new);
step3.setAction(new Runnable() {
@Override
public void run() {
- invokeSubtypeEnablerOfThisIme();
+ final Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
+ intent.setAction(Intent.ACTION_VIEW);
+ startActivity(intent);
+ finish();
}
});
mSetupStepGroup.addStep(step3);
@@ -282,19 +285,6 @@ public final class SetupWizardActivity extends Activity implements View.OnClickL
mNeedsToAdjustStepNumberToSystemState = true;
}
- void invokeSubtypeEnablerOfThisIme() {
- final InputMethodInfo imi =
- UncachedInputMethodManagerUtils.getInputMethodInfoOf(getPackageName(), mImm);
- if (imi == null) {
- return;
- }
- final Intent intent = new Intent();
- intent.setAction(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, imi.getId());
- startActivity(intent);
- }
-
private int determineSetupStepNumberFromLauncher() {
final int stepNumber = determineSetupStepNumber();
if (stepNumber == STEP_1) {
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/AdditionalSubtypeUtils.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/AdditionalSubtypeUtils.java
index de1acdca0..078b32e30 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/AdditionalSubtypeUtils.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/AdditionalSubtypeUtils.java
@@ -107,29 +107,35 @@ public final class AdditionalSubtypeUtils {
final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR);
final ArrayList subtypesList = new ArrayList<>(prefSubtypeArray.length);
for (final String prefSubtype : prefSubtypeArray) {
- final String[] elems = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR);
- if (elems.length != LENGTH_WITHOUT_EXTRA_VALUE
- && elems.length != LENGTH_WITH_EXTRA_VALUE) {
- Log.w(TAG, "Unknown additional subtype specified: " + prefSubtype + " in "
- + prefSubtypes);
- continue;
- }
- final String localeString = elems[INDEX_OF_LOCALE];
- final String keyboardLayoutSetName = elems[INDEX_OF_KEYBOARD_LAYOUT];
- // Here we assume that all the additional subtypes have AsciiCapable and EmojiCapable.
- // This is actually what the setting dialog for additional subtype is doing.
- final InputMethodSubtype subtype = createAsciiEmojiCapableAdditionalSubtype(
- localeString, keyboardLayoutSetName);
- if (subtype.getNameResId() == SubtypeLocaleUtils.UNKNOWN_KEYBOARD_LAYOUT) {
- // Skip unknown keyboard layout subtype. This may happen when predefined keyboard
- // layout has been removed.
- continue;
- }
- subtypesList.add(subtype);
+ final InputMethodSubtype subtype = createSubtypeFromString(prefSubtype);
+ if (subtype != null)
+ subtypesList.add(subtype);
}
return subtypesList.toArray(new InputMethodSubtype[subtypesList.size()]);
}
+ // use string created with getPrefSubtype
+ public static InputMethodSubtype createSubtypeFromString(final String prefSubtype) {
+ final String[] elems = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR);
+ if (elems.length != LENGTH_WITHOUT_EXTRA_VALUE
+ && elems.length != LENGTH_WITH_EXTRA_VALUE) {
+ Log.w(TAG, "Unknown additional subtype specified: " + prefSubtype);
+ return null;
+ }
+ final String localeString = elems[INDEX_OF_LOCALE];
+ final String keyboardLayoutSetName = elems[INDEX_OF_KEYBOARD_LAYOUT];
+ // Here we assume that all the additional subtypes have AsciiCapable and EmojiCapable.
+ // This is actually what the setting dialog for additional subtype is doing.
+ final InputMethodSubtype subtype = createAsciiEmojiCapableAdditionalSubtype(
+ localeString, keyboardLayoutSetName);
+ if (subtype.getNameResId() == SubtypeLocaleUtils.UNKNOWN_KEYBOARD_LAYOUT) {
+ // Skip unknown keyboard layout subtype. This may happen when predefined keyboard
+ // layout has been removed.
+ return null;
+ }
+ return subtype;
+ }
+
public static String createPrefSubtypes(final InputMethodSubtype[] subtypes) {
if (subtypes == null || subtypes.length == 0) {
return "";
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/DictionaryInfoUtils.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/DictionaryInfoUtils.java
index 372e08a51..e05865c83 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -329,6 +329,7 @@ public class DictionaryInfoUtils {
return MAIN_DICT_PREFIX + locale.toLowerCase(Locale.ENGLISH) + ".dict";
}
+ @Nullable
public static DictionaryHeader getDictionaryFileHeaderOrNull(final File file,
final long offset, final long length) {
try {
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/InputMethodPicker.kt b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/InputMethodPicker.kt
new file mode 100644
index 000000000..6a2fe465d
--- /dev/null
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/InputMethodPicker.kt
@@ -0,0 +1,80 @@
+package org.dslul.openboard.inputmethod.latin.utils
+
+import android.app.AlertDialog
+import android.os.IBinder
+import android.text.Spannable
+import android.text.SpannableString
+import android.text.SpannableStringBuilder
+import android.text.style.RelativeSizeSpan
+import android.view.WindowManager
+import android.view.inputmethod.InputMethodInfo
+import android.view.inputmethod.InputMethodSubtype
+import org.dslul.openboard.inputmethod.latin.LatinIME
+import org.dslul.openboard.inputmethod.latin.R
+import org.dslul.openboard.inputmethod.latin.RichInputMethodManager
+
+// similar to what showSubtypePicker does in https://github.com/rkkr/simple-keyboard/blob/master/app/src/main/java/rkr/simplekeyboard/inputmethod/latin/RichInputMethodManager.java
+fun showInputMethodPicker(latinIme: LatinIME, richImm: RichInputMethodManager, windowToken: IBinder) {
+ val pm = latinIme.packageManager
+ val thisImi = richImm.inputMethodInfoOfThisIme
+ val currentSubtype = richImm.currentSubtype.rawSubtype
+ val enabledImis = richImm.inputMethodManager.enabledInputMethodList
+ .sortedBy { it.hashCode() }.sortedBy { it.loadLabel(pm).toString() } // first label, then hashCode
+ val enabledSubtypes = mutableListOf>()
+ var currentSubtypeIndex = 0
+ enabledImis.forEach { imi ->
+ val subtypes = richImm.getEnabledInputMethodSubtypeList(imi, true)
+ if (subtypes.isEmpty()) {
+ enabledSubtypes.add(imi to null)
+ } else {
+ subtypes.forEach {
+ if (!it.isAuxiliary) {
+ enabledSubtypes.add(imi to it)
+ if (imi == thisImi && it == currentSubtype)
+ currentSubtypeIndex = enabledSubtypes.lastIndex
+ }
+ }
+ }
+ }
+
+ val items = mutableListOf()
+ for (imiAndSubtype in enabledSubtypes) {
+ val (imi, subtype) = imiAndSubtype
+
+ val title = SpannableString(subtype?.getDisplayName(latinIme, imi.packageName, imi.serviceInfo.applicationInfo)
+ ?.ifBlank { imi.loadLabel(pm) }
+ ?: imi.loadLabel(pm))
+ val subtitle = SpannableString(if (subtype == null) "" else "\n${imi.loadLabel(pm)}")
+ title.setSpan(
+ RelativeSizeSpan(0.9f), 0, title.length,
+ Spannable.SPAN_INCLUSIVE_INCLUSIVE
+ )
+ subtitle.setSpan(
+ RelativeSizeSpan(0.85f), 0, subtitle.length,
+ Spannable.SPAN_EXCLUSIVE_INCLUSIVE
+ )
+ items.add(SpannableStringBuilder().append(title).append(subtitle))
+ }
+
+ val dialog = AlertDialog.Builder(DialogUtils.getPlatformDialogThemeContext(latinIme))
+ .setTitle(R.string.select_input_method)
+ .setSingleChoiceItems(items.toTypedArray(), currentSubtypeIndex) { di, i ->
+ di.dismiss()
+ val (imi, subtype) = enabledSubtypes[i]
+ if (imi == thisImi)
+ latinIme.switchToSubtype(subtype)
+ else if (subtype != null)
+ latinIme.switchInputMethodAndSubtype(imi, subtype)
+ else
+ latinIme.switchInputMethod(imi.id)
+ }
+ .create()
+
+ val window = dialog.window
+ val layoutParams = window?.attributes
+ layoutParams?.token = windowToken
+ layoutParams?.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG
+ window?.attributes = layoutParams
+ window?.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
+ dialog.show()
+}
diff --git a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/SubtypeLocaleUtils.java b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/SubtypeLocaleUtils.java
index 4a5f1064a..6ec380e7c 100644
--- a/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/app/src/main/java/org/dslul/openboard/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -313,14 +313,14 @@ public final class SubtypeLocaleUtils {
return LocaleUtils.constructLocaleFromString(localeString);
}
- @Nonnull
+ @Nullable
public static String getKeyboardLayoutSetDisplayName(
@Nonnull final InputMethodSubtype subtype) {
final String layoutName = getKeyboardLayoutSetName(subtype);
return getKeyboardLayoutSetDisplayName(layoutName);
}
- @Nonnull
+ @Nullable
public static String getKeyboardLayoutSetDisplayName(@Nonnull final String layoutName) {
return sKeyboardLayoutToDisplayNameMap.get(layoutName);
}
diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml
new file mode 100644
index 000000000..f98674568
--- /dev/null
+++ b/app/src/main/res/drawable/ic_delete.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_divider.xml b/app/src/main/res/drawable/ic_divider.xml
new file mode 100644
index 000000000..bc057ea79
--- /dev/null
+++ b/app/src/main/res/drawable/ic_divider.xml
@@ -0,0 +1,16 @@
+
+
+ -
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_plus.xml b/app/src/main/res/drawable/ic_plus.xml
new file mode 100644
index 000000000..491ef1785
--- /dev/null
+++ b/app/src/main/res/drawable/ic_plus.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/layout/language_list_item.xml b/app/src/main/res/layout/language_list_item.xml
new file mode 100644
index 000000000..7d9ba5eef
--- /dev/null
+++ b/app/src/main/res/layout/language_list_item.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/language_search_filter.xml b/app/src/main/res/layout/language_search_filter.xml
new file mode 100644
index 000000000..218ffba0f
--- /dev/null
+++ b/app/src/main/res/layout/language_search_filter.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/locale_settings_dialog.xml b/app/src/main/res/layout/locale_settings_dialog.xml
new file mode 100644
index 000000000..94a0dba1d
--- /dev/null
+++ b/app/src/main/res/layout/locale_settings_dialog.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-af/strings.xml b/app/src/main/res/values-af/strings.xml
index 8e006382c..0c7559cbf 100644
--- a/app/src/main/res/values-af/strings.xml
+++ b/app/src/main/res/values-af/strings.xml
@@ -25,7 +25,7 @@
"Opspring met sleuteldruk"
"Voorkeure"
"Rekeninge en privaatheid"
- "Voorkoms en uitlegte"
+ "Voorkoms en uitlegte"
"Gebaarinvoer"
"Tekskorrigering"
"Gevorderd"
@@ -231,4 +231,6 @@
Voorkoms sal sisteem verstellings naboots
Diep swart agtergronde
Kan kragverbruik verminder, afhangende van die toestel se skermtegnologie
+ "Gebruik stelseltale"
+ "Verander sleutelbord"
\ No newline at end of file
diff --git a/app/src/main/res/values-am/strings.xml b/app/src/main/res/values-am/strings.xml
index 6cbf89101..caa9594c5 100644
--- a/app/src/main/res/values-am/strings.xml
+++ b/app/src/main/res/values-am/strings.xml
@@ -28,7 +28,7 @@
"ቁልፍ ጫን ላይ ብቅ ባይ"
"ምርጫዎች"
"መለያዎች እና ግላዊነት"
- "መልክ እና አቀማመጦች"
+ "መልክ እና አቀማመጦች"
"በጣት ምልክት መተየብ"
"ፅሁፍ ማስተካከያ"
"የላቀ"
@@ -190,4 +190,6 @@
"ተጨማሪ ቋንቋዎች…"
"ሰርዝ"
" ሀለሐመሠረሰሸቀበቨተቸኀነኘአከኸወዐዘዠየደጀገጠጨጰጸፀፈፐ"
+ "የሥርዓት ቋንቋዎችን ይጠቀሙ"
+ "ቁልፍ ሰሌዳ ይቀይሩ"
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 50b8a2040..d0f6f7f9d 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -25,7 +25,7 @@
نافذة منبثقة عند الضغط على المفاتيح
"الإعدادات المفضّلة"
"الحسابات والخصوصية"
- "المظهر والتنسيقات"
+ "المظهر والتنسيقات"
"الكتابة بالإشارة"
"تصحيح النص"
"الإعدادات المتقدمة"
@@ -218,4 +218,6 @@
سمة العائلة
متغير السمة
الحدود الرئيسية
+ "استخدام لغات النظام"
+ "تغيير لوحة المفاتيح"
\ No newline at end of file
diff --git a/app/src/main/res/values-as/strings.xml b/app/src/main/res/values-as/strings.xml
new file mode 100644
index 000000000..6fa62f225
--- /dev/null
+++ b/app/src/main/res/values-as/strings.xml
@@ -0,0 +1,5 @@
+
+
+ "ছিষ্টেমৰ ভাষা ব্যৱহাৰ কৰক"
+ "কীব\'ৰ্ড সলনি কৰক"
+
diff --git a/app/src/main/res/values-ast-rES/strings.xml b/app/src/main/res/values-ast-rES/strings.xml
new file mode 100644
index 000000000..6d73c3274
--- /dev/null
+++ b/app/src/main/res/values-ast-rES/strings.xml
@@ -0,0 +1,5 @@
+
+
+ Usar les llingües del sistema
+ Cambéu de tecláu
+
diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml
index acb3e3f97..c3dfb4420 100644
--- a/app/src/main/res/values-az/strings.xml
+++ b/app/src/main/res/values-az/strings.xml
@@ -28,7 +28,7 @@
"Klikləmədə popup"
"Seçimlər"
"Hesablar & Məxfilik"
- "Görünüş & Düzümlər"
+ "Görünüş & Düzümlər"
"Jest ilə yazma"
"Mətn korreksiyası"
"Qabaqcıl"
@@ -190,4 +190,7 @@
"Digər dillər..."
"Silin"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Sistem dillərini istifadə edin"
+ "Klaviaturanı dəyişin"
+ "Görünüş"
diff --git a/app/src/main/res/values-b+sr+Latn/strings.xml b/app/src/main/res/values-b+sr+Latn/strings.xml
index 6bbafb6df..7e1f4b5d4 100644
--- a/app/src/main/res/values-b+sr+Latn/strings.xml
+++ b/app/src/main/res/values-b+sr+Latn/strings.xml
@@ -28,7 +28,7 @@
"Iskačući prozor prilikom pritiska tastera"
"Podešavanja"
"Nalozi i privatnost"
- "Izgled i rasporedi"
+ "Izgled i rasporedi"
"Kucanje pokretima"
"Ispravljanje teksta"
"Napredno"
@@ -190,4 +190,6 @@
"Još jezika..."
"Izbriši"
" ABVGDĐEŽZIJKLLJMNNJOPRSTĆUFHCČDŽŠ"
+ "Koristi jezike sistema"
+ "Promenite tastaturu"
diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml
index 79f763c39..35a773da2 100644
--- a/app/src/main/res/values-be/strings.xml
+++ b/app/src/main/res/values-be/strings.xml
@@ -28,7 +28,7 @@
"Па націску на клавішы ўсплывае акно"
"Параметры"
"Улік. запісы і прыватнасць"
- "Знешні выгляд і раскладкі"
+ "Знешні выгляд і раскладкі"
"Жэставы набор"
"Выпраўленне тэксту"
"Дадатковыя"
@@ -209,4 +209,6 @@
Паглядзець на GitHub
Ліцэнзія з адкрытым зыходным кодам
GNU General Public License v3.0
+ "Выкарыстоўваць мовы сістэмы"
+ "Змяніць клавіятуру"
diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml
index 40bbacc91..c0d2f7b86 100644
--- a/app/src/main/res/values-bg/strings.xml
+++ b/app/src/main/res/values-bg/strings.xml
@@ -28,7 +28,7 @@
"Изск. прозорец при натискане на клавиш"
"Предпочитания"
"Профили и поверителност"
- "Облик и оформления"
+ "Облик и оформления"
"Въвеждане чрез жест"
"Коригиране на текст"
"Разширени"
@@ -190,4 +190,6 @@
"Още езици…"
"Изтриване"
" АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЮЯ"
+ "Използване на системните езици"
+ "Промяна на клавиатурата"
diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml
index cedfceea8..92d64c816 100644
--- a/app/src/main/res/values-bn/strings.xml
+++ b/app/src/main/res/values-bn/strings.xml
@@ -29,7 +29,7 @@
কিপ্রেস পপআপ
পছন্দসমূহ
অ্যাকাউন্ট ও গোপনীয়তা
- অবয়ব ও লেআউট
+ অবয়ব ও লেআউট
অঙ্গুলিহেলন টাইপিং
পাঠ্য সংশোধন
উন্নত
@@ -285,4 +285,7 @@
ওপেন-সোর্স লাইসেন্স
জিএনইউ জেনারেল পাবলিক লাইসেন্স তৃতীয় সংস্করণ
বোতামের বিভাজন সংকীর্ণকরণ
+ "সিস্টেমের ভাষাগুলি ব্যবহার করুন"
+ "কীবোর্ড পরিবর্তন করুন"
+ "উপস্থিতি"
diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml
index 345aeccf3..dd192f1d2 100644
--- a/app/src/main/res/values-bs/strings.xml
+++ b/app/src/main/res/values-bs/strings.xml
@@ -28,7 +28,7 @@
"Iskačuči prozor pri pritisku na tipku"
"Postavke"
"Računi i privatnost"
- "Izgled i rasporedi tipki"
+ "Izgled i rasporedi tipki"
"Pisanje pokretima"
"Ispravka teksta"
"Napredno"
@@ -190,4 +190,6 @@
"Više jezika…"
"Izbriši"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Koristi jezik sistema"
+ "Promijeni tastaturu"
diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml
index 99efa68e9..aa78f4931 100644
--- a/app/src/main/res/values-ca/strings.xml
+++ b/app/src/main/res/values-ca/strings.xml
@@ -25,7 +25,7 @@
"Amplia en prémer tecles"
"Preferències"
"Comptes i privadesa"
- "Aparença i disposició"
+ "Aparença i disposició"
"Escriptura gestual"
"Correcció de textos"
"Avançada"
@@ -231,4 +231,6 @@
Activa la redimensió del teclat
L\'aspecte seguirà la configuració del sistema.
Alfabètic (Colemak Mod-DH)
+ "Utilitza els idiomes del sistema"
+ "Canvia el teclat"
\ No newline at end of file
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index 4dccfd202..61b636f33 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -28,7 +28,7 @@
"Detail znaku při stisku klávesy"
"Předvolby"
"Účty a ochrana soukromí"
- "Vzhled a rozvržení"
+ "Vzhled a rozvržení"
"Psaní gesty"
"Oprava textu"
"Rozšířená nastavení"
@@ -190,4 +190,6 @@
"Další jazyky…"
"Smazat"
" ABCČDEFGHChIJKLMNOPQRŘSŠTUVWXYZŽ"
+ "Použít systémové jazyky"
+ "Změna klávesnice"
diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml
new file mode 100644
index 000000000..bd1e72e03
--- /dev/null
+++ b/app/src/main/res/values-cy/strings.xml
@@ -0,0 +1,5 @@
+
+
+ Defnyddio ieithoedd y system
+ Newid bysellfwrdd
+
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index 5f0489c2a..79b534136 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -25,7 +25,7 @@
"Pop op ved tastetryk"
"Præferencer"
"Konti og privatliv"
- "Udseende og layouts"
+ "Udseende og layouts"
"Glidende indtastning"
"Tekstkorrigering"
"Avanceret"
@@ -231,4 +231,6 @@
Deaktiver indlæring af nye ord
Flere taster
Vis tips med lange tryk
+ "Brug systemsprogene"
+ "Skift tastatur"
\ No newline at end of file
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index ba8ba74d5..c57b46ae4 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -28,7 +28,7 @@
"Bei Tastendruck Pop-up"
"Einstellungen"
"Konten & Datenschutz"
- "Darstellung & Layouts"
+ "Darstellung & Layouts"
"Bewegungseingabe"
"Textkorrektur"
"Erweitert"
@@ -190,4 +190,6 @@
"Weitere Sprachen..."
"Löschen"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Systemsprache verwenden"
+ "Tastatur ändern"
diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml
index 61a570f03..e1d50b782 100644
--- a/app/src/main/res/values-el/strings.xml
+++ b/app/src/main/res/values-el/strings.xml
@@ -25,7 +25,7 @@
"Εμφάνιση με το πάτημα πλήκτρου"
"Προτιμήσεις"
"Λογαριασμοί και απόρρητο"
- "Εμφάνιση και διάταξη"
+ "Εμφάνιση και διάταξη"
"Πληκτρολόγηση με κίνηση"
"Διόρθωση κειμένου"
"Σύνθετες"
@@ -231,4 +231,6 @@
Εμφάνιση υποδείξεων με παρατεταμένο πάτημα
Πλήκτρο προχείρου
Θέμα οικογένεια
+ "Χρήση γλωσσών συστήματος"
+ "Αλλαγή πληκτρολογίου"
\ No newline at end of file
diff --git a/app/src/main/res/values-en-rAU/strings.xml b/app/src/main/res/values-en-rAU/strings.xml
index 27a403f2c..72e25f0d9 100644
--- a/app/src/main/res/values-en-rAU/strings.xml
+++ b/app/src/main/res/values-en-rAU/strings.xml
@@ -28,7 +28,7 @@
"Pop-up on key press"
"Preferences"
"Accounts & Privacy"
- "Appearance & Layouts"
+ "Appearance & Layouts"
"Gesture Typing"
"Text correction"
"Advanced"
@@ -190,4 +190,6 @@
"More languages…"
"Delete"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Use system languages"
+ "Change keyboard"
diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml
index 27a403f2c..72e25f0d9 100644
--- a/app/src/main/res/values-en-rCA/strings.xml
+++ b/app/src/main/res/values-en-rCA/strings.xml
@@ -28,7 +28,7 @@
"Pop-up on key press"
"Preferences"
"Accounts & Privacy"
- "Appearance & Layouts"
+ "Appearance & Layouts"
"Gesture Typing"
"Text correction"
"Advanced"
@@ -190,4 +190,6 @@
"More languages…"
"Delete"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Use system languages"
+ "Change keyboard"
diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml
index efaddb152..481fe2747 100644
--- a/app/src/main/res/values-en-rGB/strings.xml
+++ b/app/src/main/res/values-en-rGB/strings.xml
@@ -25,7 +25,7 @@
"Pop-up on key press"
"Preferences"
"Accounts & Privacy"
- "Appearance & Layouts"
+ "Appearance & Layouts"
"Gesture Typing"
"Text correction"
"Advanced"
@@ -231,4 +231,7 @@
%s (Akkhor)
Autospace after punctuation
Automatically insert space after punctuation when typing a new word
+ "Use system languages"
+ "Change keyboard"
+ "Appearance"
\ No newline at end of file
diff --git a/app/src/main/res/values-en-rIN/strings.xml b/app/src/main/res/values-en-rIN/strings.xml
index 27a403f2c..28895d025 100644
--- a/app/src/main/res/values-en-rIN/strings.xml
+++ b/app/src/main/res/values-en-rIN/strings.xml
@@ -28,7 +28,7 @@
"Pop-up on key press"
"Preferences"
"Accounts & Privacy"
- "Appearance & Layouts"
+ "Appearance & Layouts"
"Gesture Typing"
"Text correction"
"Advanced"
@@ -190,4 +190,7 @@
"More languages…"
"Delete"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Use system languages"
+ "Change keyboard"
+ "Appearance"
diff --git a/app/src/main/res/values-en-rXC/strings.xml b/app/src/main/res/values-en-rXC/strings.xml
index 45f80431a..3a09aceb6 100644
--- a/app/src/main/res/values-en-rXC/strings.xml
+++ b/app/src/main/res/values-en-rXC/strings.xml
@@ -28,7 +28,7 @@
"Popup on keypress"
"Preferences"
"Accounts & Privacy"
- "Appearance & Layouts"
+ "Appearance & Layouts"
"Gesture Typing"
"Text correction"
"Advanced"
@@ -190,4 +190,6 @@
"More languages…"
"Delete"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Use system languages"
+ "Change keyboard"
diff --git a/app/src/main/res/values-es-rUS/strings.xml b/app/src/main/res/values-es-rUS/strings.xml
index 25fd5166b..9f363f74d 100644
--- a/app/src/main/res/values-es-rUS/strings.xml
+++ b/app/src/main/res/values-es-rUS/strings.xml
@@ -25,7 +25,7 @@
"Ampliar al presionar teclas"
"Preferencias"
"Cuentas y privacidad"
- "Apariencia y diseños"
+ "Apariencia y diseños"
"Escritura gestual"
"Corrección ortográfica"
"Avanzada"
@@ -228,4 +228,6 @@
Entrada
Teclas adicionales
Correcciones
+ "Usar idiomas del sistema"
+ "Cambiar el teclado"
\ No newline at end of file
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index c4cce5112..80f7d125e 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -25,7 +25,7 @@
"Ampliar al pulsar tecla"
"Preferencias"
"Cuentas y privacidad"
- "Aspecto y diseño"
+ "Aspecto y diseño"
"Escritura gestual"
Corrección de texto
"Ajustes avanzados"
@@ -231,4 +231,6 @@
Si está deshabilitada, la tecla del portapapeles pegará el contenido del portapapeles, si lo hay
Espacio automático después del punto
Insertar un espacio automático después del punto cuando se escriba una nueva palabra
+ "Usar idiomas del sistema"
+ "Cambiar teclado"
\ No newline at end of file
diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml
index 5ba1f1637..570b20b8b 100644
--- a/app/src/main/res/values-et/strings.xml
+++ b/app/src/main/res/values-et/strings.xml
@@ -28,7 +28,7 @@
"Klahvivajutusel kuva hüpik"
"Eelistused"
"Kontod ja privaatsus"
- "Välimus ja paigutused"
+ "Välimus ja paigutused"
"Joonistusega sisestamine"
"Teksti korrigeerimine"
"Täpsemad"
@@ -190,4 +190,6 @@
"Rohkem keeli ..."
"Kustuta"
" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"
+ "Kasuta süsteemi keeli"
+ "Klaviatuuri muutmine"
diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml
index 8708d3b78..7a528b982 100644
--- a/app/src/main/res/values-eu/strings.xml
+++ b/app/src/main/res/values-eu/strings.xml
@@ -25,7 +25,7 @@
"Handitu teklak, sakatzean"
"Hobespenak"
"Kontuak eta pribatutasuna"
- "Itxura eta diseinuak"
+ "Itxura eta diseinuak"
"Idazketa lerrakorra"
"Testu-zuzenketa"
"Ezarpen aurreratuak"
@@ -231,4 +231,6 @@
Gaien familia
Alfabeto (Colemak Mod-DH)
Alfabeto (Workman)
+ "Erabili sistemaren hizkuntzak"
+ "Aldatu teklatua"
\ No newline at end of file
diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml
index b0bf4dfb2..6f9b8313b 100644
--- a/app/src/main/res/values-fa/strings.xml
+++ b/app/src/main/res/values-fa/strings.xml
@@ -28,7 +28,7 @@
"بازشدن با فشار کلید"
"تنظیمات برگزیده"
"حسابها و حریم خصوصی"
- "شکل ظاهری و چیدمان"
+ "شکل ظاهری و چیدمان"
"ورودی اشارهای"
"اصلاح نوشتار"
"پیشرفته"
@@ -190,4 +190,6 @@
"زبانهای بیشتر…"
"حذف"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "استفاده از زبانهای سیستم"
+ "تغییر صفحهکلید"
diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml
index 81cd0e5e3..e3de01cb3 100644
--- a/app/src/main/res/values-fi/strings.xml
+++ b/app/src/main/res/values-fi/strings.xml
@@ -28,7 +28,7 @@
"Ponnahdusikkuna painalluksella"
"Asetukset"
"Tilit ja tietosuoja"
- "Ulkoasu ja asettelut"
+ "Ulkoasu ja asettelut"
"Piirtokirjoitus"
"Tekstin korjaus"
"Lisäasetukset"
@@ -190,4 +190,7 @@
"Lisää kieliä…"
"Poista"
" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"
+ "Käytä järjestelmän kieliä"
+ "Vaihda näppäimistö"
+ "Ulkonäkö"
diff --git a/app/src/main/res/values-fr-rCA/strings.xml b/app/src/main/res/values-fr-rCA/strings.xml
index cc942794d..c4a893caa 100644
--- a/app/src/main/res/values-fr-rCA/strings.xml
+++ b/app/src/main/res/values-fr-rCA/strings.xml
@@ -28,7 +28,7 @@
"Agrandir les caractères"
"Préférences"
"Comptes et confidentialité"
- "Apparence et dispositions"
+ "Apparence et dispositions"
"Entrée gestuelle"
"Correction du texte"
"Avancés"
@@ -190,4 +190,6 @@
"Plus de langues…"
"Supprimer"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Utiliser les langues du système"
+ "Changer de clavier"
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 48135b85b..c20514a48 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -25,7 +25,7 @@
"Agrandir les caractères"
"Préférences"
"Comptes et confidentialité"
- "Apparence et dispositions"
+ "Apparence et dispositions"
"Saisie gestuelle"
"Correction du texte"
"Paramètres avancés"
@@ -231,4 +231,6 @@
%s (Akkhor)
Espace auto après la ponctuation
Insertion automatique d\'un espace après la ponctuation lors de la saisie d\'un nouveau mot
+ "Utiliser les langues du système"
+ "Changer de clavier"
\ No newline at end of file
diff --git a/app/src/main/res/values-gd/strings.xml b/app/src/main/res/values-gd/strings.xml
new file mode 100644
index 000000000..c85c1ee24
--- /dev/null
+++ b/app/src/main/res/values-gd/strings.xml
@@ -0,0 +1,5 @@
+
+
+ Cleachd cànain an t-siostaim
+ Atharraich am meur-chlàr
+
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 2759fb441..e81b51f7a 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -28,7 +28,7 @@
"Ventás emerxentes ao premer as teclas"
"Preferencias"
"Contas e privacidade"
- "Aparencia e deseños"
+ "Aparencia e deseños"
"Escritura por xestos"
"Corrección ortográfica"
"Configuración avanzada"
@@ -190,4 +190,6 @@
"Máis idiomas..."
"Eliminar"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Usar idiomas do sistema"
+ "Cambiar teclado"
diff --git a/app/src/main/res/values-gu/strings.xml b/app/src/main/res/values-gu/strings.xml
index 1f9445072..aef24d70a 100644
--- a/app/src/main/res/values-gu/strings.xml
+++ b/app/src/main/res/values-gu/strings.xml
@@ -28,7 +28,7 @@
"કીપ્રેસ પર પોપઅપ"
"પસંદગી"
"એકાઉન્ટ્સ અને ગોપનીયતા"
- "દેખાવ અને લેઆઉટ્સ"
+ "દેખાવ અને લેઆઉટ્સ"
"સાંકેતિક ટાઇપિંગ"
"ટેક્સ્ટ સુધારણા"
"વિગતવાર"
@@ -190,4 +190,6 @@
"વધુ ભાષાઓ…"
"કાઢી નાખો"
" [અ આ ઇ ઈ ઉ ઊ ઋ એ ઐ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ વ શ ષ સ હ ળ]"
+ "સિસ્ટમ ભાષાઓનો ઉપયોગ કરો"
+ "કીબોર્ડ બદલો"
diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml
index c3e349638..a3c2276eb 100644
--- a/app/src/main/res/values-hi/strings.xml
+++ b/app/src/main/res/values-hi/strings.xml
@@ -28,7 +28,7 @@
"बटन दबाने पर पॉपअप दिखाएं"
"प्राथमिकताएं"
"खाते और निजता"
- "दिखावट और सज्जा"
+ "दिखावट और सज्जा"
"संकेतोें द्वारा टाइपिंग"
"लेख सुधार"
"बेहतर सेटिंग"
@@ -190,4 +190,6 @@
"ज़्यादा भाषाएं…"
"मिटाएं"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "सिस्टम की भाषाओं का उपयोग करें"
+ "कीबोर्ड बदलें"
diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml
index 7db82e17c..4f9ed162c 100644
--- a/app/src/main/res/values-hr/strings.xml
+++ b/app/src/main/res/values-hr/strings.xml
@@ -25,7 +25,7 @@
Povećana tipka pri pritisku tipke
Osobitosti
"Računi i privatnost"
- "Izgled i rasporedi"
+ "Izgled i rasporedi"
Tipkanje gestama
"Ispravljanje teksta"
Napredno
@@ -231,4 +231,6 @@
Tamnocrne pozadine
Tipka međuspremnika
Broj retka
+ "Upotrijebi jezike sustava"
+ "Promjena tipkovnice"
\ No newline at end of file
diff --git a/app/src/main/res/values-hu-rZZ/strings.xml b/app/src/main/res/values-hu-rZZ/strings.xml
index b9a8ae216..4c242ab67 100644
--- a/app/src/main/res/values-hu-rZZ/strings.xml
+++ b/app/src/main/res/values-hu-rZZ/strings.xml
@@ -28,7 +28,7 @@
"Nagyobb billentyű gombnyomásra"
"Beállítások"
"Fiókok és adatvédelem"
- "Megjelenés és elrendezés"
+ "Megjelenés és elrendezés"
"Kézmozdulatokkal történő gépelés"
"Szövegjavítás"
"Speciális"
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index 4006d8781..2eae671e4 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -25,7 +25,7 @@
"Nagyobb billentyű gombnyomásra"
"Beállítások"
"Fiókok és adatvédelem"
- "Megjelenés és elrendezés"
+ "Megjelenés és elrendezés"
"Kézmozdulatokkal történő gépelés"
"Szövegjavítás"
"Speciális"
@@ -193,4 +193,6 @@
Ábécé (Colemak Mod-DH)
Ábécé (Workman)
A kinézet követi a rendszerbeállítást
+ "Rendszernyelvek használata"
+ "Billentyűzet megváltoztatása"
\ No newline at end of file
diff --git a/app/src/main/res/values-hy/strings.xml b/app/src/main/res/values-hy/strings.xml
index 03d7014ec..a45b06668 100644
--- a/app/src/main/res/values-hy/strings.xml
+++ b/app/src/main/res/values-hy/strings.xml
@@ -28,7 +28,7 @@
"Ելնող պատուհան՝ ստեղնի հպման դեպքում"
"Նախընտրանքներ"
"Հաշիվներ և գաղտնիություն"
- "Արտաքին տեսք և դասավորություն"
+ "Արտաքին տեսք և դասավորություն"
"Ժեստերով մուտքագրում"
"Տեքստի ուղղում"
"Հավելյալ"
@@ -190,4 +190,7 @@
"Ավելի շատ լեզուներով..."
"Ջնջել"
" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"
+ "Օգտագործել համակարգի լեզուները"
+ "Փոխել ստեղնաշարը"
+ "Արտաքին տեսք"
diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml
index 2c1d72cf8..fa92314b8 100644
--- a/app/src/main/res/values-in/strings.xml
+++ b/app/src/main/res/values-in/strings.xml
@@ -25,7 +25,7 @@
"Muncul saat tombol ditekan"
"Preferensi"
"Akun & Privasi"
- "Tampilan & Tata Letak"
+ "Tampilan & Tata Letak"
"Ketikan Gestur"
"Koreksi teks"
"Lanjutan"
@@ -231,4 +231,6 @@
%s (Akkhor)
Spasi otomatis setelah tanda baca
Otomatis sisipkan spasi setelah tanda baca saat mengetik kata baru
+ "Gunakan bahasa sistem"
+ "Ubah keyboard"
\ No newline at end of file
diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml
index e3a361503..be91c489c 100644
--- a/app/src/main/res/values-is/strings.xml
+++ b/app/src/main/res/values-is/strings.xml
@@ -28,7 +28,7 @@
"Stækkaðir stafir við innslátt"
"Kjörstillingar"
"Reikningar og persónuvernd"
- "Útlit og uppsetning"
+ "Útlit og uppsetning"
"Bendingainnsláttur"
"Textaleiðrétting"
"Ítarlegt"
@@ -190,4 +190,7 @@
"Fleiri tungumál…"
"Eyða"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Nota kerfistungumál"
+ "Skipta um lyklaborð"
+ "Útlit"
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 7abc83198..7e357a1cc 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -25,7 +25,7 @@
"Popup tasti"
"Preferenze"
"Account e privacy"
- "Aspetto e layout"
+ "Aspetto e layout"
"Digitazione gestuale"
"Correzione testo"
"Avanzate"
@@ -231,4 +231,6 @@
Variante tema
Bordi tasto
Modalità giorno/notte automatica
+ "Utilizza le lingue di sistema"
+ "Cambia tastiera"
\ No newline at end of file
diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml
index 6c444c11a..151de6dda 100644
--- a/app/src/main/res/values-iw/strings.xml
+++ b/app/src/main/res/values-iw/strings.xml
@@ -25,7 +25,7 @@
"חלון קופץ בלחיצה על מקש"
"העדפות"
"חשבונות ופרטיות"
- "מראה ופריסות"
+ "מראה ופריסות"
"הקלדה רציפה"
"תיקון טקסט"
"אפשרויות מתקדמות"
@@ -231,4 +231,7 @@
השבת למידה של מילים חדשות
עוד מפתחות
רקע שחור עמוק
+ "שימוש בשפות מערכת"
+ "שינוי מקלדת"
+ "מראה"
\ No newline at end of file
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 10c9b0acb..d929453ad 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -28,7 +28,7 @@
"キー押下時ポップアップ"
"設定"
"アカウントとプライバシー"
- "外観とレイアウト"
+ "外観とレイアウト"
"ジェスチャー入力"
"テキストの修正"
"詳細設定"
@@ -190,4 +190,6 @@
"その他の言語…"
"削除"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "システム言語を使用"
+ "キーボードの変更"
diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml
index e97999236..a4fae9dee 100644
--- a/app/src/main/res/values-ka/strings.xml
+++ b/app/src/main/res/values-ka/strings.xml
@@ -28,7 +28,7 @@
"გადიდება ღილაკზე დაჭერისას"
"პარამეტრები"
"ანგარიშები & კონფიდენციალურობა"
- "იერსახე & განლაგებები"
+ "იერსახე & განლაგებები"
"ჟესტებით წერა"
"ტექსტის კორექცია"
"გაფართოებული"
@@ -190,4 +190,7 @@
"სხვა ენები…"
"წაშლა"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "სისტემის ენების გამოყენება"
+ "კლავიატურის შეცვლა"
+ "იერსახე"
diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml
index 1520ec748..79e625b87 100644
--- a/app/src/main/res/values-kk/strings.xml
+++ b/app/src/main/res/values-kk/strings.xml
@@ -28,7 +28,7 @@
"Басылған пернені үлкейтіп көрсету"
"Қалауларыңыз"
"Есептік жазбалар және құпиялылық"
- "Сыртқы түр және орналасулар"
+ "Сыртқы түр және орналасулар"
"Қимыл арқылы теру"
"Мәтінді түзету"
"Қосымша"
@@ -190,4 +190,6 @@
"Қосымша тілдер…"
"Жою"
" АӘБВГҒДЕЁЖЗИЙКҚЛМНҢОӨПРСТУҰҮФХҺЦЧШЩЪЫІЬЭЮЯ"
+ "Жүйелік тілдерді пайдалану"
+ "Пернетақтаны өзгерту"
diff --git a/app/src/main/res/values-km/strings.xml b/app/src/main/res/values-km/strings.xml
index 178482b94..680a0e717 100644
--- a/app/src/main/res/values-km/strings.xml
+++ b/app/src/main/res/values-km/strings.xml
@@ -28,7 +28,7 @@
"លេចឡើងនៅពេលចុចគ្រាប់ចុច"
"ចំណូលចិត្ត"
"គណនី & ភាពឯកជន"
- "រូបរាង & ប្លង់"
+ "រូបរាង & ប្លង់"
"កាយវិការបញ្ចូល"
"ការកែអត្ថបទ"
"កម្រិតខ្ពស់"
@@ -190,4 +190,7 @@
"ភាសាច្រើនទៀត…"
"លុប"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ប្រើភាសាប្រព័ន្ធ"
+ "ប្ដូរក្ដារចុច"
+ "រូបរាង"
diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml
index 6be4f28fb..eb52edb33 100644
--- a/app/src/main/res/values-kn/strings.xml
+++ b/app/src/main/res/values-kn/strings.xml
@@ -28,7 +28,7 @@
"ಕೀಪ್ರೆಸ್ನಲ್ಲಿ ಪಾಪ್ಅಪ್"
"ಪ್ರಾಶಸ್ತ್ಯಗಳು"
"ಖಾತೆಗಳು ಮತ್ತು ಗೌಪ್ಯತೆ"
- "ಗೋಚರತೆ ಮತ್ತು ಲೇಔಟ್ಗಳು"
+ "ಗೋಚರತೆ ಮತ್ತು ಲೇಔಟ್ಗಳು"
"ಗೆಸ್ಚರ್ ಟೈಪಿಂಗ್"
"ಪಠ್ಯ ತಿದ್ದುಪಡಿ"
"ಸುಧಾರಿತ"
@@ -190,4 +190,6 @@
"ಇನ್ನಷ್ಟು ಭಾಷೆಗಳು…"
"ಅಳಿಸಿ"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ಸಿಸ್ಟಂ ಭಾಷೆಗಳನ್ನು ಬಳಸಿ"
+ "ಕೀಬೋರ್ಡ್ ಬದಲಿಸಿ"
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 4faf943a8..30df39ff4 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -28,7 +28,7 @@
"키를 누를 때 팝업"
"환경설정"
"계정 및 개인정보 보호"
- "모양 및 레이아웃"
+ "모양 및 레이아웃"
"제스처 타이핑"
"텍스트 수정"
"고급"
@@ -190,4 +190,6 @@
"더보기…"
"삭제"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "시스템 언어 사용"
+ "키보드 변경"
diff --git a/app/src/main/res/values-ky/strings.xml b/app/src/main/res/values-ky/strings.xml
index 412cf2fd6..b087aec68 100644
--- a/app/src/main/res/values-ky/strings.xml
+++ b/app/src/main/res/values-ky/strings.xml
@@ -28,7 +28,7 @@
"Баскыч басылганда калкып чыкма"
"Мүмкүнчүлүктөрдү тандоо"
"Аккаунттар"
- "Көрүнүш жана жайгашуулар"
+ "Көрүнүш жана жайгашуулар"
"Жаңсап терүү"
"Текстти оңдоо"
"Өркүндөтүлгөн"
@@ -190,4 +190,6 @@
"Дагы тилдер…"
"Жок кылуу"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Тутум тилдерин колдонуу"
+ "Баскычтопту өзгөртүү"
diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml
new file mode 100644
index 000000000..9901993af
--- /dev/null
+++ b/app/src/main/res/values-lb/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Tastatur wiesselen
+
diff --git a/app/src/main/res/values-lo/strings.xml b/app/src/main/res/values-lo/strings.xml
index 9d855b079..0747b013b 100644
--- a/app/src/main/res/values-lo/strings.xml
+++ b/app/src/main/res/values-lo/strings.xml
@@ -28,7 +28,7 @@
"ໂຕອັກສອນເວລາພິມ"
"ການຕັ້ງຄ່າ"
"ບັນຊີ ແລະ ຄວາມເປັນສ່ວນຕົວ"
- "ລັກສະນະ & ໂຄງຮ່າງ"
+ "ລັກສະນະ & ໂຄງຮ່າງ"
"ການພິມແບບລາກນິ້ວ"
"ການແປງຄຳໃຫ້ຖືກຕ້ອງ"
"ຂັ້ນສູງ"
@@ -190,4 +190,7 @@
"ພາສາອື່ນໆ..."
"ລຶບ"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ໃຊ້ພາສາຂອງລະບົບ"
+ "ປ່ຽນແປ້ນພິມ"
+ "ຮູບແບບໜ້າຕາ"
diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml
index 83595c626..f08e272c1 100644
--- a/app/src/main/res/values-lt/strings.xml
+++ b/app/src/main/res/values-lt/strings.xml
@@ -28,7 +28,7 @@
"Iššoka paspaudus klavišą"
"Nuostatos"
"Paskyros ir privatumas"
- "Išvaizda ir išdėstymai"
+ "Išvaizda ir išdėstymai"
"Įvestis gestais"
"Teksto taisymas"
"Išplėstiniai"
@@ -192,4 +192,6 @@
"Daugiau kalbų..."
"Ištrinti"
" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"
+ "Sistemos kalbų naudojimas"
+ "Klaviatūros keitimas"
diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml
index a4638d571..70a884465 100644
--- a/app/src/main/res/values-lv/strings.xml
+++ b/app/src/main/res/values-lv/strings.xml
@@ -28,7 +28,7 @@
"Parādās, nospiežot taustiņu"
"Preferences"
"Konti un konfidencialitāte"
- "Izskats un izkārtojumi"
+ "Izskats un izkārtojumi"
"Ievadīt ar žestiem"
"Teksta korekcija"
"Papildu"
@@ -190,4 +190,6 @@
"Citas valodas..."
"Dzēst"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Sistēmas valodu izmantošana"
+ "Tastatūras maiņa"
diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml
index 93735e253..7becfde74 100644
--- a/app/src/main/res/values-mk/strings.xml
+++ b/app/src/main/res/values-mk/strings.xml
@@ -28,7 +28,7 @@
"Појавен прозорец на притискање копче"
"Претпочитани поставки"
"Сметки и приватност"
- "Изглед и распоред"
+ "Изглед и распоред"
"Пишување со движење"
"Корекција на текст"
"Напредни"
@@ -190,4 +190,6 @@
"Повеќе јазици..."
"Избриши"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Користи ги системските јазици"
+ "Измени тастатура"
diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml
index 0a5147b08..d99552ef4 100644
--- a/app/src/main/res/values-ml/strings.xml
+++ b/app/src/main/res/values-ml/strings.xml
@@ -25,7 +25,7 @@
"കീ അമർത്തുമ്പോൾ പോപ്പപ്പ്"
"മുൻഗണനകൾ"
"അക്കൗണ്ടുകളും സമന്വയവും"
- "രൂപഭാവവും ലേഔട്ടുകളും"
+ "രൂപഭാവവും ലേഔട്ടുകളും"
"ഗെസ്ചർ ടൈപ്പിംഗ്"
"ടെക്സ്റ്റ് തിരുത്തൽ"
"വിപുലം"
@@ -231,4 +231,6 @@
ഇൻപുട്ട്
അധിക കീകൾ
തിരുത്തലുകൾ
+ "സിസ്റ്റം ഭാഷകൾ ഉപയോഗിക്കുക"
+ "കീബോഡ് മാറ്റുക"
\ No newline at end of file
diff --git a/app/src/main/res/values-mn/strings.xml b/app/src/main/res/values-mn/strings.xml
index ced475eec..8139041c0 100644
--- a/app/src/main/res/values-mn/strings.xml
+++ b/app/src/main/res/values-mn/strings.xml
@@ -28,7 +28,7 @@
"Товч дарахад попап гарна"
"Тохируулга"
"Хаяг & Нууцлал"
- "Харагдах байдал & Зураглал"
+ "Харагдах байдал & Зураглал"
"Зангаагаар бичих"
"Текст засварлах"
"Дэлгэрэнгүй"
@@ -190,4 +190,7 @@
"Өөр хэлүүд…"
"Устгах"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Системийн хэлүүдийг ашиглах"
+ "Гарыг өөрчлөх"
+ "Харагдац"
diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml
index d53a5ce6b..c3e6c67bd 100644
--- a/app/src/main/res/values-mr/strings.xml
+++ b/app/src/main/res/values-mr/strings.xml
@@ -28,7 +28,7 @@
"की दाबताना पॉपअप"
"प्राधान्ये"
"खाती आणि गोपनीयता"
- "स्वरूप आणि लेआउट"
+ "स्वरूप आणि लेआउट"
"जेश्चर टायपिंग"
"मजकूर दुरुस्ती"
"प्रगत"
@@ -190,4 +190,6 @@
"अधिक भाषा..."
"हटवा"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "सिस्टम भाषा वापरा"
+ "कीबोर्ड बदला"
diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml
index b2f8f6de5..47f167942 100644
--- a/app/src/main/res/values-ms/strings.xml
+++ b/app/src/main/res/values-ms/strings.xml
@@ -28,7 +28,7 @@
"Pop timbul pada tekanan kunci"
"Pilihan"
"Akaun & Privasi"
- "Penampilan & Bentangan"
+ "Penampilan & Bentangan"
"Taipan Gerak Isyarat"
"Pembetulan teks"
"Lanjutan"
@@ -190,4 +190,7 @@
"Lebih banyak bahasa..."
"Padam"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Gunakan bahasa sistem"
+ "Tukar papan kekunci"
+ "Tampilan"
diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml
index 09606644f..ce587ef1a 100644
--- a/app/src/main/res/values-my/strings.xml
+++ b/app/src/main/res/values-my/strings.xml
@@ -28,7 +28,7 @@
"ခလုတ်နှိပ်လိုက်သည်နှင့် ပေါ်လာရန်"
"ရွေးချယ်စရာများ"
"အကောင့်များ & ကိုယ်ပိုင်ကိစ္စ"
- "ပုံပန်းသွင်ပြင် & အပြင်အဆင်များ"
+ "ပုံပန်းသွင်ပြင် & အပြင်အဆင်များ"
"လှုပ်ရှားမှုဖြင့်စာရိုက်ခြင်း"
"စာအမှားပြပြင်ခြင်း"
"အဆင့်မြင့်"
@@ -190,4 +190,6 @@
"ဘာသာစကားပိုများများ…"
"ဖျက်ရန်"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "သတ်မှတ် ဘာသာစကားများကို သုံးပါ"
+ "ကီးဘုတ် ပြောင်းလဲရန်"
diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml
index 988e7422a..35a58cc4f 100644
--- a/app/src/main/res/values-nb/strings.xml
+++ b/app/src/main/res/values-nb/strings.xml
@@ -25,7 +25,7 @@
"Forgrunnsvindu ved tastetrykk"
"Innstillinger"
"Kontoer og personvern"
- "Utseende og utforming"
+ "Utseende og utforming"
Håndvendingsskriving
"Tekstkorrigering"
"Avansert"
@@ -222,4 +222,6 @@
Tastekanter
Draktfamilie
Svarte bakgrunner
+ "Bruk systemspråk"
+ "Endre tastatur"
\ No newline at end of file
diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml
index b7594507f..625f7935d 100644
--- a/app/src/main/res/values-ne/strings.xml
+++ b/app/src/main/res/values-ne/strings.xml
@@ -28,7 +28,7 @@
"कुञ्जी दबाउँदा पपअप"
"प्राथमिकताहरू"
"खाताहरू तथा गोपनीयता"
- "आवरण तथा लेआउटहरू"
+ "आवरण तथा लेआउटहरू"
"इशारा टाइपिङ"
"पाठ सुधार"
"उन्नत"
@@ -190,4 +190,7 @@
"थप भाषाहरू..."
"मेट्नुहोस्"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "प्रणालीका भाषाहरू प्रयोग गर्नुहोस्"
+ "कुञ्जीपाटी परिवर्तन गर्नुहोस्"
+ "उपस्थिति"
diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
new file mode 100644
index 000000000..bc060496b
--- /dev/null
+++ b/app/src/main/res/values-night/colors.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ #FFF
+ #BBB
+ #666
+
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 5b5d6eb3e..afb1ef9f5 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -28,7 +28,7 @@
"Pop-up bij toetsaanslag"
"Voorkeuren"
"Accounts en privacy"
- "Uiterlijk en lay-out"
+ "Uiterlijk en lay-out"
"Invoer met bewegingen"
"Tekstcorrectie"
"Geavanceerd"
@@ -190,4 +190,6 @@
"Meer talen…"
"Verwijderen"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Systeemtalen gebruiken"
+ "Toetsenbord wijzigen"
diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml
new file mode 100644
index 000000000..1e15350bb
--- /dev/null
+++ b/app/src/main/res/values-or/strings.xml
@@ -0,0 +1,5 @@
+
+
+ "ସିଷ୍ଟମ୍ ଭାଷା ବ୍ୟବହାର କରନ୍ତୁ"
+ "କୀ’ବୋର୍ଡ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"
+
diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml
index bf60ed62c..09ea66ec0 100644
--- a/app/src/main/res/values-pa/strings.xml
+++ b/app/src/main/res/values-pa/strings.xml
@@ -28,7 +28,7 @@
"ਕੁੰਜੀ ਦਬਾਉਣ ’ਤੇ ਪੌਪਅੱਪ ਕਰੋ"
"ਤਰਜੀਹਾਂ"
"ਖਾਤੇ & ਪ੍ਰਾਈਵੇਸੀ"
- "ਪ੍ਰਗਟਾਅ & ਲੇਆਉਟਸ"
+ "ਪ੍ਰਗਟਾਅ & ਲੇਆਉਟਸ"
"ਸੰਕੇਤ ਟਾਈਪਿੰਗ"
"ਟੈਕਸਟ ਸੁਧਾਈ"
"ਵਿਕਸਿਤ"
@@ -190,4 +190,6 @@
"ਹੋਰ ਭਾਸ਼ਾਵਾਂ…"
"ਮਿਟਾਓ"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ਸਿਸਟਮ ਭਾਸ਼ਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰੋ"
+ "ਕੀ-ਬੋਰਡ ਬਦਲੋ"
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index c4c4b2cd1..ce1a9a9fe 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -25,7 +25,7 @@
"Powiększ po naciśnięciu"
"Ustawienia"
"Konta i prywatność"
- "Wygląd i układy"
+ "Wygląd i układy"
"Pisanie gestami"
"Korekta tekstu"
"Zaawansowane"
@@ -231,4 +231,6 @@
Może zmniejszyć zużycie energii w zależności od technologii ekranu urządzenia
Automatyczne wstawianie spacji po znaku interpunkcyjnym podczas wpisywania nowego słowa
Automatyczne wstawianie spacji po znaku interpunkcyjnym
+ "Użyj języków systemu"
+ "Zmień klawiaturę"
\ No newline at end of file
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index ff0c7d983..a65273cc0 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -5,7 +5,7 @@
Vibrar ao tocar nas teclas
Som ao tocar nas teclas
O corretor ortográfico usa entradas da sua lista de contatos
- Aparência e Layouts
+ Aparência e Layouts
Escrita por Gestos
Correção de Texto
Avançado
@@ -214,4 +214,6 @@
Toque novamente para salvar
Espaço automático após pontuação
Inserir automaticamente espaço após pontuação ao digitar uma nova palavra
+ "Usar idiomas do sistema"
+ "Alterar teclado"
\ No newline at end of file
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index d38101a44..12973f876 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -25,7 +25,7 @@
Mostrar popup de teclas
"Preferências"
"Contas e privacidade"
- Aparência e esquemas
+ Aparência e esquemas
"Escrita com gestos"
"Correção de texto"
Avançado
@@ -222,4 +222,6 @@
Variante do tema
Limite das teclas
Definições de verificação ortográfica OpenBoard
+ "Utilizar idiomas do sistema"
+ "Alterar teclado"
\ No newline at end of file
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index 37f56de1b..6f69e3373 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -25,7 +25,7 @@
Mostrar popup de teclas
"Preferências"
"Contas e privacidade"
- Aparência e esquemas
+ Aparência e esquemas
"Escrita com gestos"
"Correção de texto"
"Avançado"
@@ -222,4 +222,7 @@
Modo diurno/noturno automático
Alterar método de introdução com a tecla Espaço
\'Trackpad\' na barra de espaço
+ "Usar idiomas do sistema"
+ "Alterar teclado"
+ "Aparência"
\ No newline at end of file
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 015b0b537..e4f26c070 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -28,7 +28,7 @@
"Pop-up la apăsarea tastei"
"Preferințe"
"Conturi și confidențialitate"
- "Aspect"
+ "Aspect"
"Tastare gestuală"
"Corectarea textului"
"Avansate"
@@ -190,4 +190,7 @@
"Mai multe limbi…"
"Ștergeți"
" AĂÂBCDEFGHIÎJKLMNOPQRSȘTȚUVWXYZ"
+ "Folosește limbile sistemului"
+ "Schimbați tastatura"
+ "Aspect"
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 735ba4c4a..09fa58526 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -25,7 +25,7 @@
"Увеличивать при нажатии"
"Настройки"
"Аккаунты"
- "Вид и раскладки"
+ "Вид и раскладки"
"Непрерывный ввод"
"Исправление текста"
"Дополнительные настройки"
@@ -250,4 +250,6 @@
Посмотреть на GitHub
Лицензия с открытым исходным кодом
GNU General Public License v3.0
+ "Языки системы"
+ "Выбор раскладки"
diff --git a/app/src/main/res/values-sc-rIT/strings.xml b/app/src/main/res/values-sc-rIT/strings.xml
new file mode 100644
index 000000000..b062a0d70
--- /dev/null
+++ b/app/src/main/res/values-sc-rIT/strings.xml
@@ -0,0 +1,4 @@
+
+
+ Càmbia su tecladu
+
diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml
index 48f9ef989..5f7961628 100644
--- a/app/src/main/res/values-si/strings.xml
+++ b/app/src/main/res/values-si/strings.xml
@@ -28,7 +28,7 @@
"යතුරු එබීම මත උත්පතනය"
"අභිරුචි"
"ගිණුම් සහ රහස්යතාව"
- "පෙනුම සහ පිරිසැලසුම්"
+ "පෙනුම සහ පිරිසැලසුම්"
"ඉංගිත ටයිප් කිරීම"
"පෙළ නිවැරදි කිරීම"
"උසස්"
@@ -190,4 +190,7 @@
"තවත් භාෂා…"
"මකන්න"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "පද්ධති භාෂා භාවිත කරන්න"
+ "යතුරු පුවරු වෙනස් කිරීම"
+ "පෙනුම"
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index 06dc2c500..614cd039e 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -25,7 +25,7 @@
"Detail znaku pri stlačení"
"Predvoľby"
"Účty a ochrana osobných údajov"
- "Vzhľad a rozloženie"
+ "Vzhľad a rozloženie"
"Písanie gestami"
"Oprava textu"
"Rozšírené"
@@ -206,4 +206,6 @@
Návrhy
Experimentálne
Ostatné
+ "Použiť jazyky systému"
+ "Zmeniť klávesnicu"
\ No newline at end of file
diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml
index fc1408d34..6848e3fc3 100644
--- a/app/src/main/res/values-sl/strings.xml
+++ b/app/src/main/res/values-sl/strings.xml
@@ -28,7 +28,7 @@
"Povečaj črko ob pritisku"
"Nastavitve"
"Računi in zasebnost"
- "Videz in postavitve"
+ "Videz in postavitve"
"Pisanje s kretnjami"
"Popravki besedila"
"Dodatno"
@@ -190,4 +190,6 @@
"Več jezikov ..."
"Izbriši"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Uporaba sistemskih jezikov"
+ "Sprememba tipkovnice"
diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml
index b59417005..586c143fb 100644
--- a/app/src/main/res/values-sq/strings.xml
+++ b/app/src/main/res/values-sq/strings.xml
@@ -28,7 +28,7 @@
"Zmadhim germe kur shtyp"
"Preferencat"
"Llogaritë dhe privatësia"
- "Pamja dhe struktura"
+ "Pamja dhe struktura"
"Shkrimi me gjeste"
"Korrigjim teksti"
"I përparuar"
@@ -190,4 +190,6 @@
"Gjuhë të tjera…"
"Fshi"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Përdor gjuhët e sistemit"
+ "Ndërro tastierë"
diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml
index 86e076e5d..9089ceb1b 100644
--- a/app/src/main/res/values-sr/strings.xml
+++ b/app/src/main/res/values-sr/strings.xml
@@ -28,7 +28,7 @@
"Искачући прозор приликом притиска тастера"
"Подешавања"
"Налози и приватност"
- "Изглед и распореди"
+ "Изглед и распореди"
"Куцање покретима"
"Исправљање текста"
"Напредно"
@@ -190,4 +190,6 @@
"Још језика..."
"Избриши"
" АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ"
+ "Користи језике система"
+ "Промените тастатуру"
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index e73aeb806..c46b12349 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -25,7 +25,7 @@
"Popup vid tangenttryck"
Alternativ
Konton & integritet
- Utseende & layouter
+ Utseende & layouter
"Svepskrivning"
"Textkorrigering"
"Avancerat"
@@ -231,4 +231,6 @@
Utseendet kommer följa systeminställningarna
Kan minska strömförbrukningen beroende på enhetens skärmteknik
Helsvarta bakgrunder
+ "Använda systemspråk"
+ "Byt tangentbord"
\ No newline at end of file
diff --git a/app/src/main/res/values-sw/strings.xml b/app/src/main/res/values-sw/strings.xml
index 9eb443522..351cf1733 100644
--- a/app/src/main/res/values-sw/strings.xml
+++ b/app/src/main/res/values-sw/strings.xml
@@ -28,7 +28,7 @@
"Ibuka kitufe kinapobonyezwa"
"Mapendeleo"
"Akaunti na Faragha"
- "Mwonekano na Mipangilio"
+ "Mwonekano na Mipangilio"
"Kuandika kwa Ishara"
"Masahihisho ya maandishi"
"Mahiri"
@@ -190,4 +190,6 @@
"Lugha zingine..."
"Futa"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Tumia lugha za mfumo"
+ "Badilisha kibodi"
diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml
index df500536e..43b746930 100644
--- a/app/src/main/res/values-ta/strings.xml
+++ b/app/src/main/res/values-ta/strings.xml
@@ -28,7 +28,7 @@
"விழை அழுத்தத்தின்போது பாப்அப் செய்"
"விருப்பங்கள்"
"கணக்குகள் & தனியுரிமை"
- "தோற்றம் & தளவமைப்புகள்"
+ "தோற்றம் & தளவமைப்புகள்"
"ஸ்வைப் தட்டச்சு"
"உரை திருத்தம்"
"மேம்பட்டவை"
@@ -190,4 +190,6 @@
"மேலும் மொழிகள்..."
"நீக்கு"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "சாதன மொழிகளைப் பயன்படுத்து"
+ "விசைப்பலகையை மாற்று"
diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml
index a6877a638..4031287de 100644
--- a/app/src/main/res/values-te/strings.xml
+++ b/app/src/main/res/values-te/strings.xml
@@ -28,7 +28,7 @@
"కీని నొక్కినప్పుడు పాప్అప్ చూపు"
"ప్రాధాన్యతలు"
"ఖాతాలు & గోప్యత"
- "కనిపించే తీరు & లేఅవుట్లు"
+ "కనిపించే తీరు & లేఅవుట్లు"
"సంజ్ఞ టైపింగ్"
"వచన సవరణ"
"అధునాతనం"
@@ -190,4 +190,6 @@
"మరిన్ని భాషలు…"
"తొలగించు"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "సిస్టమ్ భాషలను ఉపయోగించు"
+ "కీబోర్డ్ను మార్చు"
diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml
index 07cc9010f..e51d3d024 100644
--- a/app/src/main/res/values-th/strings.xml
+++ b/app/src/main/res/values-th/strings.xml
@@ -28,7 +28,7 @@
"ป๊อปอัปเมื่อกดแป้น"
"ค่ากำหนด"
"บัญชีและความเป็นส่วนตัว"
- "ลักษณะที่ปรากฏและการจัดวาง"
+ "ลักษณะที่ปรากฏและการจัดวาง"
"การป้อนข้อมูลด้วยท่าทาง"
"การแก้ไขข้อความ"
"ขั้นสูง"
@@ -190,4 +190,6 @@
"ภาษาเพิ่มเติม…"
"ลบ"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ใช้ภาษาของระบบ"
+ "เปลี่ยนแป้นพิมพ์"
diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml
index 256668288..f8b523f43 100644
--- a/app/src/main/res/values-tl/strings.xml
+++ b/app/src/main/res/values-tl/strings.xml
@@ -28,7 +28,7 @@
"Mag-popup sa keypress"
"Mga Kagustuhan"
"Mga Account at Privacy"
- "Hitsura at Mga Layout"
+ "Hitsura at Mga Layout"
"Gesture na Pagta-type"
"Pagwawasto ng text"
"Advanced"
@@ -190,4 +190,6 @@
"Higit pang mga wika..."
"I-delete"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Gamitin ang mga wika ng system"
+ "Baguhin ang keyboard"
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 0a6ca881b..a01173da0 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -25,7 +25,7 @@
"Tuşa basıldığında pop-up aç"
"Tercihler"
"Hesaplar ve Gizlilik"
- "Görünüm ve Düzenler"
+ "Görünüm ve Düzenler"
"Hareketle Yazma"
"Metin düzeltme"
"Gelişmiş"
@@ -231,4 +231,6 @@
Ek tuşlar
Noktalama işaretlerinden sonra otomatik boşluk
Yeni bir sözcük yazarken noktalama işaretlerinden sonra otomatik olarak boşluk ekle
+ "Sistem dillerini kullan"
+ "Klavyeyi değiştir"
\ No newline at end of file
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 50c265ac3..fa4eea18e 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -25,7 +25,7 @@
"Збільшення натиснутих"
"Параметри"
"Облік. записи й конфіденційність"
- "Вигляд і розкладка"
+ "Вигляд і розкладка"
"Введення тексту жестами"
"Виправлення тексту"
"Додатково"
@@ -207,4 +207,6 @@
Подивитися на GitHub
Ліцензія з відкритим кодом
GNU General Public License v3.0
+ "Використовувати мови системи"
+ "Змінити клавіатуру"
diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml
index ace52d253..333667b7d 100644
--- a/app/src/main/res/values-ur/strings.xml
+++ b/app/src/main/res/values-ur/strings.xml
@@ -28,7 +28,7 @@
"کلید دبانے پر پاپ اپ"
"ترجیحات"
"اکاؤنٹس اور رازداری"
- "ظہور اور لے آؤٹس"
+ "ظہور اور لے آؤٹس"
"اشارہ جاتی ٹائپنگ"
"متن کی اصلاح"
"جدید ترین"
@@ -190,4 +190,6 @@
"مزید زبانیں…"
"حذف کریں"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "سسٹم زبانیں استعمال کریں"
+ "کی بورڈ تبدیل کریں"
diff --git a/app/src/main/res/values-uz/strings.xml b/app/src/main/res/values-uz/strings.xml
index e30206ae4..30afff96b 100644
--- a/app/src/main/res/values-uz/strings.xml
+++ b/app/src/main/res/values-uz/strings.xml
@@ -28,7 +28,7 @@
"Tugma bosilganda qalqib chiqish"
"Sozlamalar"
"Hisoblar va maxfiylik"
- "Ko‘rinish va sxema"
+ "Ko‘rinish va sxema"
"Qo‘l uzmasdan yozish"
"Matnni tuzatish"
"Kengaytirilgan sozlamalar"
@@ -190,4 +190,6 @@
"Ko‘proq tillar…"
"O‘chirish"
" ABDEFGHIJKLMNOPQRSTUVXYZO‘G‘SHCH"
+ "Tizimdagi mavjud tillar"
+ "Klaviaturani o‘zgartirish"
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 8e7debb4d..edc0ca0f1 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -28,7 +28,7 @@
"Phông chữ lớn hơn bật lên khi nhấn phím"
"Tùy chọn"
"Tài khoản và bảo mật"
- "Giao diện và bố cục"
+ "Giao diện và bố cục"
"Nhập bằng cử chỉ"
"Sửa văn bản"
"Nâng cao"
@@ -190,4 +190,6 @@
"Ngôn ngữ khác…"
"Xóa"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Sử dụng ngôn ngữ hệ thống"
+ "Thay đổi bàn phím"
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index ece008033..56b486781 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -25,7 +25,7 @@
"按键时弹出显示字符"
"偏好设置"
"帐号和隐私权"
- "外观和布局"
+ "外观和布局"
"滑行输入"
"文字更正"
"高级"
@@ -231,4 +231,6 @@
调整键盘大小
调整键盘高度
字母表
+ "使用系统语言"
+ "更改键盘"
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index 20d21ec36..28ca17c8b 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -25,7 +25,7 @@
"按鍵時顯示彈出式視窗"
"偏好設定"
"帳戶與私隱權"
- "外觀和版面配置"
+ "外觀和版面配置"
"手勢輸入"
"文字更正"
"進階"
@@ -203,4 +203,6 @@
設定
輸入
文字改正
+ "使用系統語言"
+ "變更鍵盤"
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index dbb46ecd6..4cc076e49 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -28,7 +28,7 @@
"按鍵時顯示大型字體"
"偏好設定"
"帳戶與隱私權"
- "外觀與版面配置"
+ "外觀與版面配置"
"手勢輸入"
"文字修正"
"進階"
@@ -190,4 +190,6 @@
"更多語言…"
"刪除"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "使用系統語言"
+ "變更鍵盤"
diff --git a/app/src/main/res/values-zu/strings.xml b/app/src/main/res/values-zu/strings.xml
index 357e3f1e5..57f06cfb8 100644
--- a/app/src/main/res/values-zu/strings.xml
+++ b/app/src/main/res/values-zu/strings.xml
@@ -28,7 +28,7 @@
"Ugaxekile ngokucindezela ukhiye"
"Izintandokazi"
"Ama-akhawunti nobumfihlo"
- "Ukubonakala nezakhiwo"
+ "Ukubonakala nezakhiwo"
"Ukuthayipha ngokuthinta"
"Ukulungisa umbhalo"
"Okuthuthukisiwe"
@@ -190,4 +190,6 @@
"Izilimi eziningi…"
"Susa"
" ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "Sebenzisa izilimi zesistimu"
+ "Shintsha ikhibhodi"
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index d364f1005..466b21a5f 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -135,4 +135,9 @@
#FFCCCCCC
#FF607D8B
+
+
+ #000
+ #555
+ #AAA
diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml
index 26437859b..b1cd0f89c 100644
--- a/app/src/main/res/values/donottranslate.xml
+++ b/app/src/main/res/values/donottranslate.xml
@@ -142,4 +142,6 @@
org.dslul.openboard.inputmethod.latin.HIDE_SOFT_INPUT
+
+ 100% FOSS keyboard, based on AOSP.
diff --git a/app/src/main/res/values/predefined-subtypes.xml b/app/src/main/res/values/predefined-subtypes.xml
index 3bf0e617f..2f2102e38 100644
--- a/app/src/main/res/values/predefined-subtypes.xml
+++ b/app/src/main/res/values/predefined-subtypes.xml
@@ -22,5 +22,6 @@
- de:qwerty:AsciiCapable
- fr:qwertz:AsciiCapable
+ - hu:qwerty:AsciiCapable
diff --git a/app/src/main/res/values/preferences_styles.xml b/app/src/main/res/values/preferences_styles.xml
new file mode 100644
index 000000000..50f6d7174
--- /dev/null
+++ b/app/src/main/res/values/preferences_styles.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6191817bf..f499f84c7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -43,8 +43,6 @@
Preferences
Accounts & Privacy
-
- Appearance & Layouts
Gesture Typing
@@ -476,6 +474,8 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
Now you can type in all your favorite apps with %s.
Configure additional languages
+
+ Configure the keyboard
Finished
@@ -502,14 +502,18 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
Built-in dictionary
"Add dictionary from file"
-
+
"Really replace existing user-added dictionary for %s?"
+
+ "Really replace user-added dictionary \"%s\"?"
"New dictionary file contains older version code than current file. Really replace current dictionary for %s?"
"Replace dictionary"
-
+
"Really remove user-added dictionary \"%1$s\" for %2$s?"
+
+ "Really remove user-added dictionary \"%1$s\"?"
"Remove dictionary"
@@ -528,6 +532,8 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
"Error: Selected file is not a valid dictionary file"
"The selected file is for %1$s, but %2$s was expected. Still use it for %2$s?"
+
+ "Error: script not compatible with this keyboard"
"Still use"
@@ -690,6 +696,16 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
Open-source license
GNU General Public License v3.0
-
- 100% FOSS keyboard, based on AOSP.
-
\ No newline at end of file
+
+ Close
+
+ "Use system languages"
+
+ "Change keyboard"
+
+ Appearance & Layouts
+
+ "Appearance"
+
diff --git a/app/src/main/res/xml/method.xml b/app/src/main/res/xml/method.xml
index 28df0a3be..25b311050 100644
--- a/app/src/main/res/xml/method.xml
+++ b/app/src/main/res/xml/method.xml
@@ -443,13 +443,6 @@
android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection,EmojiCapable"
android:isAsciiCapable="true"
/>
-
+
+
+
+
+
diff --git a/app/src/main/res/xml/prefs.xml b/app/src/main/res/xml/prefs.xml
index 9f2552739..fe1dc5d1e 100644
--- a/app/src/main/res/xml/prefs.xml
+++ b/app/src/main/res/xml/prefs.xml
@@ -16,6 +16,11 @@
+
-
-
-
-
-
+
+
+
+
+