Xcode .xcstringsカタログ
Lingo.dev CLIを使用したXcode .xcstringsファイルのAI翻訳
Xcode .xcstringsカタログとは?
Xcode .xcstringsカタログは、Xcode 15で導入されたAppleの最新のローカリゼーション形式です。すべてのローカリゼーションを1つのJSONファイルに保存し、複数形、デバイスバリエーション、翻訳メタデータをサポートしています。
例えば:
{
"sourceLanguage" : "en",
"strings" : {
"item_count" : {
"comment" : "Number of items displayed in the list - supports pluralization",
"extractionState" : "manual",
"localizations" : {
"en" : {
"variations" : {
"plural" : {
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 item"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%d items"
}
},
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "No items"
}
}
}
}
}
}
},
"welcome_message" : {
"comment" : "Welcome message shown on the app's home screen",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hello, world!"
}
}
}
}
}
}
Lingo.dev CLIとは?
Lingo.dev CLIは、AIでアプリやコンテンツを翻訳するための無料のオープンソースCLIです。従来の翻訳管理ソフトウェアに代わるものとして設計されており、既存のパイプラインと統合できます。
詳細については、概要をご覧ください。
このガイドについて
このガイドでは、Lingo.dev CLIを使用してXcode .xcstringsファイルを翻訳する方法を説明します。
以下の方法を学びます:
- ゼロからプロジェクトを作成する
- 翻訳パイプラインを設定する
- AIで翻訳を生成する
前提条件
Lingo.dev CLIを使用するには、Node.js v18+がインストールされていることを確認してください:
❯ node -v
v22.17.0
ステップ 1. プロジェクトを設定する
プロジェクトのディレクトリに、i18n.jsonファイルを作成します:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
このファイルは、翻訳パイプラインの動作を定義し、どの言語間で翻訳するか、およびローカライズ可能なコンテンツがファイルシステム上のどこに存在するかを指定します。
利用可能なプロパティの詳細については、i18n.jsonを参照してください。
ステップ 2. ソースロケールを設定する
_ソースロケール_は、コンテンツが最初に書かれた元の言語と地域です。ソースロケールを設定するには、i18n.jsonファイルのlocale.sourceプロパティを設定します:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
ソースロケールはBCP 47言語タグとして提供する必要があります。
Lingo.dev CLIがサポートするロケールコードの完全なリストについては、サポートされているロケールコードを参照してください。
ステップ 3. ターゲットロケールを設定する
_ターゲットロケール_は、コンテンツを翻訳したい言語と地域です。ターゲットロケールを設定するには、i18n.jsonファイルのlocale.targetsプロパティを設定します:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
ステップ 4. ソースコンテンツを作成する
まだ作成していない場合は、翻訳するコンテンツを含む.xcstringsファイルを作成します。
注意: 翻訳プロセス中、ソースコンテンツファイルは上書きされ、翻訳されたコンテンツ(ソースコンテンツに加えて)が含まれるようになります。
ステップ 5. バケットを作成する
-
i18n.jsonファイルのbucketsオブジェクトに"xcode-xcstrings"オブジェクトを追加します:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "xcode-xcstrings": {} } } -
"xcode-xcstrings"オブジェクト内で、1つ以上のincludeパターンの配列を定義します:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "xcode-xcstrings": { "include": ["./example.xcstrings"] } } }これらのパターンは翻訳するファイルを定義し、以下のいずれかの方法で指定できます:
- 特定のファイルパスを指定する(例:
"some/dir/file.xcstrings") - ワイルドカードプレースホルダーとしてアスタリスクを使用する(例:
"some/dir/*.xcstrings")
再帰的なグロブパターン(例:
**/*.xcstrings)はサポートされていません。 - 特定のファイルパスを指定する(例:
ステップ 6. LLMを設定する
Lingo.dev CLIは大規模言語モデル(LLM)を使用してAIでコンテンツを翻訳します。これらのモデルを使用するには、サポートされているプロバイダーからAPIキーが必要です。
できるだけ早く始めるために、毎月10,000トークンの無料利用を提供する当社独自のホスト型プラットフォームLingo.dev Engineの使用をお勧めします:
-
Lingo.devアカウントにサインアップしてください。
-
次のコマンドを実行します:
npx lingo.dev@latest loginこれによりデフォルトのブラウザが開き、認証を求められます。
-
画面の指示に従ってください。
ステップ 7. 翻訳を生成する
i18n.jsonファイルを含むディレクトリで、次のコマンドを実行します:
npx lingo.dev@latest run
このコマンドは以下を実行します:
i18n.jsonファイルを読み込みます。- 翻訳が必要なファイルを検索します。
- ファイルから翻訳可能なコンテンツを抽出します。
- 設定されたLLMを使用して抽出されたコンテンツを翻訳します。
- 翻訳されたコンテンツをファイルシステムに書き込みます。
翻訳が初めて生成されるとき、i18n.lockファイルが作成されます。このファイルは、どのコンテンツが翻訳されたかを追跡し、後続の実行で不要な再翻訳を防ぎます。
例
example.xcstrings(翻訳前)
{
"sourceLanguage" : "en",
"strings" : {
"welcome_message" : {
"comment" : "Welcome message shown on the app's home screen",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hello, world!"
}
}
}
},
"item_count" : {
"comment" : "Number of items - supports pluralization",
"extractionState" : "manual",
"localizations" : {
"en" : {
"variations" : {
"plural" : {
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "No items"
}
},
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 item"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%d items"
}
}
}
}
}
}
}
}
}
example.xcstrings (翻訳後)
{
"sourceLanguage" : "en",
"strings" : {
"welcome_message" : {
"comment" : "Welcome message shown on the app's home screen",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Hello, world!"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "¡Hola, mundo!"
}
}
}
},
"item_count" : {
"comment" : "Number of items - supports pluralization",
"extractionState" : "manual",
"localizations" : {
"en" : {
"variations" : {
"plural" : {
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "No items"
}
},
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 item"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%d items"
}
}
}
}
},
"es" : {
"variations" : {
"plural" : {
"zero" : {
"stringUnit" : {
"state" : "translated",
"value" : "Sin elementos"
}
},
"one" : {
"stringUnit" : {
"state" : "translated",
"value" : "1 elemento"
}
},
"other" : {
"stringUnit" : {
"state" : "translated",
"value" : "%d elementos"
}
}
}
}
}
}
}
}
}
i18n.json
{
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {
"xcode-xcstrings": {
"include": ["./example.xcstrings"]
}
},
"$schema": "https://lingo.dev/schema/i18n.json"
}
i18n.lock
version: 1
checksums:
d3330df55a54ce785f378e7388282a96:
welcome_message: 57da71b2c89eaddcbca81b3c3766deed
item_count/zero: 955c31a42e9ff663a49e69e944c8c537
item_count/one: 154c8eed472b867c8d5af66d162abd2c
item_count/other: ecb3f18dc6a5e7b3e1d9afe7ef62cf07
614e9d20c639fed18ee30b9f9637c83d:
item_count/one: d25ee41f72a2ea94ebc6debc85b9e573
item_count/other: ecb3f18dc6a5e7b3e1d9afe7ef62cf07
item_count/zero: 955c31a42e9ff663a49e69e944c8c537
welcome_message: 0468579ef2fbc83c9d520c2f2f1c5059