2010-05-15 88 views
7

我有一个本地化的字符串需要采取一些变量。但是,在本地化中,重要的是变量的顺序可以从语言变为语言。如何创建格式化的本地化字符串?

因此,这不是一个好主意:

NSString *text = NSLocalizedString(@"My birthday is at %@ %@ in %@", nil); 

在某些语言中一些词语来在别人面前,而在其他的反向。我目前缺乏一个很好的例子。

我该如何在格式化字符串中提供NAMED变量?有没有办法做到这一点,没有一些重自制的字符串替换?甚至像{%@ 1},{%@ 2}等一些编号变量就足够了......是否有解决方案?

回答

12

这就是为什么NSLocalizedString有两个参数。使用第二个参数来包含描述变量本地语言含义的注释。然后,翻译人员可以使用$ +编号构造对其进行重新排序。请参阅Apple的Notes for Localizers

但是,您不能跳过一种语言的参数。例如,如果您有3个英文参数和4个法文参数,并且您不需要英文第三个参数,则不能像%[email protected] %[email protected] and %[email protected]那样格式化。你只能跳过最后一个。

3

我在几个星期后通过构建我自己的简单模板系统NSScanner解决了这个问题。该方法使用模板系统来查找语法为${name}的变量。变量通过NSDictionary提供给方法。

- (NSString *)localizedStringFromTemplateString:(NSString *)string variables:(NSDictionary *)variables { 
    NSMutableString *result = [NSMutableString string]; 
    // Create scanner with the localized string 
    NSScanner *scanner = [[NSScanner alloc] initWithString:NSLocalizedString(string, nil)]; 
    [scanner setCharactersToBeSkipped:nil]; 

    NSString *output; 

    while (![scanner isAtEnd]) { 
     output = NULL; 
     // Find ${variable} templates 
     if ([scanner scanUpToString:@"${" intoString:&output]) { 
      [result appendString:output]; 

      // Skip syntax 
      [scanner scanString:@"${" intoString:NULL]; 

      output = NULL; 

      if ([scanner scanUpToString:@"}" intoString:&output]) { 
       id variable = nil; 
       // Check for the variable 
       if ((variable = [variables objectForKey:output])) { 
        if ([variable isKindOfClass:[NSString class]]) { 
         // NSString, append 
         [result appendString:variable]; 
        } else if ([variable respondsToSelector:@selector(description)]) { 
         // Not a NSString, but can handle description, append 
         [result appendString:[variable description]]; 
        } 
       } else { 
        // Not found, localize the template key and append 
        [result appendString:NSLocalizedString(output, nil)]; 
       } 
       // Skip syntax 
       [scanner scanString:@"}" intoString:NULL]; 
      } 
     } 
    } 

    [scanner release]; 

    return result; 
} 

凭借本地化文件看起来像这样:

"born message" = "I was born in ${birthYear} on a ${birthWeekDay}. ${byebye}"; 
"byebye"  = "Cheers!"; 

我们可以实现以下结果...

NSDictionary *variables = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1986], @"birthYear", @"monday", @"birthWeekDay", nil]; 
NSString *finalString [self localizedStringFromTemplateString:@"born message" variables:variables]; 
NSLog(@"%@", finalString); // "I was born in 1986 on a monday. Cheers!" 

正如你所看到的,我已经添加了一些额外的功能太。首先,找不到任何变量(我的例子中的${byebye})将被本地化并附加到结果中。我这样做是因为我从我的应用程序包加载HTML文件,并通过localize方法运行它们(当这样做时,我不会在创建扫描仪时本地化输入字符串)。此外,我增加了发送其他内容的能力,而不仅仅是NSString对象,因为它具有一些额外的灵活性。

这个代码也许不是最好的表演或漂亮编写的,但它的工作没有任何明显的性能影响:)

10

格式化的本地化字符串例如:

NSString *today = [MyHandWatch today]; 
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Today is %@", @""), today]; 

genstrings将产生在Localizable.strings文件中这一行:

"Today is %@" = "Today is %@"; 
+0

它根本不起作用,它returnes相同的字符串 – user2159978 2014-03-20 11:21:43

+0

@ user2159978难道你真的只是复制最后一行? OF COURSE它会返回相同的字符串... – 2016-02-03 14:37:08