diff --git a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml index 73b1ae679b..ca79447d3a 100644 --- a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml +++ b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml @@ -261,6 +261,12 @@ android:parentActivityName=".KeymanSettingsActivity" android:launchMode="singleTask" android:theme="@style/AppTheme.Base" /> + > list = null; diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/GetStartedActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/GetStartedActivity.java index ede2962217..d159e1a197 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/GetStartedActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/GetStartedActivity.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import com.tavultesoft.kmea.BaseActivity; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.data.Keyboard; @@ -29,7 +30,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.widget.TextView; -public class GetStartedActivity extends AppCompatActivity { +public class GetStartedActivity extends BaseActivity { private static ListView listView = null; private static ArrayList> list = null; diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java index 01bb79d4f5..7802f239ca 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/InfoActivity.java @@ -4,6 +4,7 @@ package com.tavultesoft.kmapro; +import com.tavultesoft.kmea.BaseActivity; import com.tavultesoft.kmea.BuildConfig; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.KMManager.FormFactor; @@ -20,7 +21,7 @@ import android.widget.TextView; import android.annotation.SuppressLint; import androidx.appcompat.app.AppCompatActivity; -public class InfoActivity extends AppCompatActivity { +public class InfoActivity extends BaseActivity { private final static String TAG = "InfoActivity"; private WebView webView; private final String HELP_PRODUCTION_HOST = "help.keyman.com"; diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java index 6e3ef52681..f25af7371a 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KMPBrowserActivity.java @@ -19,6 +19,7 @@ import android.webkit.WebView; import android.webkit.WebViewClient; import androidx.appcompat.app.AppCompatActivity; +import com.tavultesoft.kmea.BaseActivity; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.util.KMPLink; @@ -27,7 +28,7 @@ import java.util.regex.Pattern; import static android.app.Application.getProcessName; -public class KMPBrowserActivity extends AppCompatActivity { +public class KMPBrowserActivity extends BaseActivity { private static final String TAG = "KMPBrowserActivity"; // URL for keyboard search web page presented to user when they add a keyboard in the app. diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java index b681fff7e0..10bd0f9c2c 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsActivity.java @@ -2,10 +2,12 @@ package com.tavultesoft.kmapro; import android.os.Bundle; +import com.tavultesoft.kmea.BaseActivity; + import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; -public class KeymanSettingsActivity extends AppCompatActivity { +public class KeymanSettingsActivity extends BaseActivity { protected static final String installedLanguagesKey = "InstalledLanguages"; protected static final String installKeyboardOrDictionaryKey = "InstallKeyboardOrDictionary"; protected static final String showBannerKey = "ShowBanner"; @@ -20,6 +22,7 @@ public class KeymanSettingsActivity extends AppCompatActivity { setContentView(R.layout.keyman_settings_layout); Toolbar toolbar = (Toolbar) findViewById(R.id.keyman_settings_toolbar); toolbar.setTitleTextColor(getResources().getColor(android.R.color.white)); + toolbar.setTitle(R.string.keyman_settings); setSupportActionBar(toolbar); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java index fa15d4c1b9..468367f879 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsFragment.java @@ -1,3 +1,7 @@ +/** + * Copyright (C) 2020-2021 SIL International. All rights reserved. + */ + package com.tavultesoft.kmapro; import android.content.Context; @@ -12,6 +16,7 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; +import com.tavultesoft.kmea.DisplayLanguages; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.data.Dataset; @@ -19,7 +24,7 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { private static final String TAG = "SettingsFragment"; private static Context context; - private Preference languagesPreference, installKeyboardOrDictionary; + private Preference languagesPreference, installKeyboardOrDictionary, displayLanguagePreference; private CheckBoxPreference setSystemKeyboardPreference; private CheckBoxPreference setDefaultKeyboardPreference; @@ -46,6 +51,13 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { Intent installIntent = new Intent(context, KeymanSettingsInstallActivity.class); installKeyboardOrDictionary.setIntent(installIntent); + displayLanguagePreference = new Preference(context); + displayLanguagePreference.setKey(DisplayLanguages.displayLanguageKey); + displayLanguagePreference.setTitle(getString(R.string.change_display_language)); + displayLanguagePreference.setWidgetLayoutResource(R.layout.preference_translate_icon_layout); + Intent displayLanguageIntent = new Intent(context, KeymanSettingsLocalizeActivity.class); + displayLanguagePreference.setIntent(displayLanguageIntent); + /* Automatically does the following: SharedPreferences.Editor editor = prefs.edit(); @@ -106,6 +118,7 @@ public class KeymanSettingsFragment extends PreferenceFragmentCompat { screen.addPreference(languagesPreference); screen.addPreference(installKeyboardOrDictionary); + screen.addPreference(displayLanguagePreference); screen.addPreference(setSystemKeyboardPreference); screen.addPreference(setDefaultKeyboardPreference); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsLocalizeActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsLocalizeActivity.java new file mode 100644 index 0000000000..fae8c6f463 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/KeymanSettingsLocalizeActivity.java @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2021 SIL International. All rights reserved. + */ + +package com.tavultesoft.kmapro; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.View; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.SimpleAdapter; +import android.widget.TextView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.preference.PreferenceManager; + +import com.tavultesoft.kmea.DisplayLanguages; + +import java.util.ArrayList; +import java.util.HashMap; + +public class KeymanSettingsLocalizeActivity extends AppCompatActivity { + private static final String TAG = "SettingsLocalizeActivity"; + private static ArrayList> localizeOptionList = null; + private static Typeface titleFont = null; + private static final String titleKey = "title"; + private static final String subtitleKey = "subtitle"; + private static final String iconKey = "icon"; + private static Context context; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + supportRequestWindowFeature(Window.FEATURE_NO_TITLE); + context = this; + + setContentView(R.layout.activity_list_layout); + final Toolbar toolbar = findViewById(R.id.list_toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setDisplayShowHomeEnabled(true); + getSupportActionBar().setDisplayShowTitleEnabled(false); + + final ListView listView = findViewById(com.tavultesoft.kmea.R.id.listView); + + Bundle bundle = getIntent().getExtras(); + + final TextView textView = findViewById(R.id.bar_title); + textView.setText(getString(R.string.change_display_language)); + if (titleFont != null) { + textView.setTypeface(titleFont, Typeface.BOLD); + } + + localizeOptionList = new ArrayList<>(); + + final String noIcon = "0"; + for(DisplayLanguages.DisplayLanguageType l: DisplayLanguages.DisplayLanguages) { + HashMap hashMap = new HashMap<>(); + hashMap.put(titleKey, l.getLanguageName()); + hashMap.put(iconKey, noIcon); + localizeOptionList.add(hashMap); + } + + String[] from = new String[]{titleKey, subtitleKey, iconKey}; + int[] to = new int[]{com.tavultesoft.kmea.R.id.text1, com.tavultesoft.kmea.R.id.image1}; + + ListAdapter adapter = new SimpleAdapter(context, localizeOptionList, com.tavultesoft.kmea.R.layout.list_row_layout1, from, to) { + }; + listView.setAdapter(adapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + // Store the BCP-47 language tag in shared preference + if (position >= 0 && position < DisplayLanguages.DisplayLanguages.length) { + + DisplayLanguages.DisplayLanguageType l = DisplayLanguages.DisplayLanguages[position]; + String languageTag = l.getLanguageTag(); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(DisplayLanguages.displayLanguageKey, languageTag); + editor.commit(); + + // Restart the app to use selected locale + Intent intent = new Intent(context, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + } + }); + } + + @Override + public boolean onSupportNavigateUp() { + super.onBackPressed(); + return true; + } +} \ No newline at end of file diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index 2585dcd520..ddaf2ea3fa 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018-2020 SIL International. All rights reserved. + * Copyright (C) 2018-2021 SIL International. All rights reserved. */ package com.tavultesoft.kmapro; @@ -17,6 +17,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.tavultesoft.kmea.BaseActivity; import com.tavultesoft.kmea.KMKeyboardDownloaderActivity; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.KMManager.KeyboardType; @@ -92,7 +93,7 @@ import android.widget.Toast; import io.sentry.android.core.SentryAndroid; -public class MainActivity extends AppCompatActivity implements OnKeyboardEventListener, OnKeyboardDownloadEventListener, +public class MainActivity extends BaseActivity implements OnKeyboardEventListener, OnKeyboardDownloadEventListener, ActivityCompat.OnRequestPermissionsResultCallback { public static Context context; diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/WebBrowserActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/WebBrowserActivity.java index a2be8fd173..229b24fdb4 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/WebBrowserActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/WebBrowserActivity.java @@ -10,6 +10,7 @@ import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import com.tavultesoft.kmea.BaseActivity; import com.tavultesoft.kmea.KMManager; import com.tavultesoft.kmea.util.KMPLink; @@ -48,7 +49,7 @@ import androidx.appcompat.app.AppCompatActivity; import static android.app.Application.getProcessName; -public class WebBrowserActivity extends AppCompatActivity { +public class WebBrowserActivity extends BaseActivity { private static final String TAG = "WebBrowserActivity"; private WebView webView; private EditText addressField; diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/ic_translate.png b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/ic_translate.png new file mode 100644 index 0000000000..20cf9715e0 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-hdpi/ic_translate.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/ic_translate.png b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/ic_translate.png new file mode 100644 index 0000000000..20cf9715e0 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-mdpi/ic_translate.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/ic_translate.png b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/ic_translate.png new file mode 100644 index 0000000000..3f804126c2 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xhdpi/ic_translate.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/ic_translate.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/ic_translate.png new file mode 100644 index 0000000000..71b2332aaa Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xxhdpi/ic_translate.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/ic_translate.png b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/ic_translate.png new file mode 100644 index 0000000000..0065c18426 Binary files /dev/null and b/android/KMAPro/kMAPro/src/main/res/drawable-xxxhdpi/ic_translate.png differ diff --git a/android/KMAPro/kMAPro/src/main/res/layout/preference_translate_icon_layout.xml b/android/KMAPro/kMAPro/src/main/res/layout/preference_translate_icon_layout.xml new file mode 100644 index 0000000000..d66b445010 --- /dev/null +++ b/android/KMAPro/kMAPro/src/main/res/layout/preference_translate_icon_layout.xml @@ -0,0 +1,5 @@ + + diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml index 8784919a06..1285c9f2e7 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml @@ -95,6 +95,9 @@ Install Keyboard or Dictionary + + Change display language + Always show banner diff --git a/android/KMEA/app/build.gradle b/android/KMEA/app/build.gradle index 20c23e8aa0..d5b7348f28 100644 --- a/android/KMEA/app/build.gradle +++ b/android/KMEA/app/build.gradle @@ -66,6 +66,7 @@ dependencies { implementation 'com.google.android.material:material:1.2.1' implementation 'commons-io:commons-io:2.6' implementation 'io.sentry:sentry-android:3.1.0' + implementation 'androidx.preference:preference:1.1.1' // Robolectric testImplementation 'androidx.test:core:1.2.0' diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/BaseActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/BaseActivity.java new file mode 100644 index 0000000000..fdd8ed2de1 --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/BaseActivity.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2021 SIL International. All rights reserved. + */ + +package com.tavultesoft.kmea; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.SharedPreferences; +import android.os.Build; +import android.os.LocaleList; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.PreferenceManager; + +import com.tavultesoft.kmea.util.ContextUtils; + +import java.util.Locale; + +public class BaseActivity extends AppCompatActivity { + + @Override + protected void attachBaseContext(Context newBase) { + // Override the app locale using the BCP 47 tag from shared preferences + // Using PreferenceManager because this is before onCreate() + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(newBase); + String languageTag = prefs.getString(DisplayLanguages.displayLanguageKey, DisplayLanguages.unspecifiedLocale); + Locale localeToSwitchTo; + if (languageTag == null || languageTag.equals(DisplayLanguages.unspecifiedLocale)) { + // If display language not specified, use the default locale + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + super.attachBaseContext(newBase); + return; + } + localeToSwitchTo = LocaleList.getDefault().get(0); + } else { + localeToSwitchTo = Locale.forLanguageTag(languageTag); + } + ContextWrapper localeUpdatedContext = ContextUtils.updateLocale(newBase, localeToSwitchTo); + super.attachBaseContext(localeUpdatedContext); + } + +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/DisplayLanguages.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/DisplayLanguages.java new file mode 100644 index 0000000000..7ffc3e511d --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/DisplayLanguages.java @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2021 SIL International. All rights reserved. + */ + +package com.tavultesoft.kmea; + +public class DisplayLanguages { + private static final String TAG = "DisplayLanguages"; + public static final String displayLanguageKey = "DisplayLanguage"; + public static final String unspecifiedLocale = ""; // empty string for app to use device's default locale + + public static class DisplayLanguageType { + String languageTag; + String languageName; + + public DisplayLanguageType(String languageTag, String languageName) { + this.languageTag = languageTag; + this.languageName = languageName; + } + + public String getLanguageTag() { + return this.languageTag; + } + + public String getLanguageName() { + return this.languageName; + } + } + + // Display Language types (as named in translate.keyman.com) + // Order doesn't matter since we're storing BCP-47 tags in the settings preference + public static final DisplayLanguageType[] DisplayLanguages = + { + new DisplayLanguageType(unspecifiedLocale, "Default Locale"), + new DisplayLanguageType("de-DE", "German"), + new DisplayLanguageType("km-KH", "Khmer"), + new DisplayLanguageType("ann", "Obolo") + }; + +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index cd56cf6bc7..c55138ad35 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -22,7 +22,7 @@ import java.util.List; import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DOWNLOAD_KEYBOARD; import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DOWNLOAD_MODEL; -public class KMKeyboardDownloaderActivity extends AppCompatActivity { +public class KMKeyboardDownloaderActivity extends BaseActivity { // Bundle Keys // Cloud diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardInfoActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardInfoActivity.java index 63f95182ab..4c2a316e96 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardInfoActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardInfoActivity.java @@ -36,7 +36,7 @@ import com.tavultesoft.kmea.util.MapCompat; import com.tavultesoft.kmea.util.QRCodeUtil; // Public access is necessary to avoid IllegalAccessException -public final class KeyboardInfoActivity extends AppCompatActivity { +public final class KeyboardInfoActivity extends BaseActivity { private static final String TAG = "KeyboardInfoActivity"; private static Toolbar toolbar = null; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java index 5da07ec094..960e29a08f 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java @@ -45,7 +45,7 @@ import android.widget.Toast; import androidx.appcompat.widget.Toolbar; -public final class KeyboardPickerActivity extends AppCompatActivity { +public final class KeyboardPickerActivity extends BaseActivity { //TODO: view instances should not be static private static Toolbar toolbar = null; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelInfoActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelInfoActivity.java index 7213a2cd68..80f45ed553 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelInfoActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelInfoActivity.java @@ -38,7 +38,7 @@ import com.tavultesoft.kmea.util.MapCompat; import static com.tavultesoft.kmea.ConfirmDialogFragment.DialogType.DIALOG_TYPE_DELETE_MODEL; // Public access is necessary to avoid IllegalAccessException -public final class ModelInfoActivity extends AppCompatActivity { +public final class ModelInfoActivity extends BaseActivity { private static ArrayList> infoList = null; private final String titleKey = "title"; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java index 741a1eb8d3..a4d03ef3ad 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java @@ -40,7 +40,7 @@ import java.util.Map; * Gets the list of installable lexical models from Keyman cloud and allows user to download a model. * Displays a list of available models for a language ID. */ -public final class ModelPickerActivity extends AppCompatActivity { +public final class ModelPickerActivity extends BaseActivity { private Context context; private static Toolbar toolbar = null; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/util/ContextUtils.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/util/ContextUtils.java new file mode 100644 index 0000000000..c432dfa63b --- /dev/null +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/util/ContextUtils.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2021 SIL International. All rights reserved. + */ +package com.tavultesoft.kmea.util; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.LocaleList; + +import java.util.Locale; + +/** + * Class to programmatically change the application locale (#4236) + * References + * Tutorial from https://lokalise.com/blog/android-app-localization/#Change_Application_Locale_Programmatically + * https://github.com/nirm2009/lokalise/tree/master/android-i18n + * https://stackoverflow.com/questions/39705739/android-n-change-language-programmatically + */ +public class ContextUtils extends ContextWrapper { + public ContextUtils(Context base) { + super(base); + } + + public static ContextWrapper updateLocale(Context context, Locale localeToSwitchTo) { + Resources resources = context.getResources(); + Configuration configuration = resources.getConfiguration(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + LocaleList localeList = new LocaleList(localeToSwitchTo); + LocaleList.setDefault(localeList); + configuration.setLocales(localeList); + } else { + configuration.locale = localeToSwitchTo; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + context = context.createConfigurationContext(configuration); + } else { + resources.updateConfiguration(configuration, resources.getDisplayMetrics()); + } + + return new ContextUtils(context); + } + +} diff --git a/resources/build/l10n/README.md b/resources/build/l10n/README.md index 0a89c334a5..318e6815e3 100644 --- a/resources/build/l10n/README.md +++ b/resources/build/l10n/README.md @@ -1,6 +1,6 @@ # Localization Maintenance -Localization for Keyman is maintained at https://crowdin.com/project/keyman +Localization for Keyman is maintained at https://translate.keyman.com Downloading and updating files between Keyman and Crowdin happens automatically on GitHub by way of the Crowdin git integration. The configuration file for all platforms @@ -69,6 +69,9 @@ To download latest translations for the specific language: crowdin download -b master -l {language_code} ``` +Note: the Crowdin API doesn't handle custom languages so those will need to be manually synced. +See https://support.crowdin.com/api/language-codes/ + To display a list of latest translations from Crowdin: ```bash @@ -83,6 +86,12 @@ To upload source files to Crowdin: crowdin upload sources ``` +### Updating DisplayLanguages.java in Keyman Engine for Android +In Keyman for Android, the settings menu for changing display languages is maintained in +android/KMEA/app/src/main/java/com/tavultesoft/kmea/DisplayLangugages.java + +For the BCP-47 language tags to use in that file, don't include script names since the Android locales only handle language ID and region. + ## Tip Microsoft offers a website that allows to check how terms used in Windows are translated