複数形に対応したMacアプリのラベルを完成させるには、Xcodeで複数形のバリエーションを追加し、サポートする各ローカライズに必要なすべてのカテゴリを用意して、表示結果をテストします。この手順では、架空の項目選択メッセージを使用します。

ここでの課題は、SwiftUI Macアプリの、数に応じて変化するラベルを1つ仕上げることです。このメッセージは選択中の項目数を報告し、0以上の整数を受け取り、その意味を翻訳後も保ちます。カテゴリの網羅性、プレースホルダーの確認、実行時のテストを組み合わせることで、カタログ項目の完成基準を明確にします。

複数形のカテゴリをすべて網羅するには?

Appleは、Xcode 15以降で複数形をローカライズする方法としてString Catalogを推奨しています。複数形に関するドキュメントでは、必須のフォールバックと文法上の完全性を区別しています。otherはstrings辞書で必須ですが、言語固有の追加カテゴリを省略すると文法が不自然になることがあります。英語ではoneとotherが必要で、zeroカテゴリは任意です。複数形を含む文字列のローカライズ。

使用できるカテゴリ名は、zero、one、two、few、many、otherです。これらは言語ごとの文法上の分類を表すもので、すべての言語に共通する6つの数値範囲ではありません。oneというカテゴリを、数が1かどうかだけを判定する普遍的なアプリのルールにしてはいけません。Unicodeは、名詞以外の変化も含め、数によって句に必要となる変化に基づいてカテゴリを定義しています。複数形ルール。

この課題では、次のメッセージ仕様を使います。これは説明用のアプリ要件であり、Appleが定めた要件ではありません。

仕様項目 この例での要件
メッセージキー selection.count
英語のデフォルト値 \(count) items selected
入力 countという名前の、0以上のSwift Int
意味 現在選択されている項目の数
出力 数を含む、完全にローカライズされたラベル1つ
網羅範囲 ソースローカライズを含む、サポート対象のすべてのローカライズ
受け入れ基準 必要なカテゴリが用意され、数値の置換が保たれ、代表的な出力が確認されている

このラベルでは、数値を表示することを意図的に要件としています。Appleによると、複数形のバリエーションでは数値を文字で表すことも、数値フォーマット指定子を省略することもできます。別のメッセージ仕様なら、それを許容してもよいでしょう。ここでは数値を表示することで、ラベルとその対象となる選択項目を照らし合わせやすくします。複数形を含む文字列のローカライズ。

Swiftのメッセージをカタログに結び付ける

SwiftのString.LocalizationValueは、実行時の補間を含むローカライズ可能なテキストをサポートしています。安定した識別子を英語のソーステキストと別にする場合、Appleは個別のdefaultValueを受け取るStringのイニシャライザーを案内しています。これはselection.countに適しています。識別子がメッセージを特定し、デフォルト値が英語の文言を指定します。String.LocalizationValue。

小規模なテストアプリでは、Xcode 15以降を使ってSwiftUIのmacOSアプリプロジェクトを作成し、macOS 12以降をデプロイメントターゲットに設定します。生成されたアプリのエントリーファイルを、以下のプログラム全体で置き換えます。ターゲット内の@main宣言は1つだけにしてください。カタログの手順を進める前に、Localizable.xcstringsをアプリターゲットに追加します。このプログラムにはXcodeとmacOS SDKが必要です。調査環境ではコンパイルしていません。

import Foundation
import SwiftUI

@main
struct PluralSampleApp: App {
    var body: some Scene {
        WindowGroup {
            PluralSampleView()
        }
    }
}

struct PluralSampleView: View {
    @State private var count: Int = 1

    private let samples: [Int] = [
        0, 1, 2, 3, 4, 5, 10, 11, 12,
        20, 21, 22, 100, 101, 102, 1_000_000
    ]

    private var selectionLabel: String {
        String(
            localized: "selection.count",
            defaultValue: "\(count) items selected",
            comment: "Selection summary. The integer is the number of selected items. Keep the count visible in every plural variant."
        )
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Picker("Sample count", selection: $count) {
                ForEach(samples, id: \.self) { value in
                    Text(verbatim: String(value)).tag(value)
                }
            }

            Text(verbatim: selectionLabel)
        }
        .padding(24)
        .frame(minWidth: 360)
    }
}

数値ピッカーの項目はテスト入力です。ローカライズされた要約はString(localized:defaultValue:comment:)で解決され、その結果の文字列が表示されます。Appleの説明によると、イニシャライザーの第1引数は検索キー、デフォルト値はソーステキスト、コメントは翻訳時の補足情報になります。ビルド時に、Xcodeはローカライズ用APIに渡された文字列を抽出します。アプリのテキストを翻訳用に準備する。

整数は、ローカライズ可能な補間の中に保持してください。この仕様では、アプリ側の分岐で英語の単数形と複数形の文を別々に組み立てないでください。メッセージを1つに保つことで、指定された数に合うローカライズ済みの文言を選ぶという、カタログの役割が明確になります。

サポートするすべてのローカライズでカテゴリを用意する

Xcodeのエディタを使って、バリエーションの構造を作成します。

  1. Product > Buildを選び、カタログを生成します。
  2. Localizable.xcstringsを開き、ソースローカライズを選択します。
  3. selection.countをControlキーを押しながらクリックし、Vary by Pluralを選びます。
  4. ソース言語の各バリエーションを入力します。
  5. サイドバーのAddボタンでサポート対象のローカライズを追加し、それぞれのバリエーションを入力します。

Xcodeは言語固有の複数形を追加し、補間のフォーマット指定子を決定します。ソースローカライズに複数形のバリエーションを適用すると、各言語のバリエーション構造が同期されます。別のローカライズだけに適用した場合は、そのローカライズだけが対象になります。String Catalogでテキストをローカライズし、バリエーションを設定する。

この整数補間では、英語の項目を次のようにできます。

英語のカテゴリ カタログ値
one %lld item selected
other %lld items selected

実際の補間型に対してXcodeが生成した指定子を使用してください。Appleのドキュメントにある整数の例では%lldを使っています。翻訳に別のプレースホルダーをコピーすると、引数の仕様に適合しなくなることがあります。Xcodeは最初、バリエーションの各フィールドにキーの値を入力するため、すべてのフィールドの文言を確認してください。String Catalogでテキストをローカライズし、バリエーションを設定する。

実際のローカライズ識別子ごとに1行を設けた網羅性確認表を作成します。このメッセージについてXcodeが生成したカテゴリ、各カテゴリのテキストが完成しているか、テストする入力値を記録します。プロジェクトで実際に使われている識別子を使えば、広い言語名によって未確認のローカライズが見えなくなるのを防げます。

英語のカテゴリ一式をすべての行にコピーしてはいけません。同様に、どこでも6つのカテゴリすべてを求めてはいけません。まずカタログが用意する構造を使い、次にテスト入力を選ぶ際にその言語の基数の複数形ルールを確認します。基数ルールは量に関するもので、序数ルールは順序に関するため、別の問いに答えるものです。Unicodeはこれらを別のルールタイプとして定義しています。Unicode技術標準 #35: 数値。

構造、プレースホルダー、表示テキストを個別に検証する

それぞれ異なる問いに答えるため、3つの観点で確認します。カテゴリの欠落は網羅性の問題、プレースホルダーの誤りは書式の問題、不自然な文は文言の問題です。これらを分けて記録すると、次に何を修正するかが明確になります。

カテゴリの網羅性を確認する

確認表の各行について、必要なカテゴリとカタログに入力済みの項目を照らし合わせます。otherが存在すること、必要なカテゴリに値がない、または未完成のソーステキストが残っている状態になっていないことを確認します。

簡単な完全性チェックでは、必要なカテゴリを、そのローカライズ用に生成されたカテゴリに、意図的にサポート対象とした上書きを加えた集合として定義します。未入力の集合は、完成したテキストが入っているカテゴリを必要なカテゴリから差し引いたものです。要素が1つでも残れば、この記事の受け入れ基準ではメッセージは未完成です。これは、ドキュメントにあるバリエーション設定の手順から導いた実用的な確認方法であり、Xcodeがこのチェックリストとまったく同じ検証を行うという主張ではありません。

2つのカテゴリで正当に同じ文言を使う場合は、必要な箇所にその文言を残し、両方の項目を確認してください。目的は必要なカテゴリ全体でメッセージの意味を保つことです。文字列のペアすべてに目に見える違いを設ける必要はありません。

数値の置換を確認する

ビルドして、カタログの診断結果を確認します。Appleは、フォーマット指定子の不一致など、よくある問題を検出するString Catalogの検証について説明しています。該当する診断を解消し、各バリエーションが数値を表示するというこのメッセージの要件を満たしているか確認します。多言語対応アプリをビルドする。

この引数1つの例では、数値のプレースホルダーが存在し、数値型のままで、意図した場所に1回挿入されているかを確認します。ビルドの成功は有用な根拠ですが、受け入れを判断するにはカテゴリの網羅性と実際の表示テキストも確認する必要があります。

Macアプリで代表的な数値をテストする

Product > Scheme > Edit Schemeを選び、Runを選択してOptionsを開きます。App Languageと該当するApp Regionを設定し、ダイアログを閉じてMacアプリを実行します。サポート対象のローカライズごとに繰り返します。Appleは、ローカライズされた出力をテストするためのこのスキーム設定手順を説明しています。アプリ実行時のローカライズのテスト。

サンプルのピッカーにある数値は最初のテストセットであり、すべてのカテゴリを網羅する普遍的な値ではありません。そのローカライズのテスト行を完了とする前に、各言語に適した値を追加します。

テスト項目 確認内容
0、1、2 項目なし、項目1つ、少数の複数項目の選択
必要なカテゴリごとに代表的な入力値を最低1つ ローカライズごとの文法上の区別が網羅されていること
関連するルールの境界の前後にある値 小さい数以外でのカテゴリの変化
有効範囲内の大きな数 数値の置換とラベルに収まるか
テストするすべての入力値 意味、文全体、表示される数値

Unicodeのルールではカテゴリごとに条件と例が定められており、小数桁など数値の詳細が影響することもあります。この仕様で受け付けるのは整数のみです。アプリが後に小数の数量も受け付けるようになった場合は、整数の結果だけで網羅性が確認できたと考えず、補間、ソース文言、テストをまとめて見直してください。Unicode技術標準 #35: 数値。

予想外の結果を診断する

観察された症状に応じて、次に確認する箇所を選びます。

症状 次の対応
カタログにselection.countがない 再度ビルドし、ローカライズ可能な呼び出しと選択中のテーブルを確認する
1つのローカライズにしか複数形のバリエーションがない Vary by Pluralを適用した場所を見直す
バリエーションに英語の複数形の文言が残っている 初期入力されたフィールドを確認し、完成した翻訳を入力する
表示される数値がない、または形式が崩れている バリエーションのプレースホルダーをXcodeが生成した指定子およびメッセージ仕様と比較する
大きな数で予想外の文言になる そのローカライズのカテゴリルールを確認し、代表的なテストを追加する
正しい文言が収まらない ビューを調整し、ラベル全体を再テストする

Xcode 15より前のバージョンを使う古いプロジェクトでは、Appleがサポートする方法として.stringsと.stringsdictリソースを使用します。複数形辞書は言語固有のバリエーションを提供し、otherを必須とします。ただし、正しい文法に必要な残りのカテゴリを用意する必要はなくなりません。複数形を含む文字列のローカライズ。

サポート対象のすべてのローカライズで網羅性確認表の行が完成し、プレースホルダーが仕様を満たし、代表的な数値で実行中のアプリに意図したラベルが表示されたら、メッセージは完成です。サポート対象のローカライズ、数値入力の型、またはメッセージの意味が変わるたびに、それらの行を見直してください。

参考資料