Skip to main content

Python i18n: Hướng dẫn bản địa hóa đầy đủ

Thiết lập python-i18n với tệp bản dịch JSON hoặc YAML, xử lý phần giữ chỗ và dạng số nhiều rồi tự động dịch bằng AI.

1

Cài đặt python-i18n

python-i18n là thư viện quốc tế hóa gọn nhẹ dành cho Python. Thư viện hỗ trợ sẵn tệp bản dịch JSON và YAML, khóa lồng nhau, nội suy phần giữ chỗ và dạng số nhiều.

Terminal
pip install python-i18n
python-i18n hỗ trợ JSON theo mặc định. Với tệp bản dịch YAML, hãy cài phần phụ thuộc YAML tùy chọn bằng pip install python-i18n[YAML] để bổ sung PyYAML.
Terminal
# To use YAML translation files instead of JSON:
pip install python-i18n[YAML]
2

Cấu hình bản dịch

Đặt định dạng tệp, thêm đường dẫn tệp bản dịch và cấu hình ngôn ngữ mặc định cùng ngôn ngữ dự phòng. Nhập cấu hình này tại điểm vào của ứng dụng trước mọi lệnh gọi dịch.

i18n_config.py
import i18n

# Set the file format (json or yaml)
i18n.set("file_format", "json")

# Add the directory containing your translation files
i18n.load_path.append("translations/")

# Set the default locale
i18n.set("locale", "en")

# Set the fallback locale (used when a key is missing)
i18n.set("fallback", "en")

# Enable/disable error on missing translations
i18n.set("error_on_missing_translation", False)
load_path phải trỏ đến thư mục chứa tệp bản dịch, không phải một tệp cụ thể. Nếu bản dịch trả về khóa thô, hãy kiểm tra load_path có chính xác và tên tệp có khớp với mã ngôn ngữ hay không (ví dụ: en.json, de.json).
3

Tạo tệp bản dịch

Tạo một tệp cho mỗi ngôn ngữ ở định dạng JSON hoặc YAML. Dùng khóa lồng nhau để sắp xếp chuỗi theo tính năng hoặc trang. Giữ ngôn ngữ nguồn (thường là tiếng Anh) làm nguồn tham chiếu duy nhất.

translations/en.json
// translations/en.json
{
  "greeting": "Hello!",
  "welcome": "Welcome to our application",
  "nav": {
    "home": "Home",
    "about": "About",
    "settings": "Settings"
  },
  "cart": {
    "item_count": "%{count} item(s) in your cart"
  }
}

// translations/de.json
{
  "greeting": "Hallo!",
  "welcome": "Willkommen in unserer Anwendung",
  "nav": {
    "home": "Startseite",
    "about": "Über uns",
    "settings": "Einstellungen"
  },
  "cart": {
    "item_count": "%{count} Artikel in Ihrem Warenkorb"
  }
}
Đặt tên khóa theo nội dung mô tả, không theo vị trí hiển thị: 'cart.item_count' phù hợp hơn 'homepage_cart_label'. Khóa nên tiếp tục dùng được sau khi thiết kế lại UI.
4

Dùng bản dịch trong mã của bạn

Gọi i18n.t() bằng đường dẫn khóa phân tách bởi dấu chấm để tra cứu chuỗi đã dịch. Bạn có thể ghi đè ngôn ngữ cho từng lệnh gọi mà không thay đổi cài đặt chung.

app.py
import i18n

# Simple translation
print(i18n.t("greeting"))          # "Hello!"
print(i18n.t("nav.home"))          # "Home"
print(i18n.t("nav.about"))         # "About"

# Translation with a specific locale
print(i18n.t("greeting", locale="de"))   # "Hallo!"
print(i18n.t("nav.home", locale="ja"))   # "ホーム"

# Missing key returns a placeholder
print(i18n.t("missing.key"))       # "Missing.Key"
Khóa lồng nhau dùng ký pháp dấu chấm: i18n.t('nav.home'). Nếu khóa JSON chứa dấu chấm theo nghĩa đen, python-i18n sẽ hiểu đó là dấu phân tách cấp lồng nhau. Tránh dùng dấu chấm trong tên khóa.
5

Phần giữ chỗ và dạng số nhiều

python-i18n hỗ trợ nội suy phần giữ chỗ bằng cú pháp %{name} và dạng số nhiều cơ bản bằng các khóa con 'zero', 'one' và 'many'. Truyền đối số từ khóa vào i18n.t() cho cả hai tính năng.

Placeholders
# translations/en.json
# {
#   "welcome_user": "Welcome, %{name}!",
#   "order_status": "Order #%{order_id}: %{status}",
#   "file_size": "File size: %{size} %{unit}"
# }

import i18n

# Single placeholder
print(i18n.t("welcome_user", name="Alice"))
# "Welcome, Alice!"

# Multiple placeholders
print(i18n.t("order_status", order_id=12345, status="shipped"))
# "Order #12345: shipped"

# Reusable with different values
print(i18n.t("file_size", size=2.5, unit="MB"))
# "File size: 2.5 MB"

print(i18n.t("file_size", size=800, unit="KB"))
# "File size: 800 KB"
Pluralization
# translations/en.json
# {
#   "inbox": {
#     "zero": "No messages",
#     "one": "1 message",
#     "many": "%{count} messages"
#   }
# }

import i18n

print(i18n.t("inbox", count=0))    # "No messages"
print(i18n.t("inbox", count=1))    # "1 message"
print(i18n.t("inbox", count=42))   # "42 messages"
Tính năng dạng số nhiều của python-i18n dùng ba loại: zero, one và many. Các loại này đáp ứng tiếng Anh cùng nhiều ngôn ngữ nhưng không hỗ trợ đầy đủ quy tắc số nhiều CLDR (few, two, other). Với ngôn ngữ có dạng số nhiều phức tạp như tiếng Ả Rập, tiếng Nga hoặc tiếng Ba Lan, bạn có thể cần tự xử lý trường hợp biên hoặc dùng thư viện nâng cao hơn.
6

Chuyển đổi ngôn ngữ khi chạy

Chuyển ngôn ngữ đang dùng trên toàn cục bằng i18n.set('locale', code) hoặc ghi đè cho từng lệnh gọi bằng đối số từ khóa locale. Trong framework web, hãy phát hiện ngôn ngữ ưu tiên của người dùng từ yêu cầu và đặt ngôn ngữ trước khi kết xuất.

Locale switching
import i18n

# Set locale globally
i18n.set("locale", "de")
print(i18n.t("greeting"))           # "Hallo!"

# Switch to Japanese
i18n.set("locale", "ja")
print(i18n.t("greeting"))           # "こんにちは!"

# Override per-call without changing global locale
i18n.set("locale", "en")
print(i18n.t("greeting"))           # "Hello!"
print(i18n.t("greeting", locale="de"))  # "Hallo!"
app.py
from flask import Flask, request, g
import i18n

app = Flask(__name__)

i18n.set("file_format", "json")
i18n.load_path.append("translations/")

SUPPORTED_LOCALES = ["en", "de", "ja", "es", "fr"]

@app.before_request
def set_locale():
    # Check URL parameter, cookie, then Accept-Language header
    locale = request.args.get("lang")
    if not locale:
        locale = request.cookies.get("locale")
    if not locale:
        locale = request.accept_languages.best_match(SUPPORTED_LOCALES)
    g.locale = locale or "en"
    i18n.set("locale", g.locale)

@app.route("/")
def index():
    return i18n.t("welcome")
i18n.set('locale', ...) thay đổi ngôn ngữ trên toàn cục. Trong máy chủ web đa luồng (gunicorn có worker, Django), thao tác này có thể gây tranh chấp khi một yêu cầu đổi ngôn ngữ giữa lúc yêu cầu khác đang kết xuất. Hãy ghi đè ngôn ngữ theo từng lệnh gọi hoặc dùng vùng lưu trữ cục bộ theo luồng để tránh tình trạng này.
7

Dự phòng ngôn ngữ thông minh với python-i18n-locale-chain

Theo mặc định, python-i18n chỉ hỗ trợ một ngôn ngữ dự phòng. Khi người dùng pt-BR không có bản dịch pt-BR, thư viện chuyển thẳng sang tiếng Anh dự phòng và bỏ qua bản dịch pt-PT hoàn toàn phù hợp. python-i18n-locale-chain khắc phục vấn đề này bằng chuỗi dự phòng có thể cấu hình, bao phủ 75 biến thể ngôn ngữ.

python-i18n-locale-chain là gói mã nguồn mở miễn phí. Một lệnh gọi hàm kích hoạt 75 chuỗi dự phòng tích hợp sẵn cho các biến thể vùng miền của tiếng Trung, Bồ Đào Nha, Tây Ban Nha, Pháp, Đức, Ý, Hà Lan, Anh, Ả Rập, Na Uy và Mã Lai.
Terminal
pip install python-i18n-locale-chain
i18n_config.py
from locale_chain import configure
import i18n

i18n.set("file_format", "json")
i18n.load_path.append("translations/")

# Activate smart fallback chains (75 built-in chains)
configure()

# Now pt-BR falls back to pt-PT -> pt -> en (instead of just en)
result = i18n.t("greeting", locale="pt-BR")

# es-MX falls back to es-419 -> es -> en
result = i18n.t("greeting", locale="es-MX")

# zh-Hant-HK falls back to zh-Hant-TW -> zh-Hant -> en
result = i18n.t("greeting", locale="zh-Hant-HK")
Advanced configuration
from locale_chain import configure, reset

# Override specific chains
configure(overrides={
    "pt-BR": ["pt"],         # Skip pt-PT, go straight to pt
    "ja-JP": ["ja"],         # Add a new chain
})

# Full custom map (no defaults)
configure(
    fallbacks={"pt-BR": ["pt-PT"]},
    merge_defaults=False
)

# Use German as final fallback instead of English
configure(default_locale="de")

# Restore original i18n.t() behaviour
reset()
Các chuỗi đáng ưu tiên kiểm thử nhất: pt-BR -> pt-PT -> pt -> en (tiếng Bồ Đào Nha), es-MX -> es-419 -> es -> en (tiếng Tây Ban Nha), zh-Hant-HK -> zh-Hant-TW -> zh-Hant -> en (tiếng Trung phồn thể). Chúng bao quát những tình huống dự phòng vùng miền phổ biến nhất.
8

Tự động hóa bản dịch

Sau khi hoàn tất thiết lập i18n, hãy dùng AI để dịch các tệp ngôn ngữ. Trong IDE, yêu cầu trợ lý AI dịch tệp nguồn hoặc dùng i18n Agent CLI trong quy trình CI/CD.

Terminal
# In your IDE, ask your AI assistant:
> Translate translations/en.json to German, Japanese, and Spanish

translations/de.json created (1.2s)
translations/ja.json created (1.5s)
translations/es.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate translations/en.json --lang de,ja,es
Dịch theo từng phần. Khi thêm khóa mới vào tệp nguồn, chỉ dịch phần thay đổi thay vì tạo lại mọi tệp. Cách này bảo toàn các bản dịch đã qua con người duyệt.

Tự động đảm bảo chất lượng bản dịch

Dùng i18n-validate để phát hiện khóa bị thiếu và phần giữ chỗ bị hỏng trước khi phát hành. Dùng i18n-pseudo để kiểm thử UI bằng bản dịch giả trước khi có bản dịch thực.

Lỗi thường gặp

Bản dịch trả về khóa thô

Nguyên nhân: chưa đặt load_path hoặc đường dẫn trỏ sai thư mục, file_format không khớp với phần mở rộng tệp hoặc tên tệp không khớp với mã ngôn ngữ. Hãy xác minh i18n.load_path chứa đúng thư mục và tệp được đặt tên chính xác (ví dụ: en.json, de.json).

Không tải được tệp YAML

python-i18n cần PyYAML để hỗ trợ YAML nhưng không cài sẵn theo mặc định. Hãy cài bằng pip install python-i18n[YAML]. Nếu thiếu gói này, hệ thống âm thầm bỏ qua tệp YAML và bản dịch trả về phần giữ chỗ cho khóa bị thiếu.

Không tra cứu được khóa lồng nhau

python-i18n dùng ký pháp dấu chấm cho khóa lồng nhau: i18n.t('nav.home'). Nếu JSON dùng khóa phẳng có dấu chấm trong tên (ví dụ: 'nav.home' là một khóa duy nhất), thư viện sẽ hiểu đó là phép tra cứu lồng nhau và không tìm thấy. Hãy dùng đối tượng JSON lồng nhau thực sự.

Thay đổi ngôn ngữ bị rò rỉ giữa các yêu cầu

i18n.set('locale', ...) là thao tác toàn cục. Trên máy chủ đa luồng, một yêu cầu có thể đổi ngôn ngữ khi yêu cầu khác đang kết xuất. Hãy dùng đối số từ khóa locale= cho từng lệnh gọi i18n.t() hoặc đặt ngôn ngữ trong vùng lưu trữ cục bộ theo luồng bằng middleware.

Cấu trúc tệp đề xuất

Project Structure
my-python-app/
├── translations/
│   ├── en.json           # Source language (JSON)
│   ├── de.json           # German
│   ├── ja.json           # Japanese
│   ├── es.json           # Spanish
│   └── pt-BR.json        # Brazilian Portuguese
├── app.py                # Application entry point
├── i18n_config.py        # i18n setup and configuration
├── requirements.txt      # pip dependencies
└── pyproject.toml        # Project metadata

# Or with YAML files:
my-python-app/
├── translations/
│   ├── en.yml
│   ├── de.yml
│   └── ja.yml
├── app.py
└── ...

Dùng thử i18n Agent ngay

Thả tệp bản dịch của bạn vào đây

JSON, YAML, PO, XML, CSV, Markdown, Properties

hoặc nhấp để duyệt

Ngôn ngữ đích

Không cần đăng kýBáo giá tức thì

Dự phòng ngôn ngữ với python-i18n-locale-chain

Khi thiếu khóa bản dịch trong ngôn ngữ vùng miền như es-419, python-i18n chuyển thẳng sang ngôn ngữ mặc định thay vì kiểm tra ngôn ngữ cha es trước.

Terminal
pip install python-i18n-locale-chain
Configuration
from i18n_locale_chain import configure_chain

configure_chain('{')
    'es': ['en', 'ru'],
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
'}')

# Usage: t('greeting', locale='es') — falls back through chain

Xem Hướng dẫn dự phòng ngôn ngữ để biết danh sách đầy đủ các framework được hỗ trợ và 75 chuỗi tích hợp sẵn. Learn more →

Câu hỏi thường gặp