Đưa ngôn ngữ hiện tại thành state của ứng dụng chứ không phải biến đọc một lần lúc khởi động.
Khi state đổi, React render lại và mọi chuỗi được lấy lại từ từ điển.
jsx
const LanguageContext = createContext(null)
function LanguageProvider({ children }) {
const [locale, setLocale] = useState(() => localStorage.getItem('locale') ?? 'vi')
useEffect(() => {
localStorage.setItem('locale', locale)
document.documentElement.lang = locale
}, [locale])
const t = (key) => DICT[locale][key] ?? key
return <LanguageContext value={{ locale, setLocale, t }}>{children}</LanguageContext>
}Những điểm cần nói thêm:
- Không hardcode chuỗi trong component. Mọi văn bản đi qua
t(key)hoặc một object song ngữ, nếu không thì đổi ngôn ngữ chỉ đổi được một nửa màn hình. - Cập nhật
document.documentElement.langđể trình đọc màn hình và công cụ dịch nhận đúng ngôn ngữ. - Chuỗi có biến và số nhiều phải dùng placeholder (
Xin chào {name}), không nối chuỗi theo trật tự tiếng Việt vì trật tự từ mỗi ngôn ngữ mỗi khác. - Ngày tháng và tiền không dịch tay mà để
Intlxử lý theo locale. - Nội dung từ server (tên sản phẩm, thông báo lỗi) cần gửi kèm header ngôn ngữ, đổi locale thì gọi lại API — dịch phía client không xử lý được phần này.
Nếu cần SEO cho cả hai ngôn ngữ thì locale phải nằm trong URL (/vi/..., /en/...) chứ không chỉ trong localStorage, để mỗi ngôn ngữ có một địa chỉ riêng cho bot lập chỉ mục.