戻る

gt-react@10.12.0

Ernest McCarter avatarErnest McCarter
gt-reactgt-i18nv10.12.0tstring-translationbrowsersynchronousi18n

概要

gt-react は、ブラウザーでモジュールレベルの文字列翻訳を同期的に行うための t() 関数をエクスポートするようになりました。

これまで、gt-react で文字列を翻訳するには、useGT のような React のコンテキストベースのフックが必要でした。フックはコンポーネント内ではうまく機能しますが、よくあるケースの 1 つには対応できません。それは、React コンポーネントの外側で、レンダリング前に、通常のユーティリティファイル内で、モジュールレベルの文字列を翻訳することです。

t() はそのギャップを埋めます。これは、ブラウザーコード内のどこからでも呼び出せる同期関数です:

import { t } from 'gt-react/browser';

const greeting = t('Hello, world!');

フックも非同期も、コンポーネントツリーも不要です。

このアプローチを採用する理由

この PR の核となるアイデアは、翻訳の仕組みを React のコンテキスト方式から離して試してみることです。コンポーネントツリーの外で動作することで、t() はより興味深いパターン、とりわけモジュールレベルでの翻訳を可能にします。文字列はレンダリングされる場所ではなく、定義された場所で翻訳できます。

これにはトレードオフがあります:

  • クライアントサイドのみ。 t() はクライアントサイドの React アプリケーションでのみ動作します。アプリがレンダリングされる前に翻訳を読み込むため、ブラウザーでのモジュール実行に依存します。
  • 言語の切り替えにはページ全体の再読み込みが必要。 翻訳はモジュールの読み込み時に確定されるため、ロケールを切り替えるにはモジュールを再実行する必要があります。つまり、ページ全体の再読み込みが必要です。セッションの途中で言語をホットスワップすることはできません。

一方で、開発者体験は大幅に向上します。フックで文字列をラップする必要も、コンポーネントレベルの煩雑な実装も、非同期の境界もなく、必要なのは関数呼び出しだけです。

既存の React コンテキスト方式 (useGT<T> など) がなくなるわけではありません。これは、こうしたトレードオフを許容できるプロジェクトに向けた追加の選択肢です。

仕組み

t() は、事前に読み込まれた翻訳を同期的に解決します。これらの翻訳は、新しい非同期セットアップ関数 bootstrap() によって用意され、アプリがレンダリングされる前に現在のロケール向けのすべての翻訳が読み込まれます。

まず bootstrap() を実行するように、アプリのエントリポイントを変更する必要があります。通常は main.tsx ですが、index.html でエントリポイントを変更することもできます。

// bootstrap.tsx (新しいエントリーポイント)
import gtConfig from '../gt.config.json';
import { bootstrap } from 'gt-react/browser';

async function getTranslations(locale: string) {
  return import(`./_gt/${locale}.json`);
}

await bootstrap({
  ...gtConfig,
  getTranslations,
});

await import('./main.tsx');

getTranslations 関数は async です。まず翻訳を読み込み、その後で React アプリがインポートされて実行されます。この仕組みにより、t() はモジュールレベルでも利用できます。つまり、どのモジュールでも t() が呼び出される時点では、翻訳はすでに利用可能になっています。

これは、クライアントサイドの React アプリでのみ機能します。ブラウザで読み込むと、モジュールレベルのコードが再実行されるためです。また、翻訳済みコンテンツを切り替えるにはモジュールを再実行する必要があるため、ロケールの切り替えにはページ全体の再読み込みが必要です。

実験的: この機能は現在、クライアントサイド専用の React アプリケーションでのみ利用できます。

変数

t()msg() と同様に、変数の補間に対応しています:

import { t } from 'gt-react/browser';

t('Hello, {name}!', { name: 'John' });  // → "Hola, John!"

該当するケース

t() は、React コンポーネントツリーの外で翻訳が必要な場合に適しています。たとえば、定数ファイル、ユーティリティ関数、設定オブジェクト、ルーター定義、あるいはブラウザーでモジュールスコープで実行されるあらゆる処理です。

次の点に注意してください。

  • これはまだ gt-react システムのほかの部分とは統合されていません。 上で説明したブートストラップ設定を行う必要があります。これは単体のアプローチです。
  • クライアントサイドのみ。 サーバーサイドで翻訳する場合は、useGT のような React のコンテキストベースのフックを使用してください。

設計上の注意

t() はブラウザー専用です。サーバー上 (window が未定義の環境) で呼び出されると、警告をログに出力し、ソース文字列にフォールバックします。これは意図的な挙動です。サーバーサイドでの翻訳には、既存の React のコンテキストベースのフックを使用してください。


API リファレンス

パラメータ、戻り値の型、セットアップの詳細については、t() API の完全なリファレンスを参照してください。