Next.js i18n

2021. 5. 29. 14:36Dev

반응형

기본적으로 nextjs는 i18n을 지원한다.

 

https://github.com/isaachinman/next-i18next 라이브러리도 있지만 현재(8.3.0) SSR시 문제가 있는 것으로 보인다. 

 

그래서 https://github.com/i18next/react-i18next 라이브러리를 사용해서 구현하였다. 사실 next-18next는 react-i18next의 랩핑 수준의 구현체이므로 크게 다르지 않다.

 

시작하기

next.config.js 에서 i18n 속성을 정의해 준다.

  i18n: {
    defaultLocale: 'ko',
    locales: ['ko', 'en'],
  },

 

그럼 이제 각 페이지 getStaticProps, getServerSideProps API에서 locale prop으로 접근 가능하다.

export async function getStaticProps(context: GetStaticPropsContext) {
  const locale = context.locale

  return {
    props: {
      locale,
    },
  }
}

 

컴포넌트에서 locale을 전달 받아서 pages/_app.tsx 컴포넌트에서 i18n Provider를 랩핑해준다.

function App({ Component, pageProps }: AppProps) {
  const { locale } = pageProps
  const i18n = React.useMemo(() => createI18n({ locale }), [locale])

  return (
    <I18nextProvider i18n={i18n}>
      <Component {...pageProps} />
    </I18nextProvider>
  )
}

여기서 createI18n은 대략 아래와 같은데 i18n을 초기화 후 인스턴스를 넘겨주는 형태이다. 참고

import i18n, { i18n as I18n } from 'i18next'
import { initReactI18next } from 'react-i18next'

import languages, { lngs } from './languages'

type Props = {
  locale: string
}

const { en, ko } = languages

const createI18n = ({ locale }: Props): I18n => {
  i18n.use(initReactI18next).init({
    resources: { en, ko },
    lng: locale,
    fallbackLng: lngs[0],
    interpolation: {
      escapeValue: false,
    },
  })

  return i18n
}

export default createI18n

페이지 컴포넌트에서 아래와 같이 사용하면된다.

import type { GetStaticPropsContext } from 'next'
import { useTranslation } from 'react-i18next'

export async function getStaticProps(context: GetStaticPropsContext) {
  const locale = context.locale

  return {
    props: { locale },
  }
}

export default function Home() {
  const { t } = useTranslation() // default ns 'common'

  return (
    <div>
      <div>{t('hello')}</div>
    </div>
  )
}

getStaticProps가 전달해준 locale prop은 pages/_app.tsx 컴포넌트에서 사용하게 된다.

 

코드를 살펴보면 getStaticProps(혹은 getServerSideProps) API에서 전달하는 props은 pages/_app.tsx 컴포넌트에서 사용한다는 느낌이 직관적이지 않다. 그래서 흐름을 이해하는데 다소 어려웠다. 때문에 공통적으로 페이지 컴포넌트에 locale을 주입해 줄 수 있도록 구현할 수 있는 부분을 찾아보았고 아래와 같다.

pages/_app.tsx

import type { AppProps, AppContext } from 'next/app'

function App({ Component, pageProps, locale }: AppProps & { locale: string }) {
  return (
    <I18nextProvider i18n={i18n}>
      <Component {...pageProps} />
    </I18nextProvider>
  )
}

App.getInitialProps = async ({ ctx }: AppContext) => {
  const { locale } = ctx
  return { locale }
}

문제는 페이지 최적화 기능이 opt out 되면서 모든 페이지가 SSR로 작동한다. 빌드시 경고 문구도 볼 수 있다.

https://nextjs.org/docs/messages/opt-out-auto-static-optimization

트레이드 오프를 생각해서 구현할 필요가 있다.

 

국제화 빌드 과정

getStaticProps API를 사용하면 빌드타임에  locale을 주입하고 각 지원 언어별 html 파일들을 생성해 정적페이지를 만든다.

getServerSideProps 혹은 App.getInitialProps API를 사용하면 서버에서 런타임으로 locale을 주입해주고 html을 동적 생성한다.

 

귀찮지만 각각의 페이지 컴포넌트에서 locale을 주입해주는 방식이 최적화할 수 있으므로 추천한다.

 

 

반응형

'Dev' 카테고리의 다른 글

Next.js meta 태그와 script 태그 다루기  (0) 2021.06.17
JWT cookie vs localStorage  (0) 2021.06.01
amplify nextjs ssr  (0) 2021.05.02
redux saga eventChannel에 관하여  (1) 2020.07.29
drag and drop(feat. react)  (0) 2020.02.14