Cách dịch tệp PO mà không làm hỏng ứng dụng của bạn

OpenL Team 7/3/2026
Cách dịch tệp PO mà không làm hỏng ứng dụng của bạn

TABLE OF CONTENTS

Tệp PO trông như những tệp văn bản đơn giản cho đến khi một %s bị dịch sai, một dạng số nhiều bị thiếu, hoặc msgid bị chỉnh sửa làm hỏng ứng dụng của bạn. Hãy dùng quy trình này để dịch các chuỗi dành cho con người trong khi giữ nguyên cấu trúc gettext.

Đừng dán toàn bộ tệp vào một công cụ dịch văn bản thông thường. Tệp PO nằm ở vùng cận mã nguồn: phần chữ cần dịch, nhưng cấu trúc tệp, placeholder, chú thích và chỉ số số nhiều phải được giữ nguyên.

Cách 1: Dùng công cụ dịch tệp PO

Chọn cách này khi bạn muốn bản nháp đầu nhanh nhất và không muốn tự sửa thủ công các cặp msgid / msgstr.

  1. Sao lưu tệp .po gốc. Giữ một bản sạch trong kho của bạn trước khi gửi gì đó cho công cụ dịch. Nếu bản dịch làm hỏng tệp, bạn cần một bản chuẩn để đối chiếu.

  2. Mở một công cụ dịch hiểu PO. Dùng công cụ được xây cho tệp gettext, như OpenL PO Translator, một công cụ dịch tài liệu tính phí theo lượt. Công cụ hiểu PO nên dịch chuỗi đích trong khi giữ nguyên chuỗi nguồn, chú thích, placeholder và cấu trúc tệp. Nếu bạn vẫn đang chọn công cụ, hãy so sánh trong best PO translator guide.

  3. Tải tệp .po lên. Dùng tệp ngôn ngữ có các mục msgidmsgstr. Nếu bạn chỉ có mẫu .pot, hãy tạo tệp .po cho ngôn ngữ đích từ nó trước, rồi tải tệp .po lên.

  4. Chọn ngôn ngữ nguồn và đích. Khớp ngôn ngữ nguồn với văn bản trong msgid, không phải ngôn ngữ của giao diện quản trị. Ví dụ, nếu tệp chứa chuỗi msgid tiếng Anh và bạn cần đầu ra tiếng Tây Ban Nha, hãy chọn English sang Spanish.

  5. Tải xuống tệp đã dịch. Lưu nó với quy ước đặt tên locale mà framework của bạn mong đợi. Plugin WordPress thường dùng mẫu text-domain cộng locale, còn Django thường lưu tệp dưới locale/<language>/LC_MESSAGES/.

  6. Rà soát các chuỗi rủi ro trước. Tìm trong tệp đã dịch các ký tự %, {, }, <, >, msgid_plural, msgctxt, và #, fuzzy. Đây là những mục có khả năng ảnh hưởng đến hành vi khi chạy nhất.

  7. Kiểm tra tệp đã dịch trong ứng dụng của bạn. Tải ngôn ngữ lên cục bộ rồi bấm qua các màn hình dùng chuỗi đã dịch. Một tệp PO không xong chỉ vì đã được dịch; nó chỉ xong khi ứng dụng vẫn hiển thị đúng.

Cách 2: Dịch tệp PO trong Poedit

Chọn cách này khi bạn cần duyệt thủ công, tương thích với WordPress, hoặc một quy trình làm việc từng mục cẩn thận.

  1. Mở tệp trong Poedit. Poedit là trình soạn dịch chuyên cho PO và các định dạng localization khác; trình soạn cơ bản miễn phí, còn bản Pro có tính năng nâng cao cho quy trình nặng hơn. Với WordPress, Polyglots Handbook chính thức giải thích rằng Poedit có thể tạo tệp .po.mo từ một tệp POT và hỗ trợ dạng số nhiều cùng UTF-8.

  2. Cập nhật từ mẫu POT nếu nguồn đã thay đổi. Nếu nhà phát triển sửa văn bản ứng dụng, hãy cập nhật tệp .po từ .pot mới nhất trước khi dịch. Việc này giúp các chuỗi mới, bị xóa và chuỗi fuzzy hiện rõ thay vì âm thầm phát hành văn bản UI cũ.

  3. Chỉ dịch trường msgstr. msgid là chuỗi nguồn mà ứng dụng dùng để tra bản dịch. Trong quy trình gettext bình thường, người dịch nên sửa msgstr, không phải msgid.

  4. Giữ nguyên placeholder chính xác. Đừng dịch hoặc tách khoảng trắng của các biến như %s, %d, %1$s, {name}, %(count)s, :name, hoặc thẻ HTML. Nếu cần đổi thứ tự từ, hãy di chuyển placeholder như một khối hoàn chỉnh.

  5. Xử lý dạng số nhiều như các bản dịch riêng biệt. Một mục số nhiều có thể có msgid, msgid_plural và nhiều giá trị msgstr[n]. Hãy điền đủ mọi ô số nhiều mà ngôn ngữ đích cần, thay vì sao chép cùng một câu ở mọi chỗ.

  6. Lưu và biên dịch tệp .mo nếu ứng dụng của bạn cần. Một số hệ thống đọc trực tiếp tệp .po trong lúc phát triển, nhưng WordPress và nhiều thiết lập gettext khác dùng tệp .mo đã biên dịch lúc chạy. Poedit có thể biên dịch .mo khi lưu; Django có thể biên dịch thông điệp bằng django-admin compilemessages.

  7. Giải quyết cảnh báo trước khi tải lên. Trong Poedit, biểu tượng cảnh báo thường chỉ ra placeholder hỏng, biến thiếu hoặc lệch dạng số nhiều. Hãy sửa những lỗi đó trước khi nhập bản dịch vào WordPress, Django, Drupal hoặc nhánh phát hành của bạn.

Cách 3: Dùng nền tảng localization

Chọn cách này khi nhiều người dịch, biên tập viên hoặc quản lý phát hành cần làm việc trên cùng các tệp PO.

  1. Nhập tệp PO vào một nền tảng hỗ trợ gettext. Weblate và các nền tảng localization tương tự hỗ trợ quy trình PO. Các nền tảng làm việc nhóm thường là sản phẩm trả phí, dù Weblate cũng có bản tự host mã nguồn mở. Cách chúng xử lý chú thích, header, chuỗi fuzzy và placeholder khác nhau, nên hãy kiểm tra cài đặt định dạng trước khi tải tệp sản xuất lên.

  2. Bật kiểm tra placeholder và thẻ. Bật các quy tắc QA cho placeholder kiểu printf, biến có tên, thẻ HTML/XML và dạng số nhiều. Những kiểm tra này bắt được lỗi mà trình kiểm tra chính tả bình thường không thể thấy.

  3. Giữ chú thích của nhà phát triển hiển thị. Chú thích PO có thể mang ngữ cảnh như tham chiếu nguồn, ghi chú do nhà phát triển trích xuất, cờ và chuỗi nguồn trước đó. Người dịch cần những ghi chú đó khi một nhãn UI ngắn như “Open” có thể là động từ, tính từ hoặc lệnh menu.

  4. Dùng translation memory nhưng vẫn duyệt. Translation memory rất hữu ích cho các chuỗi UI lặp lại, nhưng nó có thể chép lại một bản dịch cũ sang bối cảnh mới. Hãy rà soát các chuỗi được tái dùng khi msgctxt, tham chiếu nguồn hoặc UI xung quanh đã thay đổi.

  5. Xuất tệp PO và chạy kiểm tra cục bộ. Đừng tin mù quáng vào bản xuất. Đưa tệp đã dịch lại vào ứng dụng, biên dịch nếu cần, và kiểm tra các màn hình trước khi gộp.

Những quy tắc PO bạn tuyệt đối không được phá

Mục PODịch nó?Ví dụ an toànVì sao quan trọng
msgidKhôngmsgid "Save changes"Ứng dụng dùng chuỗi nguồn này làm khóa tra trong nhiều quy trình gettext.
msgstrmsgstr "Guardar cambios"Đây là văn bản ngôn ngữ đích mà người dùng nhìn thấy.
msgctxtKhôngmsgctxt "button"Ngữ cảnh giúp phân biệt các chuỗi nguồn giống nhau.
%s, %d, %1$sKhôngHello, %s -> Hola, %sMã chạy sẽ thay các placeholder này bằng giá trị thực.
{name}, %(count)s, :nameKhôngWelcome, {name}Biến có tên phải khớp với mã ứng dụng.
Thẻ HTMLThường là không<strong>Warning</strong>Hãy dịch phần chữ, không phải cú pháp thẻ.
msgid_pluralKhôngmsgid_plural "%d files"Chuỗi nguồn số nhiều thuộc đường chạy gốc.
msgstr[0], msgstr[1]Có, cẩn thậnmsgstr[0] "%d file"Mỗi ngôn ngữ đích có quy tắc số nhiều riêng.
#, fuzzyXem lại trước#, fuzzyFuzzy nghĩa là bản dịch có thể đã cũ hoặc chưa được xác nhận.
#. chú thích của devThường là không#. Button labelCác ghi chú này giúp người dịch hiểu ngữ cảnh.

Ví dụ nhanh: PO an toàn và PO bị hỏng

Đây là một mục gettext bình thường:

#. %s is the user's display name.
#, c-format
msgid "Welcome back, %s"
msgstr ""

Một bản dịch tiếng Tây Ban Nha an toàn giữ nguyên %s:

#. %s is the user's display name.
#, c-format
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, %s"

Một bản dịch hỏng thay đổi placeholder:

msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, % s"

Chỉ một khoảng trắng nhỏ như vậy cũng có thể quan trọng. msgfmt --check-format của GNU được thiết kế để bắt các lệch format-string như placeholder % sai, và Poedit cũng cảnh báo các vấn đề placeholder phổ biến. Với danh sách rộng hơn những chuỗi không nên động vào, hãy dùng hướng dẫn của chúng tôi về what not to translate.

Cách kiểm tra một tệp PO đã dịch

  1. Chạy kiểm tra gettext nếu bạn đã cài gettext.
msgfmt --check --check-format -o /tmp/messages.mo path/to/messages.po

Lệnh này kiểm tra cú pháp, header và format string, rồi ghi một catalog biên dịch tạm thời nếu tệp hợp lệ.

  1. Biên dịch tệp theo cách framework của bạn mong đợi.
django-admin compilemessages

Với dự án Django, compilemessages biên dịch các tệp .po do makemessages tạo thành .mo để hỗ trợ gettext.

  1. Tìm các bản dịch trống.
grep -n 'msgstr ""' path/to/messages.po

Các msgstr trống có thể là có chủ ý nếu mục đó chưa dịch, nhưng chúng không nên làm bạn bất ngờ khi phát hành.

  1. Tìm các chuỗi fuzzy.
grep -n '#, fuzzy' path/to/messages.po

Các chuỗi fuzzy nên được con người xem lại trước khi phát hành. Theo mặc định, msgfmt không dùng bản dịch fuzzy trừ khi biên dịch với --use-fuzzy, vì vậy một mục fuzzy có thể hành xử như chuỗi chưa dịch trong catalog cuối cùng.

  1. Kiểm tra UI thật. Mở các màn hình có biểu mẫu, số lượng số nhiều, thông báo lỗi, menu tài khoản và luồng thanh toán. Kiểm tra PO phát hiện lỗi tệp; chỉ kiểm tra UI mới phát hiện được câu chữ gượng, tràn chữ và thiếu ngữ cảnh.

Nên chọn cách nào?

Tình huốngCách tốt nhấtLý do
Bạn cần bản nháp nhanh cho một tệp POTrình dịch tệp POĐường đi nhanh nhất với việc giữ cấu trúc
Bạn duy trì plugin hoặc theme WordPressPoeditQuy trình WordPress quen thuộc với việc biên dịch .mo
Bạn duy trì ứng dụng DjangoTrình dịch PO hoặc Poedit, rồi compilemessagesDịch có thể nhanh, nhưng vẫn cần biên dịch theo framework
Bạn có nhiều ngôn ngữ và người duyệtNền tảng localizationQuản lý, lịch sử, QA và duyệt tốt hơn
Bạn đang dịch chuỗi dành cho devDuyệt người sau khi dịch máyThuật ngữ code, placeholder và ngữ cảnh quan trọng hơn
Bạn cũng đang cục bộ hóa JSON hoặc tệp i18n frontendDùng quy trình riêng cho định dạngQuy tắc PO không phải lúc nào cũng áp dụng cho JSON, YAML hoặc ICU messages

Nếu dự án của bạn trộn các tệp gettext PO với tệp locale JSON, hãy dịch từng định dạng bằng công cụ hiểu cấu trúc của nó. PO file xoay quanh msgidmsgstr; JSON localization xoay quanh khóa và giá trị. Với quy trình đó, hãy xem hướng dẫn best JSON translators in 2026.

FAQ

Tôi có thể dùng Google Translate để dịch PO file không?

Bạn có thể sao chép từng giá trị msgstr vào một công cụ dịch chung, nhưng việc tải lên hoặc dán cả tệp PO vào một công cụ dịch văn bản thuần là rủi ro. Công cụ dịch thông thường có thể thay đổi msgid, chú thích, escape dấu ngoặc kép, chỉ số số nhiều hoặc placeholder. Hãy dùng công cụ hiểu PO, Poedit hoặc một nền tảng localization thay vào đó.

Khác nhau giữa .po, .pot.mo là gì?

.pot là mẫu được trích từ mã nguồn. Nó thường chứa chuỗi gốc nhưng chưa có bản dịch hoàn chỉnh. .po là tệp dịch có thể chỉnh sửa cho một ngôn ngữ đích. .mo là catalog nhị phân đã biên dịch mà nhiều ứng dụng dựa trên gettext nạp lúc chạy.

Tôi có nên dịch msgid không?

Không, trong quy trình bình thường là không. Hãy dịch msgstr. GNU gettext manual mô tả msgid là chuỗi gốc chưa dịch và msgstr là bản dịch; các chuỗi msgid được các công cụ gettext tạo ra và quản lý.

Làm sao kiểm tra một tệp PO hợp lệ?

Chạy msgfmt --check --check-format nếu đã có gettext, mở tệp trong Poedit, hoặc dùng các kiểm tra QA của nền tảng localization. Sau đó biên dịch và kiểm tra tệp trong ứng dụng. Việc xác thực là cần thiết, nhưng không thay thế được kiểm tra UI.

Nếu tôi làm hỏng placeholder thì sao?

Ở mức tốt nhất, ứng dụng sẽ hiển thị chuỗi kỳ lạ. Tệ hơn, trình định dạng lúc chạy sẽ báo lỗi vì chuỗi đã dịch không còn khớp với các biến mà mã nguồn truyền vào. Placeholder chỉ nên được di chuyển như token hoàn chỉnh, không bao giờ dịch hoặc sửa dở dang.

OpenL có thể dịch PO file không?

Có. OpenL PO Translator được xây cho tệp gettext .po và nói rằng nó giữ placeholder và biến nguyên vẹn trong khi dịch sang hơn 100 ngôn ngữ. Đây là quy trình dịch tài liệu tính phí theo lượt, nên hãy dùng nó cho bản nháp đầu nhanh khi việc giữ cấu trúc PO quan trọng hơn việc làm thủ công tất cả. Nếu bạn chỉ có mẫu .pot, hãy tạo một tệp .po cho ngôn ngữ đích trước khi dùng OpenL.

Sources