Nextjs와 Chakra UI를 사용하여 국제화 (i18n) 루트 웹 응용 프로그램 설정하기

안녕하세요!!본고에서, 나는 당신에게 NextjsChakraUI를 사용하여 다국어 웹 응용 프로그램을 설정하는 방법을 보여 드리겠습니다.

머리말


다국어 웹 응용 프로그램은 다양한 언어(예를 들어 영어, 아랍어, 프랑스어 등)로 내용을 제공하는 응용 프로그램이다.
다국어 웹 응용 프로그램을 구축하면 기업에 이점을 가져다 줄 수 있다. 예를 들어 고객층을 확대하고 매출을 확보하는 것이다.
클라이언트 로켈에 따라 내용을 왼쪽에서 오른쪽(LTR) 및 오른쪽에서 왼쪽(RTL) 언어로 표현하는 방법을 보여주는 프레젠테이션 애플리케이션을 구축합니다.
시범 프로그램은 아래 그림과 같다.


이 자습서는 다음 두 단계로 진행됩니다.
1단계:Nextjs, ChakraUI 및 기타 종속 항목을 설정합니다.
2단계: 응용 프로그램의 국제화를 설정합니다.
자, 시작합시다.

첫 번째 단계: Nextjs와 ChakraUI를 설정합니다.


NextJs는 서버측 렌더링과 정적 웹 응용 프로그램을 구축하는 React 프레임워크입니다. 
NextJs를 설정하려면 프로젝트 디렉토리에서 다음 명령을 실행합니다.
yarn create next-app
yarn add typescript
yarn add -D @types/react @types/react-dom @types/node
파일 구조는 다음과 같습니다.

펄스 휠 사용자 인터페이스 설정


ChakraUI는 응용 프로그램 구축에 필요한 빌드 블록을 제공하는 간단하고 모듈화된 구성 요소 라이브러리입니다.Check out the docs .
Chakra UI를 설정하려면 패키지와 해당 피어 종속성을 설치합니다.
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
Chakra UI를 사용하려면 테마 공급자를 설정해야 합니다.
다음과 같이 pages/_app.tsx 어플리케이션을 열고 ChakraProvider로 포장합니다.
import { ChakraProvider } from "@chakra-ui/react";
import { AppProps } from "next/app";

function MyApp(props: AppProps) {
  const { Component, pageProps } = props;
  return (
    <ChakraProvider>
      <Component {...pageProps} />
    </ChakraProvider>
  );
}

export default MyApp;
Chakra의 UI 기능을 시연하기 위해 카드 구성 요소를 구축합니다.
import React from "react";
import { Box, Text, Container } from "@chakra-ui/react";

export const data = [
  {
    image_url: "https://cutt.ly/ehEjUVT",
    title_en: "Sample shoe",
    title_ar: "حذاء عينة",
    price: 20,
    currency_en: "AED",
    currency_ar: "درهم",
  },
  {
    image_url: "https://cutt.ly/ehEjUVT",
    title_en: "Christmas shoe",
    title_ar: "حذاء عيد الميلاد",
    price: 30,
    currency_en: "AED",
    currency_ar: "درهم",
  },
  {
    image_url: "https://cutt.ly/ehEjUVT",
    title_en: "Sample booth",
    title_ar: "كشك عينة",
    price: 40,
    currency_en: "AED",
    currency_ar: "درهم",
  },
];

type CardPropType = {
  children: React.ReactNode;
};

// product card component
const Card = (props: CardPropType) => {
  const { children } = props;
  return (
    <Box
      borderWidth={1}
      borderTopRightRadius={10}
      maxW={400}
      paddingY={"10px"}
      paddingX={"10px"}
      my={"10px"}
    >
      {children}
    </Box>
  );
};

export default function Home() {
  return (
    <Container>
     {data.map((item, index) => {
       return (
        <Card key={index}>
              <img
                src={item.image_url}
              />
              <Text fontSize="xl">Sample shoe</Text>
              <Text fontSize="xl">
                {currency} {price}
              </Text>
         </Card>
       )
     })
    </Container>
  );
}
변경 사항을 보려면 명령yarn dev을 사용하여 서버를 실행합니다.

2단계: 국제화 설정


NextJs에 다중 언어 지원을 추가하려면 다음 구성을 사용하여 응용 프로그램의 루트 디렉토리에 next.config.js 파일을 생성합니다.
module.exports = {
    i18n: {
        locales: ['en', 'ar'],
        defaultLocale: 'en',
    },
};
locales 프로그램이 지원하는 언어를 지정하는 데 사용됩니다.defaultLocale 예비(fallback) 언어를 지정합니다._document.tsx 디렉터리에 pages 파일을 만듭니다. 이 _document.tsx는 바디 요소에 접근할 수 있도록 합니다. 이 요소는 HTML dir (방향) 과 lang 속성을 변경하는 데 사용됩니다.
import Document, {Html, Head, Main, NextScript, DocumentContext} from 'next/document'

class MyDocument extends Document {
    static async getInitialProps(ctx: DocumentContext) {
        const initialProps = await Document.getInitialProps(ctx);
        return { ...initialProps }
    }

    render() {
        const {locale} = this.props.__NEXT_DATA__ 
        const dir = locale === 'ar' ? 'rtl' : 'ltr';
        return (
            <Html>
                <Head />
                <body dir={dir} lang={locale}>
                <Main />
                <NextScript />
                </body>
            </Html>
        )
    }
}

export default MyDocument

로컬 기반 변경 내용


간단한 방법


우리가 언어 업데이트 내용을 기반으로 하는 간단한 방법 중 하나는 locale 갈고리에 끼워진NextJsuseRouter를 이용하는 것이다.
지역이 pages/_index.tsx로 설정되었을 때 아랍어 텍스트 업데이트 ar 파일의 제품 스티커를 사용합니다.
export default function Home() {
  const router = useRouter();
  const { locale } = router;

  return (
    <Container>
      {data.map((item, index) => {
       return (
        <Card key={index}>
              <img
                src={item.image_url}
              />
              <Text fontSize="xl">
               {locale === 'ar' ? كشك عينة : Sample booth }
              </Text>
              <Text fontSize="xl">
                {currency} {price}
              </Text>
         </Card>
       )
     })
    </Container>
  );
}

To test this, add /ar to the route. example: >http://localhost:3000/ar


더 좋은 방법.


현재의 해결 방안은 NextJs에서 페이지를 구축할 때 매우 효과적인 삼원 연산자를 사용하여 내용을 바꾸는 것이다.
다른 방법은 ar.jsonen.json를 포함하는 정적 파일을 만들고 NextJsgetStaticProps를 이용하여 지역 설정에 따라 정확한 파일을 불러오는 것이다.
1. 정적 파일을 만듭니다.en.json and ar.json 디렉토리에 두 개의 파일public/static을 생성합니다.
// en.json
{
  "item_title": "VANS"
}
// ar.json
{
  "item_title": "شاحنات"
}
2단계 getStaticProps 함수:getStaticProps 파일에 pages/index.tsx 함수를 추가합니다.
여기에서 Node 파일 시스템 (fs) 을 사용하여 문서를 읽고 내용을 도구로 구성 요소로 되돌려줍니다. 이 구성 요소도 창 대상에서 사용할 수 있습니다.
export const getStaticProps: GetStaticProps = async (ctx) => {
 const { locale } = ctx;
 const dir = path.join(process.cwd(), "public", "static"); 
 const filePath = `${dir}/${locale}.json`;
 const buffer = fs.readFileSync(filePath); 
 const content = JSON.parse(buffer.toString());
 return {
  props: { 
   content,
  },
 };
};
이 때, 우리는 Home 구성 요소의 내용 도구에 접근할 수 있으며, 이 구성 요소는 현재 언어 환경을 포함하는 정적 파일의 대상을 되돌려줍니다.
이 방법을 사용하려면 Home 구성 요소를 업데이트합니다.
export default function Home({content}) {

return (
    <Container>
      {data.map((item, index) => {
       return (
        <Card key={index}>
              <img
                src={item.image_url}
              />
              <Text fontSize="xl">
               {content.item_title}
              </Text>
              <Text fontSize="xl">
                {currency} {price}
              </Text>
         </Card>
       )
     })
    </Container>
  );
}

To test this, add /ar to the route. example: >http://localhost:3000/ar


대형 응용 프로그램에 적용되는 건장한 방법.


여러 페이지와 구성 요소를 가진 대형 응용 프로그램을 위해 다중 언어 내용을 관리하려면 useContexts 아직 부족할 수 있습니다. 전역 함수가 필요합니다. 문자열 id를 전달하고 번역된 값을 얻을 수 있습니다.
프로그램의 루트 디렉터리에 파일 trans.tsx 을 만들고 함수 trans 를 만듭니다.
trans 함수는 플러그인 react-rtl 을 이용하여 내용을 변환하고 번역된 값을 되돌려줍니다.
플러그인을 설치하려면:

yarn add react-rtl

import { createIntl, createIntlCache, IntlCache } from "react-intl";
const cache: IntlCache = createIntlCache();
const intlProv = {};
const content = {};

function getMessages(lang: string) {
  if (!content[lang]) {
     if(typeof window !== "undefined") {
      //@ts-ignore
      content[lang] = window.__NEXT_DATA__?.props.pageProps.content;
      }
   }
  return content[lang];
}

function getIntlProvider(lang: string) {
  if (!intlProv[lang]) {
    intlProv[lang] = createIntl({
     locale: lang,
     messages: getMessages(lang),
     onError: () => {},
    },
    cache // optional
   );
  }
return intlProv[lang];
}

export const trans = (id: string, values?: any) => {
let locale: string;
if(typeof window !== "undefined") {
   //@ts-ignore
   locale = window.__NEXT_DATA__?.locale;
}
 const intl = getIntlProvider(locale);
 return intl.formatMessage({ id }, values);
};
우리는 getMessagesgetIntlProvider 함수를 만들어서 그 역할을 설명한다.
getMessages 함수는 getStaticProps 함수에서 저장된 창의 대상에서 내용을 가져옵니다.
getIntlProvider 함수는 현재 언어에 따라 getMessages 함수에서 이 내용을 번역합니다.
이 방법을 사용하려면 Home 구성 요소를 업데이트합니다.

export default function Home({content}) {

return (
    <Container>
      {data.map((item, index) => {
       return (
        <Card key={index}>
              <img
                src={item.image_url}
              />
              <Text fontSize="xl">
               {trans('item_title')}
              </Text>
              <Text fontSize="xl">
                {currency} {price}
              </Text>
         </Card>
       )
     })
    </Container>
  );
}

To test this, add /ar to the route. example: >http://localhost:3000/ar


아랍어rtl와 일치하도록 뒤집지 않은 스타일도 있습니다. 예를 들어 borderTopRightRadiusborderTopLeftRadius로 변경되지 않았습니다.
이 문제를 해결하기 위해 ChakraUI가 감정을 사용하기 때문에 우리는 stylis 플러그인을 추가하여 스타일을 효과적으로 변환할 수 있다.
플러그인을 설치하려면:
yarn add stylis-plugin-rtl stylis
rtl-provider.tsx라는 파일을 만듭니다.그리고 RtlProvider 구성 요소를 만듭니다. 이 구성 요소는 stylis-plugin-rtl.
import { CacheProvider } from "@emotion/react";
import createCache, { Options } from "@emotion/cache";
import React from "react";
import { useRouter } from "next/router";
import stylisPluginRtl from "stylis-plugin-rtl";

export type LangDirection = "rtl" | "ltr";

type CreateCacheOptions = {
  [K in LangDirection]: Options;
}

const options: CreateCacheOptions = {
  rtl: { key: "ar", stylisPlugins: [stylisPluginRtl as any] },
  ltr: { key: "en" },
};


type RtlProviderProps = {
  children: React.ReactNode;
};

export function RtlProvider(props: RtlProviderProps) {
  const { locale } = useRouter();

  const { children } = props;
  const direction = locale == "ar" ? "rtl" : "ltr";

  return (
    <CacheProvider value={createCache(options[direction])}>
      {children}
    </CacheProvider>
  );
}

pages/_app.tsx 파일로 이동하여 저희가 만든 <App/> 패키지RtlProvider 구성 요소를 사용하십시오.
import { ChakraProvider } from "@chakra-ui/react";
import { AppProps } from "next/app";
import { RtlProvider } from "../rtl-provider";

function MyApp(props: AppProps) {
  const { Component, pageProps } = props;
  return (
    <ChakraProvider>
      <RtlProvider>
        <Component {...pageProps} />
      </RtlProvider>
    </ChakraProvider>
  );
}

export default MyApp;
응용 프로그램 서버를 다시 시작하고 ar 로케일을 라우트에 추가합니다: http://localhost:3000/ar.borderTopRightRadiusborderTopLeftRadius로 전환되었습니다.
이제 로케일에 따라 LTR에서 RTL로 어플리케이션을 전환할 수 있습니다.
우리는 단추를 추가해서 루트에서 언어를 직접 바꾸어 코드의 흥미를 높일 수 있다.

export default function Home({content}) {

return (
    <Container>
       <Button
          bg={"tomato"}
          display={{ base: "none", md: "flex" }}
          onClick={async () => {
            await router.push("/", "/", {
              locale: locale === "en" ? "ar" : "en",
            });
            router.reload();
          }}
        >
          {trans("change_app_language")}
        </Button>
      {data.map((item, index) => {
       return (
        <Card key={index}>
              <img
                src={item.image_url}
              />
              <Text fontSize="xl">
               {trans('item_title')}
              </Text>
              <Text fontSize="xl">
                {currency} {price}
              </Text>
         </Card>
       )
     })
    </Container>
  );
}
다음은 github의 전체 코드에 대한 링크입니다.
너는 나를 따라와도 된다
안전과 즐거움을 유지하다.

좋은 웹페이지 즐겨찾기