Tính năngPluginGiáTài nguyên
Thay đổi ngôn ngữ
Tài nguyênCách dịch tệp XLIFF (Drupal, Symfony, Angular, iOS)

Cách dịch tệp XLIFF (Drupal, Symfony, Angular, iOS)

SimplePoTranslate Team16 tháng 4, 2026
Cách dịch tệp XLIFF (Drupal, Symfony, Angular, iOS)

Tuần trước, một nhà phát triển Drupal đã đăng lên Stack Overflow một câu chuyện diễn ra hàng nghìn lần mỗi năm trong các nhóm bản địa hóa doanh nghiệp. Nhóm của cô ấy đã xuất một tệp XLIFF 40MB từ trang Drupal của họ. Cô ấy mở tệp bằng trình chỉnh sửa văn bản, dán các đoạn vào Google Translate, rồi ghép lại tệp, nhập ngược lại vào Drupal – và một nửa số trang không thể hiển thị vì các chuỗi đã dịch chứa XML bị lỗi định dạng, các ký tự thoát sai vị trí và các thẻ <g> bị hỏng do định dạng nội tuyến đã bị phá hủy.

XLIFF là tiêu chuẩn bản địa hóa doanh nghiệp vì một lý do. Nó dựa trên XML, không phụ thuộc vào công cụ và hỗ trợ siêu dữ liệu phong phú mà các dự án dịch thuật nghiêm túc cần: trạng thái dịch, các bản dịch thay thế, ghi chú giữa người dịch và nhà phát triển, và đánh dấu nội tuyến có cấu trúc. Nhưng chính sự linh hoạt của nó lại khiến nó dễ bị hỏng, và các công cụ xử lý tệp .po một cách an toàn thường thất bại với XLIFF.

Hướng dẫn này sẽ giải thích điều gì làm cho XLIFF khác biệt, tại sao các phương pháp dịch thông thường lại phá vỡ nó, và cách đúng đắn để dịch các tệp XLIFF cho Drupal, Symfony, Angular và iOS – bốn nền tảng mà XLIFF được sử dụng phổ biến nhất vào năm 2026.

XLIFF là gì (và tại sao các nhóm doanh nghiệp sử dụng nó)

XLIFF là viết tắt của XML Localization Interchange File Format (Định dạng tệp trao đổi bản địa hóa XML). Đây là một tiêu chuẩn OASIS được thiết kế đặc biệt để di chuyển nội dung dịch giữa các công cụ – hệ thống quản lý nội dung, cơ sở dữ liệu bộ nhớ dịch, công cụ CAT và nền tảng bản địa hóa. Không giống như các tệp Gettext .po (lưu trữ các cặp khóa-giá trị phẳng) hoặc các tệp ngôn ngữ JSON (lồng nhau tùy ý), XLIFF là một tài liệu XML có cấu trúc với một lược đồ tiêu chuẩn hóa.

XLIFF 1.2 so với XLIFF 2.0

Có hai phiên bản tồn tại và chúng không hoàn toàn tương thích.

XLIFF 1.2 là phiên bản cũ hơn, được triển khai rộng rãi hơn. Nó sử dụng các phần tử <trans-unit> để bao bọc nội dung có thể dịch, với các phần tử con <source><target>. Định dạng nội tuyến sử dụng các thẻ ghép nối <g>, <x>, và <bpt> / <ept>. Công cụ Quản lý Dịch thuật của Drupal và nhiều nền tảng cũ hơn vẫn xuất 1.2.

XLIFF 2.0 là bản sửa đổi năm 2014, đơn giản và gọn gàng hơn. Nó sử dụng <unit><segment> với <source><target>. Đánh dấu nội tuyến sử dụng <pc> (mã ghép nối) và <ph> (phần giữ chỗ). Thành phần dịch thuật của Symfony và các bản xuất iOS hiện đại mặc định là 2.0.

Một công cụ dịch thuật xử lý 1.2 không tự động xử lý 2.0. Từ vựng thẻ khác nhau và các quy tắc thoát cũng khác một chút. Luôn kiểm tra phiên bản nền tảng của bạn xuất ra trước khi chọn quy trình dịch thuật.

Giải phẫu một đơn vị XLIFF

Một trans-unit XLIFF 1.2 tối thiểu trông như thế này:

<trans-unit id="msg_welcome" datatype="plaintext">
  <source>Welcome, <g id="1">%name%</g>!</source>
  <target state="needs-translation">Welcome, <g id="1">%name%</g>!</target>
  <note>Displayed on the homepage after login</note>
</trans-unit>

Thẻ <g id="1"> bao bọc một biến giữ chỗ. Thuộc tính state cho nền tảng biết chuỗi này cần được dịch. Thẻ <note> là một gợi ý cho nhà phát triển. Một người dịch hiểu XLIFF sẽ tạo ra:

<target state="translated">¡Bienvenido, <g id="1">%name%</g>!</target>

Một người dịch coi tệp là văn bản thuần túy có thể tạo ra bất kỳ biến thể bị lỗi nào sau đây:

<target>¡Bienvenido, <g id="1">%nombre%</g>!</target>
<target>¡Bienvenido, &lt;g id="1"&gt;%name%&lt;/g&gt;!</target>
<target>¡Bienvenido, %name%!</target>

Mỗi lỗi này làm hỏng quá trình nhập khác nhau. Lỗi thứ nhất đổi tên biến. Lỗi thứ hai thoát XML. Lỗi thứ ba loại bỏ hoàn toàn thẻ định dạng.

Giải pháp tồi (Tại sao bạn không thể chỉ dịch XML)

Phần lớn các nhóm bắt đầu với ba cách tiếp cận tương tự và mất vài ngày trước khi từ bỏ.

Đưa XLIFF cho AI thông thường

Sao chép tệp, dán vào Claude hoặc ChatGPT, yêu cầu dịch. Mô hình thường thực hiện khá tốt với văn bản nhưng xử lý các thẻ XLIFF không nhất quán. Đôi khi nó giữ lại các thẻ <g>, đôi khi nó dịch thuộc tính id, đôi khi nó loại bỏ hoàn toàn. Xác thực thất bại. Quá trình nhập của bạn báo lỗi phân tích XML.

Sử dụng công cụ CAT không hỗ trợ XLIFF

Các công cụ như Poedit được xây dựng cho định dạng .po. Chúng có thể mở XLIFF nhưng coi đó là một vùng chứa văn bản chung. Các thẻ nội tuyến không bị khóa. Các phần giữ chỗ không được bảo vệ. Bạn sẽ nhận được bản dịch trông ổn trong trình chỉnh sửa nhưng lại thất bại trong việc xác thực lược đồ khi nhập.

Viết một tập lệnh tùy chỉnh

Nhóm của bạn viết một tập lệnh Node hoặc Python để phân tích XLIFF bằng xml2js, trích xuất các chuỗi nguồn, gọi Google Translate và ghi lại các chuỗi đích. Nó hoạt động cho 90% chuỗi. 10% còn lại – các chuỗi có định dạng lồng nhau, nhóm số nhiều hoặc các ký tự đặc biệt – bị lỗi theo những cách mà chỉ xuất hiện sau khi bạn đã triển khai.

Chế độ lỗi "định dạng linh hoạt gặp người dịch ngây thơ" tương tự cũng ảnh hưởng đến các tệp JSON i18next và Gettext .po. Hướng dẫn của chúng tôi về dịch tệp JSON i18next cho React và Next.js và bài viết của chúng tôi về cách dịch tệp .po mà không làm hỏng biến mã đề cập đến các vấn đề song song cho các định dạng đó.

Cách đúng: Xử lý XLIFF có nhận thức cú pháp

Một quy trình dịch XLIFF phù hợp tuân theo các nguyên tắc tương tự như công cụ PO của chúng tôi, được điều chỉnh cho XML.

Phân tích, không dùng Regex

Xem XLIFF như một tài liệu có cấu trúc. Phân tích nó bằng một trình phân tích XML thực sự, xây dựng một cây và duyệt qua các phần tử <trans-unit> (hoặc <unit> cho 2.0). Cố gắng dùng regex để khớp nội dung nguồn và đích là con đường nhanh nhất dẫn đến các tệp bị hỏng.

Khóa thẻ nội tuyến trước khi dịch

Mỗi thẻ <g>, <x>, <bpt>, <ept>, <ph>, <pc> bên trong thẻ <source> phải được giữ nguyên theo vị trí và thuộc tính id. Thay thế chúng bằng các phần giữ chỗ số trước khi gửi văn bản đến LLM, sau đó chèn lại các thẻ gốc với các thuộc tính của chúng sau khi bản dịch được trả về.

Tôn trọng máy trạng thái

Các đơn vị XLIFF có các thuộc tính trạng thái: new, needs-translation, translated, reviewed, final, signed-off. Một quy trình chỉ nên dịch các đơn vị ở trạng thái new hoặc needs-translation, và đặt trạng thái đầu ra thành translated (không phải final – một người đánh giá vẫn nên xác minh).

Bảo toàn cấu trúc ngoài các đơn vị dịch thuật

Các tệp XLIFF chứa tiêu đề, siêu dữ liệu, thuộc tính cấp tệp, ghi chú và các bản dịch thay thế (<alt-trans>). Những thứ này phải được giữ nguyên không thay đổi trong suốt quá trình khứ hồi. Loại bỏ hoặc sắp xếp lại chúng sẽ phá vỡ khả năng tương thích khứ hồi với nền tảng nguồn.

Xác thực trước khi bàn giao

Trước khi trả về XLIFF đã dịch, hãy xác thực theo lược đồ. XLIFF 1.2 có XSD chính thức. XLIFF 2.0 có XSD riêng. Một công cụ không thể tự xác thực là một công cụ sẽ giao cho bạn các tệp bị lỗi.

Các ghi chú cụ thể theo nền tảng

Mỗi nền tảng chính sử dụng XLIFF đều có những đặc điểm riêng đáng biết.

Drupal

Công cụ Quản lý Dịch thuật (TMGMT) của Drupal xuất XLIFF 1.2. Các loại nội dung bao gồm các nút (trang, bài viết), thuật ngữ phân loại và cấu hình. TMGMT bao bọc mỗi trường có thể dịch trong một <trans-unit> riêng biệt với định dạng ID đặc trưng của Drupal (fieldname:delta:format).

Lưu ý: Drupal lưu trữ thông tin định dạng văn bản (HTML đã lọc, HTML đầy đủ, văn bản thuần túy) cùng với nội dung. Bản dịch phải giữ nguyên đánh dấu HTML khi định dạng cho phép, hoặc chuyển thành văn bản thuần túy khi định dạng không cho phép. Quy trình của bạn cần có nhận thức theo từng trường.

Symfony

Thành phần dịch thuật của Symfony sử dụng XLIFF 2.0 theo mặc định (kể từ Symfony 4). Các chuỗi nằm trong translations/messages.xx.xliff. Symfony hỗ trợ định dạng tin nhắn ICU bên trong XLIFF, nghĩa là một đơn vị có thể chứa các cấu trúc {count, plural, one {...} other {...}}.

Lưu ý: Các danh mục số nhiều ICU bên trong XLIFF cần được bảo vệ kép. Các thẻ XML vẫn còn nguyên vẹn, VÀ các từ khóa ICU (plural, one, other, =0) không được dịch. Nhiều công cụ XLIFF xử lý một lớp nhưng không xử lý cả hai.

Angular i18n

Angular xuất XLIFF 1.2 hoặc 2.0 thông qua lệnh ng extract-i18n. Các tệp chứa các chuỗi mẫu thành phần, với các thẻ <x> đại diện cho các biểu thức và nội suy Angular như {{ count }}.

Lưu ý: Angular sử dụng xung đột băm id trên các chuỗi nguồn giống hệt nhau. Một bản dịch phải duy trì chính xác ID đơn vị, nếu không Angular không thể khớp chúng khi nhập. Việc đổi tên thuộc tính id trong quá trình xử lý sẽ gây lỗi ngay lập tức.

iOS (Xuất từ Xcode)

Xcode xuất XLIFF 1.2 để bản địa hóa ứng dụng thông qua Product > Export Localizations. Các chuỗi đến từ Localizable.strings, các mục trong Info.plist, storyboard và XIB. Các quy tắc số nhiều của iOS nằm trong các tệp .stringsdict được xuất dưới dạng các trans-unit bổ sung.

Lưu ý: Các chuỗi storyboard của iOS tham chiếu ID phần tử UI. Những ID này không được thay đổi. Ngoài ra, Xcode yêu cầu thuộc tính target-language phải khớp chính xác với định dạng ngôn ngữ dự kiến của nó (ví dụ: es, không phải es-ES, trong một số ngữ cảnh) nếu không nó sẽ âm thầm bỏ qua quá trình nhập.

Dịch XLIFF với SimplePoTranslate

SimplePoTranslate hỗ trợ XLIFF trên các gói Pro và Lifetime. Quy trình làm việc tương tự như đối với các tệp .po.

1. Xuất tệp XLIFF của bạn

Từ nền tảng nguồn của bạn, xuất một hoặc nhiều tệp .xliff. Đối với Drupal, hãy sử dụng hành động xuất của TMGMT. Đối với Symfony, tìm translations/messages.en.xliff. Đối với Angular, chạy ng extract-i18n --format=xlf2. Đối với Xcode, sử dụng tính năng xuất Localization.

2. Tải lên SimplePoTranslate

Kéo tệp vào bảng điều khiển. Nền tảng tự động phát hiện phiên bản XLIFF (1.2 hoặc 2.0), phân tích cấu trúc và xác định các đơn vị có thể dịch. Chọn ngôn ngữ đích và tông giọng của bạn.

3. Dịch thuật có nhận thức cú pháp

Các thẻ nội tuyến, tham số ICU, phần giữ chỗ và ID đơn vị được khóa trước khi dịch. Công cụ AI cơ bản chỉ nhìn thấy văn bản rõ ràng với ngữ cảnh. Văn bản đã dịch được chèn lại vào cấu trúc gốc chính xác, trạng thái được cập nhật và tệp được xác thực theo lược đồ XLIFF trước khi bàn giao.

4. Tải xuống và nhập

Tải xuống tệp XLIFF đã dịch (cùng với các tệp .po, .json.php tương đương nếu bạn cần đa nền tảng). Nhập vào nền tảng nguồn của bạn. Xác thực bằng cách hiển thị một vài trang hoặc chế độ xem đã dịch trước khi triển khai.

# Angular example
ng extract-i18n --format=xlf2 --output-path=src/locale
# upload src/locale/messages.xlf to SimplePoTranslate
# download messages.es.xlf
# reference in angular.json i18n configuration
ng build --localize

5. Tích hợp vào CI

Khi bạn tin tưởng vào quy trình, hãy tự động hóa nó. Xuất XLIFF trong mỗi bản phát hành, gửi qua API, tải xuống các tệp đã dịch, commit vào repo, triển khai. Đây là cùng một mẫu thân thiện với CI mà nhiều công ty sử dụng để dịch .po của WordPress – xem bài viết của chúng tôi về dịch thuật dựa trên đám mây mà không làm hỏng trang web để biết mẫu kiến trúc.

Tổng hợp

XLIFF là công cụ phù hợp cho công việc bản địa hóa nghiêm túc – có cấu trúc, không phụ thuộc vào công cụ và đủ phong phú để mang siêu dữ liệu dự án qua các hệ thống. Nhưng cấu trúc XML của nó cũng rất dễ vỡ. Mỗi thẻ, thuộc tính và giá trị trạng thái đều có trọng lượng ngữ nghĩa, và một người dịch không hiểu XLIFF dưới dạng định dạng sẽ làm hỏng tệp của bạn theo những cách có thể không phát hiện được cho đến khi quá trình nhập thất bại hoặc người dùng báo cáo UI bị hỏng.

Cách tiếp cận an toàn là nhận thức cú pháp: phân tích XML, khóa các phần tử cấu trúc, chỉ dịch các bề mặt văn bản có ngữ cảnh, xác thực theo lược đồ trước khi bàn giao. Điều này đúng cho dù bạn đang triển khai một trang Drupal, một API Symfony, một SPA Angular hay một ứng dụng iOS. Nền tảng có thể khác nhau, nhưng nguyên tắc XLIFF thì không.

Sẵn sàng dịch các tệp XLIFF cho Drupal, Symfony, Angular hoặc iOS mà không làm hỏng thẻ? Thử SimplePoTranslate miễn phí – không cần thẻ tín dụng. Tải lên .xliff, tải xuống các bản dịch an toàn, nhập vào nền tảng của bạn.