Skip to content

Commit 4cb5fc4

Browse files
fix(i18n): make sure namespace params from useTranslation hooks are not passed with empty value (#2831)
* fix: make sure namespace params from useTranslation hooks are not passed empty * fix: back key useEffect * docs: changeset
1 parent f2b47cb commit 4cb5fc4

File tree

4 files changed

+47
-32
lines changed

4 files changed

+47
-32
lines changed

.changeset/breezy-yaks-taste.md

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+
fix: typing issue and force use of string array with at least one element for namespaces in useTranslation hook

biome.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@
3232
"attributePosition": "auto",
3333
"includes": [
3434
"**",
35-
"!**/.next/",
36-
"!**/coverage/",
37-
"!**/node_modules/",
38-
"!**/storybook-static",
39-
"!**/dist/",
35+
"!**/.next/*",
36+
"!**/coverage/*",
37+
"!**/node_modules/*",
38+
"!**/storybook-static/*",
39+
"!**/dist/*",
4040
"!**/pnpm-lock.yaml",
4141
"!**/package.json",
4242
"!**/CHANGELOG.md",
4343
"!**/*.snap",
44-
"!**/__snapshots__/"
44+
"!**/__snapshots__/*"
4545
]
4646
},
4747
"javascript": {

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

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ describe('i18n hook', () => {
117117
const spy = vi.spyOn(console, 'error')
118118
spy.mockImplementation(() => {})
119119

120-
expect(() => renderHook(() => useTranslation())).toThrow(
120+
expect(() => renderHook(() => useTranslation(['test']))).toThrow(
121121
new Error('useTranslation must be used within a I18nProvider'),
122122
)
123123
spy.mockRestore()
@@ -133,34 +133,41 @@ describe('i18n hook', () => {
133133
spy.mockRestore()
134134
})
135135

136-
it('should use defaultLoad, useTranslation, switch local and translate', async () => {
137-
const { result } = renderHook(() => useTranslation<Locale, Locales>([]), {
138-
wrapper: wrapper({ defaultLocale: 'en' }),
139-
})
140-
// first render there is no load
141-
expect(result.current.t('title')).toEqual('')
136+
it(
137+
'should use defaultLoad, useTranslation, switch local and translate',
138+
async () => {
139+
const { result } = renderHook(
140+
() => useTranslation<Locale, Locales>(['test']),
141+
{
142+
wrapper: wrapper({ defaultLocale: 'en' }),
143+
},
144+
)
145+
// first render there is no load
146+
expect(result.current.t('title')).toEqual('')
142147

143-
await waitFor(() => {
144-
// after load of en locale
145-
expect(result.current.t('title')).toEqual(en.title)
146-
})
148+
await waitFor(() => {
149+
// after load of en locale
150+
expect(result.current.t('title')).toEqual(en.title)
151+
})
147152

148-
await act(async () => {
149-
await result.current.switchLocale('fr')
150-
})
153+
await act(async () => {
154+
await result.current.switchLocale('fr')
155+
})
151156

152-
await waitFor(() => {
153-
expect(result.current.t('title')).toEqual(fr.title)
154-
})
157+
await waitFor(() => {
158+
expect(result.current.t('title')).toEqual(fr.title)
159+
})
155160

156-
await act(async () => {
157-
await result.current.switchLocale('es')
158-
})
161+
await act(async () => {
162+
await result.current.switchLocale('es')
163+
})
159164

160-
await waitFor(() => {
161-
expect(result.current.t('title')).toEqual(es.title)
162-
})
163-
})
165+
await waitFor(() => {
166+
expect(result.current.t('title')).toEqual(es.title)
167+
})
168+
},
169+
{},
170+
)
164171

165172
it('should use specific load on useTranslation', async () => {
166173
const { result } = renderHook(
@@ -262,7 +269,8 @@ describe('i18n hook', () => {
262269

263270
it('should work with a component', async () => {
264271
const { result } = renderHook(
265-
() => useTranslation<{ 'with.identifier': 'Hello {identifier}' }>([]),
272+
() =>
273+
useTranslation<{ 'with.identifier': 'Hello {identifier}' }>(['test']),
266274
{
267275
wrapper: wrapper({ defaultLocale: 'en' }),
268276
},

packages/use-i18n/src/usei18n.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export function useTranslation<
151151
LocaleParam extends BaseLocale = {},
152152
LocalSupportedType extends string = '',
153153
>(
154-
namespaces: string[] = [],
154+
namespaces: [string, ...string[]],
155155
load: LoadTranslationsFn<LocalSupportedType> | undefined = undefined,
156156
): RequiredGenericContext<LocaleParam, LocalSupportedType> & {
157157
isLoaded: boolean
@@ -162,6 +162,8 @@ export function useTranslation<
162162
}
163163
const { loadTranslations, namespaces: loadedNamespaces } = context
164164

165+
// here we generate a key string from the array of namespace in order to only trigger the use effect
166+
// when the passed keys change and not when the ref of the array change
165167
const key = namespaces.join(',')
166168
useEffect(() => {
167169
// eslint-disable-next-line @typescript-eslint/no-floating-promises

0 commit comments

Comments
 (0)