Android国际化入门

国际化

支持不同语言,在不同的国家都可以使用。

本文将会介绍如下节点:

  • 实现 string 资源的国际化

  • 简繁体切换实现

  • 在现有业务上,做国际化遇到的一些问题

string 资源的国际化实现

在 Android 开发规范中,我们一般不建议在代码或者布局文件中 hard code 我们 string 字符串,而是需要将这些字符串放在单独的 string.xml 文件。

  • 错误示例

错误示例

  • 正确的姿势

正确的姿势

2.实现步骤

2.1 创建语言区域目录

在 res/ 文件中创建对应国家或者地区资源文件,具体如下

  • 创建语言区域目录

res/value-ISO语言代码

  • res/value 默认的语言目录
  • res/value-zh 表示中国
  • res/value-zh-rHK 表示中国香港
  • res/value-zh-rTW 表示中国台湾
  • res/value-zh-rMO 表示中国澳门
  • res/value-es 表示美国

本文演示的是中文简体和繁体的国际化,所以下面展示的是中国台湾,香港繁体和中文简体。

创建语言区域目录和字符串文件

2.2 创建语言区域目录对应的字符串文件

默认的 res/value/strings.xml

<resources>
    <string name="text">纸短情长-默认</string>
</resources>

res/value-zh-rHK/strings.xml

<resources>
    <string name="text">紙短情長-HK</string>
</resources>

res/value-zh-rTW/strings.xml

<resources>
    <string name="text">紙短情長-TW</string>
</resources>

2.3 应用资源文件

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/text"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

2.4 测试

在这里调节不同的语言环境就可以看到加载不同的资源文件了。

3. 简繁体切换实现

本地的语言环境是简体,但是我们在需要在应用动态读取繁体资源。这种操作意味着去更新应用的 Configuration 配置信息。

3.1 操作步骤

  • 获取一个需要转化的 Locale 对象
  • 读取 Configuration 配置信息
  • 修改locale为目标locale
  • 更新configuration
  • 重启Activity

**注意:**当修改 Configuration 之后,需要调用Activity#recreate() 方法重新创建 activity 。

3.2 简体转繁体

/**
 * 简体转繁体
 *
 * @param view
 */
public void s2t(View view) {
    // 本地语言设置
    // 获取一个需要转化的 Locale 对象
    Locale myLocale = Locale.TAIWAN;
    Resources res = getResources();
    DisplayMetrics dm = res.getDisplayMetrics();
    //读取 Configuration 配置信息
    Configuration conf = res.getConfiguration();
    //修改locale为目标locale
    conf.locale = myLocale;
    //更新configuration
    res.updateConfiguration(conf, dm);
    //重启Activity
    recreate();
}

3.3 繁体转简体

/**
 * 繁体转简体
 *
 * @param view
 */
public void t2s(View view) {
    // 本地语言设置
    Locale myLocale = Locale.CHINESE;
    Resources res = getResources();
    DisplayMetrics dm = res.getDisplayMetrics();
    Configuration conf = res.getConfiguration();
    conf.locale = myLocale;
    res.updateConfiguration(conf, dm);
    //重启Activity
    recreate();
}

4. 在现有业务上,做国际化遇到的一些问题

一般的应用在开发初期只会针对国内用户进行开发,也就是一般不会去做国际化,当我们应用发展到一定的规模之后就需要往海外市场拓展。

下面就会有一个这样需求,就是在当前的简体中文版基础上开发一个繁体中文版。需要国际化,就需要解决以下几个问题:

  • 服务端接口是简体中文。

4.1 服务端接口国际化

因为时间比较赶,无法让服务端去修改接口,所以只能在客户端获取到接口数据之后,在进行简繁体转换。

因为项目使用是 OKHTTP 网络请求框架,因此我们使用拦截器的方式拦截返回的响应 Response 对象,修改返回内容来实现接口数据国际化。

  • 定义拦截器

在这里定义的拦截器中是 Application Interceptor 拦截器。放在 OKHTTP 拦截器自带拦截器之前,也就是说在这个拦截器得到的响应就是网络请求得到数据的响应,因此在这里修改响应内容即可。

注意在读取 final String content = response.body().string(); 之后,对应的流会被关闭,那么这时上层获取到 Response 之后,在调用 body().string()就会报错,因此我们在读取数据,并转化为繁体之后,需要构造一个新的 ResponseBody 给 Response 即可。

public class Simple2TraditionChineseInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());

        if (response.body() != null && response.body().contentType() != null) {

            final MediaType mediaType = response.body().contentType();

            final String content = response.body().string();

            String convertResult = content;


            JChineseConvertor jChineseConvertor = JChineseConvertor

                    .getInstance();

            //将简体数据转化为繁体
            try {
                final String convertToTraditionalChinese = jChineseConvertor.s2t(content);
                if (!TextUtils.isEmpty(convertToTraditionalChinese)) {
                    convertResult = convertToTraditionalChinese;
                }
            } catch (Exception e) {
                //当转化异常时,使用默认返回的数据
                Logger.e("接口返回数据转化失败");
                e.printStackTrace();
            }

            //构造一个新的ResponseBody,因为 response.body().string() 调用之后会把流关闭,因此这里要新建。
            ResponseBody responseBody = ResponseBody.create(mediaType, convertResult);

            response = response.newBuilder().body(responseBody).build();
        }
        return response;
    }
}
  • 配置拦截器
public static OkHttpClient getClient() {
    if (client == null) {
        synchronized (HttpUtils.class){
            if (client==null) {
                OkHttpClient.Builder builder = new OkHttpClient.Builder();
                builder.connectTimeout(CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
                builder.readTimeout(READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
                builder.writeTimeout(WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
                builder.addInterceptor(new ReportInterceptor());   // 添加上报接口性能
                //判断是否对接口进行简繁体转换
                if (LiveCore.isShowTraditionalChinese()) {
                    builder.addInterceptor(new Simple2TraditionChineseInterceptor());   // 国际化
                }
                client = builder.build();
            }
        }
    }
    return client;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值