1. Documentation
    2. 环境
    3. Intlayer与Vite和React

    开始使用 Intlayer、Vite 和 React 进行国际化 (i18n)

    什么是 Intlayer?

    Intlayer 是一个创新的开源国际化 (i18n) 库,旨在简化现代 Web 应用程序的多语言支持。

    使用 Intlayer,您可以:

    • 轻松管理翻译,使用声明式词典在组件级别进行管理。
    • 动态本地化元数据、路由和内容。
    • 确保 TypeScript 支持,通过自动生成的类型,提高自动完成和错误检测。
    • 享受高级特性,如动态区域侦测和切换。

    在 Vite 和 React 应用程序中设置 Intlayer 的逐步指南

    第 1 步:安装依赖

    使用 npm 安装必要的包:

    bash
    1npm install intlayer react-intlayer
    bash
    1yarn add intlayer react-intlayer
    bash
    1pnpm add intlayer react-intlayer

    第 2 步:项目配置

    创建配置文件来配置您的应用程序语言:

    typescript
    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;

    要查看所有可用参数,请参考 配置文档

    第 3 步:在您的 Vite 配置中集成 Intlayer

    将 intlayer 插件添加到您的配置中。

    typescript
    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});

    第 4 步:声明您的内容

    创建并管理您的内容字典:

    tsx
    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";

    查看如何声明您的 Intlayer 声明文件

    第 5 步:在您的代码中使用 Intlayer

    在整个应用程序中访问您的内容字典:

    tsx
    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;

    注意:如果您想在 string 属性中使用内容,例如 alttitlehrefaria-label 等,您必须调用函数的值,如:

    tsx
    1<img src={content.image.src.value} alt={content.image.value} />

    (可选)第 6 步:更改内容的语言

    要更改内容的语言,您可以使用 useLocale 钩子提供的 setLocale 函数。该函数允许您设置应用程序的区域并相应更新内容。

    tsx
    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};

    (可选)第 7 步:为您的应用程序添加本地化路由

    此步骤的目的是为每种语言创建唯一的路由。这对于 SEO 和 SEO 友好的 URL 很有用。 示例:

    tsx
    1// /dashboard 2// /es/dashboard 3// /fr/dashboard

    默认情况下,默认语言的路由没有前缀。如果您想要前缀默认语言,可以在配置中将 middleware.prefixDefault 选项设置为 true。有关更多信息,请参见 配置文档

    要在您的应用程序中添加本地化路由,您可以创建一个 LocaleRouter 组件,它包装您的应用程序路由并处理基于语言的路由。以下是使用 React Router 的示例:

    tsx
    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 检测当前语言并设置适当的语言 cookie。如果没有指定语言,该插件将根据用户的浏览器语言偏好确定最合适的语言。如果未检测到任何语言,将重定向到默认语言。

    ts
    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});

    (可选)第 8 步:更改语言时更改 URL

    要在语言更改时更改 URL,您可以使用 useLocale 钩子提供的 onLocaleChange 属性。与此同时,您可以使用 react-router-domuseLocationuseNavigate 钩子来更新 URL 路径。

    tsx
    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};

    配置 TypeScript

    Intlayer 使用模块扩展来获得 TypeScript 的好处,并增强您的代码库。

    alt text

    alt text

    确保您的 TypeScript 配置包括生成的类型。

    json5
    1// tsconfig.json 2 3{ 4 // 你的自定义配置 5 include: [ 6 "src", 7 "types", // <- 包括自动生成的类型 8 ], 9}

    Git 配置

    建议忽略 Intlayer 生成的文件。这允许您避免将它们提交到 Git 仓库。

    为此,您可以在 .gitignore 文件中添加以下指令:

    gitignore
    1# 忽略 Intlayer 生成的文件 2.intlayer

    如果您有改善此文档的想法,请随时通过在GitHub上提交拉取请求来贡献。

    文档的 GitHub 链接

    在此页面