Как создать отформатированную локализованную строку?

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

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

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

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

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

8
задан Michael Petrotta 15 May 2010 в 19:57
поделиться

2 ответа

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

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

13
ответ дан 5 December 2019 в 06:22
поделиться

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

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

3
ответ дан 5 December 2019 в 06:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: