最近的做的外销项目 涉及几十种语言
这些小语种在我看来跟乱码一样
翻译一般是由外包翻译公司翻译的
这里面就容易存在一些问题
问题1:
翻译的流程是 客户端开发写中文---翻译成英文----外包翻译根据英文字符串翻译小语种,在这个流程中,有些多义词和一些涉及语境的词就很容易翻译错误。
问题2:
前面说了,翻译公司提供回来的字符串我们都看不懂,错了也不知道,几乎都是上线之后,用户反馈过来,我们才晓得
因此小语种的翻译bug一直是项目里面比较多的一类bug
于是基于android的换肤方案改写了一套text的替换方案,原理基本相同。写给有小语种需求的朋友
流程
1:从独立的plugapk包中取出PlugResources资源
2:构建自己的TextResResources 实现getText等方法 将getText方法代理到PlugResources的getText
3:Application启动的时候将Application的mResources对象Hook掉并设置TextResResources对象
4:Activity启动的时候将Activity的mResources对象Hook掉并设置TextResResources对象
5:注册ActivtyLifecycleCallbacks 在onActivityCreated中对activity的LayoutInfater实现自己的Factory,在Factory中对text的Attribute的属性进行拦截并重新setText
上述的流程基本上其实就是一个换肤流程
说一下几点要注意的点
1:不管Hook的是Application还是Activity的mResources 一定是在attachBaseContext里面对baseContext进行Hook,直接将Activity或者Application本身进行hook是不成功的 因为Activity或者Application本身并不是Context,他只是一个ContextWapper。而ContextWapper中真正的Context其实就是在attachBaseContext时赋值的
2:我们对Activity或者Application的mResources进行了Hook,但是如果不实现流程5中的ActivtyLifecycleCallbacks,那么XML中编写的text无法实现替换,原因在于View使用TypedArray在进行赋值的时候,并不是直接使用mResources,而是直接使用mResourcesImpl,所以直接hooke了mResources还是没用,其实mResources的getText方法也是调用mResources中的mResourcesImpl的方法
再说一下使用过程中可能遇到的性能问题
1:因为在hook完成后,调用PlugResources的getText方法,要先从本地Resources中根据Id获取原资源的name和type,然后在使用name和type调用getIndentifier获取PlugResources中的resId,这个过程耗时较长,虽然也是纳秒级别的,但其耗时比不hook场景下高一个数据级,
2:使用sd卡中的plugapk包生成PlugResources,该过程耗时10-15ms