README.md와 README.zh.md가 서로 멀어지는 것을 어떻게 막았는가
I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link, formatting, markdown, and any code blocks exactly as they are while translating the surrounding text into Korean.
드리프트 문제
Every project that ships a translated README follows the same lifecycle:
- Someone writes
README.mdin English. - A contributor opens a PR with
README.zh.md. Great. - Months later, English has new sections while the Chinese version still reflects the original.
- A second translator adds
README.es.md. Which version should they translate from? The currentREADME.mdor the staleREADME.zh.md?
After a while you end up with several READMEs that disagree on what the project actually is. It’s hard to tell at a glance which file is stale, reviewers don’t read all three, and translations rot because nothing forces them to stay in sync.
솔루션: NRG
I built a small Java tool—NRG (README Generator)—to keep translated READMEs in lockstep.
- Write one
README.src.md. - Run NRG and get back
README.md,README.zh.md,README.ja.md, and any other language variants you list.
The template lines fall into three categories:
| Category | Description |
|---|---|
| Shared | Appears in every output (badges, code blocks, file paths, anything language‑agnostic). No markup needed. |
| Language‑tagged | Appears only in the specified language’s output. |
| Inline per‑language | Useful for short strings like anchor names or button labels where a full line per language would be overkill. |
Example template snippet

This library is small but hard to use.
Эта библиотека маленькая, но сложная в использовании.
本库虽小,但难以使用。
${en:‘Table of contents’, ru:‘Содержание’, zh:‘目录’}
Running the generator:
```bash
nrg -f README.src.md
produces the language‑specific files, each stamped with a header comment indicating that the file is generated.
## CI 통합
NRG는 **check** 모드가 있는 GitHub Action(`nanolaba/nrg-action@v1`)을 제공합니다. 모든 PR에서 다음을 수행합니다.
1. README 파일들을 임시 디렉터리로 다시 생성합니다.
2. 커밋된 버전과 차이를 비교합니다.
일치하지 않으면 빌드가 통합 diff와 함께 실패합니다. 예시:
```diff
--- README.md (on disk)
+++ README.md (generated)
@@ -27,7 +27,7 @@
-## Quick start
+## Getting started
따라서 기여자는 README.zh.md를 직접 편집할 수 없으며, README.src.md를 업데이트하고 다시 생성하거나 CI가 PR을 거부하도록 해야 합니다.
같은 검사를 로컬에서도 실행할 수 있습니다:
nrg -f README.src.md --check
이는 pre‑commit 훅에 활용하기에 편리합니다.
위젯
템플릿 구문으로 직접 표현할 수 없는 모든 것은 위젯입니다. 제공되는 기본 위젯은 다음과 같습니다:
${widget:tableOfContents(ordered='true')} # auto‑builds a TOC
${widget:import(path='docs/intro.src.md')} # compose templates
${widget:exec(cmd='git rev-parse --short HEAD')} # embed shell output
${widget:fileTree(path='src/main/java', depth='2')} # generate a directory tree
${widget:math(expr='\\pi r^2')} # render LaTeX (SVG fallback)
추가 내장 위젯: alert, badge, if / endIf, date, todo.
맞춤 위젯은 NRGWidget 인터페이스를 구현하는 클래스를 만들어 구현합니다—예를 들어 “기능 매트릭스” 위젯과 같이 프로젝트별 패턴에 유용합니다.
Maven 플러그인
Java 프로젝트의 경우, NRG를 컴파일 단계에서 자동으로 실행할 수 있습니다:
<plugin>
<groupId>com.nanolaba</groupId>
<artifactId>nrg-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<sourceFile>README.src.md</sourceFile>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>create-files</goal>
</goals>
</execution>
</executions>
</plugin>
GitHub Action (언어‑agnostic)
액션이 Java 자체를 프로비저닝하므로, 저장소에 Java 툴체인이 필요하지 않습니다:
- uses: nanolaba/nrg-action@v1
with:
file: README.src.md
mode: check
Python, JavaScript, Rust, 혹은 다른 어떤 언어 생태계에서도 작동합니다.
- Java 8 최소 – 바이너리는 이식 가능합니다. JDK 설치가 싫다면 GitHub Action이 터치 없이 사용할 수 있는 옵션입니다.
- 번역 도구가 아님 – NRG는 구조를 동기화합니다; 실제 본문 번역은 인간(또는 LLM)의 작업입니다.
- Markdown AST 없음 – 치환과 위젯은 원시 텍스트에서 작동합니다. 이는 99 %의 경우에 동작하지만, 영리한 작성자가 NRG가 잡지 못하는 깨진 Markdown을 만들 수 있습니다. 더 엄격한 검사를 위해 별도의
validate모드를 사용하세요. - 초기 단계 – 현재 v1.2이며, 소수의 오픈‑소스 레포에서 사용됩니다. 위젯 API는 아직 발전 중일 수 있습니다.
피드백
프로젝트가 아직 방향을 바꿀 수 있을 만큼 작을 때 솔직한 피드백을 받고 싶습니다.
- 현재 설정(수동 동기화, 커스텀 스크립트, 아무것도 하지 않음)보다 이것을 어떻게 채택하시겠습니까?
- 무엇이 사용하지 않게 만들까요?
레포지토리, 전체 문서 및 GIF 데모는 다음에서 확인할 수 있습니다:
읽어 주셔서 감사합니다 – 댓글로 질문에 답변해 드리겠습니다.