Tính năngPluginGiáTài nguyên
Thay đổi ngôn ngữ
Tài nguyên.po vs .mo vs .pot: Giải thích các tệp dịch thuật WordPress

.po vs .mo vs .pot: Giải thích các tệp dịch thuật WordPress

SimplePoTranslate Team21 tháng 4, 2026
.po vs .mo vs .pot: Giải thích các tệp dịch thuật WordPress

Bạn mở thư mục languages của một chủ đề WordPress và tìm thấy ba tệp trông gần như giống hệt nhau: twentytwentyfour.pot, twentytwentyfour-de_DE.potwentytwentyfour-de_DE.mo. Cùng chủ đề, cùng ngôn ngữ, ba phần mở rộng khác nhau. Bạn sẽ chỉnh sửa tệp nào? Tệp nào WordPress thực sự tải? Và tại sao việc chỉnh sửa sai tệp lại khiến bản dịch của bạn biến mất một cách âm thầm?

Nếu bạn đã từng thắc mắc tệp nào quan trọng trong cuộc tranh luận tệp po vs mo, bạn không đơn độc. Ba phần mở rộng này là xương sống của mọi trang web WordPress đã được dịch, nhưng sự khác biệt giữa chúng lại làm bối rối cả người mới bắt đầu lẫn các nhà phát triển dày dặn kinh nghiệm. Chỉnh sửa sai tệp và khách truy cập người Đức của bạn vẫn thấy tiếng Anh. Chỉnh sửa đúng tệp nhưng bỏ qua một bước thì cũng không có gì thay đổi.

Hướng dẫn này giải thích chính xác các tệp .pot, .po.mo là gì, cách chúng liên quan trong quy trình làm việc của GNU Gettext, nơi chúng cư trú trong WordPress và tại sao bạn không bao giờ nên mở tệp .mo bằng trình soạn thảo văn bản. Cuối cùng bạn sẽ biết tệp nào cần chạm vào và tệp nào nên bỏ qua.

Các tệp .pot, .po và .mo là gì?

Tóm lại: tệp .pot là mẫu trắng, tệp .po là bản dịch có thể chỉnh sửa của bạn, và tệp .mo là tệp nhị phân đã biên dịch mà WordPress đọc trong thời gian chạy. Chúng tạo thành một chuỗi, và mỗi liên kết chỉ có một nhiệm vụ.

Ba định dạng này đều đến từ GNU Gettext, hệ thống bản địa hóa mà WordPress, Drupal và hàng nghìn dự án PHP và C dựa vào. Gettext tách chuỗi nguồn mà nhà phát triển viết khỏi bản dịch mà người dịch cung cấp, để cùng một cơ sở mã có thể nói hàng tá ngôn ngữ mà không cần chạm vào một dòng mã PHP nào.

Hãy nghĩ nó như một thẻ công thức. .pot là thẻ trắng với các ô nguyên liệu nhưng không có số lượng. .po là thẻ đã được điền cho một món ăn cụ thể. .mo là bản sao đã được ép nhựa, có thể quét bằng máy mà nhà bếp thực sự sử dụng trong quá trình phục vụ. Bạn viết trên thẻ giấy; bạn không bao giờ viết nguệch ngoạc lên thẻ đã ép nhựa.

Tệp .pot: Mẫu chính

Tệp .pot (Portable Object Template) chứa mọi chuỗi có thể dịch trong một chủ đề hoặc plugin với các bản dịch để trống. Đây là danh sách tổng thể mà các nhà phát triển gửi đi để người dịch biết chính xác những gì cần dịch. Các dòng msgstr bị trống vì chưa có ngôn ngữ nào được chọn.

#: includes/checkout.php:42
msgid "Add to Cart"
msgstr ""

#: includes/account.php:108
msgid "Your order has been shipped to %s"
msgstr ""

Chú ý msgstr "" trống. Một .pot là một mẫu, không phải một bản dịch. Bạn sao chép nó một lần cho mỗi ngôn ngữ và điền vào chỗ trống. Bạn hiếm khi chỉnh sửa .pot bằng tay; nó được tạo lại từ mã nguồn bất cứ khi nào các chuỗi thay đổi.

Tệp .po: Bản dịch có thể chỉnh sửa bằng con người của bạn

Tệp .po (Portable Object) là một bản sao của .pot với các dòng msgstr đã được điền cho một ngôn ngữ. Đây là tệp mà người dịch và nhà phát triển thực sự chỉnh sửa. Nó là văn bản thuần túy, dễ đọc bằng con người và thân thiện với kiểm soát phiên bản.

#: includes/checkout.php:42
msgid "Add to Cart"
msgstr "In den Warenkorb"

#: includes/account.php:108
msgid "Your order has been shipped to %s"
msgstr "Ihre Bestellung wurde an %s versandt"

msgid là chuỗi nguồn tiếng Anh gốc và không bao giờ được thay đổi. msgstr là bản dịch của bạn. %s là một phần giữ chỗ phải được giữ nguyên trong bản dịch — việc bỏ hoặc sắp xếp lại nó là nguyên nhân phổ biến nhất gây ra lỗi bố cục, mà chúng tôi đã đề cập chi tiết trong cách dịch các tệp PO mà không làm hỏng biến mã.

Tệp .mo: Nhị phân đã biên dịch

Tệp .mo (Machine Object) là phiên bản nhị phân đã biên dịch của .po của bạn. WordPress không thể đọc các tệp .po một cách hiệu quả trong thời gian chạy, vì vậy nó tải .mo đã được biên dịch trước thay thế. Mở một .mo trong trình soạn thảo văn bản sẽ hiển thị các byte không thể đọc được — nó dành cho máy móc, không phải con người.

Khi WordPress gọi load_textdomain() hoặc load_theme_textdomain(), nó tìm kiếm tệp .mo, phân tích bảng băm nhị phân của nó và hoán đổi mọi msgid với msgstr phù hợp ngay lập tức. Định dạng nhị phân này giúp việc tra cứu nhanh chóng ngay cả trên các trang web có hàng nghìn chuỗi.

Ba tệp này liên quan đến nhau như thế nào trong Quy trình làm việc của Gettext?

Chúng tạo thành một quy trình một chiều: mã nguồn trở thành .pot, .pot trở thành .po theo từng ngôn ngữ, và mỗi .po được biên dịch thành .mo. Bản dịch luôn chảy xuống.

Dưới đây là toàn bộ vòng đời theo thứ tự:

  1. Một nhà phát triển bao bọc các chuỗi hiển thị cho người dùng trong các hàm Gettext như __()_e() bên trong mã nguồn PHP.
  2. Một công cụ quét đọc mã nguồn và tạo mẫu .pot chứa mọi chuỗi được bao bọc.
  3. Một người dịch sao chép .pot thành một tệp .po dành riêng cho ngôn ngữ (ví dụ de_DE.po) và điền vào mỗi msgstr.
  4. Tệp .po hoàn chỉnh được biên dịch thành tệp .mo nhị phân.
  5. WordPress tải .mo trong thời gian chạy và hiển thị trang web đã được dịch.

Khi nhà phát triển thêm các chuỗi mới sau này, .pot được tạo lại, các mục mới được hợp nhất vào mỗi .po hiện có (giữ lại các bản dịch cũ), người dịch điền vào các chỗ trống, và .po được biên dịch lại thành .mo. Chu kỳ lặp lại trong suốt vòng đời của dự án.

Điểm mấu chốt: bạn chỉnh sửa .po, sau đó biên dịch thành .mo. Bạn không bao giờ chỉnh sửa trực tiếp .mo, và bạn không bao giờ dịch bên trong .pot. Nếu bạn muốn hiểu sâu hơn về toàn bộ quy trình, hướng dẫn toàn diện về bản địa hóa WordPress sẽ trình bày toàn bộ quy trình với các ví dụ.

Quy ước đặt tên và nơi các tệp cư trú

WordPress rất nghiêm ngặt về tên tệp. Nếu đặt tên sai, tệp .mo đã được dịch hoàn hảo của bạn sẽ bị bỏ qua, vì WordPress tìm kiếm một sự khớp chính xác dựa trên miền văn bản (text domain) và ngôn ngữ (locale).

Quy tắc đặt tên cho các bản dịch chủ đề và plugin là:

# Pattern: textdomain-locale.po / .mo
twentytwentyfour-de_DE.po      # German (Germany) translation
twentytwentyfour-de_DE.mo      # compiled binary WordPress loads
twentytwentyfour-fr_FR.po      # French (France)
twentytwentyfour.pot           # template, no locale suffix

textdomain khớp với chuỗi được truyền dưới dạng đối số thứ hai cho các hàm Gettext như __( 'Add to Cart', 'twentytwentyfour' ). locale là mã ngôn ngữ WordPress như de_DE, fr_FR hoặc pt_BR. Mẫu .pot không mang hậu tố ngôn ngữ vì nó không phụ thuộc vào ngôn ngữ.

Vị trí cũng quan trọng như việc đặt tên. WordPress tìm kiếm một vài đường dẫn dễ đoán:

  • Bản dịch chủ đề nằm trong thư mục wp-content/themes/your-theme/languages/ của chính chủ đề.
  • Bản dịch plugin nằm trong wp-content/plugins/your-plugin/languages/.
  • Bản dịch từ translate.wordpress.org và các ghi đè của người dùng nằm trong các thư mục chung wp-content/languages/themes/wp-content/languages/plugins/, những thư mục này được ưu tiên và tồn tại sau các bản cập nhật.

Đặt một tệp de_DE.mo có tên đúng vào thư mục chính xác và khách truy cập người Đức sẽ thấy tiếng Đức. Đặt nó sâu hơn một thư mục, hoặc viết sai chính tả miền văn bản, và WordPress sẽ lặng lẽ quay về tiếng Anh mà không có thông báo lỗi. Nếu bản dịch của bạn không xuất hiện, nguyên nhân thông thường là do tên hoặc đường dẫn không khớp, và hướng dẫn khắc phục sự cố bản dịch bị thiếu bao gồm mọi nguyên nhân phổ biến.

Tại sao bạn không bao giờ nên chỉnh sửa trực tiếp tệp .mo

.mo là một tệp nhị phân đã biên dịch, không có cách an toàn nào để chỉnh sửa nó bằng tay — và bất kỳ thay đổi nào bạn cố gắng thực hiện sẽ bị ghi đè vào lần biên dịch lại .po tiếp theo. .po là nguồn sự thật; .mo là một tạo phẩm xây dựng có thể loại bỏ.

Quy tắc duy nhất này giải thích một phần lớn các yêu cầu hỗ trợ "bản dịch của tôi đã thay đổi nhưng trang web không cập nhật". Ai đó điều chỉnh một chuỗi, lưu .po và quên biên dịch lại .mo. WordPress tiếp tục tải tệp nhị phân cũ, vì vậy cách diễn đạt mới không bao giờ xuất hiện. Cách khắc phục luôn là: chỉnh sửa .po, biên dịch lại thành .mo, tải lại.

Có một lý do thứ hai khiến quy tắc này quan trọng: các tệp .mo không thân thiện với việc so sánh (diff) trong kiểm soát phiên bản. Vì chúng là nhị phân, một thay đổi nhỏ trong cách diễn đạt sẽ tạo ra một khối dữ liệu không rõ ràng trong lịch sử Git của bạn mà không người đánh giá nào có thể đọc được. Việc giữ .po làm nguồn sự thật được theo dõi và coi .mo là một tạo phẩm được tạo ra giúp kho lưu trữ của bạn có thể xem xét và các bản dịch của bạn có thể kiểm tra được.

Thực hiện việc này thủ công trên hàng chục ngôn ngữ là tẻ nhạt và dễ mắc lỗi. Đây là lúc quy trình làm việc đám mây tiết kiệm thời gian thực sự. Các công cụ như SimplePoTranslate dịch các chuỗi .po của bạn và trả về một tệp ZIP duy nhất chứa .po.mo phù hợp với nhau — đã được biên dịch, đặt tên đúng, sẵn sàng để đưa vào wp-content/languages/. Không cần biên dịch thủ công và không có khả năng có tệp .mo cũ.

Nó cũng áp dụng Syntax Locking, đóng băng mọi phần giữ chỗ như %s, %1$s{name}, cùng với các thẻ HTML, trước khi dịch. Các biến của bạn vẫn nguyên vẹn, vì vậy bạn không bao giờ gửi một tệp .mo làm hỏng bố cục. Và vì nó chạy hoàn toàn trên đám mây, không có plugin bổ sung nào làm nặng trang web của bạn — bạn tải lên một tệp và tải xuống các bản dịch đã hoàn thành, đã biên dịch.

Tổng kết

Một khi sự khác biệt giữa tệp po và mo được hiểu rõ, toàn bộ hệ thống dịch WordPress sẽ không còn cảm thấy bí ẩn nữa. .pot là mẫu của nhà phát triển, .po là bản sao làm việc có thể chỉnh sửa của người dịch, và .mo là tệp nhị phân đã biên dịch mà WordPress thực sự phục vụ khách truy cập. Bản dịch chảy theo một hướng — từ mẫu đến .po đến .mo — và bạn chỉ chỉnh sửa thủ công tệp ở giữa.

Hãy nhớ ba quy tắc giúp ngăn chặn chín mươi phần trăm các vấn đề về dịch thuật: không bao giờ dịch bên trong .pot, luôn biên dịch lại .mo sau khi chỉnh sửa .po, và khớp chính xác tên textdomain-locale. Tuân thủ các quy tắc đó và các chuỗi đã dịch của bạn sẽ luôn xuất hiện.

Sẵn sàng ngừng vật lộn với việc biên dịch và đặt tên các tệp dịch thủ công? Dùng thử SimplePoTranslate miễn phí — không cần thẻ tín dụng. Tải lên tệp .po hoặc .pot của bạn và nhận lại một gói .po + .mo sẵn sàng sử dụng ở gói miễn phí chỉ trong vài phút.