refactor: enhance i18n handling by implementing state management for active language and optimizing resource loading
This commit is contained in:
@@ -1,48 +1,87 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation, changeLanguage, i18n } from '@repo/core-i18n';
|
||||
|
||||
// Decentralized locale imports
|
||||
import homeId from '../locales/id/home.json';
|
||||
import homeEn from '../locales/en/home.json';
|
||||
|
||||
export default function I18nLandingSample() {
|
||||
const { t } = useTranslation(['common', 'home']);
|
||||
// Bendera penanda statis di level modul (default: false)
|
||||
let isHomeDictLoaded = false;
|
||||
|
||||
// 1. Lazy-load the 'home' namespace when the module mounts
|
||||
useEffect(() => {
|
||||
export default function I18nLandingSample() {
|
||||
// 1. Eksekusi SINKRONUS tepat sebelum render pertama (hanya berjalan 1x)
|
||||
if (!isHomeDictLoaded) {
|
||||
i18n.addResourceBundle('id', 'home', homeId, true, false);
|
||||
i18n.addResourceBundle('en', 'home', homeEn, true, false);
|
||||
isHomeDictLoaded = true; // Kunci benderanya agar tidak jalan lagi saat re-render
|
||||
}
|
||||
|
||||
// 2. Sekarang useTranslation akan melihat kamus yang sudah siap
|
||||
const { t } = useTranslation(['common', 'home']);
|
||||
|
||||
const [activeLang, setActiveLang] = useState(i18n.language);
|
||||
|
||||
useEffect(() => {
|
||||
const handleLangChange = (lng: string) => setActiveLang(lng);
|
||||
i18n.on('languageChanged', handleLangChange);
|
||||
|
||||
return () => {
|
||||
i18n.off('languageChanged', handleLangChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 2. Change language without syncCallback to prove decoupling
|
||||
const setLanguage = (lng: string) => {
|
||||
// We intentionally omit the second argument (syncCallback)
|
||||
// because the landing page is public and doesn't need backend syncing.
|
||||
changeLanguage(lng).catch(console.error);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: 40, textAlign: 'center', backgroundColor: '#f8fafc', color: '#0f172a' }}>
|
||||
<h1 style={{ fontSize: 36, fontWeight: 'bold', marginBottom: 16 }}>
|
||||
{t('home:welcome')}
|
||||
</h1>
|
||||
|
||||
<h1 style={{ fontSize: 36, fontWeight: 'bold', marginBottom: 16 }}>{t('home:welcome')}</h1>
|
||||
|
||||
<div style={{ marginBottom: 32 }}>
|
||||
<button
|
||||
<button
|
||||
onClick={() => setLanguage('id')}
|
||||
style={{ padding: '8px 16px', marginRight: 8, cursor: 'pointer', borderRadius: 4, background: '#3b82f6', color: 'white', border: 'none' }}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
marginRight: 8,
|
||||
cursor: 'pointer',
|
||||
borderRadius: 4,
|
||||
background: activeLang === 'id' ? '#1d4ed8' : '#93c5fd',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
fontWeight: activeLang === 'id' ? 'bold' : 'normal',
|
||||
}}
|
||||
>
|
||||
Bahasa Indonesia
|
||||
</button>
|
||||
<button
|
||||
<button
|
||||
onClick={() => setLanguage('en')}
|
||||
style={{ padding: '8px 16px', cursor: 'pointer', borderRadius: 4, background: '#3b82f6', color: 'white', border: 'none' }}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
cursor: 'pointer',
|
||||
borderRadius: 4,
|
||||
background: activeLang === 'en' ? '#1d4ed8' : '#93c5fd',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
fontWeight: activeLang === 'en' ? 'bold' : 'normal',
|
||||
}}
|
||||
>
|
||||
English
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button style={{ padding: '16px 32px', fontSize: 18, fontWeight: 'bold', cursor: 'pointer', borderRadius: 8, background: '#10b981', color: 'white', border: 'none' }}>
|
||||
<button
|
||||
style={{
|
||||
padding: '16px 32px',
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
cursor: 'pointer',
|
||||
borderRadius: 8,
|
||||
background: '#10b981',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
}}
|
||||
>
|
||||
{t('home:cta')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user