Hướng dẫn multi-language i18n next js trên Next.js App Router: next-intl, routing và kiểm thử SEO
· Tác giả: Trường — Founder Webchốt
Sau nhiều lần debug merge nhầm file JSON khiến nút thanh toán tiếng Anh hiển thị copy tiếng Việt cũ, mình chốt một quy tắc: hướng dẫn multi-language i18n next js phải đi kèm quy trình người chứ không chỉ snippet npm. Bài viết này dành cho kỹ sư đang dùng App Router và muốn gắn next-intl để tách namespace message, giữ type an toàn hơn, và still ship nhanh. Bạn sẽ thấy vì sao segment [locale] nên đứng ngay dưới app, middleware chọn locale thế nào để không loop, và checklist hreflang trước khi bật index. Cuối bài có phần liên quan tới gói tại trang dịch vụ nếu muốn Webchốt lên chuẩn staging hai ngôn ngữ trong hai tuần.
Locale routing là phần nhìn thấy trên URL; đừng giấu ngôn ngữ sau cookie duy nhất | Nguồn: webchot.com
next-intl setup trên App Router: provider, messages và cấu trúc thư mục
Cài gói rồi tạo thư mục messages/ với vi.json, en.json (hoặc thêm locale khác). Khóa nên theo namespace feature ví dụ hero.title thay vì flat title để tránh đụng nhau khi dự án lớn. Trong app/[locale]/layout.tsx bọc NextIntlClientProvider với messages đã import theo locale param; phần server có thể dùng helper getMessages của thư viện để đồng bộ. Static path: khai generateStaticParams trả về danh sách locale để build SSG cho landing marketing.
Developer hay quên tách “chuỗi marketing dài” khỏi “chuỗi UI ngắn”; reviewer dịch sẽ bối rối nếu một key chứa cả đoạn HTML lẫn markdown. Chuẩn hoá markdown nhẹ hoặc rich text từ CMS riêng, còn UI string giữ plain. Khi thêm locale mới, chạy script diff key để biết EN thiếu gì so với VI trước khi ship.
Middleware locale matching và tránh redirect vòng
Middleware đọc pathname; nếu thiếu prefix locale hợp lệ thì redirect sang default (thường vi) nhưng phải whitelist file tĩnh và route API auth. Sai lần thường gặp là matcher quá rộng khiến webhook bị redirect 307 — làm hỏng tích hợp thanh toán. Một pattern an toàn: chỉ enforce locale cho các path front-store, để /api/* đi thẳng. Cookie ghi nhớ lựa chọn người dùng có thể set sau lần đổi ngôn từ menu; lần sau middleware ưu tiên cookie trước Geo IP.
- Điểm 1: Luôn log vào staging khi redirect xảy ra để dễ tái hiện loop.
- Điểm 2: Test trình duyệt ẩn danh để chắc default locale đúng khi chưa có cookie.
- Điểm 3: Kiểm tra link nội bộ: helper
Linkcủa next-intl giữ prefix locale tự động. - Điểm 4: Không đoán ngôn ngữ chỉ bằng Geo IP cho trang legal; có thể vi phạm kỳ vọng khách FDI.
Bảng so sánh: subpath locale so với tách microsite theo tên miền
Ước lượng nhanh chi phí vận hành năm đầu cho team 5 người marketing + 2 dev.
| Tiêu chí | Lựa chọn A | Lựa chọn B | Khuyên dùng |
|---|---|---|---|
| SEO tập trung domain authority | Cao (/vi /en chung apex) | Thấp hơn nếu tách domain mới | A nếu brand một |
| Cookie session đơn giản | Dễ chia sẻ | Cần cross-domain | A |
| Tốc độ tách team theo thị trường | Chậm hơn | Nhanh nếu microsite độc lập | B khi pháp lý bắt buộc |
| hreflang phức tạp | Vừa phải | Cao nếu nhiều apex | A cho SME xuất khẩu |
Với khách Webchốt là xưởng cơ khí hoặc SaaS B2B, A thường đủ; chỉ chọn B khi hợp đồng bảo hiểm hoặc data residency bắt tách hẳn. Khi chọn A, nhớ map OG và canonical theo từng locale — share Zalo lấy đúng title tiếng Việt, LinkedIn share bản EN không bị lệch.
Năm bước triển khai thực tế từ staging tới production
- Bước 1: Dựng nhánh git
feature/i18n, tách toàn bộ chuỗi UI sang JSON, CI chạy grep cấm chuỗi tiếng Việt hardcode trong component client (trừ proper noun). - Bước 2: Thêm middleware và
[locale]; viết test Playwright đổi locale và assert URL + text hero. - Bước 3: Sinh
sitemap-*.xmlper locale; upload Search Console; bật noindex trên staging. - Bước 4: Proofread trang pricing và điều khoản trước khi mở index; đồng bộ email template Stripe hoặc cổng thanh toán địa phương.
- Bước 5: Monitor tuần đầu: crawl errors, duplicate title, bounce theo locale trong GA4 — điều chỉnh fallback nếu thấy người dùng nhảy locale bất thường.
Sau bước 5 nếu vẫn thấy hreflang báo đỏ trong GSC, đừng sửa tay từng URL — kiểm tra template server có strip thẻ do compression CDN. Một lần Cloudflare minify HTML đã làm mất chuỗi alternate; tắt minify cho path blog fix ngay.
Chi phí, phạm vi dự án và lúc cần đội triển khai
Hướng dẫn multi-language i18n next js trên lý thuyết gọn, nhưng chi phí ẩn nằm ở QA layout (tiếng Đức dài hơn 30%) và đồng bộ CMS. Nếu bạn đã có designer hệ thống component, phần code có thể hai đến ba sprint; nếu phải refactor page lớn trước đó dùng hardcode, hãy nhân đôi thời gian. Gói thực tế: audit code + dựng skeleton next-intl + 2 locale + hreflang + 10 trang ưu tiên; phần dịch nội dung marketing tính riêng theo từ. Xem thêm mô-đun và SLA tại dịch vụ Webchốt — có phân nhánh gói SEO đa vùng và retainer bảo trì sau go-live.
Khi cần cam kết bảo hành mười hai tháng, team Webchốt ghim checklist regression locale mỗi lần release; khách chỉ cần gửi PR message JSON là có preview Vercel với hai ngôn ngữ. Đừng quên kênh liên hệ cho các yêu cầu gấp về hreflang khi đổi slug hàng loạt sau rebranding.
Sai lầm phổ biến khi làm i18n vội
Danh sách này đến từ log support thực tế, không phải lý thuyết sách trắng.
- Sai lầm 1: Để SEO title/ description dùng cùng chuỗi giữa VI và EN khiến Google coi duplicate; mỗi locale cần biên tập riêng kể cả khi ý nghĩa giống.
- Sai lầm 2: Dùng cờ quốc gia làm icon ngôn ngữ — gây nhầm locale (EN UK vs EN US) và phản cảm văn hoá.
- Sai lầm 3: Quên định dạng tiền: hiển thị VND kiểu US trong locale EN làm buyer doanh nghiệp nghi ngờ độ chính xác hợp đồng.
- Sai lầm 4: Publish bản machine translate thô cho trang money mà không noindex, dẫn đến thin content penalty khó gỡ.
FAQ — hướng dẫn multi-language i18n next js
next-intl có bắt buộc không hay chỉ là lựa chọn tiện?
Không bắt buộc; Next.js cho phép tự fetch dictionary theo locale. Điểm mạnh của next-intl là convention rõ, hooks thống nhất và tài liệu cập nhật theo App Router. Đội lớn có thể fork wrapper riêng, đội nhỏ thường tiết kiệm thời gian nhờ ecosystem. Nếu dự án cần ICU phức tạp hoặc runtime override message từ CMS, vẫn có thể kết hợp loader động thay vì chỉ file JSON tĩnh — miễn là pipeline cache và invalidation được thiết kế trước.
Làm sao test nhanh khi thêm locale thứ ba?
Thêm file JSON, mở rộng mảng locale trong middleware và generateStaticParams, rồi chạy Storybook hoặc page test nhỏ trước khi lăn toàn site. Viết một test đơn vị đảm bảo mọi key critical path checkout đều tồn tại; nếu thiếu, fail build. Staging nên bật banner “locale beta” để người nội bộ báo lỗi wording trước khi công khai.
Có nên dùng Google Translate plugin cho người dùng cuối?
Widget dịch tự động tiện demo nhưng làm xấu layout và có thể đụng điều khoản privacy nếu gửi text ra ngoài trình duyệt. Với thương hiệu B2B, tốt hơn là bản dịch biên tập và tắt auto translate trên trang giá và pháp lý. Nếu vẫn muốn hỗ trợ khẩn cấp, chỉ bật ở blog kiến thức chung kèm disclaimer.
Server Actions và form error message đa ngôn ngữ thế nào?
Trả mã lỗi enum từ server rồi map sang message ở client theo locale hiện tại; tránh nhúng chuỗi đã dịch sẵn từ server nếu không truyền locale nhất quán. Với Zod schema, có thể dùng adapter dịch message lỗi theo dictionary. Luôn log locale vào Sentry để tái hiện bug “tiếng lẫn”.
Webchốt hỗ trợ gì nếu tôi đã có code nhưng hreflang lỗi?
AuditDiff trang chủ và template ưu tiên, export bảng mapping URL đôi bên, sửa template head và sitemap, sau đó gửi lại Search Console validation. Nếu cần, team có thể thay middleware matcher và đồng bộ CMS webhook — xem gói cụ thể ở dich-vu và pricing để chọn phạm vi giờ.
Liên Hệ Webchốt
Khi bạn cần đóng gói hướng dẫn multi-language i18n next js thành repo chạy được production — gồm next-intl, middleware, message lint và checklist hreflang — cứ gửi link GitHub hoặc zip dự án qua email. Trong 48 giờ làm việc, Webchốt có thể trả bản đánh giá rủi ro routing và đề xuất sprint không làm gián đoạn release hiện tại. Hotline dưới đây kết nối thẳng founder để tranh luận kỹ thuật cụ thể (segment vs cookie, static export hay SSR). Nếu bạn đang ở giai đoạn RFP, nhắc rõ số locale dự kiến và có cần tuân thủ EU cookie hay không để báo giá sát.
- Hotline / Zalo: 0905 151 701 — gặp anh Trường (founder/dev).
- Chat Zalo: zalo.me/0905151701 — phản hồi nhanh.
- Email: hi@webchot.com — phản hồi <12h làm việc.
- Studio: 262/1/93 Phan Anh, Phường Phú Thạnh, TP.HCM (T2–T7, 9h–18h).
Tham khảo thêm: 17 template Next.js · 10 dịch vụ web chuyên sâu · bảng giá Webchốt 2026 · 12 công cụ kế toán/tài chính miễn phí · trang liên hệ.
Reference: Next.js docs · web.dev Core Web Vitals.