Tính năngPluginGiáTài nguyên
Thay đổi ngôn ngữ
Tài nguyênCách Tự Động Hóa Dịch File .po Trong Quy Trình CI/CD Của Bạn

Cách Tự Động Hóa Dịch File .po Trong Quy Trình CI/CD Của Bạn

SimplePoTranslate Team9 tháng 6, 2026
Cách Tự Động Hóa Dịch File .po Trong Quy Trình CI/CD Của Bạn

Nhóm của bạn hợp nhất (merge) vào main mười bốn lần một ngày. Mỗi lần hợp nhất đó có thể thêm một chuỗi mới mà người dùng nhìn thấy – một nhãn nút, một thông báo lỗi, một chú giải công cụ. Và mỗi chuỗi đó ban đầu chỉ có bằng tiếng Anh. Trong quy trình phát hành của bạn, sẽ có lúc một người phải nhận ra các chuỗi mới, xuất chúng, dịch chúng, dán chúng lại và biên dịch lại. Người đó là một nút thắt cổ chai, và trong một nhóm giao hàng nhanh, nút thắt đó có nghĩa là người dùng tiếng Đức của bạn nhìn thấy các văn bản giữ chỗ (placeholder) tiếng Anh trong hai sprint.

Giải pháp là tự động hóa bản dịch trong quy trình CI/CD của bạn để các chuỗi mới được dịch ngay trong lần hợp nhất đã giới thiệu chúng – không cần con người tham gia vào lộ trình quan trọng cho các trường hợp thường xuyên. Điều này hoàn toàn có thể thực hiện được ngày nay, nhưng chỉ khi bạn tránh được cái bẫy mà hầu hết các nhóm mắc phải: tự tay thực hiện các lệnh gọi LLM thô sơ làm hỏng một cách âm thầm các văn bản giữ chỗ %s và cấu trúc .po của bạn. Hướng dẫn này sẽ trình bày một mẫu pipeline CI thực tế, một khung GitHub Actions hoạt động và các quyết định thiết kế – tính bất biến (idempotency), chỉ dịch các chuỗi mới (translate-only-new), cổng đánh giá (review gates) – những yếu tố phân biệt một pipeline hữu ích với một pipeline tạo ra các bản dựng bị lỗi.

Tại Sao Dịch Thủ Công Lại Là Nút Thắt Cổ Chai Của Quy Trình Phát Hành

Câu trả lời cho "tại sao không dịch trước mỗi lần phát hành" là vì thời gian không bao giờ khớp. Các chuỗi được các nhà phát triển thêm vào liên tục, nhưng việc dịch lại diễn ra theo đợt bởi một người khác theo một lịch trình khác. Khoảng cách giữa hai nhịp điệu này là nơi nợ dịch thuật của bạn tích lũy.

Vấn Đề Hai Nhịp Điệu

Hãy hình dung quy trình thủ công. Một nhà phát triển thêm __( 'Export to CSV', 'mytextdomain' ) và hợp nhất. Không ai tạo lại file .pot. Hai tuần sau, ai đó chạy wp i18n make-pot, nhận thấy bốn mươi chuỗi mới chưa được dịch (một số từ các nhà phát triển đã nghỉ phép), đoán ý định của một nửa trong số chúng, và gửi một file .po cho một người dịch. Bản dịch quay trở lại, được dán vào, và có thể các văn bản giữ chỗ vẫn còn nguyên vẹn hoặc có thể không. Trong khi đó, ba bản phát hành đã được gửi đi với các chuỗi đó bằng tiếng Anh.

Mỗi bước đều thủ công, theo đợt và dễ mắc lỗi. Mục tiêu của tự động hóa CI/CD là biến điều này thành một thứ chạy tự động khi hợp nhất, chỉ dịch những gì thực sự thay đổi và báo lỗi lớn khi có điều gì đó không ổn – biến dịch thuật từ một công việc định kỳ thành một phần vô hình của pipeline.

Mẫu Pipeline: Trích Xuất, So Sánh, Dịch, Commit

Ở cấp độ cao, một công việc dịch tự động chạy bốn bước khi hợp nhất vào main: tạo lại mẫu, phát hiện những gì mới, chỉ dịch những chuỗi đó và commit kết quả trở lại. Toàn bộ quy trình phải có tính bất biến (idempotent) – chạy nó trong một lần hợp nhất không có thay đổi chuỗi phải tạo ra không có khác biệt (diff) và không có nhiễu.

Trích Xuất và So Sánh

Bước một là trích xuất. Tạo lại file .pot từ mã nguồn hiện tại để nó phản ánh mọi chuỗi trong cơ sở mã:

wp i18n make-pot . languages/myplugin.pot

Bước hai là so sánh (diff). Đây là quyết định thiết kế quan trọng nhất trong toàn bộ pipeline. Bạn không muốn dịch lại mọi chuỗi trong mỗi lần hợp nhất – điều đó làm lãng phí các lệnh gọi API, có nguy cơ dịch lại các chuỗi mà con người đã sửa và tạo ra các khác biệt đánh giá khổng lồ. Thay vào đó, bạn hợp nhất file .pot mới vào mỗi file .po hiện có và chỉ dịch các mục hiện đang trống (các chuỗi thực sự mới):

# Merge new template into each locale, preserving existing translations.
# Newly-added strings appear with empty msgstr; --backup=none keeps the tree clean.
for po in languages/*.po; do
    msgmerge --update --backup=none "$po" languages/myplugin.pot
done

Sau msgmerge, chỉ các chuỗi hoàn toàn mới có msgstr trống. Mọi thứ đã được dịch trước đó đều không bị động chạm. Thuộc tính đó là điều làm cho pipeline có tính bất biến và giữ cho các khác biệt đánh giá của bạn nhỏ và dễ xem xét.

Dịch và Commit

Bước ba gửi các mục trống đó đến bước dịch. Bước bốn commit file .po đã cập nhật, biên dịch file .mo và tạo lại bất kỳ file JSON nào. Chúng ta sẽ kết nối tất cả những điều đó vào GitHub Actions tiếp theo.

Khung GitHub Actions

Đây là câu trả lời cho "điều này thực sự trông như thế nào trong một file workflow": một công việc được kích hoạt khi đẩy (push) lên main chạy chu trình trích xuất-so sánh-dịch-commit và mở một pull request với các kết quả thay vì commit trực tiếp vào main.

File Workflow

name: Translate on merge

on:
  push:
    branches: [ main ]

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install WP-CLI and gettext
        run: |
          sudo apt-get update && sudo apt-get install -y gettext
          curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
          sudo mv wp-cli.phar /usr/local/bin/wp && sudo chmod +x /usr/local/bin/wp

      - name: Regenerate template and merge into locales
        run: |
          wp i18n make-pot . languages/myplugin.pot
          for po in languages/*.po; do
            msgmerge --update --backup=none "$po" languages/myplugin.pot
          done

      - name: Translate only new (empty) strings
        env:
          TRANSLATE_API_KEY: ${{ secrets.TRANSLATE_API_KEY }}
        run: ./scripts/translate-new-strings.sh languages/

      - name: Compile .mo and JSON
        run: |
          wp i18n make-mo languages/
          wp i18n make-json languages/ --no-purge

      - name: Open pull request with translations
        uses: peter-evans/create-pull-request@v6
        with:
          branch: chore/auto-translations
          title: "chore: auto-translate new strings"
          commit-message: "chore: auto-translate new strings"

Nơi Công Việc Thực Sự Ẩn Giấu

Bước translate-new-strings.sh là nơi quá trình dịch thực sự diễn ra. Phiên bản ngây thơ của tập lệnh đó đọc từng mục trống, bắn nó vào một API của LLM từng chuỗi một và dán phản hồi trở lại. Phiên bản ngây thơ đó chính là cái bẫy, và điều đáng nói rõ là tại sao.

Tại Sao Các Lệnh Gọi LLM Tự Tay Làm Hỏng File Của Bạn

Câu trả lời ngắn gọn: các lệnh gọi LLM thô sơ coi các chuỗi .po của bạn là văn xuôi, và các chuỗi .po của bạn không phải là văn xuôi – chúng là dữ liệu có cấu trúc với các văn bản giữ chỗ, các dạng số nhiều và ngữ cảnh mà một lệnh gọi hoàn thành trò chuyện (chat-completion) sẽ vui vẻ phá hủy.

Sự Hỏng Hóc Văn Bản Giữ Chỗ Mà Bạn Sẽ Không Thấy Trong Các Bài Kiểm Tra

Gửi Deleted %d of %s files đến một điểm cuối trò chuyện chung và bạn có thể nhận lại Supprimé %d des %s fichiers (ổn) hoặc Supprimé %d de % s fichiers (một khoảng trắng đã lọt vào văn bản giữ chỗ, và giờ đây sprintf() sẽ báo lỗi trong thời gian chạy). Gửi một mục số nhiều và mô hình có thể gộp hai dạng thành một, làm hỏng các ngôn ngữ có nhiều hơn hai loại số nhiều. Gửi một chuỗi với <a href="%s"> và mô hình có thể dịch URL hoặc bỏ thẻ. Không có lỗi nào trong số này xuất hiện trong các bài kiểm tra của bạn trừ khi bạn kiểm tra cụ thể đầu ra được hiển thị trong mọi ngôn ngữ – chúng xuất hiện dưới dạng lỗi thời gian chạy trong môi trường sản xuất cho những người dùng mà bạn không thể đọc báo cáo lỗi từ họ.

Cái Bẫy Bảo Trì

You can try to defend against this with prompt engineering and regex post-processing, and many teams do. The problem is that you are now maintaining a brittle translation engine as a side project, re-discovering every placeholder edge case the Gettext ecosystem already solved. We catalog the specific ways variables get mangled - and how to prevent them - in dịch file PO mà không làm hỏng biến mã. The lesson there applies directly: the model quality is rarely the issue; the structural handling around it is.

Đưa Dịch Thuật Đám Mây Sử Dụng API Vào CI

Đây là lúc một dịch vụ dịch thuật dựa trên API thay thế việc đoán mò của tập lệnh translate-new-strings.sh của bạn. Thay vì tự tay thực hiện các lệnh gọi LLM và xử lý hậu kỳ bằng regex, bước CI của bạn tải file .po đã thay đổi lên một dịch vụ đã hiểu cấu trúc Gettext và trả về đầu ra sạch. Hình dạng pipeline vẫn giống hệt – trích xuất, so sánh, dịch, commit – nhưng bước giữa mong manh trở thành một lệnh gọi API duy nhất.

Lệnh Gọi API Thay Thế Tập Lệnh Của Bạn

SimplePoTranslate được xây dựng chính xác cho mục đích này. Nó cung cấp một API đám mây phù hợp cho tự động hóa và CI, vì vậy bước dịch của quy trình làm việc của bạn trở thành một yêu cầu chuyển file .po và nhận lại một file đã dịch, không cần lặp lại từng chuỗi. Tính năng Syntax Locking của nó tự động giữ các token %s, %1$s, {count}, HTML và mã code đúng vị trí – toàn bộ loại lỗi từ phần trước được xử lý bởi công cụ thay vì bằng regex mà bạn tự duy trì. Với hỗ trợ Gettext plural và msgctxt đầy đủ, các dạng số nhiều và ngữ cảnh vẫn tồn tại qua lại, điều mà một lệnh gọi hoàn thành trò chuyện không thể đảm bảo.

Tính Bất Biến và Cổng Đánh Giá Vẫn Là Của Bạn

Hai quyết định thiết kế vẫn thuộc về bạn bất kể bạn sử dụng công cụ nào. Thứ nhất, tính bất biến: tiếp tục chỉ dịch các mục trống sau msgmerge, để các lần hợp nhất không hoạt động không tạo ra khác biệt. Thứ hai, một cổng đánh giá: để công việc mở một pull request, như khung trên đã làm, thay vì commit trực tiếp vào main. Dịch máy rất tuyệt vời để đưa các chuỗi lên mạng nhanh chóng, nhưng một cái nhìn của con người trước khi hợp nhất sẽ bắt được những lỗi ngữ cảnh hiếm gặp – và một PR mang lại cho bạn cái nhìn đó mà không làm tắc nghẽn trường hợp phổ biến. Các nhóm đang xử lý nhiều ngôn ngữ hoặc nhiều trang web khách hàng sẽ nhận ra hình dạng này từ quy trình dịch thuật lý tưởng cho các đại lý, nơi cùng một mẫu tự động hóa-sau đó-đánh giá được mở rộng trên hàng chục dự án.

Kết Luận

Để tự động hóa dịch thuật trong CI/CD mà không làm hỏng các bản dựng, mẫu này là nhất quán: tạo lại file .pot khi hợp nhất, msgmerge nó vào từng ngôn ngữ để chỉ hiển thị các chuỗi mới, chỉ dịch các chuỗi đó và commit kết quả sau một cổng đánh giá pull request. Tính bất biến giữ cho các khác biệt của bạn sạch sẽ; cổng đánh giá giữ cho bản dịch tệ hiếm gặp không lọt vào môi trường sản xuất.

Phần cần làm đúng là bản thân bước dịch. Các lệnh gọi LLM tự tay sẽ làm hỏng các văn bản giữ chỗ và các dạng số nhiều theo những cách mà các bài kiểm tra của bạn sẽ không phát hiện được, và bạn sẽ dành nhiều thời gian hơn để duy trì công cụ dịch thuật hơn là mã tính năng mà nó phục vụ. Một công cụ dựa trên API với Syntax Locking loại bỏ toàn bộ chế độ lỗi đó, vì vậy pipeline của bạn dịch các chuỗi mới trong cùng một lần hợp nhất đã giới thiệu chúng – và người dùng không nói tiếng Anh của bạn sẽ không còn nhìn thấy các văn bản giữ chỗ tiếng Anh nữa.

Sẵn sàng tự động hóa dịch thuật trong pipeline của bạn mà không làm hỏng các văn bản giữ chỗ? Dùng thử SimplePoTranslate miễn phí — không yêu cầu thẻ tín dụng. Bắt đầu với gói miễn phí, xác thực API với các file .po của riêng bạn và kết nối nó vào CI khi bạn đã sẵn sàng.