DichHay.comDịch Hay
Dịch phần mềm và ứng dụng

Biến và placeholder trong chuỗi dịch: giữ nguyên mã mà câu vẫn đúng ngữ pháp

%s, %1$d, {name}, {{count}}, thẻ in đậm: phần nào trong chuỗi không được đụng, khi nào được đổi thứ tự, và vì sao câu ghép từ nhiều mảnh không thể dịch cho đúng.

Macro shot of a mechanical keyboard with a few keycaps removed and resting beside it on a walnut desk, shallow depth of field, warm amber light, deep teal background

Placeholder, hay biến, là chỗ trống trong một chuỗi giao diện mà ứng dụng sẽ điền giá trị vào lúc chạy: tên người dùng, số lượng, ngày giờ, số tiền. Trong tệp chuỗi chúng hiện ra dưới dạng như %s, %d, %1$s, {name}, {{count}} hoặc {0}. Nguyên tắc cơ bản khi dịch: giữ nguyên từng ký tự của biến, giữ đủ số lượng, và chỉ đổi vị trí của biến khi định dạng đó cho phép.

Biến là nguồn gây lỗi kỹ thuật nhiều nhất trong bản dịch phần mềm, vì sai một ký tự là ứng dụng hiện chữ thô, hiện sai dữ liệu, hoặc ở một số ngôn ngữ lập trình thì dừng hẳn màn hình. Nhưng biến cũng là nơi ngữ pháp bị bẻ cong nhiều nhất, vì người viết chuỗi nguồn thường chỉ nghĩ theo trật tự từ tiếng Anh. Bài này đi qua các kiểu biến, cách dịch an toàn, và những cấu trúc chuỗi mà người dịch nên báo lại cho lập trình viên thay vì cố dịch.

Các kiểu biến thường gặp và cách nhận ra

Mỗi ngôn ngữ lập trình và mỗi thư viện có cú pháp riêng. Người dịch không cần nhớ hết, chỉ cần nhận ra "đây là mã, không phải chữ".

KiểuVí dụ trong chuỗiÝ nghĩaĐược đổi vị trí không
Kiểu printf không đánh số%s, %d, %@, %.2fChuỗi, số nguyên, đối tượng, số thực hai chữ số thập phânKhông — điền theo thứ tự xuất hiện; đổi chỗ là đổi dữ liệu
Kiểu printf có đánh số%1$s, %2$dBiến thứ nhất, biến thứ haiĐược — số thứ tự giữ dữ liệu đúng chỗ
Ngoặc nhọn có số{0}, {1}Tham số theo vị tríĐược
Ngoặc nhọn có tên{name}, {count}, {{user}}Tham số theo tênĐược, và dễ hiểu nhất cho người dịch
Thẻ định dạng<b>…</b>, <0>…</0>, [link]…[/link]In đậm, đường dẫn, kiểu chữĐược di chuyển cả cặp, phải bao đúng phần chữ tương ứng
Ký tự đặc biệt\n, \t, %%Xuống dòng, tab, dấu phần trăm thậtGiữ nguyên; %% là cách viết một dấu % trong kiểu printf

Lưu ý dấu phần trăm: trong chuỗi kiểu printf, muốn hiện chữ "Giảm 20%" thì phải viết "Giảm 20%%". Người dịch quen tay gõ một dấu phần trăm sau con số là đã tạo ra một biến lạ, và tuỳ ngôn ngữ lập trình, ứng dụng có thể hiện sai hoặc báo lỗi. Ngược lại, trong định dạng không dùng printf như phần lớn tệp JSON thì một dấu phần trăm là đủ. Hỏi lại khi không chắc.

Vì sao trật tự biến là chuyện ngữ pháp, không chỉ là kỹ thuật

Câu tiếng Anh "%s shared %s with you" nghe hợp lý: người chia sẻ, động từ, vật được chia sẻ. Sang tiếng Việt vẫn giữ được trật tự đó: "%s đã chia sẻ %s với bạn". Nhưng sang tiếng Nhật hay tiếng Hàn, động từ nằm cuối câu và tân ngữ đứng trước, nên trật tự tự nhiên cần đảo. Nếu biến không đánh số, người dịch tiếng Nhật buộc phải giữ trật tự tiếng Anh và viết một câu ngượng, hoặc đảo trật tự và làm tên người với tên tệp đổi chỗ cho nhau trên màn hình.

Tiếng Việt có những trường hợp tương tự, chỉ ít hơn. Câu "Last updated %s ago" dịch thành "Cập nhật %s trước" là ổn; nhưng "%s of %s" (ví dụ "3 of 10") có thể cần thành "%s/%s" hoặc "%s trên %s" tuỳ ngữ cảnh. Câu sở hữu "%s's profile" trong tiếng Anh đặt chủ sở hữu trước, tiếng Việt đặt sau: "Hồ sơ của %s" — vẫn một biến nên không sao. Khi có hai biến trở lên và trật tự cần đổi, chỉ đổi được an toàn nếu biến có số hoặc có tên.

Vì vậy khi người dịch gặp chuỗi nhiều biến không đánh số mà ngữ pháp tiếng đích cần đảo, cách làm chuyên nghiệp là báo lại cho lập trình viên đổi sang biến đánh số, không tự xoay xở. Sửa một dòng mã rẻ hơn rất nhiều so với một màn hình hiện sai tên người gửi.

Biến làm thay đổi ngữ pháp xung quanh nó

Không phải lúc nào chỉ cần giữ biến là đủ. Giá trị điền vào biến có thể làm chữ xung quanh phải đổi, và người dịch không nhìn thấy giá trị đó. Ví dụ quen thuộc nhất là số: "%d item" chỉ đúng khi số bằng 1; vấn đề số nhiều có bài riêng trong chuyên mục.

Ví dụ ít người để ý hơn là giống ngữ pháp và cách. Tiếng Pháp, tiếng Đức, tiếng Nga chia tính từ và động từ theo giống của danh từ; câu "{user} đã thích bài viết của bạn" dịch sang tiếng Nga cần biết người dùng là nam hay nữ để chia động từ quá khứ. Tiếng Nga, tiếng Ba Lan còn đổi đuôi danh từ theo cách, nên một tên sản phẩm điền vào giữa câu có thể cần một dạng khác dạng nguyên. Những ngôn ngữ này cần chuỗi viết theo kiểu chọn lựa (select) của ICU MessageFormat hoặc cơ chế tương đương, không chỉ một biến trơn.

Tiếng Việt may mắn không chia giống hay cách, nhưng có loại từ và xưng hô. "{count} {item}" dịch máy móc thành "3 sản phẩm" thì ổn, nhưng nếu biến item lúc chứa "áo", lúc chứa "đôi giày", loại từ "cái", "đôi", "chiếc" sẽ lệch. Tương tự, chuỗi chèn tên người vào câu chào phải chọn một cách xưng hô dùng được cho mọi người — thường là gọi thẳng tên hoặc dùng "bạn" — vì ứng dụng không biết người đó bao nhiêu tuổi.

Câu ghép từ nhiều mảnh: lỗi quốc tế hoá người dịch không sửa được

Mảnh chuỗi rời nhau trên cùng một dòng. Lập trình viên viết "You have" + số + "new messages" thành ba chuỗi. Người dịch nhận ba mảnh, không biết chúng ghép với nhau, dịch "Bạn có" và "tin nhắn mới" — may thì đúng, nhưng sang tiếng Nhật hay tiếng Thổ Nhĩ Kỳ là không thể sắp lại trật tự.

Một từ dùng lại cho nhiều câu. Chuỗi "Delete" được dùng cho nút, cho tiêu đề hộp thoại và cho mục trong menu. Tiếng Anh một chữ dùng được cả ba, tiếng Việt có thể cần "Xoá", "Xoá mục này?" và "Xoá…" khác nhau. Chuỗi dùng chung cho nhiều vai trò buộc bản dịch phải chọn cách kém tự nhiên nhất.

Chữ có đường dẫn bị tách đôi. "By continuing you agree to our" + đường dẫn "Terms". Tiếng Việt muốn viết "Khi tiếp tục, bạn đồng ý với Điều khoản sử dụng" thì vẫn ổn, nhưng tiếng Đức có thể cần động từ đứng sau đường dẫn. Cách đúng là một chuỗi duy nhất có thẻ đánh dấu phần được gắn đường dẫn.

Ghép tính từ với danh từ bằng mã. "New" + tên loại tài liệu, "Last" + đơn vị thời gian. Các ngôn ngữ chia giống sẽ cần dạng tính từ khác nhau cho mỗi danh từ.

Cách xử lý đúng. Người dịch ghi lại từng trường hợp kèm khoá chuỗi và gợi ý viết lại thành một chuỗi hoàn chỉnh có biến đặt tên. Bên đặt dịch nên coi danh sách này là đầu vào cho đợt sửa quốc tế hoá, không phải là lời phàn nàn.

Thẻ định dạng và đường dẫn trong chuỗi

Ngoài biến dữ liệu, chuỗi giao diện hay chứa thẻ đánh dấu một phần chữ cần in đậm, đổi màu hoặc gắn đường dẫn. Ví dụ chuỗi nguồn "Read our <link>privacy policy</link> before continuing" chứa một cặp thẻ bao quanh cụm từ sẽ được bấm vào. Khi dịch, cặp thẻ phải đi theo đúng cụm từ tương ứng trong tiếng đích: "Vui lòng đọc <link>chính sách quyền riêng tư</link> trước khi tiếp tục". Nếu người dịch để thẻ bao nhầm cả câu, toàn bộ câu thành đường dẫn; nếu bao hụt, người dùng chỉ bấm được vào chữ "chính sách".

Một số thư viện dùng thẻ đánh số như <0>…</0> hoặc <1>…</1> thay cho tên. Số thứ tự đó gắn với một thành phần cụ thể trong mã, nên không được đánh lại số theo thứ tự xuất hiện trong câu dịch: nếu ngữ pháp tiếng đích đưa thẻ <1> lên trước thẻ <0> thì cứ để nguyên số, chỉ đổi vị trí. Thẻ tự đóng (chỉ có một vế) thường là chỗ chèn biểu tượng hoặc ngắt dòng, giữ nguyên vị trí tương đối trong câu.

Với tiếng Việt, cần đặc biệt để ý khi cụm được gắn thẻ là một danh từ ghép: "Terms of Service" thành "Điều khoản dịch vụ", thẻ bao cả cụm, không bao riêng chữ "Điều khoản". Còn khi thẻ chỉ để in đậm một con số hay một tên riêng, như "Còn <b>{days}</b> ngày dùng thử", hãy giữ phần in đậm đúng là phần quan trọng nhất của câu — người dùng lướt mắt sẽ chỉ đọc phần đó.

Quy tắc an toàn khi dịch chuỗi có biến

Áp dụng cho người dịch, và cũng là danh mục để người duyệt bản dịch rà lại:

  1. Chép biến bằng cách sao chép, không gõ lại; công cụ dịch tốt sẽ khoá biến thành một khối không sửa được.
  2. Đếm số biến ở bản nguồn và bản dịch phải bằng nhau, kể cả biến lặp lại hai lần.
  3. Không dịch tên trong ngoặc nhọn: {name} giữ nguyên là {name}, không thành {tên}.
  4. Giữ khoảng trắng quanh biến theo đúng quy tắc tiếng đích: tiếng Việt có dấu cách trước và sau biến chứa từ, tiếng Nhật và tiếng Trung thường không có.
  5. Thẻ định dạng phải đi thành cặp, bao đúng phần chữ có ý nghĩa tương ứng sau khi dịch, không bao dư hay hụt.
  6. Khi cần đổi trật tự mà biến không đánh số, dừng lại và hỏi; ghi lại khoá chuỗi để lập trình viên sửa.
  7. Đọc lại câu bằng cách điền thử vài giá trị thật vào biến: tên dài, tên ngắn, số 0, số 1, số lớn.

Bước cuối là bước hay bị bỏ nhất mà lại rẻ nhất. "Chào mừng {name} quay lại!" nghe ổn với tên "An", nhưng nếu biến chứa địa chỉ email dài thì câu có thể tràn dòng; nếu biến có thể rỗng với người dùng chưa đặt tên thì màn hình hiện "Chào mừng quay lại!" với hai dấu cách. Những trường hợp này người dịch nên ghi chú để nhóm sản phẩm quyết định.

Kiểm tra biến tự động: bắt lỗi trước khi tới máy người dùng

Phần lớn lỗi biến bắt được bằng máy, không cần người. Công cụ dịch chuyên nghiệp và nền tảng quản lý bản dịch đều có bước kiểm tra chất lượng tự động so biến giữa bản nguồn và bản dịch: thiếu biến, thừa biến, biến bị sửa chữ, thẻ không đóng, dấu phần trăm lẻ. Bên dịch nên chạy bước này trước khi giao, và bên nhận nên chạy lại khi nhập vào kho mã.

Nhóm phát triển có thể thêm một lớp nữa trong quy trình dựng bản: chương trình kiểm tra đọc mọi tệp ngôn ngữ, so tập biến của từng khoá với ngôn ngữ nguồn, và dừng bản dựng nếu không khớp. Đoạn kiểm tra này viết một lần, dùng mãi, và chặn được loại lỗi gây hậu quả nặng nhất là màn hình thanh toán hiện sai số tiền vì hai biến bị đổi chỗ.

Máy không bắt được lỗi ngữ pháp quanh biến hay lỗi xưng hô. Phần đó chỉ lộ ra trong kiểm thử ngôn ngữ trên bản chạy thật, khi biến đã có giá trị. Đó là lý do một bản dịch qua hết kiểm tra tự động vẫn cần người đọc trên màn hình. Ở Dịch Hay, bước so biến chạy trên mọi tệp trước khi bàn giao, và các chuỗi ghép mảnh được gom thành danh sách riêng gửi kèm để nhóm phát triển sửa.

Câu hỏi thường gặp

Có được thêm biến vào bản dịch không, ví dụ lặp lại tên người dùng cho câu tự nhiên hơn?

Chỉ khi định dạng cho phép dùng lại biến có tên hoặc có số và nhóm phát triển đồng ý. Với biến kiểu printf không đánh số thì tuyệt đối không, vì mỗi biến thêm vào sẽ đòi một giá trị mà mã không truyền. An toàn nhất là viết lại câu để dùng đúng số biến như bản nguồn.

Có được bỏ bớt một biến nếu tiếng Việt không cần không?

Không nên. Với kiểu printf, bỏ một biến làm các biến sau lệch dữ liệu. Với kiểu có tên, bỏ biến có thể không gây lỗi kỹ thuật nhưng làm mất thông tin người dùng cần. Nếu thật sự thấy biến thừa trong tiếng đích, ghi chú để nhóm sản phẩm quyết định thay vì tự bỏ.

ICU MessageFormat là gì và người dịch có cần học không?

Đó là cú pháp viết chuỗi cho phép một chuỗi tự chọn dạng đúng theo số lượng (plural) hoặc theo giá trị như giống (select), do dự án ICU của Unicode phát triển và được nhiều thư viện dùng. Người dịch không cần viết từ đầu, nhưng cần đọc hiểu cấu trúc để chỉ dịch phần chữ trong từng nhánh và giữ nguyên từ khoá như plural, one, other.

Dấu cách quanh biến trong tiếng Việt có quy tắc chung không?

Biến chứa một từ hoặc một cụm từ thì có dấu cách hai bên như chữ thường. Biến chứa con số đi với đơn vị thì theo quy ước của sản phẩm, ví dụ "10 phút" có dấu cách, còn phần trăm thường viết liền. Quan trọng là thống nhất trong toàn ứng dụng và ghi vào hướng dẫn văn phong.

Làm sao biết một biến chứa gì khi tệp không có ghi chú?

Tìm khoá đó trong ảnh chụp màn hình hoặc bản cài thử, xem tên biến nếu là kiểu có tên, hoặc hỏi lập trình viên. Đừng đoán khi biến nằm trong câu có tiền, có thời hạn hay có thông tin cá nhân. Hỏi một câu tốn vài phút, sửa một lỗi đã phát hành tốn cả một bản cập nhật.

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

Gửi yêu cầu dịch

Cho biết loại dịch vụ, ngôn ngữ và nơi bản dịch sẽ dùng. Chúng tôi xem yêu cầu, liên hệ lại để nhận tệp mẫu hoặc chương trình sự kiện và báo phương án phù hợp.

Thông tin chỉ dùng để liên hệ về yêu cầu dịch của bạn. Đừng dán tài liệu mật vào ô ghi chú — chúng tôi sẽ hướng dẫn cách gửi tệp an toàn khi liên hệ lại.