Getting Started Internationalizing (i18n) with Intlayer and React Create App
What is Intlayer?
Intlayer 是一个创新的开源国际化(i18n)库,旨在简化现代Web应用程序中的多语言支持。
使用Intlayer,您可以:
- 轻松管理翻译,使用组件级的声明性字典。
- 动态本地化元数据、路由和内容。
- 确保TypeScript支持,自动生成类型,提高自动补全和错误检测能力。
- 受益于高级功能,如动态语言检测和切换。
Step-by-Step Guide to Set Up Intlayer in a 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;
要查看所有可用参数,请参考在这里的配置文档。
Step 3: Integrate Intlayer in Your CRA Configuration
更改您的脚本以使用react-intlayer
1 "scripts": {
2 "build": "react-intlayer build",
3 "start": "react-intlayer start",
4 "transpile": "intlayer build"
5 },
注意:react-intlayer脚本是基于craco的。您也可以根据intlayer craco插件实现自己的设置。在这里查看示例。
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 getStarted: t<ReactNode>({
9 en: (
10 <>
11 编辑 <code>src/App.tsx</code> 并保存以重新加载
12 </>
13 ),
14 fr: (
15 <>
16 Éditez <code>src/App.tsx</code> et enregistrez pour recharger
17 </>
18 ),
19 es: (
20 <>
21 Edita <code>src/App.tsx</code> y guarda para recargar
22 </>
23 ),
24 }),
25 reactLink: {
26 href: "https://reactjs.org",
27 content: t({
28 en: "学习React",
29 fr: "Apprendre React",
30 es: "Aprender React",
31 }),
32 },
33 },
34} satisfies DeclarationContent;
35
36export default appContent;
Step 5: Utilize Intlayer in Your Code
在您的应用程序中访问您的内容字典:
1import logo from "./logo.svg";
2import "./App.css";
3import { IntlayerProvider, useIntlayer } from "react-intlayer";
4import { LocaleSwitcher } from "./components/LangSwitcherDropDown";
5
6function AppContent() {
7 const content = useIntlayer("app");
8
9 return (
10 <header className="App-header">
11 <img src={logo} className="App-logo" alt="logo" />
12
13 {content.getStarted}
14 <a
15 className="App-link"
16 href={content.reactLink.href.value}
17 target="_blank"
18 rel="noopener noreferrer"
19 >
20 {content.reactLink.content}
21 </a>
22 </header>
23 );
24}
25
26function App() {
27 return (
28 <IntlayerProvider>
29 <div className="App">
30 {/* 为了正确使用useIntlayer钩子,您应该在子组件中访问您的数据 */}
31 <AppContent />
32 </div>
33 <div className="absolute bottom-5 right-5 z-50">
34 <LocaleSwitcher />
35 </div>
36 </IntlayerProvider>
37 );
38}
39
40export default App;
注意:如果您想在string属性中使用您的内容,例如alt、title、href、aria-label等,您必须调用函数的值,如:
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)}>更改语言为英语</button>
9 );
10};
(Optional) Step 7: Add localized Routing to your application
此步骤的目的是为每种语言创建唯一路由。这对于SEO和搜索引擎友好的URL非常有用。 示例:
1// /dashboard
2// /es/dashboard
3// /fr/dashboard
默认情况下,默认语言环境的路由没有前缀。如果您想为默认语言环境添加前缀,可以在配置中将middleware.prefixDefault选项设置为true。有关更多信息,请参见配置文档。
要将本地化路由添加到您的应用程序,您可以创建一个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 = removeLocaleFromUrl(
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);
(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)}>更改语言为英语</button>
24 );
25};
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 链接