@@ -17,22 +17,33 @@ export const useLanguagePicker = (handleClose?: () => void) => {
17
17
const { t } = useTranslation ( "common" )
18
18
const locale = useLocale ( )
19
19
20
- // Get the preferred language for the users browser
21
- const [ navLang ] = typeof navigator !== "undefined" ? navigator . languages : [ ]
22
20
const locales = useMemo ( ( ) => filterRealLocales ( LOCALES_CODES ) , [ ] )
23
- const intlLocalePreference = useMemo (
24
- ( ) =>
25
- locales ?. reduce ( ( acc , cur ) => {
26
- if ( cur . toLowerCase ( ) === navLang . toLowerCase ( ) ) return cur
27
- if (
28
- navLang . toLowerCase ( ) . startsWith ( cur . toLowerCase ( ) ) &&
29
- acc !== navLang
30
- )
31
- return cur
32
- return acc
33
- } , "" ) as Lang ,
34
- [ navLang , locales ]
35
- )
21
+
22
+ // Find all matching browser language preferences in order
23
+ const intlLocalePreferences = useMemo ( ( ) => {
24
+ // Get the preferred languages for the users browser
25
+ const navLangs = typeof navigator !== "undefined" ? navigator . languages : [ ]
26
+ const preferences : Lang [ ] = [ ]
27
+
28
+ for ( const navLang of navLangs ) {
29
+ const match = locales ?. find ( ( locale ) => {
30
+ // Exact match first
31
+ if ( locale . toLowerCase ( ) === navLang . toLowerCase ( ) ) return true
32
+ // Then partial match (e.g., 'en-US' matches 'en')
33
+ if ( navLang . toLowerCase ( ) . startsWith ( locale . toLowerCase ( ) ) ) return true
34
+ return false
35
+ } ) as Lang | undefined
36
+
37
+ if ( match && ! preferences . includes ( match ) ) {
38
+ preferences . push ( match )
39
+ }
40
+ }
41
+
42
+ return preferences
43
+ } , [ locales ] )
44
+
45
+ // Keep the first preference for backward compatibility
46
+ const intlLocalePreference = intlLocalePreferences [ 0 ] || ""
36
47
37
48
const languages = useMemo < LocaleDisplayInfo [ ] > (
38
49
( ) =>
@@ -43,17 +54,35 @@ export const useLanguagePicker = (handleClose?: () => void) => {
43
54
locale as Lang ,
44
55
t
45
56
)
46
- const isBrowserDefault = intlLocalePreference === localeOption
47
- return { ...displayInfo , isBrowserDefault }
57
+ const isBrowserDefault = intlLocalePreferences . includes (
58
+ localeOption as Lang
59
+ )
60
+ return {
61
+ ...displayInfo ,
62
+ isBrowserDefault,
63
+ }
48
64
} )
49
65
. sort ( ( a , b ) => {
50
- // Always put the browser's preferred language first
51
- if ( a . localeOption === intlLocalePreference ) return - 1
52
- if ( b . localeOption === intlLocalePreference ) return 1
66
+ const aPreferenceIndex = intlLocalePreferences . indexOf (
67
+ a . localeOption as Lang
68
+ )
69
+ const bPreferenceIndex = intlLocalePreferences . indexOf (
70
+ b . localeOption as Lang
71
+ )
72
+
73
+ // First, sort by browser preferences (all browser preferences come first)
74
+ if ( a . isBrowserDefault && ! b . isBrowserDefault ) return - 1
75
+ if ( ! a . isBrowserDefault && b . isBrowserDefault ) return 1
76
+
77
+ // If both are browser preferences, sort by preference order
78
+ if ( a . isBrowserDefault && b . isBrowserDefault ) {
79
+ return aPreferenceIndex - bPreferenceIndex
80
+ }
81
+
53
82
// Otherwise, sort alphabetically by source name using localeCompare
54
83
return a . sourceName . localeCompare ( b . sourceName , locale )
55
84
} ) || [ ] ,
56
- [ intlLocalePreference , locale , locales , t ]
85
+ [ intlLocalePreferences , locale , locales , t ]
57
86
)
58
87
59
88
const intlLanguagePreference = languages . find (
0 commit comments