皆さん、2022 年明けましておめでとうございます!今日は、ほとんどのブログ投稿とは異なること、つまり、バイリンガル ブログを純粋な Typescript で実装する方法についてお話したいと思います。
2015 年にこのブログを作成して以来、より多くの読者にリーチするためにバイリンガルにしたいと常に考えていましたが、2019 年末にようやく実装しました。 i18next などのサードパーティ ライブラリ。また、実装の型システムにおける Typescript の優れた機能に大きく依存しています。
私のソリューションは、おそらくプロの基準で最も「適切」またはスケーラブルではありませんが、個人のブログの特定のユースケースにうまく適合すると思います.いくつかの重要な利点があります:
- 型システムは、エントリの変換を忘れないことを保証します
- 言語ごとに任意に異なる Javascript を使用できるため、非常に柔軟です (この Web サイトは React で実装されているため、任意の JSX 1 を使用できます) )。これは、選択した言語で特定の UI 要素のみをレンダリングしたい場合に便利なプロパティです (たとえば、中国では Twitter が禁止されているため、このサイトの中国語版から Twitter リンクを削除しました)。
- ブログのためだけに i18n ライブラリを学ぶ必要はありません
したがって、多言語の個人 Web サイトを作成する場合は、同様のアプローチを使用することをお勧めします。
このブログでは、静的サイト ジェネレーター GatsbyJS を使用しています。静的サイト ジェネレーターに慣れていない場合は、"テンプレート" を使用して、Markdown などの形式のコンテンツを適切な HTML ページに変換することができます。 2
ブログ投稿用に、言語ごとに個別のマークダウン ファイルを用意しています。たとえば、この投稿の中国語版と、現在お読みになっているテキストは、別のマークダウン ファイルに保存されています。ただし、「テンプレート」にはまだ多くのテキストが含まれています。例としては、右側のサイドバーにある私の略歴、さまざまなメニュー項目、ブログ投稿タグなどがあります。
GatsbyJS の「テンプレート」は、特定の React コンポーネントである Javascript (そして、私は JS にトランスパイルする Typescript を使用することにしました) です。これらの React コンポーネントと翻訳は静的 HTML に組み込まれます。 一方、Python を使用して静的サイト ジェネレーターを使用するとします。その場合、理想的には、Web サイトの翻訳を動的にロードするオーバーヘッドを回避するために、ビルド時に翻訳を実行できるように、Python で国際化を実装する必要があります。
私の国際化の実装のほとんどは、translation.tsx ファイルにあります:
まず、en
があります すべての翻訳エントリを英語で保存するオブジェクト:
const en = {
ai: "AI",
algorithms: "Algorithms",
archive: "Archive",
...
};
en
以降 は単なるオブジェクトですが、jsx オブジェクトや関数などのよりエキサイティングなデータをエントリとして保存することもできます:
all_n_posts: (n: number) => (
<>
All <Link to={`/en/archive`}>{n} posts</Link>
</>
),
en
で 定義されたオブジェクトとして、typeof
によってその型を照会できます オペレーター:
export type Translations = typeof en;
このリフレクション機能は便利ですが、ほとんどのプログラミング言語にはありません。具体的には、型を自分で定義する手間を省きます。これは、言語機能が DRY 原則の達成にどのように役立つかを示す好例です。
今度は Translations
で en
の構造を反映した別のオブジェクトを作成できます オブジェクトですが、明示的な型要件があります:
const zh: Translations = {
ai: "AI",
algorithms: "算法",
archive: "博文目录",
...
};
このように、型システムにより、エントリの変換を忘れることはありません。
そして、すべての言語の翻訳を 1 つのオブジェクトにまとめることができます。このオブジェクトは、特定の翻訳エントリを照会するためのテンプレートのメイン エントリ ポイントとして機能します:
export const translations = {
en: en,
zh: zh,
};
次に keyof
を使用します 翻訳のキーの共用体型を取得する演算子:この場合、 "en" | "zh"
.keyof
Typescript のもう 1 つの優れたリフレクション機能です。ただし、オブジェクトではなく型を想定しているため、別の typeof
を適用する必要があります。 keyof
を適用する前の演算子 :
export type Language = keyof typeof translations;
たとえば、現在の言語をパラメーターとして渡す場合など、言語の明示的な型注釈が必要な場合は常に、上記の共用体型を使用します。
最後に Object.keys
を使用します 言語のリストを取得して、すべての言語をループできるようにします。
export const languages = Object.keys(translations) as Language[];
この Web サイトはバイリンガルのみであり、他の言語での記述方法はわかりません。それでも、英語を「デフォルト」言語として扱うことを除いて、実装に特定の言語のハードコーディングはありません。したがって、それは些細なことです。この実装を拡張して、より多くの言語をサポートします。必要なのは、Translations
で別のオブジェクトを定義することだけです。 入力して translations
のエントリとして追加します .
翻訳を使用するには、まずページの現在の言語をそのコンポーネントに渡す必要があります。次に、translations[lang]["entry"]
を使用できます。 正確に翻訳が必要な場所 ("entry"
を置き換えます) translations[lang]["all_n_posts"](n)
のように関数を呼び出すだけなので、このスキームは関数に対しても機能します。 .
それでおしまい!国際化ロジック全体を実装しました!新しいエントリを追加するには、en
に翻訳を追加するだけです。 そして zh
ただし、バイリンガル ブログを維持する上で最も困難な部分は、常に実際のブログ投稿を翻訳することです。また、このサイトの多数の英語のみのバージョンの投稿が示すように、完璧な仕事をしたとは言えません。 、私はそれに取り組み続けるつもりです。私のアプローチの技術的な側面が、あなたにも試してみるように促すことを願っています!