在国际化开发过程中,遇到过需要校验的地方,你会如何选择?用string value本身进行compare?一旦出现翻译后的内容跟标的mismatch又将如何呢?我们是幸福的,因为身处一个国际化底蕴深厚的团队,无论服务器抑或客户端;我们又是不幸的,源自客户端和服务器进行通信时,数据包括了本地化后的字符串,判断逻辑为我们平添烦恼。近日偶遇一则这样的真实案例,为该情况提供了完美注脚。
故事背景
在AUT的iOS终端创建Application List Compliance Policy,同时切换设备语言为日文。点击Application List Non-compliant > tap Details按钮,App闪退……需要注意的是在英文,中文等其他语言环境下,该问题不复现。(逻辑背景信息——iOS App从服务器获得的rule变量是本地化的字符串。随后App和本地存储的rule类型进行比较。如果类型相同,访问所有的units。否则,访问一个unit)
疑犯
经历一番探(tuī )讨(wěi),我们首先把目光投在了资源文件上,来关注RuleType的在服务器和客户端的翻译对比。
| 服务器端的RuleType | iOS App 的RuleType |
英文 | Rule Type | Rule Type |
日文 | ルール タイプ | ルールの種類 |
中文 | 规则类型 | 规则类型 |
哦,看来真相大白了,原来是server端跟App端的rule type不匹配的缘故哦。所以只要让二者保持内容一致即可咯,快试试看。(1分钟后……)
非常遗憾,闪退问题并未如愿消失……于是我们得出新的推论,资源文件内容的不匹配的确是个问题,至少他导致了mismatch的发生从而阻碍了server和client端的通信,但他并非罪魁祸首。
真凶
回到代码中,反复揣摩此处的逻辑背景,最大的嫌疑人应该定位为unitsInString。
#define UNITS_IN_STRING @[@"ComplianceRuleValueNone",@"ComplianceRuleValueMinutes",@"ComplianceRuleValueHours",@"ComplianceRuleValueDays"]
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.rule = @"Rule Type";
self.valueText = [[NSMutableString alloc] initWithString:@"\n\n"];
self.unitsInString = UNITS_IN_STRING;
id obj = @4;
if([self.rule caseInsensitiveCompare:NSLocalizedString(@"RuleType", nil)] == NSOrderedSame) {
for (int iterationCount = 0; iterationCount < self.unitsInString.count; iterationCount++) {
[self.valueText appendFormat:@"%@\n", NSLocalizedString(self.unitsInString[iterationCount], nil)];
}
}
else{
[valueText appendFormat:@"%@",NSLocalizedString(self.durationUnitsInString[[obj integerValue]], nil)];
}
self.defaultTextView.text =self.valueText;
}
@end
关注else部分,日文测试环境下,App 进入到该部分,需要访问一个预先定义数组中的元素。访问数组中的元素self.unitsInString[objValue],这时一个常见的开发错误出现了,没有对越界访问进行判断和保护。
于是关于闪退问题的fix的示意代码如下:添加对该数组越界的判断,否则不继续进行任何对比和赋值操作。
else {
if ([obj integerValue] >= 0 && [obj integerValue] < self.durationUnitsInString.count) {
[valueText appendFormat:@"%@",NSLocalizedString(self.durationUnitsInString[[obj integerValue]], nil)];
}
}
再次测试,在我们并未对日文资源文件进行修改的情况下,闪退问题消息。当然了,这并不代表翻译的mismatch不是问题,依然需要作为该bug的衍生问题进行随后的跟进。
反思
尘埃落定,个人感悟如下:
1、未来再次遇到App闪退的问题时,不用过分怀疑l10n资源文件的mismatch问题,她大抵上没这个能力
2、遇到server和client端需要进行信息校验时,最好不要用l10n资源文件中的内容作为token,否则后患无穷
有着类似经历和故事的你又如何看呢?