Django 앱을 두 개 이상의 언어로 배포해 본 적이 있다면, 그 과정을 잘 알고 있을 것입니다. 문자열을 gettext()로 감싸고, makemessages를 실행하고, 수백 개의 항목이 있는 .po 파일을 열어 한 줄씩 번역합니다. 두 개 언어와 오십 개 문자열이라면 감당할 만합니다. 여섯 개 언어와 오백 개 문자열이라면, 다시는 돌아오지 않을 하루 종일의 작업입니다.
이 가이드는 Django의 국제화(i18n) 파이프라인을 처음부터 끝까지 다루고, 어디서 문제가 발생하는지 설명하며, AI 기반 번역으로 가장 고통스러운 부분을 자동화하는 방법을 보여줍니다.
표준 Django i18n 워크플로우
Django의 내장 i18n 시스템은 잘 설계되어 있습니다. 핵심 루프는 다음과 같습니다:
1단계: 번역할 문자열을 표시합니다 Python 코드와 템플릿에서:
from django.utils.translation import gettext as _
def dashboard(request):
welcome = _("Welcome back, %(name)s!") % {"name": request.user.first_name}
return render(request, "dashboard.html", {"welcome": welcome})
{% load i18n %}
<h1>{% trans "Account Settings" %}</h1>
<p>{% blocktrans %}You have {{ count }} unread messages.{% endblocktrans %}</p>
2단계: 문자열을 추출합니다 .po 파일로:
python manage.py makemessages -l de -l fr -l nl
이것은 전체 코드베이스를 스캔하고 언어별로 하나의 .po 파일을 생성하며, 번역 가능한 모든 문자열을 포함합니다:
#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""
#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""
3단계: 비어 있는 모든 msgstr을 번역합니다 수동으로.
4단계: 완성된 .po 파일을 바이너리 .mo 파일로 컴파일합니다:
python manage.py compilemessages
1단계, 2단계, 4단계는 빠릅니다. 3단계에서 프로세스가 무너집니다.
수동 번역이 확장되지 않는 이유
일반적인 Django 애플리케이션에는 200개에서 2,000개 사이의 번역 가능한 문자열이 있습니다. 이것을 대상 언어 수로 곱하면 상당한 시간 투자가 필요합니다.
이것은 이론적인 불만이 아닙니다. 잘 알려진 Django Forum 스레드에서 한 개발자가 .po 파일당 수동 번역에 8시간 이상을 소비했다고 보고했습니다. Django 코어 기여자는 단일 릴리스에 커뮤니티가 제출한 번역을 통합하는 데 10시간 이상을 소비했다고 설명했으며, 대부분 검토, 서식 수정, 깨진 플레이스홀더 수정에 사용했습니다.
문제는 시간이 지남에 따라 복합적으로 증가합니다:
- 플레이스홀더가 깨집니다.
Welcome, %(name)s!같은 문자열을 Google Translate에 복사하면, 종종Willkommen, %(Name)s!또는Bienvenue, %(nom)s!가 돌아옵니다. 그 미묘한 손상이 런타임 크래시를 유발합니다. - 일관성이 무너집니다. 용어집 없이 "dashboard"가 한 파일에서는 "Instrumententafel"로, 다른 파일에서는 "Dashboard"로 번역됩니다. 석 달 후에는 어느 것이 의도적이었는지 아무도 기억하지 못합니다.
- 스프린트가 문자열을 추가합니다. 모든 기능 브랜치가 새로운 번역 가능한 문자열을 추가합니다. 지난 분기에 전체 번역 작업 비용을 지불했더라도, 이제
.po파일 여기저기에 40개의 미번역 항목이 흩어져 있습니다. - AI 어시스턴트는 한 번만 도움이 됩니다.
.po파일을 ChatGPT나 Claude에 붙여넣으면 괜찮은 결과를 얻을 수 있습니다. 하지만 다음 스프린트에서 15개의 새 문자열이 나타나면, 처음부터 프롬프트를 작성하고, 전체 파일을 다시 번역하며, 이미 있는 것과 일관성을 유지하기를 바라게 됩니다.
근본 원인은 번역이 점진적이고 반복 가능한 프로세스가 아닌 일회성 이벤트로 취급된다는 것입니다.
AI로 번역 자동화하기
아이디어는 간단합니다: 사람이 각 .po 파일을 열어 msgstr 값을 채우는 대신, 도구가 파일을 읽고, 미번역 문자열을 AI 모델이나 번역 API로 보내고, 결과를 다시 쓰고, 나머지(주석, 파일 구조, 플레이스홀더, 복수형)를 모두 보존합니다.
TranslateBot Django는 정확히 이 작업을 수행하는 오픈 소스 패키지입니다. Django의 관리 명령 시스템에 플러그인되므로 이미 갖고 있는 워크플로우에 맞습니다.
단계별 설정
1. 패키지 설치
pip install translatebot-django
또는 uv를 사용한다면 (권장):
uv add --dev translatebot-django
개발 의존성으로 설치하는 것은 의도적입니다. TranslateBot은 번역을 생성할 때만 필요하며, 프로덕션 런타임에서는 필요하지 않습니다.
2. INSTALLED_APPS에 추가
# settings.py
INSTALLED_APPS = [
# ...
"translatebot_django",
]
3. AI 제공자 설정
# settings.py
import os
TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"
TranslateBot은 내부적으로 LiteLLM을 사용하므로, 문자열 하나만 변경하면 100개 이상의 모델 중 어느 것이든 교체할 수 있습니다:
| 제공자 | TRANSLATEBOT_MODEL 값 |
|---|---|
| OpenAI | gpt-4o-mini, gpt-4o |
| Anthropic | claude-sonnet-4-5-20250929 |
gemini/gemini-2.5-flash |
|
| Azure OpenAI | azure/gpt-4o-mini |
| DeepL | 대신 TRANSLATEBOT_PROVIDER = "deepl" 사용 |
DeepL의 경우 추가 패키지를 설치하세요: pip install translatebot-django[deepl]. DeepL의 무료 티어는 월 500,000자를 무료로 제공하며, 대부분의 소규모에서 중규모 프로젝트에 충분합니다.
4. 언어 정의
# settings.py
LANGUAGES = [
("en", "English"),
("de", "German"),
("fr", "French"),
("nl", "Dutch"),
("ja", "Japanese"),
]
5. 번역 실행
python manage.py translate
이것으로 끝입니다. TranslateBot은 프로젝트에서 .po 파일을 스캔하고, 미번역 항목을 식별하고, 최적화된 배치로 설정된 AI 모델에 보내고, 결과를 다시 씁니다. 기존 번역은 건드리지 않습니다.
단일 언어를 번역하려면:
python manage.py translate --target-lang nl
출력은 다음과 같습니다:
Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings
6. 평소대로 컴파일
python manage.py compilemessages
전체 워크플로우는 이제:
python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages
세 개의 명령. 모든 언어. 모든 스프린트.
설계부터 점진적
반복 가능한 워크플로우를 위한 가장 중요한 기능은 점진적 번역입니다. TranslateBot은 msgstr이 비어 있는 항목만 번역합니다. 500개의 문자열이 있고 이번 스프린트에서 15개가 새로운 경우, 그 15개만 API로 전송됩니다.
이것은 실용적인 이유로 중요합니다:
- 비용. 전체 파일이 아닌 새 문자열에 대해서만 비용을 지불합니다.
- 속도. 15개 문자열 번역은 분이 아닌 초 단위입니다.
- 안정성. 이미 검토하고 승인한 번역은 절대 덮어쓰이지 않습니다 (명시적으로
--overwrite를 전달하지 않는 한).
플레이스홀더 안전성
Django는 여러 플레이스홀더 형식을 사용합니다: %(name)s, %s, %d, {0}, {name}, 그리고 <strong> 또는 <a href="...">와 같은 인라인 HTML 태그. 이 중 하나라도 번역에서 손상되면 런타임 오류나 깨진 마크업이 발생합니다.
TranslateBot은 AI 모델에게 모든 플레이스홀더 형식을 보존하도록 지시하고 출력을 검증합니다. 다음과 같은 문자열:
Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.
네덜란드어로 다음과 같이 번역됩니다:
Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.
모든 플레이스홀더가 온전히 유지됩니다.
TRANSLATING.md로 품질 제어하기
AI 모델은 맥락을 이해할 때 더 잘 번역합니다. TranslateBot은 프로젝트 루트에서 TRANSLATING.md 파일을 찾고 모든 번역 요청에 그 내용을 포함합니다.
# Translation Context
## About This Project
A B2B project management tool for construction companies.
## Terminology
- "project" means a construction project, not a software project
- "plan" means a building plan/blueprint, not a subscription plan
- Keep "Gantt chart" as-is in all languages
## Tone
- German: use formal "Sie" form (business context)
- French: use formal "vous" form
- Dutch: use informal "je" form
## Do Not Translate
- Brand name: "BuildFlow"
- Feature names: "SmartSchedule", "CostTracker"
이 파일은 코드와 함께 버전 관리되므로 팀 전체가 동일한 번역 맥락을 공유합니다. 전문 용어가 있는 앱에 대해 앱별 TRANSLATING.md 파일을 배치할 수도 있습니다. 의료 기록 모듈과 청구 모듈은 각각 자체 용어집을 가질 수 있습니다.
커밋 전 미리보기
--dry-run 플래그는 API 호출이나 파일 수정 없이 정확히 무엇이 번역될지 보여줍니다:
python manage.py translate --target-lang fr --dry-run
Found 15 untranslated entries
Dry run mode: skipping LLM translation
Would translate 'Welcome to our site'
Would translate 'Hello, %(name)s!'
...
Dry run complete: 15 entries would be translated
이것은 대규모 번역 실행 전이나 API 비용에 대해 알기 전에 명령이 무엇을 하는지 이해하고 싶은 새 팀원을 온보딩할 때 유용합니다.
CI/CD 통합
강제 없이는 번역이 오래되는 것은 불가피합니다. TranslateBot에는 CI 파이프라인용으로 설계된 check_translations 관리 명령이 포함되어 있습니다:
# .github/workflows/ci.yml
jobs:
translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- run: uv python install
- run: uv sync --frozen
- name: Install gettext
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends gettext
- name: Check translations
run: uv run python manage.py check_translations --makemessages
--makemessages 플래그는 먼저 makemessages -a --no-obsolete를 실행하여 확인 전에 .po 파일이 현재 소스 코드를 반영하도록 합니다. 미번역이거나 퍼지인 항목이 있으면 명령이 코드 1로 종료되고 빌드가 실패합니다:
locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed
일반적인 개발자 워크플로우는 다음과 같이 됩니다:
- 기능 브랜치에서 새 번역 가능 문자열을 추가합니다.
- 해당 문자열이 미번역이므로 CI가 실패합니다.
- 로컬에서
python manage.py translate를 실행합니다. - 업데이트된
.po파일을 커밋합니다. - CI가 통과합니다.
번역이 조용히 동기화에서 벗어나는 일은 없습니다.
데이터베이스 콘텐츠 번역
애플리케이션이 데이터베이스에 번역 가능한 콘텐츠를 저장하는 경우 (제품 이름, 블로그 포스트 제목, 카테고리 레이블), TranslateBot은 django-modeltranslation과도 통합됩니다:
pip install translatebot-django[modeltranslation]
# Translate all registered model fields
python manage.py translate --target-lang de --models
# Translate specific models only
python manage.py translate --target-lang de --models Product Category
동일한 점진적 로직이 적용됩니다: 대상 언어 값이 비어 있는 필드만 번역됩니다.
비용 비교
가장 흔한 질문 중 하나는 AI 번역이 대안에 비해 비용 효율적인지 여부입니다. 5개 언어에 500개의 번역 가능한 문자열이 있는 프로젝트에 대한 대략적인 비교입니다:
| 접근 방식 | 예상 비용 | 시간 투자 |
|---|---|---|
| 수동 (개발자 시간) | 직접 비용 $0, 20-40시간 이상 | 매우 높음 |
| 전문 번역 서비스 | $500-2,000+ | 낮음 (하지만 느린 처리) |
| SaaS 현지화 플랫폼 | $50-200/월 | 중간 |
| TranslateBot + GPT-4o-mini | ~$0.05 (일회성) | 분 |
| TranslateBot + DeepL Free | $0 (월 최대 500k자) | 분 |
| TranslateBot + Claude/GPT-4o | ~$0.30 (일회성) | 분 |
숫자는 문자열 수와 대상 언어에 따라 변하지만, 규모 차이는 일관됩니다. 지속적인 유지보수 (매 스프린트마다 추가되는 20-50개의 새 문자열 번역)의 경우, AI 비용은 본질적으로 0입니다.
모범 사례
--dry-run으로 시작하세요. 첫 번째 실제 번역 실행 전에 무엇이 일어날지 미리 확인하세요. 이것은 자신감을 키우고 설정 문제를 조기에 잡습니다.
번역 전에 .po 파일을 커밋하세요. 문제가 발생하면 git checkout으로 즉시 깨끗한 상태로 돌아갈 수 있습니다.
첫날부터 TRANSLATING.md를 작성하세요. 프로젝트 설명과 몇 가지 용어 규칙만 있는 간단한 파일이라도 번역 품질을 측정 가능하게 향상시킵니다.
CI에 check_translations를 추가하세요. 이 단일 단계가 가장 흔한 i18n 실패 모드를 방지합니다: 번역으로 표시되었지만 실제로 번역되지 않은 문자열.
비용 효율성을 위해 gpt-4o-mini 또는 DeepL을 사용하세요. GPT-4o나 Claude 같은 프리미엄 모델은 마케팅 카피, 법률 텍스트, 도메인별 용어처럼 정밀도가 중요한 프로젝트에 남겨두세요.
중요한 문자열을 검토하세요. AI 번역은 대부분의 UI 텍스트에 충분히 좋지만, 법적 구속력이 있거나 안전에 중요하거나 고위험 맥락에서 고객을 대면하는 내용은 원어민에게 검토를 받으세요.
시간에서 초로
Django의 i18n 프레임워크는 번역을 추출하고 컴파일하는 데 뛰어납니다. 격차는 항상 번역 단계 자체에 있었습니다 - 여러 언어에 걸쳐 수백 개의 msgstr 값을 채우는 지루하고 오류가 발생하기 쉬운 작업.
TranslateBot이 그 격차를 메웁니다. 설치하고, AI 제공자를 지정하고, 명령 하나를 실행하세요. 새 문자열이 번역됩니다. 기존 문자열은 그대로 유지됩니다. 플레이스홀더는 온전합니다. CI가 놓친 것을 잡아냅니다.
.po 파일이 귀찮은 일에서 빌드의 또 다른 부분으로 바뀝니다.
pip install translatebot-django
translatebot.dev에서 시작하세요.