34

現在のアプリには、「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

4 に答える 4

62

iOS 7 の時点で、Foundation フレームワークは複数形をネイティブでサポートしています。 これを使用する方法の簡単なチュートリアルを次に示します。

Localizable.stringsdictという名前の 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>%#@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];

編集:これを指摘してくれたZaphodに感謝します->:複数形化を機能させるには、.stringsdictと一緒にLocalizable.stringsファイルを作成する必要もあります(空であっても)。

于 2013-12-01T02:51:16.520 に答える
12

私のチームは、まさにこの状況を処理するためのオープン ソース ライブラリを開発しました。github でiOS i18n の複数形ライブラリをチェックしてください。

基本的な前提は、複数の文字列のキーは、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”);

実行時に、英語の場合、numItems の値に応じて文字列「1 Item Processed」または「%d Items Processed」が返されます。

ロシア語のファイルは次のようになります。

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

ロシア語または他の言語の「処理されたアイテム」を検索するコードを変更する必要はなく、ライブラリはその特定の言語の CLDR 複数形ルールに従って正しい文字列を返します。

ライブラリに関するご意見、ご提案、改善点などをお気軽にお寄せください。

于 2013-03-27T17:10:47.317 に答える
2

英語では、"1 file" と "5 files" のように 2 つの複数形しかありません。ロシア語には、整数以外を数えない限り、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 パーティ ライブラリ。
于 2013-10-30T16:53:16.143 に答える
0

同じ情報を表示する別の方法を検討します。おそらく次のようなものです。

@"Items processed: %d"

興味があれば、 MDCには複数形化規則の長い包括的なリストがありますが、これらすべての規則を実装する努力をする価値はないと思います。考慮しなければならないもう 1 つのことは、複数形の後に数値が表示される言語があるかどうかです。これは、フォーマット文字列を無効にするためです (頭のてっぺんから外れる言語は考えられませんが、おそらく場所数字が関係するより複雑なローカライズされた文字列には注意が必要です)。

于 2011-02-25T21:51:41.407 に答える