Skip to content

Commit c391b12

Browse files
formatted useLocalesMap error and added additional checks
1 parent c05dc47 commit c391b12

File tree

1 file changed

+53
-13
lines changed

1 file changed

+53
-13
lines changed

components/use-locales-map.js

+53-13
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,64 @@ import { useRouter } from "next/router";
55
* @typedef {DefaultLocale | "zh-CN" | "es-ES" | "pt-BR" | "ja" | "ko" | "ru"} Locale
66
* @typedef {{locale?: Locale | undefined; locales?: Locale[] | undefined; defaultLocale?: DefaultLocale | undefined}} TypedRouter
77
* @typedef {Omit<import('next/router').NextRouter, "locale" | "locales" | "defaultLocale"> & TypedRouter} NextRouter
8+
*/
9+
10+
/**
811
* @template T
912
* @type {(localesMap: Record<Locale, T>) => T}
1013
*/
1114
export default function useLocalesMap(localesMap) {
1215
/** @type {NextRouter} */
1316
const router = useRouter();
14-
const { locale, defaultLocale } = router;
17+
const { locale, locales, defaultLocale } = router;
1518

1619
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.");
1821
}
1922

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+
);
2235
}
2336

2437
if (!localesMap.hasOwnProperty(defaultLocale)) {
25-
throw new Error(
38+
localesMapError(
39+
localesMap,
2640
`Locales map must contain default locale "${defaultLocale}"`
2741
);
2842
}
2943

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+
}
3761
}
3862

39-
if (["string", "number", "symbol"].includes(typeof localesMap[defaultLocale])) {
63+
if (
64+
["string", "number", "symbol"].includes(typeof localesMap[defaultLocale])
65+
) {
4066
return localesMap[locale] || localesMap[defaultLocale];
4167
}
4268

@@ -76,3 +102,17 @@ export function mergeDeep(target, ...sources) {
76102

77103
return mergeDeep(target, ...sources);
78104
}
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

Comments
 (0)