Repository: thundernest/k-9
Issue: Localized strings fail

Persian translation is fully done via transifex and it works properly while device language is set to Persian. But when device language is set to English and app language is set to Persian, some strings still are English.

### Expected behavior
Regardless of device language, all strings be in Persian (selected via app setting)

### Actual behavior
Some strings are English and some Persian.

### Steps to reproduce
1. Set device language to English.
2. Set app language to Persian.
3. Exit app.
4. Open app.
5. Some strings are english. For example:
5.1. "load up to 10 more" at bottom of screen
5.2. "inbox" and "outbox" in left menu
5.3. try to compose a new mail, then title "Compose" is in English. Also tap 3 dots menu, all items under it are English.
5.4. tap back to leave compose. Then tap pencil icon to open "compose" again.  It's now in Persian.
5.5. Go to settings. Choose an account setting. Go to Fetch mail. Then go to incoming server setting. Title of dialog is English.

### Environment
K-9 Mail version: 5.703

Android version: 7.1.1

Account type (IMAP, POP3, WebDAV/Exchange):
IMAP

Please take some time to retrieve logs and attach them here.

For steps 5.3 - 5.4:

[K9log.txt](https://github.com/k9mail/k-9/files/4002776/K9log.txt)


Changed files:
app/ui/base/src/main/java/com/fsck/k9/ui/base/AppLanguageManager.kt, app/k9mail/src/main/java/com/fsck/k9/App.kt

diff --git a/app/k9mail/src/main/java/com/fsck/k9/App.kt b/app/k9mail/src/main/java/com/fsck/k9/App.kt
index d097ae524..79646b9fe 100644
--- a/app/k9mail/src/main/java/com/fsck/k9/App.kt
+++ b/app/k9mail/src/main/java/com/fsck/k9/App.kt
@@ -2,6 +2,7 @@ package com.fsck.k9
 
 import android.app.Application
 import android.content.res.Configuration
+import android.content.res.Resources
 import com.fsck.k9.activity.MessageCompose
 import com.fsck.k9.controller.MessagingController
 import com.fsck.k9.external.MessageProvider
@@ -25,6 +26,7 @@ class App : Application() {
     private val themeManager: ThemeManager by inject()
     private val appLanguageManager: AppLanguageManager by inject()
     private val appCoroutineScope: CoroutineScope = GlobalScope + Dispatchers.Main
+    private var appLanguageManagerInitialized = false
 
     override fun onCreate() {
         Core.earlyInit(this)
@@ -46,13 +48,14 @@ class App : Application() {
 
     private fun initializeAppLanguage() {
         appLanguageManager.init()
-        applyOverrideLocale()
+        applyOverrideLocaleToConfiguration()
+        appLanguageManagerInitialized = true
         listenForAppLanguageChanges()
     }
 
-    private fun applyOverrideLocale() {
+    private fun applyOverrideLocaleToConfiguration() {
         appLanguageManager.getOverrideLocale()?.let { overrideLocale ->
-            updateConfigurationWithLocale(resources.configuration, overrideLocale)
+            updateConfigurationWithLocale(superResources.configuration, overrideLocale)
         }
     }
 
@@ -61,14 +64,14 @@ class App : Application() {
             .drop(1) // We already applied the initial value
             .onEach { overrideLocale ->
                 val locale = overrideLocale ?: Locale.getDefault()
-                updateConfigurationWithLocale(resources.configuration, locale)
+                updateConfigurationWithLocale(superResources.configuration, locale)
             }
             .launchIn(appCoroutineScope)
     }
 
     override fun onConfigurationChanged(newConfiguration: Configuration) {
-        applyOverrideLocale()
-        super.onConfigurationChanged(resources.configuration)
+        applyOverrideLocaleToConfiguration()
+        super.onConfigurationChanged(superResources.configuration)
     }
 
     private fun updateConfigurationWithLocale(configuration: Configuration, locale: Locale) {
@@ -79,7 +82,31 @@ class App : Application() {
         }
 
         @Suppress("DEPRECATION")
-        resources.updateConfiguration(newConfiguration, resources.displayMetrics)
+        superResources.updateConfiguration(newConfiguration, superResources.displayMetrics)
+    }
+
+    private val superResources: Resources
+        get() = super.getResources()
+
+    // Creating a WebView instance triggers something that will cause the configuration of the Application's Resources
+    // instance to be reset to the default, i.e. not containing our locale override. Unfortunately, we're not notified
+    // about this event. So we're checking each time someone asks for the Resources instance whether we need to change
+    // the configuration again. Luckily, right now (Android 11), the platform is calling this method right after
+    // resetting the configuration.
+    override fun getResources(): Resources {
+        val resources = super.getResources()
+
+        if (appLanguageManagerInitialized) {
+            appLanguageManager.getOverrideLocale()?.let { overrideLocale ->
+                if (resources.configuration.currentLocale != overrideLocale) {
+                    Timber.w("Resources configuration was reset. Re-applying locale override.")
+                    appLanguageManager.applyOverrideLocale()
+                    applyOverrideLocaleToConfiguration()
+                }
+            }
+        }
+
+        return resources
     }
 
     companion object {
diff --git a/app/ui/base/src/main/java/com/fsck/k9/ui/base/AppLanguageManager.kt b/app/ui/base/src/main/java/com/fsck/k9/ui/base/AppLanguageManager.kt
index 7498dc399..328490f52 100644
--- a/app/ui/base/src/main/java/com/fsck/k9/ui/base/AppLanguageManager.kt
+++ b/app/ui/base/src/main/java/com/fsck/k9/ui/base/AppLanguageManager.kt
@@ -45,6 +45,12 @@ class AppLanguageManager(
         setLocale(appLanguage)
     }
 
+    fun applyOverrideLocale() {
+        currentOverrideLocale?.let { overrideLocale ->
+            Locale.setDefault(overrideLocale)
+        }
+    }
+
     private fun setLocale(appLanguage: String) {
         val overrideLocale = getOverrideLocaleForLanguage(appLanguage)
         currentOverrideLocale = overrideLocale