Iphone 如何创建格式化的本地化字符串?

Iphone 如何创建格式化的本地化字符串?,iphone,string-formatting,Iphone,String Formatting,我有一个本地化字符串,它需要一些变量。然而,在本地化过程中,变量的顺序在不同语言之间变化是很重要的 所以这不是一个好主意: NSString *text = NSLocalizedString(@"My birthday is at %@ %@ in %@", nil); 在某些语言中,有些词出现在其他词之前,而在另一些语言中则相反。我目前缺乏一个好的榜样 如何在格式化字符串中提供命名变量?有没有办法不用一些沉重的自制字符串替换?即使是一些编号的变量,如{%@1}、{%@2},等等,也足够了。

我有一个本地化字符串,它需要一些变量。然而,在本地化过程中,变量的顺序在不同语言之间变化是很重要的

所以这不是一个好主意:

NSString *text = NSLocalizedString(@"My birthday is at %@ %@ in %@", nil);
在某些语言中,有些词出现在其他词之前,而在另一些语言中则相反。我目前缺乏一个好的榜样


如何在格式化字符串中提供命名变量?有没有办法不用一些沉重的自制字符串替换?即使是一些编号的变量,如{%@1}、{%@2},等等,也足够了。。。有解决方案吗?

几周前,我在一个项目中通过使用
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文件,并通过本地化方法运行它们(在这样做时,我在创建扫描仪时不会本地化输入字符串)。此外,我还添加了发送除
NSString
对象之外的其他内容的功能,以获得额外的灵活性


这段代码可能不是性能最好或写得最漂亮的,但它完成了这项工作却没有任何明显的性能影响:)

这就是为什么
NSLocalizedString
采用两个参数的原因。使用第二个参数包含一条注释,描述变量的母语含义。然后,翻译人员可以使用
$
+数字结构对它们重新排序。看苹果的


但是,不能跳过一种语言中的参数。例如,如果您有3个英文参数和4个法文参数,而您不需要第三个英文参数,则不能像
%1$@%2$@和%4$@
那样格式化。您只能跳过最后一个。

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

NSString *today = [MyHandWatch today];
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Today is %@", @""), today];
GenString将在Localizable.strings文件中生成此行:

"Today is %@" = "Today is %@";

@用户2159978你真的复制了最后一行吗?当然,它将返回相同的字符串。。。