Appearance
Internationalization (i18n)
Setup
- Library: i18next + react-i18next + i18next-http-backend
- Languages:
id(Indonesian, default) +en(English) - Namespace:
common - Translation files:
public/locales/{lang}/common.json
Using Translations
tsx
import { useI18n } from '@/hooks';
const { t, lang, setLang } = useI18n();
t('nav.dashboard') // → 'Dasbor' (id) | 'Dashboard' (en)
t('auth.login.title') // → 'Masuk ke Hermina 360' (id)
t('validation.required', { field: 'Email' }) // → 'Email wajib diisi'Translation File Structure
public/locales/id/common.json:
json
{
"app": { "name": "Hermina 360" },
"nav": { "dashboard": "Dasbor", "logout": "Keluar" },
"auth": {
"login": {
"title": "Masuk ke Hermina 360",
"email": "Email"
}
},
"validation": { "required": "{{field}} wajib diisi" },
"dashboard": {
"executive": { "title": "Ringkasan Eksekutif" }
}
}Adding a New Key
- Add to
public/locales/id/common.json - Add to
public/locales/en/common.json - Use in component:
t('your.new.key')
Switching Language
tsx
const { setLang } = useI18n();
setLang('en'); // persists to localStorage, syncs i18nextAnt Design Locale
The Ant Design locale is synced to the active language in src/main.tsx:
ts
const antdLocaleMap = { id: idID, en: enUS };
<ConfigProvider locale={antdLocaleMap[lang]}>Language Store
Language is persisted in useLanguageStore (key: hermina360-lang). On hydration, it automatically syncs with i18next.