Cách dịch tệp HTML mà không làm hỏng thẻ, thuộc tính hoặc liên kết
Cần dịch gì trong tệp HTML, cần giữ nguyên gì và cách kiểm tra. Kèm trang mẫu, công cụ kiểm tra miễn phí và bài kiểm tra LLM cục bộ 9 lần chạy.

Để dịch một tệp HTML, hãy dịch phần văn bản mà người đọc nhìn thấy và các thuộc tính chứa từ ngữ dành cho người đọc, chẳng hạn như alt, title, placeholder, aria-label và phần mô tả meta của trang. Hãy để nguyên phần đánh dấu: tên thẻ, href, src, id, class, script, style và bất kỳ nội dung nào được đánh dấu translate="no". Sau đó, thay đổi một giá trị dễ bị bỏ qua, thuộc tính lang trên phần tử <html>, để trình duyệt, trình đọc màn hình và công cụ tìm kiếm biết trang hiện đang ở ngôn ngữ nào.
Giữ nguyên các thẻ hóa ra lại là phần dễ dàng. Chúng tôi đã dịch một trang trợ giúp HTML dài 59 dòng sang tiếng Trung Giản thể chín lần bằng một mô hình cục bộ, sử dụng ba phương pháp và kiểm tra mọi kết quả đầu ra bằng một script. Mọi lần chạy đều giữ nguyên mọi thẻ, liên kết và ID. Điều không ổn lại tinh vi hơn: mô hình đã dịch một dòng bên trong khối mã <pre> trong cả sáu lần chạy gửi toàn bộ tệp, nó để nguyên aria-label của thanh điều hướng bằng tiếng Anh trong cả sáu lần, và phương pháp giữ phần đánh dấu an toàn nhất về mặt thiết kế, dịch từng mảnh văn bản một, lại tạo ra một câu hướng dẫn người đọc làm sai trong cả ba lần chạy của nó.
Trả lời nhanh: Cần dịch gì và giữ nguyên gì
| Phần của tệp | Ví dụ từ mẫu của chúng tôi | Có dịch không? |
|---|---|---|
| Văn bản hiển thị | tiêu đề, đoạn văn, ô bảng, văn bản liên kết, <label> | Có |
<title> và mô tả meta | <title>Export Your Library | Shelfmark Help</title> | Có. Cả hai đều xuất hiện trong kết quả tìm kiếm và tab trình duyệt. |
og:title và các thẻ meta mạng xã hội khác | <meta property="og:title" content="Export Your Library"> | Có, chỉ giá trị content |
alt, title, placeholder, aria-label | alt="The Export dialog with EPUB selected", aria-label="Breadcrumb" | Có |
lang trên <html> | <html lang="en"> | Thay đổi thành ngôn ngữ đích, ví dụ zh-Hans |
| Tên thẻ và thuộc tính | <a>, <img>, width, bản thân aria-label | Không |
href, src, id, class, for, name, type, data-* | href="#choose-format", id="q" | Không |
<code>, <pre>, <script>, <style> | shelfmark export --format epub | Không. Quyết định riêng về chú thích mã và đầu ra mẫu. |
| Văn bản do CSS thiết lập | .note::before { content: "Note: "; } | Có, nhưng nó nằm trong stylesheet, vì vậy hãy lên kế hoạch cho việc đó |
| Dữ liệu có cấu trúc JSON-LD | "name": "Export your Shelfmark library" | Dịch các giá trị name và description; giữ nguyên khóa và JSON hợp lệ |
Các phần tử có translate="no" | <span translate="no">Shelfmark</span> | Không |
| Chú thích HTML | <!-- Generated by the help-center build... --> | Tùy chọn. Người đọc không bao giờ nhìn thấy chúng. |
| Tham chiếu ký tự | <library>, , © | Giữ nguyên các ký tự đã thoát. < không được trở thành < thật. |
Danh sách này không phải do chúng tôi phát minh. Phần về thuộc tính translate trong Tiêu chuẩn HTML định nghĩa "các thuộc tính có thể dịch": title trên mọi phần tử, alt trên hình ảnh, placeholder trên ô nhập liệu, content trên các phần tử meta có tên được biết là có thể dịch, và lang, mà theo đó phải được thay đổi để phù hợp với ngôn ngữ mới. Tài liệu cũng nêu aria-label của ARIA như một ví dụ về thuộc tính mà các đặc tả khác có thể bổ sung, và nói rằng trong một phần tử translate="no", văn bản và giá trị thuộc tính "phải được giữ nguyên khi trang được bản địa hóa."
Những gì chúng tôi đã kiểm tra
Chúng tôi đã viết sample-source.html, một trang trung tâm trợ giúp cho cùng một ứng dụng đọc sách hư cấu, Shelfmark, mà chúng tôi đã sử dụng trong bài kiểm tra dịch Markdown. Nó có một ví dụ cho mỗi hàng trong bảng trên, cùng một vài cái bẫy:
- một câu được chia cắt bởi các thẻ nội tuyến: "Trước khi xuất, hãy sao lưu ghi chú của bạn. Việc xuất sẽ sao chép sách của bạn, nhưng không xóa bất cứ thứ gì khỏi Shelfmark," với tên sản phẩm nằm trong
translate="no"; - một câu có hai phần tử
<code>nội tuyến mà thứ tự của chúng rất quan trọng: "Nhập đường dẫn đến thư mục<library>sau--out"; - một khối
<pre><code>với một lệnh và một dòng đầu ra mẫu,# Export finished: 128 books; - một quy tắc CSS chèn từ "Note:" trước một đoạn văn;
- một liên kết trong trang đến
#choose-format, một liên kếtmailto:, một biểu mẫu tìm kiếm và một khối JSON-LD.
Sau đó, chúng tôi yêu cầu một mô hình cục bộ dịch nó sang tiếng Trung giản thể theo ba cách:
- Toàn bộ tệp. Dán toàn bộ tệp và yêu cầu trả lại tệp đã dịch.
- Có hướng dẫn. Tương tự, cộng thêm tám quy tắc: giữ nguyên mọi tên thẻ và thuộc tính, không thay đổi
href,src,id,classvà các giá trị tương tự, dịch các thuộc tính văn bản và thẻ meta được liệt kê, để yên<code>,<pre>,<script>, và<style>ngoại trừnamevàdescriptioncủa JSON-LD, tôn trọngtranslate="no", giữ nguyên tham chiếu ký tự và chú thích, và đặtlangthànhzh-Hans. - Phân đoạn. Cách tiếp cận của các công cụ trích xuất văn bản từ HTML: một script chia tệp thành thẻ và văn bản, bỏ qua
<code>,<pre>,<script>,<style>, và các phần tửtranslate="no", gửi các phần văn bản còn lại và thuộc tính văn bản đến mô hình dưới dạng danh sách JSON được đánh số, và ghi các bản dịch trở lại phần đánh dấu chưa bị động đến. Nó cũng tự đặtlang="zh-Hans".
Mô hình là Qwen 3.6 27B (Q4_K_M) trong LM Studio, với chế độ suy nghĩ tắt và nhiệt độ 0.3, trên Apple M4 Max với 64 GB bộ nhớ. Chúng tôi đã chạy mỗi phương pháp ba lần, tổng cộng chín lần chạy, vào ngày 27 tháng 10 năm 2026. Script là run_llm_html_test.py, và cả chín đầu ra đều được công bố nguyên bản; README liệt kê mọi tệp. Nếu bạn chưa từng thiết lập mô hình cục bộ, hướng dẫn dịch bằng LLM cục bộ của chúng tôi sẽ đề cập đến các cài đặt.
Đây là một bài kiểm tra nhỏ với một mô hình, một cặp ngôn ngữ và một trang. Nó cho thấy những vấn đề nào xảy ra và cách phát hiện chúng. Nó không xếp hạng các mô hình hay công cụ.
Kết quả: Phần đánh dấu vẫn sống sót; ba quyết định thì không
Chúng tôi đã kiểm tra mọi kết quả đầu ra bằng check_html_translation.py, một công cụ kiểm tra chỉ sử dụng thư viện chuẩn của Python. Toàn bộ kết quả đầu ra nằm trong check-results.txt, và results.csv có một dòng cho mỗi lần chạy.
| Kiểm tra | Toàn bộ tệp (3 lần chạy) | Có hướng dẫn (3 lần chạy) | Phân đoạn (3 lần chạy) |
|---|---|---|---|
Cùng 58 thẻ theo thứ tự; mọi href, src, id, class không thay đổi | 3 trên 3 | 3 trên 3 | 3 trên 3 |
Văn bản translate="no" được giữ nguyên, liên kết trong trang vẫn hoạt động, <library> vẫn được thoát | 3 trên 3 | 3 trên 3 | 3 trên 3 |
Dòng đầu ra mẫu bên trong <pre> đã được dịch | 3 trên 3 | 3 trên 3 | 0 trên 3 (bị bỏ qua theo thiết kế) |
CSS content: "Note: " đã được dịch | 3 trên 3 | 0 trên 3 | 0 trên 3 (bị bỏ qua theo thiết kế) |
JSON-LD name và description đã được dịch | 3 trên 3 | 3 trên 3 | 0 trên 3 (bị bỏ qua theo thiết kế) |
aria-label="Breadcrumb" đã được dịch | 0 trên 3 | 0 trên 3 | 3 trên 3 |
Câu có hai phần tử <code> nội tuyến nói đúng ý | 3 trên 3 | 3 trên 3 | 0 trên 3 |
| Khoảng trắng giữa văn bản tiếng Trung qua một thẻ nội tuyến | không có | 0, 5 và 4 | 6 trong mỗi lần chạy |
lang trên <html> | zh-CN (không được yêu cầu) | zh-Hans | zh-Hans (do script đặt) |
Cả chín lần chạy đều giữ nguyên 58 thẻ theo cùng thứ tự, mọi href, src, id và class, đích liên kết trong trang, chú thích, <library> đã thoát, và tên sản phẩm bên trong translate="no". Nếu bạn lo rằng một mô hình sẽ làm hỏng đánh dấu của một trang đơn giản, thì nó đã không làm vậy. Vấn đề nằm ở việc cần dịch những gì.
1. Đầu ra mẫu bên trong <pre> bị dịch
Khối mã trong mẫu của chúng tôi kết thúc bằng một dòng đầu ra chương trình:
<pre><code>shelfmark export --format epub --covers --out ~/Books/export
# Export finished: 128 books</code></pre>
Trong cả sáu lần chạy toàn tệp và có hướng dẫn, mô hình trả về # 导出完成:128 本书 trên dòng đó, kể cả ba lần mà lời nhắc nói không được thay đổi bất cứ thứ gì bên trong <pre>. Bản thân lệnh không bao giờ bị động đến. Mô hình coi dòng đó là chú thích, và dịch chú thích là một lựa chọn hợp lý trong một bài hướng dẫn. Nhưng dòng này là thứ chương trình in ra, và người đọc so sánh nó với terminal của họ sẽ thấy tiếng Anh. Hãy quyết định trước khi dịch xem đầu ra mẫu và chú thích mã có được dịch hay không, và nói cho công cụ biết, hoặc bảo vệ hoàn toàn các khối <pre>.
Các lần chạy toàn tệp cũng dịch content: "Note: " trong CSS trong khối <style>, trong khi các lần chạy có hướng dẫn, được bảo để yên <style>, giữ nguyên tiếng Anh. Cả hai đều không sai tự thân. Dịch bảng định kiểu là đúng cho một trang mà CSS nằm nội tuyến, và sai cho một trang web mà một bảng định kiểu dùng chung phục vụ mọi ngôn ngữ. Dù thế nào, đó là quyết định mà ai đó phải đưa ra, không phải chi tiết để mô hình đoán.
2. Nhãn trợ năng bị bỏ qua
Điều hướng breadcrumb là <nav aria-label="Breadcrumb">. Trình đọc màn hình đọc nhãn đó; người đọc có thị lực không bao giờ thấy nó. Trong cả sáu lần chạy toàn tệp và có hướng dẫn, nó vẫn ở tiếng Anh, mặc dù lời nhắc có hướng dẫn đã liệt kê aria-label trong số các thuộc tính cần dịch. Trong một lần chạy có hướng dẫn, aria-label="Search" của nút tìm kiếm cũng vẫn ở tiếng Anh.
Phương pháp phân đoạn dịch nó mọi lần, vì script của nó thu thập mọi giá trị aria-label, alt, title và placeholder và yêu cầu từng giá trị một cách rõ ràng. Đó là lập luận mạnh nhất cho việc trích xuất các thuộc tính văn bản một cách có chủ đích thay vì hy vọng mô hình chú ý đến chúng.
3. Dịch từng mảnh giữ nguyên thẻ nhưng làm hỏng câu
Phương pháp phân đoạn an toàn cho đánh dấu về mặt cấu trúc: mô hình không bao giờ nhìn thấy thẻ, nên không thể làm hỏng thẻ. Nó đã vượt qua mọi kiểm tra cấu trúc trong cả ba lần chạy. Nó cũng tạo ra bản dịch duy nhất trong bài kiểm tra đưa ra hướng dẫn sai cho người đọc.
Câu tiếng Anh là "Type the path to the <library> folder after --out." Thẻ nội tuyến <code> chia câu thành ba mảnh: "Type the path to the", "folder after", và dấu chấm. Tiếng Trung sắp xếp các từ này theo thứ tự khác, nên người dịch cần di chuyển hai phần tử mã. Phương pháp phân đoạn không thể di chuyển chúng. Cả ba lần chạy đều đảo ngược hướng dẫn. Lần chạy 2 tạo ra kết quả này (lần chạy 1 và 3 dùng 后 thay vì 之后, với nghĩa tương tự):
在 <code><library></code> 之后输入 <code>--out</code>文件夹的路径。
Câu đó có nghĩa là "sau <library>, nhập đường dẫn của thư mục --out," ngược lại với hướng dẫn. Cả sáu lần chạy toàn tệp và có hướng dẫn đều di chuyển các phần tử mã và làm đúng:
在 <code>--out</code> 后面输入 <code><library></code> 文件夹的路径。
Việc tách tương tự để lại khoảng trắng thừa nơi thẻ gặp văn bản tiếng Trung, chẳng hạn như 前往 <b>设置</b> và <b>书库</b> ,, trong cả ba lần chạy phân đoạn, sáu chỗ mỗi lần. Trình duyệt hiển thị chúng dưới dạng khoảng trống nhìn thấy được, kể cả trước dấu câu tiếng Trung. Các lần chạy toàn tệp không có; hai trong ba lần chạy có hướng dẫn có bốn hoặc năm chỗ.
Một trình kiểm tra cấu trúc không thể phát hiện câu bị đảo ngược, vì mọi thẻ đều ở đúng vị trí cũ. Trình kiểm tra của chúng tôi báo cáo khi mã nội tuyến thay đổi thứ tự, điều này là bình thường với nhiều ngôn ngữ, nhưng cảnh báo đó không thể phân biệt đúng sai. Trong bài kiểm tra này, nó kích hoạt trên cả sáu bản dịch đúng và im lặng với ba bản dịch sai, vì những bản sai giữ nguyên thứ tự tiếng Anh. Chỉ người đọc câu mới có thể phân biệt. Cách khắc phục là gửi toàn bộ câu, cùng với các thẻ nội tuyến của chúng, đến người dịch, đúng như các lần chạy toàn tệp đã làm, và kiểm tra cấu trúc sau đó.
Những khác biệt nhỏ hơn
lang: các lần chạy toàn tệp tự đổi thànhzh-CN. Các lần chạy có hướng dẫn dùngzh-Hansnhư yêu cầu. Cả hai đều là thẻ ngôn ngữ hợp lệ;zh-Hanschỉ hệ chữ (tiếng Trung giản thể),zh-CNchỉ khu vực. Hướng dẫn về khai báo ngôn ngữ của W3C khuyến nghị khai báo ngôn ngữ trên phần tử<html>chứ không dùng thẻ metaContent-Language.- JSON-LD: các lần chạy toàn tệp và có hướng dẫn đã dịch các giá trị
namevàdescriptionvà giữ JSON hợp lệ. Tập lệnh phân đoạn của chúng tôi bỏ qua nội dung<script>, nên dữ liệu có cấu trúc của nó vẫn bằng tiếng Anh, đây cũng là cách một công cụ bỏ qua tập lệnh sẽ hoạt động. - Tham chiếu ký tự: các lần chạy toàn tệp và có hướng dẫn giữ nguyên
›, ,©, và tham chiếu emoji như đã viết. Năm trong sáu lần chạy đó đã viết lại khoảng2–5bằng từ tiếng Trung (2 到 5 hoặc 2 至 5); một lần chạy có hướng dẫn viết dấu gạch ngang thông thường thay vì tham chiếu, mặc dù lời nhắc của nó nói giữ nguyên tham chiếu. Tập lệnh phân đoạn của chúng tôi giải mã tất cả và viết lại ký tự, hiển thị giống nhau. Điều quan trọng,<library>bên trong<code>, vẫn được thoát trong cả chín lần chạy.
Trước khi dịch: Chuẩn bị tệp
- Đánh dấu những gì không được thay đổi. Đặt
translate="no"trên tên sản phẩm, số model, chuỗi giống mã trong văn xuôi, và bất cứ thứ gì khác phải giữ nguyên. Đây là một phần của HTML, không tốn kém gì, và mô hình đã tôn trọng nó trong cả sáu lần chạy gửi toàn bộ tệp. Các công cụ phân đoạn đọc nó, như tập lệnh của chúng tôi, bỏ qua hoàn toàn những phần tử đó. Hướng dẫn không dịch của chúng tôi đề cập cách quyết định những gì nằm trong danh sách đó. - Quyết định chính sách mã. Chú thích mã có được dịch không? Kết quả mẫu có được dịch không? Bảng kiểu có được chia sẻ giữa các ngôn ngữ không? Viết câu trả lời, cùng với những tên không được thay đổi, vào một bảng thuật ngữ dịch, và đưa nó cho người hoặc công cụ dịch.
- Giữ ID bằng ngôn ngữ nguồn. Các liên kết trong trang trỏ đến giá trị
id. Nếu ai đó dịch mộtid, mọi liên kết đến nó sẽ hỏng. Không lần chạy nào của chúng tôi làm vậy, nhưng một người dịch "sốt sắng" bản địa hóa neo sẽ làm hỏng. - Thu thập văn bản ẩn. Liệt kê các thuộc tính chứa từ ngữ,
alt,title,placeholder,aria-label,valuetrên nút, thẻ meta, và JSON-LD, để chúng được kiểm tra và không bị bỏ quên. - Không dịch chuỗi JavaScript tại chỗ. Các thông báo do tập lệnh đặt, như cảnh báo hoặc nhãn nút được tạo trong mã, cần một bước bản địa hóa riêng trong mã. Không lần chạy toàn tệp hoặc có hướng dẫn nào trong sáu lần thay đổi khối tập lệnh của chúng tôi, điều này đúng, nhưng có nghĩa là những chuỗi đó vẫn bằng tiếng Anh.
Sau khi dịch: Kiểm tra
-
Chạy kiểm tra cấu trúc.
python3 check_html_translation.py source.html translated.html --lang zh-Hans --keep ShelfmarkNó so sánh các thẻ và thứ tự của chúng, mọi thuộc tính không phải văn bản dành cho người đọc, nội dung của
<pre>,<script>, và<style>, mã nội tuyến, khóa JSON-LD, văn bảntranslate="no", chú thích, và liên kết trong trang. Nó cảnh báo về các thuộc tính văn bản vẫn bằng tiếng Anh, giá trịlangkhác với mong đợi, văn bản hiển thị có vẻ chưa được dịch, mã nội tuyến đã thay đổi thứ tự, và khoảng trắng giữa văn bản tiếng Trung, Nhật hoặc Hàn qua một thẻ nội tuyến. Nó không đánh giá chất lượng bản dịch. -
Đọc từng câu có chứa thẻ nội tuyến. Đây là nơi ý nghĩa bị phá vỡ trong bài kiểm tra của chúng tôi. Đừng dựa vào cảnh báo "mã nội tuyến bị sắp xếp lại" của trình kiểm tra để tìm những câu này: trong bài kiểm tra của chúng tôi, những bản dịch sai là những bản giữ nguyên thứ tự gốc.
-
Mở trang trong trình duyệt. Nhấp vào các liên kết trong trang, dùng phím Tab qua biểu mẫu với trình đọc màn hình nếu có thể, và tìm khoảng trống xung quanh văn bản in đậm và được liên kết.
-
Đối với ngôn ngữ từ phải sang trái, cũng đặt
dir="rtl"trên phần tử<html>. Hướng dẫn dịch sách RTL của chúng tôi đề cập những thay đổi khác. -
Đối với XHTML, chẳng hạn như các tệp chương bên trong EPUB, cũng xác nhận rằng tệp vẫn là XML hợp lệ, ví dụ với
xmllint --noout chapter.xhtml. Trình duyệt tha thứ cho thẻ chưa đóng; trình đọc sách điện tử có thể không. Danh sách kiểm tra QA dịch EPUB của chúng tôi đề cập phần còn lại của sách điện tử.
BookTranslator phù hợp ở đâu
Trang tải lên của BookTranslator chấp nhận các tệp .html, .htm và .xhtml cùng với sách và tài liệu, vì vậy bạn có thể tải lên một trang đã lưu hoặc một bài viết trợ giúp tĩnh dưới dạng một tệp hoàn chỉnh. Chúng tôi không chạy mẫu này qua BookTranslator cho bài viết này và chúng tôi chưa kiểm tra cách nó xử lý thứ tự mã nội tuyến, nội dung CSS hoặc JSON-LD, vì vậy hãy kiểm tra đầu ra của nó giống như bạn sẽ kiểm tra bất kỳ công cụ nào khác. Bạn thấy giá trước khi thanh toán.
Dù bạn sử dụng công cụ nào, hãy thực hiện các bước chuẩn bị trước khi dịch và kiểm tra sau đó. Một trang có mọi thẻ nguyên vẹn vẫn có thể bảo người đọc gõ sai điều gì đó. Nếu HTML của bạn thực chất là tài liệu được viết bằng Markdown, hướng dẫn dịch Markdown của chúng tôi sẽ đề cập đến định dạng nguồn thay thế.
Tải các tệp kiểm tra
Mọi thứ từ bài kiểm tra này đều có thể tái sử dụng miễn phí:
- sample-source.html: mẫu tiếng Anh 59 dòng;
- check_html_translation.py: công cụ kiểm tra cấu trúc (chỉ dùng thư viện chuẩn Python);
- run_llm_html_test.py: ba phương pháp, dành cho bất kỳ máy chủ cục bộ tương thích OpenAI nào;
- chín đầu ra trong thư mục outputs, cùng với check-results.txt và results.csv.
Bài viết liên quan





