Getting Started Internationalizing (i18n) with Intlayer and Vite and React
What is Intlayer?
Intlayerは、現代のウェブアプリケーションにおける多言語サポートを簡素化するために設計された革新的なオープンソースの国際化(i18n)ライブラリです。
Intlayerを使用すると、次のことができます。
- 宣言的辞書を使用して簡単に翻訳を管理できます。
- メタデータ、ルート、およびコンテンツを動的にローカライズできます。
- 自動生成された型によるTypeScriptサポートを保証し、自動補完およびエラー検出を向上させます。
- 動的ロケール検出と切り替えなどの高度な機能の恩恵を享受できます。
Step-by-Step Guide to Set Up Intlayer in a Vite and React Application
Step 1: Install Dependencies
必要なパッケージをnpmを使用してインストールします。
1npm install intlayer react-intlayer
1yarn add intlayer react-intlayer
1pnpm add intlayer react-intlayer
Step 2: Configuration of your project
アプリケーションの言語を設定するための設定ファイルを作成します。
1// intlayer.config.ts
2
3import { Locales, type IntlayerConfig } from "intlayer";
4
5const config: IntlayerConfig = {
6 internationalization: {
7 locales: [
8 Locales.ENGLISH,
9 Locales.FRENCH,
10 Locales.SPANISH,
11 // 他のロケールを追加してください
12 ],
13 defaultLocale: Locales.ENGLISH,
14 },
15};
16
17export default config;
すべての利用可能なパラメータについては、configuration documentation hereを参照してください。
Step 3: Integrate Intlayer in Your Vite Configuration
設定にintlayerプラグインを追加します。
1import { defineConfig } from "vite";
2import react from "@vitejs/plugin-react-swc";
3import { intLayerPlugin } from "react-intlayer/vite";
4
5// https://vitejs.dev/config/
6export default defineConfig({
7 plugins: [react(), intLayerPlugin()],
8});
Step 4: Declare Your Content
コンテンツ辞書を作成して管理します。
1// src/app.content.tsx
2import { t, type DeclarationContent } from "intlayer";
3import { type ReactNode } from "react";
4
5const appContent = {
6 key: "app",
7 content: {
8 viteLogo: t({
9 en: "Vite logo",
10 fr: "Logo Vite",
11 es: "Logo Vite",
12 }),
13 reactLogo: t({
14 en: "React logo",
15 fr: "Logo React",
16 es: "Logo React",
17 }),
18
19 title: "Vite + React",
20
21 count: t({
22 en: "count is ",
23 fr: "le compte est ",
24 es: "el recuento es ",
25 }),
26
27 edit: t<ReactNode>({
28 // 内容にReactノードを使用する場合は、Reactをインポートすることを忘れないでください
29 en: (
30 <>
31 Edit <code>src/App.tsx</code> and save to test HMR
32 </>
33 ),
34 fr: (
35 <>
36 Éditez <code>src/App.tsx</code> et enregistrez pour tester HMR
37 </>
38 ),
39 es: (
40 <>
41 Edita <code>src/App.tsx</code> y guarda para probar HMR
42 </>
43 ),
44 }),
45
46 readTheDocs: t({
47 en: "Click on the Vite and React logos to learn more",
48 fr: "Cliquez sur les logos Vite et React pour en savoir plus",
49 es: "Haga clic en los logotipos de Vite y React para obtener más información",
50 }),
51 },
52} satisfies DeclarationContent;
53
54export default appContent;
注: コンテンツファイルにTSXコードが含まれる場合は、コンテンツファイルにimport React from "react";をインポートすることを検討してください。
See how to declare your Intlayer declaration files。
Step 5: Utilize Intlayer in Your Code
アプリケーション全体でコンテンツ辞書にアクセスします。
1import { useState } from "react";
2import reactLogo from "./assets/react.svg";
3import viteLogo from "/vite.svg";
4import "./App.css";
5import { LocaleSwitcher } from "./components/LangSwitcherDropDown";
6import { IntlayerProvider, useIntlayer } from "react-intlayer";
7
8function AppContent() {
9 const [count, setCount] = useState(0);
10 const content = useIntlayer("app");
11
12 return (
13 <>
14 <div>
15 <a href="https://vitejs.dev" target="_blank">
16 <img src={viteLogo} className="logo" alt={content.viteLogo.value} />
17 </a>
18 <a href="https://react.dev" target="_blank">
19 <img
20 src={reactLogo}
21 className="logo react"
22 alt={content.reactLogo.value}
23 />
24 </a>
25 </div>
26 <h1>{content.title}</h1>
27 <div className="card">
28 <button onClick={() => setCount((count) => count + 1)}>
29 {content.count}
30 {count}
31 </button>
32 <p>{content.edit}</p>
33 </div>
34 <p className="read-the-docs">{content.readTheDocs}</p>
35 <div className="absolute bottom-5 right-5 z-50">
36 <LocaleSwitcher />
37 </div>
38 </>
39 );
40}
41
42function App() {
43 return (
44 <IntlayerProvider>
45 <AppContent />
46 </IntlayerProvider>
47 );
48}
49
50export default App;
注: alt、title、href、aria-labelなどのstring属性でコンテンツを使用する場合は、関数の値を呼び出す必要があります。次のようになります。
tsx1<img src={content.image.src.value} alt={content.image.value} />
(Optional) Step 6: Change the language of your content
コンテンツの言語を変更するには、useLocaleフックによって提供されるsetLocale関数を使用できます。この関数を使用すると、アプリケーションのロケールを設定し、それに応じてコンテンツを更新できます。
1import { Locales } from "intlayer";
2import { useLocale } from "react-intlayer";
3
4const LocaleSwitcher = () => {
5 const { setLocale } = useLocale();
6
7 return (
8 <button onClick={() => setLocale(Locales.English)}>
9 Change Language to English
10 </button>
11 );
12};
(Optional) Step 7: Add localized Routing to your application
このステップの目的は、各言語のユニークなルートを作成することです。これはSEOおよびSEOフレンドリーなURLに役立ちます。 例:
1// /dashboard
2// /es/dashboard
3// /fr/dashboard
デフォルトのロケールには、ルートがプレフィックスされていません。デフォルトのロケールをプレフィックスしたい場合は、設定のmiddleware.prefixDefaultオプションをtrueに設定できます。詳細については、configuration documentationを参照してください。
アプリケーションにローカライズされたルーティングを追加するには、アプリケーションのルートをラップし、ロケールベースのルーティングを処理するLocaleRouterコンポーネントを作成できます。以下は、React Routerを使用した例です。
1// 必要な依存関係と関数のインポート
2import { Locales, getConfiguration, getPathWithoutLocale } from "intlayer"; // 'intlayer'からのユーティリティ関数と型
3import { FC, PropsWithChildren } from "react"; // 関数型コンポーネントとプロップのためのReact型
4import { IntlayerProvider } from "react-intlayer"; // 国際化コンテキストのためのプロバイダー
5import {
6 BrowserRouter,
7 Routes,
8 Route,
9 useParams,
10 Navigate,
11 useLocation,
12} from "react-router-dom"; // ナビゲーションを管理するためのルータコンポーネント
13
14// Intlayerから設定を分解
15const { internationalization, middleware } = getConfiguration();
16const { locales, defaultLocale } = internationalization;
17
18/**
19 * ローカライズ処理を管理し、適切なロケールコンテキストで子をラップするコンポーネント。
20 * URLベースのロケール検出と検証を管理します。
21 */
22const AppLocalized: FC<PropsWithChildren> = ({ children }) => {
23 const path = useLocation().pathname; // 現在のURLパスを取得
24 const { locale } = useParams<{ locale: Locales }>(); // URLからロケールパラメータを抽出
25
26 // 現在のロケールを決定し、指定されていない場合はデフォルトに戻ります
27 const currentLocale = locale ?? defaultLocale;
28
29 // パスからロケールプレフィックスを除去してベースパスを構築
30 const pathWithoutLocale = getPathWithoutLocale(
31 path // 現在のURLパス
32 );
33
34 /**
35 * middleware.prefixDefaultがtrueの場合、デフォルトロケールは常にプレフィックスされるべきです。
36 */
37 if (middleware.prefixDefault) {
38 // ロケールを検証
39 if (!locale || !locales.includes(locale)) {
40 // 更新されたパスでデフォルトロケールにリダイレクトします
41 return (
42 <Navigate
43 to={`/${defaultLocale}/${pathWithoutLocale}`}
44 replace // 現在の履歴エントリを新しいものに置き換えます
45 />
46 );
47 }
48
49 // IntlayerProviderで子をラップし、現在のロケールを設定します
50 return (
51 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
52 );
53 } else {
54 /**
55 * middleware.prefixDefaultがfalseの場合、デフォルトロケールはプレフィックスされません。
56 * 現在のロケールが有効であり、デフォルトロケールでないことを確認します。
57 */
58 if (
59 currentLocale.toString() !== defaultLocale.toString() &&
60 !locales
61 .filter(
62 (locale) => locale.toString() !== defaultLocale.toString() // デフォルトロケールを除外
63 )
64 .includes(currentLocale) // 現在のロケールが有効なロケールのリストに含まれているか確認
65 ) {
66 // ロケールプレフィックスのないパスにリダイレクト
67 return <Navigate to={pathWithoutLocale} replace />;
68 }
69
70 // IntlayerProviderで子をラップし、現在のロケールを設定します
71 return (
72 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
73 );
74 }
75};
76
77/**
78 * ローカライズされたルートをセットアップするためのルータコンポーネント。
79 * ナビゲーションを管理し、ローカライズされたコンポーネントをレンダリングするためにReact Routerを使用します。
80 */
81export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => (
82 <BrowserRouter>
83 <Routes>
84 <Route
85 // ロケールをキャプチャするルートパターン(例:/en/、/fr/)とその後のすべてのパスに一致
86 path="/:locale/*"
87 element={<AppLocalized>{children}</AppLocalized>} // ローカル管理で子をラップします
88 />
89
90 {
91 // デフォルトロケールのプレフィックスが無効な場合、ルートパスに直接子をレンダリング
92 !middleware.prefixDefault && (
93 <Route
94 path="*"
95 element={<AppLocalized>{children}</AppLocalized>} // ローカル管理で子をラップします
96 />
97 )
98 }
99 </Routes>
100 </BrowserRouter>
101);
並行して、intLayerMiddlewarePluginを使用してアプリケーションにサーバーサイドルーティングを追加することもできます。このプラグインは、URLに基づいて現在のロケールを自動的に検出し、適切なロケールクッキーを設定します。ロケールが指定されていない場合、このプラグインはユーザーのブラウザ言語の設定に基づいて最も適切なロケールを決定します。ロケールが検出されない場合は、デフォルトロケールにリダイレクトします。
1import { defineConfig } from "vite";
2import react from "@vitejs/plugin-react-swc";
3import { intLayerPlugin, intLayerMiddlewarePlugin } from "react-intlayer/vite";
4
5// https://vitejs.dev/config/
6export default defineConfig({
7 plugins: [react(), intLayerPlugin(), intLayerMiddlewarePlugin()],
8});
(Optional) Step 8: Change the URL when the locale changes
ロケールが変更されたときにURLを変更するには、useLocaleフックによって提供されるonLocaleChangeプロップを使用できます。並行して、react-router-domからのuseLocationおよびuseNavigateフックを使用してURLパスを更新することができます。
1import { Locales, getLocalizedUrl } from "intlayer";
2import { useLocale } from "react-intlayer";
3import { useLocation, useNavigate } from "react-router-dom";
4
5const LocaleSwitcher = () => {
6 const location = useLocation(); // 現在のURLパスを取得。例: /fr/about
7 const navigate = useNavigate();
8
9 const changeUrl = (locale: Locales) => {
10 // 更新されたロケールでURLを構築
11 // 例: /es/aboutをスペイン語のロケールに設定
12 const pathWithLocale = getLocalizedUrl(location.pathname, locale);
13
14 // URLパスを更新
15 navigate(pathWithLocale);
16 };
17
18 const { setLocale } = useLocale({
19 onLocaleChange: changeUrl,
20 });
21
22 return (
23 <button onClick={() => setLocale(Locales.English)}>
24 Change Language to English
25 </button>
26 );
27};
Configure TypeScript
Intlayerは、TypeScriptの利点を得るためにモジュール拡張を使用し、コードベースを強化します。
TypeScriptの設定に自動生成された型を含めるようにしてください。
1// tsconfig.json
2
3{
4 // あなたのカスタム設定
5 include: [
6 "src",
7 "types", // <- 自動生成された型を含める
8 ],
9}
Git Configuration
Intlayerによって生成されたファイルを無視することをお勧めします。これにより、これらのファイルをGitリポジトリにコミットするのを避けることができます。
これを行うには、次の指示を.gitignoreファイルに追加できます。
1# Intlayerによって生成されたファイルを無視
2.intlayer
このドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンク