美文网首页学习Android技术知识Android知识
Android通过代码实现多语言切换

Android通过代码实现多语言切换

作者: JarvanMo | 来源:发表于2017-05-20 16:31 被阅读1020次

    前言

    最近接手一个Android项目,需要实现对维吾尔族语的支持。虽然做了这么久的android开发,只做过多语言支持,但做应用内部多语言支持还是第一次,而且还是对维吾尔语的支持。所以,又是一次面向搜索引擎编程。

    面向搜索编程

    如果我们搜索“android 多语言切换”,我相信得到大部分的答案是千篇一律的,连文章都长的一样:

    Locale locale = new Locale("zh");
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
    

    以上代码应该说没什么大问题,毕竟确实可以工作,可以实现需求。但是,作为一个强迫症患者,我实际受不了有2处划线的地方,也就是说上面代码中有2处被废弃了(没错,API 25被废弃的):

     config.locale = locale;
     getBaseContext().getResources().updateConfiguration(config, 
     getBaseContext().getResources().getDisplayMetrics());
    

    看到有2处被废弃了,必须进去看看啊。

    /**
         * Current user preference for the locale, corresponding to
         * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a>
         * resource qualifier.
         *
         * @deprecated Do not set or read this directly. Use {@link #getLocales()} and
         * {@link #setLocales(LocaleList)}. If only the primary locale is needed,
         * <code>getLocales().get(0)</code> is now the preferred accessor.
         */
        @Deprecated public Locale locale;
    

    很显然我们找到了替代方法:

    config.setLocales(LocaleList);
    config.setLocale(locale);
    

    很好,没问题。继续查看下一个:

        /**
         * Store the newly updated configuration.
         *
         * @deprecated See {@link android.content.Context#createConfigurationContext(Configuration)}.
         */
        @Deprecated
        public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
            updateConfiguration(config, metrics, null);
        }
    

    很简单嘛,代替方法也找到了哦。于是就这么写了下去:

        Locale locale = new Locale("ug");
        final Resources res = getResources();
        final Configuration config = res.getConfiguration();
        config.setLocale(locale); // getLocale() should return a Locale
        createConfigurationContext(config);
    

    完全不好用!怎么写就是不好用。再仔细一看,文档上说createConfigurationContext(config)会返回一个新的Context,然而对新Context如何处理只字未提。又是一番面向搜索编程,终于找到了正确姿势:

        @Override
        protected void attachBaseContext(Context newBase) {
            Locale locale = new Locale("ug");
            final Resources res = newBase.getResources();
            final Configuration config = res.getConfiguration();
            config.setLocale(locale); // getLocale() should return a Locale
            final Context newContext = newBase.createConfigurationContext(config);
            super.attachBaseContext(newContext);
        }
    

    我们的Activity应该重写这个方法。然后当Activity被创建的时候,新的Context将被应用。需要注意的,如果你想让当前Activity生效,你需要调用recreate()

    当然啦,我们也可以写个工具类:

    public class ConfigurationWrapper {
        private ConfigurationWrapper() {
        }
    
        public static Context wrapConfiguration(@NonNull final Context context, @NonNull final Configuration config) {
            return context.createConfigurationContext(config);
        }
     
        
        public static Context wrapLocale(@NonNull final Context context,@NonNull final Locale locale) {
            final Resources res = context.getResources();
            final Configuration config = res.getConfiguration();
            config.setLocale(locale);
            return wrapConfiguration(context, config);
        }
    }
    

    然后你就可以这样使用。如果你想更改configuration,就可以用wrapConfiguration

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(ConfigurationWrapper.wrapLocale(newContext, getLocale()));
    }
    

    关于Locale

    实现多语言切换用到了Locale。Locale里很多常见国家和地区以及语言,如果我们做常见的语言,可以直接调用系统的,比如Locale.CHINESE。但是这次做的维吾尔语的适配,略我坑一下。
    首先,维吾尔语的英文名字叫Uyghur。Locale里并没有,也可能是我找的不对。
    其次,Uyghur是阿拉伯系的。嗯,没错,有个词叫RTL,会出现神奇的东西。
    最后,AndroidStudio的values里面是有Uyghur选项的。并且有相对应选项,其中就包括中国,我猜这就是维吾尔语。所以就建了一个,全名是:values-ug-rCN
    问题是,我最开始直接这样写的:

     Locale locale = new Locale("ug-rCN");
    

    好吧,是我太天真,不好用。机智的我看了看Locale的构造方法。后来猜了一个结论

    ug代表语种,rCN代表国家和地区。比如说同样都是中文zh,但分了很多国家和地区,如中国,台湾,香港以及新家坡等
    

    所以下面的写法才是正确姿势:

    结束

    相关文章

      网友评论

      本文标题:Android通过代码实现多语言切换

      本文链接:https://www.haomeiwen.com/subject/vldpxxtx.html