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ữ
- 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ợ
- Sử dụng key trong component:
t('your.new.key') - Cập nhật tuyến đường mới trong
routePatternsnếu cần thiết
Thêm ngôn ngữ mới
- Tạo file JSON mới trong
src/i18n/locales/(vd:fr.jsoncho tiếng Pháp) - Cập nhật mảng
localestrongsrc/i18n/i18n-navigation.ts - Thêm tuyến đường cho ngôn ngữ mới trong
routePatterns - 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
- 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
- Tái sử dụng text: Sử dụng text đã dịch trong các file ngôn ngữ thay vì hardcode
- SEO thân thiện: Tùy chỉnh metadata cho mỗi ngôn ngữ
- URL thân thiện: Sử dụng
routePatternsđể có URL thân thiện theo từng ngôn ngữ - 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
- 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]);
