仕組み

@lingo.dev/compilerは、インテリジェントなコード解析とAI翻訳により、ビルド時にReactアプリケーションを多言語アプリに変換します。

ビルド時変換

従来のランタイムi18nライブラリ(i18next、react-intl)はランタイムで動作します。つまり、アプリの実行中に翻訳を読み込み、値を補間し、メッセージをフォーマットします。これにより、バンドルサイズ、ランタイムオーバーヘッド、複雑さが増加します。

@lingo.dev/compilerは異なる動作をします。ビルドプロセス中にコードを変換します。Reactコンポーネントはクリーンなままで、翻訳は最適化されたバンドルに事前コンパイルされます。

結果: ランタイムオーバーヘッドゼロ、バンドルサイズの削減、手動での翻訳キー管理が不要。

プロセス

1. AST解析

コンパイラはBabelを使用してReactコードを抽象構文木(AST)に解析します。JSXを走査し、翻訳可能なコンテンツを識別します。

  • テキストノード(<p>Hello</p>
  • 文字列属性(<img alt="Logo" />
  • テンプレート式内のテキスト(<p>Hello {name}</p>

コンパイラはReactコンポーネントの境界を理解し、正確な翻訳のためのコンテキスト情報を維持します。技術的な識別子、コードスニペット、翻訳不要な要素は自動的にフィルタリングされます。

2. コンテンツ抽出

翻訳可能な各文字列に対して、コンパイラは以下を実行します。

  • 安定したハッシュベースの識別子を生成
  • コンポーネントコンテキスト(ファイル、位置、周囲の要素)を保持
  • リッチテキスト構造を抽出(<strong><em>などのネストされた要素を処理)
  • 補間プレースホルダーを維持

このメタデータは.lingo/metadata.jsonに保存されます。これは、アプリ内のすべての翻訳可能なコンテンツを追跡するバージョン管理されたファイルです。

3. 翻訳生成

開発中、翻訳サーバーがオンデマンド翻訳を処理します。

  • 疑似翻訳モード(デフォルト): 即座に偽の翻訳を生成します。APIコストをかけずに何が翻訳されるかを確認するのに便利です。
  • 実翻訳モード: 設定されたLLMプロバイダー(Lingo.dev EngineまたはダイレクトLLM)を呼び出します。

翻訳サービスはステートレスであり、部分的な障害を適切に処理します。一部の翻訳が失敗した場合でも、キャッシュされた翻訳は引き続き使用されます。

4. コードインジェクション

コンパイラは翻訳ルックアップをJSXに注入します。

// Your source code
<p>Hello {name}</p>

// Transformed code (simplified)
<p>{t('abc123', { name })}</p>

t()関数は最適化され、自動的に注入されます。事前にロードされた翻訳辞書でハッシュベースのルックアップを実行します。

5. バンドル最適化

ビルド時に以下が実行されます。

  • ロケールごとのバンドルが作成されます
  • 使用されている翻訳のみが含まれます
  • デッドコード除去により未使用の翻訳が削除されます
  • 辞書はコンポーネントごとにツリーシェイキングされます

開発ワークフロー

開発モード

{
  dev: {
    usePseudotranslator: true,
  }
}

npm run devを実行すると以下が行われます。

  1. コンパイラが翻訳サーバーを起動します(ポート60000-60099を自動検索)
  2. アプリが翻訳をサーバーにリクエストします
  3. 疑似翻訳機能が即座に偽の翻訳を生成します
  4. 翻訳は.lingo/metadata.jsonにキャッシュされます
  5. HMRは通常通り動作し、状態は保持されます

開発ウィジェット(有効な場合)を使用すると、ブラウザ内で翻訳を編集し、変更をリアルタイムで確認できます。

本番モード

{
  buildMode: "cache-only",
}

npm run buildを実行すると以下が行われます。

  1. 翻訳サーバーは起動しません
  2. .lingo/metadata.jsonからのキャッシュされた翻訳のみが使用されます
  3. 翻訳が不足している場合、明確なエラーでビルドが失敗します
  4. API呼び出しは行われず、APIキーは不要です

なぜキャッシュのみなのか? 本番環境では、決定論的なビルドが必要です。翻訳は本番ビルド中ではなく、CI(APIキーがある場所)で生成する必要があります。

推奨ワークフロー

ローカル開発:

  • 疑似翻訳機能を使用
  • 高速なフィードバックループ
  • APIコストなし

CI/CD:

{
  buildMode: "translate",
  dev: {
    usePseudotranslator: false,
  }
}
  • 実際の翻訳を生成
  • デプロイごとに1回実行
  • .lingo/の変更をコミット

本番ビルド:

{
  buildMode: "cache-only",
}
  • 事前生成された翻訳を使用
  • APIキー不要
  • 高速で決定論的なビルド

アーキテクチャ

コンパイラは明確な関心の分離を中心に構成されています:

メタデータマネージャー

  • .lingo/metadata.jsonのCRUD操作
  • ファイルロックによるスレッドセーフ
  • 翻訳用のハッシュベース識別子

翻訳サービス

  • 翻訳ワークフローのオーケストレーション
  • キャッシュ戦略の処理
  • 部分的な失敗の管理
  • 成功した翻訳とエラーの両方を返却

トランスレーター(ステートレス)

  • Pseudotranslator: 即座の疑似翻訳
  • LCP Translator: Lingo.dev Engineとの統合
  • LLM Translators: プロバイダーとの直接統合
  • 組み込みキャッシュなし—サービス層が処理

翻訳サーバー

  • 開発用HTTPサーバー
  • リアルタイムウィジェット更新のためのWebSocketサポート
  • 自動ポート管理
  • バッチリクエスト処理

実装の詳細については、ソースコードアーキテクチャドキュメントを参照してください。

フレームワーク統合

Next.js

コンパイラはwithLingo()ラッパー経由で統合されます:

  • WebpackとTurbopackの両方をサポート
  • React Server Componentsと連携
  • 遅延プラグイン読み込みのための非同期設定
  • 自動ロケールベースルーティング(設定されている場合)

Vite

コンパイラはlingoCompilerPlugin経由で統合されます:

  • Unpluginベース(Vite、Webpack、Rollupで動作)
  • 完全なHMRサポート
  • 効率的な開発サーバー統合
  • 自動仮想モジュール生成

よくある質問

Server Componentsで動作しますか? はい。Next.jsでは、コンパイラはServerとClient Componentsの両方を変換します。翻訳の検索はアイソモーフィックに動作します。

コード分割はどうなりますか? 翻訳はコンポーネントと一緒に自動的に分割されます。各チャンクには必要な翻訳のみが含まれます。

翻訳はどのようにキャッシュされますか? すべての翻訳は.lingo/metadata.jsonに保存されます。このファイルはバージョン管理され、翻訳キャッシュとして機能します。コンパイラはコンテンツハッシュを使用し、新しいテキストまたは変更されたテキストのみが再翻訳をトリガーします。

翻訳が失敗した場合はどうなりますか? サービスは部分的な結果を返します。成功した翻訳はキャッシュされて使用され、エラーはデバッグ用のコンテキストと共にログに記録されます。アプリは壊れません。キャッシュされた翻訳またはソーステキストにフォールバックします。

変換されたコードを確認できますか? はい。ビルド出力で変換されたファイルを確認できます。変換は最小限です。ハッシュベースのルックアップを使用した t() 関数呼び出しのみです。

次のステップ