Nextjs에서 다국어 지원 next-i18next 적용하기

시작하기

이전에 react에서 다국어 i18n을 지원하는 포스트를 작성했었습니다.
nextjs에서는 다른 방법으로 i18n을 설정해 주어야 합니다.
시작해보도록 하겠습니다.

설치하기

Nextjs 에서 typescript 적용하기 포스트 를 참고하여 프로젝트를 생성해줍니다.

1
yarn add i18next next-i18next react-i18next i18next-icu
  • i18next: javascript로 작성된 국제화 프레임 워크로 표준 i18n 기능을 제공합니다.
  • next-i18next: next에서 쉽게 번역을 제공합니다.
  • react-i18next: 고차 컴포넌트 (hoc) 및 컨텍스트에 i18next를 추가합니다.
  • i18next-icu: i18next와 함께 ICU 형식 (International Components for Unicode)을 사용하는 i18nFormat 플러그인입니다.

설정하기

몇 가지 파일을 만들어 주도록 합니다.

  • src/i18n.ts: i18n 설정파일 입니다.
  • public/locate/en/common.json: en일시에 보여줄 정적 데이터 파일입니다.
  • public/locate/ko/common.json: ko일시에 보여줄 정적 데이터 파일입니다.
public/locate/en/common.json
1
2
3
{
"hello": "hello"
}
public/locate/ko/common.json
1
2
3
{
"hello": "안녕하세요"
}
src/i18n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import ICU, { IcuInstance } from "i18next-icu";
import en from "i18next-icu/locale-data/en";
import ko from "i18next-icu/locale-data/ko";
import NextI18Next from "next-i18next";
import { useTranslation as originalUseTranslation } from "react-i18next";
import { NextComponentType, NextPageContext } from "next";

const use: IcuInstance[] = [];
const icu = new ICU({});
icu.addLocaleData(ko);
icu.addLocaleData(en);
use.push(icu);

const NextI18NextInstance = new NextI18Next({
browserLanguageDetection: false,
defaultLanguage: "en",
defaultNS: "common",
fallbackLng: "en",
keySeparator: "###",
localePath: "public/locales",
otherLanguages: ["ko"],
use
});

export const { appWithTranslation, withTranslation } = NextI18NextInstance;

export default NextI18NextInstance;

export const includeDefaultNamespaces = (namespaces: string[]) =>
["common"].concat(namespaces);

export const { Trans } = NextI18NextInstance;
export const useTranslation = originalUseTranslation;
export type I18nPage<P = {}> = NextComponentType<
NextPageContext,
{ namespacesRequired: string[] },
P & { namespacesRequired: string[] }
>;

적용하기

설정이 완료되었다면 다음으로 사이트에 적용하도록 하겠습니다.
모든 pages에서 i18n을 적용하기위해 pages폴더 내부에 _app.tsx를 생성하여 적용합니다.

pages/_app.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import App from "next/app";
import React from "react";
import { appWithTranslation } from "../src/i18n";

class ReactApp extends App<any> {
public render() {
const { Component, pageProps } = this.props;
return (
<>
<Component {...pageProps} />
</>
);
}
}

export default appWithTranslation(ReactApp);

다음으로 pages/index.tsx 파일에 적용해보도록 하겠습니다.

pages/index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React from "react";
import { I18nPage, useTranslation } from "../src/i18n";

const Index: I18nPage = () => {
const { t, i18n } = useTranslation();
return (
<div>
<h1>Index</h1>
<p>{t("hello")}</p>
<button
onClick={() =>
i18n.changeLanguage(i18n.language === "en" ? "ko" : "en")
}
>
Change Language
</button>
</div>
);
};

export default Index;

예시로 버튼을 클릭하면 hello의 언어가 바뀌는 것을 구현했습니다.

react-i18next에서 지원하는 훅스를 이용하면 간편하게 사용할 수 있습니다.
useTranslation의 반환값으로 t, 18n이 대표적입니다.

  • t: commonjs의 키에 해당하는 string을 입력하면 그것이 맞춰 value가 반환됩니다.
  • i18n: i18n 메소드로 언어 변경이나 현재 언어확인 등을 할수 있는 객체입니다.

최종 결과

Warning

1
You have not declared a namespacesRequired array on your page-level component: Index. This will cause all namespaces to be sent down to the client, possibly negatively impacting the performance of your app. For more info, see: https://github.com/isaachinman/next-i18next#4-declaring-namespace-dependencies

완성을 하고 보니 에디터 콘솔에서 다음과 같은 warning메시지가 나옵니다.
페이지 레벨의 컴포넌트에는 namespaces가 필수로 정의되야한다는 의미입니다.
이 경고를 수정해보도록 하겠습니다.

pages/index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
//...
import {
I18nPage,
useTranslation,
includeDefaultNamespaces
} from "../src/i18n";

//...

Index.getInitialProps = async () => ({
namespacesRequired: includeDefaultNamespaces(["Index"])
});

클린!

Share