[gatsby] Gatsby에서 i18next 사용하기(다국어지원)

Suyeon·2020년 12월 6일
7

React

목록 보기
10/26

Internationalization of gatsby site using i18next.

포토폴리오 웹사이트를 제작하던 중, 다국어 지원(영어/한국어)기능을 추가하기 위해 i18n 라이브러리를 처음 사용해봤다. 이 방법 이외에도 gatsby에서 지원하는 플러그인을 사용할 수도 있다.

Installation

  • npm install react-i18next i18next --save
  • npm install i18next-http-backend i18next-browser-languagedetector --save (if you'd like to detect user language and load translation)

i18n.js

Root엥 i18n.js파일을 생성한다.

// i18n.tsx (root)
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';

const languages = ['en', 'ko']; // (*)

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    debug: true,
    whitelist: languages,

    interpolation: {
      escapeValue: false,
    },
  });

export default i18n;

Layout.js

SSR방식을 사용하는 웹사이트는 I18nextProvider로 랩핑을 해줘야 한다. 따라서 Layout 컴포넌트를 I18nextProvider로 감싸줬다.

// Layout.js
import { I18nextProvider } from 'react-i18next';
import i18n from '../../i18n';

const Layout: React.FC<LayoutProps> = ({ children }) => {
  return (
    <I18nextProvider i18n={i18n}> // (*)
      <div style={{ overflow: 'hidden' }}>
         {...}
      </div>
    </I18nextProvider>
  );
};

export default Layout;

Hook을 사용하거나, HOC를 사용하는 방법이 있는데 난 functional component와 함께 Hook을 사용했다. 각자 선호하는 방식을 선택하면 될 것 같다.

유저가 언어를 선택할 수 있는 드롭다운 메뉴를 생성했다. i18next-browser-languagedetector는 자동으로 사용자의 브라우저의 언어를 인식하여 해당언어로 컨텐츠를 번역한다. 따라서 드롭다운 메뉴의 글자 또한 사용자의 브라우저 언어에 따라서 변경했다.

// Dropdown.js
import { useTranslation } from 'react-i18next';

const LangDropDown: React.FC = () => {
  const [lang, setLang] = useState('en');
  const { i18n } = useTranslation(); // (*) change the language (118n instace)
  const { ref, clickInside, setClickInside } = useClickInside(false);
  
    useEffect(() => {
    // Detect user's browser language and change default language of dropdown
    const userLanguage: string = window.navigator.language;

    if (userLanguage === 'ko') {
      setLang('ko');
      i18n.changeLanguage('ko');
    } else {
      setLang('en');
      i18n.changeLanguage('en');
    }
  }, []);

  const languages: Languages[] = [
    { lang: 'en', icon: usa },
    { lang: 'ko', icon: korea },
  ];

  const handleClick = (lang: string): void => {
    i18n.changeLanguage(lang); // (**)
    setLang(lang);
  };

  return (
    <Wrapper>
      <span>{lang}</span>
	  { isHover && (<Dropdown>
          {languages.map((lang) => (
            <li onClick={() => handleClick(lang.lang)} key={lang.lang}> // (*)
              <img src={lang.icon} alt={lang.lang} />
              {lang.lang}
            </li>
          ))}
        </Dropdown>)}
      <img src={arrow} alt="Language Options" />
    </Wrapper>
  );
};

export default React.memo(LangDropDown);

translation.json

번역을 하기 위해서 public - locales - en - translation.json 파일을 생성한다. (언어별로 폴더를 생성한다.)

// locale-en-translation.json
{
	"About": {
    	"0": "Hello",
      	"1": "I am Suyeon"
    }
}
// locale-ko-translation.json
{
	"About": {
    	"0": "안녕하세요",
      	"1": "저는 수연입니다"
    }
}

Translate Contents

이제 드디어 번역할 시간이다! 번역을 할 때는 i18next에서 제공하는 t function을 사용하면 된다.

import { useTranslation } from 'react-i18next';

const About: React.FC = () => {
  const { t } = useTranslation(); // (*) Translate

  return (
    <Wrapper>
        <Description>{t('About.0')}</Description> // (*)
        <Description>{t('About.1')}</Description>
    </Wrapper>
  );
};

export default About;

gatsby-config.js

페이지를 이동할 경우, 내가 선택한 언어와 아이콘을 일정하게 보여주기 위해서 gatsby-plugin-layout을 설치한다.

  • npm i gatsby-plugin-layout
// gatsby-config.js
plugins: [{
  resolve: `gatsby-plugin-layout`,
  options: {
    component: `${__dirname}/src/components/Layout.js`
  }
}]

gatsby-node.js

gatsby build를 할 때 locales 폴더가 알맞게 public안에 위치할 수 있도록 경로를 세팅한다.

const fs = require('fs-extra');
const path = require('path');
exports.onPostBuild = () => {
  console.log('Copying locales');
  fs.copySync(
    path.join(__dirname, '/src/locales'),
    path.join(__dirname, '/public/locales'),
  );
};

번역된 모습


참고 자료
step-by-step-guide-to-use-i18next-in-gatsby-app
Multi-language Translate React JS APP with React Hook & I18NEXT
i18next 공식문서
gatsby 공식문서

profile
Hello World.

2개의 댓글

comment-user-thumbnail
2020년 12월 8일

👍

답글 달기
comment-user-thumbnail
2021년 5월 12일

만은 도움이 되어읍미다

답글 달기