목적
국제화(internalization)된 애플리케이션은 다양한 언어로 서비스를 할 수 있습니다. 그러기 위해서는 사용자의 언어/지역을 자동으로 감지하거나 사용자가 직접 선택할 수 있도록 합니다.
라이브러리 비교
React에서 사용할 수 있는 국제화(internalization, 이하 i18n) 라이브러리는 두 종류가 있습니다.
- react-intl
- react-i18next
- Next.js지원을 강화한 next-i18next
결론부터 말하자면 다음과 같습니다.
- Next.js와 Server Side Rendering(SSR)을 사용해야 한다면 next-i18next
- Next.js의 Static Site Generation(SSG)을 사용해야 한다면 react-i18next
- SSR이 필요해질 경우 next-i18next로 갈아타기 편리하기 때문
- Next.js를 사용하지 않는다면 react-intl
셋팅
i18next
번역 기능을 제공하는 JavaScript 라이브러리로, React와 같은 프론트엔드 프레임워크와 독립적으로 사용될 수 있습니다. 이 라이브러리는 다국어 지원을 위해 필요한 핵심 기능을 제공하며, 텍스트의 번역, 다국어 문구들의 로딩과 캐싱, 언어 변경 등을 처리할 수 있습니다. i18next 는 다양한 환경에서 사용할 수 있으며, 웹 앱 뿐만 아니라 모바일 앱이나 서버 측 앱에서도 사용할 수 있습니다.
react-i18next(Quick start)
i18next 를 React 애플리케이션에서 쉽게 사용할 수 있도록 해주는 고급적인 React 바인딩 라이브러리입니다. react-i18next 는 i18next 와 함께 사용하기 위해 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"
/>
)
}
결과
나중에 추가하면 좋을 사항
- google sheets 연동으로 번역가와 소통 줄이기 : NHN 국제화(i18n) 자동화 가이드
- 참고 문서
https://myeongjae.kim/blog/2020/04/12/react-internationalization-libraries-comparison
'Developer > React' 카테고리의 다른 글
디자인 시스템을 개발하면서 알게 된 peerDependencies의 역할 (1) | 2024.06.10 |
---|---|
리액트에서 DOM 사이즈 줄이는 최적화 방법 (0) | 2024.01.10 |
리액트에서 라이브러리없이 간단하게 이미지 최적화하기 (2) | 2024.01.03 |
useEffect와 useLayoutEffect의 차이 예제로 쉽게 이해하기 (0) | 2023.01.13 |
React Clean Code 를 위한 팁 (0) | 2022.09.04 |