Heute zeige ich Ihnen, dass die Übersetzung eines GESAMTEN Projekts in React noch nie so einfach war wie heutzutage. Aber zuerst müssen Sie wissen, warum dies wichtig ist.
Wenn Leute mit dem Programmieren beginnen, sind die Codetexte und Nachrichten häufig auf Portugiesisch (pt-BR). Die Übersetzung des Projekts in andere Sprachen hat nie Priorität und wird als komplex oder unnötig angesehen.
Es hängt von Ihrer Realität ab. Hier sind einige Gründe, warum Sie diesen Prozess in Betracht ziehen sollten:
Das Unternehmen braucht es
Es könnte sein, dass das Unternehmen, in dem Sie arbeiten, oder ein SaaS-Dienst, den Sie haben, in einem anderen Land tätig wird und diesen Bedarf hat. Ein Produkt mit dieser Funktionalität macht einen RIESIGEN Unterschied.
Bewerbung auf eine internationale Stelle
Wenn Sie sich auf internationale Stellen bewerben, kann ein Portfolio mit bereits internationalisierten Projekten ein markantes Highlight sein. Es zeigt, dass Sie bereit sind, an einem globalen Projekt zu arbeiten, und nicht faul sind wie die meisten.
Man kann nie zu viel lernen
Internationalisierung ist nicht nur ein Feature, sondern auch eine wichtige Lernerfahrung. Es ist eine weitere Waffe, die Sie in Ihr Arsenal an Fähigkeiten und Werkzeugen aufnehmen.
Projektübersetzungen sind bereits ein altes Problem. Die Leute haben diese Auswahl im HTML mit der Landesflagge getroffen, damit die Leute sie auswählen können, und sie mit if im Code gefüllt, um zu wissen, welcher Text angezeigt wird.
Es wurde sehr vernachlässigt. Websites wurden in einer einzigen Sprache erstellt und Übersetzungen wurden willkürlich hinzugefügt. Wenn es im Backend wäre, wäre der Deal noch schlimmer.
Mit der Globalisierung des Internets ist die Nachfrage nach mehrsprachiger Software gestiegen und bringt spezielle Tools für i18n mit sich. Im Backend entstanden Lösungen wie GNU Gettext, gefolgt von Bibliotheken wie i18next und React-Intl für das Frontend. Hier kommt der Zweifel ins Spiel...
i18next: Dieses erschien im Jahr 2011, es war ein npm-Paket, das sowohl für Node.js als auch für SPA auf der Clientseite funktionierte. Die Community hat es übernommen und 2015 schließlich die React-Version in der React-i18next-Bibliothek erstellt. Daher haben wir als positive und negative Punkte:
react-intl: Teil des FormatJS-Projekts, folgt internationalen JavaScript-API-Standards und gewährleistet so die Kompatibilität mit modernen Browsern.
i18next meine Freunde! Ich empfehle immer, die Dokumente zu lesen, um loszulegen, aber schauen wir uns Doidos Leitfaden an!
npm install i18next i18next-chained-backend i18next-http-backend i18next-resources-to-backend react-i18next next-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;
{ "welcome": "Welcome to our application!", "login": "Login" }
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;
Natürlich nicht, ich zeige euch jetzt, was ich im CrazyStack-Projekt gemacht habe. Zuerst habe ich in Nextjs eine andere Konfiguration erstellt und dabei ein statisches JSON verwendet, das ich im öffentlichen Ordner des Projekts selbst definiert habe! Schauen Sie mal rein:
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`, }, ], }, });
Dann habe ich eine Kontext-API erstellt, um die Sprache zu speichern und im gesamten Projekt darauf zuzugreifen. Beginnend mit Importen
import { useTranslation } from "react-i18next"; import { createContext, useState, useContext } from "react";
const I18NContext = createContext({} as any);
Es wird ein Kontext erstellt, um Daten (z. B. die aktuelle Sprache) über das DOM zu speichern und bereitzustellen.
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.
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.
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.
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.
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.
"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];
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:
Dropdown de Idiomas:
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.
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.
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 der ersten Anwendung erfahren Sie, wie Sie eine REST-API im Node.js-Ökosystem erstellen. Es werden Anwendungsfälle mit komplexen Geschäftsregeln wie der Auflistung verfügbarer Zeiten, der Generierung von Bestellungen aus gebuchten Terminen, Treuesystemen, Provisionen, Zahlungen, Kundenbewertungen und vielem mehr erstellt. Alles erfolgt in TypeScript und unter Verwendung der nicht relationalen Datenbank MongoDB.
In der zweiten Anwendung erfahren Sie, wie Sie im React.js-Ökosystem ein Administrationspanel erstellen, um Diagramme anzuzeigen und Datensätze zu bearbeiten. Alles erfolgt mit TypeScript und unter Verwendung des Next.js-Frameworks. Darüber hinaus wird die visuelle Komponentenbibliothek Chakra UI verwendet, die das Atomic Design-Konzept auf die erstellten Komponenten anwendet. Um mehr zu erfahren, besuchen Sie Crazystack.com.br.
Das obige ist der detaillierte Inhalt vonDas Übersetzen Ihres React-Projekts mit i war noch nie so einfach. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!