Lingo.dev の CLI は、設定した ローカライゼーションエンジン を通じて、Android の 文字列リソース(strings.xml)を翻訳します。CLI の android バケットタイプは、<resources>、<string>、<string-array>、<plurals> 要素をネイティブに理解し、XML の構造を保ったまま、各ターゲットロケールに応じた正しい複数形カテゴリを生成します。
このガイドでは、CLI の設定からローカルでの翻訳、さらに GitHub Actions を使った自動化まで、Android アプリのローカライゼーションを一通り紹介します。コードを push するたびに翻訳が反映される状態まで構築できます。
デモリポジトリ
一緒に進めるには、lingodotdev/android-app-localization-example を clone するか fork してください。このリポジトリには、文字列リソースを含む動作確認済みの Android プロジェクト、Lingo.dev CLI の設定、GitHub Actions のワークフローが含まれています。
Android ローカライゼーションの仕組み#
Android では、各ロケールごとに専用の values-[locale]/ ディレクトリを用意する リソースディレクトリの規約 が使われます。システムは、デバイスの言語設定に応じて、実行時に適切な strings.xml を読み込みます。
app/src/main/res/
values/ # Default (source) strings
strings.xml
values-es/ # Spanish
strings.xml
values-fr/ # French
strings.xml
values-ja/ # Japanese
strings.xml一般的な strings.xml には、次の 3 種類の要素があります。
<resources>
<!-- Simple strings -->
<string name="app_name">My App</string>
<string name="welcome_message">Welcome back!</string>
<!-- String arrays -->
<string-array name="planets">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
</string-array>
<!-- Plurals -->
<plurals name="items_count">
<item quantity="one">%d item</item>
<item quantity="other">%d items</item>
</plurals>
</resources>CLI はこれら 3 種類すべての要素を解析し、ローカライゼーションエンジンを通じて翻訳したうえで、ロケールごとのファイルを適切な values-[locale]/ ディレクトリに書き出します。
前提条件#
ローカライゼーションエンジンを作成する
CLI を実行するたびに、コンテンツは ローカライゼーションエンジン を通って処理されます。これは、どの LLM モデル、用語集、ブランドボイス、指示 を適用するかを決める設定です。Lingo.dev dashboard で作成し、API key を生成してください。
Node.js を確認する
CLI の利用には Node.js 18 以上が必要です。
node -vAndroid プロジェクトを準備する
プロジェクトには、app/src/main/res/values/ 内にデフォルトの strings.xml が必要です。Android Studio では、新規プロジェクトを作成するとこのファイルが自動で作成されます。リソースディレクトリの設定方法については、Android の localization guide を参照してください。
CLI を設定する#
プロジェクトルートに i18n.json ファイルを作成します。android バケットを指定すると、CLI は Android の XML リソースを解析し、ロケールごとに個別のファイルを生成します。
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"]
}
}
}[locale] プレースホルダーは、実行時に設定済みの各ロケールコードに展開されます。CLI はこのパターンにソースロケールを当てはめるため、source: "en" の場合は values-en/strings.xml を探します。ターゲットロケールでは、values-es/strings.xml や values-fr/strings.xml などが生成されます。
デフォルトロケールのディレクトリをつなぐ#
Android ではデフォルトの文字列を values/(ロケール接尾辞なし)に保存しますが、CLI は [locale] をそのまま解釈して values-en/strings.xml を探します。この 2 つの規約をつなぐために、symlink を作成してください。
cd app/src/main/res
ln -s values values-enこれにより、ソース文字列は values/strings.xml(Android が期待する場所)と values-en/strings.xml(CLI が参照する場所)の両方で利用できるようになります。symlink はリポジトリに commit してください。git は macOS と Linux で symlink をネイティブに追跡できます。
Windows
Windows 上の Git では、設定によって symlink が通常のテキストファイルとしてチェックアウトされる場合があります。Windows を使っている場合は、clone 前に git config core.symlinks true を実行するか、values/ ディレクトリを values-en/ にコピーしてください。
複数のリソースファイル
文字列を複数のファイル(たとえば strings.xml や arrays.xml)に分けている場合は、それらをすべて列挙してください。symlink はディレクトリ全体をカバーするため、values/ 内のすべてのファイルに values-en/ 経由でアクセスできます。
{
"buckets": {
"android": {
"include": [
"app/src/main/res/values-[locale]/strings.xml",
"app/src/main/res/values-[locale]/arrays.xml"
]
}
}
}ローカルで翻訳する#
API キーを設定して、CLI を実行します。
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runCLI はソースの strings.xml を読み込み、lockfile を使って未翻訳のエントリを特定し、その差分だけをローカライゼーションエンジン経由で翻訳して、結果をターゲットの values-[locale]/ ディレクトリに書き込みます。翻訳結果は任意のターゲットファイルを開いて確認できます。
開発中に特定のロケールだけを対象にする場合は、次を使います。
npx lingo.dev@latest run --target-locale es複数形#
Android では、複数形を扱うために <plurals> 要素と CLDR quantity strings(zero、one、two、few、many、other)を使います。必要な複数形カテゴリは言語によって異なり、英語では 2 つ(one と other)、ロシア語では 4 つ、アラビア語では 6 つ必要です。
CLI は翻訳時も <plurals> の構造を保ち、各ターゲットロケールに適した quantity エントリを生成します。たとえば、2 つのカテゴリを持つソースエントリがあると、
<plurals name="messages_count">
<item quantity="one">%d new message</item>
<item quantity="other">%d new messages</item>
</plurals>各ターゲット言語に対して正しいカテゴリが生成されます。ローカライゼーションエンジンは、各ロケールに適用される CLDR plural rules を理解しており、その言語に必要なカテゴリだけを生成します。
キーのロック#
ブランド名や API エンドポイント、書式パターンなど、一部の文字列値はすべての言語で同一のままにしたいことがあります。そうした場合は キーのロック を使うことで、翻訳せずに値をそのままコピーできます。
{
"buckets": {
"android": {
"include": ["app/src/main/res/values-[locale]/strings.xml"],
"lockedKeys": ["app_name", "api_base_url"]
}
}
}ロックされたキーは翻訳パイプラインを通さず、ソースからすべてのターゲットファイルへそのままコピーされます。
GitHub Actions で自動化する#
push のたびに翻訳を実行するには、.github/workflows/translate.yml にワークフローファイルを追加します。
翻訳は main に直接 commit されます。手間が少なく、小規模チームに最適です。
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lingo.dev
uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}API キーは、GitHub リポジトリの Settings > Secrets and variables > Actions で LINGODOTDEV_API_KEY として保存してください。
デプロイ前に検証する#
未翻訳の文字列が本番環境に含まれないようにするため、デプロイゲートとして --frozen フラグを使用します。翻訳が必要なエントリが 1 つでもある場合、CLI は非ゼロの終了ステータスを返します。
npx lingo.dev@latest run --frozenこれをビルド前の独立した CI ステップとして追加してください。
- name: Verify translations
run: npx lingo.dev@latest run --frozen