-
Notifications
You must be signed in to change notification settings - Fork 11
Add i18next integration #242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
All contributors have signed the DCO. |
ebabe0d to
8894c30
Compare
|
I have read the DCO document and I hereby sign the DCO. |
| import i18n from './i18n.client.js'; | ||
|
|
||
| // Hydrate i18n with server state to prevent flicker | ||
| const { initialI18nStore, initialLanguage } = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this we get "Willkommen" -> "Welcome" -> "Willkommen" because server first gets the language from the headers, returns German, then the client side is initializing its json language file and because this is async it shows English for a split second and this causes flicker. Happy to do it in a more elegant way but this is what Bob suggested after a lot of back and forth 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this comment into a code comment please.
| supportedLngs: ['en', 'de'], | ||
|
|
||
| // Important for SSR | ||
| useSuspense: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReactDOMServer does not yet support Suspense
| preload: ['en', 'de'], // Preload all languages on server | ||
|
|
||
| // Important for SSR | ||
| useSuspense: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReactDOMServer does not yet support Suspense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add this in the comments. This needs to be an easy to find information for users.
| }; | ||
|
|
||
| const head = `<meta name="description" content="Server-side rendered page"> | ||
| <script>window.__INITIAL_I18N_STATE__ = ${JSON.stringify(initialState).replace(/</g, '\\u003c')}</script>`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this even the very first response from the server will contain the correct language that was sent in the request headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into a code comment please.
| // https://vite.dev/config/ | ||
| export default defineConfig({ | ||
| plugins: [react()], | ||
| plugins: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can also be loaded via native json file loaders but this one seemed reasonable to use https://www.npmjs.com/package/vite-plugin-i18next-loader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into a code comment please.
- Install i18next and react-i18next with full SSR support - Configure client-side i18n with browser language detection - Configure server-side i18n with filesystem backend - Add improved German translations (idiomatic business German) - Integrate with Vite via i18next-loader plugin - Add i18next middleware to Express server - Update server-side entry to serialize translations for hydration - Update client-side entry to hydrate with server state - Translate all Welcome page content with defaultValue pattern - Document i18n usage and architecture in CLAUDE.md English text stays inline in components as defaultValue. Other languages defined in src/locales/*.json files. Browser automatically detects user's preferred language. No language flicker due to proper SSR hydration.
c5734a7 to
6d36394
Compare
rodet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I think this works great, good job @Josip-Ledic .
Two things to change before we release this:
- Update the copyright years for each file here
- Move a bunch of your PR explanation comments into the code so those don't get lost. They are valuable piece of information that should be in the code.
src/components/footer/Footer.jsx
Outdated
| <p>Footer</p> | ||
| <p>Copyright IBM 2025</p> | ||
| <p>{t('footer.title', 'Footer')}</p> | ||
| <p>{t('footer.copyright', 'Copyright IBM 2026')}</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be "Copyright IBM 2025, 2026" (original date, last edit date) instead
src/pages/dashboard/Dashboard.jsx
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright update needed 2025, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright update needed 2025, 2026
| preload: ['en', 'de'], // Preload all languages on server | ||
|
|
||
| // Important for SSR | ||
| useSuspense: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add this in the comments. This needs to be an easy to find information for users.
| // https://vite.dev/config/ | ||
| export default defineConfig({ | ||
| plugins: [react()], | ||
| plugins: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into a code comment please.
| }; | ||
|
|
||
| const head = `<meta name="description" content="Server-side rendered page"> | ||
| <script>window.__INITIAL_I18N_STATE__ = ${JSON.stringify(initialState).replace(/</g, '\\u003c')}</script>`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into a code comment please.
| import i18n from './i18n.client.js'; | ||
|
|
||
| // Hydrate i18n with server state to prevent flicker | ||
| const { initialI18nStore, initialLanguage } = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this comment into a code comment please.
i18n is a significant feature that warrants this upgrade
Summary
t('someKey', "Default value in English co-located like this")