Loading header...

Hướng dẫn sử dụng tính năng đa ngôn ngữ

Giới thiệu

Dự án sử dụng next-intl để hỗ trợ đa ngôn ngữ, cho phép hiển thị nội dung trong nhiều ngôn ngữ khác nhau. Hệ thống đa ngôn ngữ được tích hợp sâu vào routing và SEO của Next.js.

Cấu trúc thư mục

/
├── src/
│   ├── app/
│   │   ├── [locale]/      # Route động theo ngôn ngữ
│   ├── i18n/
│   │   ├── locales/       # File dịch theo ngôn ngữ
│   │   │   ├── en.json    # Tiếng Anh
│   │   │   └── vi.json    # Tiếng Việt
│   │   ├── i18n-navigation.ts # Cấu hình navigation đa ngôn ngữ
│   │   └── index.ts       # Cấu hình chung
│   └── middleware.ts      # Middleware xử lý ngôn ngữ

File ngôn ngữ

File ngôn ngữ được lưu trữ dưới dạng JSON trong thư mục src/i18n/locales/.

Ví dụ vi.json:

1{ 2 "layout": { 3 "home": "Trang chủ", 4 "about": "Giới thiệu", 5 "blog": "Blog", 6 "contact": "Liên hệ" 7 }, 8 "home": { 9 "hero": { 10 "title": "Chào mừng đến với Next.js Boilerplate", 11 "description": "Một boilerplate hiện đại để xây dựng ứng dụng web.", 12 "cta": "Tìm hiểu thêm" 13 }, 14 "featured_posts": { 15 "title": "Bài viết nổi bật", 16 "description": "Khám phá những bài viết mới nhất từ blog của chúng tôi.", 17 "view_all": "Xem tất cả" 18 } 19 } 20}

Sử dụng trong Client Components

Hook useTranslations

1'use client'; 2 3import { useTranslations } from 'next-intl'; 4 5export default function Header() { 6 const t = useTranslations(); 7 8 return ( 9 <header> 10 <nav> 11 <ul> 12 <li>{t('layout.home')}</li> 13 <li>{t('layout.about')}</li> 14 <li>{t('layout.blog')}</li> 15 <li>{t('layout.contact')}</li> 16 </ul> 17 </nav> 18 </header> 19 ); 20}

Chuyển đổi ngôn ngữ

1'use client'; 2 3import { useLocale } from 'next-intl'; 4import { Link } from '@/i18n/i18n-navigation'; 5 6export default function LanguageSwitcher() { 7 const locale = useLocale(); 8 9 return ( 10 <div> 11 <Link href="/" locale="vi" className={locale === 'vi' ? 'active' : ''}> 12 Tiếng Việt 13 </Link> 14 <Link href="/" locale="en" className={locale === 'en' ? 'active' : ''}> 15 English 16 </Link> 17 </div> 18 ); 19}

Sử dụng trong Server Components

Sử dụng getTranslations

1import { getTranslations } from 'next-intl/server'; 2 3export default async function Page({ 4 params: { locale }, 5}: { 6 params: { locale: string }; 7}) { 8 const t = await getTranslations({ 9 locale, 10 }); 11 12 return ( 13 <main> 14 <h1>{t('home.hero.title')}</h1> 15 <p>{t('home.hero.description')}</p> 16 <button>{t('home.hero.cta')}</button> 17 </main> 18 ); 19}

Định tuyến với Link đa ngôn ngữ

1import { Link } from '@/i18n/i18n-navigation'; 2 3export default function Navigation() { 4 return ( 5 <nav> 6 <ul> 7 <li> 8 <Link href="/">Trang chủ</Link> 9 </li> 10 <li> 11 <Link href="/about">Giới thiệu</Link> 12 </li> 13 <li> 14 <Link href="/blog">Blog</Link> 15 </li> 16 </ul> 17 </nav> 18 ); 19}

Định tuyến đa ngôn ngữ

Cấu hình tuyến đường

File src/i18n/i18n-navigation.ts chứa cấu hình cho các tuyến đường đa ngôn ngữ:

1export const routing = { 2 locales: ['vi', 'en'], 3 defaultLocale: 'vi', 4}; 5 6export const routePatterns = { 7 // Các tuyến đường có path khác nhau giữa các ngôn ngữ 8 about: { 9 vi: 'gioi-thieu', 10 en: 'about', 11 }, 12 blog: { 13 vi: 'blog', 14 en: 'blog', 15 }, 16 contact: { 17 vi: 'lien-he', 18 en: 'contact', 19 }, 20 policy: { 21 vi: 'chinh-sach', 22 en: 'policy', 23 }, 24};

Middleware

Middleware trong src/middleware.ts xử lý việc chuyển hướng:

1export function middleware(request: NextRequest) { 2 // Kiểm tra ngôn ngữ hợp lệ 3 // Chuyển hướng nếu cần thiết 4 // Xử lý URL theo quy tắc đa ngôn ngữ 5}

Metadata đa ngôn ngữ cho SEO

1import { createPageMetadata, generateMetadata } from '@/utils/seo'; 2 3export async function generateMetadata({ 4 params: { locale }, 5}: { 6 params: { locale: string }; 7}) { 8 const metadataProps = createPageMetadata('home', locale); 9 return generateMetadata(metadataProps); 10}

Thêm hoặc sửa đổi nội dung đa ngôn ngữ

  1. Thêm key mới vào file ngôn ngữ: Đảm bảo thêm cho tất cả các ngôn ngữ được hỗ trợ
  2. Sử dụng key trong component: t('your.new.key')
  3. Cập nhật tuyến đường mới trong routePatterns nếu cần thiết

Thêm ngôn ngữ mới

  1. Tạo file JSON mới trong src/i18n/locales/ (vd: fr.json cho tiếng Pháp)
  2. Cập nhật mảng locales trong src/i18n/i18n-navigation.ts
  3. Thêm tuyến đường cho ngôn ngữ mới trong routePatterns
  4. Cập nhật các cấu hình SEO và metadata

Các function hữu ích

useLocale

Lấy ngôn ngữ hiện tại trong client component:

1import { useLocale } from 'next-intl'; 2 3export default function Example() { 4 const locale = useLocale(); // 'vi' hoặc 'en' 5 return <div>Current locale: {locale}</div>; 6}

setRequestLocale

Thiết lập ngôn ngữ cho server component:

1import { setRequestLocale } from 'next-intl/server'; 2 3export default async function Page({ 4 params: { locale }, 5}: { 6 params: { locale: string }; 7}) { 8 setRequestLocale(locale); 9 // ... 10}

Các thực tiễn tốt nhất

  1. Nhất quán key: Sử dụng cấu trúc key nhất quán trong tất cả các file dịch
  2. Tái sử dụng text: Sử dụng text đã dịch trong các file ngôn ngữ thay vì hardcode
  3. SEO thân thiện: Tùy chỉnh metadata cho mỗi ngôn ngữ
  4. URL thân thiện: Sử dụng routePatterns để có URL thân thiện theo từng ngôn ngữ
  5. Kiểm tra: Luôn kiểm tra tất cả các ngôn ngữ được hỗ trợ khi thêm tính năng mới
  6. Fallback: Sử dụng fallback cho các key chưa được dịch

Xử lý ngôn ngữ trong API

Khi gọi API, bạn có thể thiết lập ngôn ngữ cho request:

1import { setApiLocale } from '@/services/api-client'; 2 3// Thiết lập ngôn ngữ cho API 4setApiLocale(locale); 5 6// Hoặc lấy dữ liệu theo ngôn ngữ cụ thể 7const post = await apiService.fetchItem('posts', slug, locale, [ 8 'title', 'content' 9]);

Đầu tư là chiến thuật. Cấu trúc là chiến lược.