Android国际化方案实践总结

背景:项目已经基于模块化的方式上线,原项目由于之前赶进度等原因,部分代码中直接插入中文,现需要国际化。

国际化所需要做的事情:

  • 用户系统(国内外手机号的注册)
  • 语言切换

用户系统

这个客户端需要实现的就是注册的支持,

  1. 从服务端拉取‘国家’与‘区号码’,经用户选择,获取验证码,提交服务端处理,问题不大。
  2. 测试验证的话,有开源平台支持国外验证码的获取,可Google。

字符串翻译

重点说下语言切换的思路以及需要注意的点:

  1. 将代码中的中文转移到String文件中,AS快捷键option + enter自动将代码中的字符串转成String资源。

2.创建一个String_module的library模块,将所有strings.xml文件中的资源copy到String_module中,经脚本去重后,进行翻译。

  1. 所有需要翻译字符串的所在模块均添加对String_module的依赖。

  2. 对于Activity/Fragment直接引用String_module的string.xml文件的资源。

  3. 在接口内,我们在实现中传递给接口一个context即可。

  4. class或常量中,我们在String_module中定义一个基于applicationContext的弱引用的context全部变量,添加getString()方法。

internal var globalSharedResourceContext: WeakReference? = null

fun initGlobalShareResourceContext(context: Application){
    globalSharedResourceContext = WeakReference(context.applicationContext)
}

至此,所有翻译的工作已全部完成。

语言切换

语言切换首先需要明确是否跟随系统。其次本地需要维护App的系统语言的环境变量,可以用SP存储,服务端肯定也要保存一份。

Android系统的语言切换是通过去更新resourcesconfiguration来实现的(对于Activity最终是会触发onConfigurationChanged方法),那么我们肯定需要去获取resources对象,然后生成一个新的configuration去更新就好了。代码如下:

fun updateResourceLocale(context:Context, locale:Locale){
    val newConfig = context.resources.configuration
    if (locale != newConfig.locale){
        newConfig.locale = locale
        context.resources.updateConfiguration(newConfig, resources.displayMetrics)
    }
}

我们知道,获取resource一般通过context去获取,而一个App的context数量是:activity数量 + service数量 + 1(applicationContext),一个context对应获取一个Resource对象(实际是以弱引用的方式管理resource的对象),要修改我们只需要对每个有context对象的Activity/Service/Application去重新修改一些configration就可以。

我们可以将实现封装在BaseActivity中。在基础模块中维护一个模块的全局变量,记录当前App的语言,然后维护该变量修改App的语言以达到我们想要的需求。

Android详细系统语言切换过程分析可参考1 2 3

最后,有一个AS自动化插件AndroidLocalizationer,有兴趣可以了解一下。

你可能感兴趣的:(Android国际化方案实践总结)