Skip to content

Latest commit

 

History

History
224 lines (167 loc) · 9.37 KB

HelpDoc.md

File metadata and controls

224 lines (167 loc) · 9.37 KB

目录

如何设置 App 默认的语种

  • 在从来没有调用过 MultiLanguages.setAppLanguage 的情况下,又不想让应用跟随系统的语种,而是想指定某个语种该怎么做?具体写法示例如下:
public final class XxxApplication extends Application {

    static {
        // 设置默认的语种(越早设置越好)
        MultiLanguages.setDefaultLanguage(LocaleContract.getEnglishLocale());
    }
}
  • 当然你如果想判断当前的系统语种类型,然后再设置默认的语种,可以这样写:
public final class XxxApplication extends Application {

    @Override
    protected void attachBaseContext(Context newBase) {
        if (newBase != null) {
            Locale systemLanguage = MultiLanguages.getSystemLanguage(newBase);
            // 如果当前语种既不是中文(包含简体和繁体)和英语(包含美式英式等),就默认设置成英文的,避免跟随系统语种
            if (!MultiLanguages.equalsLanguage(systemLanguage, LocaleContract.getChineseLocale()) &&
                    !MultiLanguages.equalsLanguage(systemLanguage, LocaleContract.getEnglishLocale())) {
                MultiLanguages.setDefaultLanguage(LocaleContract.getEnglishLocale());
            }
        }
        // 绑定语种
        super.attachBaseContext(MultiLanguages.attach(newBase));
    }
}

切换语种后没有任何效果该怎么办

  • 情况一:可以检查一下是否在 build.gradle 文件中配置了仅保留某个国家的语种资源,例如 resConfigs 'zh' 就代表只保留和中文相关的语种资源,而其他国家的语种资源就不会被打包进 apk 包中,这样就会导致在切换语种的时候始终都是中文的尴尬局面。

  • 情况二:如果是 Fragment 里面的语种切换之后没有变化,请检查 Fragment 在 Activity 重启之后是否被复用了,一般情况下是调用了 fragment.setRetainInstance(true) 导致的。

  • 情况三:如果是上架 GooglePlay 或者华为的 aab 包后,上架成功后再下载发现切换不了 App 语种,那是因为在分包的时候导致多语言资源缺失了,这时候需要对主模块的 build.gradle 文件进行配置,具体用法可以参考官方文档

android {

    ......

    bundle {

        ......

        language {
            enableSplit = false
        }

        ......
    }
}
  • 其他情况:如果不是以上原因造成的,请提一个 issue 给到我处理。

怎么在切换语种后应用到所有 Activity 上

  • 在 Application 的 onCreate 方法中加入以下代码
MultiLanguages.setOnLanguageListener(new OnLanguageListener() {

    @Override
    public void onAppLocaleChange(Locale oldLocale, Locale newLocale) {
        Log.i("MultiLanguages", "监听到应用切换了语种,旧语种:" + oldLocale + ",新语种:" + newLocale);
        // 如需在系统切换语种后应用也要随之变化的,可以在这里获取所有的 Activity 并调用它的 recreate 方法
        // getAllActivity 只是演示代码,需要自行替换成项目已实现的方法,若项目中没有,请自行封装
        List<Activity> activityList = getAllActivity();
        for (Activity activity : activityList) {
            activity.recreate();
        }
    }

    @Override
    public void onSystemLocaleChange(Locale oldLocale, Locale newLocale) {
        Log.i("MultiLanguages", "监听到系统切换了语种,旧语种:" + oldLocale + ",新语种:" + newLocale +
                ",是否跟随系统:" + MultiLanguages.isSystemLanguage());
    }
});

怎么在用户切换系统语种的时候重启 App

  • 在 Application 的 onCreate 方法中加入以下代码
MultiLanguages.setOnLanguageListener(new OnLanguageListener() {

    @Override
    public void onAppLocaleChange(Locale oldLocale, Locale newLocale) {
        Log.i("MultiLanguages", "监听到应用切换了语种,旧语种:" + oldLocale + ",新语种:" + newLocale);
    }

    @Override
    public void onSystemLocaleChange(Locale oldLocale, Locale newLocale) {
        Log.i("MultiLanguages", "监听到系统切换了语种,旧语种:" + oldLocale + ",新语种:" + newLocale +
                ",是否跟随系统:" + MultiLanguages.isSystemLanguage());
        // 如需在系统切换语种后应用也要随之变化的,可以在这里获取所有的 Activity 并调用它的 recreate 方法
        // getAllActivity 只是演示代码,需要自行替换成项目已实现的方法,若项目中没有,请自行封装
        List<Activity> activityList = getAllActivity();
        for (Activity activity : activityList) {
            activity.recreate();
        }
    }
});

WebView 导致语种失效的解决方案

  • 由于 WebView 初始化会修改 Activity 语种配置,间接导致 Activity 语种会被还原回去,所以需要你手动重写 WebView 对这个问题进行修复
public final class LanguagesWebView extends WebView {

    public LanguagesWebView(@NonNull Context context) {
        this(context, null);
    }

    public LanguagesWebView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, android.R.attr.webViewStyle);
    }

    public LanguagesWebView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        // 修复 WebView 初始化时会修改 Activity 语种配置的问题
        MultiLanguages.updateAppLanguage(context);
    }
}

Android 13 WebView 语种失效怎么办

  • webView.loadUrl(@NonNull String url) 替换成 webView.loadUrl(@NonNull String url, @NonNull Map<String, String> additionalHttpHeaders),并添加 Accept-Language 请求头即可,具体的示例代码如下:
public final class MainActivity extends Activity {

    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mWebView = findViewById(R.id.wv_main_web);

        mWebView.setWebViewClient(new LanguagesViewClient());
        mWebView.setWebChromeClient(new WebChromeClient());
        mWebView.loadUrl("https://developer.android.google.cn/kotlin", generateLanguageRequestHeader(this));
    }

    public static class LanguagesViewClient extends WebViewClient {

        @TargetApi(Build.VERSION_CODES.N)
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            return shouldOverrideUrlLoading(view, request.getUrl().toString());
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            String scheme = Uri.parse(url).getScheme();
            if (scheme == null) {
                return false;
            }
            switch (scheme) {
                // 如果这是跳链接操作
                case "http":
                case "https":
                    view.loadUrl(url, generateLanguageRequestHeader(view.getContext()));
                    break;
                default:
                    break;
            }
            return true;
        }
    }

    /**
     * 给 WebView 请求头添加语种环境
     */
    @NonNull
    public static Map<String, String> generateLanguageRequestHeader(Context context) {
        Map<String, String> map = new HashMap<>(1);
        // Android 13 上面语种失效的问题解决方案
        // https://developer.android.google.cn/about/versions/13/features/app-languages?hl=zh-cn#consider-header
        map.put("Accept-Language", String.valueOf(MultiLanguages.getAppLanguage(context)));
        return map;
    }
}

有没有一种不用通过重启的方式来切换语种

  • 我先问大家一个问题,生米煮成熟饭了,怎么从熟饭变成生米?这显然是不现实的,退一万步讲,假设框架能做到,文字和图片都能自动跟随语种的变化而变化,那么通过接口请求的数据又怎么切换语种?是不是得重新请求?如果是列表数据是不是得从第 1 页开始请求?再问大家一个问题,还有语种切换是一个常用动作吗?我相信大家此时心里已经有了答案。

  • 所以并不是做不到不用重启的效果,而是没有那个必要(切语种不是常用动作),并且存在一定的硬伤(虽然 UI 层不用动,但是数据层还是要重新请求)。