Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android App 国际化

Android App 国际化

原创
作者头像
QQ音乐技术团队
修改于 2017-11-01 01:39:42
修改于 2017-11-01 01:39:42
5K01
代码可运行
举报
运行总次数:1
代码可运行

前言

internationalization (国际化)简称 i18n,因为在i和n之间还有18个字符,localization(本地化),简称L10n。一般用语言_地区的形式表示一种语言,如zh_CN表示简体中文。Android 对i18n和L10n提供了非常好的支持。Android没有专门的API来提供国际化,而是通过对不同resource的命名来达到国际化的目的,同时这种命名方法还可用于对硬件的区分,如不同的屏幕分辨率用不同的图片。我们引用这些resource时,在java代码中是通过R.resource_type.resource_name的方式来使用,如R.string.title,在xml中直接引用,如@ string/title引用了名字为title的字符串。values表示默认的资源文件夹,即当Resource找不到匹配的资源时,会使用values文件夹下的资源。文件夹的命名必须都是小写字符,否则在一些大小写敏感的文件系统中可能会出错。

本文主要介绍Android App国际化过程中遇到的问题和解决方案。

1.整理HardCode

App国际化是要在保持App原功能不变的情况下,主要对字符串进行替换。一般在涉及字符串的位置都要在strings.xml里面设置对应的item,方便后续的修改和复用,其他语言只需要新建values_xx(xx表示国家代号)资源文件夹,系统会自动进行替换。但是经常一个项目由多位同事参与,每个人的编程习惯会有异同,在xml或者java文件中会有遗漏的硬编码(HardCode),因此第一步是整理项目中的硬编码,统一归并到strings.xml中。

Android Studio是Google官方推荐的Android IDE,拥有很多强大的功能。利用集成的Lint工具,可以将项目中大部分的HardCode搜索出来。首先建立一份模板文件,进入Preferences > Inspections,新建一份Profile

然后自定义名称,主要用于检测HardCode,以后可以根据需要自由切换Profile。

在下面的勾选框中选择Android > Lint > Internationailization > Hardcoded text 和 TextView Internationailization两项,颜色是黄色,表示在代码中会以黄色来提醒。

然后由Lint进行代码分析,选择Analyze > Inspect Code,选择自己的项目,选择之前保存的Inspection模板

检测之后,Hardcoded text可以扫描出xml中出现的HardCode代码

TextView Internationailization可以扫描出setText的问题,而这种问题主要分两种.

第一种是直接插入字符串,第二种是拼接字符串。

细心的同学会发现最上面的setText("我的测试")并没有被标记出来,这也是Lint的一个问题所在。

这个情况可以通过正则表达式来搜索,搜索setText(.*"),需要注意对括号进行转义。

这下可以找到所有的setText。下面是几点注意事项

  1. 间接使用setText。我们有时候不会直接使用setText,而是在基类里对setText进行封装,比如显示页面的顶部名字方法setTitleName,Lint不会对这种间接使用setText的情况进行提示,可以借助Annotations来帮助Lint排查问题。在方法参数中添加@ StringRes来限制传入的参数必须是本地资源中的字符串的资源id,同时需要将旧方法删除,不要让两者并存。其他类型的资源如图片、尺寸、颜色等,也分别可以添加 @ DrawableRes, @ DimenRes, @ ColorRes来限制。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitleName("首页");//旧方法
        setTitleName(R.string.app_name);//新方法
        setTitleName(111);//报错的方法
    }

    public void setTitleName(String res)
    {
        tx2.setText(res);
    }

    public void setTitleName(@StringRes int ResID)
    {
        tx2.setText(getResources().getString(ResID));
    }
  1. 占位符。有些业务需求是要将动态信息和静态信息拼接起来,开发的时候有时嫌麻烦,就直接通过+号连接字符串了,这是不好的编程习惯,违反App国际化规范。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String name = "张三";
int age = 21;
tx2.setText("名字是"+name+",年龄是"+age+"的用户");//不规范用法
tx2.setText(String.format("名字是%s,年龄是%d的用户",name,age));//规范用法

需要注意的是这个格式不能直接粘贴在strings.xml中,需要修改格式将%替换为$,并添加上参数位置,如拼接的第一个参数是%1$s,%1表示第一个位置的变量, $s表示为字符串类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  <string name="info">名字是%1$s,年龄是%2$d的用户</string>
  1. 转义字符。字符串中有时候会出现特殊字符,这类特殊字符在xml中需要转义,下面是一些常用的特殊字符转义之后的样

符号

转义表示

" 或 "

' 或 '

&

& 或 &

<

< 或 <

>

> 或 >

换行

\n

2.Strings.xml > Excel

现在已经整理好了strings.xml文件,下一步就是让专业的翻译人员翻译对应的语言。其实直接提供strings.xml文件就可以了,但是这样不容易进行去重、统计、整理,一般整理出excel文档比较合适。比较直接的方法可以直接将内容复制到excel文档中

然后利用替换功能,可以将<string name="</string>>这三段文字依次替换为空(顺序不能变),得到如下状态

然后利用excel的分列功能,以"为分隔符

可以将内容分为两列

对于重复项的问题,我们采取的方案是以待翻译的文字作为关键字,保持唯一性。先对字段进行排序

然后找出重复的字符串,还是利用excel的功能在C1处插入公式=IF(COUNTIF(B$1:B1,B1)>1,"重复","")

得到的界面如下

将标记重复的字段在java或xml代码中找到引用的地方,替换成重复字段第一次出现的name(这也是刚才要排序的原因,可以在excel中直接找到第一次出现的name),最后在strings.xml中删除。

再利用excel的去重功能,选择 数据 > 删除重复项,以待翻译字段所在列为查重列,可以得到最终的结果

可以将得到文档提交给专业的翻译团队了。

3.Excel > Strings.xml

得到翻译好的的excel文档之后

依旧可以借助excel的拼接功能,在D1输入拼接语句="<string name="&""""&A1&""""&">"&C1&"</string>",可以生成符合strings.xml中格式要求的内容

下拉统一格式,所有的都可以自动拼接

最后在项目中的res目录下创建各自的资源文件夹,右击res文件夹 > New > Android resource directory

选择Locale

例如选择的英语,会得到如下的文件夹

然后将前面整理好的各国语言的strings.xml放到对应的目录下即可。

4.语言切换

App国际化在应用内部需要设置语言切换的功能,修改语言的功能如图所示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Resources resources = getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
Configuration config = resources.getConfiguration();
// 应用用户选择语言
config.locale = Locale.US;
resources.updateConfiguration(config, dm);

但是修改之后应用并不会自动刷新界面。有如下几种方式解决问题

1 .重写onConfigurationChanged方法,在AndroidManifest.xml里面设置android:configChanges="locale",Configuration发生变化时会调用该方法,和文字有关的控件需要在这里重新刷新。界面元素太多的情况下,这种方式会很繁琐。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
 public void onConfigurationChanged(Configuration newConfig) {
     button.setText(R.string.second);//需要刷新的控件
     super.onConfigurationChanged(newConfig);
 }

采用recreate方法,注册一个语言被修改的监听,回退到其他界面的时候需要刷新界面,recreate方法可以刷新Activity,比正常启动Activity多调用了onSaveInstanceState和onRestoreInstanceState,而且是Android3.0以后的api,界面也会有明显的闪屏现象。

一般修改语言界面都在比较深的操作中,上述两种方式是修改语言之后直接刷新当前界面,另一种方式是重新从主界面进入,对应的实现方式就是清空之前的堆栈信息,直接跳到主界面,微信中修改语言之后的界面效果也是如此。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();

为了保证用户设置成功后重新启动应用时,保存的语言依然生效,要对用户的选择语言进行持久化保存,一般是通过SharedPreferences来保存,重新启动应用时在Application的onCreate()方法中就要读取保存的语言信息,修改Configuration。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public class MyApplication extends Application {
  @Override
    public void onCreate() {
        super.onCreate();
        LanguageUtil.applyUserLocale();
    }
 }

还有一种情况,应用在后台运行,用户切换了系统的语言,会影响Configuration。模拟一个场景,系统语言是中文,应用语言初始化是系统语言中文,修改应用语言为日文,发现主界面变成日文,回到桌面,再进入系统设置,修改系统语言为英文,这时再返回应用,应用显示英文,这个和应用功能违背,应该以应用语言为主。为了解决这种情况,一般在基类BaseActivity里面添加逻辑判断,目前应用语言是否和系统语言相同,如果不同就以应用语言为主,相同就跳过。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class BaseActivity extends Activity {
@Override
    public void onCreate() {
        super.onCreate();
        if(!LanguageUtil.isEqualSystem())
            LanguageUtil.setUserLocaleCoverSystem();
    }
}

5.界面适配

导入英文strings.xml之后,界面肯定会有很多错乱的地方,原因各种各样。下面仅根据项目中出现的情况,总结出大部分App都会出现的一些问题。

位置问题。最早的产品原型中可能不会考虑到国际化的需求,很多控件的布局写成固定值,英文不适用于之前的设计,所以出现错位、遮挡、显示不全等现象。在不影响视觉的情况下,可以对位置参数进行微调,如果区别十分明显,可以将固定值改为代码中动态获取,或者将固定值存在values_en的dimens.xml中。 英文过长。中英文之间的翻译存在长度的不确定性,有时会出现换行的现象。从翻译的角度来看,可以让翻译团队根据所属界面的特殊性来重新翻译,尽量控制在一定字符以内。也可以尝试使用英文缩写(这个适用性比较低,只适用于比较流行的词语,否则容易产生歧义),或者将高宽的固定值改成wrap_content,或者调整字体大小,同样需要在values_en的dimens.xml中记录。 按钮文字全部变成大写。纯文本信息的按钮在中文情况下是正常显示,但是setText纯英文之后内容自动变成了大写。以Theme.AppCompat.Light.DarkActionBar主题为例。跟踪源码可发现,该主题中有:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<style name="Base.TextAppearance.AppCompat.Button">
        <item name="android:textSize">@dimen/abc_text_size_button_material</item>
        <item name="textAllCaps">true</item>
        <item name="android:textColor">?android:textColorPrimary</item>
</style>

关键的原因在于:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<item name="textAllCaps">true</item>

解决方法可以在项目的自定义主题中修改如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="textAllCaps">false</item>
</style>

或者为具体的Button控件设置如下属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Button
    android:id="@+id/btn_answer1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAllCaps="false"
    />

App国际化适配界面的工作“因App而异”,更多的内容需要一个个界面进行调整,没有完整的通用方法。遇到特殊情况,需要和产品交流,可能需要修改普通版的原有功能,也有可能屏蔽国际版中的一些功能,要有所取舍。总之整个过程需要多方的参与和沟通,才能有效迅速的达到国际化效果。

总结

Android App国际化的工作并没有太多的技术难度,更多的是一些繁琐的文本处理。如何利用自动化的工具来解放人工操作,如何从看似杂乱无章的内容中寻找出规律,如何改善自己的编程规范,才是真正能从这个过程中学习到的东西。当然我只是列举了部分情况,不同的项目都会对应着不同的特例,很难面面俱到,仍然需要不断的摸索。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Windows Server 上安装EMQX
EMQ X是中国杭州一家科技公司(公司名叫EMQ)发布的面向5G和物联网市场的消息与流处理开源软件。2013年,EMQ 作为一个开源项目在Github: https://github.com/emqx/emqx 上发布,目前已成为全球市场广泛应用的开源MQTT消息服务器。 EMQ X Broker是基于Apache License 2.0开放源码的发布订阅模式一款mqtt服务器,基于高并发的 Erlang/OTP 语言平台开发,支持百万级连接和分布式集群架构。支持MQTT5.0 、高并发低时延、扩展模块与插件、跨平台安装部署,在全球物联网市场广泛应用。无论是产品原型设计、物联网创业公司、还是大规模的商业部署,EMQ X Broker 都支持开源免费使用。
张善友
2025/04/28
3570
Windows Server 上安装EMQX
如何在树莓派4B上安装EMQ X Broker
跟师新生命的创始人大石头玩树莓派下的.NET Core有几个月时间了,一直想从零开始写一些入门的东西,但看了淘宝、京东还有哔哩哔哩等平台上很多入门的教程了,就一直没动手。
崔文远TroyCui
2020/07/21
1.8K0
初识EMQX与安装
EMQ X 基于 Erlang/OTP 平台开发的 MQTT 消息服务器,是开源社区中最流行的 MQTT 消息服务器。EMQ X 是开源百万级分布式 MQTT 消息服务器(MQTT Messaging Broker),用于支持各种接入标准 MQTT 协议的设备,实现从设备端到服务器端的消息传递,以及从服务器端到设备端的设备控制消息转发。从而实现物联 网设备的数据采集,和对设备的操作和控制。
叫我阿杰好了
2022/11/07
4.8K0
初识EMQX与安装
亿级万物互联新时代的物联网消息中间件 EMQX 调研
最近去某餐厅吃饭,进门时智能门自动打开房门同时来一句"欢迎光临",然后伸手到门口的洗手台,水管无接触自动出水,端起菜盘走向台子选择自己喜欢的菜品,最后将菜盘放在智能结账机上,智能结账机通过图形识别算法识别到选了什么菜,然后计算出应该付多少钱,最后小编摘下口罩刷一刷人脸钱就付过去了,整个过程无需其他人的参与,也无需带任何物品包含手机。可能你也已经感受到了,我们身边越来越多的硬件设备正在被嵌入芯片、注入软件,从而实现各种各样的新应用、新功能,比如智能门锁,智能音箱等,前几年炒的火热的智能家居,物联网万物互联等概念,现在正在潜移默化的影响着所有人,了解一些物联网知识对我们了解这个新时代有所帮助。
宋小生
2022/11/28
1.1K0
亿级万物互联新时代的物联网消息中间件 EMQX 调研
EMQ X | 百万级的开源MQTT消息服务器(搭建一个私有MQTT服务器)
EMQ X 全称 Erlang/Enterprise/Elastic MQTT Broker,它是基于 Erlang/OTP 语言平台开发,支持大规模连接和分布式集群,发布订阅模式的百万级开源 MQTT 消息服务器。
Mculover666
2020/07/16
17.2K0
EMQ X | 百万级的开源MQTT消息服务器(搭建一个私有MQTT服务器)
Java物联网开发(二) —— 开源百万级分布式 MQTT 消息服务器EMQX
Mnesia 数据库是 Erlang 内置的一个分布式 DBMS,可以直接存储 Erlang 的各种数据结构 EMQ X 使用 Mnesia 数据库存储自身运行数据,例如告警记录、规则引擎已创建的资源和规则、Dashbaord用户信息等数据,这些数据都将被存储在 mnesia 目录下,因此一旦删除该目录,将导致 EMQ X 丢失所有业务数据。可以通过 emqx_ctl mnesia 命令查询 EMQ X 中 Mnesia 数据库的系统信息。
时间静止不是简史
2021/08/12
8.2K0
Java物联网开发(二) —— 开源百万级分布式 MQTT 消息服务器EMQX
MQTT服务器部署
现在物联网常用的通信方式有哪些?RF433/315M、蓝牙、Zigbee、wifi、以太网等等,通信协议也按不同功能分了许多种,例如TCP、MQTT等,具体可到https://blog.csdn.net/sinat_36098122/article/details/80930168 研究。我当前用的比较多的是MQTT协议,它被较多的用来需要省电的设备通信上,采用发布/订阅的形式传输消息,具体可参考https://www.cnblogs.com/skullboyer/p/9085210.html。 要使用MQTT通信,就少不了MQTT服务器,它是消息传送的中转站(代理)。也就是说MQTT服务器并不存储消息,消息的发布与接收都由客户端完成。我主要写一下目前也是较流行的两者MQTT服务器的搭建:EMQ和Mosquitto。这两种服务器都是开源的,这里写的是部署在windows服务器上的方法(没办法菜鸟只能搞win,以后再玩玩Linux)。
全栈程序员站长
2022/08/24
7.2K0
MQTT服务器部署
EMQX vs VerneMQ | 2023 MQTT Broker 对比
EMQX 和 VerneMQ 都是用 Erlang/OTP 开发的高性能、分布式开源 MQTT Broker,以其稳定性、容错性和扩展性著称。
EMQ映云科技
2023/04/21
7810
EMQX从搭建到作用于MQTT
​ 1. 协议与实现:MQTT 是一种协议,定义了消息发布、订阅、分发的标准;而 EMQX 是基于此协议实现的消息代理服务。EMQX 支持 MQTT 3.1、3.1.1 和 5.0 版本的协议。
一只牛博
2025/05/31
3820
EMQX从搭建到作用于MQTT
从零开始上手 MQTT over QUIC:快速体验下一代物联网标准协议
QUIC(RFC9000) 是下一代互联网协议 HTTP/3 的底层传输协议,与 TCP/TLS 协议相比,它在减少连接开销与消息延迟的同时,为现代移动互联网提供了有效灵活的传输层。
EMQ映云科技
2022/11/28
1.4K0
EMQ X + ClickHouse 实现物联网数据接入与分析
物联网数据采集涉及到大量设备接入、海量的数据传输,EMQ X 物联网消息中间件 与 ClickHouse 联机分析 (OLAP) 数据库的组合技术栈完全能够胜任物联网数据采集传输与存储、分析处理业务。
小晨说数据
2022/03/10
2K0
EMQ X + ClickHouse 实现物联网数据接入与分析
EMQX vs NanoMQ | 2023 MQTT Broker 对比
EMQX 和 NanoMQ 都是由全球领先的开源物联网数据基础设施软件供应商 EMQ 开发的开源 MQTT Broker。
EMQ映云科技
2023/04/19
1.6K0
EMQ百万级MQTT消息服务(介绍和搭建)
先上节了解完MQTT之后我们需要选择一个MQTT服务端,在MQTT官方推荐下找了找最后选择了使用EMQ来进行服务端实现,EMQ有什么优势可以在官方推荐的那么多的服务器实现中脱颖而出,本章就来和大家一起慢慢了解EMQ相关的特性 附上: 喵了个咪的博客:w-blog.cn EMQ官方地址:http://emqtt.com/ EMQ中文文档:http://emqtt.com/docs/v2/guide.html 1.EMQ EMQ (Erlang/Enterprise/Elastic MQTT Broker) 是
喵了个咪233
2018/04/17
2.9K0
EMQ百万级MQTT消息服务(介绍和搭建)
基于内网穿透技术的无公网IP环境下EMQX开源MQTT服务器远程访问方法
随着物联网技术的飞速发展,MQTT协议在智能设备间的信息传递中越来越吃香。而EMQX作为一款高性能、可扩展且稳定的开源MQTT消息服务器,简直是众多开发者心中的‘香饽饽’。但问题来了,如何在远程环境下轻松控制这些MQTT服务器呢?别担心,cpolar这款内网穿透神器能帮你轻松搞定!本文将带你一起探索,如何用EMQX和cpolar实现MQTT的远程连接。
命运之光
2025/04/18
2570
基于内网穿透技术的无公网IP环境下EMQX开源MQTT服务器远程访问方法
EMQX vs Mosquitto | 2023 MQTT Broker 对比
物联网开发者需要为自己的物联网项目选择合适的 MQTT 消息产品或服务,从而构建可靠高效的基础数据层,保障上层物联网业务。目前市面上有很多开源的 MQTT 产品,在性能功能等方面各有优点。本文将选取目前最为流行的两个开源 MQTT Broker:EMQX 和 Mosquitto,从技术架构、性能、功能、社区情况等多维度进行 1v1 对比,帮助读者更加深入了解这两个产品。
EMQ映云科技
2023/04/21
3.2K0
EMQX 5.0 发布:单集群支持 1 亿 MQTT 连接的开源物联网消息服务器
近日,全球领先的开源物联网数据基础设施软件供应商 EMQ 映云科技宣布,旗下核心产品开源分布式物联网 MQTT 消息服务器 EMQX 5.0 版本正式发布!
EMQ映云科技
2022/07/07
1.3K0
EMQX基础功能
EMQ X Dashboard 是一个 Web 应用程序,你可以直接通过浏览器来访问它,无需安装任何其他软件。 当 EMQX 成功运行在你的本地计算机上且 EMQX Dashboard 被默认启用时,通过访问 http://localhost:18083 来查看Dashboard,默认用户名是 admin ,密码是 public 。
叫我阿杰好了
2022/11/07
6.5K0
EMQX基础功能
EMQX+Prometheus+Grafana:MQTT 数据可视化监控实践
作为一款全球下载量超千万的大规模分布式物联网 MQTT 服务器,最新发布的 EMQX 5.0 不仅全球首个达成单集群 1 亿 MQTT 连接支持,也是首个将 QUIC 引入 MQTT 的开创性产品。如今,EMQX 在各个行业为高可靠、高性能的物联网实时数据移动、处理和集成提供着动力,助力企业构建关键业务的 IoT 应用。
EMQ映云科技
2022/12/12
2.3K0
非GO--物联网平台emqx和mqtt在Vue和Nodejs里面的使用
MQTT(Message Queuing Telemetry Transport)是一种轻量级的通信协议,专为物联网设备和应用程序之间的通信而设计。它是一种发布/订阅模式的协议,允许设备和应用程序通过一个中间代理(broker)进行通信。
言志志
2023/11/09
9910
非GO--物联网平台emqx和mqtt在Vue和Nodejs里面的使用
如何在 Google Cloud 上部署 EMQX 企业版
Google Cloud 的 IoT Core 产品将于 2023 年 8 月 16 日停止服务,随着这一日期的临近,许多用户正在为他们现有的物联网业务寻找新的解决方案,而 EMQX 企业版是实现这一目标的理想选择。
EMQ映云科技
2023/04/19
3.2K0
推荐阅读
相关推荐
Windows Server 上安装EMQX
更多 >
交个朋友
加入[架构及运维] 腾讯云技术交流站
云架构设计 云运维最佳实践
加入前端工作实战群
前端工程化实践 组件库开发经验分享
加入架构与运维趋势交流群
技术趋势前瞻 架构演进方向
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验