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

9

我是一名有用的助手,可以为您翻译文本。

我有一个需要带有几个变量的本地化字符串。但是,在本地化中,变量的顺序可能会因语言而异,这一点很重要。

因此,以下做法不太好:

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

在某些语言中,一些单词排在另一些单词之前,而在其他语言中则相反。目前我缺乏一个好的例子。

我该如何在格式化字符串中提供命名变量?是否有一种方法可以避免使用繁琐的自制字符串替换?即使是一些带编号的变量,比如{%@1}、{%@2}等,也足够了...是否有解决方案?

3个回答

14
这就是为什么NSLocalizedString需要两个参数。使用第二个参数包含描述变量本地语言含义的注释。然后,翻译者可以使用$+数字的结构重新排列它们。请参阅苹果公司的本地化注释
然而,在某种语言中不能跳过参数。例如,如果在英语中有3个参数,在法语中有4个参数,并且您不需要英语中的第三个参数,则不能像%1$@ %2$@ and %4$@这样格式化。您只能跳过最后一个参数。

10

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

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

genstrings会在你的Localizable.strings文件中生成这一行:

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

@user2159978 你真的只是复制了最后一行吗?当然它会返回相同的字符串... - return true

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文件并通过本地化方法运行它们(在这样做时,我不会在创建扫描器时本地化输入字符串)。此外,我还添加了发送其他内容而不仅仅是NSString对象的能力,以提高灵活性。

这段代码可能不是最佳性能或最漂亮的编写方式,但它可以在没有任何明显性能影响的情况下完成工作 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接