gt-next@6.8.0
概要
一般に、コードベースが成熟するほど、コンテンツは断片化しやすくなります。 文章は関数、ユーティリティ、ロジック、サービスなどに散らばっていきます。
function getSubject(gender) {
return gender === "male" ? "boy" : "girl"
}
function getObject(toy, gender) {
return toy === "ball" ? "ball" : getSubject(gender)
}
function Component({ gender, toy }) {
return (
<>
<p>
The beautiful {getSubject(gender)} plays with the {getObject(toy, gender)}.
</p>
</>
)
}いざ国際化が必要になると、開発者は身動きが取れない設計にしてしまっていたことに気づきます。 文法上の一致、活用、複数ファイルにまたがる語順の変更といったものを扱うのは、大規模なリファクタリングなしでは現実的ではありません。 従来は、各文のあり得るあらゆるパターンを手作業で抽出し、翻訳辞書に追加するしかありませんでした。
gt-next 6.8.0 では、優れた i18n ライブラリはコードベースをライブラリに合わせさせるのではなく、コードベースに適応すべきだという考えを、さらに強く打ち出しています。
gt-next はすでにコンテンツをインラインで翻訳できますが、そのようなライブラリに不可欠な 2 つの基本機能がまだ不足しています。
(1) 文の断片化への対応と、(2) 文法上の一致・活用・語順の変化を保ったままコンテンツを再利用できることです。
翻訳の中で静的な関数呼び出しを直接使えるようにするため、<Static> コンポーネントを導入します。
function getSubject(gender) {
return gender === "male" ? "boy" : "girl"
}
function getObject(type, gender) {
return type === "ball" ? "ball" : getSubject(gender)
}
function Component({ gender, toy }) {
return (
<T>
<p>
The beautiful <Static>{getSubject(gender)}</Static> plays with the <Static>{getObject(toy, gender)}</Static>.
</p>
</T>
)
}重要な注意点
とはいえ、<Static> コンポーネントは慎重に、必要性を見極めたうえで使用することを強く推奨します。
<Static> コンポーネントは強力である一方、翻訳エントリ数が大幅に増える原因にもなり得ます。
使い方を誤ると、アプリケーションの読み込み時間に悪影響を及ぼす可能性があります。
<Static> の使い方
<T> コンポーネントや <Var> コンポーネントと同様に、<Static> コンポーネントも、CLI ツールに対して翻訳可能なコンテンツを探す場所と探さない場所を示すフラグです。
<Static> タグ内の関数呼び出しを CLI ツールが参照解決し、その関数が返しうるすべての内容を収集するよう指示します。
すべての return 文は、<T> コンポーネントで囲まれているものとして扱われます。
CLI ツールが関数呼び出しの取りうるすべての出力を見つけると、出力ごとに個別の翻訳エントリを作成します。 たとえば、次のコードでは、"The boy is beautiful" と "The girl is beautiful" という 2 つの個別の翻訳エントリが作成されます。 出力ごとに異なる翻訳エントリが存在するため、断片化された文でも 文法上の一致、活用、語順に対応できます。たとえば、"El niño es hermoso" や "La niña es hermosa" のようなケースです。
function getSubject(gender) {
return gender === "male" ? "boy" : "girl"
}
function Component({ gender }) {
return (
<T>
The <Static>{getSubject(gender)}</Static> is beautiful.
</T>
)
}制限事項と今後の改善点
乗算
前述のとおり、<Static> コンポーネントを多用しすぎると、大量の翻訳エントリが生成され、読み込み時間のパフォーマンスに悪影響を及ぼす可能性があります。
たとえば、2 つの <Static> コンポーネントがあり、それぞれが 2 通りの結果を返す関数呼び出しをラップしているコンポーネントを考えてみてください。
この場合、4 つの翻訳エントリが作成されます。
<Static> コンポーネントが 1 つ増えるごとに、翻訳数は各関数呼び出しの取りうる結果の数だけ増えていきます。
function getSubject(gender) {
return gender === "male" ? "boy" : "girl"
}
function getObject(toy) {
return toy === "ball" ? "ball" : "crayon"
}
function Component({ gender, toy }) {
return (
<T>
<Static>{getSubject(gender)}</Static> plays with the <Static>{getObject(toy)}</Static>.
</T>
)
}構文
すべての return 文は、<T> コンポーネントでラップされているものとして扱うことが重要です。
動的な変数や関数呼び出しは、引き続き <Var> コンポーネントでラップする必要があります。
現在、<Static> では子要素に関数呼び出ししか指定できませんが、今後はより複雑な式にも対応する予定です。
gt-next 6.8.0 時点では、静的関数で次の構文がサポートされています:
function getExamples(key) {
switch (key) {
case "string, number, and boolean literals":
if (condition1) {
return "The boy"
} else if (condition2) {
return 22
} else {
return true
}
case "jsx expressions":
return (
<>
Hello, <Static>{getTitle(title)}</Static>. How are you, <Var>{name}</Var>?
</>
);
case "ternary operators":
return condition ? "The boy" : "The girl"
case "function calls":
return otherStaticFunction();
}
}結論
gt-next 6.8.0 では、翻訳カバレッジや適切な文法上の一致を損なうことなく、文の断片化を解消するソリューションとして <Static> コンポーネントが導入されました。