x
This commit is contained in:
1 parent
6f67ee6077
commit
62db477dbd
13 files changed
+660
-98
No files matched your search
@@ -1,21 +1,34 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import i18n from '../lib/i18n'
|
||||
|
||||
/**
|
||||
* Returns the current i18n language code (2-char) in a hydration-safe way.
|
||||
* Returns a hydration-safe 2-char language code.
|
||||
*
|
||||
* On the server and during initial client render the value is always 'th'
|
||||
* (matching the SSR output). After hydration it updates to the user's saved
|
||||
* language so all components re-render with the correct locale without
|
||||
* triggering a hydration mismatch.
|
||||
* WHY this pattern is necessary:
|
||||
* - i18n.ts reads localStorage synchronously at module-load time (before React hydrates)
|
||||
* - So i18n.language may already be 'ja', 'ko', etc. when client components first render
|
||||
* - useTranslation() subscribes to this and causes components to render the user's language
|
||||
* DURING hydration, but the server rendered 'th' — causing a mismatch error
|
||||
*
|
||||
* SOLUTION:
|
||||
* - Always return 'th' until the component has mounted (matching the server)
|
||||
* - After mount, sync to the real language and subscribe to future changes
|
||||
* - Components using this hook NEVER cause a hydration mismatch
|
||||
*/
|
||||
export function useLang(): string {
|
||||
const { i18n } = useTranslation()
|
||||
const [lang, setLang] = useState('th') // must match server default
|
||||
// Always 'th' on first render (matches SSR) — updated post-hydration
|
||||
const [lang, setLang] = useState('th')
|
||||
|
||||
useEffect(() => {
|
||||
setLang(i18n.language ? i18n.language.substring(0, 2) : 'th')
|
||||
}, [i18n.language])
|
||||
// Sync immediately after hydration
|
||||
const current = i18n.language ? i18n.language.substring(0, 2) : 'th'
|
||||
setLang(current)
|
||||
|
||||
// Subscribe to future language changes (user clicks language button)
|
||||
const handler = (lng: string) => setLang(lng.substring(0, 2))
|
||||
i18n.on('languageChanged', handler)
|
||||
return () => { i18n.off('languageChanged', handler) }
|
||||
}, [])
|
||||
|
||||
return lang
|
||||
}
|
||||
Reference in new issue
Block a user