Lingo.dev の CLI と localization API は、メールのローカライズに 2 つのパターンをサポートしています。1 つはビルド時にテンプレートファイルを翻訳してロケールごとのテンプレートを配信する方法、もう 1 つは送信前に実行時でコンテンツを翻訳する方法です。どちらも、用語集ルール、ブランドボイス、モデル選択が自動で適用される設定済みの ローカライゼーションエンジン を通して実行されます。
アプローチを選ぶ#
| アプローチ | 最適な用途 | 仕組み |
|---|---|---|
| ビルド時(CLI) | テンプレートファイル - react-email の JSON 文字列 | リポジトリ内のファイルを翻訳し、ロケールごとのテンプレートをデプロイ |
| 実行時(API) | 動的コンテンツ、ESP 側でレンダリングされるテンプレート | 送信前に ローカライゼーション API を呼び出し、翻訳済みコンテンツをメールプロバイダーに渡します |
どのアプローチを選ぶ?
翻訳対象のメール文面がリポジトリ内のリソースファイルとして管理されている場合は、ビルド時のアプローチを使います。メール内容が動的に生成される場合や、メールサービスプロバイダー側に保存されている場合は、実行時のアプローチを使います。
前提条件#
すべての翻訳はローカライゼーションエンジンを通ります。これは、使用するLLMモデル、用語集、ブランドボイス、適用ルールを決める設定です。まずはLingo.devのダッシュボードで作成し、続いてCLIをインストールして認証してください。
npm install -g @lingo.dev/cli
lingo loginCLI の利用には Node 22+ が必要です。CI では、LINGO_API_KEY を実行する代わりに lingo login を設定してください。
ビルド時のローカライズ#
CLI は JSON リソースファイルからメールコンテンツを翻訳します。翻訳対象の文面を JSON に切り出して CLI から指定すれば、ソースファイルと並んでロケールごとのファイルが生成されます。
react-email テンプレートは、HTML をレンダリングする React コンポーネントです。翻訳対象の文字列を react-i18next のような i18n ライブラリで JSON リソースファイルに切り出し、その JSON ファイルを CLI で翻訳します。
設定ファイルをひな形から作成するには lingo init を、組織とエンジンを紐づけるには lingo link を実行します。生成される .lingo/config.json は次のようになります。
{
"orgId": "org_abc123",
"engineId": "eng_abc123",
"sourceLocale": "en",
"targetLocales": ["es", "fr", "de", "ja"],
"files": [{ "pattern": "emails/locales/en.json" }]
}ロケールはパスに含まれます。CLI はパターン内のソースロケールを各ターゲットロケールに置き換えるため、emails/locales/en.json から emails/locales/es.json、emails/locales/fr.json などが生成されます。.lingo/config.json はリポジトリにコミットしてください。
初回はすべてのロケールを翻訳し、その後は変更があったものだけを翻訳します。
lingo push --backfill-missing # first run / new locale
lingo push # delta on later runsレンダリング時にロケールをメールコンポーネントに渡し、対応する JSON ファイルを読み込みます。react-email の render() 関数は、送信可能なロケール別の HTML を生成します。
直近の push 実行結果をいつでも取得するには、lingo pull を使います。変更を書き込まずに翻訳が最新かどうかを確認するには(たとえば CI で)、lingo check を使います。
実行時のローカライズ#
メールコンテンツが動的な場合、たとえばパーソナライズされた通知、ユーザー生成コンテンツの要約、CMS に保存されたマーケティングコピーなどは、送信前に実行時で翻訳します。これは Translation API guide で説明しているパターンに基づいています。
async function sendLocalizedEmail(userId, templateId, content) {
const user = await db.users.findById(userId);
const response = await fetch("https://api.lingo.dev/process/localize", {
method: "POST",
headers: {
"X-API-Key": process.env.LINGODOTDEV_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
engineId: "eng_abc123",
sourceLocale: "en",
targetLocale: user.locale,
data: {
subject: content.subject,
preheader: content.preheader,
body: content.body,
},
}),
});
const { data } = await response.json();
await emailProvider.send({
to: user.email,
subject: data.subject,
html: renderTemplate(templateId, data),
});
}ベストプラクティス#
| 項目 | 推奨事項 |
|---|---|
| 件名 | 50 文字以内に収めてください。ブランド名を翻訳対象外に固定するには glossary を使います。 |
| プレビューテキスト | 本文とは分けて翻訳してください。メールクライアントでは独立して表示されます。 |
| ブランドボイス | ローカライゼーションエンジンで ロケールごとのトーン を設定してください。日本語のマーケティングメールには、ドイツ語とは異なる文体が必要です。 |
| RTL 言語 | アラビア語、ヘブライ語、ペルシャ語では、メールクライアント上でレンダリング結果をテストしてください。HTML dir="rtl" の扱いはクライアントごとに異なります。 |
| キーの固定 | 翻訳してはいけない URL、製品名、法的識別子には locked keys を使ってください。 |
