日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:52010
  • 待審:67
  • 小程序:12
  • 文章:1106242
  • 會(huì)員:784

說(shuō)瘋狂的開發(fā)者!

今天我將向您展示,將整個(gè)項(xiàng)目翻譯成 react 從未像現(xiàn)在這樣容易。但首先您需要知道為什么這很重要。

當(dāng)人們開始編程時(shí),代碼文本和消息通常使用葡萄牙語(yǔ)(pt-br)。將項(xiàng)目翻譯成其他語(yǔ)言從來(lái)都不是優(yōu)先事項(xiàng),并且被認(rèn)為是復(fù)雜或不必要的。

那么為什么它會(huì)相關(guān)呢?

這取決于你的實(shí)際情況。以下是您應(yīng)該考慮此過(guò)程的一些原因:

公司需要
可能是您工作的公司或您擁有的某些 saas 開始在另一個(gè)國(guó)家/地區(qū)運(yùn)營(yíng)并且有此需求。具有此功能的產(chǎn)品有巨大的差異。

申請(qǐng)國(guó)??際職位空缺
如果您正在申請(qǐng)國(guó)際職位空缺,擁有包含國(guó)際化項(xiàng)目的作品集可以給您帶來(lái)引人注目的亮點(diǎn)。這表明您已準(zhǔn)備好從事全球項(xiàng)目,并且不像大多數(shù)人一樣懶惰。

你永遠(yuǎn)不會(huì)學(xué)太多
國(guó)際化不僅是一種特征,也是一種重要的學(xué)習(xí)經(jīng)歷。這是您的技能和工具庫(kù)中的另一種武器。

過(guò)去是如何做到的?

項(xiàng)目翻譯已經(jīng)是個(gè)老問(wèn)題了。人們?cè)?html 中選擇了該國(guó)家的國(guó)旗,供人們選擇,并在代碼中用 if 填充以了解將顯示哪些文本。
這是非常被忽視的。網(wǎng)站是用單一語(yǔ)言制作的,翻譯是隨意添加的。如果是在后端,交易會(huì)更糟糕。

隨著互聯(lián)網(wǎng)的全球化,對(duì)多語(yǔ)言軟件的需求不斷增長(zhǎng),帶來(lái)了針對(duì)國(guó)際化的特定工具。像 gnu gettext 這樣的解決方案出現(xiàn)在后端,隨后出現(xiàn)了像 i18next 和 react-intl 這樣的前端庫(kù)。然后疑問(wèn)就來(lái)了…

i18next 對(duì)比react-intl:選擇哪一個(gè)?

i18next:這個(gè)出現(xiàn)于 2011 年,它是一個(gè) npm 包,適用于客戶端的 node.js 和 spa。社區(qū)采納了它,并最終于2015年在react-i18next lib中制作了react版本。因此,作為積極和消極的點(diǎn),我們有:

優(yōu)點(diǎn):靈活性、路上時(shí)間(自 2011 年起)、龐大的生態(tài)系統(tǒng)(一次學(xué)習(xí),隨處翻譯)和自動(dòng)回退。

缺點(diǎn):學(xué)習(xí)曲線。有很多文檔需要閱讀,但并不是您需要的所有內(nèi)容都在那里。

react-intl:formatjs 項(xiàng)目的一部分,遵循國(guó)際 javascript api 標(biāo)準(zhǔn),確保與現(xiàn)代瀏覽器的兼容性。

優(yōu)點(diǎn):與 ecmascript 標(biāo)準(zhǔn)保持一致,集成簡(jiǎn)單。

缺點(diǎn):靈活性較差,插件支持較少。

我們將使用哪一個(gè)?

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

使用 i18next 國(guó)際化 react 應(yīng)用程序

    安裝

   npm install i18next i18next-chained-backend i18next-http-backend i18next-resources-to-backend react-i18next next-i18next 

登錄后復(fù)制

    配置:創(chuàng)建一個(gè)i18n.js來(lái)配置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;

登錄后復(fù)制

    translations:在 locales/en/translation.json 和 locales/pt/translation.json 中創(chuàng)建翻譯文件。

   {
     "welcome": "welcome to our application!",
     "login": "login"
   }

登錄后復(fù)制

    翻譯的使用:在 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;

登錄后復(fù)制

    語(yǔ)言更改:允許用戶更改語(yǔ)言。

   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;

登錄后復(fù)制

這就是全部嗎?

當(dāng)然不是,我現(xiàn)在向您展示我在 crazystack 項(xiàng)目中做了什么。首先,我在 nextjs 中做了一個(gè)不同的配置,采用了我在項(xiàng)目本身的公共文件夾中定義的靜態(tài) 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`,
        },
      ],
    },
  });

登錄后復(fù)制

然后我創(chuàng)建了一個(gè)上下文 api 來(lái)保存語(yǔ)言并在整個(gè)項(xiàng)目中訪問(wèn)它。從進(jìn)口開始

2. 進(jìn)口

import { usetranslation } from "react-i18next";
import { createcontext, usestate, usecontext } from "react";

登錄后復(fù)制

usetranslation:react-i18next 掛鉤來(lái)訪問(wèn)翻譯功能。在這里,您將在項(xiàng)目中幾乎每個(gè) jsx 組件中使用它。

createcontext、usestate、usecontext:用于創(chuàng)建和使用上下文以及管理狀態(tài)的 react 函數(shù)。

3. 上下文創(chuàng)建

const i18ncontext = createcontext({} as any);

登錄后復(fù)制

創(chuàng)建上下文來(lái)通過(guò) dom 存儲(chǔ)和提供數(shù)據(jù)(例如當(dāng)前語(yǔ)言)。

4. 環(huán)境檢查

export const isbrowser = typeof window !== "undefined";

登錄后復(fù)制

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

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>
  );
};

登錄后復(fù)制

這個(gè)組件是一個(gè)provider,它包裝了react組件樹并提供了語(yǔ)言的當(dāng)前狀態(tài)以及更改它的函數(shù)。

usetranslation:從react-i18next庫(kù)中檢索i18n對(duì)象,其中包含有關(guān)當(dāng)前語(yǔ)言的信息。

currentlanguage:存儲(chǔ)當(dāng)前語(yǔ)言的state,根據(jù)i18n檢測(cè)到的語(yǔ)言進(jìn)行初始化。

changelanguage:更改語(yǔ)言的函數(shù),這也會(huì)將選擇保存在 localstorage 中,以便在頁(yè)面重新加載之間保持持久性。

6. 掛鉤使用i18n

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

登錄后復(fù)制

這個(gè)鉤子可以輕松訪問(wèn)任何組件中的國(guó)際化上下文。

檢查您是否在瀏覽器中(isbrowser)。如果沒(méi)有,則返回默認(rèn)值,以避免服務(wù)器端出錯(cuò)。
如果在瀏覽器中,則消耗并返回 i18ncontext 上下文。

7. 轉(zhuǎn)換圖

const countrytolanguage = {
  br: "pt-br",
  us: "en",
};
const languagetocountry = {
  "pt-br": "br",
  en: "us",
};

登錄后復(fù)制

這些對(duì)象將國(guó)家/地區(qū)代碼映射到語(yǔ)言代碼,反之亦然,從而可以輕松地在不同約定之間格式化語(yǔ)言代碼。

8. 格式化函數(shù)

export const formatlanguagefromi18n = (language) =&gt; languagetocountry[language];
export const formatlanguagefromselect = (language) =&gt; countrytolanguage[language];

登錄后復(fù)制

這些函數(shù)根據(jù)需要格式化語(yǔ)言環(huán)境。 formatlanguagefromi18n 將語(yǔ)言代碼轉(zhuǎn)換為國(guó)家/地區(qū)代碼,而 formatlanguagefromselect 則進(jìn)行反向轉(zhuǎn)換。

完整代碼

"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];

登錄后復(fù)制

然后我改變了導(dǎo)航欄

在代碼中,我使用國(guó)家/地區(qū)下拉菜單選擇語(yǔ)言。看看:

"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>
  );
};

登錄后復(fù)制

導(dǎo)入和初始設(shè)置:

useauth:檢查用戶是否經(jīng)過(guò)身份驗(yàn)證。

usebreakpointvalue:根據(jù)屏幕大小決定是否顯示桌面版本。

usestate:設(shè)置國(guó)家/語(yǔ)言(國(guó)家)的初始狀態(tài),使用formatlanguagefromi18n函數(shù)格式化i18n的當(dāng)前語(yǔ)言

useeffect:第一個(gè)效果是在卸載組件時(shí)清除側(cè)邊欄(onclose)。第二個(gè)效果檢查語(yǔ)言是否保存在 localstorage 中,如果是,則更新國(guó)家/地區(qū)狀態(tài)并更改應(yīng)用程序中的語(yǔ)言。

語(yǔ)言下拉菜單:

下拉列表是使用react-country-region-selector庫(kù)的countrydropdown組件實(shí)現(xiàn)的,該組件被定制為用作語(yǔ)言選擇器。

value={country}:下拉列表中選擇的值由國(guó)家/地區(qū)控制。

onchange={(val) => { … }}:當(dāng)下拉值改變時(shí),更新國(guó)家狀態(tài),并調(diào)用changelanguage函數(shù)更改應(yīng)用程序語(yǔ)言。

whitelist={[“us”, “br”]}:將下拉選項(xiàng)限制為“us”(英語(yǔ))和“br”(葡萄牙語(yǔ))。

style={…}:下拉菜單的自定義內(nèi)聯(lián)樣式,使用主題的顏色和間距。

    語(yǔ)言選擇器行為

    下拉列表允許用戶選擇首選語(yǔ)言,并且此選擇會(huì)保留在 localstorage 中。
    更改語(yǔ)言時(shí),下拉列表會(huì)反映此更改,并且應(yīng)用程序會(huì)更新為使用新選擇的語(yǔ)言。
    要在文章中包含您在圖像中提供的代碼片段,您可以遵循以下格式:


以及如何更改文本?

從一個(gè)組件到另一個(gè)組件,我都遵循相同的過(guò)程。下面的代碼展示了如何根據(jù)本地化密鑰用動(dòng)態(tài)翻譯替換靜態(tài)文本:

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>
  );
};

登錄后復(fù)制

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

結(jié)論

這個(gè)想法可以應(yīng)用于任何靜態(tài)文本組件。只需使用 usetranslation 鉤子即可。
國(guó)際化您的應(yīng)用程序可以打開全球市場(chǎng)的大門,突出您的投資組合并提高您的技能。在 i18next 和 react-intl 之間進(jìn)行選擇取決于您項(xiàng)目的具體需求,但對(duì)于那些想要入門的人來(lái)說(shuō),兩者都是很好的選擇。

課程建議

2022 年,我創(chuàng)建了crazystack 訓(xùn)練營(yíng)。在其中,我展示了在線服務(wù)調(diào)度系統(tǒng)的 2 個(gè)完整應(yīng)用程序,應(yīng)用了設(shè)計(jì)模式、簡(jiǎn)潔架構(gòu)、功能切片設(shè)計(jì)、solid、ddd 以及單元、集成和 e2e 測(cè)試等先進(jìn)概念。

在第一個(gè)應(yīng)用程序中,您將學(xué)習(xí)如何在 node.js 生態(tài)系統(tǒng)中構(gòu)建 rest api。將創(chuàng)建涉及復(fù)雜業(yè)務(wù)規(guī)則的用例,例如列出可用時(shí)間、根據(jù)預(yù)訂生成訂單、忠誠(chéng)度系統(tǒng)、傭金、付款、客戶評(píng)論等等。一切都在 typescript 中完成并使用非關(guān)系數(shù)據(jù)庫(kù) mongodb。

在第二個(gè)應(yīng)用程序中,您將學(xué)習(xí)如何在 react.js 生態(tài)系統(tǒng)中構(gòu)建管理面板來(lái)查看圖表和操作記錄。一切都是通過(guò) typescript 和 next.js 框架完成的。此外,還將使用chakra ui可視化組件庫(kù),將原子設(shè)計(jì)概念應(yīng)用于創(chuàng)建的組件。要了解更多信息,請(qǐng)?jiān)L問(wèn)crazystack.com.br。

分享到:
標(biāo)簽:React 簡(jiǎn)單 翻譯 項(xiàng)目
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 52010

    網(wǎng)站

  • 12

    小程序

  • 1106242

    文章

  • 784

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定