Next app에 다국어 적용하기

2 minute read

다국어 적용의 필요성

국내에서만 서비스 하는 것이 아니라면 언제나 다국어 적용이 필요해진다.
React나 Vue에서도 각각 맞는 i18n 모듈이 있고, 공식문서를 확인하며 따라하면 충분히 적용된다.
Next.js에서도 간편하게 사용할 수 있는 모듈이 있어서 해당 모듈에 대해서 설치하고 간단히 적용하는 방법에 대해서 적어볼 것이다.

적용해볼 모듈은 next-i18next이다.

설치하고 적용해보기

npm install next-i18next

해당 명령어로 설치할 수 있다.

이제 번역 컨텐츠를 구성해보자.
만약에 한국어와 영어로 한다고 생각한다면, public 폴더에 en과 ko를 만들어줄 수 있다.

.
└── public
    └── locales
        ├── en
        |   └── common.json
        └── ko
            └── common.json

다른 페이지들이 추가된다면 common.json과 더불어 home.json 등의 파일을 만들어주면 된다.
기본적으로 common.json을 만들어두는 게 좋다. 왜냐하면 common.json이 없으면 next-i18next는 Default namespace Not Found라는 에러를 뱉어낼 것이기 때문이다. 따로 Default namespace를 잡아주지 않을 것이라면 공통된 요소에 쓰는 컨텐츠는 common.json으로 사용하면 된다.

이제 해야할 것은 next-i18next.config.js 파일을 루트 디렉토리에 만드는 것이다.

// next-i18next.config.js

module.exports = {
  i18n: {
    defaultLocale: "en",
    locales: ["en", "ko"],
  },
};

defaultLocale은 en으로 잡고, 사용하는 locale은 en과 ko를 입력해주었다.

주의할 점

해당 파일의 역할과 Locale의 이름에 대해서 알아두어야 할 것이 있다.
우선 next.js는 브라우저 렌더링이 아니라 서버 사이드 렌더링이다. 그래서 react나 vue로 i18n을 넣었을 때와는 다른 상황을 겪게된다. 그건 default값을 전달할 때 다르다는 것이다. 브라우저 렌더링이라면 디폴트 값을 navigator.language 등을 통해서 브라우저의 언어를 갖고오고 해당 값을 전달할 것이다. 그러면 한국어 사용자라면 맨 처음 화면이 한글로 보여질 것이고, 영어권 사용자라면 영어로 보여지도록 만들어 줄 수 있을 것이다.
그러나 서버사이드 렌더링에서는 navigator.language을 사용할 수 없다.

서버사이드렌더링에서 사용하는 것은 요청 Header에 담기는 Accept-Language이다

기본적으로 요청을 할 때 헤더에 Accept-Language가 담긴다.
요청헤더
이미지가 아니라 실제로 확인하고 싶다면 크롬 개발자 도구를 켜고, 네트워크 패널을 켠채로 요청을 해보자.

그리고 next-i18next는 Accept-Language에 맞게 우선적으로 보여주지만 거기에 없다면 디폴트 값을 보여준다.

한국어는 Accept-Language에서 보통 ko로 표현되므로 ko로 설정해주자.

여기서는 디폴트로 설정된 locale이 “/” 이고, ko는 “/ko”가 된다.

next.config.js 추가하기

// next.config.js

const { i18n } = require("./next-i18next.config");

module.exports = {
  i18n,
};

아까 만든 next-i18next.config에서 i18n을 갖고와서 i18n을 전달해주면 된다.

이제는 프로젝트에 적용시켜 보자.

// _app.js

import { appWithTranslation } from "next-i18next";

const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;

export default appWithTranslation(MyApp);

_app에 기본적으로 MYApp이라는 컴포넌트가 있을 것이다. 해당 컴포넌트를 appWithTranslation으로 감싸주면 된다.

그리고 페이지에서는 getStaticProps를 불러와주자.

// pages/index.js

import { serverSideTranslations } from "next-i18next/serverSideTranslations";

export const getStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["common"])),
  },
});

마지막으로는 useTranslation 훅을 통해서 t 함수를 불러와서 적용시켜주면 된다.

import { useTranslation } from "next-i18next";

export const Home = () => {
  const { t } = useTranslation("common");

  return (
    <div>
      <p>{t("Header")}</p>
    </div>
  );
};

내가 만든 예시

내가 만든 예시를 통해 좀 더 살펴보자.

// public/locales/en/common.json
{
  "h1": "A simple example",
  "change-locale": "Change locale",
  "to-second-page": "To second page",
  "error-with-status": "A  error occurred on server",
  "error-without-status": "An error occurred on the server",
  "title": "Home | next-i18next"
}

위와 같이 영어, 한국에 대한 common.json을 만들어두었다.(번역 컨텐츠 작업)
next-i18next.config.js와 next.config.js, _app.jsx는 위와 똑같이 적었다.

// pages/index.js

import Link from "next/link";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { useTranslation } from "next-i18next";

const Home = () => {
  const { t } = useTranslation("common");
  return (
    <div>
      <p>{t("h1")}</p>
      <p>{t("change-locale")}</p>
      <p>{t("to-second-page")}</p>
      <p>{t("error-with-status")}</p>
      <p>{t("error-without-status")}</p>
      <p>{t("title")}</p>
      <div>
        <Link href="/" locale="en">
          <button>영어</button>
        </Link>
        <Link href="/" locale="ko">
          <button>한국어</button>
        </Link>
      </div>
    </div>
  );
};

export const getStaticProps = async ({ locale }) => {
  console.log("locale of getStaticProps", locale);
  return {
    props: {
      ...(await serverSideTranslations(locale, ["common"])),
    },
  };
};

export default Home;

해당 코드에서는 언어를 바꾸는 버튼도 들어가 있다.

import Link from "next/link";

<Link href="/" locale="en">
    <button>영어</button>
</Link>
<Link href="/" locale="ko">
    <button>한국어</button>
</Link>

링크 컴포넌트를 갖고와서 locale을 변경하면 해당 언어에 맞게 변경되는 것을 확인할 수 있다.

Leave a comment