Android-國際化(多語言)切換詳解及例項

weixin_34321977發表於2017-10-17

internationalization(國際化)簡稱 i18n,因為在i和n之間還有18個字元,localization(本地化),簡稱L10n。

一.原理:

Android中實現國際化相對來說還是簡單的,因為Android有很獨特的資源管理方式。程式碼可以不和資源發生關係,我們通常通過 R 檔案提供的索引來間接的引用某一個資源。

把顯示的字串都轉換成檔案資源,再用程式碼程式碼提取,也就是把字串儲存在對應的values目錄下。


二.實現步驟:

國際化切換可以手動國際化,也可以一鍵國際化。

1.手動國際化
為支援多國語言,在res/中建立一個額外的values目錄以連字元和ISO國家程式碼結尾命名,比如values-es/是為語言程式碼為"es"的區域設定的簡單的資原始檔的目錄。Android會在執行時根據裝置的區域設定,載入相應的資源。
以中英文切換為例:
如果預設是中文就不用建立相應的values檔案了,因為系統找不到對應的資源直接會走預設的。
(1).首先建立一個values資原始檔values-en/放進對應的strings.xml。

2787891-0999ff2dbadfaab1

新增不同區域語言的字串值到相應的檔案就可以了。

(2).UI顯示字串用程式碼提取:
生成對應的string檔案不用每個都改,這樣很麻煩,教大家一個簡單方法如下:

2787891-7c2bb5692b585eea

這樣直接就生成了string.xml,直接去改相應的字串就好了。

2.一鍵國際化
如果需要很多語言的時候,手動的切換很麻煩。這時需要用到Android Studio外掛:AndroidLocalizationer,它可以實現一鍵國際化。
使用方法:
(1).下載AndroidLocalizationer外掛
下載地址:
https://github.com/westlinkin/AndroidLocalizationer
(2).整合到Android studio中。

2787891-501815ac132ff520

整合成功之後重啟。
(3).使用
2787891-7683b8c6b425ed13

2787891-aef9845567932a2f

根據你的需要來選擇對應的語言
結果如下:
2787891-6fc8a6ac93f2e0fb

附加:這個外掛還是有些不穩定的地方,有的Android Studio版本是不支援此外掛的。


二.國際化實現例項

2787891-c85dc5c99cbfbe92

1.配置資原始檔,這個在前面已經講過了。
2.封裝一個ContextWrapper類
ContextWrapper建構函式中必須包含一個真正的Context引用,同時ContextWrapper中提供了attachBaseContext()用於給ContextWrapper物件中指定真正的Context物件,呼叫ContextWrapper的方法都會被轉向其所包含的真正的Context物件。

public class MyContextWrapper extends ContextWrapper {

    public MyContextWrapper(Context base) {
        super(base);
    }

    @SuppressWarnings("deprecation")
    public static ContextWrapper wrap(Context context, String language) {
        Configuration config = context.getResources().getConfiguration();
        Locale sysLocale = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            sysLocale = getSystemLocale(config);
        } else {
            sysLocale = getSystemLocaleLegacy(config);
        }
        if (!language.equals("") && !sysLocale.getLanguage().equals(language)) {
            Locale locale = new Locale(language);
            Locale.setDefault(locale);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                setSystemLocale(config, locale);
            } else {
                setSystemLocaleLegacy(config, locale);
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                context = context.createConfigurationContext(config);
            } else {
                context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
            }
        }
        return new MyContextWrapper(context);
    }

    @SuppressWarnings("deprecation")
    public static Locale getSystemLocaleLegacy(Configuration config){
        return config.locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static Locale getSystemLocale(Configuration config){
        return config.getLocales().get(0);
    }

    @SuppressWarnings("deprecation")
    public static void setSystemLocaleLegacy(Configuration config, Locale locale){
        config.locale = locale;
    }

    @TargetApi(Build.VERSION_CODES.N)
    public static void setSystemLocale(Configuration config, Locale locale){
        config.setLocale(locale);
    }
}

3.attachBaseContext實現

@Override
protected void attachBaseContext(Context newBase) {
    //Public.Language 為 對應的資源格式字尾,比如"zh"      "
    super.attachBaseContext(MyContextWrapper.wrap(newBase, Public.Language));
}

如果想要整個APP都實現國際化,直接把attachBaseContext寫在封裝好的BaseActivity裡。
4.呼叫

//動態改變字尾名,可以存在本地資料中,方法比較多就不細說了。Public.Language="zh";
recreate();

其中recreate();是Android3.0以後引入的。

希望大家支援下我的公眾號:

2787891-ef00a53190d04286

相關文章