Как создать отформатированную локализованную строку? - PullRequest
7 голосов
/ 15 мая 2010

У меня есть локализованная строка, которая должна принимать несколько переменных. Однако при локализации важно, чтобы порядок переменных мог меняться от языка к языку.

Так что это не очень хорошая идея:

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

В некоторых языках одни слова стоят перед другими, а в других наоборот. У меня нет хорошего примера на данный момент.

Как бы я предоставил NAMED-переменные в форматированной строке? Есть ли способ сделать это без каких-либо тяжелых самодельных замен строк? Даже некоторых пронумерованных переменных, таких как {% @ 1}, {% @ 2} и т. Д., Будет достаточно ... есть ли решение?

Ответы [ 3 ]

12 голосов
/ 04 июля 2010

Вот почему NSLocalizedString принимает два параметра. Используйте второй параметр, чтобы включить комментарий, описывающий значение переменных на родном языке. Затем переводчики могут изменить их порядок, используя числовую конструкцию $ +. См. Apple Примечания для локализаторов .

Однако нельзя пропустить параметры на одном языке. Например, если у вас есть 3 параметра на английском и 4 на французском и вам не нужен третий на английском, вы не можете форматировать как %1$@ %2$@ and %4$@. Вы можете пропустить только последний.

10 голосов
/ 29 ноября 2010

Пример форматированной локализованной строки:

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

genstrings сгенерирует эту строку в вашем файле Localizable.strings:

"Today is %@" = "Today is %@";
3 голосов
/ 16 мая 2010

Я решил эту проблему в проекте несколько недель назад, создав собственную простую систему шаблонов с 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 объектов, для дополнительной гибкости.

Этот код, возможно, не самый эффективный или самый красивый написанный, но он выполняет свою работу без каких-либо заметных последствий для производительности:)

...