ホームページ  >  記事  >  ウェブフロントエンド  >  i を使用した React プロジェクトの翻訳がかつてないほど簡単になりました

i を使用した React プロジェクトの翻訳がかつてないほど簡単になりました

王林
王林オリジナル
2024-08-24 11:04:05506ブラウズ

Nunca foi tão fácil TRADUZIR seu projeto React com i

クレイジーな開発者って言ってください!

今日は、プロジェクト全体を React に変換することが、今ほど簡単になったことはないということを説明します。しかし、まずこれがなぜ重要なのかを知る必要があります。

プログラミングを始めるとき、コード テキストとメッセージがポルトガル語 (pt-BR) であるのが一般的です。プロジェクトを他の言語に翻訳することは決して優先事項ではなく、複雑であるか不必要であると考えられています。

では、なぜそれが関係があるのでしょうか?

それはあなたの現実次第です。このプロセスを検討する必要がある理由は次のとおりです:

会社はそれを必要としています
あなたが働いている会社、またはあなたが所有しているいくつかの SaaS が別の国で事業を開始し、このニーズを抱えている可能性があります。この機能を備えた製品には大きな違いがあります。

海外求人への応募
国際的な求人に応募する場合、すでに国際化されたプロジェクトを含むポートフォリオを持っていると、印象的なハイライトを得ることができます。これは、あなたが世界的なプロジェクトに取り組む準備ができており、ほとんどの人のように怠け者ではないことを示しています。

学びすぎることはありません
国際化は単なる機能ではなく、重要な学習体験でもあります。これは、スキルやツールの武器庫に含めるもう 1 つの武器です。

昔はどのように行われていたのでしょうか?

プロジェクトの翻訳はすでに古い問題です。人々は、HTML 内で国旗を選択できるようにその選択を作成し、どのテキストが表示されるかを知るためにコード内に if を入力しました。
とても無視されていました。ウェブサイトは単一言語で作成され、翻訳は無計画に追加されました。それがバックエンドにあった場合、取引はさらに悪化したでしょう。

インターネットのグローバル化に伴い、多言語ソフトウェアの需要が高まり、i18n に特化したツールが提供されています。 GNU Gettext のようなソリューションがバックエンドで登場し、その後、フロントエンド用の i18next や reverse-intl などのライブラリが登場しました。ここで疑問が生じます...

i18next vs.反応 intl: どれを選択しますか?

  • i18next: これは 2011 年に登場した、クライアント側の Node.js と SPA の両方で動作する npm パッケージでした。コミュニティはそれを採用し、最終的に 2015 年に React バージョンを React-i18next ライブラリに作成しました。したがって、ポジティブな点とネガティブな点としては次のとおりです。

    • 長所: 柔軟性、移動時間 (2011 年以降)、広大なエコシステム (一度学習すればどこでも翻訳可能)、自動フォールバック。
    • 短所: 学習に時間がかかる。読まなければならないドキュメントはたくさんありますが、必要なものがすべて揃っているわけではありません。
  • react-intl: FormatJS プロジェクトの一部であり、国際 JavaScript API 標準に従い、最新のブラウザーとの互換性を確保します。

    • 長所: ECMAScript 標準に準拠しており、統合が簡単です。
    • 短所: 柔軟性が低く、プラグインのサポートが少ないです。

そしてどれを使いましょうか?

i18次は友達!始めるにはドキュメントを読むことを常にお勧めしますが、Doido のガイドに行きましょう!

i18next を使用した React アプリケーションの国際化

  1. インストール:
   npm install i18next i18next-chained-backend i18next-http-backend i18next-resources-to-backend react-i18next next-i18next 

  1. 構成: i18next を構成するための i18n.js を作成します。
   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;
  1. 翻訳: locales/en/translation.json および locales/pt/translation.json に翻訳ファイルを作成します。
   {
     "welcome": "Welcome to our application!",
     "login": "Login"
   }
  1. 翻訳の使用: 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;
  1. 言語変更: ユーザーが言語を変更できるようにします。
   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 プロジェクトで私が行ったことを紹介します。まず、プロジェクト自体のパブリック フォルダーで定義した静的 JSON を取得して、Nextjs で別の構成を作成しました。見てみましょう:

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.
  1. 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 を使用します。

2 番目のアプリケーションでは、React.js エコシステムで管理パネルを構築してグラフを表示し、レコードを操作する方法を学びます。すべて TypeScript と Next.js フレームワークを使用して行われます。さらに、Chakra UI ビジュアル コンポーネント ライブラリが使用され、Atomic Design の概念が作成されたコンポーネントに適用されます。詳細については、crazystack.com.br をご覧ください。

以上がi を使用した React プロジェクトの翻訳がかつてないほど簡単になりましたの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。