@@ -5,37 +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 ;
18
+
15
19
if ( ! localesMap ) {
16
- throw new Error ( "Pass a locales map as argument to useLocalesMap" ) ;
20
+ throw new Error ( "Pass a locales map as argument to useLocalesMap hook. " ) ;
17
21
}
18
22
19
- if ( ! isObject ( localesMap ) ) {
20
- 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
+ ) ;
21
35
}
22
36
23
37
if ( ! localesMap . hasOwnProperty ( defaultLocale ) ) {
24
- throw new Error (
38
+ localesMapError (
39
+ localesMap ,
25
40
`Locales map must contain default locale "${ defaultLocale } "`
26
41
) ;
27
42
}
28
43
29
- if (
30
- localesMap . hasOwnProperty ( locale ) &&
31
- typeof localesMap [ locale ] !== typeof localesMap [ defaultLocale ]
32
- ) {
33
- throw new Error (
34
- `Invalid locales map: Shape of "${ locale } " must be the same as "${ defaultLocale } "`
35
- ) ;
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
+ }
36
61
}
37
62
38
- if ( [ "string" , "number" , "symbol" ] . includes ( typeof localesMap [ defaultLocale ] ) ) {
63
+ if (
64
+ [ "string" , "number" , "symbol" ] . includes ( typeof localesMap [ defaultLocale ] )
65
+ ) {
39
66
return localesMap [ locale ] || localesMap [ defaultLocale ] ;
40
67
}
41
68
@@ -76,3 +103,17 @@ function mergeDeep(target, ...sources) {
76
103
77
104
return mergeDeep ( target , ...sources ) ;
78
105
}
106
+
107
+ /**
108
+ * Throw an error with a formatted message.
109
+ * @template T
110
+ * @param {Record<Locale, T> } localesMap
111
+ * @param {string[] } args
112
+ */
113
+ export function localesMapError ( localesMap , ...args ) {
114
+ throw new Error (
115
+ [ "Invalid locales map" , JSON . stringify ( localesMap , null , 2 ) , ...args ] . join (
116
+ "\n"
117
+ )
118
+ ) ;
119
+ }
0 commit comments