Lingo.dev の CLI は、設定した ローカライゼーションエンジン を通じて Rails の config/locales YAML ファイルを翻訳します。Rails には i18n API が標準で組み込まれており、アプリ内の翻訳可能なテキストはロケールごとの YAML ファイルに保存されます。Lingo.dev はランタイム依存を追加することなく、既存のパイプラインに自然に組み込めます。
このガイドでは、Rails アプリをエンドツーエンドでローカライズする手順を紹介します。CLI の設定、ロケールごとの YAML ファイルの整理、リクエストごとのロケール切り替え、そして GitHub Actions による翻訳自動化までを扱います。
デモリポジトリ
一緒に進めるには、lingodotdev/ruby-on-rails-localization-example を clone または fork してください。このリポジトリには、config/locales YAML ファイル、Lingo.dev CLI の設定、GitHub Actions のワークフローを備えた、動作する Rails アプリが含まれています。
Rails のローカライズの仕組み#
Rails は config/locales/ 配下の YAML ファイルから翻訳を読み込みます。各ファイルはルートにロケールコードを持ち、I18n.t を使ってコードから参照する検索パスに対応した、ネスト構造のキーを含みます。
| レイヤー | 内容 | ファイル例 |
|---|---|---|
| UI 文言 | ボタン、ラベル、フラッシュメッセージ | config/locales/en.yml |
| メーラー文面 | ActionMailer の件名と本文 | config/locales/mailers.en.yml |
| モデルのエラー | バリデーションメッセージと属性名 | config/locales/activerecord.en.yml |
Rails の YAML ファイルでは、先頭のキーがそのままロケールコードになります。たとえば en:、es:、fr: です。CLI の yaml-root-key バケットはこの構造を理解しており、ローカライゼーションエンジンに送る前にロケールの接頭辞を取り除き、その後、ターゲットロケールコードを新しいルートキーとして持つ対応ファイルを書き出します。ネストされたキー、%{name} の補間トークン、CLDR の複数形カテゴリ(zero/one/two/few/many/other)はそのまま保持されます。
前提条件#
ローカライゼーションエンジンを作成する
CLI を実行するたびに、コンテンツは ローカライゼーションエンジン を通って処理されます。これは、どの LLM モデル、glossary、ブランドボイス、instructions を適用するかを決める設定です。Lingo.dev dashboard で作成し、API key を生成してください。
Ruby と Rails を確認する
このガイドは Rails 7.2 以上を対象としており、Ruby 3.1 以上が必要です。バージョンを確認してください。
ruby -v
rails -vNode.js を確認する
CLI の利用には Node.js 18 以上が必要です。
node -vRails i18n を設定する
このガイドでは、アプリがすでに config/locales/*.yml に翻訳を保存していることを前提としています。ビューやコントローラーに文字列がハードコードされている場合は、まずそれらを t() 呼び出しに切り出してください。たとえば、次のようなコードを置き換えます。
<h1>Welcome</h1>次のようにします。
<h1><%= t(".welcome") %></h1>その後、対応するキーを config/locales/en.yml に追加してください。移行手順の全体については、Rails の internationalization guide を参照してください。
翻訳ファイルを整理する#
Rails は config/locales/ 配下にある *.yml ファイルをすべて自動で読み込みます。ソースロケールは翻訳済みファイルと並べて配置し、ディレクトリ全体を信頼できる単一の情報源にしましょう。
config/locales/
en.yml # Source locale
es.yml # Generated by Lingo.dev
fr.yml
de.yml一般的な en.yml には、プレーンな文字列、ネストされた名前空間、%{name} の補間、複数形が混在しています。
en:
hello: "Hello"
home:
welcome: "Welcome, %{name}!"
cta: "Get started"
notifications:
unread:
zero: "No unread notifications"
one: "1 unread notification"
other: "%{count} unread notifications"
errors:
messages:
blank: "can't be blank"CLI を設定する#
プロジェクトルートに i18n.json ファイルを作成します。ロケールファイルを指す yaml-root-key バケットを定義してください。
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de"]
},
"buckets": {
"yaml-root-key": {
"include": ["config/locales/[locale].yml"]
}
}
}[locale] プレースホルダーは、設定された各ロケールコードに展開されます。source: "en" を使うと、CLI は config/locales/en.yml を読み込み、翻訳済みファイルを config/locales/es.yml、config/locales/fr.yml、config/locales/de.yml に書き出します。
Rails は en.yml と並んで mailers.en.yml、pages.en.yml などのファイルも問題なく読み込みます。追加のパターンは、yaml-root-key バケットの include 配列に加えてください。
{
"buckets": {
"yaml-root-key": {
"include": [
"config/locales/[locale].yml",
"config/locales/mailers.[locale].yml",
"config/locales/pages.[locale].yml"
]
}
}
}複数ロケール向けに Rails を設定する#
利用可能なロケールと、デフォルトで使うロケールを Rails に指定します。config/application.rb では次のように設定します。
module YourApp
class Application < Rails::Application
config.i18n.available_locales = [:en, :es, :fr, :de]
config.i18n.default_locale = :en
config.i18n.fallbacks = [:en]
end
endURL パラメータまたは Accept-Language ヘッダーをもとに、ApplicationController でリクエストごとのロケールを選択します。
class ApplicationController < ActionController::Base
around_action :switch_locale
private
def switch_locale(&action)
locale = params[:locale] || http_accept_locale || I18n.default_locale
I18n.with_locale(locale, &action)
end
def http_accept_locale
header = request.headers["Accept-Language"].to_s
header.scan(/[a-z]{2}/).find { |l| I18n.available_locales.map(&:to_s).include?(l) }
end
def default_url_options
{ locale: I18n.locale }
end
endビューで翻訳を表示する#
ERB テンプレートでは t と l ヘルパーを使います。キーの先頭にドットを付けると現在のビューパス基準で解決されるため、翻訳キーをそのテンプレートの近くに保てます。
<h1><%= t(".welcome", name: @user_name) %></h1>
<p><%= t("notifications.unread", count: @unread_count) %></p>
<%= link_to t(".cta"), signup_path, class: "btn-primary" %>レイアウトにロケール切り替えを追加します。
<nav>
<% I18n.available_locales.each do |locale| %>
<%= link_to locale.upcase, url_for(locale: locale) %>
<% end %>
</nav>ローカルで翻訳する#
API キーを設定して CLI を実行します。
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runCLI はバケットパターンに一致するすべてのファイルを読み込み、lockfile を使って未翻訳のエントリを特定し、その差分をローカライゼーションエンジン経由で翻訳して、各ターゲットロケールファイルに書き出します。ロケールのルートキー、ネストされた名前空間、%{name} 形式の補間トークン、複数形カテゴリは保持され、変更されるのは翻訳対象のテキストだけです。
開発中に特定のロケールだけを対象にするには、次を実行します。
npx lingo.dev@latest run --target-locale es初回の翻訳実行後は、新しい YAML ファイルを読み込ませるために Rails サーバーを再起動してください。
bin/rails serverスペイン語の表示を確認するには、/es にアクセスしてください。
複数形#
Rails は CLDR plural categories、つまり zero、one、two、few、many、other を使います。I18n.t に count: 引数を渡すと、Rails が対応するキーを選択します。
t("notifications.unread", count: 0) # => "No unread notifications"
t("notifications.unread", count: 1) # => "1 unread notification"
t("notifications.unread", count: 12) # => "12 unread notifications"CLI は各複数形バリエーションをその場で翻訳します。ターゲットロケールで英語の one/other より多くのカテゴリが必要な場合は、ソースの en.yml で定義しておいてください。
GitHub Actions で自動化する#
プッシュのたびに翻訳を実行するには、.github/workflows/translate.yml にワークフローファイルを追加します。
翻訳は main に直接コミットされます。手間がなく、小規模チームに最適です。
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 }}GitHub リポジトリの Settings > Secrets and variables > Actions に、API キーを LINGODOTDEV_API_KEY として保存してください。
デプロイ前に検証する#
未翻訳コンテンツが本番環境に出ないよう、デプロイゲートとして --frozen フラグを使います。翻訳が必要なエントリが1つでもある場合、CLI は非ゼロの終了ステータスを返します。
npx lingo.dev@latest run --frozenこれを、アセットのプリコンパイルやコンテナビルドの前に、独立した CI ステップとして追加してください。
- name: Verify translations
run: npx lingo.dev@latest run --frozen
- name: Precompile assets
run: bundle exec rails assets:precompile