-
[Next] i18n 자동화 프로세스 도입 - (1) : i18next-scanner를 통해 코드에서 key 값 추출하기Next.js 2022. 11. 27. 15:03
1. i18n 자동화 프로세스 도입 배경
서비스에 유저에 해당하는 국가의 언어로 세팅하거나, 그 국가에 맞는 sw를 개발하는 과정을 i18n이라고 칭한다.
서비스에서 I18n을 성공적으로 이끌기 위한 가장 큰 요소는 번역이라고 할 수 있다.
이때, 번역을 서비스에 입히기 위해서는 아래와 같은 불편한 절차가 진행될 것이다.
1) 번역 담당자는 서비스에 번역이 필요한 언어를 선정하고, 서비스에서 번역이 필요한 부분을 정리하여 번역가들에게 번역을 넘겨야 한다.
2) 그 이후, 전달 받은 번역을 개발자에게 전달하여 서비스에 적용하는 작업을 해야 한다.
이 과정에서 아래의 단점이 있다.
첫번째로, 번역가에게 필요한 부분을 넘기는 과정에서 필요한 부분을 정리하고, 메일 등으로 전달해야 하는 번거로운 의사소통 작업이 발생한다.
두번째로, 개발자는 번역 파일을 전달 받은 후, 수작업으로 번역본을 특정 저장소에 저장해야 하는 번거로움이 발생한다.
세번째로, 각 페이지(모듈) 별 번역본이 정리되지 않은 채로 받을 경우, 그대로 저장소에 적용이 된다면 서비스 페이지에 필요하지 않은 번역도 추가 요청될 수 있다.
즉, 번역을 적용하는 과정에서 자동화하는 프로세스가 없다면, 위와 같은 불필요한 의사소통, 번거로움, 리소스 낭비 등의 단점이 생길 수 있다.2. i18n 자동화 프로세스 절차 소개
이를 해결하기 위해, 자동화 프로세스는 간단하게 정리하면 다음과 같다.
개발자는 구글 엑셀시트에 번역해야 하는 부분에 대해 코드를 스캔하여 자동으로 올린다. 그 이후 번역가는 번역이 필요한 부분에 번역을 옮긴다. 번역가의 작업이 완료되면, 개발자는 key에 해당하는 값을 다운받아, 코드에 적용하여 서비스에서는 번역이 적용된 값이 나오게 한다.
1) 구글 스프레드 시트에 번역이 필요한 key 값을 코드를 스캔한다.
2) 구글 스프레드 시트에 key 값을 업로드한다.
3) 구글 스프레드 시트에 번역가는 번역을 기입한다.
4) 지금까지 완료된 key값과 번역값에 대해 구글 스프레드를 next.js에서 I18n 번역 값이 필요한 위치에 다운로드 한다. 이때, next는 I18n을 지원하므로, public/locales 폴더 아래에 다운로드 하면 된다.
3. 필요한 라이브러리
npm install i18next // 작성 당시 버전 19.6.3 npm install -D i18next-scanner // 작성 당시 버전 2.11.0 npm install -D google-spreadsheet
4. i18next-scanner 사용법
기존에는 번역 data를 선정하여 key값을 부여한 후 번역가에게 번역을 요청하였다.
사실상 key값은 개발자들이 번역값에 대해 구분하기 위해 정하는 임의의 값임으로, 개발자가 구분한 key값들을 얻고자 한다.
이때, code 상에서 매번 key 값을 엑셀에 올리는 일은 번거로운 시간 낭비가 될 수 있다.
그래서 I18next-scanner 라이브러리를 사용하여, key 값을 자동으로 추출하고자 한다.
i18next-scanner란, 특정 규칙을 갖는 코드를 스캔하여 각 언어에 맞게 json 파일을 생성해준다.
1) install
일단, i18next-scanner를 install 한다.npm install --save-dev i18next-scanner
2) 루트 위치에 i18next-scanner.config 파일을 생성
i18next-scanner 를 사용할 셋팅 정보를 위해 root 위치에 i18next-scanner.config 파일을 만들어야한다.
이때 주의해야 할 점이 있다. 코드를 스캔할 대, 특정 규칙이 있는 코드만 추출해야 한다.
그러므로, 통상 I18next를 사용할 때 쓰는 규칙인'i18next.t' , 'i18n.t', '$i18n.t', 't' 등만 허용하도록 해야, 무분별한 코드 추출을 방지할 수 있다.
그리고, scan한 코드를 저장할 위치는
public/locales 아래에 저장한다.왜냐하면, next.js에서 제공하는 i18n을 이용하기 위해서 지정된 위치가 바로 저기이기 때문이다.
또한, 하나의 엑셀 스프레드 시트에 번역을 저장을 하면, 관리하기가 어려워진다. 그래서 여러 개의 시트에서 작업을 할 수 있도록 하고자 하는데, 이때 여러 개로 나누는 기준은 서비스마다 다를 수 있다. 여기서는 여러 개로 나눈 기준이 메인 주제가 아니므로 기본 default 값인 ‘common’, ‘example’, ‘ecommerce’ 3가지로 나누겠다. 이렇게 3가지로 나누게 된다면(실제로는 그 이상으로 나누게 될 것이다.), ‘common’, ‘example’, ‘ecommerce’별로 나눠진 3종류의 data 전부 가져올 것 없이, 한 번에 수많은 양의 데이터를 가져오는 게 아니라 각 필요한 namespace 별 시트만 가져오게 된다!
/* eslint-disable @typescript-eslint/no-var-requires */ const path = require('path'); var fs = require('fs'); var chalk = require('chalk'); const COMMON_EXTENSIONS = '/**/*.{js,jsx,ts,tsx,vue,html}'; const DEFAULT_NS = 'common'; module.exports = { input: [`./pages${COMMON_EXTENSIONS}`, `./components${COMMON_EXTENSIONS}`, `./stories${COMMON_EXTENSIONS}`], options: { defaultLng: 'en', lngs: ['ko', 'en', 'ja', 'zh'], ns: ['common', 'ecommerce', 'example'], defaultNs: 'common', func: { list: ['i18next.t', 'i18n.t', '$i18n.t', 't'], extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue', '.html'], }, resource: { loadPath: path.join(__dirname, 'public/locales/{{lng}}/{{ns}}.json'), savePath: path.join(__dirname, 'public/locales/{{lng}}/{{ns}}.json'), }, defaultValue(lng, ns, key) { const keyAsDefaultValue = ['ko-KR']; if (keyAsDefaultValue.includes(lng)) { const separator = '~~'; const value = key.includes(separator) ? key.split(separator)[1] : key; return value; } return ''; }, keySeparator: false, nsSeparator: false, prefix: '%{', suffix: '}', }, transform: function customTransform(file, enc, done) { ('use strict'); const parser = this.parser; const content = fs.readFileSync(file.path, enc); let ns; const match = content.match(/useTranslation\(.+\)/); if (match) ns = match[0].split(/(\'|\")/)[2]; let count = 0; parser.parseFuncFromString(content, { list: ['t'] }, function (key, options) { parser.set( key, Object.assign({}, options, { ns: ns ? ns : DEFAULT_NS, nsSeparator: ':', keySeparator: '.', }) ); ++count; }); if (count > 0) { console.log(`i18next-scanner: count=${chalk.cyan(count)}, file=${chalk.yellow(JSON.stringify(file.relative))}`); } done(); }, };
3) 코드에 키값 추가
위 사진 처럼 코드에 번역값에 대한 키값을 추가한다.
또한 코드를 자동으로 추출이 행해진다면, 각 key값들에 대해 알맞은 namespace에 맞게 저장이 되어야한다.
이렇게 처리를 하기 위해, 번역값을 가져오는 코드인 useTranslation에 해당하는 namespace를 기입하고, namespace를
구분할 수 있는 코드도 추가적으로 작업하였다.
4) package.json에 명령어 추가"scan:i18n": "i18next-scanner --config i18next-scanner.config.js",
npm run scan:i18n을 터미널에 실행하면,public/locales 아래에 언어별 네임스페이스에 맞는 json 파일들이 생성이 완료된다.
참고자료:
https://meetup.toast.com/posts/295
'Next.js' 카테고리의 다른 글
[Next.js] next.js 에서 meta tag 손쉽게 적용하기 (feat. next-seo) (0) 2023.03.16 [Next] i18n 자동화 프로세스 도입 - (3) : key upload, download (0) 2022.12.11 [Next] production 배포 환경에서, console log 숨기기 (0) 2022.12.04 [Next] i18n 사용법 with next-i18next (0) 2022.11.13 [NEXT] HOC를 이용하여 next.js router guard 만들기 (0) 2022.09.04