起因:

项目中适配了中英文语言,在切换英文语言重启软件后,部分已适配多语言的文字显示中文,在同一个Activity中有的正常,有的却不正常。

探究:

一开始以为哪里设置文字的时候没有去适配,于是开始整个项目搜素还是没找到,心中一万个草**跑过,于是乎来到百度搜索,果然有人遇到类似的问题,然后开始慢慢探究...

起初是在Application中 写了一个Toast 弹出一段从资源文件定义的文字,当软件语言设置为英文后,重启后弹出的确是中文,而在进入到主界面后默认是英文,而部分文字后续更新后也是中文,真是见了鬼了,两部分调用的都是同一个方法啊:

    public final String getString(@StringRes int resId) {
        return getResources().getString(resId);
    }

难道 getResources() 不是同一个对象?于是我就在Application 中 和 Activity中打印了两个getResources()的hashcode:

Android 应用内切换语言 出现中英文混乱问题_App


确实不一样,然后又在这两个地方验证了Local信息,调用代码如下:

  public static Locale getAppLocale(Context context) {
        //获取应用语言
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        Locale locale = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            locale = configuration.getLocales().get(0);
            Log.i("App-TAG", "getAppLocale: " + locale.getLanguage() + " " + locale.getCountry());
        } else {
            locale = configuration.locale;
        }
        return locale;
    }

输出:

Android 应用内切换语言 出现中英文混乱问题_App_02

小黑子,露出鸡脚了吧,竟然获取的默认Local不一致!

看来调用系统接口返回的也不一定准确啊,那么有什么好的解决方法吗?


解决:

既然系统接口获取的不准确,那就找到一个获取准确Local的方法就行了

Locale appLocale = new Locale("en")

使用该方式可以获取具体语言准确的Local,当然我们不能硬编码,可以在你切换语言的时候将 getLanguage() 持久化一下,在用的时候从缓存中拿就可以了。

为了确保万无一失,在Application 和 BaseActivity中 重写  attachBaseContext 方法,在方法中都要设置一下:

Application 和 BaseActivity中:

    @Override
    protected void attachBaseContext(Context base) {
        Log.i("TAG", "attachBaseContext");
        super.attachBaseContext(MultiLanguageUtil.attachBaseContext(base));
    }

MultiLanguageUtil 类相关代码:

public static Context attachBaseContext(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return createConfigurationResources(context);
        } else {
            setConfiguration(context);
            return context;
        }
    }

    @TargetApi(Build.VERSION_CODES.N)
    private static Context createConfigurationResources(Context context) {
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();

        //如果本地有语言信息,以本地为主,如果本地没有使用默认Locale
        Locale locale = null;
        String spLanguage = SpUtil.getString(context, ConstantGlobal.LOCALE_LANGUAGE);
        String spCountry = SpUtil.getString(context, ConstantGlobal.LOCALE_COUNTRY);

        Locale appLocale = new Locale(spLanguage);//getAppLocale(context);
        if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {
            if (isSameLocal(appLocale, spLanguage, spCountry)) {
                locale = appLocale;
            } else {
                locale = new Locale(spLanguage, spCountry);
            }
        } else {
            locale = appLocale;
        }

        configuration.setLocale(locale);
        configuration.setLocales(new LocaleList(locale));

        return context.createConfigurationContext(configuration);
    }

    public static void setConfiguration(Context context) {
        Locale appLocale = getAppLocale(context);

        //如果本地有语言信息,以本地为主,如果本地没有使用默认Locale
        Locale locale = null;
        String spLanguage = SpUtil.getString(context, ConstantGlobal.LOCALE_LANGUAGE);
        String spCountry = SpUtil.getString(context, ConstantGlobal.LOCALE_COUNTRY);

        if (!TextUtils.isEmpty(spLanguage) && !TextUtils.isEmpty(spCountry)) {
            if (isSameLocal(appLocale, spLanguage, spCountry)) {
                locale = appLocale;
            } else {
                locale = new Locale(spLanguage, spCountry);
            }
        } else {
            locale = appLocale;
        }

        Configuration configuration = context.getResources().getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(locale);
        } else {
            configuration.locale = locale;
        }
        Resources resources = context.getResources();
        DisplayMetrics dm = resources.getDisplayMetrics();
        resources.updateConfiguration(configuration, dm);//语言更换生效的代码!
    }