使用 i 翻译你的 React 项目从未如此简单
说疯狂的开发者!
今天我将向您展示,将整个项目翻译成 React 从未像现在这样容易。但首先您需要知道为什么这很重要。
当人们开始编程时,代码文本和消息通常使用葡萄牙语 (pt-BR)。将项目翻译成其他语言从来都不是优先事项,并且被认为是复杂或不必要的。
那么为什么它会相关呢?
这取决于您的实际情况。以下是您应该考虑此过程的一些原因:
公司需要
可能是您工作的公司或您拥有的某些 SaaS 开始在另一个国家/地区运营并且有此需求。具有此功能的产品有巨大的差异。
国际职位空缺申请
如果您正在申请国际职位空缺,拥有包含国际化项目的作品集可以给您带来引人注目的亮点。这表明您已准备好从事全球项目,并且不像大多数人一样懒惰。
你永远不会学太多
国际化不仅是一种特征,也是一种重要的学习经历。这是您的技能和工具库中的另一种武器。
过去是如何做到的?
项目翻译已经是个老问题了。人们在 HTML 中选择了该国家的国旗,供人们选择,并在代码中用 if 填充以了解将显示哪些文本。
这是非常被忽视的。网站是用单一语言制作的,翻译是随意添加的。如果是在后台的话,那就更惨了。
随着互联网的全球化,对多语言软件的需求不断增长,带来了针对国际化的特定工具。像 GNU Gettext 这样的解决方案出现在后端,随后出现了像 i18next 和 react-intl 这样的前端库。这就是疑问所在......
i18next 对比React-intl:选择哪一个?
-
i18next:这个出现于 2011 年,它是一个 npm 包,适用于客户端的 Node.js 和 SPA。社区采纳了它,并最终于2015年在react-i18next lib中制作了React版本。因此,作为积极和消极的观点,我们有:
- 优点:灵活性、路途时间(自 2011 年起)、庞大的生态系统(一次学习,随处翻译)和自动回退。
- 缺点:学习曲线。有很多文档需要阅读,但并不是您需要的所有内容都在那里。
-
react-intl:FormatJS 项目的一部分,遵循国际 JavaScript API 标准,确保与现代浏览器的兼容性。
- 优点:与 ECMAScript 标准保持一致,集成简单。
- 缺点:灵活性较差,插件支持较少。
我们将使用哪一个?
i18next 我的朋友们!我总是建议阅读文档来开始,但让我们看看 Doido 的指南!
使用 i18next 国际化 React 应用程序
- 安装:
npm install i18next i18next-chained-backend i18next-http-backend i18next-resources-to-backend react-i18next next-i18next
- 配置:创建一个i18n.js来配置i18next。
import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import Backend from 'i18next-http-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; i18n .use(Backend) .use(LanguageDetector) .use(initReactI18next) .init({ fallbackLng: 'en', interpolation: { escapeValue: false } }); export default i18n;
- 翻译:在 locales/en/translation.json 和 locales/pt/translation.json 中创建翻译文件。
{ "welcome": "Welcome to our application!", "login": "Login" }
- 翻译的使用:在React中使用useTranslation钩子。
import React from 'react'; import { useTranslation } from 'react-i18next'; function App() { const { t } = useTranslation(); return ( <div> <h1>{t('welcome')}</h1> <button>{t('login')}</button> </div> ); } export default App;
- 语言更改:允许用户更改语言。
import React from 'react'; import { useTranslation } from 'react-i18next'; function LanguageSwitcher() { const { i18n } = useTranslation(); const changeLanguage = (lng) => i18n.changeLanguage(lng); return ( <div> <button onClick={() => changeLanguage('en')}>English</button> <button onClick={() => changeLanguage('pt')}>Português</button> </div> ); } export default LanguageSwitcher;
这就是全部吗?
当然不是,我现在将向您展示我在 CrazyStack 项目中所做的事情。首先,我在 Nextjs 中做了一个不同的配置,采用了我在项目本身的公共文件夹中定义的静态 JSON!看看:
import i18next from "i18next"; import ChainedBackend from "i18next-chained-backend"; import HttpBackend from "i18next-http-backend"; import resourcesToBackend from "i18next-resources-to-backend"; import { initReactI18next } from "react-i18next"; import { defaultTexts } from "./defaultTexts"; i18next .use(ChainedBackend) .use(initReactI18next) .init({ lng: "pt-br", fallbackLng: "pt-br", interpolation: { escapeValue: false, }, compatibilityJSON: "v3", react: { //wait: true,//usar no react native useSuspense: false, }, backend: { backends: [HttpBackend, resourcesToBackend(defaultTexts)], backendOptions: [ { loadPath: `${process.env.NEXT_PUBLIC_URL}/{{lng}}/{{ns}}.json`, }, ], }, });
然后我创建了一个上下文 API 来保存语言并在整个项目中访问它。从导入开始
2. 进口
import { useTranslation } from "react-i18next"; import { createContext, useState, useContext } from "react";
- useTranslation:React-i18next 挂钩来访问翻译功能。在这里,您将在项目中的几乎每个 JSX 组件中使用它。
- createContext、useState、useContext:用于创建和使用上下文以及管理状态的 React 函数。
3. 上下文创建
const I18NContext = createContext({} as any);
创建上下文来通过 DOM 存储和提供数据(例如当前语言)。
4. Verificação do Ambiente
export const isBrowser = typeof window !== "undefined";
Essa linha verifica se o código está sendo executado no navegador (em vez de no servidor), essencial para manipular recursos específicos do cliente, como localStorage.
5. Componente I18nProvider
export const I18nProvider = ({ children }: any) => { const { i18n } = useTranslation() || {}; const [currentLanguage, setCurrentLanguage] = useState( formatLanguageFromi18N(i18n?.language) ); const changeLanguage = (language) => { setCurrentLanguage(language); i18n?.changeLanguage?.(formatLanguageFromSelect(language)); localStorage.setItem("language", formatLanguageFromSelect(language)); }; return ( <I18NContext.Provider value={{ changeLanguage, currentLanguage, setCurrentLanguage }}> {children} </I18NContext.Provider> ); };
Este componente é um provider que envolve a árvore de componentes React e fornece o estado atual do idioma e a função para alterá-lo.
- useTranslation: Recupera o objeto i18n da biblioteca react-i18next, que contém informações sobre o idioma atual.
- currentLanguage: Estado que armazena o idioma atual, inicializado com base no idioma detectado pelo i18n.
- changeLanguage: Função para alterar o idioma, que também salva a escolha no localStorage para persistência entre recargas da página.
6. Hook useI18n
export const useI18n = () => { if (!isBrowser) { return { currentLanguage: "pt-br", setCurrentLanguage: () => {}, changeLanguage: () => {}, }; } return useContext(I18NContext); };
Este hook facilita o acesso ao contexto de internacionalização em qualquer componente.
- Verifica se está no navegador (isBrowser). Se não estiver, retorna valores padrão para evitar erros no server side.
- Se estiver no navegador, consome e retorna o contexto I18NContext.
7. Mapas de Conversão
const countryToLanguage = { BR: "pt-br", US: "en", }; const languageToCountry = { "pt-br": "BR", en: "US", };
Esses objetos mapeiam códigos de países para códigos de idiomas e vice-versa, facilitando a formatação dos códigos de idioma entre diferentes convenções.
8. Funções de Formatação
export const formatLanguageFromi18N = (language) => languageToCountry[language]; export const formatLanguageFromSelect = (language) => countryToLanguage[language];
Essas funções formatam os códigos de idioma conforme necessário. formatLanguageFromi18N converte o código de idioma para o código do país, enquanto formatLanguageFromSelect faz a conversão inversa.
Código completo
"use client"; import { useTranslation } from "react-i18next"; import { createContext, useState, useContext } from "react"; const I18NContext = createContext({} as any); export const isBrowser = typeof window !== "undefined"; export const I18nProvider = ({ children }: any) => { const { i18n } = useTranslation() || {}; const [currentLanguage, setCurrentLanguage] = useState( formatLanguageFromi18N(i18n?.language) ); const changeLanguage = (language) => { setCurrentLanguage(language); i18n?.changeLanguage?.(formatLanguageFromSelect(language)); localStorage.setItem("language", formatLanguageFromSelect(language)); }; return ( <I18NContext.Provider value={{ changeLanguage, currentLanguage, setCurrentLanguage }}> {children} </I18NContext.Provider> ); }; export const useI18n = () => { if (!isBrowser) { return { currentLanguage: "pt-br", setCurrentLanguage: () => {}, changeLanguage: () => {}, }; } return useContext(I18NContext); }; const countryToLanguage = { BR: "pt-br", US: "en", }; const languageToCountry = { "pt-br": "BR", en: "US", }; export const formatLanguageFromi18N = (language) => languageToCountry[language]; export const formatLanguageFromSelect = (language) => countryToLanguage[language];
Depois eu mexi na Navbar
No código eu tenho um select de idioma utilizando um dropdown de países. Olha só:
"use client"; //@ts-nocheck import { Header, Flex, Logo, Profile, NotificationsNav, SearchBar } from "@/shared/ui"; import { useBreakpointValue, Icon, IconButton, useMediaQuery } from "@chakra-ui/react"; import { RiMenuLine } from "react-icons/ri"; import { useAuth, useSidebarDrawer } from "@/shared/libs"; import { useEffect, useState } from "react"; import { CountryDropdown } from "react-country-region-selector"; import { theme } from "@/application/theme"; import { formatLanguageFromi18N, useI18n } from "@/application/providers/i18nProvider"; import { useTranslation } from "react-i18next"; export const NavBar = ({ showLogo = true }) => { const { isAuthenticated } = useAuth() || {}; const { i18n } = useTranslation(); const { changeLanguage, setCurrentLanguage } = useI18n() || {}; const { onOpen = () => {}, onClose } = useSidebarDrawer() || {}; const isDesktopVersion = useBreakpointValue({ base: false, lg: true }); const [country, setCountry] = useState(formatLanguageFromi18N(i18n?.language)); useEffect(() => { return () => { onClose?.(); }; }, []); const Dropdown = CountryDropdown as any; useEffect(() => { const language = localStorage.getItem("language"); if (language) { setCountry(formatLanguageFromi18N(language)); setCurrentLanguage(language); i18n?.changeLanguage?.(language); } }, []); return ( <Header> <Flex alignItems={"center"} w={"100%"}> {isAuthenticated && !isDesktopVersion && ( <IconButton aria-label="Open sidebar" fontSize="24" icon={<Icon as={RiMenuLine} />} variant="unstyled" onClick={onOpen} mr="1" mt={2} /> )} <Logo marginBottom={0} /> {/* {isLargerThan560 && ( <SearchBar placeholder="Pesquise por nome..." name="search" width="auto" /> )} */} {isAuthenticated && ( <Flex align="center" ml="auto"> {/* <NotificationsNav /> */} <Dropdown value={country} onChange={(val) => { setCountry(val); changeLanguage(val); }} labelType="short" valueType="short" showDefaultOption defaultOptionLabel="Selecione o idioma" whitelist={["US", "BR"]} style={{ backgroundColor: theme.colors.secondary[400], padding: 10, width: 60, marginRight: 15, borderRadius: 8, }} /> <Profile showProfileData={isDesktopVersion} /> </Flex> )} </Flex> </Header> ); };
Importações e Setup Inicial:
- useAuth: Verifica se o usuário está autenticado.
- useBreakpointValue: Determina se a versão desktop deve ser exibida com base no tamanho da tela.
- useState: Define o estado inicial do país/língua (country) usando a função formatLanguageFromi18N para formatar a língua atual do i18n.
- useEffect: Primeiro efeito limpa o sidebar ao desmontar o componente (onClose). O segundo efeito verifica se o idioma está salvo no localStorage e, caso esteja, atualiza o estado country e muda o idioma na aplicação.
Dropdown de Idiomas:
- O dropdown é implementado usando o componente CountryDropdown da biblioteca react-country-region-selector, que é customizado para servir como um seletor de idioma.
- value={country}: O valor selecionado no dropdown é controlado pelo estado country.
- onChange={(val) => { ... }}: Quando o valor do dropdown é alterado, o estado country é atualizado, e a função changeLanguage é chamada para alterar o idioma da aplicação.
- whitelist={["US", "BR"]}: Restringe as opções do dropdown a "US" (inglês) e "BR" (português).
- style={...}: Estilização inline personalizada para o dropdown, utilizando cores e espaçamentos do tema theme.
-
Comportamento do Seletor de Idioma:
- O dropdown permite que o usuário selecione o idioma preferido, e essa seleção é persistida no localStorage.
- Ao mudar o idioma, o dropdown reflete essa mudança, e a aplicação é atualizada para usar o novo idioma selecionado. Para incluir o trecho de código que você forneceu na imagem no seu artigo, você pode seguir este formato:
E como mudar os textos?
De componente em componente eu fui fazendo o mesmo procedimento. O código abaixo mostra como substituir o texto estático por uma tradução dinâmica baseada na chave de localização:
import { Divider } from "@chakra-ui/react"; import { IoExitOutline } from "react-icons/io5"; import { useRouter } from "next/navigation"; import { useTranslation } from "react-i18next"; // Importando o hook useTranslation type ProfileProps = { showProfileData?: boolean; }; export const Profile = ({ showProfileData }: ProfileProps) => { const { t } = useTranslation(["PAGES"]); // Obtendo a função t para tradução const { user, logout } = useAuth() || {}; const router = useRouter(); const { showUserMenu, setShowUserMenu } = useProfile(); return ( <Box> {/* Outras partes do componente */} <Flex> <IoExitOutline /> <Text fontSize="sm"> {t("PAGES:HOME_PAGE.logout", { defaultValue: "Sair" })} // Chave de tradução com valor padrão </Text> </Flex> </Box> ); };
Neste exemplo, o hook useTranslation é utilizado para carregar a chave de tradução PAGES:HOME_PAGE.logout. Se a chave não for encontrada, o texto padrão "Sair" será exibido.
Conclusão
A ideia pode ser aplicada em qualquer componente de texto estático. Basta usar a hook useTranslation.
Internacionalizar sua aplicação pode abrir portas para mercados globais, destacar seu portfólio e aprimorar suas habilidades. Escolher entre i18next e react-intl depende das necessidades específicas do seu projeto, mas ambos são excelentes opções para quem deseja começar.
Sugestão de cursos
Em 2022 eu criei o bootcamp CrazyStack. Nele, eu mostro 2 aplicações completas de um sistema de agendamentos online de serviços aplicando conceitos avançados como Design Patterns, Clean Architecture, Feature Sliced Design, SOLID, DDD, além de Testes unitários, de integração e E2E.
在第一个应用程序中,您将学习如何在 Node.js 生态系统中构建 REST API。将创建涉及复杂业务规则的用例,例如列出可用时间、根据预订生成订单、忠诚度系统、佣金、付款、客户评论等等。一切都在 TypeScript 中完成并使用非关系数据库 MongoDB。
在第二个应用程序中,您将学习如何在 React.js 生态系统中构建管理面板来查看图表和操作记录。一切都是通过 TypeScript 和 Next.js 框架完成的。此外,还将使用Chakra UI可视化组件库,将原子设计理念应用到创建的组件中。要了解更多信息,请访问crazystack.com.br。
以上是使用 i 翻译你的 React 项目从未如此简单的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。
