Localizable.strings を String Catalog(.xcstrings)に移行する

更新 · LocalePilot

Xcode 15 以降、Apple は String Catalog への移行を推し進めています。全言語を 1 つの JSON ファイルにまとめ、複数形やデバイス別バリエーションも扱えます。移行自体は 2 クリックです。注意が必要なのは、その後の差分です。

お急ぎですか?単体の .strings ファイルをブラウザでそのままカタログに変換できます。無料・登録不要で、何もアップロードされません。

移行の前に

次の 2 つを準備しておけば、予期しないトラブルはほとんど防げます。

  • クリーンな Git ツリーと専用ブランチ。後で確認すべきことはすべて差分にあるので、その差分だけを切り離しておきたいからです。
  • 移行前にビルドが通ること。Xcode はビルド時にコードをスキャンしてカタログを埋めます。プロジェクトがコンパイルできないと、カタログは不完全なままで、その理由もわかりません。

移行の手順

プロジェクトナビゲータで Localizable.strings を右クリックし、Migrate to String Catalog を選びます。Xcode が対象のファイルとターゲットを一覧表示します。正確な文言は Xcode のバージョンによって変わることがありますが、流れは同じです。

fr.lproj/Localizable.strings、de.lproj/Localizable.strings などのファイルは、全言語を持つ 1 つの Localizable.xcstrings に置き換えられます。.strings ファイルのコメントは、各キーのコメントになります。

ファイルの中身

String Catalog は JSON です。シンプルなキーの例:

{
  "sourceLanguage" : "en",
  "strings" : {
    "welcome_user" : {
      "comment" : "Home screen greeting",
      "localizations" : {
        "fr" : {
          "stringUnit" : {
            "state" : "translated",
            "value" : "Bon retour, %@ !"
          }
        }
      }
    }
  },
  "version" : "1.0"
}

複数形は variations の下に保存されます。

"items_left" : {
  "localizations" : {
    "fr" : {
      "variations" : {
        "plural" : {
          "one" : { "stringUnit" : { "state" : "translated", "value" : "%lld article restant" } },
          "other" : { "stringUnit" : { "state" : "translated", "value" : "%lld articles restants" } }
        }
      }
    }
  }
}

各コロンの前にスペースが入っている点に注意してください。これが Xcode の書き方です。ファイルを「標準的な」JSON として書き直すツールを使うと、翻訳を 1 つも変えていないのに巨大な差分が生まれます。

差分で確認すべきこと

Stale と表示されたキー。ビルド後、Xcode はコード内で見つからなくなったキーに印を付けます。必ずしも不要になったわけではありません。実行時に組み立てられるキー(NSLocalizedString(variable, comment: "") や設定ファイルから読むキー)はスキャンでは見えません。削除する前に確認してください。

コードから抽出された新しいキー。ビルドによって、Localizable.strings に入れたことのない文字列が追加されることがあります。典型的なのは SwiftUI の Text("…") リテラルで、デフォルトでローカライズ対象になります。これらは未翻訳の状態で追加されるため、Xcode が言語ごとに表示する割合は下がりますが、これは想定どおりです。

状態。すべての値には状態があります:translated、needs_review、そしてまだ誰も翻訳していない文字列の new。3 か月後、何が実際にレビュー済みかを知る手がかりになります。

書式指定子。Text("\(count) items left") のような SwiftUI の文字列は、%lld items left というキーを生成します。古い .strings で同じ文に %d を使っていた場合、ほぼ重複したキーが 2 つできます。コードが実際に使っているほうを残してください。

古い iOS バージョンはどうなる?

iOS 17 は必要ありません。カタログはソース形式です。ビルド時に Xcode がアプリバンドル内の通常の .strings ファイルにコンパイルします。デプロイメントターゲットは変わりません。

Xcode の外でカタログを編集する

文字列が少しなら Xcode のエディタで十分です。1 言語をまるごとレビューしたり、まとめて翻訳したり、プレースホルダーをチェックしたりするなら、専用のツールが役立ちます。LocalePilot は .xcstrings ファイルを開き、Xcode と同じ書式で書き戻します。変更のないカタログはバイト単位で同一のまま出力され、編集は該当する行だけを変更し、編集した値は translated 状態になります。複数形とデバイス別バリエーションは編集でき、置換(%#@count@)を使うキーや shouldTranslate: false が付いたキーはそのまま保持され、Xcode で編集します。

よくある質問

String Catalog には iOS 17 が必要ですか?

いいえ。Xcode はビルド時にカタログを通常のローカライズファイルにコンパイルします。アプリのデプロイメントターゲットは変わりません。

String Catalog の Stale とは何ですか?

前回のビルドで、Xcode がそのキーをコード内に見つけられなかったという意味です。削除する前に、実行時に組み立てられるキーでないことを確認してください。

移行を元に戻すには?

専用のブランチで、直前にコミットしてから移行してください。Git で元に戻せば .strings ファイルが復活します。