Cách dịch tệp .po của Drupal bằng AI

Hầu hết mọi người liên tưởng các tệp .po với WordPress, nhưng định dạng gettext đã có trước WordPress hàng thập kỷ và hỗ trợ dịch giao diện trên toàn bộ thế giới mã nguồn mở. Drupal là một trong những người dùng lớn nhất của nó. Nếu bạn điều hành một trang web Drupal đa ngôn ngữ, mọi nhãn menu, mô tả trường, thông báo lỗi và chuỗi mô-đun đều đi qua các tệp .po chính xác như trong WordPress, chỉ khác ở phương ngữ placeholder và quy trình nhập. Và giống như WordPress, ngay khi trang web của bạn vượt quá một vài chuỗi, việc dịch thủ công các tệp đó sẽ trở thành nút thắt cổ chai.
Hướng dẫn này nói về cách dịch tệp Drupal po bằng AI mà không làm hỏng những thứ tạo nên Drupal. Chúng tôi sẽ đi sâu vào hệ thống dịch của Drupal, nơi các chuỗi thực sự đến từ đâu, cú pháp placeholder khác với WordPress và tuyệt đối phải được giữ nguyên, cũng như quy trình xuất, dịch và nhập lại hoàn chỉnh bao gồm các lệnh drush giúp quy trình này có thể lặp lại.
Cách hệ thống dịch của Drupal hoạt động
Drupal xử lý dịch giao diện thông qua mô-đun cốt lõi locale (đôi khi được gọi là "Interface Translation" trong Drupal hiện đại). Sau khi được bật, nó quản lý một bảng cơ sở dữ liệu gồm các chuỗi nguồn và bản dịch của chúng theo từng ngôn ngữ, đồng thời có thể nhập và xuất các bản dịch đó dưới dạng tệp gettext .po tiêu chuẩn.
Giao diện quản trị nằm tại /admin/config/regional/translate. Từ đó bạn có thể tìm kiếm các chuỗi chưa được dịch, chỉnh sửa chúng trực tiếp và quan trọng là nhập tệp .po để tải hàng loạt bản dịch hoặc xuất trạng thái hiện tại sang tệp .po để chỉnh sửa ngoại tuyến. Chu trình xuất/chỉnh sửa/nhập đó là quy trình làm việc mà chúng tôi đang tối ưu hóa.
Không giống như WordPress, nơi mỗi plugin và theme xuất bản các tệp .po và .mo riêng trong thư mục languages/, Drupal tập trung các chuỗi giao diện vào cơ sở dữ liệu của nó và coi .po là định dạng trao đổi. Bạn xuất, làm việc với tệp và nhập lại. Bước biên dịch .mo mà WordPress yêu cầu được xử lý nội bộ.
Các chuỗi đến từ đâu
Các chuỗi của Drupal có nguồn gốc từ ba nơi, và một bản dịch hoàn chỉnh phải bao gồm tất cả chúng:
- Core cung cấp hàng ngàn chuỗi có thể dịch được cho giao diện người dùng quản trị, biểu mẫu và thông báo hệ thống.
- Contrib modules (Views, Webform, Commerce, và các mô-đun khác) mỗi mô-đun tự đăng ký chuỗi của riêng mình thông qua hàm
t(). - Themes đóng góp các chuỗi mẫu, nhãn vùng và mô tả cài đặt theme.
Khi bạn xuất từ /admin/config/regional/translate, bạn có thể giới hạn phạm vi xuất cho các chuỗi đã dịch, chưa dịch hoặc tất cả các chuỗi. Để thực hiện một lượt dịch mới, chỉ xuất các chuỗi chưa dịch sẽ cung cấp cho bạn một tệp .po tập trung với chính xác những công việc còn lại.
Một hệ quả thực tế của cấu trúc ba nguồn này: công việc dịch thuật của bạn không bao giờ thực sự "hoàn thành." Mỗi khi bạn thêm một mô-đun đóng góp, bật một tính năng mới hoặc cập nhật Drupal core, một loạt các mục msgid chưa dịch mới sẽ xuất hiện trong các bảng locale. Đây là lý do tại sao các nhóm Drupal coi dịch thuật là một quy trình lặp đi lặp lại chứ không phải là một nhiệm vụ khởi chạy một lần. Cùng một vòng lặp xuất, dịch, nhập lại chạy trên mọi triển khai có liên quan đến các mô-đun, và vòng lặp đó càng nhanh thì nợ dịch thuật tích lũy giữa các bản phát hành càng ít.
Cũng cần lưu ý rằng Drupal có thể tự động lấy các bản dịch do cộng đồng đóng góp từ localize.drupal.org cho core và các mô-đun đóng góp phổ biến. Những bản dịch này bao gồm các chuỗi thông thường, nhưng hiếm khi bao gồm các mô-đun tùy chỉnh của bạn, theme của bạn hoặc các cụm từ dành riêng cho dự án mà trang web của bạn thực sự sử dụng. Khoảng cách giữa bản dịch cộng đồng và một trang web được bản địa hóa hoàn chỉnh chính xác là công việc mà một lượt AI giải quyết nhanh chóng.
Placeholder của Drupal không giống với Placeholder của WordPress
Đây là điều quan trọng nhất cần hiểu trước khi gửi bất kỳ tệp .po nào của Drupal cho một công cụ dịch AI: Drupal không sử dụng các placeholder kiểu printf %s và %1$s phổ biến trong WordPress. Hàm t() của Drupal sử dụng ba tiền tố placeholder khác biệt, mỗi loại có hành vi thoát khác nhau:
@variable— giá trị được thoát HTML, giá trị mặc định an toàn cho văn bản do người dùng cung cấp.%variable— giá trị được thoát và bọc trong đánh dấu nhấn mạnh<em>.:placeholder— được sử dụng cho các thuộc tính URL, được xử lý thông qua quy trình làm sạch URL.
Một chuỗi nguồn Drupal điển hình trông như thế này trong tệp .po được xuất:
#: core/modules/node/node.module
msgid "@count comments"
msgid_plural "@count comments"
msgstr[0] ""
msgstr[1] ""
#: core/modules/user/user.module
msgid "Welcome @name, you last logged in on %date."
msgstr ""
Nếu một dịch giả thay đổi @count thành @cuenta, thay thế @name bằng từ đã dịch cho "name," hoặc chèn một khoảng trắng biến @count thành @ count, placeholder sẽ không còn khớp với những gì lệnh gọi t() truyền vào. Drupal sau đó sẽ in token @count nguyên văn ra trang thay vì số thực tế. Bản dịch trông có vẻ hoàn chỉnh nhưng trang web bị lỗi rõ rệt.
Đây là cùng một loại lỗi xảy ra với các chuỗi %s của WordPress, và chúng tôi đề cập sâu về nguyên tắc chung trong bài cách dịch tệp PO mà không làm hỏng các biến code. Sự khác biệt của Drupal đơn giản là có ba kiểu placeholder thay vì một, và một công cụ dịch phải nhận diện tất cả chúng.
Tại sao các công cụ dịch thông thường lại thất bại ở đây
Dán chuỗi node.module đó vào một hộp dịch máy thông thường và bạn sẽ thường thấy @count bị sai, %date được liên kết với <em> được bản địa hóa thành một token khác, hoặc các dạng số nhiều bị gộp thành một. Không có công cụ nào trong số này được xây dựng với ngữ nghĩa gettext trong tâm trí. Chúng dịch văn bản; chúng không hiểu rằng @count là một hợp đồng với mã ứng dụng.
Một quy trình dịch thuật nhận biết gettext với Syntax Locking coi @variable, %variable và :placeholder là các token bất biến. Chúng được khóa trước khi dịch và khôi phục sau đó, để câu xung quanh được dịch trong khi các placeholder không bị chạm đến. Khóa tương tự bao gồm %s và %1$s của WordPress, {{name}} của i18next và HTML nội tuyến, đó là lý do tại sao một công cụ duy nhất có thể phục vụ dự án Drupal, Symfony hoặc Laravel dễ dàng như một dự án WordPress. Các dạng số nhiều của Drupal thông qua msgid_plural được giữ nguyên là dạng số nhiều chứ không bị làm phẳng, điều này quan trọng vì các ngôn ngữ của Drupal có thể có từ một đến sáu biến thể số nhiều.
Cũng có một chế độ lỗi tinh tế hơn đáng nói. Các chuỗi của Drupal thường nhúng đánh dấu nội tuyến và liên kết bên trong văn bản có thể dịch được, ví dụ Read the <a href=":url">documentation</a> trong đó :url là một placeholder và các thẻ <a> phải tồn tại. Một dịch giả không hiểu cấu trúc có thể dịch thuộc tính href, bỏ thẻ đóng hoặc bản địa hóa tên placeholder. Context-Aware AI đọc toàn bộ chuỗi như một đơn vị, kết hợp với khóa token, giữ nguyên cả đánh dấu và hợp đồng :url trong khi chỉ dịch văn bản "documentation" dễ đọc giữa chúng.
Vòng lặp xuất, dịch và nhập lại
Quy trình làm việc lặp lại có ba giai đoạn, và drush làm cho việc xuất và nhập có thể viết script để bạn không phải nhấp qua giao diện người trị mỗi lần.
Bước 1: Xuất tệp PO
Bạn có thể xuất từ giao diện người dùng tại /admin/config/regional/translate bằng cách chọn ngôn ngữ và phạm vi xuất, hoặc thực hiện từ dòng lệnh. Mô-đun locale hiển thị chức năng xuất thông qua các dịch vụ dịch của Drupal, và hầu hết các nhóm đều viết script cho nó. Một lời gọi drush điển hình để kích hoạt nhập bản dịch (ngược lại, chúng ta sẽ sử dụng ở bước ba) trông như thế này:
# Re-import a translated PO file for Spanish, overwriting customized strings
drush locale:import es /var/www/translations/es-untranslated.po \
--type=customized --override=all
# Rebuild caches so the new strings render immediately
drush cache:rebuild
Về phía xuất, biểu mẫu xuất của quản trị viên tạo ra tệp .po; nhiều nhóm đóng gói dịch vụ xuất locale trong một lệnh Drush tùy chỉnh nhỏ để tự động hóa hoàn toàn. Dù bằng cách nào, bạn cũng sẽ có một tệp gettext .po tiêu chuẩn chứa các mục msgid chưa dịch của bạn.
Bước 2: Dịch tệp
Đây là giai đoạn AI thay thế hàng giờ chỉnh sửa thủ công. Tải tệp .po đã xuất lên một công cụ dịch trên nền tảng đám mây, chọn ngôn ngữ mục tiêu của bạn và để nó xử lý. Bởi vì các tệp .po của Drupal cho một trang web lớn thường vượt quá 10MB sau khi kết hợp core, contrib và themes, Smart Batching rất quan trọng ở đây: tệp được chia nhỏ, dịch và lắp ráp lại mà không cần bạn phải tự tay tách hoặc gặp giới hạn kích thước. Đầu ra là một tệp .po hoàn chỉnh với mọi msgstr được điền và mọi placeholder @count, %date và :url chính xác như lúc ban đầu.
Bước 3: Nhập lại vào Drupal
Nhập lại tệp đã dịch thông qua /admin/config/regional/translate hoặc thông qua lệnh drush locale:import được hiển thị ở trên, sau đó xây dựng lại bộ nhớ cache. Drupal hợp nhất các bản dịch vào các bảng locale của nó, và các chuỗi xuất hiện trên toàn trang web ngay lập tức. Chạy lại vòng lặp bất cứ khi nào bạn thêm một mô-đun hoặc cập nhật core, vì mỗi lần đều mang đến các chuỗi chưa dịch mới.
Một chi tiết nhập cần được thực hiện đúng: cờ --override kiểm soát liệu các bản dịch đến có thay thế các bản dịch hiện có hay không. Sử dụng --override=all khi bạn muốn tệp được dịch bằng AI là có thẩm quyền, hoặc một cài đặt thận trọng hơn nếu bạn đã tinh chỉnh thủ công một số chuỗi trong giao diện người dùng Drupal mà bạn không muốn bị ghi đè. Đối với hầu hết các quy trình tự động, việc coi tệp .po là nguồn sự thật và ghi đè mọi thứ giúp hệ thống dễ đoán: tệp trong kiểm soát phiên bản là những gì trang web hiển thị, chấm hết.
Đối với các trang web đa ngôn ngữ có nhiều ngôn ngữ mục tiêu, vòng lặp chạy một lần cho mỗi ngôn ngữ. Xuất bộ chưa dịch, dịch sang tiếng Đức, nhập; xuất lại, dịch sang tiếng Tây Ban Nha, nhập; và cứ thế. Bởi vì mỗi ngôn ngữ là một tệp .po độc lập, bạn có thể chạy chúng song song, và một công cụ dịch trên nền tảng đám mây xử lý chúng đồng thời biến những gì từng là một tuần làm việc của nhà thầu thành một buổi chiều.
PO của Drupal là một trong số nhiều định dạng
Cần lưu ý rằng gettext .po không phải là cách duy nhất Drupal xử lý dịch thuật. Cấu hình và các thực thể nội dung cũng có thể được trao đổi dưới dạng XLIFF, đây là tiêu chuẩn mà mô-đun Translation Management Tool (TMGMT) dựa vào cho các quy trình làm việc của nhà cung cấp dịch thuật chuyên nghiệp. Nếu quá trình bản địa hóa Drupal của bạn chạy qua XLIFF thay vì các tệp .po giao diện, các nguyên tắc bảo toàn placeholder là giống hệt nhau nhưng cấu trúc tệp khác nhau, và chúng tôi sẽ đề cập đến con đường đó trong bài dịch các tệp XLIFF cho Drupal, Symfony và Angular.
Tuy nhiên, đối với lớp dịch giao diện, .po vẫn là công cụ chính. Vòng lặp xuất, dịch bằng AI, nhập lại biến một công việc thủ công mất nhiều ngày thành vài phút xử lý, và miễn là công cụ bạn sử dụng thực sự hiểu các placeholder gettext, các hợp đồng @variable của bạn sẽ nguyên vẹn và trang web Drupal của bạn sẽ không bị lỗi ở mọi ngôn ngữ bạn xuất bản.
Sẵn sàng dịch các tệp
.pocủa Drupal mà không làm hỏng bất kỳ@variablenào? Dùng thử SimplePoTranslate miễn phí — không yêu cầu thẻ tín dụng. Gói miễn phí xử lý các tệp gettext.povà.pottiêu chuẩn với đầy đủ Syntax Locking, vì vậy các placeholder của Drupal của bạn sẽ đi qua chính xác như mã mong đợi.