フォーマット

更新日:4 週間前 · 読了目安 2分

CLI は18種類のファイル形式に対応しています。形式はファイル拡張子から自動判定されますが、常に明示指定が必要な3つの形式(formatfiles[]yaml-openapi)では、yaml-root-key エントリで android を設定して上書きしてください。

形式拡張子format の値補足
JSON.jsonjsonキー/値形式。key controls に対応。
JSONC.jsoncjsoncコメント付きJSON。コメントは保持され、translator notes としても使えます。
YAML.yaml.ymlyaml汎用YAML。すべての文字列値が翻訳され、キーと構造はそのまま保持されます。
OpenAPI YAML.yaml.ymlyaml-openapiOpenAPI仕様向け。format を明示的に指定してください。通常の .yaml は自動判定で yaml として扱われます。
ロケールをルートキーにする YAML.yaml.ymlyaml-root-keyロケールが YAML のルートキーです(Rails config/locales)。ルートキーは対象のロケールに書き換えられます。format を明示的に設定してください。
Markdown.mdmd本文は翻訳対象。frontmatter はオプトイン。
MDX.mdxmdxMarkdown + JSX。コンポーネントのpropsはオプトイン。
Markdoc.mdocmarkdocMarkdown + タグ。frontmatter とタグ属性に対応。
TypeScript.ts.mts.ctstypescriptロケールモジュール(export default { … })。文字列リテラルは翻訳され、コードは保持されます。
Gettext PO.popomsgstr が翻訳され、msgid、コメント、ヘッダーは保持されます。
Flutter ARB.arbflutter文字列値が翻訳され、@ メタデータと {placeholders} は保持されます。
Android.xmlandroidstrings.xmlformat は明示的に指定してください — .xml は自動判定されません。
Xcode strings.stringsxcode-strings値は翻訳され、キーは保持されます。
Xcode String Catalog.xcstringsxcode-xcstrings1つのファイルにすべてのロケールを保持します — ターゲットも同じファイルに書き戻されます(詳細は下記)。
Xcode stringsdict.stringsdictxcode-stringsdict複数形文字列が翻訳され、書式制御キーは保持されます。
XLIFF.xlf.xliffxliff<source> は保持され、<target> はユニット単位で書き込まれます。バージョン1.2と2.0に対応。
SubRip.srtsrt字幕テキストが翻訳され、インデックスとタイムコードはそのままです。
PHP.phpphpLaravel return [ … ]。文字列値が翻訳され、キー、数値、構造は保持されます。

実際の流れを見る

demo projectは、ドキュメント形式とデータ形式(JSON、JSONC、Markdown、MDX、Markdoc、OpenAPI YAML)をひととおり試せる小規模なSandboxです。各形式に必要な設定が、そのまま揃っています。npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demoでクローンして、pushを実行してください。アプリ形式とフレームワーク形式は含まれていませんが、これらについてはExample projectsにフレームワークごとの完全なリポジトリが用意されており、設定は以下の形式別スニペットで確認できます。

bash
npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo
cd my-lingo-demo

JSON と JSONC#

シンプルなキー/値形式の翻訳です。key control で別途指定しない限り、すべての文字列値が翻訳されます。

json
{ "pattern": "content/en/app.json", "lockedKeys": ["meta.version"] }

JSONCではコメントも保持され、エンジンがそれをコンテキストとして読み取ります — 詳しくは translator notes を参照してください。

json
{ "pattern": "content/en/settings.jsonc", "preservedKeys": ["featureFlags"] }

Markdown、MDX、Markdoc#

本文のテキストはデフォルトで翻訳されます。frontmatter と埋め込みコンポーネントは、明示的に有効化しない限り翻訳されません

Frontmatter#

translateFrontmatterFields で、翻訳対象にする frontmatter フィールドを指定します。

json
{
  "pattern": "content/en/guide.md",
  "translateFrontmatterFields": ["title", "description"]
}

MDX コンポーネントのprops#

MDXでは、特定のコンポーネント上の特定のpropsを translateComponentProps で翻訳対象にできます。

json
{
  "pattern": "content/en/landing.mdx",
  "translateFrontmatterFields": ["title"],
  "translateComponentProps": [{ "component": ["Hero", "Callout"], "props": ["title", "body"] }]
}

これにより、titlebody 上の <Hero> および <Callout> props が翻訳され、それ以外のpropsは変更されません。

Markdoc#

MarkdocはMarkdownと同様に動作し、frontmatter とタグ属性を保持します。

json
{
  "pattern": "content/en/changelog.mdoc",
  "translateFrontmatterFields": ["title"]
}

YAML#

汎用YAMLは .yaml/.yml から自動判定されます。すべての文字列値が翻訳され、キーと構造は保持されます。

json
{ "pattern": "content/en/strings.yaml" }

OpenAPI仕様は例外です。同じ .yaml 拡張子を使いますが、format を明示的に指定する必要があります。これにより、エンジンは人が読むフィールド(summary、description)のみを翻訳し、スキーマキー、path、operation ID はそのまま保持します。

json
{ "pattern": "content/en/api.yaml", "format": "yaml-openapi" }

Rails スタイルのロケールファイルも、もう1つの特殊なケースです。ロケールが YAML のルートキー(en:)となり、出力先ファイルも対象のロケール(es:)をルートにする必要があります。これらも format を明示的に設定してください。

json
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }

アプリ / フレームワーク向けフォーマット#

PO、Flutter ARB、Xcode .strings、Xcode .stringsdict、TypeScriptロケールモジュール、XLIFF、SubRip、PHP は、いずれも同じルールです。翻訳可能なテキストだけを翻訳し、構造に関わる要素はそのまま保持します(キー、ID、メタデータ、プレースホルダー、タイムコード、コード、書式など)。どれも拡張子から自動判定されるので、ソースファイルにパターンを向けるだけで使えます。

json
{ "pattern": "lib/l10n/app_en.arb" }
{ "pattern": "locales/en.po" }
{ "pattern": "Localizable.strings" }
{ "pattern": "l10n/en.xlf" }

ただし1つだけ、拡張子が曖昧で自動判定できないため、format の明示指定が必要な形式があります。

json
{ "pattern": "res/values/strings.xml", "format": "android" }

Xcode String Catalogs#

.xcstrings(String Catalog)ファイルには、すべてのロケールが1つのファイルに入っています。ロケールごとの出力パスはなく、CLIはソースロケールを読み取り、すべてのターゲットを同じファイルに書き戻します。

json
{ "pattern": "Localizable.xcstrings" }

カタログ内で"shouldTranslate": falseのフラグが付いた文字列はスキップされ、CLIによって未翻訳のまま変更されません。

キースコープを使える形式は?#

lingo push --key は、指定したキーだけを再翻訳し、それ以外には手を加えません。使うには、安定した名前を持つキーと、特定のキーを含まなくても成立するファイルが必要です。そのため、ドキュメント形式と複数形辞書は対象外です。

キースコープに対応キースコープは非対応
jsonjsoncyamlyaml-root-keypoflutterandroidxcode-stringsxcode-xcstringsxliffphptypescriptmdmdxmarkdochtmlsrtyaml-openapixcode-stringsdict

mdmdxmarkdochtmlsrtyaml-openapi では、各ユニットはドキュメント内の位置 — セクション番号、ノードパス、字幕キュー番号など — で特定されます。つまり、その上位にある要素が少しでも編集されるとキーが変わってしまい、特定のユニットを狙ったスコープでも別の文字列を選んでしまうか、何も選べなくなります。xcode-stringsdict が対象外になるのは逆の理由です。こちらのキーは複数形カテゴリそのもので、有効な複数形辞書として成立させるために必須なので、省くことはできません。

lingo push は、キー指定の実行中に対象外のファイルがあっても処理全体を失敗にはせず、警告を出してそのファイルだけを除外します。そのため、push ではそれらをキーバリュー形式のファイルと一緒に混在させることはできます。これらを push する場合は、--key を付けないでください。

対応している形式の中でも、位置ベースのメンバーは同じ扱いになります。配列要素、Android の <string-array> 項目、<plurals> の quantity では、スコープ内でもソーステキストがそのまま維持されます。

出力パス#

このパターンで指定するのはソースファイルです。各ターゲットパスは、そこから導き出されます。ルールは次の 4 つで、上から順に適用されます。

  1. パスセグメント全体またはファイル名全体がロケールになっている場合 — これが一般的なケースです。content/en/app.jsoncontent/de/app.jsonlocales/en.jsonlocales/de.json
  2. セグメントやファイル名の末尾にロケールが付く場合。この形式を採用しているのは、Android、Xcode の .strings/.stringsdict、Flutter、そして yaml-root-key です。res/values-en/res/values-de/app_en.arbapp_de.arbdevise.en.ymldevise.de.yml
  3. デフォルト言語用にプラットフォームが予約している名前が使われていて、パス内にロケールがまったく含まれない場合。 Android の res/values/res/values-de/ になり、Xcode の Base.lprojde.lproj になります。
  4. String Catalog。1 つのファイルですべてのロケールを保持するため、ターゲットパスソースパスと同じです。

Android だけは、ターゲットパスが BCP 47 にならない唯一のプラットフォームです。CLI は Android が実際に読み取るリソース修飾子を書き出すため、pt-BRvalues-pt-rBR/ に、zh-Hansvalues-b+zh+Hans/ に出力されます。

どのルールにも当てはまらない場合 — つまりソースロケールがパス内のどこにも現れない場合 — CLI はフォールバックとして、ファイルの横に <locale>/ ディレクトリを作成し、lingo push で推測によるものだと知らせます。この警告が出たら、パターンが誤っているサインです。Configuration を参照してください。

legacy CLI から移行する場合#

legacy CLI で対応していた形式の多くは、現在のCLIでも利用できます(PO、XLIFF、Android/Xcode strings、Flutter ARB など — 上の表を参照)。一方で、あまり一般的でない一部の形式(例: CSV、HTML、MJML、.properties)はまだ未対応です。必要な形式が追加されるまでは、legacy CLI docs を参照してください。