Локализация динамических множественных существительных сообщений (например, «5 элементов обработано») на iPhone с помощью Objective-C - PullRequest
34 голосов
/ 26 февраля 2011

В моем текущем приложении у меня есть код, который отображает сообщение, например, «5 элементов обработано».Чтобы сохранить фразу грамматически правильной, то есть, должна ли она быть «5 предметами» или «5 предметами», я использую следующий код:

int numItems = 5;
NSString *myString = [[NSString alloc] initWithFormat:@"%d Item%@ Processed", numItems, (numItems == 1 ? @"" : @"s")];

Пока все работает нормально.Но я локализую свое приложение и хочу убедиться, что текст грамматически корректен на всех языках, на которые я перевожу приложение.Я мог бы сделать что-то вроде этого:

int numItems = 5;
NSString *myString = (numItems == 1 ? 
NSLocalizedStringWithTable(@"%d Item Processed", @"myApp", @"singular version") :
NSLocalizedStringWithTable(@"%d Items Processed", @"myApp", @"plural version"));

Однако не все языки имеют одинаковые правила работы множественного числа!Например, (простите мой очень конкретный пример здесь) на русском языке, существительные, измененные с номерами, заканчивающимися на последнюю цифру 1 (т.е. 21, 31, но не 11), используют именительный падеж, числа, заканчивающиеся на 2-4 взять родительный падеж единственного числа, 5+ взять родительный падеж множественного числа.Это потребовало бы гораздо более серьезной логики для обработки того, как приумножить определенное существительное в грамматически правильной манере, и эта логика не соответствовала бы английской логике.Поэтому, теоретически, я не могу иметь грамматическую логику в своем коде Objective-C, а должен иметь грамматическую логику в файле строк.Есть ли способ сделать это? Как люди переводят динамический текст для своих приложений, чтобы он оставался грамматически правильным?

Ответы [ 4 ]

61 голосов
/ 01 декабря 2013

Начиная с iOS 7, платформа Framework имеет встроенную поддержку плюрализации. Вот краткое руководство по его использованию:

Создать файл списка имен с именем Localizable.stringsdict

Английская локализация:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>%d tasks waiting for action</key>
        <dict>
            <key>NSStringLocalizedFormatKey</key>
            <string>%#@tasks@ waiting for action</string>
            <key>tasks</key>
            <dict>
                <key>NSStringFormatSpecTypeKey</key>
                <string>NSStringPluralRuleType</string>
                <key>NSStringFormatValueTypeKey</key>
                <string>d</string>
                <key>one</key>
                <string>A task is</string>
                <key>two</key>
                <string>Two tasks are</string>
                <key>other</key>
                <string>%d tasks are</string>
            </dict>
        </dict>
    </dict>
</plist>

Польская локализация:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>%d tasks waiting for action</key>
        <dict>
            <key>NSStringLocalizedFormatKey</key>
            <string>Masz %#@zadanie@ do zrobienia</string>
            <key>zadanie</key>
            <dict>
                <key>NSStringFormatSpecTypeKey</key>
                <string>NSStringPluralRuleType</string>
                <key>NSStringFormatValueTypeKey</key>
                <string>d</string>
                <key>one</key>
                <string>jedno zadanie</string>
                <key>few</key>
                <string>%d zadania</string>
                <key>other</key>
                <string>%d zadań</string>
            </dict>
        </dict>
    </dict>
</plist>

И, наконец, в вашем файле реализации вы можете вызвать словарь так:

cell.tasksInfoLabel.text = [NSString localizedStringWithFormat:NSLocalizedString(@"%d tasks waiting for action", @"%d tasks waiting for action"), (long)taskCount];

EDIT: Спасибо Zaphod за указание на это ->: Вам также необходимо создать файл Localizable.strings рядом с .stringsdict, чтобы обеспечить работу множественного числа (даже если он пустой).

12 голосов
/ 27 марта 2013

Моя команда разработала библиотеку с открытым исходным кодом для обработки именно этой ситуации, ознакомьтесь с нашей множественной библиотекой iOS i18n на github.

Основная предпосылка заключается в том, что ключи для множественных строк расширены досодержат их форму множественного числа в соответствии с правилами множественного числа CLDR , и поиск строк не использует типичную NSLocalizedString.

Английский файл для приведенного примера будет выглядеть следующим образом:

"%d Items Processed##{one}"   = "1 Item Processed";    
"%d Items Processed##{other}" = "%d Items Processed";

Поиск будет выполняться с использованием функции SLPluralizedString

SLPluralizedString(@”%d Items Processed”, numItems, @”Number of items processed”);

Во время выполнения дляПо-английски будет возвращаться строка «1 обработанный элемент» или «% d обработанных элементов» в зависимости от значения numItems.

Русский файл будет выглядеть следующим образом:

"%d Items Processed##{one}"   = "%d элемент обработан";
"%d Items Processed##{few}"   = "%d элемента обработано";
"%d Items Processed##{many}"  = "%d элементов обработано";
"%d Items Processed##{other}" = "%d элемента обработано";

Вашзатем не нужно менять код для поиска «Обработанные элементы» на русском или любом другом языке, и библиотека будет возвращать правильную строку в соответствии с правилами множественного числа CLDR для этого конкретного языка.

Пожалуйста, не стесняйтесь поделитьсяваши мысли о библиотеке, предложения, улучшения и т. д.

2 голосов
/ 30 октября 2013

На английском языке есть только 2 формы множественного числа, например «1 файл» и «5 файлов». На русском языке есть 3 формы множественного числа (101 файл, 2 файла, 11 файлов), если не считать нецелые числа. На самом деле на языке может быть до 6 множественных форм (например, на арабском языке - 6). Кажется, есть 3 способа решения этой проблемы, просто выберите то, что достаточно хорошо, но не слишком сложно для вас:

  1. Попробуйте использовать множественные нейтральные сообщения, например, «Количество обработанных элементов:% d» вместо «% d обработанных элементов |% d обработанных элементов».

  2. Поддержка локализаций для каждой формы множественного числа, до 6.

    "%d Gold Coins##{PluralForm0}" -> "%d золотая монета" // e.g. 1 gold coin
    "%d Gold Coins##{PluralForm1}" -> "%d золотые монеты" // e.g. 2 gold coins
    "%d Gold Coins##{PluralForm2}" -> "%d золотых монет"  // e.g. 5 gold coins
    …
    "%d Gold Coins##{PluralForm5}" -> "%d How did we get here if this is not Arabic???"
    

    Зная значение% d и целевой язык, ваше приложение должно будет обнаружить номер формы во множественном числе во время выполнения, то есть реализовать что-то вроде

    unsigned int "NumberToPluralFormNumber(unsigned int number, const std::string& langCode);
    

    метод. Если вы поддерживаете только 2-5 языков и числа в сообщениях всегда неотрицательные целые числа, на самом деле это довольно просто реализовать без любой сторонней библиотеки, вы можете скопировать / вставить C-совместимые однострочные для каждого язык от http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html. Обратите внимание, что он действителен только для неотрицательных целых чисел, поэтому число множественных форм может отличаться от того, что говорит unicode.org.

  3. 3d party libs.
1 голос
/ 26 февраля 2011

Я бы рассмотрел альтернативные способы отображения той же информации, возможно, что-то вроде:

@"Items processed: %d"

MDC имеет длинный, полный список правил плюрализации, если вам интересно, ноЯ действительно не думаю, что стоит реализовать все эти правила.Еще одна вещь, которую вы, возможно, должны рассмотреть, это то, что если на каких-либо языках число появилось бы после плюрализации, так как это отбросило бы вашу строку формата (я не могу вспомнить ни одного языка, который был бы не в моей голове, но, возможно, это местодля осторожности в любой из ваших более сложных локализованных строк с числами).

...