2. FrontEnd/React / / 2023. 11. 20. 13:26

[React] react-i18next로 다국어 처리 적용하기

회사에서 맡은 프로젝트 중 관리자 페이지 웹사이트에 다국어처리를 적용하게 되었다.
우선, 관리자 페이지여서 SEO는 따로 필요 없었기 때문에 React이고, 이에 따라 react-i18next 적용해서 했던방법을 정리하여 나중에 기억안날때 꺼내볼 목적이다.
(참고 : 서버에서 다국어 지원을 제공하는 next-i18next 라이브러리도 있음)

1. 패키지 설치

$ yarn add react-i18next i18next
$ npm i react-i18next i18next

2. 폴더 구조 (옵션이지만 이렇게 하는게 이쁨)

src > locales폴더 만든 후, en / ko폴더 안 json으로 넣었다.
현재는 관리자페이지만 다국어 처리 적용을하여 json으로 관리해도 될 만큼의 작은규모라 이렇게 하였음

대규모일 경우엔 또 찾아봐야겠다...오우

3. locales폴더 안 i18n.ts 생성 (i18n config 설정)

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import translationEN from 'locales/en/translation.json';
import translationKO from 'locales/ko/translation.json';

const resources = {
  en: {
    translation: translationEN,
  },
  ko: {
    translation: translationKO,
  },
};

i18n.use(initReactI18next).init({
  resources,
  lng: 'ko', // 기본 설정 언어, 'cimode'로 설정할 경우 키 값으로 출력된다.
  fallbackLng: 'en', // 번역 파일에서 찾을 수 없는 경우 기본 언어
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

4. en / ko 폴더의 json관리

json의 key값은 동일하게 설정할것 / value값은 각자 언어에따라 설정

{
  "header": {
    "mypage": "My page",
    "logout": "Sign Out",
    "login": "Sign In",
    "register": "Sign Up",
    "language": "Languages",
    "help": "Help"
  },
  "nav": {
    "dashboard": "Dashboard",
    "shopping-mall": "Shopping Mall"
  }
}

{
  "header": {
    "mypage": "마이페이지",
    "logout": "로그아웃",
    "login": "로그인",
    "register": "회원가입",
    "language": "언어설정",
    "help": "고객센터"
  },
  "nav": {
    "dashboard": "대시보드",
    "shopping-mall": "쇼핑몰"
  }
}

5. 번들링을 위해 index.tsx에 import 하기

// src/index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import './global.scss';
import App from './App';
import reportWebVitals from './reportWebVitals';
import "locales/i18n"; //여기 다국어처리 config한걸 import 한다.

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>,
  document.getElementById('root'),
);

 

6. 사용

// 사용할 컴포넌트

import React, { useState, useRef, useCallback, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import i18n from "locales/i18n";

export default function Header() {
  const { t } = useTranslation();
  const languageRef = useRef<null | HTMLDivElement>(null);
  const [isLanguageMenuOpen, setLanguageMenuOpen] = useState<boolean>(false);


  // 언어 변경하기
  const changeLanguage = (lang: string) => {
    i18n.changeLanguage(lang);
    setLanguageMenuOpen(false);
  };

  return (
    <header>
      <div onClick={() => navigate("/user/signin")}>{t(`header.login`)}</div>
      <div onClick={() => navigate("/user/register")}>{t(`header.register`)}</div>
      <div ref={languageRef} onClick={() => setLanguageMenuOpen(prev => !prev)}>
        {t(`header.language`)}
        {isLanguageMenuOpen && (
          <ul>
            <li onClick={() => changeLanguage("ko")}>한국어</li>
            <li onClick={() => changeLanguage("en")}>English</li>
          </ul>
         )}
      </div>
      <div>{t(`header.help`)}</div>
    
      {isLoggingIn && (
        <div onMouseEnter={() => setSubMenuOpen(true)} onMouseLeave={() => setSubMenuOpen(false)}>
          <div>
            <nav>
              <div>{t(`nav.dashboard`)}</div>
              <div>{t(`nav.shopping-mall`)}</div>
            </nav>
          </div>
        </div>
      )}
    </header>
  )
}

 


폴더구조는 다음 사진과 같다.

728x90
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유