TRANSLATING your React project with i has never been easier
Say crazy dev!
Today I'm going to show you that translating an ENTIRE project into React has never been easier than it is nowadays. But first you need to know why this would be important.
When people start programming, it is common for the code texts and messages to be in Portuguese (pt-BR). Translating the project into other languages is never a priority and is considered complex or unnecessary.
So why would it be relevant?
It depends on your reality. Here are some reasons why you should consider this process:
The company needs it
It could be that the company where you work or some SaaS you have starts operating in another country and has this need. A product that has this functionality has a HUGE difference.
Application for an international vacancy
If you are applying for international vacancies, having a portfolio with already internationalized projects can give you a striking highlight. It shows that you are prepared to work on a global project and are not lazy like most.
You can never learn too much
Internationalization is not just a feature, but also an important learning experience. It's another weapon that you include in your arsenal of skills and tools.
How was it done in the past?
Project translation is already an old problem. People made that select in the HTML with the country's flag for people to select and filled it with if in the code to know which text would be displayed.
It was very neglected. Websites were made in a single language, and translations were added haphazardly. If it were on the backend, the deal would be even worse.
With the globalization of the internet, the demand for multilingual software has grown, bringing specific tools for i18n. Solutions like GNU Gettext emerged on the backend, followed by libs like i18next and react-intl for the frontend. This is where the doubt comes in...
i18next vs. react-intl: Which one to choose?
-
i18next: This one appeared in 2011, it was an npm package that worked for both Node.js and SPA on the client side. The community adopted it and finally made the React version in the react-i18next lib in 2015. Therefore, as positive and negative points we have:
- Pros: Flexibility, road time (since 2011), vast ecosystem (learn once translate everywhere) and automatic fallback.
- Cons: Learning curve. There are a lot of docs to read, but not everything you need is there.
-
react-intl: Part of the FormatJS project, follows International JavaScript API standards, ensuring compatibility with modern browsers.
- Pros: Aligned with ECMAScript standards, simplicity in integration.
- Cons: Less flexible and less plugin support.
And which one will we use?
i18next my friends! I always recommend reading the docs to get started, but let's go to Doido's guide!
Internationalizing a React Application with i18next
- Installation:
npm install i18next i18next-chained-backend i18next-http-backend i18next-resources-to-backend react-i18next next-i18next
- Configuration: Create an i18n.js to configure 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;
- Translations: Create translation files in locales/en/translation.json and locales/pt/translation.json.
{ "welcome": "Welcome to our application!", "login": "Login" }
- Use of Translations: Use the useTranslation hook in React.
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;
- Language Change: Allow users to change the language.
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;
Is that all?
Of course not, I'll now show you what I did in the CrazyStack project. First I made a different config in Nextjs taking a static JSON that I defined in the public folder of the project itself! Take a look:
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`, }, ], }, });
Then I created a context API to save the language and access it throughout the project. Starting with imports
2. Imports
import { useTranslation } from "react-i18next"; import { createContext, useState, useContext } from "react";
- useTranslation: React-i18next hook to access translation features. This here you will use in practically every JSX component you have in the project.
- createContext, useState, useContext: React functions for creating and consuming contexts, as well as managing state.
3. Context Creation
const I18NContext = createContext({} as any);
A context is created to store and provide data (such as the current language) through the 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.
In the first application, you will learn how to build a REST API in the Node.js ecosystem. Use cases will be created involving complex business rules such as listing available times, generating orders from booked appointments, loyalty systems, commissions, payments, customer reviews and much more. Everything done in TypeScript and using the non-relational database MongoDB.
In the second application, you will learn how to build an administration panel in the React.js ecosystem to view graphs and manipulate records. All done with TypeScript and using the Next.js framework. In addition, the Chakra UI visual component library will be used, applying the Atomic Design concept to the components created. To find out more, visit crazystack.com.br.
The above is the detailed content of TRANSLATING your React project with i has never been easier. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.
