Nếu bạn từng phát hành một ứng dụng Django bằng nhiều ngôn ngữ, bạn biết quy trình này. Bạn bọc các chuỗi trong gettext(), chạy makemessages, mở file .po với hàng trăm mục, và bắt đầu dịch từng dòng. Với hai ngôn ngữ và năm mươi chuỗi, điều đó có thể chấp nhận được. Với sáu ngôn ngữ và năm trăm chuỗi, đó là cả một ngày làm việc mà bạn sẽ không bao giờ lấy lại được.
Hướng dẫn này bao gồm toàn bộ quy trình quốc tế hóa (i18n) của Django từ đầu đến cuối, giải thích nơi nó gặp vấn đề, và chỉ ra cách tự động hóa phần khó khăn nhất bằng dịch thuật hỗ trợ AI.
Quy Trình Django i18n Tiêu Chuẩn
Hệ thống i18n tích hợp của Django được thiết kế tốt. Vòng lặp chính trông như thế này:
Bước 1: Đánh dấu các chuỗi cần dịch trong mã Python và template:
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>
Bước 2: Trích xuất các chuỗi vào file .po:
python manage.py makemessages -l de -l fr -l nl
Lệnh này quét toàn bộ codebase và tạo một file .po cho mỗi ngôn ngữ, chứa mọi chuỗi có thể dịch:
#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""
#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""
Bước 3: Dịch từng msgstr trống bằng tay.
Bước 4: Biên dịch các file .po hoàn chỉnh thành file nhị phân .mo:
python manage.py compilemessages
Bước 1, 2 và 4 nhanh chóng. Bước 3 là nơi quy trình sụp đổ.
Tại Sao Dịch Thủ Công Không Mở Rộng Được
Một ứng dụng Django điển hình có khoảng 200 đến 2.000 chuỗi có thể dịch. Nhân với số ngôn ngữ đích, và bạn đang đối mặt với một cam kết thời gian nghiêm trọng.
Đây không phải là phàn nàn lý thuyết. Trong một chủ đề nổi tiếng trên Django Forum, một nhà phát triển báo cáo đã dành hơn 8 giờ cho mỗi file .po để dịch thủ công. Một contributor cốt lõi của Django mô tả đã dành hơn 10 giờ để tích hợp các bản dịch do cộng đồng gửi vào một bản phát hành duy nhất, chủ yếu là review, sửa định dạng và khắc phục placeholder bị hỏng.
Các vấn đề tích lũy theo thời gian:
- Placeholder bị hỏng. Sao chép chuỗi như
Welcome, %(name)s!vào Google Translate, và bạn thường nhận lạiWillkommen, %(Name)s!hoặcBienvenue, %(nom)s!. Sự hỏng tinh vi này gây crash khi chạy. - Tính nhất quán trôi dạt. Không có bảng thuật ngữ, "dashboard" được dịch là "Instrumententafel" trong một file và "Dashboard" trong file khác. Ba tháng sau, không ai nhớ cái nào là có chủ đích.
- Sprint thêm chuỗi mới. Mỗi nhánh tính năng thêm chuỗi mới có thể dịch. Ngay cả khi bạn đã trả tiền cho bản dịch đầy đủ quý trước, giờ bạn có 40 mục chưa dịch rải rác trong các file
.po. - Trợ lý AI giúp một lần. Bạn có thể dán file
.povào ChatGPT hoặc Claude và nhận kết quả khá tốt. Nhưng sprint tiếp theo, khi 15 chuỗi mới xuất hiện, bạn phải viết prompt từ đầu, dịch lại toàn bộ file, và hy vọng nó nhất quán với những gì đã có.
Nguyên nhân gốc rễ là dịch thuật được coi như sự kiện một lần thay vì quy trình tăng dần, có thể lặp lại.
Tự Động Hóa Dịch Thuật Với AI
Ý tưởng rất đơn giản: thay vì con người mở từng file .po và điền giá trị msgstr, một công cụ đọc file, gửi các chuỗi chưa dịch đến mô hình AI hoặc API dịch thuật, ghi kết quả trở lại, và bảo toàn mọi thứ khác (comment, cấu trúc file, placeholder, dạng số nhiều).
TranslateBot Django là gói mã nguồn mở làm chính xác điều này. Nó tích hợp vào hệ thống management command của Django, nên phù hợp với quy trình bạn đã có.
Thiết Lập Từng Bước
1. Cài Đặt Gói
pip install translatebot-django
Hoặc, nếu bạn dùng uv (khuyến nghị):
uv add --dev translatebot-django
Cài đặt như dev dependency là có chủ đích. Bạn chỉ cần TranslateBot khi tạo bản dịch, không phải lúc chạy trên production.
2. Thêm vào INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
# ...
"translatebot_django",
]
3. Cấu Hình Nhà Cung Cấp AI
# settings.py
import os
TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"
TranslateBot sử dụng LiteLLM bên trong, nghĩa là bạn có thể chuyển sang bất kỳ mô hình nào trong hơn 100 mô hình bằng cách thay đổi một chuỗi:
| Nhà cung cấp | Giá trị 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 | Dùng TRANSLATEBOT_PROVIDER = "deepl" thay thế |
Với DeepL, cài thêm extra: pip install translatebot-django[deepl]. Gói miễn phí của DeepL cho bạn 500.000 ký tự mỗi tháng miễn phí, đủ cho hầu hết các dự án nhỏ đến trung bình.
4. Định Nghĩa Ngôn Ngữ
# settings.py
LANGUAGES = [
("en", "English"),
("de", "German"),
("fr", "French"),
("nl", "Dutch"),
("ja", "Japanese"),
]
5. Chạy Dịch Thuật
python manage.py translate
Vậy là xong. TranslateBot quét dự án để tìm file .po, xác định các mục chưa dịch, gửi chúng đến mô hình AI đã cấu hình theo batch tối ưu, và ghi kết quả trở lại. Các bản dịch hiện có không bị thay đổi.
Để dịch một ngôn ngữ duy nhất:
python manage.py translate --target-lang nl
Kết quả hiển thị như sau:
Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings
6. Biên Dịch Như Thường
python manage.py compilemessages
Quy trình đầy đủ giờ là:
python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages
Ba lệnh. Mọi ngôn ngữ. Mọi sprint.
Tăng Dần Theo Thiết Kế
Tính năng quan trọng nhất cho quy trình có thể lặp lại là dịch tăng dần. TranslateBot chỉ dịch các mục có msgstr trống. Nếu bạn có 500 chuỗi và 15 chuỗi mới trong sprint này, chỉ 15 chuỗi đó được gửi đến API.
Điều này quan trọng vì lý do thực tế:
- Chi phí. Bạn chỉ trả cho chuỗi mới, không phải toàn bộ file.
- Tốc độ. Dịch 15 chuỗi mất vài giây, không phải vài phút.
- Ổn định. Các bản dịch bạn đã review và phê duyệt không bao giờ bị ghi đè (trừ khi bạn truyền
--overwriterõ ràng).
An Toàn Placeholder
Django sử dụng nhiều định dạng placeholder: %(name)s, %s, %d, {0}, {name}, và thẻ HTML inline như <strong> hoặc <a href="...">. Nếu bất kỳ cái nào bị hỏng trong dịch thuật, bạn sẽ gặp lỗi runtime hoặc markup bị vỡ.
TranslateBot hướng dẫn mô hình AI bảo toàn tất cả định dạng placeholder và xác thực đầu ra. Chuỗi như:
Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.
Được dịch sang tiếng Hà Lan là:
Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.
Mọi placeholder được giữ nguyên vẹn.
Kiểm Soát Chất Lượng Với TRANSLATING.md
Mô hình AI dịch tốt hơn khi hiểu ngữ cảnh. TranslateBot tìm file TRANSLATING.md ở thư mục gốc dự án và đưa nội dung của nó vào mỗi yêu cầu dịch.
# 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"
File này được quản lý phiên bản cùng code, nên cả đội chia sẻ cùng ngữ cảnh dịch. Bạn cũng có thể đặt file TRANSLATING.md riêng cho mỗi app có thuật ngữ chuyên biệt.
Xem Trước Trước Khi Commit
Cờ --dry-run hiển thị chính xác những gì sẽ được dịch mà không thực hiện lệnh gọi API hay sửa đổi file:
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
Điều này hữu ích trước đợt dịch lớn hoặc khi thành viên mới muốn hiểu lệnh làm gì trước khi cam kết chi phí API.
Tích Hợp CI/CD
Không có cơ chế bắt buộc, bản dịch lỗi thời là không thể tránh khỏi. TranslateBot bao gồm management command check_translations được thiết kế cho pipeline CI:
# .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
Cờ --makemessages chạy makemessages -a --no-obsolete trước, đảm bảo file .po phản ánh mã nguồn hiện tại trước khi kiểm tra. Nếu có mục chưa dịch hoặc fuzzy, lệnh thoát với mã 1 và build thất bại:
locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed
Quy trình nhà phát triển điển hình trở thành:
- Thêm chuỗi mới có thể dịch trong nhánh tính năng.
- CI thất bại vì các chuỗi đó chưa được dịch.
- Chạy
python manage.py translatetrên máy local. - Commit file
.pođã cập nhật. - CI thành công.
Bản dịch không bao giờ lặng lẽ mất đồng bộ.
Dịch Nội Dung Cơ Sở Dữ Liệu
Nếu ứng dụng lưu trữ nội dung có thể dịch trong database (tên sản phẩm, tiêu đề bài viết, nhãn danh mục), TranslateBot cũng tích hợp với 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
Logic tăng dần tương tự áp dụng: chỉ các trường có giá trị ngôn ngữ đích trống mới được dịch.
So Sánh Chi Phí
Một trong những câu hỏi phổ biến nhất là liệu dịch AI có hiệu quả về chi phí so với các phương án thay thế. Đây là so sánh sơ bộ cho dự án có 500 chuỗi có thể dịch trong 5 ngôn ngữ:
| Phương pháp | Chi phí ước tính | Đầu tư thời gian |
|---|---|---|
| Thủ công (thời gian developer) | $0 từ túi, 20-40+ giờ | Rất cao |
| Dịch vụ dịch chuyên nghiệp | $500-2.000+ | Thấp (nhưng chậm) |
| Nền tảng bản địa hóa SaaS | $50-200/tháng | Trung bình |
| TranslateBot + GPT-4o-mini | ~$0,05 (một lần) | Phút |
| TranslateBot + DeepL Free | $0 (tới 500k ký tự/tháng) | Phút |
| TranslateBot + Claude/GPT-4o | ~$0,30 (một lần) | Phút |
Các con số thay đổi tùy thuộc vào số lượng chuỗi và ngôn ngữ đích, nhưng sự khác biệt bậc độ lớn là nhất quán. Cho bảo trì liên tục (dịch 20-50 chuỗi mới thêm mỗi sprint), chi phí AI về cơ bản bằng không.
Thực Hành Tốt Nhất
Bắt đầu với --dry-run. Trước lần chạy dịch thật đầu tiên, xem trước những gì sẽ xảy ra. Điều này xây dựng sự tự tin và phát hiện vấn đề cấu hình sớm.
Commit file .po trước khi dịch. Nếu có sự cố, git checkout đưa bạn về trạng thái sạch ngay lập tức.
Viết TRANSLATING.md từ ngày đầu tiên. Ngay cả file ngắn gọn với mô tả dự án và vài quy tắc thuật ngữ cũng cải thiện đáng kể chất lượng dịch.
Thêm check_translations vào CI. Bước duy nhất này ngăn chặn lỗi i18n phổ biến nhất: chuỗi được đánh dấu để dịch nhưng chưa bao giờ thực sự được dịch.
Dùng gpt-4o-mini hoặc DeepL để tiết kiệm chi phí. Dành mô hình cao cấp như GPT-4o hoặc Claude cho dự án cần độ chính xác cao, như nội dung marketing, văn bản pháp lý, hoặc thuật ngữ chuyên ngành.
Review các chuỗi quan trọng. Dịch AI đủ tốt cho hầu hết văn bản UI, nhưng hãy nhờ người bản ngữ review bất cứ nội dung nào ràng buộc pháp lý, quan trọng về an toàn, hoặc hướng đến khách hàng trong bối cảnh rủi ro cao.
Từ Hàng Giờ Đến Hàng Giây
Framework i18n của Django xuất sắc trong việc trích xuất và biên dịch bản dịch. Khoảng trống luôn nằm ở bước dịch thuật, công việc nhàm chán và dễ sai sót khi điền hàng trăm giá trị msgstr trong nhiều ngôn ngữ.
TranslateBot lấp đầy khoảng trống đó. Cài đặt nó, trỏ đến nhà cung cấp AI, và chạy một lệnh. Chuỗi mới được dịch. Chuỗi hiện có không bị thay đổi. Placeholder được giữ nguyên. CI bắt bất cứ thứ gì bị bỏ sót.
File .po của bạn không còn là gánh nặng mà trở thành một phần bình thường của quy trình build.
pip install translatebot-django
Bắt đầu tại translatebot.dev.