简体   繁体   English

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

[英]How to create a formatted localized string?

I have a localized string which needs to take a few variables. 我有一个本地化的字符串,需要采取一些变量。 However, in localization it is important that the order of the variables can change from language to language. 但是,在本地化中,变量的顺序可能会因语言而异。

So this is not a good idea: 所以这不是一个好主意:

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

In some languages some words come before others, while in others it's reverse. 在某些语言中,某些词语出现在其他语言之前,而在其他语言中则是相反的。 I lack of an good example at the moment. 我目前缺乏一个很好的例子。

How would I provide NAMED variables in a formatted string? 如何在格式化字符串中提供NAMED变量? Is there any way to do it without some heavy self-made string replacements? 没有一些沉重的自制字符串替换,有没有办法做到这一点? Even some numbered variables like {%@1}, {%@2}, and so on would be sufficient... is there a solution? 即使是一些编号变量,如{%@ 1},{%@ 2}等也足够......是否有解决方案?

This is why NSLocalizedString takes two parameters. 这就是NSLocalizedString采用两个参数的原因。 Use the second parameter to include a comment describing the native language meaning of the variables. 使用第二个参数包含描述变量的本机语言含义的注释。 Then, translators can reorder them using the $ + number construct. 然后,翻译人员可以使用$ +数字结构重新排序它们。 See Apple's Notes for Localizers . 请参阅Apple的Localizing Notes

However you cannot skip parameters in one language. 但是,您不能跳过一种语言的参数。 For example, if you have 3 parameters in English and 4 in French and you don't need the third in English, you cannot format like %1$@ %2$@ and %4$@ . 例如,如果您有3个英语参数和4个法语参数,并且您不需要英语中的第三个参数,则不能格式化为%1$@ %2$@ and %4$@ You can only skip the last one. 你只能跳过最后一个。

Formatted localized string example: 格式化本地化字符串示例:

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

genstrings will generate this line in your Localizable.strings file: genstrings将在Localizable.strings文件中生成此行:

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

I solved this in a project a few weeks back by building my own simple template system with NSScanner . 几个星期前,我通过使用NSScanner构建自己的简单模板系统解决了这个问题。 The method uses a template system that finds variables with the syntax ${name} . 该方法使用模板系统查找具有语法${name}变量。 Variables are supplied to the method through an NSDictionary . 变量通过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;
}

With a localize file looking like this: 使用如下所示的localize文件:

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

We can accomplish the following results... 我们可以完成以下结果......

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!"

As you can see, I've added some extra functionality too. 如您所见,我还添加了一些额外的功能。 Firstly, any variables that aren't found ( ${byebye} in my example) will be localized and appended to the results. 首先,任何未找到的变量(在我的示例中${byebye} )都将被本地化并附加到结果中。 I did this because i load in HTML-files from my application bundle and run them through the localize method (when doing that, I don't localize the input string when creating the scanner though). 我这样做是因为我从我的应用程序包中加载了HTML文件并通过localize方法运行它们(当这样做时,我不会在创建扫描程序时本地化输入字符串)。 Also, I added the ability to send in other things than just NSString objects, for some extra flexibility. 此外,我添加了除了NSString对象之外的其他功能,以获得一些额外的灵活性。

This code maybe isn't the best performing or prettiest written, but it does the job without any noticeable performance impacts :) 这段代码可能不是性能最好或最漂亮的代码,但它可以在没有任何明显性能影响的情况下完成工作:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM