添加多国语言文件

下面以添加 西班牙语 为例,首先在 res 右键 “new”,选择 “Values resource file”。

android 支持哪些语言 安卓支持的语言_xml

左侧选中 “Locale”,点击 “ >> ”,然后 “Chosen qualifiers” 面板中就会出现 “Locale” 这栏

android 支持哪些语言 安卓支持的语言_android 支持哪些语言_02


西班牙语是 “es”,在 “Language” 面板中最开始是没有搜索框的,直接聚焦后输入,搜索框就会自动出现了。然后在右边的 “Specific Region Only” 面版中 选择 “Any Region”。

android 支持哪些语言 安卓支持的语言_ci_03

多语言表(转自 )

语言

英语名称

中文名称

国家码

国标

Language

English Name

Chinese Name

Code

GB

ICS

JB

KK

L

العربية

Arabic(Israel)

阿拉伯语(以色列)

ar_IL

Y

Y

Y

Y

Y

Arabic(Egypt)

阿拉伯语(埃及)

ar_EG

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

中文

Chinese Simplified

中文简体

zh_CN

Y

Y

Y

Y

Y

中文

Chinese Tradition

中文繁体

zh_TW

Y

Y

Y

Y

Y

中文

Chinese

中文(香港)

zh_HK

N

N

P

P

Y

Nederlands

Dutch (Netherlands)

荷兰语

nl_NL

Y

Y

Y

Y

Y

Nederlands

Dutch (Netherlands)

荷兰语(比利时)

nl_BE

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English

English(United States)

英语(美国)

en_US

Y

Y

Y

Y

English

English(Australia)

英语(澳大利亚)

en_AU

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(Canada)

英语(加拿大)

en_CA

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(India)

英语(印度)

en_IN

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(Ireland)

英语(爱尔兰)

en_IE

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(New Zealand)

英语(新西兰)

en_NZ

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(Singapore)

英语(新加波)

en_SG

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(South Africa)

英语(南非)

en_ZA

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

English

English(United Kingdom)

英语(英国)

en_GB

GD_MN

GD_MN

GD_MN

Y

Y

Français

French

法语

fr_FR

Y

Y

Y

Y

Y

Français

French

法语(比利时)

fr_BE

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

Français

French

法语(加拿大)

fr_CA

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

Français

French

法语(瑞士)

fr_CH

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

Deutsch

German

德语

de_DE

Y

Y

Y

Y

Y

Deutsch

German

德语(列支敦斯登)

de_LI

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

Deutsch

German

德语(奥地利)

de_AT

GD_MN

GD_MN

GD_MN

Y

Y

Deutsch

German

德语(瑞士)

de_CH

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

Italiano

Italian

意大利语

it_IT

Y

Y

Y

Y

Y

Italiano

Italian

意大利语(瑞士)

it_CH

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

Protuguês

Portuguese

葡萄牙语(巴西)

Pt_BR

Y

Y

Y

Y

Y

Protuguês

Portuguese

葡萄牙语

Pt_PT

Y

Y

Y

Y

Y

Español

Spanish

西班牙语

es_ES

Y

Y

Y

Y

Y

Español

Spanish

西班牙语(美国)

es_US

GD_MN

GD_MN

P

Y

Y

বাংলা

Bengali

孟加拉语

bn_BD

Y

N

N

N

Y

বাংলা

Bengali

孟加拉语(印度)

bn_IN

Y

Y

Y

Y

Y

hrvatski

Croatian

克罗地亚语

hr_HR

GD_MN

GD_MN

P

Y

Y

čeština

Czech

捷克语

cs_CZ

Y

Y

Y

Y

Y

Dansk

Danish

丹麦语

da_DK

GD_MN

GD_MN

P

Y

Y

ελληνικά

Greek

希腊语

el_GR

GD_MN

Y

Y

Y

Y

עברית

Hebrew

希伯来语(以色列)

he_IL

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

עברית

Hebrew

希伯来语(以色列)

iw_IL

GD_MN

GD_MN

Y

Y

Y

हिंदी

Hindi

印度语

hi_IN

Y

Y

Y

Y

Y

Magyar

Hungarian

匈牙利语

hu_HU

GD_MN

Y

Y

Y

Y

Indonesian

印度尼西亚语

in_ID

Y

Y

Y

Y

Y

日本語の言語

Japanese

日语

ja_JP

GD_MN

GD_MN

P

P

Y

한국의

Korean

韩语(朝鲜语)

ko_KR

GD_MN

GD_MN

Y

Y

Y

Bahasa Melayu

Malay

马来语

ms_MY

Y

Y

Y

Y

Y

فارسی

Perisan

波斯语

fa_IR

Y

Y

Y

Y

Y

Polski

Polish

波兰语

Pl_PL

GD_MN

GD_MN

P

Y

Y

româna

Romanian

罗马尼亚语

ro_RO

GD_MN

Y

Y

Y

Y

Русский

Russian

俄罗斯语

ru_RU

Y

Y

Y

Y

Y

српски

Serbian

塞尔维亚语

sr_RS

GD_MN

GD_MN

P

P

Y

Svenska

Swedish

瑞典语

sv_SE

GD_MN

GD_MN

P

Y

Y

ไทย

Thai

泰语

th_TH

Y

Y

Y

Y

Y

Türkçe

Turkey

土耳其语

tr_TR

Y

Y

Y

Y

Y

اردو

Urdu

乌尔都语

ur_PK

Y

Y

Y

Y

Y

tiếng việt

Vietnamese

越南语

vi_VN

Y

Y

Y

Y

Y

catalá

Catalan

加泰隆语(西班牙)

ca_ES

GD_MN

GD_MN

P

P

Y

latviešu

Latviesu

拉脱维亚语

lv_LV

GD_MN

GD_MN

P

Y

Y

Lietuvių

Lithuanian

立陶宛语

lt_LT

GD_MN

GD_MN

P

Y

Y

Norsk bokmal

Norwegian

挪威语

Nb_NO

GD_MN

GD_MN

P

Y

Y

Slovenčina

slovencina

斯洛伐克语

sk_SK

GD_MN

GD_MN

P

Y

Y

Slovenščina

Slovenian

斯洛文尼亚语

sl_SI

GD_MN

GD_MN

P

P

Y

български

bulgarian

保加利亚语

bg_BG

GD_MN

GD_MN

P

Y

Y

українська

Ukrainian

乌克兰语

uk_UA

GD_MN

GD_MN

P

Y

Y

Tagalog

Filipino

菲律宾语

tl_PH

GD_MN

Y

Y

Y

Y

Suomi

Finnish

芬兰语

fi_FI

GD_MN

GD_MN

P

Y

Y

Afrikaans

Afrikaans

南非语

af_ZA

N

GD_MN

GD_MN

GD_MN

GD_MN

Rumantsch

Romansh

罗曼什语(瑞士)

rm_CH

GD_MN

GD_MN

GD_MN

GD_MN

GD_MN

ဗမာ

Burmese(Zawgyi)

缅甸语(民间)

my_ZG

N

N

P

P

Y

ဗမာ

Burmese(Paduak)

缅甸语(官方)

my_MM

N

N

Y

Y

Y

ខ្មែរ

Khmer

柬埔寨语

km_KH

N

N

Y

Y

Y

አማርኛ

Amharic

阿姆哈拉语(埃塞俄比亚)

am_ET

N

GD_MN

GD_MN

GD_MN

GD_MN

беларуская

Belarusian

白俄罗斯语

be_BY

N

GD_MN

GD_MN

GD_MN

GD_MN

eesti

Estonian

爱沙尼亚语

et_EE

N

GD_MN

P

P

Y

Kiswahili

Swahili

斯瓦希里语(坦桑尼亚)

sw_TZ

N

GD_MN

GD_MN

GD_MN

GD_MN

isiZulu

Zulu

祖鲁语(南非)

zu_ZA

N

GD_MN

GD_MN

GD_MN

GD_MN

azərbaycanca

Azerbaijani

阿塞拜疆语

az_AZ

N

N

N

GD_MN

GD_MN

Հայերէն

Armenian

亚美尼亚语(亚美尼亚)

hy_AM

N

N

P

P

Y

ქართული

Georgian

格鲁吉亚语(格鲁吉亚)

ka_GE

N

N

N

GD_MN

GD_MN

ລາວ

Laotian

老挝语(老挝)

lo_LA

N

N

N

GD_MN

GD_MN

Монгол

Mongolian

蒙古语

mn_MN

N

N

N

GD_MN

GD_MN

नेपाली

Nepali

尼泊尔语

ne_NP

N

N

N

GD_MN

GD_MN

қазақ тілі

Kazakh

哈萨克语

kk_KZ

N

N

P

P

Y

Galego

Galician

加利西亚语

gl-rES

N

N

N

N

GD_MN

íslenska

Icelandic

冰岛语

is-rIS

N

N

N

N

GD_MN

ಕನ್ನಡ

Kannada

坎纳达语

kn-rIN

N

N

N

N

GD_MN

кыргыз тили; قىرعىز تىلى

Kyrgyz

吉尔吉斯语

ky-rKG

N

N

N

N

GD_MN

മലയാളം

Malayalam

马拉亚拉姆语

ml-rIN

N

N

N

N

GD_MN

मराठी

Marathi

马拉提语/马拉地语

mr-rIN

N

N

N

N

GD_MN

தமிழ்

Tamil

泰米尔语

ta-rIN

N

N

N

N

GD_MN

македонски јазик

Macedonian

马其顿语

mk-rMK

N

N

N

N

GD_MN

తెలుగు

Telugu

泰卢固语

te-rIN

N

N

N

N

GD_MN

Ўзбек тили

Uzbek

乌兹别克语

uz-rUZ

N

N

N

N

GD_MN

Euskara

Basque

巴斯克语

eu-rES

N

N

N

N

GD_MN

සිංහල

Sinhala

僧加罗语(斯里兰卡)

si_LK

N

N

N

N

N

下面我做一个支持默认、中文、英文、西班牙语的实例

分别创建如下文件

android 支持哪些语言 安卓支持的语言_重启_04

实现方案:

  • 通过数组存储字符串的ID
    arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="language_ids">
        <item>@string/language_default</item>
        <item>@string/language_zh</item>
        <item>@string/language_en</item>
        <item>@string/language_es</item>
    </array>
</resources>
  • 切换语言的工具类(安卓7为分界,有两种不同的处理方案)
    LanguageUtil.java
public class LanguageUtil {
    private static final String SP_NAME = "LanguageSP";
    private static final String LANGUAGE_INDEX = "LanguageIndex";

    private static LanguageUtil instance;
    private Context context;
    private int[] languageIds;

    public static LanguageUtil getInstance(Context context) {
        if (instance == null) {
            instance = new LanguageUtil(context);
        } else {
            instance.context  = context;
        }
        return instance;
    }

    private LanguageUtil(Context context) {
        this.context = context;
        final Resources resources = context.getResources();
        TypedArray ta = resources.obtainTypedArray(R.array.language_ids);

        languageIds = new int[ta.length()];
        for (byte i = 0; i < ta.length(); i++) {
            languageIds[i] = ta.getResourceId(i, 0);
        }
    }

    /**
     * 获取语言的字符串数组
     */
    private String[] getLanguages() {
        final String[] languages = new String[languageIds.length];
        for (byte i = 0; i < languageIds.length; i++) {
            languages[i] = context.getString(languageIds[i]);
        }
        return languages;
    }

    /**
     * 根据索引拿到国际化区域类
     */
    private Locale getLocale(int index) {
        Locale locale;
        switch(languageIds[index]) {
            case R.string.language_en:
                locale = Locale.ENGLISH;
                break;
            case R.string.language_es:
                locale = new Locale("es");
                break;
            case R.string.language_zh:
                locale = Locale.CHINA;
                break;
            default:
                if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    locale = LocaleList.getDefault().get(0);
                } else {
                    locale = Locale.getDefault();
                }
                break;
        }
        return locale;
    }

    /**
     * 在 API 24(Android 7.0)后需要在重启后替换 Context 才能切换语言
     * ContextWrapper中提供了attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象,调用ContextWrapper的方法都会被转向其所包含的真正的Context对象
     */
    private Context attachBaseContext(int index) {
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        Locale locale = getLocale(index);
        configuration.setLocale(locale);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            configuration.setLocale(locale);
            context = context.createConfigurationContext(configuration);
        } else {
            DisplayMetrics dm = resources.getDisplayMetrics();
            resources.updateConfiguration(configuration, dm);
        }
        return context;
    }

    /**
     * 重启 Activity
     */
    private void recreate(final Activity activity) {
//        activity.runOnUiThread(new Runnable() {
//            @Override
//            public void run() {
//重启 Activity(这个方法一定要在主线程中被调用)
//注意:recreate 这个方法有的问题,有时候会闪屏,就是一个界面跳两次出来
//recreate之后不能finish,会崩溃
//                activity.recreate();
//            }
//        });

        //重启 Activity
        Intent intent = new Intent(context, activity.getClass());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        activity.startActivity(intent);
        activity.finish();
    }

    private void saveIndexToPreference(int index) {
        SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor et = sp.edit();
        et.putInt(LANGUAGE_INDEX, index);
        et.commit();
    }

    private int getIndexFromPreference() {
        SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        return sp.getInt(LANGUAGE_INDEX, 0);
    }

    public void changeLanguage(int index, Activity activity) {
        saveIndexToPreference(index);
        attachBaseContext(index);
        recreate(activity);
    }
    
    /**
     * 每次Activity启动时都会去寻找默认的语言配置,所以必须在分配Context之前进行预处理,修改成你所需要的配置。
     * 这个预处理方法就是 attachBaseContent
     */
    public Context restoreLanguage() {
        int index = getIndexFromPreference();
        return attachBaseContext(index);
    }
}
  • 所有Activity都必须继承一个基类,在基类的 attachBaseContext 方法中切换语言
    BaseInternationalActivity.java
public abstract class BaseInternationalActivity extends AppCompatActivity {

    @Override
    protected void attachBaseContext(Context newBase) {
        newBase= LanguageUtil.getInstance(newBase).restoreLanguage();
        super.attachBaseContext(newBase);
    }
}

注意事项

上面的方法只会更新 activity 的 context,对于 application 和 service 的 context 并不会被改变。
虽然 application 和 service 也有 attachBaseContext,只会在初次打开时被替换。
而且这里只用了 activity.recreate() 影响的只会是当前的 Activity, 其它的 activity 启动的时候还是使用默认的 context。

所以如果要用到 service 里面的 context,我的做法是 比如在 bind 的时候重新设置它的context

android 支持哪些语言 安卓支持的语言_xml_05


Context类本身是一个纯abstract类,它有两个具体的实现子类:ContextImpl和ContextWrapper。其中ContextWrapper类,如其名所言,这只是一个包装而已,ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper中提供了attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象,调用ContextWrapper的方法都会被转向其所包含的真正的Context对象。