Android 多语言支持
添加多国语言文件
下面以添加 西班牙语 为例,首先在 res 右键 “new”,选择 “Values resource file”。
左侧选中 “Locale”,点击 “ >> ”,然后 “Chosen qualifiers” 面板中就会出现 “Locale” 这栏
西班牙语是 “es”,在 “Language” 面板中最开始是没有搜索框的,直接聚焦后输入,搜索框就会自动出现了。然后在右边的 “Specific Region Only” 面版中 选择 “Any Region”。
多语言表(转自 https://blog.csdn.net/u010586698/article/details/56673379)
语言 | 英语名称 | 中文名称 | 国家码 | 国标 | ||||
---|---|---|---|---|---|---|---|---|
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 |
实现方案:
- 通过数组存储字符串的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();
// }
// });//重启 ActivityIntent 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 {@Overrideprotected 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
attachBaseContext (转自 https://www.jianshu.com/p/94e0f9ab3f1d)
Android 多语言支持相关推荐
- Android多语言支持以及繁简转换
Android多语言支持以及繁简转换 Android自身就带有多语言支持.前一段时间需要做一个同时支持繁简体的APP,经过简单的搜索和探索,轻松解决了问题.并且写了一个简单的繁体到简单的转换类.分享给 ...
- Android平台语言支持状态
1.上表中的红色表示MTK新添加的语言,标记"N"表示当前版本不支持:标记"Y"表示mtk.google均支持:标记"GD_MN"表示Goo ...
- android 多个占位符,Android多语言支持:由于占位符计数不同导致的字符串格式问题...
我正在制作一个法语Android应用程序,我正在努力支持英语. 我使用"占位符"来格式化我的字符串,因此我可以将它们调整为男性和女性用户.例如,我的strings.xml文件中 ...
- Android多语言支持二
创建好的项目工程由于需求 需要做多国语言的支持 下面介绍怎么快捷的创建文件夹 建好一个android 的项目后,默认的res下面 有layout.values.drawable等目录 这些都是程序默 ...
- 默认语言及Android平台语言支持状态(印度语)Android N 设置中语言列表介绍
6.0及之前修改路径 device\company\{sub_project_name}/full_{sub_project_name}.mkc PRODUCT_LOCALES := es_US en ...
- Android开发笔记(八十三)多语言支持
汉字转拼音 app中有许多场景要对汉字排序,例如通讯录姓名.商品名称.城市名称等等,这些汉字词汇通常是按照拼音排序,所以产生了把汉字转换为拼音的需求. Android自带库 Android自带的联系人 ...
- android app支持多语言,支持多语言支持的Android应用程序
本文中,我们将学习如何构建支持(国际化和本地化)多种语言的Android APP .语言在应用程序的整体界面中起着至关重要的作用,如果您可以添加更多语言,以便您可以支持更广泛的受众,那么语言就非常棒. ...
- 关于Android应用多语言支持实现
多语言支持包含有两种情况:1. 程序本身提供有一个切换配置,可随时切换显示 2. 随系统的语言环境自动切换,也就是当更换系统显示语言设置时,软件也显示相应的语言版本. 第一种稍复杂些,本人没实现过,有 ...
- android语言列表+波斯,Android 多语言入门及实战
右键res,选择 New Resource Directory ,选择 locale ,选择自己想要适配的语言类型 设置应用内多语言 Android 7.0以下 /** * 设置多语言 */ publ ...
最新文章
- 量子计算机 漫画,漫画 | 10分钟看懂量子比特、量子计算和量子算法
- jQuery实例——仿京东仿淘宝列表导航菜单
- python利器怎么编程-C++和Python混合编程的利器
- 重磅推荐 | 11个名企NLP项目,硅谷科学家帮你转型
- mysql json invalid json text_MySQL 5.7新增加的json数据类型
- 全局搜索快捷键_Windows 自带的聚合搜索来了,与 Mac 的 Spotlight 相比体验如何?...
- spring boot自测_将测微仪与Spring Boot 2一起使用
- STRUTS2 标签调用静态方法
- android实现1000次点击,android – AdMob收入和替代方案:展示次数和点击次数[已关闭]...
- PHPwamp开发环境搭建详解
- java 对象转map,map转对象
- wp8 android,WP8桌面主题|WP8桌面v1.5.2 for Android版 - 玩客网
- 【荣耀内推】2023届荣耀校招开启啦
- X11 - X client数量达到上限并报错Maximum number of clients reachedxlsclients
- 苹果手机投影到墙上_实用派amp;小零碎:快充数据线、实木理线器、小电视支架、高清投影仪……...
- 多个tab页如何共享websocket
- 网站流量数据分析技巧【转】
- 当你同事工作出色时,如何得体地告知他上司
- SQL连接的理解和使用(内连接:自然连接等值连接,外连接:左连接右连接全外连接)
- ZT自老罗的博客 Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析...
热门文章
- 【Python数据分析学习笔记Day3】(三)数据分析工具pandas,数据清洗,聚类K-Means
- MySQL 数据库--存储引擎
- FDC2214电容检测芯片-液位检测(金属探针探测液面)方案分析
- 常用的八款免费程序员喜欢的代码编辑器推荐「你用哪个」
- kubectl describe命令详解
- 探访河北舌尖上的“美味”:留住传统 留住乡情
- 四旋翼无人机学习第2节--cadence工程创建与原理图的添加
- JavaScript函数中的arguments(js函数中的arguments,函数默认参数arguments)
- 3.4 Linux常用的转义字符
- 很全面的5G技术基础知识PPT(三)