Home Android多语言的适配总结
Post
Cancel

Android多语言的适配总结

前言

前段时间在做多语言功能时,发现适配起来相当麻烦,不得不感慨android版本发布得越来越快了。本文就来总结一下多语言的适配问题。

多语言适配

android 7.0之后,语言设置偏好支持添加多个语言,而且在应用中activity的语言默认是跟随系统的。因此,在设置多语言时,大概有以下几步:

  1. 修改语言配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    public static void changeLanguage(Context context, Locale locale) {
            Configuration configuration = context.getResources().getConfiguration();
            DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
       
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                //这部分逻辑应该可以省略
                LocaleList localeList = new LocaleList(locale);
                configuration.setLocales(localeList);
                context.createConfigurationContext(configuration);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                configuration.setLocale(locale);
                context.getResources().updateConfiguration(configuration, displayMetrics);
            } else {
                configuration.locale = locale;
                context.getResources().updateConfiguration(configuration, displayMetrics);
            }
            SharedPreferencesUtils.setParam(context, FILENAME, APP_LANGUAGE, locale.getLanguage());
    }
    
  2. 7.0之后修改context

    7.0之后,activity的语言设置默认是跟随系统的。因此不管在第一步怎么设置,对7.0之后的系统都没有用。

    所以,需要在activity.attachBaseContext时更新这个context,添加上语言信息:

    1
    2
    3
    4
    5
    6
    7
    
    override fun attachBaseContext(newBase: Context) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                super.attachBaseContext(LanguageUtil.wrapperContext(newBase))
            } else {
                super.attachBaseContext(newBase)
            }
    }
    

    wrapperContext的逻辑是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    @TargetApi(24)
    public static Context wrapperContext(Context context) {
            Locale locale = currentLocale(context);
            Configuration configuration = context.getResources().getConfiguration();
            configuration.setLocale(locale);
            LocaleList localeList = new LocaleList(locale);
            LocaleList.setDefault(localeList);
            configuration.setLocales(localeList);
            return context.createConfigurationContext(configuration);
    }
    

    通过context.createConfigurationContext(configuration)得到一个新的包含语言信息的context给到activity,来实现语言的设置。

    在7.0之后,需要自己保存用户设置的语言信息。如上面例子中的currentLocale方法,逻辑如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    public static Locale currentLocale(Context context) {
        	//这里就保存了用户设置的语言信息
            String language = (String) SharedPreferencesUtils.getParam(context, FILENAME, APP_LANGUAGE, "");
            if (TextUtils.isEmpty(language)) {
                //如果没有设置,就获取系统的默认语言
                language = getDefaultLocale().getLanguage();
            }
            return getLocaleBy(language);
    }
       
    public static Locale getDefaultLocale() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                //7.0有多语言设置获取顶部的语言
                return Resources.getSystem().getConfiguration().getLocales().get(0);
            } else {
                return Locale.getDefault();
            }
    }
    
  3. 重启所有的activity

    设置完语言之后,需要重启创建activity才能加载设置的语言。

This post is licensed under CC BY 4.0 by the author.