Skip to content

Commit d73b2b1

Browse files
authored
fix(use-i18n): add loadDateLocal non async possibility to avoid re-render (#1762)
1 parent ebdac83 commit d73b2b1

File tree

3 files changed

+57
-34
lines changed

3 files changed

+57
-34
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@scaleway/use-i18n": minor
3+
---
4+
5+
Add a non async loadDateLocal possibility

packages/use-i18n/src/__tests__/usei18n.tsx

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
jest,
88
} from '@jest/globals'
99
import { act, renderHook, waitFor } from '@testing-library/react'
10+
import { enGB, fr as frDateFns } from 'date-fns/locale'
1011
import mockdate from 'mockdate'
1112
import type { ReactNode } from 'react'
1213
import I18n, { useI18n, useTranslation } from '..'
@@ -35,7 +36,7 @@ const defaultSupportedLocales = ['en', 'fr', 'es']
3536

3637
const wrapper =
3738
({
38-
loadDateLocale = async (locale: string) => {
39+
loadDateLocaleAsync = async (locale: string) => {
3940
if (locale === 'en') {
4041
return (await import('date-fns/locale/en-GB')).enGB
4142
}
@@ -49,6 +50,16 @@ const wrapper =
4950

5051
return (await import(`date-fns/locale/en-GB`)).enGB
5152
},
53+
loadDateLocale = (locale: string) => {
54+
if (locale === 'en') {
55+
return enGB
56+
}
57+
if (locale === 'fr') {
58+
return frDateFns
59+
}
60+
61+
return enGB
62+
},
5263
defaultLoad = async ({ locale }: { locale: string }) =>
5364
import(`./locales/${locale}.json`),
5465
defaultLocale = 'en',
@@ -61,6 +72,7 @@ const wrapper =
6172
({ children }: { children: ReactNode }) => (
6273
<I18n
6374
loadDateLocale={loadDateLocale}
75+
loadDateLocaleAsync={loadDateLocaleAsync}
6476
defaultLoad={defaultLoad}
6577
defaultLocale={defaultLocale}
6678
defaultTranslations={defaultTranslations}
@@ -271,6 +283,33 @@ describe('i18n hook', () => {
271283
})
272284
})
273285

286+
it('should work with a component', async () => {
287+
const { result } = renderHook(
288+
() => useTranslation<{ 'with.identifier': 'Hello {identifier}' }>([]),
289+
{
290+
wrapper: wrapper({ defaultLocale: 'en' }),
291+
},
292+
)
293+
const CustomComponent = ({ children }: { children: ReactNode }) => (
294+
<p style={{ fontWeight: 'bold' }}>{children}</p>
295+
)
296+
297+
await waitFor(() => {
298+
expect(
299+
result.current.t('with.identifier', { identifier: <b>My resource</b> }),
300+
).toEqual(['Are you sure you want to delete ', <b>My resource</b>, '?'])
301+
expect(
302+
result.current.t('with.identifier', {
303+
identifier: <CustomComponent>My resource</CustomComponent>,
304+
}),
305+
).toEqual([
306+
'Are you sure you want to delete ',
307+
<CustomComponent>My resource</CustomComponent>,
308+
'?',
309+
])
310+
})
311+
})
312+
274313
describe('getCurrentLocale', () => {
275314
it('should set current locale from localStorage', async () => {
276315
jest.spyOn(global, 'navigator', 'get').mockReturnValueOnce({
@@ -765,7 +804,7 @@ describe('i18n hook', () => {
765804

766805
await waitFor(() => {
767806
expect(result.current.currentLocale).toEqual('fr')
768-
expect(mockGetItem).toHaveBeenCalledTimes(2)
807+
expect(mockGetItem).toHaveBeenCalledTimes(1)
769808
expect(mockGetItem).toHaveBeenCalledWith(LOCALE_ITEM_STORAGE)
770809
})
771810

@@ -777,31 +816,4 @@ describe('i18n hook', () => {
777816
localStorageMock.mockRestore()
778817
})
779818
})
780-
781-
it('should work with a component', async () => {
782-
const { result } = renderHook(
783-
() => useTranslation<{ 'with.identifier': 'Hello {identifier}' }>([]),
784-
{
785-
wrapper: wrapper({ defaultLocale: 'en' }),
786-
},
787-
)
788-
const CustomComponent = ({ children }: { children: ReactNode }) => (
789-
<p style={{ fontWeight: 'bold' }}>{children}</p>
790-
)
791-
792-
await waitFor(() => {
793-
expect(
794-
result.current.t('with.identifier', { identifier: <b>My resource</b> }),
795-
).toEqual(['Are you sure you want to delete ', <b>My resource</b>, '?'])
796-
expect(
797-
result.current.t('with.identifier', {
798-
identifier: <CustomComponent>My resource</CustomComponent>,
799-
}),
800-
).toEqual([
801-
'Are you sure you want to delete ',
802-
<CustomComponent>My resource</CustomComponent>,
803-
'?',
804-
])
805-
})
806-
})
807819
})

packages/use-i18n/src/usei18n.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ type LoadTranslationsFn = ({
182182
locale: string
183183
}) => Promise<{ default: BaseLocale }>
184184

185-
type LoadLocaleFn = (locale: string) => Promise<DateFnsLocale>
185+
type LoadLocaleFn = (locale: string) => DateFnsLocale
186+
type LoadLocaleFnAsync = (locale: string) => Promise<DateFnsLocale>
186187
type LoadDateLocaleError = (error: Error) => void
187188

188189
const initialDefaultTranslations = {}
@@ -195,13 +196,15 @@ const I18nContextProvider = ({
195196
enableDebugKey = false,
196197
enableDefaultLocale = false,
197198
loadDateLocale,
199+
loadDateLocaleAsync,
198200
localeItemStorage = LOCALE_ITEM_STORAGE,
199201
onLoadDateLocaleError,
200202
supportedLocales,
201203
}: {
202204
children: ReactNode
203205
defaultLoad: LoadTranslationsFn
204-
loadDateLocale: LoadLocaleFn
206+
loadDateLocale?: LoadLocaleFn
207+
loadDateLocaleAsync: LoadLocaleFnAsync
205208
onLoadDateLocaleError?: LoadDateLocaleError
206209
defaultLocale: string
207210
defaultTranslations: TranslationsByLocales
@@ -216,14 +219,17 @@ const I18nContextProvider = ({
216219
const [translations, setTranslations] =
217220
useState<TranslationsByLocales>(defaultTranslations)
218221
const [namespaces, setNamespaces] = useState<string[]>([])
222+
219223
const [dateFnsLocale, setDateFnsLocale] = useState<DateFnsLocale | undefined>(
220-
undefined,
224+
loadDateLocale?.(currentLocale) ?? undefined,
221225
)
222226

227+
const loadDateFNS = loadDateLocale ?? loadDateLocaleAsync
228+
223229
const setDateFns = useCallback(
224230
async (locale: string) => {
225231
try {
226-
const dateFns = await loadDateLocale(locale)
232+
const dateFns = await loadDateFNS(locale)
227233
setDateFnsLocale(dateFns)
228234
} catch (err) {
229235
if (err instanceof Error && onLoadDateLocaleError) {
@@ -233,7 +239,7 @@ const I18nContextProvider = ({
233239
setDateFnsLocale(dateFnsLocale)
234240
}
235241
},
236-
[loadDateLocale, setDateFnsLocale, onLoadDateLocaleError, dateFnsLocale],
242+
[loadDateFNS, setDateFnsLocale, onLoadDateLocaleError, dateFnsLocale],
237243
)
238244

239245
/**

0 commit comments

Comments
 (0)