1
- import { useEffect , useState } from "react"
1
+ import { useMemo } from "react"
2
2
import { useRouter } from "next/router"
3
3
import { useTranslation } from "next-i18next"
4
4
5
- import type {
6
- I18nLocale ,
7
- Lang ,
8
- LocaleDisplayInfo ,
9
- ProjectProgressData ,
10
- } from "@/lib/types"
5
+ import type { Lang , LocaleDisplayInfo } from "@/lib/types"
11
6
12
7
import { MatomoEventOptions , trackCustomEvent } from "@/lib/utils/matomo"
13
- import { filterRealLocales , languages } from "@/lib/utils/translations"
8
+ import { filterRealLocales } from "@/lib/utils/translations"
14
9
15
- import progressDataJson from "@/data/translationProgress.json"
16
-
17
- import { DEFAULT_LOCALE } from "@/lib/constants"
10
+ import { localeToDisplayInfo } from "./localeToDisplayInfo"
18
11
19
12
import useDisclosure from "@/hooks/useDisclosure"
20
13
21
- const progressData = progressDataJson satisfies ProjectProgressData [ ]
22
-
23
14
export const useLanguagePicker = ( handleClose ?: ( ) => void ) => {
24
15
const { t } = useTranslation ( "common" )
25
16
const { locale, locales : rawLocales } = useRouter ( )
26
17
27
- const [ filteredNames , setFilteredNames ] = useState < LocaleDisplayInfo [ ] > ( [ ] )
28
-
29
- // perform all the filtering and mapping when the filter value change
30
- useEffect ( ( ) => {
18
+ const languages = useMemo < LocaleDisplayInfo [ ] > ( ( ) => {
31
19
const locales = filterRealLocales ( rawLocales )
32
20
33
21
// Get the preferred languages for the users browser
@@ -52,99 +40,26 @@ export const useLanguagePicker = (handleClose?: () => void) => {
52
40
// Remove duplicate matches
53
41
const browserLocales = Array . from ( new Set ( allBrowserLocales ) )
54
42
55
- const localeToDisplayInfo = ( localeOption : Lang ) : LocaleDisplayInfo => {
56
- const i18nItem : I18nLocale = languages [ localeOption ]
57
- const englishName = i18nItem . name
58
-
59
- // Get "source" display name (Language choice displayed in language of current locale)
60
- const intlSource = new Intl . DisplayNames ( [ locale ! ] , {
61
- type : "language" ,
62
- } ) . of ( localeOption )
63
- // For languages that do not have an Intl display name, use English name as fallback
64
- const fallbackSource =
65
- intlSource !== localeOption ? intlSource : englishName
66
- const i18nKey = "language-" + localeOption . toLowerCase ( )
67
- const i18nSource = t ( i18nKey ) // Falls back to English namespace if not found
68
-
69
- // If i18nSource (fetched from `language-{locale}` in current namespace)
70
- // is not translated (output === englishName), or not available
71
- // (output === i18nKey), use the Intl.DisplayNames result as fallback
72
- const sourceName = [ i18nKey , englishName ] . includes ( i18nSource )
73
- ? fallbackSource
74
- : i18nSource
75
-
76
- // Get "target" display name (Language choice displayed in that language)
77
- const fallbackTarget = new Intl . DisplayNames ( [ localeOption ] , {
78
- type : "language" ,
79
- } ) . of ( localeOption )
80
- const i18nConfigTarget = i18nItem . localName
81
- const targetName = i18nConfigTarget || fallbackTarget
82
-
83
- if ( ! sourceName || ! targetName ) {
84
- console . warn ( "Missing language display name:" , {
85
- localeOption,
86
- sourceName,
87
- targetName,
43
+ return (
44
+ ( locales as Lang [ ] )
45
+ ?. map ( ( localeOption ) => {
46
+ const displayInfo = localeToDisplayInfo (
47
+ localeOption ,
48
+ locale as Lang ,
49
+ t
50
+ )
51
+ const isBrowserDefault = browserLocales . includes ( localeOption )
52
+ return { ...displayInfo , isBrowserDefault }
88
53
} )
89
- }
90
-
91
- // English will not have a dataItem
92
- const dataItem = progressData . find (
93
- ( { languageId } ) =>
94
- i18nItem . crowdinCode . toLowerCase ( ) === languageId . toLowerCase ( )
95
- )
96
-
97
- const approvalProgress =
98
- localeOption === DEFAULT_LOCALE
99
- ? 100
100
- : Math . floor (
101
- ( dataItem ! . words . approved / dataItem ! . words . total ) * 100
102
- ) || 0
103
-
104
- const isBrowserDefault = browserLocales . includes ( localeOption )
105
-
106
- const returnData : Partial < LocaleDisplayInfo > = {
107
- localeOption,
108
- sourceName : sourceName ?? localeOption ,
109
- targetName : targetName ?? localeOption ,
110
- englishName,
111
- isBrowserDefault,
112
- }
113
-
114
- if ( progressData . length < 1 ) {
115
- console . warn ( `Missing translation progress data; check GitHub action` )
116
- return {
117
- ...returnData ,
118
- approvalProgress : 0 ,
119
- wordsApproved : 0 ,
120
- } as LocaleDisplayInfo
121
- }
122
-
123
- const totalWords = progressData [ 0 ] . words . total
124
-
125
- const wordsApproved =
126
- localeOption === DEFAULT_LOCALE
127
- ? totalWords || 0
128
- : dataItem ?. words . approved || 0
129
-
130
- return {
131
- ...returnData ,
132
- approvalProgress,
133
- wordsApproved,
134
- } as LocaleDisplayInfo
135
- }
136
-
137
- const displayNames : LocaleDisplayInfo [ ] =
138
- ( locales as Lang [ ] ) ?. map ( localeToDisplayInfo ) . sort ( ( a , b ) => {
139
- const indexA = browserLocales . indexOf ( a . localeOption as Lang )
140
- const indexB = browserLocales . indexOf ( b . localeOption as Lang )
141
- if ( indexA >= 0 && indexB >= 0 ) return indexA - indexB
142
- if ( indexA >= 0 ) return - 1
143
- if ( indexB >= 0 ) return 1
144
- return b . approvalProgress - a . approvalProgress
145
- } ) || [ ]
146
-
147
- setFilteredNames ( displayNames )
54
+ . sort ( ( a , b ) => {
55
+ const indexA = browserLocales . indexOf ( a . localeOption as Lang )
56
+ const indexB = browserLocales . indexOf ( b . localeOption as Lang )
57
+ if ( indexA >= 0 && indexB >= 0 ) return indexA - indexB
58
+ if ( indexA >= 0 ) return - 1
59
+ if ( indexB >= 0 ) return 1
60
+ return b . approvalProgress - a . approvalProgress
61
+ } ) || [ ]
62
+ )
148
63
} , [ locale , rawLocales , t ] )
149
64
150
65
const { isOpen, setValue, ...menu } = useDisclosure ( )
@@ -182,6 +97,6 @@ export const useLanguagePicker = (handleClose?: () => void) => {
182
97
return {
183
98
t,
184
99
disclosure : { isOpen, setValue, onOpen, onClose } ,
185
- filteredNames ,
100
+ languages ,
186
101
}
187
102
}
0 commit comments