cloudflare-next-intl 0.9.53 → 0.9.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/client/components/client_provider.js +6 -3
- package/dist/src/client/components/client_provider_static.js +4 -2
- package/dist/src/client/components/use_lazy_wrapping_provider.d.ts +12 -0
- package/dist/src/client/components/use_lazy_wrapping_provider.js +34 -0
- package/dist/src/locale_params_check/check_locale_params.js +14 -1
- package/dist/src/locale_params_check/insert_locale_params.d.ts +2 -0
- package/dist/src/locale_params_check/insert_locale_params.js +130 -0
- package/package.json +1 -1
|
@@ -3,13 +3,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { setLocaleCache, setMessageForLocaleCache } from "../../general/cache_variables.js";
|
|
4
4
|
import { createContext, useMemo } from "react";
|
|
5
5
|
import dynamic from "next/dynamic.js";
|
|
6
|
+
import useLazyWrappingProvider from "./use_lazy_wrapping_provider.js";
|
|
6
7
|
import config from "@intl-config";
|
|
7
8
|
import installConsoleErrorOverride from "../../error_handling/install_console_error_override.js";
|
|
8
9
|
import installGlobalErrorOverride from "../../error_handling/install_global_error_override.js";
|
|
9
10
|
export const LocaleContext = createContext(undefined);
|
|
10
|
-
const
|
|
11
|
+
const loadAuthUserProvider = () => import("../../firebase_auth/client/auth_user_provider.js");
|
|
11
12
|
const AutoFirebasePerformanceEvents = dynamic(() => import("../../firebase_auth/client/components/auto_firebase_performance_events.js"));
|
|
12
|
-
const
|
|
13
|
+
const loadCookieConsentProvider = () => import("../../cookie_consent/client/cookie_consent_provider.js");
|
|
13
14
|
const CookieConsentAnalytics = dynamic(() => import("../../cookie_consent/client/components/cookie_consent_analytics.js"));
|
|
14
15
|
const AutoAnalyticsEvents = dynamic(() => import("../../cookie_consent/client/components/auto_analytics_events.js"));
|
|
15
16
|
const CookieConsentDialog = dynamic(() => import("../../cookie_consent/client/components/cookie_consent_dialog.js"));
|
|
@@ -19,12 +20,14 @@ export default function LocationzationClientProvider({ language, messages, initi
|
|
|
19
20
|
setMessageForLocaleCache(language, messages);
|
|
20
21
|
installConsoleErrorOverride(config, true);
|
|
21
22
|
installGlobalErrorOverride(config);
|
|
23
|
+
const { Provider: AuthUserProvider } = useLazyWrappingProvider(loadAuthUserProvider);
|
|
24
|
+
const { Provider: CookieConsentProvider, isReady: cookieConsentReady } = useLazyWrappingProvider(loadCookieConsentProvider);
|
|
22
25
|
let providedChildren = children;
|
|
23
26
|
if (config.firebaseAuth && !skipAuthProvider) {
|
|
24
27
|
providedChildren = _jsxs(AuthUserProvider, { initialUser: initialAuthUser, children: [children, config.firebaseAuth.performance !== false && _jsx(AutoFirebasePerformanceEvents, {})] });
|
|
25
28
|
}
|
|
26
29
|
if (config.cookieConsent) {
|
|
27
|
-
providedChildren = _jsxs(CookieConsentProvider, { requiresConsent: requiresConsent, children: [providedChildren, analyticsConfig && _jsx(CookieConsentAnalytics, { config: analyticsConfig }), analyticsConfig && (analyticsConfig.googleAnalyticsId || analyticsConfig.googleAdsId) && _jsx(AutoAnalyticsEvents, { config: autoAnalyticsEventsConfig }), autoWireDialogs && _jsx(CookieConsentDialog, { ...dialogProps }), autoWireDialogs && _jsx(PrivacyPolicyUpdateDialog, { ...updateDialogProps })] });
|
|
30
|
+
providedChildren = _jsxs(CookieConsentProvider, { requiresConsent: requiresConsent, children: [providedChildren, cookieConsentReady && analyticsConfig && _jsx(CookieConsentAnalytics, { config: analyticsConfig }), cookieConsentReady && analyticsConfig && (analyticsConfig.googleAnalyticsId || analyticsConfig.googleAdsId) && _jsx(AutoAnalyticsEvents, { config: autoAnalyticsEventsConfig }), cookieConsentReady && autoWireDialogs && _jsx(CookieConsentDialog, { ...dialogProps }), cookieConsentReady && autoWireDialogs && _jsx(PrivacyPolicyUpdateDialog, { ...updateDialogProps })] });
|
|
28
31
|
}
|
|
29
32
|
const contextValue = useMemo(() => ({ language, messages }), [language, messages]);
|
|
30
33
|
return _jsx(LocaleContext.Provider, { value: contextValue, children: providedChildren });
|
|
@@ -3,11 +3,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { setLocaleCache, setMessageForLocaleCache } from "../../general/cache_variables.js";
|
|
4
4
|
import { createContext, useMemo } from "react";
|
|
5
5
|
import dynamic from "next/dynamic.js";
|
|
6
|
+
import useLazyWrappingProvider from "./use_lazy_wrapping_provider.js";
|
|
6
7
|
import config from "@intl-config";
|
|
7
8
|
import installConsoleErrorOverride from "../../error_handling/install_console_error_override.js";
|
|
8
9
|
import installGlobalErrorOverride from "../../error_handling/install_global_error_override.js";
|
|
9
10
|
export const LocaleContext = createContext(undefined);
|
|
10
|
-
const
|
|
11
|
+
const loadCookieConsentProvider = () => import("../../cookie_consent/client/cookie_consent_provider.js");
|
|
11
12
|
const CookieConsentAnalytics = dynamic(() => import("../../cookie_consent/client/components/cookie_consent_analytics.js"));
|
|
12
13
|
const AutoAnalyticsEvents = dynamic(() => import("../../cookie_consent/client/components/auto_analytics_events.js"));
|
|
13
14
|
const CookieConsentDialog = dynamic(() => import("../../cookie_consent/client/components/cookie_consent_dialog.js"));
|
|
@@ -17,9 +18,10 @@ export default function LocationzationClientProvider({ language, messages, analy
|
|
|
17
18
|
setMessageForLocaleCache(language, messages);
|
|
18
19
|
installConsoleErrorOverride(config, true);
|
|
19
20
|
installGlobalErrorOverride(config);
|
|
21
|
+
const { Provider: CookieConsentProvider, isReady: cookieConsentReady } = useLazyWrappingProvider(loadCookieConsentProvider);
|
|
20
22
|
let providedChildren = children;
|
|
21
23
|
if (config.cookieConsent) {
|
|
22
|
-
providedChildren = _jsxs(CookieConsentProvider, { requiresConsent: requiresConsent, children: [providedChildren, analyticsConfig && _jsx(CookieConsentAnalytics, { config: analyticsConfig }), analyticsConfig && (analyticsConfig.googleAnalyticsId || analyticsConfig.googleAdsId) && _jsx(AutoAnalyticsEvents, { config: autoAnalyticsEventsConfig }), autoWireDialogs && _jsx(CookieConsentDialog, { ...dialogProps }), autoWireDialogs && _jsx(PrivacyPolicyUpdateDialog, { ...updateDialogProps })] });
|
|
24
|
+
providedChildren = _jsxs(CookieConsentProvider, { requiresConsent: requiresConsent, children: [providedChildren, cookieConsentReady && analyticsConfig && _jsx(CookieConsentAnalytics, { config: analyticsConfig }), cookieConsentReady && analyticsConfig && (analyticsConfig.googleAnalyticsId || analyticsConfig.googleAdsId) && _jsx(AutoAnalyticsEvents, { config: autoAnalyticsEventsConfig }), cookieConsentReady && autoWireDialogs && _jsx(CookieConsentDialog, { ...dialogProps }), cookieConsentReady && autoWireDialogs && _jsx(PrivacyPolicyUpdateDialog, { ...updateDialogProps })] });
|
|
23
25
|
}
|
|
24
26
|
const contextValue = useMemo(() => ({ language, messages }), [language, messages]);
|
|
25
27
|
return _jsx(LocaleContext.Provider, { value: contextValue, children: providedChildren });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ComponentType } from "react";
|
|
2
|
+
type ModuleLoader<P> = () => Promise<{
|
|
3
|
+
default: ComponentType<P>;
|
|
4
|
+
}>;
|
|
5
|
+
export interface LazyWrappingProviderResult<P extends Record<string, unknown>> {
|
|
6
|
+
Provider: ComponentType<P & {
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
}>;
|
|
9
|
+
isReady: boolean;
|
|
10
|
+
}
|
|
11
|
+
export default function useLazyWrappingProvider<P extends Record<string, unknown>>(loader: ModuleLoader<P>): LazyWrappingProviderResult<P>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
const settledCache = new Map();
|
|
5
|
+
export default function useLazyWrappingProvider(loader) {
|
|
6
|
+
const opaqueLoader = loader;
|
|
7
|
+
const resolvedRef = useRef(settledCache.get(opaqueLoader) ?? null);
|
|
8
|
+
const [isReady, setIsReady] = useState(resolvedRef.current !== null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (resolvedRef.current)
|
|
11
|
+
return;
|
|
12
|
+
let cancelled = false;
|
|
13
|
+
loader().then((mod) => {
|
|
14
|
+
if (cancelled)
|
|
15
|
+
return;
|
|
16
|
+
settledCache.set(opaqueLoader, mod.default);
|
|
17
|
+
resolvedRef.current = mod.default;
|
|
18
|
+
setIsReady(true);
|
|
19
|
+
});
|
|
20
|
+
return () => {
|
|
21
|
+
cancelled = true;
|
|
22
|
+
};
|
|
23
|
+
}, []);
|
|
24
|
+
const wrapperRef = useRef(null);
|
|
25
|
+
if (!wrapperRef.current) {
|
|
26
|
+
wrapperRef.current = function LazyWrappingProvider({ children, ...props }) {
|
|
27
|
+
const Resolved = resolvedRef.current;
|
|
28
|
+
if (!Resolved)
|
|
29
|
+
return children;
|
|
30
|
+
return _jsx(Resolved, { ...props, children: children });
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return { Provider: wrapperRef.current, isReady };
|
|
34
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { relative } from 'node:path';
|
|
3
3
|
import { detectLocaleParams } from './detect_locale_params.js';
|
|
4
|
-
import { insertLocaleParamsSignature, insertLocaleParamsBody, ensureLocaleInParamsType, addParamsPropToExistingDestructure, ensureSetLocaleImport } from './insert_locale_params.js';
|
|
4
|
+
import { insertLocaleParamsSignature, insertLocaleParamsBody, ensureLocaleInParamsType, addParamsPropToExistingDestructure, ensureSetLocaleImport, wrapSyncDefaultExportWithParams, extractParamsPromiseType } from './insert_locale_params.js';
|
|
5
5
|
import { findLocaleScopedFiles } from './find_locale_scoped_files.js';
|
|
6
6
|
import { deriveRoute, makePageLabeler } from '../dynamic_pages_check/derive_page_label.js';
|
|
7
7
|
const ZERO_ARG_DEFAULT_EXPORT = /export\s+default\s+(async\s+)?function\s+[A-Za-z_$][\w$]*\s*\(\s*\)/;
|
|
8
|
+
const SYNC_DEFAULT_EXPORT = /export\s+default\s+function\s+[A-Za-z_$][\w$]*\s*\(/;
|
|
8
9
|
const LEGEND = '✓ Set up + Added ? Needs manual edit · Skipped';
|
|
9
10
|
function actionGlyph(action) {
|
|
10
11
|
switch (action) {
|
|
@@ -76,6 +77,18 @@ export async function checkLocaleParams(options, io = {}) {
|
|
|
76
77
|
reports.push({ file, action: 'would-add-locale-params' });
|
|
77
78
|
continue;
|
|
78
79
|
}
|
|
80
|
+
const isSyncDefaultExport = !detection.hasInlineDestructure && SYNC_DEFAULT_EXPORT.test(source);
|
|
81
|
+
if (isSyncDefaultExport && (isZeroArg || canAddParamsKey || canReuseExistingParams)) {
|
|
82
|
+
const existingParamsType = canReuseExistingParams ? extractParamsPromiseType(source) ?? undefined : undefined;
|
|
83
|
+
const wrapped = wrapSyncDefaultExportWithParams(source, localeParam, existingParamsType);
|
|
84
|
+
if (wrapped === source) {
|
|
85
|
+
reports.push({ file, action: 'needs-manual-edit' });
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
writeFile(file, ensureSetLocaleImport(wrapped));
|
|
89
|
+
reports.push({ file, action: 'added-locale-params' });
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
79
92
|
let updated = source;
|
|
80
93
|
if (isZeroArg) {
|
|
81
94
|
updated = insertLocaleParamsSignature(updated, localeParam);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare function insertLocaleParamsSignature(sourceText: string, localeParam: string): string;
|
|
2
|
+
export declare function wrapSyncDefaultExportWithParams(sourceText: string, localeParam: string, existingParamsType?: string): string;
|
|
2
3
|
export declare function addParamsPropToExistingDestructure(sourceText: string, localeParam: string): string;
|
|
3
4
|
export declare function insertLocaleParamsBody(sourceText: string, localeParam: string, hasInlineDestructure: boolean): string;
|
|
5
|
+
export declare function extractParamsPromiseType(sourceText: string): string | null;
|
|
4
6
|
export declare function ensureLocaleInParamsType(sourceText: string, localeParam: string): string;
|
|
5
7
|
export declare function ensureSetLocaleImport(sourceText: string): string;
|
|
@@ -18,7 +18,134 @@ export function insertLocaleParamsSignature(sourceText, localeParam) {
|
|
|
18
18
|
const replacement = `({ params }: {\n params: Promise<{ ${localeParam}: Language }>;\n})`;
|
|
19
19
|
return sourceText.slice(0, parensStart) + replacement + sourceText.slice(parensEnd);
|
|
20
20
|
}
|
|
21
|
+
const SYNC_DEFAULT_EXPORT_FUNCTION = /export\s+default\s+function\s+([A-Za-z_$][\w$]*)\s*\(/;
|
|
22
|
+
function findUnusedContentName(sourceText, baseName) {
|
|
23
|
+
let candidate = `${baseName}ContentCloudflareNextIntl`;
|
|
24
|
+
let suffix = 2;
|
|
25
|
+
while (new RegExp(`\\b${candidate}\\b`).test(sourceText)) {
|
|
26
|
+
candidate = `${baseName}ContentCloudflareNextIntl${suffix}`;
|
|
27
|
+
suffix += 1;
|
|
28
|
+
}
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
21
31
|
const DEFAULT_EXPORT_FUNCTION_OPEN_PAREN = /export\s+default\s+(?:async\s+)?function\s+[A-Za-z_$][\w$]*\s*\(/;
|
|
32
|
+
function findParamListSpan(sourceText) {
|
|
33
|
+
const openParenMatch = DEFAULT_EXPORT_FUNCTION_OPEN_PAREN.exec(sourceText);
|
|
34
|
+
if (openParenMatch === null)
|
|
35
|
+
return null;
|
|
36
|
+
const start = openParenMatch.index + openParenMatch[0].length - 1;
|
|
37
|
+
let depth = 0;
|
|
38
|
+
for (let i = start; i < sourceText.length; i++) {
|
|
39
|
+
if (sourceText[i] === '(')
|
|
40
|
+
depth++;
|
|
41
|
+
else if (sourceText[i] === ')') {
|
|
42
|
+
depth--;
|
|
43
|
+
if (depth === 0)
|
|
44
|
+
return { start, end: i + 1 };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function destructuredKeyNames(inner) {
|
|
50
|
+
const names = [];
|
|
51
|
+
let depth = 0;
|
|
52
|
+
let start = 0;
|
|
53
|
+
const parts = [];
|
|
54
|
+
for (let i = 0; i <= inner.length; i++) {
|
|
55
|
+
const char = inner[i];
|
|
56
|
+
if (i === inner.length || (char === ',' && depth === 0)) {
|
|
57
|
+
parts.push(inner.slice(start, i));
|
|
58
|
+
start = i + 1;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (char === '{' || char === '(' || char === '[')
|
|
62
|
+
depth++;
|
|
63
|
+
else if (char === '}' || char === ')' || char === ']')
|
|
64
|
+
depth--;
|
|
65
|
+
}
|
|
66
|
+
for (const part of parts) {
|
|
67
|
+
const trimmed = part.trim();
|
|
68
|
+
if (trimmed === '' || trimmed.startsWith('...'))
|
|
69
|
+
continue;
|
|
70
|
+
const key = trimmed.split(':')[0].split('=')[0].trim();
|
|
71
|
+
if (/^[A-Za-z_$][\w$]*$/.test(key))
|
|
72
|
+
names.push(key);
|
|
73
|
+
}
|
|
74
|
+
return names;
|
|
75
|
+
}
|
|
76
|
+
export function wrapSyncDefaultExportWithParams(sourceText, localeParam, existingParamsType) {
|
|
77
|
+
const nameMatch = SYNC_DEFAULT_EXPORT_FUNCTION.exec(sourceText);
|
|
78
|
+
if (nameMatch === null)
|
|
79
|
+
return sourceText;
|
|
80
|
+
const name = nameMatch[1];
|
|
81
|
+
const paramList = findParamListSpan(sourceText);
|
|
82
|
+
if (paramList === null)
|
|
83
|
+
return sourceText;
|
|
84
|
+
const bodyStart = findFunctionBodyStart(sourceText);
|
|
85
|
+
if (bodyStart === null)
|
|
86
|
+
return sourceText;
|
|
87
|
+
const bodyEnd = findMatchingBraceEnd(sourceText, bodyStart - 1);
|
|
88
|
+
if (bodyEnd === null)
|
|
89
|
+
return sourceText;
|
|
90
|
+
const contentName = findUnusedContentName(sourceText, name);
|
|
91
|
+
const originalParams = sourceText.slice(paramList.start, paramList.end);
|
|
92
|
+
const originalBody = sourceText.slice(bodyStart, bodyEnd - 1);
|
|
93
|
+
let forwardKeys = [];
|
|
94
|
+
let forwardKeyTypes = [];
|
|
95
|
+
if (originalParams !== '()') {
|
|
96
|
+
const openBrace = originalParams.indexOf('{');
|
|
97
|
+
if (openBrace === -1)
|
|
98
|
+
return sourceText;
|
|
99
|
+
const keysEnd = findMatchingBraceEnd(originalParams, openBrace);
|
|
100
|
+
if (keysEnd === null)
|
|
101
|
+
return sourceText;
|
|
102
|
+
forwardKeys = destructuredKeyNames(originalParams.slice(openBrace + 1, keysEnd - 1));
|
|
103
|
+
let j = keysEnd;
|
|
104
|
+
while (j < originalParams.length && /\s/.test(originalParams[j]))
|
|
105
|
+
j++;
|
|
106
|
+
if (originalParams[j] === ':') {
|
|
107
|
+
j++;
|
|
108
|
+
while (j < originalParams.length && /\s/.test(originalParams[j]))
|
|
109
|
+
j++;
|
|
110
|
+
if (originalParams[j] === '{') {
|
|
111
|
+
const typeEnd = findMatchingBraceEnd(originalParams, j);
|
|
112
|
+
if (typeEnd !== null) {
|
|
113
|
+
const typeBody = originalParams.slice(j + 1, typeEnd - 1).trim();
|
|
114
|
+
forwardKeyTypes = typeBody === '' ? [] : typeBody.split(';').map((s) => s.trim()).filter(Boolean);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const otherForwardKeys = forwardKeys.filter((key) => key !== 'params');
|
|
120
|
+
const otherForwardKeyTypes = forwardKeyTypes.filter((type) => !/^params\s*:/.test(type));
|
|
121
|
+
const contentFunction = `function ${contentName}${originalParams} {${originalBody}}`;
|
|
122
|
+
const alreadyHasLocaleParam = existingParamsType !== undefined && new RegExp(`\\b${localeParam}\\b`).test(existingParamsType);
|
|
123
|
+
const wrapperParamsType = existingParamsType === undefined
|
|
124
|
+
? `${localeParam}: Language`
|
|
125
|
+
: alreadyHasLocaleParam
|
|
126
|
+
? existingParamsType
|
|
127
|
+
: `${existingParamsType.replace(/;?\s*$/, '')}; ${localeParam}: Language`;
|
|
128
|
+
const wrapperSignature = otherForwardKeys.length === 0 ? `{ params }` : `{ ${otherForwardKeys.join(', ')}, params }`;
|
|
129
|
+
const forwardedJsx = forwardKeys.map((key) => (key === 'params' ? ` params={params}` : ` ${key}={${key}}`)).join('');
|
|
130
|
+
const forwardedTypeLines = otherForwardKeyTypes.map((type) => ` ${type.replace(/;?\s*$/, '')};`);
|
|
131
|
+
const wrapperFunction = [
|
|
132
|
+
`// Auto-inserted by cloudflare-next-intl's checkLocaleParams (mode: "fix") — `
|
|
133
|
+
+ `"${name}" was split into this async wrapper plus the sync "${contentName}" above `
|
|
134
|
+
+ `it (see that function's own body, unchanged) so \`await params\` never lands in a `
|
|
135
|
+
+ `function this scan didn't confirm was safe to make async. To opt this file out on a `
|
|
136
|
+
+ `later run, pass it in checkLocaleParams' \`skip\` list instead of hand-editing here.`,
|
|
137
|
+
`export default async function ${name}(${wrapperSignature}: {`,
|
|
138
|
+
...forwardedTypeLines,
|
|
139
|
+
` params: Promise<{ ${wrapperParamsType} }>;`,
|
|
140
|
+
`}) {`,
|
|
141
|
+
` const { ${localeParam} } = await params;`,
|
|
142
|
+
` setLocale(${localeParam});`,
|
|
143
|
+
``,
|
|
144
|
+
` return <${contentName}${forwardedJsx} />;`,
|
|
145
|
+
`}`,
|
|
146
|
+
].join('\n');
|
|
147
|
+
return sourceText.slice(0, nameMatch.index) + contentFunction + '\n\n' + wrapperFunction + sourceText.slice(bodyEnd);
|
|
148
|
+
}
|
|
22
149
|
function findMatchingBraceEnd(code, openBraceIndex) {
|
|
23
150
|
let depth = 0;
|
|
24
151
|
for (let i = openBraceIndex; i < code.length; i++) {
|
|
@@ -90,6 +217,9 @@ export function insertLocaleParamsBody(sourceText, localeParam, hasInlineDestruc
|
|
|
90
217
|
return sourceText.slice(0, bodyStart) + line + sourceText.slice(bodyStart);
|
|
91
218
|
}
|
|
92
219
|
const PARAMS_PROMISE_TYPE = /params\s*:\s*Promise<\{([^}]*)\}>/;
|
|
220
|
+
export function extractParamsPromiseType(sourceText) {
|
|
221
|
+
return PARAMS_PROMISE_TYPE.exec(sourceText)?.[1]?.trim() ?? null;
|
|
222
|
+
}
|
|
93
223
|
export function ensureLocaleInParamsType(sourceText, localeParam) {
|
|
94
224
|
const match = PARAMS_PROMISE_TYPE.exec(sourceText);
|
|
95
225
|
if (match === null)
|