본문 바로가기
FrontEnd

[Tip] next.js에서 i18n 을 세팅해보자

by 수비두비 2022. 5. 30.

i18n 이란?

i18n(국제화)이란 응용 프로그램을 다양한 지역에 맞게 조정하는 시스템이다. 여기서는 한국어, 영어 정도의 번역만 다룬다.

기본 동작 원리

next-i18next.config.js 파일을 통해 next-i18next에 대한 구성 환경을 제공한다. 환경 세팅 후 appWithTranslation을 useTranslation 훅에 있는 메서드(?)인 t를 통해서 해당 url에 맞는 번역 기능을 제공한다.

next-i18next 설치

npm i next-i18next // yarn add next-i18next

기본 셋업

// next-i18next.config.js
module.exports = {
  i18n: {
    defaultLocale: "ko",
    locales: ["en", "ko"],
  },
};
// next.config.js
const { i18n } = require("./next-i18next.config");
module.exports = {
  i18n,
};

locale 파일 생성

public/locales 에 만들어주면 된다.
public
     /locales
            /en
               /about.json
           /ko
              /about.json

// public/locales/ko/about.json
{
    "h1": "어바웃 페이지",
    "description": "안녕하세요 어바웃 페이지입니다.",
    "currentUrl": "현재 url"
}

// public/locales/en/about.json
{
    "h1": "About Page",
    "description": "Hello this is about page",
    "currentUrl": "current url"
}

about 페이지

serverSideTranslations 통해서 locale 정보를 넘겨주고
useTranslation 훅을 통해서 해당 json 에 값을 반환한다.

// /pages/about.tsx
import React from 'react'
import { useRouter } from 'next/router'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { useTranslation } from 'next-i18next'

export const getStaticProps = async ({ locale }: any) => ({
  props: {
    ...(await serverSideTranslations(locale, ['about'])),
  },
})
const AboutPage: React.FC = () => {
  const router = useRouter()
  const { t } = useTranslation('about')

  return (
    <div>
      <h1>{t('h1')}</h1>
      <ul>
        <li>
          {t('currentUrl')} : http://localhost:3000
          {router.locale !== 'ko' && '/' + router.locale}
          {router.pathname}
        </li>
        <li>locale: {router.locale}</li>
        <li>pathname: {router.pathname}</li>
      </ul>
    </div>
  )
}

export default AboutPage
  • 경로가 default인 경우
  • 경로가 en인 경우

사용 사례

리액트는 컴포넌트화를 많이 하는데 같은 페이지 내에서 prop으로 넘길 필요없이 useTranslation 훅을 사용할 수 있다.

  • about page
import React from 'react'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'

import { AboutHeader, AboutUrlInfo } from '@components/about'
export const getStaticProps = async ({ locale }: any) => ({
  props: {
    ...(await serverSideTranslations(locale, ['about'])),
  },
})
const AboutPage: React.FC = () => {

  return (
    <div>
      <AboutHeader />
      <AboutUrlInfo />
    </div>
  )
}

export default AboutPage
  • about component

components/about/
                            index.tsx
                            useGetUlElement.tsx

-useGetUlElement.tsx

import React from 'react'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'

const useCurrentUrl = () => {
  const router = useRouter()
  const { t } = useTranslation('about')
  const ulElement = (
    <ul>
      <li>
        {t('currentUrl')} : http://localhost:3000
        {router.locale !== 'ko' && '/' + router.locale}
        {router.pathname}
      </li>
      <li>locale: {router.locale}</li>
      <li>pathname: {router.pathname}</li>
    </ul>
  )
  return { ulElement }
}
export default useCurrentUrl

- index.tsx

import { useTranslation } from 'next-i18next'
import useCurrentUrl from './useGetUlElement'

export const AboutHeader = () => {
  const { t } = useTranslation('about')
  return <h1>{t('h1')}</h1>
}
export const AboutUrlInfo = () => {
  const { ulElement } = useCurrentUrl()
  return ulElement
}

위 파일에서 알 수 있듯이 prop으로 t 메서드를 넘길 필요가 없다.
물론 넘길 수도 있다.

브라우저 언어설정(locale)에 따른 i18적용 예시

_app.tsx 파일에서 localStorage를 활용해서 적용해보았다.
간편한 사용예시라 더 세심하게는 만들지 못했지만
이 부분은 당연히 custom hook으로 만드는 게 더 좋을 거 같다.

// pages/_app.tsx
  React.useEffect(() => {
    if (router.isReady) return
    const lang = document.documentElement.lang
    const locale = window.localStorage.getItem('locale')
    const { pathname } = router
    if (['en', 'ko'].includes(lang) && !locale) {
      window.localStorage.setItem('locale', lang)
      router.replace(`/${lang}${pathname}`)
    } else {
      window.localStorage.setItem('locale', `${router.locale}`)
      router.replace(`/${locale}${pathname}`)
    }
  }, [router.isReady])

회고

i18에 대한 고민이 사실 많지는 않았는데 이번 프로젝트에 적용을 하면서 사용법도 보고 글도 정리해서 좋았다.
강력하고 좋은 라이브러리인데 아쉬운 점도 있었다.

  • next-i18next.config.js 파일에서 defaultLocale 이라는 key 값의 value로 단순하게 'ko' 또는 'en'을 넣기보다는 브라우저 언어설정에 따라가고 싶은데 그 부분이 없어서(?) 아쉬웠고, 조금 헤맸던 거 같다.
  • 주소창에 defaultLocale 언어가 아니면 해당 언어가 남아서 조금 별로였다. 이건 어떻게 해줄 수 있을 거 같은데 나중에 깊게 다루게 된다면 보면 좋을 거 같다.

댓글