본문으로 건너뛰기

커맨드라인

chki18n 명령은 번역 파일 폴더를 검사하고 잘못된 부분을 출력합니다. 오류 수준의 이슈를 찾으면 종료 코드 1로 끝나므로, CI 작업이나 pre-commit 훅에 그대로 연결할 수 있습니다.

세 패키지가 같은 명령을 제공합니다. 플래그도 출력도 같고, 명령을 경로에 올리는 방법만 다릅니다.

bash
# 설치 없이 실행합니다. CI에서는 보통 이 방식입니다.
npx chki18n ./locales --target en

# 설치하면 명령 이름은 `chki18n`입니다.
npm install chki18n
bash
# 한 번 설치하면 명령이 경로에 등록됩니다.
dart pub global activate chki18n

# 이미 의존성으로 추가한 프로젝트 안에서는 전역 설치 없이 실행합니다.
dart run chki18n ./locales --target en
bash
# 설치 없이 실행합니다. CI에서는 보통 이 방식입니다.
pipx run chki18n ./locales --target en

# 설치하면 명령 이름은 `chki18n`입니다.
pip install chki18n

이 페이지의 나머지는 명령을 chki18n으로 씁니다.

사용법

bash
chki18n [options] <targetDirectory>

디렉터리는 인자로 바로 넘기거나 --path로 지정할 수 있으며, 둘은 같은 의미입니다. 상대 경로는 현재 작업 디렉터리를 기준으로 해석됩니다.

bash
chki18n ./locales
bash
chki18n --path ./locales --target en

플래그

text
  --path <dir>                    The directory where the files to be scanned are located (required)
  --target <locale>               The language every other language is compared against (default: `en`)
  --format <format>               Layout of the translation files: `auto`, `single`, `folder` or `nested`
  --checks <codes>                Run only these comma separated check codes
  --ignore-checks <codes>         Run every check except these comma separated check codes
  --levels <code=level>           Report a check at another severity, e.g. `EMPTY_VALUE=error`
  --interpolation-prefix <str>    Opening delimiter of an interpolation key (default: `{`)
  --interpolation-suffix <str>    Closing delimiter of an interpolation key (default: `}`)
  --exclude <dirs>                Comma separated directory names or paths to skip while scanning
  --exclude-files <globs>         Comma separated file name patterns never read as translations
  --source <dir>                  Source files to read for key usages (enables `UNUSED_KEY` and `UNDEFINED_KEY`)
  --translate-functions <names>   Comma separated names a translation call goes by (default: `t`, `$t`, `translate`)
  --key-case <case>               Case every key segment has to use: `kebab`, `camel`, `snake`
  --max-key-depth <levels>        How many levels a key may be nested, e.g. `2` for `attr.folder`
  --length-ratio <times>          Report a value more than this many times longer or shorter than the target
  --reporter <name>               How to render the report: `pretty`, `list`, `json`, `markdown`, `github`
  --group-by <axis>               Group the reported issues by `locale`, `code`, `group`, `file`, `none`
  --output <file>                 Also write the report to this file, in the format its extension implies
  --width <columns>               Lay the report out to this many columns instead of measuring the terminal
  --no-color                      Do not colour the output
  --no-info                       Do not show info messages
  --no-warn                       Do not show warning messages
  --debug                         Show debug messages
  --help                          Show this message
  --version                       Show the installed version

모든 플래그는 같은 이름의 API 옵션이기도 합니다. --ignore-checksignoreChecksignoreChecksignore_checks입니다. 양쪽이 하나의 정의에서 파생되기 때문이며, 옵션에서 두 방식을 한 번에 설명합니다.

출력 읽기

text
  Path     ./locales
  Target   en
  Locales  en, ja, ko
  Layout   single, 1 group, 5 keys

 ko ─────────────────────────────────────────────────────────────────────── 2 errors · 1 warning

  ERROR  NO_KEY (1)
         The key exists in the target language but is missing here.
    attr.folder  en: "Folder"

  ERROR  NO_INTERPOLATION_KEY (1)
    greeting     en: "Hello {name}"
      The interpolation key `{name}` of the target language is missing from this value.

  WARN   DUPLICATE_VALUE (1)
    dup-b        en: "Beta"
      The key `dup-a` in the same locale already uses this value.

 Summary ───────────────────────────────────────────────────────────────────────────────────────

  Compared 5 keys across 3 locales in 1 group. (3ms)
  2 errors · 3 warnings

  By check
    NO_INTERPOLATION_KEY  1 error
    NO_KEY                1 error
    DUPLICATE_VALUE       3 warnings

  FAIL  2 errors must be fixed before this passes.

번역가가 한 번에 다루는 단위가 언어이므로 구획은 언어별로 나뉩니다. 구획 안에서는 검사별로 묶이고 심각한 것이 위로 옵니다. 검사 코드 뒤의 숫자는 발생 횟수이고, 그 아래 한 줄은 검사의 의미입니다. 각 줄에는 키와 함께 비교 대상인 기준 언어의 값이 나옵니다. 검사가 더 구체적인 설명을 만들었다면 다음 줄에 붙습니다. 비교 대상 파일 묶음이 둘 이상이면 키 뒤에 @로 그룹이 따라옵니다.

요약은 구획이 보여 주지 않는 축을 채웁니다. 구획을 언어별로 나눴다면 집계는 검사별로, 검사별로 나눴다면 집계는 언어별로 나옵니다.

출력 형식 고르기

--reporter가 리포트의 모양을 정합니다. 어떤 형식이든 같은 이슈를 같은 순서로 담으며, 그 주변의 글만 달라집니다.

리포터쓰임새
pretty터미널에서 읽기. 구획과 색상, 요약이 있습니다. 기본값입니다.
list이슈 한 건에 한 줄. grep, 에디터, CI 로그에 알맞습니다.
json결과 객체 전체. 다른 도구가 읽을 용도입니다.
markdown표 형태. PR 코멘트나 저장소에 두는 리포트에 알맞습니다.
github워크플로 명령. GitHub Actions가 번역 파일에 직접 주석을 답니다.
bash
chki18n ./locales --target en --reporter list
text
ko  error  NO_KEY                attr.folder  en: "Folder"
ko  error  NO_INTERPOLATION_KEY  greeting     en: "Hello {name}"  The interpolation key `{name}` of the target language is missing from this value.
ko  warn   DUPLICATE_VALUE       dup-b        en: "Beta"  The key `dup-a` in the same locale already uses this value.

Found 2 errors, 3 warnings. Compared 5 keys across 3 locales in 1 group. (3ms)

pretty가 아닌 형식은 배너도 진행 상황 줄도 없이 리포트만 출력합니다. 다른 프로그램으로 그대로 넘길 수 있습니다.

bash
chki18n ./locales --target en --reporter json > report.json

--debug는 표준 출력이 아니라 표준 오류로 나가므로, 넘긴 리포트에 섞이지 않습니다.

터미널 너비에 맞추기

리포트는 터미널 너비에 맞춰 배치됩니다. 측정할 터미널이 없으면 COLUMNS 값을 쓰며, CI 러너는 보통 이 값으로 로그 너비를 알려줍니다. 측정한 너비는 120칸까지만 씁니다. 그보다 벌어지면 라벨과 집계가 한 줄로 읽히지 않기 때문입니다.

--width를 주면 이 계산을 모두 무시하며, 상한도 없습니다.

bash
chki18n ./locales --width 72

설명은 잘리지 않고 다음 줄로 넘어가므로, 좁은 터미널에서도 문장이 사라지지 않습니다. --output으로 쓰는 파일은 터미널을 아예 보지 않고 고정 너비를 쓰며, --width를 주면 그 값을 씁니다.

이슈 묶는 기준

--group-by가 구획의 단위를 정합니다. 기본값은 locale입니다.

기준구획 하나가 뜻하는 것
locale언어. 번역가가 한자리에서 처리하는 단위입니다.
code검사. 관리자가 한 번에 처리하는 단위입니다.
group비교 대상이 되는 파일 묶음. 예를 들어 common.json.
file디스크의 번역 파일 하나.
none구획 없이 한 덩어리.
bash
chki18n ./locales --target en --group-by code

구획은 심각한 것부터 놓입니다. 오류가 있는 구획, 경고만 있는 구획, 나머지 순입니다. 구획 안에서도 같은 순서를 따르고, 그다음은 검사 순서, 그다음은 키 순서입니다. 파일이 바뀌지 않았다면 두 번 실행해도 같은 줄이 같은 자리에 오므로, 저장한 리포트끼리 비교할 수 있습니다.

list, json, markdown도 이 기준을 따릅니다. list는 구획이 없으니 순서에만 반영됩니다.

리포트를 파일로 저장하기

--output은 터미널에 출력하면서 같은 리포트를 파일로도 씁니다. 형식은 확장자가 정합니다. .json.md는 각자의 형식이 있고, 나머지는 평문으로 씁니다.

bash
chki18n ./locales --target en --output translation-report.md

없는 디렉터리는 만들어 줍니다. 파일에는 색상 코드가 들어가지 않으며, 터미널 너비가 아니라 고정 너비로 배치되므로 어디서 실행하든 같은 파일이 나옵니다.

둘 다 주면 --reporter가 우선합니다. 화면과 파일의 형식을 다르게 하거나, 확장자가 뜻하지 않는 형식을 강제할 때 쓰면 됩니다.

bash
chki18n ./locales --target en --output report.txt --reporter list

리포트를 쓰지 못하면 다른 오류와 마찬가지로 실행이 실패합니다. 만들어지지 않은 파일을 만들어졌다고 보고하지 않습니다.

종료 코드

코드의미
0오류 수준 이슈 없음. 경고는 출력됐을 수 있습니다.
1오류 수준 이슈가 하나 이상이거나, 디렉터리를 읽지 못했습니다.

경고만으로는 실행이 실패하지 않습니다. 프로젝트에서 특정 경고를 차단 요소로 취급한다면 --levels로 심각도를 올리세요.

bash
chki18n ./locales --target en --levels EMPTY_VALUE=error

CI에서

GitHub Actions 스텝은 한 줄이면 됩니다. 작업 전체와 Bitbucket Pipelines 쪽은 CI에 붙이기에 정리되어 있습니다.

yaml
- name: Check translations
  run: npx chki18n ./locales --target en
yaml
- uses: dart-lang/setup-dart@v1
- name: Check translations
  run: |
    dart pub global activate chki18n
    dart pub global run chki18n ./locales --target en
yaml
- uses: actions/setup-python@v6
- name: Check translations
  run: |
    pip install chki18n
    chki18n ./locales --target en

경고를 정리하는 동안 작업을 통과 상태로 유지하려면, 이미 해결한 검사만 지정하세요.

bash
chki18n ./locales --target en --checks NO_KEY,NO_INTERPOLATION_KEY

반대로, 시끄러운 검사 하나만 제외할 수도 있습니다.

bash
chki18n ./locales --target en --ignore-checks DUPLICATE_VALUE

--reporter github는 각 이슈를 워크플로 명령으로 바꿉니다. GitHub이 이를 읽어 로그 한 줄이 아니라 번역 파일 위에 주석으로 표시합니다.

bash
chki18n ./locales --target en --reporter github
text
::error file=locales/ko.json,title=chki18n NO_KEY::ko attr.folder The key exists in the target language but is missing here. (en: "Folder")
::warning file=locales/ko.json,title=chki18n EMPTY_VALUE::ko attr.open The key is defined but its value is an empty string. (en: "Open")

error는 error 주석, warn은 warning, info는 notice가 됩니다. 줄 번호는 붙이지 않고 파일만 가리킵니다. 검사가 파싱된 번역을 다루는 데다, 가장 흔한 이슈가 애초에 파일에 없는 키이기 때문입니다.

작업 요약에는 마크다운 리포트가 어울립니다.

bash
chki18n ./locales --target en --output "$GITHUB_STEP_SUMMARY" --reporter markdown

작업이 끝난 뒤에도 결과를 남기려면 파일로 쓰고 올리면 됩니다.

yaml
- name: Check translations
  run: chki18n ./locales --target en --output translation-report.md
- uses: actions/upload-artifact@v4
  if: always()
  with:
    name: translation-report
    path: translation-report.md

pre-commit 훅에서

bash
#!/bin/sh
chki18n ./locales --target en --no-info || exit 1

--no-info는 머리말 블록과 요약을 없애고 이슈만 남깁니다. 문제가 없을 때는 조용해야 하는 훅에 알맞습니다. --no-warn은 여기서 한 걸음 더 나아가 실행을 실패로 만드는 이슈만 남기며, 몇 건을 감췄는지는 리포트에 표시됩니다.

검사 결과가 비어 있을 때

--debug는 해석된 옵션, 감지된 파일 구조, 그리고 읽었지만 로케일에 속하지 않아 건너뛴 파일을 출력합니다.

bash
chki18n ./locales --debug

어떤 파일도 일치하지 않았다면 대개 파일 구조가 원인입니다. 파일 구조를 확인하고 --format으로 강제 지정해 보세요.

Released under the MIT License