语言切换适配

前言

拿来主义而已, 也很感谢创作者的分享精神,开源有益,共同进步才能走得更远,

旧版

旧版本仅适配API28以下版本
高版本环境 AS会提示 Deprecated


/*
    * 过时 App中维护
    * 注释:
    * @author maqi
    * created at 2021/12/15 11:39
    * */
    @Deprecated("")
    private fun switchLanguage() {
        val language = xxx//SP获取
        //设置应用语言类型
        val resources = resources
        val config = resources.configuration
        val dm = resources.displayMetrics
        if (0 == language) {
            config.locale = Locale.CHINESE
        } else if (1 == language) {
            config.locale = Locale.ENGLISH
        } else /*第一次进入  取系统环境 */ {
            config.locale = Locale.getDefault()
        }
        resources.updateConfiguration(config, dm)
    }

新版工具类

仔细看了下区别并不大,主要是作者的思路很完整,加之工具封装,故笔者稍作修改,并给出使用方法,以及需要注意的其他地方,这里会给出笔者踩过的坑,看大家是不是也会遇到。

public final class LocaleUtils {

    private static final String FILE_NAME = "key_language_file";
    private static final String KEY_LANGUAGE = "key_language";
    private static final String KEY_COUNTRY = "key_country";

    /**
     * 获取手机系统的Locale
     *
     * @return
     */
    public static Locale getSystemLocale() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return LocaleList.getDefault().get(0);
        }
        return Locale.getDefault();
    }

    /**
     * 设置 App 的Locale
     *
     * @param context
     * @param loc
     * @return
     */
    public static void setAppLocale(Context context, Locale loc) {
        if (loc != null) {
            setUserSetLocale(context, loc);

            Resources rs = context.getResources();
            Configuration config = rs.getConfiguration();
            DisplayMetrics dm = rs.getDisplayMetrics();
            if (Build.VERSION.SDK_INT >= 17) {
                config.setLocale(loc);
            } else {
                config.locale = loc;
            }
            context.getResources().updateConfiguration(config, dm);
        }
    }

    /**
     * 在activity 的  onResume or onConfigChange中调用此方法
     * http://www.jianshu.com/p/47bbd34d2af8
     *
     * @param context
     * @param loc
     */
    public static void setLocaleWhenConfigChange(Context context, Locale loc) {
        if (loc != null) {
            Resources rs = context.getResources();
            Configuration config = rs.getConfiguration();
            DisplayMetrics dm = rs.getDisplayMetrics();
            if (Build.VERSION.SDK_INT >= 17) {
                config.setLocale(loc);
            } else {
                config.locale = loc;
            }
            context.getResources().updateConfiguration(config, dm);
        }
    }

    /**
     * 获取App Locale
     *
     * @param context
     * @return
     */
    public static Locale getAppLocale(Context context) {
        Configuration config = context.getResources().getConfiguration();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
            return config.getLocales().get(0);
        else
            return config.locale;
    }

    /**
     * 获取用户设置的Locale
     *
     * @param context
     * @return
     */
    public static Locale getUserSetLocale(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        String lang = sp.getString(KEY_LANGUAGE, "");
        String country = sp.getString(KEY_COUNTRY, "");
        Log.d("language", "getUserSetLocale " + "lang     " + lang + "    country     " + country);
        if (!TextUtils.isEmpty(lang) /*&& !TextUtils.isEmpty(country)*/) {
            return new Locale(lang, country);
        } else {
            return null;
        }
    }

    /**
     * 返回 en_US 格式
     *
     * @param context
     * @return
     */
    public static String getUserSetLocaleStr(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        String lang = sp.getString(KEY_LANGUAGE, "");
        String country = sp.getString(KEY_COUNTRY, "");
        if (!TextUtils.isEmpty(lang) && !TextUtils.isEmpty(country)) {
            return String.format("%s_%s", lang, country);
        }
        return "";
    }

    /**
     * 清空设置,跟随系统
     *
     * @param context
     */
    public static void removeLocaleSet(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
        final SharedPreferences.Editor edit = sp.edit();
        edit.putString(KEY_LANGUAGE, "");
        edit.putString(KEY_COUNTRY, "");
        edit.apply();
    }

    /**
     * 用户设置的Locale
     */
   public static void setUserSetLocale(Context context, Locale locale) {
        if (locale != null) {
            try {
                SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);
                final SharedPreferences.Editor edit = sp.edit();
                edit.putString(KEY_LANGUAGE, locale.getLanguage());
                edit.putString(KEY_COUNTRY, locale.getCountry());
                edit.apply();
            } catch (Exception e) {
            }
        }
    }
}
使用方式
  • Applicationoncreat中先设置好
 /*设置系统语言*/
        val isFirstOpenComplete = SharePreferenceUtil.getFirstOpenComplete(MainApp.getContext()!!)
        if (isFirstOpenComplete) {
            val sysLocale = LocaleUtils.getSystemLocale()
            val appLocale = LocaleUtils.getAppLocale(this)
            val userLocale = LocaleUtils.getUserSetLocale(this)
            Log.d(TAG, "sysLocale  " + sysLocale)
            Log.d(TAG, "appLocale  " + appLocale)
            Log.d(TAG, "userLocale  " + userLocale)
        } else {
            val userSet = LocaleUtils.getSystemLocale()
            val language = userSet?.language ?: ""
            val country = userSet?.country ?: ""
            Log.d("language", "language     $language      country     $country")
            if (language == Locale.CHINESE.language) {
                LocaleUtils.setAppLocale(this, Locale.CHINESE)
            } else {
              LocaleUtils.setAppLocale(this, Locale.ENGLISH)
            }
        }
  • 在BaseActivity的oncreate中使用,不要在Application中的registerActivityLifecycleCallbacks中使用,试过了不行.
  • requireActivity().finish()重建或者requireActivity().recreate()都是能生效的,与启动模式launchMode无关
 /*
    * API>29后 新版语言切换
    * 注释:
    * @author maqi
    * created at 2021/12/15 16:41
    * */
    private fun changeLanguage() {
        val userSetLocale = LocaleUtils.getUserSetLocale(this)
        val language = userSetLocale?.language?:""
        val country = userSetLocale?.country?:""
        Log.d("language", "reset    $language   country  $country   userSetLocale   $userSetLocale") 
        LocaleUtils.setAppLocale(this, userSetLocale)
    }
  • 语言切换以用户设置为主
    代码同上
  • 恢复出厂设置以系统设置为主,
    Locale userSet = LocaleUtils.getSystemLocale();
    String language = userSet.getLanguage();
    String country = userSet.getCountry();
	Log.d("language", "language    " + language + "   country  " + country + "   userSet   " + userSet.toString());
    LocaleUtils.setUserSetLocale(this, userSet)
  • 大多数情况,getAppLocale是不用的,因为在setAppLocale后如果恢复出厂设置调用getAppLocale的话会获取到上次设置的语言
注意事项
  • 获取固定语言
    该函数乍一看很简洁方便,其实配合之前的 LocaleUtils.setAppLocale 会出现语言混乱的情况
public String getStringInDefaultLocale(Locale local, int resId) {
   Resources currentResources = mContext.getResources();
   AssetManager assets = currentResources.getAssets();
   DisplayMetrics metrics = currentResources.getDisplayMetrics();
   Configuration config = new Configuration(currentResources.getConfiguration());
   config.locale = local;
   Resources defaultLocaleResources = new Resources(assets, metrics, config);
   String string = defaultLocaleResources.getString(resId);
   return string;
}

//使用
/*目的:维持原语言*/
String english = getStringInDefaultLocale(Locale.ENGLISH, R.string.language_english);
String china = getStringInDefaultLocale(Locale.CHINESE, R.string.language_china);

解决:直接在strings-zh或者strings-en中写同样的翻译,正常使用setText(resID)
<string name="language_china_other">简体中文</string>

  • Locale.CHINESE & Locale.CHINA,Locale.ENGLISH与Locale.US
    setUserSetLocalegetUserSetLocale时需要注意country为空的判断后使用
其他
  1. 获取语言失败现象,始终为 en,如下反射键盘流获取最稳, LocaleList.getDefault().get(0)概率性出错
  2. 如图:
    获取失败
  3. 解决:
  /**
     * 获取手机系统的Locale
     *
     * @return
     */
    public static Locale getSystemLocale() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            String displayLanguage = Locale.getDefault().getDisplayLanguage();

            PackageManager packageManager = MainApp.Companion.getContext().getPackageManager();
            Resources resources = null;
            try {
                resources = packageManager.getResourcesForApplication("android");
            } catch (PackageManager.NameNotFoundException e) {
            }
            Locale Syslocale = resources.getConfiguration().getLocales().get(0);
            String packageManagerLanguage = Syslocale.getLanguage();

            InputMethodManager imm = (InputMethodManager) MainApp.Companion.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            InputMethodSubtype ims = imm.getCurrentInputMethodSubtype();
            String immlocale = ims.getLocale();

            //displayLanguage      English        packageManagerLanguage     zh        immlocale      zh_CN
            LocaleList aDefault = LocaleList.getDefault();
            Log.d("language", "--------------------xxx-----"
                    + "        displayLanguage      " + displayLanguage
                    + "        packageManagerLanguage     " + packageManagerLanguage
                    + "        immlocale      " + immlocale);
            for (int i = 0; i < aDefault.size(); i++) {
                Locale locale = aDefault.get(i);
                Log.d("language", "getSystemLocale   " + i + "    " + locale.getLanguage()
                        + "   country  " + locale.getCountry()
                );
            }
//            return LocaleList.getDefault().get(0);
            return Syslocale;
        }
        return Locale.getDefault();
    }
  1. 参考链接:
    https://www.codenong.com/4212320/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值