Tệp chuỗi ngôn ngữ là nơi ứng dụng cất toàn bộ chữ hiển thị cho người dùng, tách khỏi mã nguồn. Mỗi dòng gồm một khoá (tên định danh mà mã gọi tới, ví dụ login.title) và một giá trị (chữ thật hiện lên màn hình, ví dụ "Đăng nhập"). Dịch ứng dụng thực chất là tạo một bản sao của tệp này cho mỗi ngôn ngữ, giữ nguyên khoá, chỉ thay giá trị.
Mỗi nền tảng có định dạng riêng: Android dùng tệp XML, iOS và macOS dùng tệp .strings, .stringsdict và gần đây là danh mục chuỗi .xcstrings, ứng dụng web và nhiều khung ứng dụng đa nền tảng dùng JSON, các dự án theo truyền thống mã nguồn mở dùng tệp PO của gettext, còn XLIFF là định dạng trao đổi chuẩn giữa công cụ phát triển và công cụ dịch. Gửi dịch đúng định dạng gốc, kèm ghi chú, là cách chắc nhất để bản dịch nhập lại không làm hỏng bản dựng.
Các định dạng tệp chuỗi thường gặp
Bảng dưới đây không nhằm dạy lập trình mà giúp người đặt dịch và người dịch nhận ra mình đang cầm loại tệp gì, chỗ nào được sửa và chỗ nào là bẫy.
| Định dạng | Thường gặp ở | Chỗ người dịch được sửa | Bẫy hay gặp |
|---|---|---|---|
| XML (strings.xml) | Ứng dụng Android | Phần chữ giữa thẻ mở và thẻ đóng | Dấu nháy đơn phải thoát bằng gạch chéo ngược; ký tự & và < phải viết dạng thực thể; có thẻ plurals cho số nhiều |
| .strings / .stringsdict | iOS, macOS đời cũ hơn | Vế bên phải dấu bằng, trong ngoặc kép | Thiếu dấu chấm phẩy cuối dòng là hỏng cả tệp; số nhiều nằm ở tệp .stringsdict riêng |
| .xcstrings (danh mục chuỗi) | Dự án Apple mới | Giá trị của từng ngôn ngữ trong cùng một tệp | Một tệp chứa mọi ngôn ngữ, sửa tay dễ đè lên ngôn ngữ khác; nên xuất ra XLIFF để dịch |
| JSON | Ứng dụng web, khung đa nền tảng | Giá trị sau dấu hai chấm | Dấu phẩy thừa hoặc thiếu làm hỏng tệp; khoá lồng nhiều tầng; biến dạng {{ten}} hoặc {ten} |
| PO (gettext) | Dự án mã nguồn mở, nhiều ứng dụng PHP, Python | Dòng msgstr | Dòng msgid là chữ nguồn, không được sửa; có cờ fuzzy đánh dấu bản dịch cần xem lại |
| XLIFF | Trao đổi giữa công cụ phát triển và công cụ dịch | Phần target của mỗi đơn vị | Thẻ nội dòng đại diện cho mã định dạng, xoá là mất định dạng; có trạng thái từng đoạn |
Nếu nhận được một tệp mà bạn không nhận ra định dạng, đừng mở bằng trình soạn thảo văn bản thường rồi lưu lại: nhiều trình soạn thảo đổi kiểu xuống dòng hoặc thêm ký tự đánh dấu đầu tệp, đủ để bản dựng báo lỗi. Hỏi lại lập trình viên, hoặc dùng công cụ dịch đọc được định dạng đó.
Khoá, giá trị và ghi chú: ba phần của một dòng chuỗi
Khoá là thứ mã nguồn gọi tới. Người dịch không bao giờ sửa khoá, kể cả khi khoá viết sai chính tả hay đặt tên xấu, vì mã đang tham chiếu đúng tên đó. Một khoá bị đổi là một chỗ trên màn hình hiện ra chính cái khoá đó thay cho chữ — lỗi rất hay gặp khi ai đó dùng chức năng tìm và thay thế trên toàn tệp.
Giá trị là chữ được dịch. Trong giá trị có thể có biến, thẻ định dạng, ký tự xuống dòng và ký tự thoát; những phần này phải giữ nguyên số lượng và cú pháp. Bài về biến và placeholder trong chuyên mục này đi sâu phần đó.
Ghi chú là phần nhiều nhóm phát triển bỏ trống nhưng lại quyết định chất lượng. Hầu hết định dạng đều có chỗ cho ghi chú: thuộc tính hoặc chú thích trong XML, dòng chú thích phía trên trong .strings, dòng bắt đầu bằng dấu thăng trong PO, phần note trong XLIFF. Một ghi chú tốt trả lời ba câu: chữ này nằm ở đâu, đóng vai trò gì (nút, tiêu đề, trạng thái, thông báo lỗi), giới hạn bao nhiêu ký tự. Ghi chú cho biến nói rõ biến đó chứa gì, ví dụ "{0} là tên cửa hàng, {1} là số đơn".
Một chi tiết nữa về khoá: cùng một chữ nguồn có thể xuất hiện dưới nhiều khoá khác nhau, ví dụ chữ "Close" ở mười hộp thoại. Đây là điều tốt chứ không phải lãng phí, vì nó cho phép dịch khác nhau khi ngữ cảnh khác nhau. Công cụ dịch sẽ gợi ý bản dịch đã có để người dịch dùng lại khi phù hợp. Ngược lại, gộp mọi chữ giống nhau về một khoá dùng chung để tiết kiệm là thói quen nên bỏ: nó tiết kiệm vài chục chuỗi nhưng khoá chết khả năng dịch đúng theo từng màn hình.
Với khách đặt dịch, cách kiểm tra nhanh chất lượng tệp nguồn là đếm tỷ lệ chuỗi có ghi chú trong nhóm chuỗi ngắn dưới ba từ. Nhóm này là nơi sai nghĩa nhiều nhất, và nếu gần như không chuỗi nào có ghi chú thì nên chuẩn bị ảnh chụp màn hình thay thế.
Mã hoá ký tự: vì sao tiếng Việt hay bị vỡ
Mọi tệp chuỗi hiện nay nên lưu bằng UTF-8. Phần lớn công cụ phát triển mặc định như vậy, nhưng lỗi vẫn xảy ra ở khâu trung gian: ai đó mở tệp bằng bảng tính, lưu thành CSV theo bảng mã mặc định của máy, rồi chép lại. Kết quả là chữ có dấu biến thành chuỗi ký tự lạ, hoặc dấu hỏi thay cho chữ.
Tiếng Việt còn một bẫy riêng ít người biết: cùng một chữ có dấu có thể được lưu theo hai cách trong Unicode. Cách dựng sẵn (NFC) dùng một mã cho cả chữ "ệ"; cách tổ hợp (NFD) lưu chữ "e" rồi thêm mã dấu mũ và mã dấu nặng. Mắt người không phân biệt được, nhưng máy thì có: chức năng tìm kiếm trong ứng dụng không khớp, sắp xếp theo bảng chữ cái lộn xộn, đếm độ dài chuỗi ra số khác nhau, và một số phông chữ hiển thị dấu lệch. Văn bản gõ trên máy Mac, hoặc chép từ một số tệp PDF, hay rơi vào dạng tổ hợp.
Cách phòng là thống nhất chuẩn hoá về NFC trước khi nhập bản dịch vào kho mã, và yêu cầu bên dịch giao tệp đã chuẩn hoá. Đây là một dòng lệnh với lập trình viên, nhưng nếu không ai nhắc thì lỗi chỉ lộ ra khi người dùng phàn nàn rằng gõ "Hà Nội" vào ô tìm kiếm không ra kết quả nào dù dữ liệu có sẵn.
Thêm một chi tiết: một số tệp có ký tự đánh dấu thứ tự byte (BOM) ở đầu. Có nền tảng chấp nhận, có nền tảng báo lỗi. Quy tắc an toàn là trả tệp đúng như lúc nhận — nhận có BOM thì trả có, nhận không có thì trả không.
Gửi tệp chuỗi đi dịch: các bước để nhận về dùng được ngay
Quy trình dưới đây dành cho nhóm phát triển hoặc người quản lý sản phẩm chuẩn bị gửi dịch lần đầu:
- Xuất tệp từ nhánh mã đã đóng chuỗi, không xuất từ nhánh đang sửa dở, để không dịch những chữ sắp bị xoá.
- Giữ nguyên định dạng gốc hoặc xuất ra XLIFF; tránh chép sang bảng tính trừ khi có công cụ chuyển ngược tự động.
- Lọc bỏ chuỗi không cần dịch (khoá kỹ thuật, tên biến môi trường, chuỗi gỡ lỗi chỉ lập trình viên thấy) hoặc đánh dấu chúng rõ ràng.
- Bổ sung ghi chú cho chuỗi dưới ba từ, chuỗi có biến, chuỗi có giới hạn độ dài.
- Gửi kèm ảnh chụp màn hình hoặc bản cài thử, bảng thuật ngữ, bản dịch cũ nếu có.
- Thống nhất cách bên dịch hỏi lại ngữ cảnh và thời hạn trả lời.
- Khi nhận lại, chạy kiểm tra cú pháp tệp và so số lượng khoá với tệp nguồn trước khi nhập vào kho mã.
Bước cuối nên tự động hoá: một đoạn kiểm tra nhỏ so số khoá, số biến trong mỗi chuỗi và cú pháp tệp sẽ bắt được phần lớn lỗi kỹ thuật trước khi chúng tới tay người kiểm thử. Bên dịch chuyên nghiệp cũng chạy kiểm tra tương tự trước khi giao, nhưng hai lớp vẫn hơn một.
Những sai lầm làm hỏng bản dựng sau khi dịch
Dịch luôn cả khoá. Thường do dùng công cụ dịch máy cho cả tệp hoặc dùng chức năng thay thế hàng loạt. Kết quả là mã gọi khoá cũ không tìm thấy, màn hình hiện tên khoá.
Đổi dấu nháy thẳng thành nháy cong. Trình soạn thảo văn bản tự đổi dấu nháy kép thẳng bao quanh giá trị thành dấu nháy cong, cú pháp tệp hỏng ngay. Dấu nháy cong chỉ được dùng bên trong chữ dịch, không được dùng làm dấu bao.
Thêm hoặc bớt dấu phẩy, dấu chấm phẩy kết thúc dòng. JSON không chấp nhận dấu phẩy sau phần tử cuối; tệp .strings bắt buộc có dấu chấm phẩy. Một ký tự sai làm hỏng cả tệp, không chỉ một dòng.
Gộp hoặc tách dòng. Người dịch thấy hai chuỗi liền nhau như một câu nên gộp nghĩa vào chuỗi đầu, để trống chuỗi sau. Trên màn hình, hai chuỗi đó có thể nằm ở hai nơi khác nhau.
Để trống giá trị thay vì giữ nguyên. Với chuỗi không cần dịch như tên thương hiệu, để trống có thể làm ứng dụng hiện chuỗi rỗng thay vì hiện bản gốc, tuỳ nền tảng. Hãy chép nguyên văn sang.
Sửa tệp nguồn thay vì tệp đích. Ở định dạng chứa nhiều ngôn ngữ trong một tệp, lỡ ghi bản dịch vào cột ngôn ngữ nguồn là bản gốc biến mất. Luôn giữ bản sao tệp nguồn trước khi giao cho người dịch.
Chuỗi không nằm trong tệp: nội dung động và chuỗi hệ thống
Một ứng dụng dịch hết tệp chuỗi vẫn có thể hiện tiếng Anh ở nhiều chỗ. Phổ biến nhất là nội dung lấy từ máy chủ: tên danh mục, mô tả gói cước, thông điệp khuyến mãi, câu hỏi trong biểu mẫu. Những chữ này nằm trong cơ sở dữ liệu hoặc hệ quản trị nội dung, cần một cột hoặc một bản ghi riêng cho mỗi ngôn ngữ, và phải có người phụ trách nhập bản dịch mỗi khi đội vận hành thêm nội dung mới.
Thứ hai là chuỗi khai báo cho hệ điều hành: lời giải thích khi ứng dụng xin quyền truy cập camera, vị trí, ảnh; tên ứng dụng hiện dưới biểu tượng; các phím tắt trên biểu tượng. Trên các nền tảng của Apple, nhóm chuỗi này nằm trong tệp khai báo riêng của ứng dụng chứ không trong tệp giao diện. Lời xin quyền đặc biệt quan trọng vì các cửa hàng ứng dụng yêu cầu giải thích rõ mục đích, và người dùng từ chối quyền khi đọc không hiểu.
Thứ ba là chuỗi trong thư viện bên thứ ba: màn hình thanh toán, khung đăng nhập, bộ chọn ảnh do thư viện cung cấp. Nhiều thư viện đã có sẵn bản tiếng Việt, một số thì không. Liệt kê các thư viện có giao diện riêng trước khi báo cho khách hàng rằng ứng dụng đã dịch xong. Khi nhận tệp chuỗi, Dịch Hay rà cả ba nhóm chữ ngoài tệp này và gửi lại danh sách để bạn xác nhận phạm vi; bạn có thể đính kèm tệp xuất hoặc ảnh chụp trong mẫu đăng ký để được xem trước.
Câu hỏi thường gặp
Có thể gửi tệp chuỗi dưới dạng bảng tính cho tiện không?
Có thể nếu nhóm phát triển có cách chuyển ngược tự động và kiểm tra lại số khoá. Rủi ro của bảng tính là đổi bảng mã khi lưu, tự định dạng số, tự đổi dấu nháy và mất ghi chú. Nếu bắt buộc dùng, hãy khoá cột khoá, để cột ghi chú và giới hạn ký tự cạnh cột dịch, và xuất bằng UTF-8.
XLIFF có bắt buộc không?
Không bắt buộc, nhưng là định dạng trao đổi chuẩn do tổ chức OASIS phát triển, được nhiều công cụ phát triển và công cụ dịch đọc được. Lợi ích chính là tách phần chữ khỏi cú pháp riêng của từng nền tảng, giữ ghi chú, và đánh dấu trạng thái từng đoạn như đã dịch, đã duyệt, cần xem lại.
Người dịch có cần cài môi trường lập trình để mở tệp không?
Không cần. Công cụ dịch chuyên dụng đọc được hầu hết định dạng chuỗi và chỉ cho sửa phần giá trị. Với tệp nhỏ, một trình soạn thảo mã có tô màu cú pháp cũng đủ, miễn là người dịch hiểu chỗ nào được sửa. Điều cần tránh là trình soạn thảo văn bản tự sửa dấu nháy và định dạng.
Tệp nguồn tiếng Việt có dấu, tệp đích tiếng Nhật, có cần lưu ý gì về mã hoá?
Chỉ cần cả hai tệp đều là UTF-8 và chữ tiếng Việt đã chuẩn hoá về dạng dựng sẵn. Tiếng Nhật, tiếng Hàn, tiếng Trung đều nằm gọn trong UTF-8. Lỗi thường xảy ra khi một bước trung gian lưu lại tệp bằng bảng mã cũ của máy tính cá nhân, nên tránh mở và lưu lại tệp bằng công cụ không rõ bảng mã.
Làm sao biết bản dịch nhận về có thiếu chuỗi không?
So số khoá giữa tệp nguồn và tệp đích, rồi liệt kê khoá có giá trị rỗng hoặc giống hệt bản nguồn. Chuỗi giống hệt bản nguồn không hẳn là thiếu, vì tên riêng hay chữ viết tắt có thể giữ nguyên, nhưng danh sách đó nên được người dịch xác nhận từng dòng.
Có nên đặt khoá chuỗi bằng chính câu tiếng Anh không?
Một số khung phát triển cho phép, và nó tiện lúc đầu. Nhược điểm là khi sửa câu tiếng Anh thì khoá đổi theo, mọi bản dịch cũ bị coi là chuỗi mới; và hai chỗ dùng cùng một câu tiếng Anh nhưng cần hai cách dịch khác nhau sẽ không tách được. Khoá có cấu trúc theo màn hình và vai trò bền hơn.