背景
通常公司里做国际化翻译管理的时候都会搭建一个Web应用去编辑管理翻译内容,最后在使用程序生成相应的语言包,我们也一样这么做。原来是生成JavaScript语言包,现在也要使用同样的数据生成Java语言包给Java项目使用。这样做有个好处就是所有的翻译资源统一管理,然后通过读取统一的数据源生成相应的语言包给开发使用,确保它们的翻译内容无论在那个程序语言里都是通用的。
想法
所有的翻译内容最终会生成一个i18n.json文件,然后JavaScript和Java去解析这个json文件即可,所以i18n.json相当于一个翻译内容的文件数据库,它的内容结果如下:
i18n.json
{
"NAME": {
"zh": "名字",
"en": "Name"
},
"CITY": {
"zh": "城市",
"en": "City"
},
"AGE": {
"zh": "年龄",
"en": "Age"
}
}
这个json文件里定义了一堆唯一的Key,每个Key里分别包含zh
和en
翻译文本,于是我想出了在Java里可以定义一个枚举类型包含所有的Key值,大概如下:
public enum Keys {
AGE,
NAME,
CITY;
}
然后我假设暴露一个API给用户通过Key获取翻译内容
public String get(Keys key) {
...
}
让用户使用枚举类型获取翻译文本有以下好处:
- 减少运行时的错误,如果输入的Key不在枚举值里编译会错误
- 通过IDE的自动提示可以很轻松找到Key值
如果不使用枚举值,可能定义的方法如下
public String get(String key) {
...
}
那么在开发者使用时可能它要频繁切换到国际化平台的Web应用上去找到相应的Key值,然后粘贴过来,并且Key值要确保复制完整。
于是我通过Python脚本读取i18n.json文件,并生成了一个i18n.java文件,里边有一个Keys的枚举值,它包含了所有从Key值,我迫不及待的想马上去使用它。
现实残酷
我通过mvn deploy
的失败输出中捕获了关键字
BUILD FAILED: code too large
What? 这是什么鬼?
通过查阅才知道,如果你的单个方法超过了64KB,那么JVM会引发这个编译错误,并终止编译。
64KB是个什么概念?
我们来算一算,因为我的Java源文件是UTF-8字符集,我们就以它来计算。 在UTF-8字符集里,一个英文字符占一个字节,1KB等于1024字节,就相当于1024个英文字符
64KB = 1024B * 64 = 65536 约6.5万个字符
实际上,i18n.json文件里大约有1万个Key,每个Key的长度平均10个字符,我们算一下实际占用
10B * 10000 = 约等于97KB
好吧,确实比最高限制64KB超出了大概30KB。没办法,我只好放弃使用enum来做Key的传参,只能使用String来替代它。
实际上,64KB的限制相当于6.5万个字符的限制在正常编程开发是绝对够用的,你要真的在一个方法里敲打的字符超过上万个我都觉得很恐怖了,以及很不好维护了,一般只有通过程序生成的Java源文件可能会不小心突破64KB这个JVM的限制。