blog 18ways

i18n đang hỏng: Đừng viết các khóa dịch nữa

Một cách làm i18n trong Next.js theo hướng AI-native, mà không làm hỏng SEO.

Quốc tế hoá (thường viết tắt là i18n), bản địa hoá (l10n) và hỗ trợ đa ngôn ngữ đều mô tả cùng một ý: điều chỉnh sản phẩm của bạn để mọi người có thể dùng nó bằng ngôn ngữ của riêng họ.

i18n vẫn được xây như thể là năm 2005

Rốt cuộc thì mọi doanh nghiệp cũng nhận ra họ cần hỗ trợ nhiều ngôn ngữ. Đến lúc đó, nhóm sản phẩm ngả người ra sau như một bác thợ máy, hít một hơi qua kẽ răng rồi nói: “Ta đang nói về bao nhiêu trang? Ít nhất cũng phải bốn sprint.”

Một phản ứng mang tính “chữa cháy” trước chi phí và công sức của công việc i18n truyền thống

Cách nền tảng chúng ta triển khai i18n về cơ bản đã không thay đổi suốt 20 năm qua. Phần lớn “best practices” về i18n đã được hình thành từ rất lâu trước khi có các kiến trúc web hiện đại, và mọi thứ sau đó đơn giản chỉ là chồng thêm lên trên chúng.

I18n là phần duy nhất của phát triển web hiện đại vẫn còn liên quan đến việc xuất tệp và gửi chúng cho ai đó. Người ta coi đó là một thiết lập hiện đại nếu thay vì gửi email, bạn tải chúng lên qua API.

Trong một thế giới của các pipeline CI và các lần triển khai tính bằng phút thay vì ngày, có lẽ chúng ta nên tự thấy may mắn vì không phải fax bất cứ thứ gì.

Vì sao i18n có cảm giác bị hỏng

Phát triển web hiện đại đã tiến rất nhanh.

Chúng ta có:

Thế nhưng quy trình quốc tế hoá vẫn cứ như thuộc về một thời đại khác.

Ngay cả những ứng dụng tương đối nhỏ cũng nhanh chóng phải xoay xở với:

Các lập trình viên không hề bắt đầu bằng ý định xây dựng những hệ thống như thế này. Họ lảo đảo bước vào nó, khi những rào cản i18n quen thuộc làm vấp ngã các lập trình viên không quen với việc các ngôn ngữ khác nhau cấu trúc câu hoàn toàn khác nhau… rồi miễn cưỡng chấp nhận hiện trạng đã được đặt ra từ 20 năm trước.

Theo thời gian, quốc tế hoá trở thành một trong những phần phức tạp nhất của stack.


Giao diện hiện đại không thể nhét vừa trong chuỗi dịch

Hãy xem một giao diện người dùng đơn giản:

jsx
<h1>Hello world!</h1>
<p>
  <a href="#/">Click here</a> to view your <b>{serverResponse.productDescription}</b>
</p>

Điều này dễ hiểu. Nó đơn giản.

Đến một lúc nào đó, chúng tôi quyết định quốc tế hoá nó. Vì thế, chúng tôi trích văn bản ra một tệp dịch:

json
{
  "mainPage": {
    "greeting": "Hello world",
    "cta": "<0>Click here</0> to view your <1>{{description}}</1>"
  }
}

Và ta tham chiếu nó trong code của mình:

jsx
<h1>{t('mainPage.greeting')}</h1>
<p>
  <Trans key="mainPage.cta">
    <a href="#/">Click here</a> to view your <b>{{ description: serverResponse.productDescription }}</b>
  </Trans>
</p>

Nhưng khoan, giờ chúng ta có văn bản tiếng Anh cả trong code lẫn trong tệp dịch của mình ư? Đúng vậy. Các thư viện i18n khác nhau có thể phủ lên nó lớp sơn khác nhau, nhưng cố dịch một đoạn văn bản đã được định dạng một phần bằng cách tách nó ra thành một tệp JSON dễ đọc cho con người là một cuộc chiến thua chắc.

Giao diện người dùng hiện đại có cấu trúc, nhưng hệ thống dịch thuật lại được xây trên nền những chuỗi ký tự phẳng.

Một khi markup, biến và nội dung động xuất hiện, lớp trừu tượng bắt đầu rò rỉ.

Nội dung động và do người dùng tạo ra phá vỡ i18n truyền thống

Mọi thứ còn khó hơn nữa khi nội dung không tĩnh.

Hãy lấy ví dụ này một lần nữa:

jsx
<b>{serverResponse.productDescription}</b>

Chuỗi đó đến từ một API. Làm sao để biến nó thành một khóa dịch?

Bí mật là: không. Giờ backend của bạn cũng phải hỗ trợ quốc tế hoá nữa.

Backend của bạn giờ phải xử lý:

Dịch giả đột nhiên cũng cần quyền truy cập vào các hệ thống backend.

Và vấn đề chỉ càng lớn hơn khi nội dung do người dùng tạo ra xuất hiện.

Đánh giá. Bình luận. Danh sách trên chợ. Diễn đàn.

Các quy trình i18n truyền thống mặc định rằng lập trình viên kiểm soát toàn bộ văn bản. Ngày càng nhiều hơn, điều đó đơn giản là không đúng.

Việc những công ty như Amazon bắt đầu thử nghiệm đánh giá người dùng được dịch vào năm 2026 nói lên rất nhiều điều về tốc độ tiến hoá quá chậm của hệ sinh thái i18n.

Phát hiện locale vẫn là một mớ hỗn độn

Ngay cả việc xác định người dùng muốn ngôn ngữ nào cũng phức tạp một cách đáng ngạc nhiên.

Trình duyệt gửi tùy chọn ngôn ngữ qua tiêu đề Accept-Language:

text
Accept-Language: en-GB,en;q=0.9,fr;q=0.8

Điều này nói với máy chủ:

  1. Ưu tiên tiếng Anh kiểu Anh
  2. Rồi bất kỳ dạng tiếng Anh nào
  3. Rồi thì bất kỳ dạng tiếng Pháp nào

Trong thực tế, để triển khai đúng cách việc này đòi hỏi:

Nhiều framework để mặc phần lớn logic này cho nhà phát triển.

Ngay cả việc phát hiện locale cơ bản cũng thường trở thành mã ứng dụng tuỳ chỉnh.

Chuyển đổi ngôn ngữ là chuyện bị để sau cùng

Hạ tầng dịch thuật chỉ là một nửa vấn đề.

Người dùng vẫn cần một cách để đổi ngôn ngữ.

Hầu hết các thư viện i18n đều cung cấp lớp dịch thuật nhưng để lại phần còn lại của vấn đề cho lập trình viên:

Những chi tiết này nghe có vẻ nhỏ, nhưng chúng nhanh chóng trở thành một khối lượng đáng kể phần “hạ tầng” của ứng dụng, nhất là nếu bạn không quen với mọi ngóc ngách của i18n. Phần lớn công ty và lập trình viên đều không quen.

Cách rút gọn: Dịch tự động website

Trước hết mức độ phức tạp này, một số đội ngũ chuyển sang các công cụ dịch website tự động. Những nền tảng này hứa hẹn sẽ tự động dịch trang web của bạn với rất ít công sức.

Một số công ty đang xây dựng những phiên bản ngày càng tinh vi của ý tưởng này. Tiếc là họ lại tạo ra một bộ vấn đề khác:

Kết quả thường là một trang web về mặt kỹ thuật có hỗ trợ nhiều ngôn ngữ nhưng lại mang đến trải nghiệm kém hơn rõ rệt, và là một hộp đen đối với các lập trình viên khi làm việc.

Chúng tôi đã đi đến đây như thế nào

Chúng tôi bắt đầu bằng một thứ đẹp đẽ và đơn giản:

jsx
<h1>Hello world!</h1>
<p>
  <a href="#/">Click here</a> to view your <b>{serverResponse.productDescription}</b>
</p>

Và rồi chúng ta có khóa dịch thuật, từ điển JSON, các pipeline bị phân mảnh, các lớp bản địa hoá backend và frontend tách rời, cùng công cụ dịch bên ngoài.

Các ứng dụng web hiện đại là những hệ thống cực kỳ tinh vi. Thế nhưng, công cụ i18n lại kỳ vọng những quy trình được thiết kế cho một thời đại khác, như một chiếc Ferrari mà phải quay tay mới nổ máy.

Suy nghĩ lại mô hình

Nếu quốc tế hoá trông như thế này thì sao?

jsx
<h1><T>Hello world!</T></h1>
<p>
  <T>
    <a href="#/">Click here</a> to view your <b>{serverResponse.productDescription}</b>
  </T>
</p>

Không có khóa dịch.

Không có từ điển JSON.

Không có quy trình thủ công.

Chỉ là văn bản.

Một cách tiếp cận khác

Ý tưởng này là nền tảng đằng sau 18ways.

18ways xem dịch thuật như một mối quan tâm runtime được tối ưu hoá. Việc trích xuất khoá dịch và quản lý tệp dịch là việc dành cho máy móc, không phải con người.

Nhà phát triển chỉ cần đánh dấu phần văn bản họ muốn dịch.

Ở hậu trường, 18ways:

Mọi thứ vẫn thân thiện với SSR và an toàn cho SEO.

Bản dịch hiểu theo ngữ cảnh

Các hệ thống i18n truyền thống đánh mất ngữ cảnh.

Một dịch giả có thể thấy thứ gì đó như thế này:

text
home

Nhưng điều đó có nghĩa là gì?

Trong tiếng Đức, những nghĩa này đòi hỏi các từ hoàn toàn khác nhau:

Nếu bạn phải dịch “home” sang tiếng Đức, bạn muốn thấy gì hơn? Một chuỗi rời rạc, hay trang nơi nó thực sự xuất hiện?

So sánh giữa việc dịch một chuỗi JSON rời rạc và việc dịch trong toàn bộ ngữ cảnh của website

Các hệ thống dịch chỉ thấy những chuỗi văn bản rời rạc sẽ gặp khó với những khác biệt này.

18ways phân tích bản dịch trong ngữ cảnh của chính giao diện thực tế.

Các tác nhân backend của chúng tôi xem xét bản dịch ngay khi chúng xuất hiện trên các trang thực tế và tối ưu cho:

Nếu bạn quen với danh từ ghép tiếng Đức thì đừng lo, phát hiện tràn cũng đã được tính đến.

Trao quyền cho biên dịch viên

Mọi thứ giúp AI tạo ra bản dịch tốt hơn cũng giúp ích cho dịch giả con người.

18ways cung cấp cho biên dịch viên cùng một môi trường hiểu ngữ cảnh mà các tác nhân AI của chúng tôi dùng.

Thay vì chỉnh sửa các tệp JSON, người dịch xem lại văn bản trực tiếp trên giao diện nơi nó xuất hiện.

Điều này cải thiện đáng kể độ chính xác của bản dịch và hiệu quả quy trình làm việc.

Bộ diện mạo của i18n tốt hơn trông như thế nào

Quốc tế hoá không cần thêm một lớp khóa dịch, tệp chuỗi và keo nối đường ống.

Các ứng dụng hiện đại đã có sẵn cấu trúc, ngữ cảnh và thông tin thời gian chạy mà chúng ta cần để làm việc này tốt hơn.

Thế hệ i18n tiếp theo nên được xây dựng cho ứng dụng render phía máy chủ, nội dung động, quy trình làm việc gốc AI và dịch giả con người làm việc song song.

Đó là hướng mà 18ways đang đi theo.

i18n đang có vấn đề: Đừng viết khoá dịch nữa | Blog 18ways