Bản địa hóa ứng dụng Next.js sang tiếng Việt: định tuyến và ICU
💡 Để bản địa hóa ứng dụng Next.js sang tiếng Việt: cấu trúc route trong
app/[lang]/, thêm proxy middleware phát hiện Accept-Language, tải message JSON theo locale, và cấu hìnhIntlvới localevi-VN. Điều đáng chú ý: tiếng Việt chỉ có một dạng số nhiều trong ICU MessageFormat, vì vậy chuỗi số nhiều chỉ cần một nhánh duy nhất.
Ý chính
- Dùng
app/[lang]/vớigenerateStaticParamstrả về các locale được hỗ trợ (bao gồmvi) để tạo route tiếng Việt tĩnh hoàn toàn. defineRoutingvàcreateMiddlewarecủa next-intl xử lý phát hiện locale, chuyển hướng và điều hướng theo locale ngay từ đầu.- Tiếng Việt (locale CLDR
vi) chỉ có một dạng số nhiều: other. Các khối ICU plural vẫn hoạt động nhưng chuỗi tiếng Việt không bao giờ cần dạng "one" riêng. - Dùng JavaScript
IntlAPI với localevi-VN: ngày hiển thị dạng DD/MM/YYYY, dấu phân cách hàng nghìn là dấu chấm, tiền tệ VND gắn ₫ sau số và không có đơn vị thập phân. - Dự trù thời gian kiểm tra bố cục: chuỗi tiếng Việt thường dài hơn tiếng Anh 10-20%. Kiểm tra nhãn nút, tên tab và menu di động trước khi ra mắt.
Bản địa hóa ứng dụng Next.js sang tiếng Việt thực sự cần những gì?
Bản địa hóa ứng dụng Next.js bao gồm ba lớp riêng biệt: định tuyến (URL nào phục vụ ngôn ngữ nào), tải message (chuỗi nào hiển thị) và định dạng locale (ngày tháng, số và tiền tệ hiển thị như thế nào). Cả ba phải chính xác trước khi phiên bản tiếng Việt sẵn sàng cho môi trường production.
Lớp định tuyến là trách nhiệm của Next.js. Lớp message được xử lý bởi thư viện như next-intl, next-i18next hoặc Lingui. Lớp định dạng dùng JavaScript Intl API hoặc wrapper cấp cao hơn. Mỗi lớp có quy trình thiết lập rõ ràng cho tiếng Việt, và ba lớp hoạt động độc lập, vì vậy bạn có thể áp dụng từng bước.
Nên chọn thư viện i18n nào cho ứng dụng hỗ trợ tiếng Việt?
Ba thư viện chiếm ưu thế trong hệ sinh thái i18n của Next.js. Lựa chọn đúng phụ thuộc vào các ràng buộc của nhóm và mức độ bạn cần kiểm soát bề mặt i18n.
- next-intl: Khuyến nghị hiện tại của cộng đồng cho App Router. Cung cấp
defineRouting,createMiddleware,createNavigation, hỗ trợ ICU MessageFormat và khóa dịch có kiểu dữ liệu. Hoạt động với cả Server và Client Components. Khuyến nghị cho dự án App Router mới. - next-i18next: Được dùng rộng rãi trong thời Pages Router. Vẫn hoạt động với App Router qua lớp tương thích nhưng cài đặt phức tạp hơn. Phù hợp nếu nhóm đã quen với react-i18next.
- Mẫu từ điển tích hợp của Next.js: Tài liệu Next.js chính thức mô tả cách tiếp cận tối giản dùng
getDictionary()không cần thư viện bên thứ ba. Đủ cho ứng dụng nhỏ với chuỗi đơn giản, nhưng không có định dạng ICU hay xử lý số nhiều.
Với tiếng Việt, hỗ trợ ICU của next-intl quan trọng vì nó xử lý nhận thức số nhiều theo locale khi chạy, cho kết quả đúng với dạng số nhiều duy nhất của tiếng Việt mà không cần cấu hình thêm.
Tin nhắn ICU hoạt động thế nào khi tiếng Việt không có số nhiều?
Tiếng Anh có hai dạng số nhiều CLDR: one (số ít) và other (tất cả số còn lại). Tiếng Việt chỉ có một: other. Tất cả các số đều ánh xạ đến other trong tiếng Việt, vì tiếng Việt dùng danh từ chỉ loại và ngữ cảnh thay vì biến hình số nhiều.
Trong thực tế, điều này có nghĩa là tiếng Việt không bao giờ cần chuỗi số ít riêng biệt. Một message tiếng Anh có số nhiều như:
{count, plural, one {# result} other {# results}}
sẽ trở thành, trong file message tiếng Việt:
{count, plural, other {# kết quả}}
Người Việt nói "1 kết quả", "2 kết quả" dùng cùng một dạng, dựa vào số đứng trước để diễn đạt số lượng. Các selector khớp chính xác =0 và =1 vẫn có sẵn khi bạn cần message trạng thái rỗng hoặc trường hợp đặc biệt.
Định dạng ngày giờ dùng ICU skeletons hoặc kiểu được định sẵn trong next-intl. Với tiếng Việt, truyền locale: 'vi' hoặc locale: 'vi-VN'. API DateTimeFormat trả về DD/MM/YYYY cho ngày ngắn trong locale tiếng Việt.
Ngày tháng, số và tiền tệ tiếng Việt: cách cấu hình Intl
JavaScript Intl API với locale vi-VN xử lý định dạng tiếng Việt chính xác mà không cần code tùy chỉnh. Đây là các mẫu cần thiết lập trong ứng dụng:
- Ngày tháng:
new Intl.DateTimeFormat('vi-VN').format(date)trả về DD/MM/YYYY. Dùng{ dateStyle: 'short' }để xuất chỉ ngày tháng. - Số:
new Intl.NumberFormat('vi-VN').format(1500000)trả về1.500.000. Dấu chấm là dấu phân cách hàng nghìn; dấu phẩy là dấu thập phân. - Tiền tệ (VND):
new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND' }).format(250000)trả về250.000 ₫. VND không có đơn vị thập phân. - Sắp xếp: Thứ tự bảng chữ cái tiếng Việt khác với ASCII. Dùng
new Intl.Collator('vi').compaređể sắp xếp danh sách thả xuống hoặc kết quả tìm kiếm theo đúng thứ tự tiếng Việt. Bảng chữ cái tiếng Việt có 29 chữ cái cơ sở.
Trong next-intl, truyền chuỗi locale qua các helper định dạng của framework; chúng gọi đúng constructor Intl bên trong. Dữ liệu CLDR hỗ trợ locale vi được duy trì bởi dự án CLDR của Unicode Consortium và được cập nhật theo mỗi lần phát hành CLDR.
Chuỗi tiếng Việt dài hơn: danh sách kiểm tra bố cục và font chữ
Chuỗi tiếng Việt thường dài hơn tiếng Anh 10-20% trong văn xuôi tự nhiên. Nhãn UI, mục điều hướng và văn bản nút có nhiều khả năng bị tràn nhất. Hãy kiểm tra danh sách này trước khi ra mắt phiên bản tiếng Việt:
- Kiểm tra tất cả nhãn nút và văn bản CTA ở độ rộng màn hình di động (viewport 375px và 390px).
- Kiểm tra tab điều hướng và breadcrumb: danh từ ghép tiếng Việt thường mở rộng hơn so với khi tiếng Anh dùng động từ ngắn.
- Xác minh hỗ trợ font: tiếng Việt dùng dấu phụ kết hợp (sáu dấu thanh cộng dấu móc và dấu phụ trên chữ cái gốc). Font hệ thống có hỗ trợ UTF-8 xử lý đúng, nhưng bộ font web chỉ dành cho ký tự Latin có thể bỏ sót ký tự tiếng Việt. Kiểm tra với các ký tự như ộ, ề, ầ, ẫ, ắ.
- Đặt
lang="vi"trên phần tử<html>gốc. Quy tắc ngắt dòng và gạch nối phụ thuộc vào ngôn ngữ trong các trình duyệt hiện đại. - Dùng
overflow-wrap: break-wordlàm biện pháp an toàn: văn bản tiếng Việt ngắt ở dấu cách giữa các âm tiết, và thuật ngữ kỹ thuật dài có thể tràn trong container hẹp.
Tự làm hay thuê chuyên gia: ranh giới thực tế cho sản phẩm hướng đến Việt Nam
Công việc kỹ thuật, thiết lập định tuyến và kết nối ICU message là các tác vụ hoàn toàn có thể tự thực hiện. Bất kỳ lập trình viên nào với một ngày làm việc đều có thể cấu hình next-intl với locale vi và kết nối file message JSON. Dịch máy cộng kiểm tra mẫu hoạt động tốt với khối lượng lớn chuỗi UI có cấu trúc: nhãn form, thông báo lỗi và tài liệu trợ giúp.
Nơi chuyên gia người Việt bản địa thực sự tiết kiệm chi phí: nội dung marketing, giọng điệu UI sản phẩm và thuật ngữ chuyên ngành. Tiếng Việt có sự phân biệt giữa văn phong trang trọng và thân mật ảnh hưởng đến mức độ chuyên nghiệp của sản phẩm. Từ Hán-Việt (từ vựng mượn từ tiếng Hán cổ điển) thể hiện chuyên môn trong tài chính, y tế và pháp luật. Máy dịch thông thường mặc định dùng từ thuần Việt mà các chuyên gia thấy chưa chính xác.
Cách phân chia thực tế cho sản phẩm SaaS vào thị trường Việt Nam: dùng MT cho phần lớn nội dung trợ giúp, và thuê chuyên gia người Việt cho 50-100 chuỗi người dùng thấy mỗi phiên làm việc. Với sản phẩm B2B mà nhóm mua hàng sẽ đánh giá phiên bản tiếng Việt, nhờ người Việt bản địa kiểm tra toàn bộ UI trước khi ra mắt.
Với dịch thuật tiếng Anh-Việt chuyên nghiệp bao gồm website và UI SaaS, dịch vụ bản địa hóa website tiếng Việt trên trang này xử lý cả dịch thuật lẫn review kỹ thuật.
Câu hỏi thường gặp
Có thể dùng Pages Router i18n của Next.js cho tiếng Việt không?
Được. Pages Router có khóa i18n tích hợp trong next.config.js với locales và defaultLocale. Đặt locales: ['en', 'vi', 'zh', 'fr'] và defaultLocale: 'en'. Next.js tự động thêm tiền tố locale vào route. Phiên bản App Router tương đương dùng thư mục app/[lang]/ thủ công và proxy middleware, cho phép kiểm soát tốt hơn về hành vi xuất tĩnh.
Tiếng Việt có cần chuẩn hóa Unicode đặc biệt không?
Dấu phụ tiếng Việt có thể được mã hóa theo hai cách: dạng ghép sẵn (NFC, một code point cho mỗi ký tự có dấu) và dạng tách rời (NFD, ký tự cơ sở cộng với dấu kết hợp). Cả hai hiển thị giống nhau trong trình duyệt nhưng thất bại khi so sánh chuỗi. Chuẩn hóa sang NFC trong file message và mọi phép so sánh chuỗi. Trong JavaScript: str.normalize('NFC'). Điều này ngăn lỗi so sánh vô hình khi hai chuỗi tiếng Việt trông giống nhau nhưng không bằng nhau.
Nên dùng 'vi' hay 'vi-VN' làm mã locale?
Dùng vi làm thẻ ngôn ngữ chính. Theo hướng dẫn BCP 47 của W3C, giữ thẻ ngắn nhất có thể trừ khi cần phân biệt biến thể vùng. Với hầu hết sản phẩm, vi bao gồm tất cả người dùng tiếng Việt. Dùng vi-VN chỉ khi thư viện bên thứ ba yêu cầu mã locale đầy đủ để tra cứu dữ liệu.
Tiếng Việt ảnh hưởng thế nào đến thiết lập hreflang trong ứng dụng Next.js?
Giá trị hreflang cho trang tiếng Việt là vi. Trong next-intl, các helper điều hướng như Link và redirect tự động thêm tiền tố locale vào URL. Để xuất thẻ hreflang, thêm chúng vào generateMetadata() hoặc trong phần head của root layout. Mỗi trang cần thẻ alternate tự tham chiếu và alternate cho mọi phiên bản ngôn ngữ khác. Xem Google Search Central để biết yêu cầu liên kết hai chiều đầy đủ.
Tiếng Việt có phải ngôn ngữ viết từ phải sang trái không?
Tiếng Việt dùng chữ Latin và hoàn toàn viết từ trái sang phải. Không cần dir="rtl" hay CSS bidi. Mối quan tâm bố cục duy nhất là ngắt dòng trong container hẹp, vì văn bản tiếng Việt được cấu thành bằng các âm tiết phân cách bởi dấu cách. Dùng overflow-wrap: break-word để xử lý các trường hợp đặc biệt. Không có sự liên quan đến thuật toán bidi cho văn bản tiếng Việt.
Nguồn tham khảo
- Tài liệu Next.js: Quốc tế hóa - Mẫu định tuyến App Router, thiết lập proxy middleware, generateStaticParams cho locale và tải từ điển. Đã xác minh tháng 9 năm 2026.
- next-intl: Định tuyến i18n App Router - Thiết lập defineRouting, createMiddleware, createNavigation và ví dụ code. Đã xác minh tháng 9 năm 2026.
- Unicode CLDR: Quy tắc số nhiều theo ngôn ngữ - Dạng số nhiều CLDR cho tiếng Việt (một dạng "other" duy nhất). Đã xác minh tháng 9 năm 2026.
- W3C Internationalization: Chọn thẻ ngôn ngữ - Hướng dẫn BCP 47 về vi so với vi-VN cho tiếng Việt. Đã xác minh tháng 9 năm 2026.
Written by Dao Huy (Lucas), Vietnamese translator & localization specialist (EN · ZH · FR → Vietnamese). See translation services →
