文字列を関数呼び出しで囲むのはやめましょう
t("Hello, {name}", { name }) の問題点
React アプリを国際化したことがあるなら、次のようなコードを書いたことがあるはずです。
const gt = useGT();
return <p>{gt("Hello, {name}! You have {count} items.", { name, count })}</p>;動作はします。ですが、かなり面倒です。ICU メッセージ形式の構文を手で書き、オブジェクト引数で変数名を毎回重ねて指定し、さらに React コンテキストを必要とする Hook から t を取り出さなければなりません。既存の文字列に薄くレイヤーを載せるだけのもののはずなのに、お作法が多すぎます。
しかも、もっと厄介です。React コンポーネントの外で翻訳が必要になった瞬間――たとえばユーティリティ関数、イベントハンドラー、サーバーアクションなどでは――そこで Hook は使えないため、回避策に頼ることになります。
テンプレートリテラルはそのまま使えます
t マクロを使うと、同じコードは次のようになります。
import { t } from "gt-react/browser";
return <p>{t`Hello, ${name}! You have ${count} items.`}</p>;以上です。標準的な JavaScript のテンプレートリテラル構文です。ICUプレースホルダーも、オプションオブジェクトも、Hookも、コンテキストプロバイダーも不要です。通常のテンプレートリテラルと同じように文字列を記述すれば、あとはコンパイラが処理します。
build 時に、GT コンパイラは次のように変換します。
t`Hello, ${name}!`into:
t("Hello, {0}!", { "0": name })tagged template は単なるシンタックスシュガーで、runtime の動作は文字列を渡して t() を呼び出す場合とまったく同じです。ですが、開発者体験は大幅に向上します。
React コンテキストへの依存はもうありません
ここでの大きな変更点は、構文ではなくアーキテクチャです。gt-react/browser からエクスポートされる t 関数は、React コンテキストを使いません。Hook も不要です。コンポーネント内で呼び出す必要もありません。
つまり、t は次のような場所で使えます。
- イベントハンドラー:
onClick={() => alert(tSaved!)} - ユーティリティ関数:
function formatError(code) { return tError: $} - 定数や設定:
const LABELS = { save: tSave, cancel: tCancel} - クライアントで JavaScript が実行されるあらゆる場所
従来のパターン、つまり useGT() が React コンテキストにスコープされた関数を返す方式は、ボトルネックでした。翻訳は本来 React の関心事ではなく、文字列の関心事なのに、それを React の関心事として扱わざるを得なかったからです。
グローバル登録
すべてのファイルで t をインポートしたくない場合は、t をグローバルに登録できます:
// アプリのエントリーポイントに追加
import "gt-react/macros";これにより globalThis.t が設定され、import しなくてもどこからでも tagged template を使えるようになります。コンパイラはこれを自動的に検出します。t がすでに GT 由来のソースから import されていれば、重複する import は挿入されません。まだ import されておらず、t を tagged template として使っている場合は、コンパイラが import を自動で挿入します。
文字列連結にも対応しています
マクロ展開はtagged templateだけに限りません。引数として渡されたテンプレートリテラルや、文字列連結にも対応しています。
// テンプレートリテラルを引数として渡す場合も変換される
t(`Welcome back, ${user}`)
// 文字列連結も変換される
t("Hello, " + name + "! Welcome.")どちらも、ビルド時には同じ t("...", { ... }) 呼び出しに正規化されます。
はじめに
1. gt-react の最新バージョンをインストールする
npm install gt-react@latest2. t マクロを使用する
次のように直接インポートすることもできます。
import { t } from "gt-react/browser";
export function Greeting({ name }) {
return <p>{t`Hello, ${name}!`}</p>;
}またはグローバルに登録して、インポートを省略します:
// app/layout.tsx またはエントリーポイント
import "gt-react/macros";// アプリのどこでも使用可能
export function Greeting({ name }) {
return <p>{t`Hello, ${name}!`}</p>;
}3. これで完了です
GT コンパイラ が build 時に変換を自動的に処理します。追加の設定は不要です。マクロ展開はデフォルトで有効になっています。
t マクロは API 面では小さな変更ですが、その背景にはより大きな考え方の転換があります。翻訳は、フレームワーク固有の回避策のようなものではなく、JavaScript に自然になじむものであるべきです。文字列は自然に書いてください。あとはツールチェーンに任せれば大丈夫です。