React (webpack) + electron 환경 다국어 적용기 (i18next)
들어가며
최근에 회사에서 다국어를 처음 적용해 봤다. 우리 프로젝트는
특수하게도 react로 만든 프로젝트를 webpack으로 번들링하여 electron을 실행해 번들링된 파일을 watch하는 방식이다.
그래서 이 글에서는 react에서사용하는 language를 browser에서 detect하는 라이브러리 (i18next-browser-languagedetector)를 사용할 수 없어 Electron에서 language를 detect하고 i18next에 적용하는 과정을 정리하려고한다.
react-i18next
먼저 우리는 react 환경이기 때문에 아래와 같이 i18next를 설치한다.
npm i --save-dev react-i18next
그리고 src 폴더 내에 locales 폴더를 만들고 아래와 같이 구성한다.
- kr - 한국어로 된 가이드 파일을 넣어놓는다.
- en - 영어로 된 가이드 파일을 넣어놓는다.
src/locales/kr/common.ts
1
2
3
4
export default {
create: "생성",
delete: "삭제"
};
src/locales/en/common.ts
1
2
3
4
export default {
create: "Create",
delete: "Delete"
};
나는 파일 명을 일반적으로 common을 기본적으로 쓰이는 값으로 작성한 뒤에 페이지별로 구분하는 편이다. (개취에 맞게 쓰세요)
위와 같이 언어에 맞게 쓸 단어들을 세팅해주면 된다. (json도 상관없음)
여기서 주의할 점은 모든 언어에 key값과 파일명은 동일해야 한다 object key값과 파일명으로 매핑하기 때문이다.
그리고 이제 locales폴더에 있는 index.ts 파일에 i18next 설정을 해줄거다.
src/locales/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import * as localeEn from "./en";
import * as localeKr from "./kr";
export const kr = { ...localeKr };
export const en = { ...localeEn };
i18n.use(initReactI18next).init({
resources: { en, kr },
fallbackLng: ["en", " kr"],
interpolation: { escapeValue: false }
});
export default i18n;
이걸로 사실 다국어 준비는 끝이다. 아래와 같이 바로 모듈을 가져와서 사용해도 되고
1
2
3
{
i18n.t("common:created");
}
아래와 같이 라이브러리에서 제공하는 Hook을 사용해도 된다.
common같은 파일명을 구분하지 않으면 참고하는 resource에서 단어를 알아서 찾아서 매핑한다.
1
2
3
4
5
6
7
8
import { useTranslation } from "react-i18next";
const { t } = useTranslation();
{
t("common:created");
// 이렇게도 사용가능하다.
t("created");
}
electron Language Detector
자 이제 서론에서 얘기했던 electron에서 detector를 설정할 때다.
우리 환경은 react와 Electron이 ipc통신을 사용하고 있어서 아래와 같이 컨트롤러를 만들었다.
electron/src/controllers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { app, BrowserWindow, ipcMain } from "electron";
export default (window: BrowserWindow) => {
ipcMain.handle("getLocale", async (event, args) => {
try {
// 현재 사용자 컴퓨터의 locale을 가져온다.
const userLocale = app.getLocale();
return userLocale;
} catch (error) {
console.log(error);
}
return true;
});
};
이렇게 electron에서 ipcHandle을 만들어 준 뒤 react에서 이 handle을 호출하는 Detector 모듈을 만들어 주면 된다.
languageDetector.ts
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
import { electron } from "~/utils/electron";
import { ModuleType } from "i18next";
// i18next에서 module에서 사용할 수 있는 interface 정의
interface LanguageDetector {
init: () => void;
async: boolean;
type: ModuleType;
detect: () => string;
cacheUserLanguage: () => void;
}
const languageDetector: LanguageDetector = {
type: "languageDetector",
async: true,
init: () => {},
// i18next 내부에서 languageDetector로 정의된 모듈의 detect함수를 실행시켜 반환값을 현재 언어로 설정한다.
detect: () =>
electron.ipcRenderer.invoke("getLocale", undefined).then((result: any) => {
return result;
}),
// user의 language를 cache할 조건이 있다면 여기에 정의
cacheUserLanguage: () => {}
};
export default languageDetector;
위와 같이 i18next에서 사용할 모듈이 만들어졌으면 이제 아래처럼 i18next에 detector를 포함해주면 끝이다!
src/locales/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import * as localeEn from "./en";
import * as localeKr from "./kr";
import languageDetector from "~/utils/languageDetector";
export const kr = { ...localeKr };
export const en = { ...localeEn };
i18n
.use(languageDetector)
.use(initReactI18next)
.init({
resources: { en },
fallbackLng: ["en"],
interpolation: { escapeValue: false }
});
export default i18n;
마치며
이상으로 i18next 기본 설정과 electron + React 환경에서 다국어를 설정하는 detector를 만들어 적용해봤다.
보통은 web 환경에서 적용을 하겠지만, 나처럼 브라우저 환경이아닌 pc의 Locale을 가지고 다국어를 적용하려는 분들에게 도움이 되었으면 좋겠다.