33import * as React from "react" ;
44import { NextIntlClientProvider } from "next-intl" ;
55
6- import { DEFAULT_LOCALE , LOCALE_COOKIE_NAME , normalizeAppLocale , type AppLocale } from "@/i18n/config" ;
6+ import { DEFAULT_LOCALE , LOCALE_COOKIE_NAME , normalizeAppLocale , resolveBrowserLocale , type AppLocale } from "@/i18n/config" ;
77import { DEFAULT_MESSAGES , loadLocaleMessages , type AppMessages } from "@/i18n/messages" ;
88
99type AppI18nContextValue = {
@@ -13,20 +13,27 @@ type AppI18nContextValue = {
1313
1414const AppI18nContext = React . createContext < AppI18nContextValue | null > ( null ) ;
1515
16- function readLocaleCookie ( ) : AppLocale {
16+ function readLocaleCookie ( ) : AppLocale | null {
1717 if ( typeof document === "undefined" ) {
18- return DEFAULT_LOCALE ;
18+ return null ;
1919 }
2020 const raw = document . cookie
2121 . split ( ";" )
2222 . map ( ( part ) => part . trim ( ) )
2323 . find ( ( part ) => part . startsWith ( `${ LOCALE_COOKIE_NAME } =` ) ) ;
2424 if ( ! raw ) {
25- return DEFAULT_LOCALE ;
25+ return null ;
2626 }
2727 return normalizeAppLocale ( decodeURIComponent ( raw . slice ( LOCALE_COOKIE_NAME . length + 1 ) ) ) ;
2828}
2929
30+ function readBrowserLocale ( ) : AppLocale {
31+ if ( typeof navigator === "undefined" ) {
32+ return DEFAULT_LOCALE ;
33+ }
34+ return resolveBrowserLocale ( navigator . languages ?. length ? navigator . languages : [ navigator . language ] ) ;
35+ }
36+
3037function writeLocaleCookie ( locale : AppLocale ) : void {
3138 if ( typeof document === "undefined" ) {
3239 return ;
@@ -46,10 +53,12 @@ export function AppI18nProvider({ children }: { children: React.ReactNode }) {
4653 const [ messages , setMessages ] = React . useState < AppMessages > ( DEFAULT_MESSAGES ) ;
4754 const localeRef = React . useRef < AppLocale > ( DEFAULT_LOCALE ) ;
4855
49- const setLocale = React . useCallback ( async ( nextLocale : AppLocale ) => {
56+ const applyLocale = React . useCallback ( async ( nextLocale : AppLocale , persist : boolean ) => {
5057 const normalized = normalizeAppLocale ( nextLocale ) ;
5158 if ( normalized === localeRef . current ) {
52- writeLocaleCookie ( normalized ) ;
59+ if ( persist ) {
60+ writeLocaleCookie ( normalized ) ;
61+ }
5362 applyDocumentLocale ( normalized ) ;
5463 return ;
5564 }
@@ -58,13 +67,20 @@ export function AppI18nProvider({ children }: { children: React.ReactNode }) {
5867 localeRef . current = normalized ;
5968 setLocaleState ( normalized ) ;
6069 setMessages ( nextMessages ) ;
61- writeLocaleCookie ( normalized ) ;
70+ if ( persist ) {
71+ writeLocaleCookie ( normalized ) ;
72+ }
6273 applyDocumentLocale ( normalized ) ;
6374 } , [ ] ) ;
6475
76+ const setLocale = React . useCallback ( async ( nextLocale : AppLocale ) => {
77+ await applyLocale ( nextLocale , true ) ;
78+ } , [ applyLocale ] ) ;
79+
6580 React . useEffect ( ( ) => {
66- void setLocale ( readLocaleCookie ( ) ) ;
67- } , [ setLocale ] ) ;
81+ const cookieLocale = readLocaleCookie ( ) ;
82+ void applyLocale ( cookieLocale ?? readBrowserLocale ( ) , cookieLocale !== null ) ;
83+ } , [ applyLocale ] ) ;
6884
6985 const value = React . useMemo < AppI18nContextValue > (
7086 ( ) => ( {
0 commit comments