使用 i 翻譯你的 React 項目從未如此簡單

    使用 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 標準保持一致,集成簡單。
      • 缺點:靈活性較差,插件支持較少。

    我們將使用哪一個?

    i18下一個我的朋友們!我總是建議閱讀文檔來開始,但讓我們看看 doido 的指南!

    使用 i18next 國際化 react 應用程序

    1. 安裝
       npm install i18next i18next-chained-backend i18next-http-backend i18next-resources-to-backend react-i18next next-i18next 
    
    
    關注:愛掏網
    1. 配置:創建一個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;
    
    關注:愛掏網
    1. translations:在 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) =&gt; i18n.changelanguage(lng);
    
         return (
           <div>
             <button onclick="{()"> changelanguage('en')}&gt;english</button>
             <button onclick="{()"> changelanguage('pt')}&gt;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. 環境檢查

    export const isbrowser = typeof window !== "undefined";
    
    關注:愛掏網

    此行檢查代碼是否在瀏覽器中運行(而不是在服務器上),這對于處理 localstorage 等特定于客戶端的功能至關重要。

    5.i18nprovider組件

    export const i18nprovider = ({ children }: any) =&gt; {
      const { i18n } = usetranslation() || {};
      const [currentlanguage, setcurrentlanguage] = usestate(
        formatlanguagefromi18n(i18n?.language)
      );
      const changelanguage = (language) =&gt; {
        setcurrentlanguage(language);
        i18n?.changelanguage?.(formatlanguagefromselect(language));
        localstorage.setitem("language", formatlanguagefromselect(language));
      };
      return (
        <i18ncontext.provider value="{{" changelanguage currentlanguage setcurrentlanguage>
          {children}
        </i18ncontext.provider>
      );
    };
    
    關注:愛掏網

    這個組件是一個provider,它包裝了react組件樹并提供了語言的當前狀態以及更改它的函數。

    • usetranslation:從react-i18next庫中檢索i18n對象,其中包含有關當前語言的信息。
    • currentlanguage:存儲當前語言的state,根據i18n檢測到的語言進行初始化。
    • changelanguage:更改語言的函數,這也會將選擇保存在 localstorage 中,以便在頁面重新加載之間保持持久性。

    6. 掛鉤使用i18n

    export const usei18n = () =&gt; {
      if (!isbrowser) {
        return {
          currentlanguage: "pt-br",
          setcurrentlanguage: () =&gt; {},
          changelanguage: () =&gt; {},
        };
      }
      return usecontext(i18ncontext);
    };
    
    關注:愛掏網

    這個鉤子可以輕松訪問任何組件中的國際化上下文。

    • 檢查您是否在瀏覽器中(isbrowser)。如果沒有,則返回默認值,以避免服務器端出錯。
    • 如果在瀏覽器中,則消耗并返回 i18ncontext 上下文。

    7. 轉換圖

    const countrytolanguage = {
      br: "pt-br",
      us: "en",
    };
    const languagetocountry = {
      "pt-br": "br",
      en: "us",
    };
    
    關注:愛掏網

    這些對象將國家/地區代碼映射到語言代碼,反之亦然,從而可以輕松地在不同約定之間格式化語言代碼。

    8. 格式化函數

    export const formatlanguagefromi18n = (language) =&gt; languagetocountry[language];
    export const formatlanguagefromselect = (language) =&gt; countrytolanguage[language];
    
    關注:愛掏網

    這些函數根據需要格式化語言環境。 formatlanguagefromi18n 將語言代碼轉換為國家/地區代碼,而 formatlanguagefromselect 則進行反向轉換。

    完整代碼

    "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) =&gt; {
      const { i18n } = usetranslation() || {};
      const [currentlanguage, setcurrentlanguage] = usestate(
        formatlanguagefromi18n(i18n?.language)
      );
      const changelanguage = (language) =&gt; {
        setcurrentlanguage(language);
        i18n?.changelanguage?.(formatlanguagefromselect(language));
        localstorage.setitem("language", formatlanguagefromselect(language));
      };
      return (
        <i18ncontext.provider value="{{" changelanguage currentlanguage setcurrentlanguage>
          {children}
        </i18ncontext.provider>
      );
    };
    
    export const usei18n = () =&gt; {
      if (!isbrowser) {
        return {
          currentlanguage: "pt-br",
          setcurrentlanguage: () =&gt; {},
          changelanguage: () =&gt; {},
        };
      }
      return usecontext(i18ncontext);
    };
    
    const countrytolanguage = {
      br: "pt-br",
      us: "en",
    };
    
    const languagetocountry = {
      "pt-br": "br",
      en: "us",
    };
    
    export const formatlanguagefromi18n = (language) =&gt; languagetocountry[language];
    export const formatlanguagefromselect = (language) =&gt; countrytolanguage[language];
    
    關注:愛掏網

    然后我改變了導航欄

    在代碼中,我使用國家/地區下拉菜單選擇語言。看看:

    "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 }) =&gt; {
      const { isauthenticated } = useauth() || {};
      const { i18n } = usetranslation();
      const { changelanguage, setcurrentlanguage } = usei18n() || {};
      const { onopen = () =&gt; {}, onclose } = usesidebardrawer() || {};
      const isdesktopversion = usebreakpointvalue({ base: false, lg: true });
      const [country, setcountry] = usestate(formatlanguagefromi18n(i18n?.language));
      useeffect(() =&gt; {
        return () =&gt; {
          onclose?.();
        };
      }, []);
      const dropdown = countrydropdown as any;
      useeffect(() =&gt; {
        const language = localstorage.getitem("language");
        if (language) {
          setcountry(formatlanguagefromi18n(language));
          setcurrentlanguage(language);
          i18n?.changelanguage?.(language);
        }
      }, []);
      return (
        <header><flex alignitems='{"center"}' w='{"100%"}'>
            {isauthenticated &amp;&amp; !isdesktopversion &amp;&amp; (
              <iconbutton aria-label="open sidebar" fontsize="24" icon="{&lt;icon" as="{rimenuline}"></iconbutton>}
                variant="unstyled"
                onclick={onopen}
                mr="1"
                mt={2}
              /&gt;
            )}
            <logo marginbottom="{0}"></logo>
            {/* {islargerthan560 &amp;&amp; (
              <searchbar placeholder="pesquise por nome..." name="search" width="auto"></searchbar>
            )} */}
            {isauthenticated &amp;&amp; (
              <flex align="center" ml="auto">
                {/* <notificationsnav></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,
                  }}
                /&gt;
                <profile showprofiledata="{isdesktopversion}"></profile></dropdown></flex>
            )}
          </flex></header>
      );
    };
    
    關注:愛掏網

    導入和初始設置:

    • useauth:檢查用戶是否經過身份驗證。
    • usebreakpointvalue:根據屏幕大小決定是否顯示桌面版本。
    • usestate:設置國家/語言(國家)的初始狀態,使用formatlanguagefromi18n函數格式化i18n的當前語言
    • useeffect:第一個效果是在卸載組件時清除側邊欄(onclose)。第二個效果檢查語言是否保存在 localstorage 中,如果是,則更新國家/地區狀態并更改應用程序中的語言。

    語言下拉菜單:

    • 下拉列表是使用react-country-region-selector庫的countrydropdown組件實現的,該組件被定制為用作語言選擇器。
    • value={country}:下拉列表中選擇的值由國家/地區控制。
    • onchange={(val) => { ... }}:當下拉值改變時,更新國家狀態,并調用changelanguage函數更改應用程序語言。
    • whitelist={["us", "br"]}:將下拉選項限制為“us”(英語)和“br”(葡萄牙語)。
    • style={...}:下拉菜單的自定義內聯樣式,使用主題的顏色和間距。
    1. 語言選擇器行為
      • 下拉列表允許用戶選擇首選語言,并且此選擇會保留在 localstorage 中。
      • 更改語言時,下拉列表會反映此更改,并且應用程序會更新為使用新選擇的語言。 要在文章中包含您在圖像中提供的代碼片段,您可以遵循以下格式:

    以及如何更改文本?

    從一個組件到另一個組件,我都遵循相同的過程。下面的代碼展示了如何根據本地化密鑰用動態翻譯替換靜態文本:

    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) =&gt; {
      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></ioexitoutline><text fontsize="sm">
              {t("PAGES:HOME_PAGE.logout", { defaultValue: "Sair" })}  // Chave de tradu??o com valor padr?o
            </text></flex></box>
      );
    };
    
    關注:愛掏網

    在此示例中,usetranslation 掛鉤用于加載 pages:home_page.logout 翻譯鍵。如果未找到該密鑰,將顯示默認文本“退出”。

    結論

    這個想法可以應用于任何靜態文本組件。只需使用 usetranslation 鉤子即可。
    國際化您的應用程序可以打開全球市場的大門,突出您的投資組合并提高您的技能。在 i18next 和 react-intl 之間進行選擇取決于您項目的具體需求,但對于那些想要入門的人來說,兩者都是很好的選擇。

    課程建議

    2022 年,我創建了crazystack 訓練營。在其中,我展示了在線服務調度系統的 2 個完整應用程序,應用了設計模式、簡潔架構、功能切片設計、solid、ddd 以及單元、集成和 e2e 測試等先進概念。

    在第一個應用程序中,您將學習如何在 node.js 生態系統中構建 rest api。將創建涉及復雜業務規則的用例,例如列出可用時間、根據預訂生成訂單、忠誠度系統、傭金、付款、客戶評論等等。一切都在 typescript 中完成并使用非關系數據庫 mongodb。

    在第二個應用程序中,您將學習如何在 react.js 生態系統中構建管理面板來查看圖表和操作記錄。一切都是通過 typescript 和 next.js 框架完成的。此外,還將使用chakra ui可視化組件庫,將原子設計概念應用于創建的組件。要了解更多信息,請訪問crazystack.com.br。

    以上就是使用 i 翻譯你的 React 項目從未如此簡單的詳細內容,更多請關注愛掏網 - it200.com其它相關文章!

    聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
    發表評論
    更多 網友評論0 條評論)
    暫無評論

    返回頂部

    主站蜘蛛池模板: 国产精品特级毛片一区二区三区| 国产亚洲综合一区二区三区| eeuss鲁片一区二区三区| 一级毛片完整版免费播放一区| 国产suv精品一区二区33| 福利一区二区在线| 91一区二区视频| 中文人妻无码一区二区三区| 国产MD视频一区二区三区| 亚洲视频一区二区三区| 国产亚洲一区二区三区在线| 一区二区三区高清在线| 夜精品a一区二区三区| 亚洲国产日韩在线一区| 精品一区二区三区在线观看视频 | 福利一区国产原创多挂探花| 麻豆精品人妻一区二区三区蜜桃| 男女久久久国产一区二区三区| 国产剧情国产精品一区| A国产一区二区免费入口 | 无码人妻精品一区二区三区9厂| 中文字幕一区二区三区精彩视频| 免费日本一区二区| 久久一本一区二区三区| 一本大道东京热无码一区| 中文字幕一区在线| 精品国产亚洲一区二区三区| 国产婷婷色一区二区三区| 日韩精品一区二区亚洲AV观看| 无码一区二区三区老色鬼| 日本午夜精品一区二区三区电影| 欧洲无码一区二区三区在线观看| 精品一区二区三区在线播放视频| 久久精品一区二区三区AV| 精品国产一区二区三区麻豆| 3D动漫精品啪啪一区二区下载 | 国产一区二区三区内射高清| 激情综合丝袜美女一区二区| 亚洲AV无码一区二三区| 中文字幕亚洲乱码熟女一区二区 | 国偷自产一区二区免费视频|