クラシックな Vite スタック上に構築された Lovable アプリをローカライズする最善の方法は、ランタイム翻訳ウィジェットを後付けすることではなく、ハードコードされた文字列を抽出してリポジトリにコミットする Lingui の PO カタログにまとめることです。Lovable アプリはクライアントレンダリングの React SPA なので、フックできるサーバーレンダーが存在せず、確実な選択肢は自分のリポジトリに存在し、ビルドと一緒に出荷される翻訳ファイルです。globalize.now は AI を活用したローカライゼーション基盤で、この抽出作業を行い、Git へのプッシュのたびにカタログを同期し続けます。一度セットアップすれば、ロケールファイルを手作業で管理する必要は二度となくなります。


あなたの Lovable アプリはどちらのスタックですか?クラシックな Vite か、それとも TanStack Start か?

まずファイルツリーを確認してください。Lovable には2種類の異なるスタックがあり、それぞれ必要な i18n セットアップが異なるからです。src/pages/Index.tsx、src/main.tsx、vite.config.ts が見えるなら、Lovable のデフォルトであるクラシックな Vite + React SPA スタックです。TanStack Start プロジェクトの場合は、代わりに src/routes/、src/router.tsx、src/routeTree.gen.ts、src/server.ts があります。

スタックはプロジェクト作成時に決まり、後から切り替えることはできないため、この選択はすでに済んでいます。クラシックな Vite スタックはすべてブラウザ内でレンダリングされ、デフォルトではサーバーサイドのデータ取得を行いません。本ガイドはこのクラシックな Vite SPA を対象としています。ファイル構成が TanStack Start のレイアウトと一致する場合は、代わりにLovable 向け TanStack Start i18n ガイドを参照してください。サーバーレンダリングによって翻訳の読み込み方法が変わるためです。


なぜ Vite SPA の Lovable アプリは i18n ツールから見落とされがちなのか?

ツール開発の関心が Lovable の新しい TanStack Start + SSR デフォルトへ移り、クラシックな Vite SPA が手薄になっているからです。実際にはこちらの方が依然として最も一般的な Lovable スタックであるにもかかわらずです。ここ数か月、Lovalingo、Intlayer、Paraglide をはじめとする Lovable 向けローカライゼーションツールは、そろって SSR ありの TanStack Start へガイドの照準を切り替えました。

その結果、空白地帯が生まれています。クライアントレンダリングの SPA には、SSR 向けガイドが見落としている現実的な制約があります\:サーバーレンダーがないため翻訳済みマークアップを差し込む場所がなく、バンドル全体がブラウザ上で読み込まれ、遅延読み込みされるスクリプトは英語 UI の上に上書きされてしまいます。良いニュースは、クラシックなスタックにはすっきりとした、十分にサポートされた解決策があるということです。ただ、声の大きいツールたちが別のスタックを追いかけるのに忙しく、この方法はほとんどの開発者の耳に届いていないだけなのです。


コミット済みカタログとランタイム翻訳ウィジェットの違いは何か?

コミット済みカタログはリポジトリにチェックインされ、ビルド時にバンドルされる翻訳ファイルです。一方、ランタイムウィジェットは、英語 UI がすでに読み込まれた後にブラウザ上でテキストを差し替えるサードパーティのスクリプトです。この違いが、Vite SPA にとって重要な3つのポイントを左右します。

第一に、フラッシュとレイアウトシフトです\:ウィジェットはまず英語を表示してから書き換えるため、ユーザーには目に見える切り替わりが発生し、レイアウトがガタつくこともあります。コミット済みカタログなら、最初の描画時点で正しい言語が表示されます。第二に、インデックス可能性です\:ビルドに含まれる文字列はソースの一部として扱われますが、ウィジェットのテキストは後から挿入されるため、クローラーが読み取りにくくなります。第三に、所有権です\:コミット済みカタログは自分のリポジトリにある自分のファイルなので、アプリがドイツ語や日本語を話し続けるために外部の何かが稼働し続ける必要はありません。


Lingui を使って Lovable の Vite アプリに i18n を追加するには?

Lingui を i18n レイヤーとして導入し、文字列をラップして、Vite プラグインにカタログをコンパイルさせましょう。Lingui は専用の Vite プラグインと PO ベースのカタログ形式を備えた軽量な i18n フレームワークで、クライアントレンダリングの SPA にまさに求められるものです。

まずパッケージをインストールします。Lingui は CLI、Vite プラグイン、React ランタイムをそれぞれ分割して提供しています\:

npm install --save-dev @lingui/cli @lingui/vite-plugin @rolldown/plugin-babel
npm install @lingui/core @lingui/react

次に、vite.config.ts でプラグインを登録し、ソースとロケールフォルダを指す lingui.config.ts を追加します\:

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { lingui } from "@lingui/vite-plugin";

export default defineConfig({
  plugins: [react(), lingui()],
});
// lingui.config.ts
import { defineConfig } from "@lingui/cli";

export default defineConfig({
  locales: ["en", "de", "fr"],
  sourceLocale: "en",
  catalogs: [
    {
      path: "src/locales/{locale}/messages",
      include: ["src"],
    },
  ],
});

そして、ハードコードされた JSX テキストを裸の文字列のままにせず、Trans マクロでラップします\:

// before
<h1>Create your account</h1>

// after
import { Trans } from "@lingui/react/macro";
<h1><Trans>Create your account</Trans></h1>

それでは抽出しましょう。CLI が src ディレクトリをスキャンし、ロケールごとに PO カタログを書き出します。例えば src/locales/en/messages.po のように\:

npx lingui extract

各言語について msgstr フィールドを埋めるか、この作業を自動化レイヤーに任せます(次のセクションを参照)。個別にコンパイルコマンドを実行する必要はありません。開発時にもビルド時にも、@lingui/vite-plugin が PO カタログをその場でコンパイルしてくれるからです。

最後に、ランタイムでロケールを有効化して言語切り替え機能を追加します\:

import { i18n } from "@lingui/core";
i18n.activate("de");

これがクラシックな Vite スタックにおける一連の流れのすべてです\:インストール、ラップ、抽出、翻訳、切り替え。翻訳内容そのもの以外は、すべてリポジトリの中に存在します。


globalize.now はプッシュのたびにこれをどう自動化するのか?

globalize.now はリポジトリを監視し、Git へのプッシュのたびに抽出と入力の作業を代行することで、手動での手順をなくします。Lovable のコードベースで新たにハードコードされた文字列を見つけ出し、Lingui が求めるキーと PO エントリを生成し、翻訳を作成した上で、更新されたカタログをコミットして戻します。これにより、コマンドを実行しなくても src/locales フォルダは常に最新の状態に保たれます。

globalize.now でリポジトリを一度接続すれば、監視が始まります。エディタ側からセットアップしたい場合は、スキルをインストールしてください\:

npx skills add globalize-now/globalize-skills

Lovable の場合は具体的に、ワークスペースに lovable-i18n スキルを追加した上で、Lovable に i18n をセットアップするよう指示するだけです。ランタイムは引き続き Lingui のままなので、アプリのレンダリング方法自体は何も変わりません。変わるのは、ロケールファイルの世話をする必要がなくなるという点です。これは、私たちのバイブコーダー向けワークフローや開発者向けセットアップが前提としている、一度セットアップすればあとはプッシュのたびに自動同期されるという同じモデルです。

料金体系は個人開発者にもわかりやすく、ワークスペースごとに月額20ユーロで、シート課金も言語数課金もありません。それに加えて、実際に使用した翻訳分の料金がかかります。新規ワークスペースにはカード登録不要で5ユーロ分のサインアップクレジットが付与され、小規模なアプリを最初から最後まで翻訳するには十分な量です。


代わりにランタイムウィジェットを使うべきか? Lovalingo が教えてくれたこと

翻訳を特定のベンダー一社に依存させたくないなら、答えはノーです。ランタイム翻訳ウィジェットは最初こそ手軽ですが、アプリが他社のサーバーが稼働し続けることに依存する形になり、その依存には現実的な破綻のリスクが伴います。

Lovable の開発者に人気のランタイムウィジェット Lovalingo は、2026年8月31日をもってサービスを終了すると発表しました。新規登録は受け付けておらず、後継サービスも指定されていません。Lovalingo自身の移行ガイダンスでは、ユーザーに対してプロジェクト所有の国際化対応へ移行するよう案内しており、これはまさに本ガイドで解説しているコミット済みカタログの方式そのものです。ウィジェットの提供元がサービスを終了すれば、挿入されていた翻訳は消え、UI は英語表示に戻ってしまいます。一方、リポジトリ内のファイルはそうはなりません。すでにウィジェットを利用している場合は、Lovalingo サービス終了への移行ガイドで移行手順を解説していますし、より広い視点でのプッシュのたびに翻訳が壊れる問題が、AI が構築するアプリにとってコミット済みカタログが優れている理由を説明しています。

globalize.nowは、ハードコードされたアプリ内テキストを翻訳可能なロケールファイルに変換し、リリースのたびに自動で最新の状態を保ちます。

globalize.nowを無料で試す