feat: implement core-i18n package with decentralized namespace support and integrate into landing and web apps
This commit is contained in:
@@ -12,11 +12,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@repo/core-api": "workspace:*",
|
||||
"@repo/core-i18n": "workspace:*",
|
||||
"@repo/ui": "workspace:*",
|
||||
"@repo/utils": "workspace:*",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"i18next": "^24.2.2",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"react-i18next": "^15.4.0",
|
||||
"tailwindcss": "^4.1.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ThemeProvider } from '@repo/ui/provider';
|
||||
import { Button } from '@repo/ui/components';
|
||||
import LandingSample from './features/public-content/presentation/LandingSample';
|
||||
import I18nLandingSample from './presentation/I18nLandingSample';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -36,6 +37,7 @@ export default function App() {
|
||||
<h1 className="text-2xl font-bold mb-4">Enterprise Web App</h1>
|
||||
<LandingSample />
|
||||
</div>
|
||||
<I18nLandingSample />
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"welcome": "Welcome to Our Product",
|
||||
"cta": "Get Started Now"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"welcome": "Selamat Datang di Produk Kami",
|
||||
"cta": "Mulai Sekarang"
|
||||
}
|
||||
@@ -15,10 +15,17 @@ initTelemetry({
|
||||
import './main.css';
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { setupI18n } from '@repo/core-i18n';
|
||||
import App from './app';
|
||||
|
||||
createRoot(document.getElementById('app')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
);
|
||||
async function bootstrap() {
|
||||
await setupI18n();
|
||||
|
||||
createRoot(document.getElementById('app')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
);
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { useEffect } 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']);
|
||||
|
||||
// 1. Lazy-load the 'home' namespace when the module mounts
|
||||
useEffect(() => {
|
||||
i18n.addResourceBundle('id', 'home', homeId, true, false);
|
||||
i18n.addResourceBundle('en', 'home', homeEn, true, false);
|
||||
}, []);
|
||||
|
||||
// 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>
|
||||
|
||||
<div style={{ marginBottom: 32 }}>
|
||||
<button
|
||||
onClick={() => setLanguage('id')}
|
||||
style={{ padding: '8px 16px', marginRight: 8, cursor: 'pointer', borderRadius: 4, background: '#3b82f6', color: 'white', border: 'none' }}
|
||||
>
|
||||
Bahasa Indonesia
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setLanguage('en')}
|
||||
style={{ padding: '8px 16px', cursor: 'pointer', borderRadius: 4, background: '#3b82f6', color: 'white', border: 'none' }}
|
||||
>
|
||||
English
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button style={{ padding: '16px 32px', fontSize: 18, fontWeight: 'bold', cursor: 'pointer', borderRadius: 8, background: '#10b981', color: 'white', border: 'none' }}>
|
||||
{t('home:cta')}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
import 'react-i18next';
|
||||
// Import the core types so we don't break the common namespace
|
||||
import type { resources as coreResources } from '@repo/core-i18n/src/setup';
|
||||
import homeEn from '../locales/en/home.json';
|
||||
|
||||
// Combine core resources with app-specific decentralized resources
|
||||
declare module 'react-i18next' {
|
||||
interface CustomTypeOptions {
|
||||
defaultNS: 'common';
|
||||
resources: typeof coreResources['en'] & {
|
||||
home: typeof homeEn;
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user