Internationalization (i18n) trong Astro: Hướng dẫn xây dựng Web đa ngôn ngữ
Web đa ngôn ngữ không còn là cơn ác mộng. Hướng dẫn sử dụng module i18n native của Astro để định tuyến và dịch thuật nội dung một cách mượt mà.
Ngày xưa làm web đa ngôn ngữ (i18n) là một cực hình đúng nghĩa. Nào là cấu hình routing /en, /vi, rồi xử lý SEO hreflang, chưa kể đến việc quản lý hàng đống file JSON bản dịch.
Nhưng kể từ phiên bản Astro 4.0 trở đi, i18n routing đã trở thành tính năng native (có sẵn). Bạn không cần cài thêm thư viện nặng nề nào cả. Hôm nay tôi sẽ guide các bạn cách setup một website hỗ trợ tiếng Việt (mặc định) và tiếng Anh.
1. Cấu hình astro.config.mjs
Đầu tiên, hãy báo cho Astro biết site của mình hỗ trợ những ngôn ngữ nào.
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
i18n: {
defaultLocale: 'vi',
locales: ['vi', 'en'],
routing: {
prefixDefaultLocale: false // URL tiếng Việt sẽ là /, tiếng Anh là /en/
// Nếu để true: Tiếng Việt sẽ là /vi/, tiếng Anh là /en/
},
fallback: {
en: 'vi' // Nếu trang tiếng Anh chưa có, fallback về tiếng Việt (option này tùy version)
}
}
});
Điều này giúp Astro tự động hiểu và xử lý các trang trong thư mục src/pages.
2. Tổ chức thư mục file
Với cấu hình trên, bạn cần tổ chức thư mục src/pages như sau:
src/pages/
index.astro (Trang chủ Tiếng Việt)
gioi-thieu.astro (Trang giới thiệu TV)
en/
index.astro (Trang chủ Tiếng Anh)
about.astro (Trang giới thiệu TA)
Astro rất thông minh, nó sẽ map src/pages/en/index.astro thành URL your-site.com/en/.
3. Dịch UI Strings (Labels, Buttons)
Routing đã xong, giờ đến phần nội dung tĩnh như menu, footer. Tôi thường tạo một folder src/i18n/ để chứa các “từ điển”.
// src/i18n/ui.ts
export const languages = {
vi: 'Tiếng Việt',
en: 'English',
};
export const defaultLang = 'vi';
export const ui = {
vi: {
'nav.home': 'Trang chủ',
'nav.about': 'Giới thiệu',
'footer.contact': 'Liên hệ ngay',
},
en: {
'nav.home': 'Home',
'nav.about': 'About',
'footer.contact': 'Contact Now',
},
} as const;
// Helper function để dùng trong file .astro
export function useTranslations(lang: keyof typeof ui) {
return function t(key: keyof typeof ui[typeof defaultLang]) {
return ui[lang][key] || ui[defaultLang][key];
}
}
Cách dùng trong component:
---
// src/components/Nav.astro
import { useTranslations } from '../i18n/ui';
const { lang } = Astro.props; // Truyền 'vi' hoặc 'en' vào props
const t = useTranslations(lang);
---
<nav>
<a href="/">{t('nav.home')}</a>
<a href="/about">{t('nav.about')}</a>
</nav>
4. Content Collections đa ngôn ngữ
Với bài viết Blog (Markdown), tôi thường đặt tên file có hậu tố ngôn ngữ thay vì chia folder, để dễ quản lý cặp bài viết.
Ví dụ: first-post.vi.md và first-post.en.md.
Hoặc chia folder:
src/content/blog/
en/
post-1.md
vi/
post-1.md
Khi query getCollection, bạn chỉ cần filter theo slug bắt đầu bằng lang hoặc dựa vào id của file.
const posts = await getCollection('blog', ({ id }) => {
return id.startsWith('vi/');
});
Kết luận
Astro i18n Routing bây giờ đã rất ổn định. Nó giải quyết 90% các vấn đề đau đầu về routing và SEO (tự động gen sitemap theo locale nếu dùng plugin sitemap). Nếu bạn định làm blog tech vươn tầm thế giới, hãy setup i18n ngay từ ngày đầu tiên (Day 1), đừng để code xong hết rồi mới refactor thì cực lắm!
Cấu hình i18n chính của Astro thường nằm ở file nào?
Thử Thách Kiến Thức Lịch Sử?
Khám phá hàng trăm câu hỏi trắc nghiệm lịch sử thú vị tại HistoQuiz. Vừa học vừa chơi, nâng cao kiến thức ngay hôm nay!