|
| 1 | +#### Table of Contents |
| 2 | + |
| 3 | +* [How to Set the Default Language of the App](#how-to-set-the-default-language-of-the-app) |
| 4 | + |
| 5 | +* [What to Do If Switching Language Has No Effect](#what-to-do-if-switching-language-has-no-effect) |
| 6 | + |
| 7 | +* [How to Apply Language Change to All Activities](#how-to-apply-language-change-to-all-activities) |
| 8 | + |
| 9 | +* [How to Refresh All Screens When the User Switches System Language](#how-to-refresh-all-screens-when-the-user-switches-system-language) |
| 10 | + |
| 11 | +* [What to Do If Returning to the App After System Language Switch Has No Effect](#what-to-do-if-returning-to-the-app-after-system-language-switch-has-no-effect) |
| 12 | + |
| 13 | +* [Solution for WebView Causing Language Failure](#solution-for-webview-causing-language-failure) |
| 14 | + |
| 15 | +* [What to Do If WebView Language Fails on Android 13](#what-to-do-if-webview-language-fails-on-android-13) |
| 16 | + |
| 17 | +* [Is There a Way to Switch Language Without Restarting](#is-there-a-way-to-switch-language-without-restarting) |
| 18 | + |
| 19 | +#### How to Set the Default Language of the App |
| 20 | + |
| 21 | +* If you have never called `MultiLanguages.setAppLanguage` and do not want the app to follow the system language, but want to specify a certain language, you can do as follows: |
| 22 | + |
| 23 | +```java |
| 24 | +public final class XxxApplication extends Application { |
| 25 | + |
| 26 | + static { |
| 27 | + // Set the default language (the earlier, the better) |
| 28 | + MultiLanguages.setDefaultLanguage(LocaleContract.getEnglishLocale()); |
| 29 | + } |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +* If you want to determine the current system language type and then set the default language, you can write: |
| 34 | + |
| 35 | +```java |
| 36 | +public final class XxxApplication extends Application { |
| 37 | + |
| 38 | + @Override |
| 39 | + protected void attachBaseContext(Context newBase) { |
| 40 | + if (newBase != null) { |
| 41 | + Locale systemLanguage = MultiLanguages.getSystemLanguage(newBase); |
| 42 | + // If the current language is neither Chinese (including Simplified and Traditional) nor English (including American and British), set it to English by default to avoid following the system language |
| 43 | + if (!MultiLanguages.equalsLanguage(systemLanguage, LocaleContract.getChineseLocale()) && |
| 44 | + !MultiLanguages.equalsLanguage(systemLanguage, LocaleContract.getEnglishLocale())) { |
| 45 | + MultiLanguages.setDefaultLanguage(LocaleContract.getEnglishLocale()); |
| 46 | + } |
| 47 | + } |
| 48 | + // Bind language |
| 49 | + super.attachBaseContext(MultiLanguages.attach(newBase)); |
| 50 | + } |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +#### What to Do If Switching Language Has No Effect |
| 55 | + |
| 56 | +* Case 1: Check if you have configured to keep only certain country language resources in the `build.gradle` file, for example, `resConfigs 'zh'` means only Chinese-related language resources are kept, and other countries' language resources will not be packaged into the apk, which will cause the language to always be Chinese when switching. |
| 57 | + |
| 58 | +* Case 2: If the language switch in Fragment has no effect, check if the Fragment is reused after the Activity restarts, usually caused by calling `fragment.setRetainInstance(true)`. |
| 59 | + |
| 60 | +* Case 3: If you cannot switch the app language after uploading the aab package to Google Play or Huawei and downloading it, it is because multi-language resources are missing during splitting. You need to configure the main module's `build.gradle` file. For details, refer to the [official documentation](https://developer.android.google.cn/guide/app-bundle/configure-base?hl=en). |
| 61 | + |
| 62 | +```groovy |
| 63 | +android { |
| 64 | +
|
| 65 | + ...... |
| 66 | +
|
| 67 | + bundle { |
| 68 | +
|
| 69 | + ...... |
| 70 | +
|
| 71 | + language { |
| 72 | + enableSplit = false |
| 73 | + } |
| 74 | +
|
| 75 | + ...... |
| 76 | + } |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +* Other cases: If the above reasons do not apply, please submit an [issue](https://github.com/getActivity/MultiLanguages/issues) for assistance. |
| 81 | + |
| 82 | +#### How to Apply Language Change to All Activities |
| 83 | + |
| 84 | +* Add the following code in the onCreate method of Application: |
| 85 | + |
| 86 | +```java |
| 87 | +MultiLanguages.setOnLanguageListener(new OnLanguageListener() { |
| 88 | + |
| 89 | + @Override |
| 90 | + public void onAppLocaleChange(Locale oldLocale, Locale newLocale) { |
| 91 | + Log.i("MultiLanguages", "Detected app language change, old language: " + oldLocale + ", new language: " + newLocale); |
| 92 | + // If you want the app to change with the system language, get all Activities here and call their recreate method |
| 93 | + // getAllActivity is just demonstration code, replace it with your own implementation. If not available, please encapsulate it yourself |
| 94 | + List<Activity> activityList = getAllActivity(); |
| 95 | + for (Activity activity : activityList) { |
| 96 | + activity.recreate(); |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + @Override |
| 101 | + public void onSystemLocaleChange(Locale oldLocale, Locale newLocale) { |
| 102 | + Log.i("MultiLanguages", "Detected system language change, old language: " + oldLocale + ", new language: " + newLocale + ", following system: " + MultiLanguages.isSystemLanguage()); |
| 103 | + } |
| 104 | +}); |
| 105 | +``` |
| 106 | + |
| 107 | +#### How to Refresh All Screens When the User Switches System Language |
| 108 | + |
| 109 | +* Add the following code in the onCreate method of Application: |
| 110 | + |
| 111 | +```java |
| 112 | +MultiLanguages.setOnLanguageListener(new OnLanguageListener() { |
| 113 | + |
| 114 | + @Override |
| 115 | + public void onAppLocaleChange(Locale oldLocale, Locale newLocale) { |
| 116 | + Log.i("MultiLanguages", "Detected app language change, old language: " + oldLocale + ", new language: " + newLocale); |
| 117 | + } |
| 118 | + |
| 119 | + @Override |
| 120 | + public void onSystemLocaleChange(Locale oldLocale, Locale newLocale) { |
| 121 | + Log.i("MultiLanguages", "Detected system language change, old language: " + oldLocale + ", new language: " + newLocale + ", following system: " + MultiLanguages.isSystemLanguage()); |
| 122 | + |
| 123 | + // If the current language is not following the system, do not proceed |
| 124 | + if (!MultiLanguages.isSystemLanguage(AppApplication.this)) { |
| 125 | + return; |
| 126 | + } |
| 127 | + |
| 128 | + // If you want the app to change with the system language, get all Activities here and call their recreate method |
| 129 | + // getAllActivity is just demonstration code, replace it with your own implementation. If not available, please encapsulate it yourself |
| 130 | + List<Activity> activityList = getAllActivity(); |
| 131 | + for (Activity activity : activityList) { |
| 132 | + activity.recreate(); |
| 133 | + } |
| 134 | + } |
| 135 | +}); |
| 136 | +``` |
| 137 | + |
| 138 | +#### What to Do If Returning to the App After System Language Switch Has No Effect |
| 139 | + |
| 140 | +* Please check if the Activity is configured with the `android:configChanges` attribute. If so, remove it and try again. For documentation, see [`<activity>`](https://developer.android.com/guide/topics/manifest/activity-element?hl=en) |
| 141 | + |
| 142 | +```xml |
| 143 | +<activity |
| 144 | + android:name=".XxxActivity" |
| 145 | + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" /> |
| 146 | +``` |
| 147 | + |
| 148 | +* If you do not want to remove the `android:configChanges` attribute but want the language switch to take effect after switching the system language, add the following code in the onCreate method of Application: |
| 149 | + |
| 150 | +```java |
| 151 | +MultiLanguages.setOnLanguageListener(new OnLanguageListener() { |
| 152 | + |
| 153 | + @Override |
| 154 | + public void onAppLocaleChange(Locale oldLocale, Locale newLocale) { |
| 155 | + Log.i("MultiLanguages", "Detected app language change, old language: " + oldLocale + ", new language: " + newLocale); |
| 156 | + } |
| 157 | + |
| 158 | + @Override |
| 159 | + public void onSystemLocaleChange(Locale oldLocale, Locale newLocale) { |
| 160 | + Log.i("MultiLanguages", "Detected system language change, old language: " + oldLocale + ", new language: " + newLocale + ", following system: " + MultiLanguages.isSystemLanguage()); |
| 161 | + |
| 162 | + // If the current language is not following the system, do not proceed |
| 163 | + if (!MultiLanguages.isSystemLanguage(AppApplication.this)) { |
| 164 | + return; |
| 165 | + } |
| 166 | + |
| 167 | + // If you want the app to change with the system language, get all Activities here and call their recreate method |
| 168 | + // getAllActivity is just demonstration code, replace it with your own implementation. If not available, please encapsulate it yourself |
| 169 | + List<Activity> activityList = getAllActivity(); |
| 170 | + for (Activity activity : activityList) { |
| 171 | + activity.recreate(); |
| 172 | + } |
| 173 | + } |
| 174 | +}); |
| 175 | +``` |
| 176 | + |
| 177 | +#### Solution for WebView Causing Language Failure |
| 178 | + |
| 179 | +* Since WebView initialization will modify the Activity language configuration, which indirectly causes the Activity language to be restored, you need to manually override WebView to fix this issue |
| 180 | + |
| 181 | +```java |
| 182 | +public final class LanguagesWebView extends WebView { |
| 183 | + |
| 184 | + public LanguagesWebView(@NonNull Context context) { |
| 185 | + this(context, null); |
| 186 | + } |
| 187 | + |
| 188 | + public LanguagesWebView(@NonNull Context context, @Nullable AttributeSet attrs) { |
| 189 | + this(context, attrs, android.R.attr.webViewStyle); |
| 190 | + } |
| 191 | + |
| 192 | + public LanguagesWebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { |
| 193 | + super(context, attrs, defStyleAttr); |
| 194 | + |
| 195 | + // Fix the issue where WebView initialization modifies the Activity language configuration |
| 196 | + MultiLanguages.updateAppLanguage(context); |
| 197 | + } |
| 198 | +} |
| 199 | +``` |
| 200 | + |
| 201 | +#### What to Do If WebView Language Fails on Android 13 |
| 202 | + |
| 203 | +* Replace `webView.loadUrl(@NonNull String url)` with `webView.loadUrl(@NonNull String url, @NonNull Map<String, String> additionalHttpHeaders)` and add the `Accept-Language` request header. Example code: |
| 204 | + |
| 205 | +```java |
| 206 | +public final class MainActivity extends Activity { |
| 207 | + |
| 208 | + private WebView mWebView; |
| 209 | + |
| 210 | + @Override |
| 211 | + protected void onCreate(Bundle savedInstanceState) { |
| 212 | + super.onCreate(savedInstanceState); |
| 213 | + setContentView(R.layout.activity_main); |
| 214 | + |
| 215 | + mWebView = findViewById(R.id.wv_main_web); |
| 216 | + |
| 217 | + mWebView.setWebViewClient(new LanguagesViewClient()); |
| 218 | + mWebView.setWebChromeClient(new WebChromeClient()); |
| 219 | + mWebView.loadUrl("https://developer.android.google.cn/kotlin", generateLanguageRequestHeader(this)); |
| 220 | + } |
| 221 | + |
| 222 | + public static class LanguagesViewClient extends WebViewClient { |
| 223 | + |
| 224 | + @TargetApi(Build.VERSION_CODES.N) |
| 225 | + @Override |
| 226 | + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { |
| 227 | + return shouldOverrideUrlLoading(view, request.getUrl().toString()); |
| 228 | + } |
| 229 | + |
| 230 | + @Override |
| 231 | + public boolean shouldOverrideUrlLoading(WebView view, String url) { |
| 232 | + String scheme = Uri.parse(url).getScheme(); |
| 233 | + if (scheme == null) { |
| 234 | + return false; |
| 235 | + } |
| 236 | + switch (scheme) { |
| 237 | + // If this is a link jump |
| 238 | + case "http": |
| 239 | + case "https": |
| 240 | + view.loadUrl(url, generateLanguageRequestHeader(view.getContext())); |
| 241 | + break; |
| 242 | + default: |
| 243 | + break; |
| 244 | + } |
| 245 | + return true; |
| 246 | + } |
| 247 | + } |
| 248 | + |
| 249 | + /** |
| 250 | + * Add language environment to WebView request header |
| 251 | + */ |
| 252 | + @NonNull |
| 253 | + public static Map<String, String> generateLanguageRequestHeader(Context context) { |
| 254 | + Map<String, String> map = new HashMap<>(1); |
| 255 | + // Solution for language failure on Android 13 |
| 256 | + // https://developer.android.com/about/versions/13/features/app-languages#consider-header |
| 257 | + map.put("Accept-Language", String.valueOf(MultiLanguages.getAppLanguage(context))); |
| 258 | + return map; |
| 259 | + } |
| 260 | +} |
| 261 | +``` |
| 262 | + |
| 263 | +#### Is There a Way to Switch Language Without Restarting |
| 264 | + |
| 265 | +* Let me ask everyone a question: once rice is cooked, how do you turn it back into raw rice? Obviously, this is unrealistic. Even if the framework could do it, and text and images could automatically change with the language, how would you switch the language for data requested via the network? Would you need to request again? If it's a list, would you need to request from page 1? Another question: is language switching a common action? I believe you already have the answer. |
| 266 | + |
| 267 | +* So it's not that switching language without restarting is impossible, but it's unnecessary (language switching is not a common action), and there are some inherent issues (even if the UI doesn't need to change, the data layer still needs to be re-requested). |
0 commit comments