Bad, messy, always have to comb.

In the face of the unknown, the strangeness is sudden.

Party A requested to realize the internationalization of the App in multiple languages, just took the time to do, hurt, was stupid to death, deliberately recorded.

If there is any wrong, welcome to correct, exchange ~

Results demonstrate

The video recording is not very good, the overall effect is out, we apologize ~

Version: 6.0, 8.0, and 10.0

To make up

A quick note:

  • Internationalization, multi-language directory creation, resource configuration;
  • Locale resource fetch and local cache, the purpose of the cache is to open your App again the next time it’s still the language you chose last time;
  • For example, after 7.0, Android is no longer the only default language, but a multi-language configuration, as shown below:

All right, go straight to the code

Appcompat: AndroidX package: appCompat: androidX package: AppCompat: androidX package: AppCompat: androidX package: AppCompat: androidX package: AppCompat: androidX package: AppCompat: androidX package: AppCompat

  • Implementation ‘androidx. Appcompat: appcompat: 1.2.0’

1. Create the corresponding resource file

There are two ways:

  • A:

Right click “res”, select “New”, “Android Resource File” :

Select the configuration language table as shown below:

  • Method 2:

Select “Resource Manager” on the left of Android Studio, then select the minimap + logo, and select the compatible country from the list.

The values directory and strings file for the selected country will then be created for us, as follows:

Ok, now that the basic language directory and files have been created, all that remains is that there will be someone responsible for providing the corresponding translation words.

Of course, our consistent principle is to do it yourself, and have enough food and clothing.

Provides some common, good online translation address, as follows:

  • www.deepl.com/translator
  • translate.google.cn/

Ii. Attached is the MMKV Utils used in the process

Remember to refer to the MMKV dependency and initialization address as follows:

  • Github.com/Tencent/MMK…

The version for personal use is as follows:

  • Implementation ‘com. Tencent: MMKV: 1.0.17’
/** * @author: HLQ_Struggle * @date: 2020/4/13 * @desc: Class MMKVPro<T>(private val MMKV: MMKV, private val key: String, private val defValue: T ) { operator fun getValue(thisRef: Any? , property: KProperty<*>): Return mmkv.run {when (defValue) {is String -> getString(key, defValue) is Boolean -> getBoolean(key, defValue) is Long -> getLong(key, defValue) is Int -> getInt(key, defValue) is Float -> getFloat(key, defValue) else -> Unit } } as T } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { return mmkv.run { when (value) { is String -> putString(key, value) is Boolean -> putBoolean(key, value) is Long -> putLong(key, value) is Int -> putInt(key, value) is Float -> putFloat(key, Value) else -> Unit}}}} /** * String) { MMKV.mmkvWithID(F_APP_CACHE, MMKV.MULTI_PROCESS_MODE, K_ENCRYPT).run { remove(key) } }Copy the code

Prepare multilingual utils

/** * @author HLQ_Struggle * @date 2021/02/26 * @desc */ ** * Activity Updates language resources */ fun getAttachBaseContext(context: Context): Context { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return setAppLanguageApi24(context) } else { SetAppLanguage (context)} return context} /** * Suppress("DEPRECATION") fun setAppLanguage(context: Context) { val resources = context.resources val displayMetrics = resources.displayMetrics val configuration = Resources. Configuration // Get the current system language, The default setting follows the system val locale = getAppLocale() if (build.version.sdk_int >= build.version_codes.jelly_bean_mr1) { configuration.setLocale(locale); } else { configuration.locale = locale; } resources.updateConfiguration(configuration, DisplayMetrics)} /** * compatible with 7.0 and above */ @targetAPI (build.version_codes.n) private fun setAppLanguageApi24(context: Context): Context { val locale = getAppLocale() val resource = context.resources val configuration = resource.configuration configuration.setLocale(locale) configuration.setLocales(LocaleList(locale)) return Context. CreateConfigurationContext (configuration)} / get App current language * * * * / private fun getAppLocale () = the when (LocalDataStorage().multilingual) {0 -> {// Follows the system getSystemLocale()} 1 -> {// Chinese locale.china} 2 -> {// English Locale.ENGLISH} else -> locale. ENGLISH} /** * getSystemLocale(): */ private fun getSystemLocale(): Locale { val systemLocale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { LocaleList.getDefault()[0] } else { Locale.getDefault() } return when (systemLocale.language) { Locale.CHINA.language -> { Locale.CHINA } Locale.ENGLISH.language -> { Locale.ENGLISH } else -> { Locale.ENGLISH } } }Copy the code

Four, in the selection of multi-language page for processing

The idea here, of course, is to cache the language list index locally, and then get the corresponding language by ID directly.

Click OK to cache the currently selected

override fun onClick(v: View?) { when (v? .id) {r.idvdone -> {// Update the selection status LocalDataStorage(). Multilingual = mAfterPosition setAppLanguage(this) reStartActivity() } } } private fun reStartActivity() { val intent = Intent(mSelfActivity, MainActivity::class.java) intent.flags = FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK startActivity(intent) / / cancel the special animation overridePendingTransition (0, 0)}Copy the code

5. Configuration processing in Application

override fun onConfigurationChanged(newConfig: Configuration?) {
    super.onConfigurationChanged(newConfig)
    // ...
    setAppLanguage(this)
}
Copy the code

Sixth, BaseActivity processing

Since the Activity needs to be rebuilt to handle the corresponding resource, I put it in BaseActivity to handle it:

override fun attachBaseContext(newBase: Context?) { super.attachBaseContext(newBase? .let { getAttachBaseContext(it) }) }Copy the code

7. Optimize items and update resource files

Be sure to update this, if you have done Apk size optimization, you will probably limit the resConfigs content, so as not to increase the Apk size with unnecessary content. Be sure to update this, if you have done Apk size optimization, you will probably limit the resConfigs content, so as not to increase the Apk size with unnecessary content. Be sure to update this, if you have done Apk size optimization, you will probably limit the resConfigs content, so as not to increase the Apk size with unnecessary content.

I just finished writing, how also no effect, then a look, good guy, limit only Chinese. The embarrassment, helplessness…

resConfigs "zh-rCN", "en"
Copy the code

Well, that’s it, of course, for Android to have to deal with multiple models of adaptation…

Here is a follow-up encounter in the update to the ~

Some of the problems of multilingualism

1. Layout issues

This is really a headache, especially for our incomplete infrastructure, the best we can do is to ensure most of the effect, try to use short English or non-Chinese.

It also reminds me, how do I make the development process as compatible as possible?

Maybe it’s experience. Take it slow.

2. Capitalize TabLayout in English mode

After switching, the effect is as follows:

The current version of TabLayout is as follows:

  • Implementation ‘com. Google. Android. Material: material: 1.2.1’

Here, just set a style:

<style name="TabLayoutTextStyle" parent="TextAppearance.Design.Tab">
    <item name="android:textSize">@dimen/sp_18</item>
    <item name="textAllCaps">false</item>
</style>
Copy the code

I’ll add it later.

The resources

  • Localize your application
  • Unicode and internationalization support
  • An overview of languages and locale parsing
  • Android (internationalization) multi-language implementation and switching
  • Android multi-language switching (compatible with Android 9 and 10)