@@ -5,38 +5,64 @@ import { useRouter } from "next/router";
5
5
* @typedef {DefaultLocale | "zh-CN" | "es-ES" | "pt-BR" | "ja" | "ko" | "ru" } Locale
6
6
* @typedef {{locale?: Locale | undefined; locales?: Locale[] | undefined; defaultLocale?: DefaultLocale | undefined} } TypedRouter
7
7
* @typedef {Omit<import('next/router').NextRouter, "locale" | "locales" | "defaultLocale"> & TypedRouter } NextRouter
8
+ */
9
+
10
+ /**
8
11
* @template T
9
12
* @type {(localesMap: Record<Locale, T>) => T }
10
13
*/
11
14
export default function useLocalesMap ( localesMap ) {
12
15
/** @type {NextRouter } */
13
16
const router = useRouter ( ) ;
14
- const { locale, defaultLocale } = router ;
17
+ const { locale, locales , defaultLocale } = router ;
15
18
16
19
if ( ! localesMap ) {
17
- throw new Error ( "Pass a locales map as argument to useLocalesMap" ) ;
20
+ throw new Error ( "Pass a locales map as argument to useLocalesMap hook. " ) ;
18
21
}
19
22
20
- if ( ! isObject ( localesMap ) ) {
21
- throw new Error ( "Locales map must be an object" ) ;
23
+ if ( typeof localesMap !== "object" ) {
24
+ localesMapError (
25
+ localesMap ,
26
+ `Locales map must be an object, but you passed ${ typeof localesMap } .`
27
+ ) ;
28
+ }
29
+
30
+ if ( Array . isArray ( localesMap ) ) {
31
+ localesMapError (
32
+ localesMap ,
33
+ "Locales map must be an object, but you passed an array."
34
+ ) ;
22
35
}
23
36
24
37
if ( ! localesMap . hasOwnProperty ( defaultLocale ) ) {
25
- throw new Error (
38
+ localesMapError (
39
+ localesMap ,
26
40
`Locales map must contain default locale "${ defaultLocale } "`
27
41
) ;
28
42
}
29
43
30
- if (
31
- localesMap . hasOwnProperty ( locale ) &&
32
- typeof localesMap [ locale ] !== typeof localesMap [ defaultLocale ]
33
- ) {
34
- throw new Error (
35
- `Invalid locales map: Shape of "${ locale } " must be the same as "${ defaultLocale } "`
36
- ) ;
44
+ for ( const key in localesMap ) {
45
+ if ( ! locales . includes ( key ) ) {
46
+ const list = locales . map ( ( l ) => `"${ l } "` ) . join ( ", " ) ;
47
+
48
+ localesMapError (
49
+ localesMap ,
50
+ `"${ key } " is not a valid locale.` ,
51
+ `Available locales are defined in "next.config.js": ${ list } .`
52
+ ) ;
53
+ }
54
+
55
+ if ( typeof localesMap [ key ] !== typeof localesMap [ defaultLocale ] ) {
56
+ localesMapError (
57
+ localesMap ,
58
+ `Shape of "${ key } " must be the same as "${ defaultLocale } "`
59
+ ) ;
60
+ }
37
61
}
38
62
39
- if ( [ "string" , "number" , "symbol" ] . includes ( typeof localesMap [ defaultLocale ] ) ) {
63
+ if (
64
+ [ "string" , "number" , "symbol" ] . includes ( typeof localesMap [ defaultLocale ] )
65
+ ) {
40
66
return localesMap [ locale ] || localesMap [ defaultLocale ] ;
41
67
}
42
68
@@ -76,3 +102,17 @@ export function mergeDeep(target, ...sources) {
76
102
77
103
return mergeDeep ( target , ...sources ) ;
78
104
}
105
+
106
+ /**
107
+ * Throw an error with a formatted message.
108
+ * @template T
109
+ * @param {Record<Locale, T> } localesMap
110
+ * @param {string[] } args
111
+ */
112
+ export function localesMapError ( localesMap , ...args ) {
113
+ throw new Error (
114
+ [ "Invalid locales map" , JSON . stringify ( localesMap , null , 2 ) , ...args ] . join (
115
+ "\n"
116
+ )
117
+ ) ;
118
+ }
0 commit comments