IntlayerとLynxとReactで国際化(i18n)を始める
Intlayerとは?
Intlayerは、モダンアプリケーションにおける多言語対応を簡素化する革新的なオープンソースの国際化(i18n)ライブラリです。これは多くのJavaScript/TypeScript環境で動作し、Lynx(react-intlayerパッケージを介して)も含まれます。
Intlayerを使用すると、以下が可能です:
- コンポーネントレベルで宣言的な辞書を使用して翻訳を簡単に管理できます。
- TypeScriptサポートを確保し、自動生成された型を利用できます。
- 動的にローカライズされたコンテンツ(UI文字列を含む)を提供できます(React for webではHTMLメタデータなどもローカライズ可能)。
- 動的なロケール検出や切り替えなどの高度な機能を利用できます。
ステップ1: 依存関係をインストールする
Lynxプロジェクトから、以下のパッケージをインストールします:
npm install intlayer react-intlayer lynx-intlayer
パッケージ
intlayer
設定、辞書コンテンツ、型生成、CLIコマンドのためのコアi18nツールキット。react-intlayer
Lynxでロケールの取得と切り替えに使用するコンテキストプロバイダーとReactフックを提供するReact統合。lynx-intlayer
IntlayerをLynxバンドラーと統合するためのプラグインを提供するLynx統合。
ステップ2: Intlayer設定を作成する
プロジェクトのルート(または便利な場所)にIntlayer設定ファイルを作成します。以下のようになります:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // ... 必要な他のロケールを追加 ], defaultLocale: Locales.ENGLISH, },};export default config;
この設定内で以下を行うことができます:
- サポートするロケールのリストを設定します。
- デフォルトロケールを設定します。
- 後で、より高度なオプション(例:ログ、カスタムコンテンツディレクトリなど)を追加することができます。
- 詳細はIntlayer設定ドキュメントをご覧ください。
ステップ3: LynxバンドラーにIntlayerプラグインを追加する
LynxでIntlayerを使用するには、lynx.config.tsファイルにプラグインを追加する必要があります:
import { defineConfig } from "@lynx-js/rspeedy";import { pluginIntlayerLynx } from "lynx-intlayer/plugin";export default defineConfig({ plugins: [ // ... 他のプラグイン pluginIntlayerLynx(), ],});
ステップ4: Intlayerプロバイダーを追加する
アプリケーション全体でユーザーの言語を同期させるには、react-intlayerのIntlayerProviderコンポーネントでルートコンポーネントをラップする必要があります。
また、Intlayerが正しく動作するようにするために、intlayerPolyfill関数ファイルを追加する必要があります。
import { root } from "@lynx-js/react";import { App } from "./App.js";import { IntlayerProvider } from "react-intlayer";import { intlayerPolyfill } from "lynx-intlayer";intlayerPolyfill();root.render( <IntlayerProvider> <App /> </IntlayerProvider>);if (import.meta.webpackHot) { import.meta.webpackHot.accept();}
ステップ5: コンテンツを宣言する
プロジェクト内の任意の場所(通常はsrc/内)にコンテンツ宣言ファイルを作成します。Intlayerがサポートする任意の拡張形式を使用できます:
- .content.ts
- .content.mjs
- .content.cjs
- .content.json
- など
例(Lynx用のTSXノードを使用したTypeScript):
import { t, type Dictionary } from "intlayer";const appContent = { key: "app", content: { title: "React", subtitle: t({ ja: "Lynx上で", en: "on Lynx", fr: "sur Lynx", es: "en Lynx", }), description: t({ ja: "ロゴをタップして楽しんでください!", en: "Tap the logo and have fun!", fr: "Appuyez sur le logo et amusez-vous!", es: "¡Toca el logo y diviértete!", }), hint: [ t({ ja: "編集", en: "Edit", fr: "Modifier", es: "Editar", }), " src/App.tsx ", t({ ja: "更新を確認してください!", en: "to see updates!", fr: "pour voir les mises à jour!", es: "para ver actualizaciones!", }), ], },} satisfies Dictionary;export default appContent;
コンテンツ宣言の詳細については、Intlayerのコンテンツドキュメントを参照してください。
ステップ4: コンポーネントでIntlayerを使用する
子コンポーネントでuseIntlayerフックを使用してローカライズされたコンテンツを取得します。
import { useCallback, useState } from "@lynx-js/react";import { useIntlayer } from "react-intlayer";import "./App.css";import arrow from "./assets/arrow.png";import lynxLogo from "./assets/lynx-logo.png";import reactLynxLogo from "./assets/react-logo.png";import { LocaleSwitcher } from "./components/LocaleSwitcher.jsx";export const App = () => { const [alterLogo, setAlterLogo] = useState(false); const { title, subtitle, description, hint } = useIntlayer("app"); const onTap = useCallback(() => { // 背景のみ setAlterLogo(!alterLogo); }, [alterLogo]); return ( <view> <view className="Background" /> <view className="App"> <view className="Banner"> <view className="Logo" bindtap={onTap}> {alterLogo ? ( <image src={reactLynxLogo} className="Logo--react" /> ) : ( <image src={lynxLogo} className="Logo--lynx" /> )} </view> <text className="Title">{title}</text> <text className="Subtitle">{subtitle}</text> </view> <view className="Content"> <image src={arrow} className="Arrow" /> <text className="Description">{description}</text> <text className="Hint"> {hint[0]} <text style={{ fontStyle: "italic" }}>{hint[1]}</text> {hint[2]} </text> </view> <LocaleSwitcher /> <view style={{ flex: 1 }}></view> </view> </view> );};
文字列ベースのプロパティ(例: ボタンのtitleやTextコンポーネントのchildren)でcontent.someKeyを使用する場合、content.someKey.valueを呼び出して実際の文字列を取得してください。
(オプション)ステップ5: アプリのロケールを変更する
コンポーネント内からロケールを切り替えるには、useLocaleフックのsetLocaleメソッドを使用します。
import { type FC } from "react";import { getLocaleName } from "intlayer";import { useLocale } from "react-intlayer";export const LocaleSwitcher: FC = () => { const { setLocale, availableLocales, locale } = useLocale(); return ( <view style={{ display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 10, }} > {availableLocales.map((localeEl) => ( <text key={localeEl} style={{ color: localeEl === locale ? "#fff" : "#888", fontSize: "12px", }} bindtap={() => setLocale(localeEl)} > {getLocaleName(localeEl)} </text> ))} </view> );};
これにより、Intlayerコンテンツを使用するすべてのコンポーネントが再レンダリングされ、新しいロケールの翻訳が表示されます。
詳細については、useLocaleドキュメントを参照してください。
TypeScriptの設定(TypeScriptを使用している場合)
Intlayerは、隠しフォルダ(デフォルトでは.intlayer)に型定義を生成し、自動補完を改善し、翻訳エラーを検出します。
// tsconfig.json{ // ... 既存のTS設定 "include": [ "src", // ソースコード ".intlayer", // <-- 自動生成された型を含める // ... 既に含めている他のもの ],}
これにより、以下の機能が有効になります:
- 辞書キーの自動補完。
- 存在しないキーへのアクセスや型の不一致を警告する型チェック。
Gitの設定
Intlayerによって自動生成されたファイルをコミットしないようにするには、以下を.gitignoreに追加します。
# Intlayerによって生成されたファイルを無視.intlayer
さらに進む
- ビジュアルエディター: Intlayerビジュアルエディターを使用して翻訳を視覚的に管理します。
- CMS統合: 辞書コンテンツをCMSから外部化して取得することもできます。
- CLIコマンド: Intlayer CLIを使用して、翻訳の抽出や欠落キーの確認などのタスクを実行します。
このドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンク