728x90
회사에서 맡은 프로젝트 중 관리자 페이지 웹사이트에 다국어처리를 적용하게 되었다.
우선, 관리자 페이지여서 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>
)
}
폴더구조는 다음 사진과 같다.
'2. FrontEnd > React' 카테고리의 다른 글
[React] AuthContext를 사용하여 로그인 관리하기 (1) | 2024.06.11 |
---|---|
[React] CRA(create-react-app) + TypeScript 세팅 +.eslintrc +.prettierrc (0) | 2024.06.10 |
[React] JSX(JavaScriptXML)은 JavaScript의 일종일까? (1) | 2024.03.26 |
[React Query] isLoading vs isFetching (0) | 2022.10.03 |
[React] React 와 Next 비교 (1) | 2022.09.11 |