在国际化开发过程中,遇到过需要校验的地方,你会如何选择?用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,否则后患无穷

有着类似经历和故事的你又如何看呢?