Lovableアプリは完全に翻訳されていても、ドイツ語ユーザーに「5 элемент」と表示したり、価格を「1,234.50」と表示したりすることがあります。原因は、英語向けに書かれた複数形・フォーマットのロジックがコンポーネントに残っていることです。globalize.nowはAI搭載のローカライズ基盤で、文字列をコミット済みのカタログに保持します。以下の手順では、複数形のルールをコードではなくカタログ側に持たせます。
Lovableアプリを翻訳すると複数形が崩れるのはなぜ?
複数形のルールが翻訳ではなくコンポーネントの中にあるからです。生成されがちなパターンは次のようなものです。
<p>{count} {count === 1 ? "item" : "items"} in your cart</p>
この1行は英語の文法をハードコードしています。翻訳者は単語を変えられても === 1 の判定は変えられず、数値が必ず先頭に来るという語順も固定されています。英語の形は2つですが、ロシア語には4つあり、「1 элемент」「2 элемента」「5 элементов」「1,5 элемента」のように、それぞれ異なる語尾が必要です。
先にルーティングを設定した場合(Lovableアプリを多言語化する方法を参照)、次にユーザーが気づくバグが複数形です。エラーは出ませんが、文が単純に間違っているからです。
ステップ1: 翻訳者が変更できる複数形を書くには?
ICU複数形メッセージを使い、ルールを翻訳側へ移します。Linguiでは、Plural コンポーネントと plural マクロのどちらでも生成できます。
import { Plural } from "@lingui/react/macro";
<p>
<Plural value={count} one="# item in your cart" other="# items in your cart" />
</p>
JSX以外の文字列では、coreパッケージのマクロを使います。
import { plural } from "@lingui/core/macro";
const label = plural(count, { one: "# file", other: "# files" });
# は数値に置き換えられます。Linguiのドキュメントにあるとおり、記述が必要なのはソース言語に必要な形だけで、other は必須です。_0="Your cart is empty" のような完全一致を使えば、英語のゼロの場合も別の分岐なしで処理できます。
Lovableのデフォルト構成ごとにセットアップは異なりますが、このAPIは共通なので、同じコンポーネントをVite SPAでもTanStack Startのプロジェクトでも使えます。
複数形を抽出すると、カタログはどうなる?
文字列ごとに標準ICU構文のメッセージが1つ、POファイルとしてリポジトリに保存されます。翻訳者(人間でもAIでも)が、その言語に必要な形を埋めていきます。
msgid "{count, plural, one {# item in your cart} other {# items in your cart}}"
msgstr "{count, plural, one {# товар в корзине} few {# товара в корзине} many {# товаров в корзине} other {# товара в корзине}}"
ロシア語の other の形は1,5のような小数もカバーしており、これが属格単数と一致する理由です。カタログはコミット済みのファイルなので、複数形の変更も他のコードと同様にプルリクエストでレビューできます。構文自体については、ICU MessageFormatとはを参照してください。
oneとother以外が必要な言語は?
Unicode CLDRは、zero・one・two・few・many・otherの6つの複数形カテゴリを定義しています。各言語はこのうち一部を使い、other はどの言語でも必須です。
| 言語 | 使用するカテゴリ |
|---|---|
| 日本語、中国語 | other |
| 英語 | one, other |
| ロシア語 | one, few, many, other |
| アラビア語 | zero, one, two, few, many, other |
CLDR仕様では、ウェールズ語も6つすべてを使うとされています。これを暗記する必要はありません。必要なのは、各言語が自分の形を埋められるカタログ形式であり、ICUメッセージ入りのPOがまさにそれです。
Lovableが三項演算子による複数形を再び書かないようにするには?
Lovableが指示を読む場所にルールを置きましょう。Lovableは新機能をプロンプトで依頼するとコンポーネントを再生成するため、ルールなしで書かれた新機能では三項演算子が復活してしまいます。
Knowledgeまたは AGENTS.md に次を追加します。
Never hand-build plurals or number formats. Use the Lingui Plural component
or plural() macro for every count. Use Intl with the active locale for every
date, number and price.
lovable-i18n スキルは、この種のルールを自動で書き込みます。その仕組みはLovableのi18nスキルの機能で解説しています。次に生成された機能のあと、差分で === 1 と !== 1 を検索し、ルールが守られていることを確認しましょう。
ステップ2: 日付と通貨をロケールに合わせてフォーマットするには?
アクティブなロケールを指定して Intl を使います。Linguiの i18n オブジェクトにも i18n.date() と i18n.number() がありますが、i18n.locale を渡して Intl を直接呼び出せば、フォーマットオプションが自分のコード上で明示されます。
import { useLingui } from "@lingui/react";
export function Price({ amount, currency }: { amount: number; currency: string }) {
const { i18n } = useLingui();
return (
<span>
{new Intl.NumberFormat(i18n.locale, { style: "currency", currency }).format(amount)}
</span>
);
}
export function OrderDate({ date }: { date: Date }) {
const { i18n } = useLingui();
return <time>{new Intl.DateTimeFormat(i18n.locale, { dateStyle: "long" }).format(date)}</time>;
}
同じ1234.5ユーロでも、ロケールごとに区切り文字や通貨記号の位置が異なる文字列として表示されます。フォーマットが通貨を換算することはありません。ユーロで保存した価格は、どの言語でもユーロのままです。データベースでは、価格ごとに通貨コードを並べて保存しておきましょう。
ステップ3: リリース前にすべての複数形カテゴリをテストするには?
ブラウザに、ある数値がどのカテゴリに該当するかを問い合わせ、各カテゴリに形が用意されているか確認します。
const ru = new Intl.PluralRules("ru");
[1, 2, 5, 21, 1.5].map((n) => ru.select(n));
// ["one", "few", "many", "one", "other"]
const ar = new Intl.PluralRules("ar");
[0, 1, 2, 3, 11, 100].map((n) => ar.select(n));
// ["zero", "one", "two", "few", "many", "other"]
リリースする言語ごとにテストを1つ追加します。各カテゴリの数値でコンポーネントをレンダリングし、形の欠落によるフォールバックが起きないことをアサートしてください。そのうえで、ロシア語とアラビア語のページをブラウザで一度目視確認しましょう。カタログで few が欠けていてもエラーにはならず、語尾が間違った形で表示されるだけです。
以前ランタイムウィジェットを使っていた場合、何が変わる?
ランタイムウィジェットは、ロード後にレンダリング済みのテキストを翻訳するため、コード内の複数形ルールを認識できません。翻訳をリポジトリに移すことが重要なのは、このためでもあります。Lovalingoは2026-08-31にサービスを終了しました。カタログをリポジトリで管理するようになると何が変わるかは、移行ガイドと比較ページで解説しています。
globalize.nowでは、リポジトリを一度接続するだけで、コードベースがアプリ内で変換されます。その後はプッシュジョブが新しいカタログ単位を翻訳し、結果はプルリクエストとして届きます。LovableはGitHubから同期するため、複数形もほかの変更と同じ流れでアプリに反映されます。セットアップはLovable連携ページに、ダッシュボードを使わないワークフローはダッシュボードなしでLovableアプリをローカライズする方法にまとめています。
globalize.nowは、ハードコードされたアプリ内テキストを翻訳可能なロケールファイルに変換し、リリースのたびに自動で最新の状態を保ちます。
globalize.nowを無料で試す