Developer/React

i18n(국제화 언어)리액트에서 적용하기

jaddong 2024. 3. 11. 17:44
320x100

목적

국제화(internalization)된 애플리케이션은 다양한 언어로 서비스를 할 수 있습니다. 그러기 위해서는 사용자의 언어/지역을 자동으로 감지하거나 사용자가 직접 선택할 수 있도록 합니다.

 

라이브러리 비교

React에서 사용할 수 있는 국제화(internalization, 이하 i18n) 라이브러리는 두 종류가 있습니다.

결론부터 말하자면 다음과 같습니다.

  1. Next.js와 Server Side Rendering(SSR)을 사용해야 한다면 next-i18next
  2. Next.js의 Static Site Generation(SSG)을 사용해야 한다면 react-i18next
    • SSR이 필요해질 경우 next-i18next로 갈아타기 편리하기 때문
  3. Next.js를 사용하지 않는다면 react-intl

 

 

셋팅

i18next

번역 기능을 제공하는 JavaScript 라이브러리로, React와 같은 프론트엔드 프레임워크와 독립적으로 사용될 수 있습니다. 이 라이브러리는 다국어 지원을 위해 필요한 핵심 기능을 제공하며, 텍스트의 번역, 다국어 문구들의 로딩과 캐싱, 언어 변경 등을 처리할 수 있습니다. i18next 는 다양한 환경에서 사용할 수 있으며, 웹 앱 뿐만 아니라 모바일 앱이나 서버 측 앱에서도 사용할 수 있습니다.

 

react-i18next(Quick start)

i18next 를 React 애플리케이션에서 쉽게 사용할 수 있도록 해주는 고급적인 React 바인딩 라이브러리입니다. react-i18nexti18next 와 함께 사용하기 위해 React 컴포넌트와 훅을 제공하여 React 앱에서 다국어 지원을 쉽게 구현할 수 있도록 도와줍니다.

주로 i18next 는 다음과 같은 구성 요소들로 이루어져 있습니다:

  • useTranslation: React 훅으로, 컴포넌트에서 다국어 텍스트를 가져오고 언어 변경을 처리할 수 있게 도와줍니다.
  • Trans: 다국어 텍스트를 렌더링하는 데 사용되는 컴포넌트입니다.
  • 기타 추가적인 유틸리티와 컴포넌트들로 구성되어 있습니다.

 

i18next-browser-languagedetector

i18next-browser-languagedetector는 i18next 라이브러리의 브라우저용 언어 감지기입니다. 이것을 사용하여 웹 애플리케이션에서 사용자의 브라우저 언어를 감지하고, 해당 언어에 맞는 디폴트 값을 설정할 수 있습니다.

 

설치

yarn add react-i18next i18next i18next-browser-languagedetector

 

1. src/i18n/index.ts

 

src/i18n/index.ts

import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import LanguageDetector from 'i18next-browser-languagedetector'

import {
  koHome,
  koGnb,
  enHome,
  enGnb,
  frHome,
  frGnb,
  jpHome,
  jpGnb,
} from '../locale'

// the translations
// (tip move them in a JSON file and import them,
// or even better, manage them separated from your code: https://react.i18next.com/guides/multiple-translation-files)
const resources = {
  ko: {
    home: koHome,
    gnb: koGnb,
  },
  en: {
    home: enHome,
    gnb: enGnb,
  },
  fr: {
    home: frHome,
    gnb: frGnb,
  },
  jp: {
    home: jpHome,
    gnb: jpGnb,
  },
}

i18n
  .use(LanguageDetector)
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    resources,
    fallbackLng: 'en',
    supportedLngs: ['ko', 'en', 'fr', 'jp'],
		// language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
    // you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
    // if you're using a language detector, do not define the lng option

    interpolation: {
      escapeValue: false, // react already safes from xss
    },
  })

export default i18n

 

 

2. src/main.tsx 에 import i18n 추가

 

src/main.tsx

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'

import {
  ContainerModalProvider,
  ProgressModalProvider,
  SnackbarProvider,
  ThemeProvider,
} from '@nwaycorp/global-designsystem'
import { nWeb3 } from '@nwaycorp/web3-react'
import './i18n' // 추가

import { App } from './App.tsx'

ReactDOM.render(
  <React.StrictMode>
    <nWeb3.ReactProvider>
      <BrowserRouter>
        <ThemeProvider theme={undefined}>
          <SnackbarProvider>
            <ProgressModalProvider>
              <ContainerModalProvider>
                <App />
              </ContainerModalProvider>
            </ProgressModalProvider>
          </SnackbarProvider>
        </ThemeProvider>
      </BrowserRouter>
    </nWeb3.ReactProvider>
  </React.StrictMode>,
  document.getElementById('root')
)

 

 

3. src/locale에 언어별 json 파일

 

src/locale/en/gnb.json

{
  "about": "about",
  "web3test": "web3 test",
  "designSystem": "design system",
  "connectWallet": "Connect Wallet",
  "disconnectWallet": "Disconnect Wallet"
}

 

 

src/locale/en/home.json

{
  "welcome": "Welcome to CCBB"
}

 

 

4. src/locale/index.ts 에서 json 파일을 export

import koHome from '../locale/ko/home.json'
import koGnb from '../locale/ko/gnb.json'
import enHome from '../locale/en/home.json'
import enGnb from '../locale/en/gnb.json'
import frHome from '../locale/fr/home.json'
import frGnb from '../locale/fr/gnb.json'
import jpHome from '../locale/jp/home.json'
import jpGnb from '../locale/jp/gnb.json'

export { koHome, koGnb, enHome, enGnb, frHome, frGnb, jpHome, jpGnb }

 

 

 

5. src/constants.ts에 화이트 리스트 language 상수 선언

 

src/constants.ts

export const languages = [
  {
    label: 'English',
    value: 'en',
  },
  {
    label: 'French',
    value: 'fr',
  },
  {
    label: 'Korean',
    value: 'ko',
  },
  {
    label: 'Japanese',
    value: 'jp',
  },
]

 

 

 

사용법

useTranslation

i18n에서 제공하는 hook

const { t, i18n } = useTranslation(['gnb'])

return (<>
    <Typography>{i18n.language}</Typography> // 현재 lanuage 상태를 보여줌
    <Typography>{t('about')}</Typography> // gnb.about를 불러옴
</>  
)

 

SelectLanguage

디자인 시스템의 Select 컴포넌트를 활용한 언어를 변경하는 컴포넌트

import { useState } from 'react'
import { useTranslation } from 'react-i18next'

import { Select } from '@nwaycorp/global-designsystem'

import { languages } from '@src/constants'

export const SelectLanguage = () => {
  const { i18n } = useTranslation()
	const initialIndex = languages.findIndex(
    (lang) => lang.value === i18n.language
  )
  const [selectedIndex, setSelectedIndex] = useState<number>(initialIndex)

  const onClickLanguageChange = (index: number) => {
    setSelectedIndex(index) // 선택된 index 값
    i18n.changeLanguage(languages[index].value) // 선택한 언어로 변경
  }

  return (
    <Select
      id="language"
      items={languages}
      onSelect={onClickLanguageChange}
      selectedIndex={selectedIndex}
      size="s"
    />
  )
}

 

결과

나중에 추가하면 좋을 사항

 

- 참고 문서

https://myeongjae.kim/blog/2020/04/12/react-internationalization-libraries-comparison

https://medium.com/ms-club-of-sliit/internationalization-using-i18next-with-react-typescript-d7c443df3be4

 

반응형