@koine/i18n 2.0.0-beta.100
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/README.md +1 -0
- package/adapter-js/code/config.cjs.d.ts +3 -0
- package/adapter-js/code/config.d.ts +3 -0
- package/adapter-js/code/createT.d.ts +3 -0
- package/adapter-js/code/defaultI18nMetadata.d.ts +3 -0
- package/adapter-js/code/defaultLocale.d.ts +3 -0
- package/adapter-js/code/formatUrl.d.ts +3 -0
- package/adapter-js/code/getI18nAlternatesFromDom.d.ts +3 -0
- package/adapter-js/code/getI18nDictionaries.d.ts +3 -0
- package/adapter-js/code/getI18nMetadata.d.ts +3 -0
- package/adapter-js/code/getT.d.ts +3 -0
- package/adapter-js/code/index.d.ts +3 -0
- package/adapter-js/code/isLocale.d.ts +3 -0
- package/adapter-js/code/loadTranslations.d.ts +3 -0
- package/adapter-js/code/locales.d.ts +3 -0
- package/adapter-js/code/pathnameToRouteId.d.ts +3 -0
- package/adapter-js/code/routes.d.ts +3 -0
- package/adapter-js/code/routesError.d.ts +3 -0
- package/adapter-js/code/routesSlim.d.ts +3 -0
- package/adapter-js/code/routesSpa.d.ts +3 -0
- package/adapter-js/code/t.d.ts +3 -0
- package/adapter-js/code/tInterpolateParams.d.ts +3 -0
- package/adapter-js/code/tPluralise.d.ts +3 -0
- package/adapter-js/code/to.d.ts +3 -0
- package/adapter-js/code/toFns.d.ts +3 -0
- package/adapter-js/code/toFormat.d.ts +3 -0
- package/adapter-js/code/toSpa.d.ts +3 -0
- package/adapter-js/code/types.d.ts +3 -0
- package/adapter-js/index.d.ts +5 -0
- package/adapter-js/options.d.ts +4 -0
- package/adapter-next/code/I18nApp.d.ts +3 -0
- package/adapter-next/code/I18nHead.d.ts +3 -0
- package/adapter-next/code/I18nLayout.d.ts +3 -0
- package/adapter-next/code/I18nPage.d.ts +3 -0
- package/adapter-next/code/I18nRoot.d.ts +3 -0
- package/adapter-next/code/I18nSetter.d.ts +3 -0
- package/adapter-next/code/deprecated_useLocale.d.ts +3 -0
- package/adapter-next/code/i18nGet.d.ts +3 -0
- package/adapter-next/code/index.d.ts +3 -0
- package/adapter-next/code/next-redirects.d.ts +3 -0
- package/adapter-next/code/next-rewrites.d.ts +3 -0
- package/adapter-next/code/useRouteId.d.ts +3 -0
- package/adapter-next/code/useTo.d.ts +3 -0
- package/adapter-next/code/useToSpa.d.ts +3 -0
- package/adapter-next/index.d.ts +5 -0
- package/adapter-next/options.d.ts +4 -0
- package/adapter-next/plugin-async.d.ts +8 -0
- package/adapter-next/plugin-legacy.d.ts +18 -0
- package/adapter-next/plugin-shared.d.ts +9 -0
- package/adapter-next/plugin.d.ts +6 -0
- package/adapter-next/redirects.d.ts +5 -0
- package/adapter-next/rewrites.d.ts +5 -0
- package/adapter-next/transformPathname.d.ts +1 -0
- package/adapter-next/webpackPluginI18n.d.ts +7 -0
- package/adapter-next-translate/code/DynamicNamespaces.d.ts +3 -0
- package/adapter-next-translate/code/I18nProvider.d.ts +3 -0
- package/adapter-next-translate/code/T.d.ts +3 -0
- package/adapter-next-translate/code/TransText.d.ts +3 -0
- package/adapter-next-translate/code/getT.d.ts +3 -0
- package/adapter-next-translate/code/index.d.ts +3 -0
- package/adapter-next-translate/code/nextTranslateI18n.d.ts +3 -0
- package/adapter-next-translate/code/useLocale.d.ts +3 -0
- package/adapter-next-translate/code/useT.d.ts +3 -0
- package/adapter-next-translate/index.d.ts +5 -0
- package/adapter-next-translate/options.d.ts +3 -0
- package/adapter-react/code/I18nContext.d.ts +3 -0
- package/adapter-react/code/I18nEffects.d.ts +3 -0
- package/adapter-react/code/I18nHeadTags.d.ts +3 -0
- package/adapter-react/code/I18nMetadataContext.d.ts +3 -0
- package/adapter-react/code/I18nMetadataProvider.d.ts +3 -0
- package/adapter-react/code/I18nMetadataSetter.d.ts +3 -0
- package/adapter-react/code/I18nProvider.d.ts +3 -0
- package/adapter-react/code/I18nRouteContext.d.ts +3 -0
- package/adapter-react/code/I18nRouteProvider.d.ts +3 -0
- package/adapter-react/code/I18nRouteSetter.d.ts +3 -0
- package/adapter-react/code/T.d.ts +3 -0
- package/adapter-react/code/TransText.d.ts +3 -0
- package/adapter-react/code/formatElements.d.ts +3 -0
- package/adapter-react/code/index.d.ts +2 -0
- package/adapter-react/code/useI18nSwitch.d.ts +3 -0
- package/adapter-react/code/useLocale.d.ts +3 -0
- package/adapter-react/code/useRouteId.d.ts +3 -0
- package/adapter-react/code/useT.d.ts +3 -0
- package/adapter-react/index.d.ts +5 -0
- package/adapter-react/options.d.ts +2 -0
- package/api.cjs.js +4026 -0
- package/api.esm.js +4000 -0
- package/client/formatRoutePathname.d.ts +4 -0
- package/client/index.d.ts +3 -0
- package/client/interpolateTo.d.ts +4 -0
- package/client/routeHasDynamicPortion.d.ts +2 -0
- package/compiler/adapter.d.ts +10 -0
- package/compiler/api.d.ts +34 -0
- package/compiler/code/data-routes.d.ts +21 -0
- package/compiler/code/data-translations.d.ts +16 -0
- package/compiler/code/data.d.ts +17 -0
- package/compiler/code/generate.d.ts +10 -0
- package/compiler/code/index.d.ts +3 -0
- package/compiler/code/tsCompile.d.ts +2 -0
- package/compiler/code/write.d.ts +10 -0
- package/compiler/config.d.ts +21 -0
- package/compiler/createAdapter.d.ts +5 -0
- package/compiler/helpers.d.ts +3 -0
- package/compiler/input/data-local.d.ts +4 -0
- package/compiler/input/data-remote.d.ts +7 -0
- package/compiler/input/data.d.ts +4 -0
- package/compiler/input/index.d.ts +4 -0
- package/compiler/input/types.d.ts +14 -0
- package/compiler/input/write.d.ts +8 -0
- package/compiler/pluralisation.d.ts +37 -0
- package/compiler/summary/data.d.ts +6 -0
- package/compiler/summary/generate.d.ts +3 -0
- package/compiler/summary/index.d.ts +2 -0
- package/compiler/summary/write.d.ts +10 -0
- package/compiler/types.d.ts +94 -0
- package/compiler-sync.cjs.d.ts +1 -0
- package/compiler-sync.cjs.default.js +1 -0
- package/compiler-sync.cjs.js +11 -0
- package/compiler-sync.cjs.mjs +2 -0
- package/compiler-sync.d.ts +4 -0
- package/compiler-sync.esm.js +7 -0
- package/compiler-worker.cjs.d.ts +1 -0
- package/compiler-worker.cjs.default.js +1 -0
- package/compiler-worker.cjs.js +17 -0
- package/compiler-worker.cjs.mjs +2 -0
- package/compiler-worker.d.ts +1 -0
- package/compiler-worker.esm.js +15 -0
- package/compiler.cjs.d.ts +1 -0
- package/compiler.cjs.default.js +1 -0
- package/compiler.cjs.js +20 -0
- package/compiler.cjs.mjs +2 -0
- package/compiler.d.ts +2 -0
- package/compiler.esm.js +12 -0
- package/formatRoutePathname.cjs.js +10 -0
- package/formatRoutePathname.esm.js +8 -0
- package/index.cjs.d.ts +1 -0
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +49 -0
- package/index.cjs.mjs +2 -0
- package/index.d.ts +2 -0
- package/index.esm.js +44 -0
- package/next.cjs.d.ts +1 -0
- package/next.cjs.default.js +1 -0
- package/next.cjs.js +353 -0
- package/next.cjs.mjs +2 -0
- package/next.d.ts +3 -0
- package/next.esm.js +329 -0
- package/package.json +62 -0
- package/types.d.ts +48 -0
package/api.cjs.js
ADDED
|
@@ -0,0 +1,4026 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var node_fs = require('node:fs');
|
|
4
|
+
var node_path = require('node:path');
|
|
5
|
+
var node = require('@koine/node');
|
|
6
|
+
var utils = require('@koine/utils');
|
|
7
|
+
var formatRoutePathname = require('./formatRoutePathname.cjs.js');
|
|
8
|
+
var t$2 = require('typescript');
|
|
9
|
+
var minimatch = require('minimatch');
|
|
10
|
+
var utils$1 = require('next/dist/shared/lib/utils');
|
|
11
|
+
var promises = require('node:fs/promises');
|
|
12
|
+
var glob = require('glob');
|
|
13
|
+
var node_https = require('node:https');
|
|
14
|
+
|
|
15
|
+
function _interopNamespace(e) {
|
|
16
|
+
if (e && e.__esModule) return e;
|
|
17
|
+
var n = Object.create(null);
|
|
18
|
+
if (e) {
|
|
19
|
+
Object.keys(e).forEach(function (k) {
|
|
20
|
+
if (k !== 'default') {
|
|
21
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
22
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function () { return e[k]; }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
n["default"] = e;
|
|
30
|
+
return Object.freeze(n);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var t__namespace = /*#__PURE__*/_interopNamespace(t$2);
|
|
34
|
+
|
|
35
|
+
// /**
|
|
36
|
+
// * Adapter creator function, either _sync_ or _async_
|
|
37
|
+
// */
|
|
38
|
+
// export type AdapterCreator<T extends AdaptersName> = (
|
|
39
|
+
// arg: AdapterArg<T>,
|
|
40
|
+
// ) => Adapter<T> | Promise<Adapter<T>>;
|
|
41
|
+
// /**
|
|
42
|
+
// * Adapter anatomy
|
|
43
|
+
// */
|
|
44
|
+
// export type Adapter<T extends AdaptersName = AdaptersName> = {
|
|
45
|
+
// dependsOn?: AdaptersName[];
|
|
46
|
+
// files: AdapterFile<T>[];
|
|
47
|
+
// /**
|
|
48
|
+
// * Adapters like `next-translate` need the JSON file to be available
|
|
49
|
+
// */
|
|
50
|
+
// needsTranslationsFiles?: boolean;
|
|
51
|
+
// };
|
|
52
|
+
let createAdapter = (e, r)=>(o, p)=>r({
|
|
53
|
+
...o,
|
|
54
|
+
adapterOptions: utils.objectMergeWithDefaults(e, p)
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const adapterJsOptions = {
|
|
58
|
+
modularized: !1
|
|
59
|
+
}; /**
|
|
60
|
+
* - When `true` it outpus each function in a separate file with a `named` and a
|
|
61
|
+
* `default` export in order to fully support SWC modularizeImport optimization.
|
|
62
|
+
* You will use these functions with named exports from `@/i18n/t`, e.g.
|
|
63
|
+
* ```ts
|
|
64
|
+
* import { myMessage_key } from "@/i18n/t";
|
|
65
|
+
*
|
|
66
|
+
* myMessage_key();
|
|
67
|
+
* ```
|
|
68
|
+
* This import is transformed into `import myMessage_key from "@/i18n/t/myMessage_key";`
|
|
69
|
+
*
|
|
70
|
+
*
|
|
71
|
+
* - When `false` usage is:
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { t } from "@/i18n";
|
|
74
|
+
*
|
|
75
|
+
* t.myMessage_key();
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @default false
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
var o$8 = (({ config: e })=>`
|
|
82
|
+
import { locales } from "./locales";
|
|
83
|
+
import { defaultLocale } from "./defaultLocale";
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
*/
|
|
87
|
+
export const config = {
|
|
88
|
+
locales,
|
|
89
|
+
defaultLocale,
|
|
90
|
+
hideDefaultLocaleInUrl: ${e.hideDefaultLocaleInUrl},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default config;
|
|
94
|
+
`);
|
|
95
|
+
|
|
96
|
+
var m$6 = (({ config: e })=>`
|
|
97
|
+
const { locales } = require("./locales");
|
|
98
|
+
const { defaultLocale } = require("./defaultLocale");
|
|
99
|
+
|
|
100
|
+
const config = {
|
|
101
|
+
locales,
|
|
102
|
+
defaultLocale,
|
|
103
|
+
hideDefaultLocaleInUrl: ${e.hideDefaultLocaleInUrl},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
exports.config = config;
|
|
107
|
+
|
|
108
|
+
module.exports = config;
|
|
109
|
+
`);
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* TODO: maybe use `params` to determine the right type with some kind of special
|
|
113
|
+
* token used in the route id
|
|
114
|
+
*
|
|
115
|
+
* NB: wrap the output of this function, e.g. `type A = {${dataParamsToTsInterfaceBody(params)}}`
|
|
116
|
+
*/ let dataParamsToTsInterfaceBody = (e)=>Object.keys(e).reduce((r, t)=>{
|
|
117
|
+
let a = e[t], s = "";
|
|
118
|
+
switch(a){
|
|
119
|
+
case "number":
|
|
120
|
+
s = "number";
|
|
121
|
+
break;
|
|
122
|
+
case "string":
|
|
123
|
+
s = "string";
|
|
124
|
+
break;
|
|
125
|
+
default:
|
|
126
|
+
s = "string | number";
|
|
127
|
+
}
|
|
128
|
+
return r.push(`${t}: ${s};`), r;
|
|
129
|
+
}, []).join(" ");
|
|
130
|
+
let escapeEachChar = (e)=>e.split("").map((e)=>`\\${e}`).join("");
|
|
131
|
+
|
|
132
|
+
var r$5 = (({ config: t, options: n })=>{
|
|
133
|
+
let { start: r, end: a } = n.translations.tokens.dynamicDelimiters;
|
|
134
|
+
return `
|
|
135
|
+
import type { I18n } from "./types";
|
|
136
|
+
import { defaultLocale } from "./defaultLocale";
|
|
137
|
+
import { tInterpolateParams } from "./tInterpolateParams";
|
|
138
|
+
|
|
139
|
+
// An optional parameter allowEmptyStrings - true as default.
|
|
140
|
+
// If allowEmptyStrings parameter is marked as false,
|
|
141
|
+
// it should log an error when an empty string is attempted to be translated
|
|
142
|
+
// and return the namespace and key as result of the translation.
|
|
143
|
+
const allowEmptyStrings = true;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @see https://github.com/aralroca/next-translate/blob/master/src/transCore.tsx
|
|
147
|
+
*/
|
|
148
|
+
export function createT<TNamespace extends I18n.TranslateNamespace>(
|
|
149
|
+
dictionaries: I18n.Dictionaries,
|
|
150
|
+
pluralRules: Intl.PluralRules,
|
|
151
|
+
locale: string = defaultLocale,
|
|
152
|
+
) {
|
|
153
|
+
const interpolateUnknown = (
|
|
154
|
+
value: unknown,
|
|
155
|
+
query?: I18n.TranslationQuery | null,
|
|
156
|
+
): typeof value => {
|
|
157
|
+
if (Array.isArray(value)) {
|
|
158
|
+
return value.map((val) => interpolateUnknown(val, query));
|
|
159
|
+
}
|
|
160
|
+
if (value instanceof Object) {
|
|
161
|
+
return objectInterpolation(
|
|
162
|
+
value as Record<string, unknown>,
|
|
163
|
+
query,
|
|
164
|
+
locale,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
return interpolation(value as string, query, locale);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return <
|
|
171
|
+
TPath extends I18n.TranslationsPaths<
|
|
172
|
+
I18n.TranslationsDictionary[TNamespace]
|
|
173
|
+
>,
|
|
174
|
+
TReturn = I18n.TranslationAtPathFromNamespace<TNamespace, TPath>,
|
|
175
|
+
>(
|
|
176
|
+
key: TPath,
|
|
177
|
+
query?: I18n.TranslationQuery,
|
|
178
|
+
options?: I18n.TranslationOptions,
|
|
179
|
+
): TReturn => {
|
|
180
|
+
const k = Array.isArray(key) ? key[0] : key;
|
|
181
|
+
const [namespace, i18nKey] = k.split("${n.translations.tokens.namespaceDelimiter}");
|
|
182
|
+
const dic = (namespace && dictionaries[namespace]) || {};
|
|
183
|
+
const pluralisedKey = getPluralisedKey(pluralRules, dic, i18nKey, query, options);
|
|
184
|
+
const dicValue = getDicValue(dic, pluralisedKey, query, options);
|
|
185
|
+
const value =
|
|
186
|
+
typeof dicValue === "object"
|
|
187
|
+
? JSON.parse(JSON.stringify(dicValue))
|
|
188
|
+
: dicValue;
|
|
189
|
+
|
|
190
|
+
const empty =
|
|
191
|
+
typeof value === "undefined" ||
|
|
192
|
+
(typeof value === "object" && !Object.keys(value).length) ||
|
|
193
|
+
(value === "" && !allowEmptyStrings);
|
|
194
|
+
|
|
195
|
+
// no need to try interpolation
|
|
196
|
+
if (empty) {
|
|
197
|
+
return query === "" ? "" : k;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// this can return an empty string if either value was already empty
|
|
201
|
+
// or it contained only an interpolation (e.g. "{{name}}") and the query param was empty
|
|
202
|
+
return interpolateUnknown(value, query) as TReturn;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// const Empty = new Symbol("Empty tranlsation message")
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get value from key (allow nested keys as parent.children)
|
|
210
|
+
*/
|
|
211
|
+
function getDicValue(
|
|
212
|
+
dic: I18n.TranslationsDictionaryLoose,
|
|
213
|
+
key: string = "",
|
|
214
|
+
query?: I18n.TranslationQuery,
|
|
215
|
+
options?: I18n.TranslationOptions,
|
|
216
|
+
): unknown | undefined {
|
|
217
|
+
const keySeparator = ".";
|
|
218
|
+
const keyParts = keySeparator ? key.split(keySeparator) : [key];
|
|
219
|
+
const returnObjects =
|
|
220
|
+
query === "obj" ||
|
|
221
|
+
options === "obj" ||
|
|
222
|
+
(options instanceof Object && options.returnObjects);
|
|
223
|
+
|
|
224
|
+
if (key === keySeparator && returnObjects) return dic;
|
|
225
|
+
|
|
226
|
+
const value: string | object = keyParts.reduce(
|
|
227
|
+
(val: I18n.TranslationsDictionaryLoose | string, key: string) => {
|
|
228
|
+
if (typeof val === "string") {
|
|
229
|
+
return {};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const res = val[key as keyof typeof val];
|
|
233
|
+
|
|
234
|
+
// pass all truthy values or (empty) strings
|
|
235
|
+
return res || (typeof res === "string" ? res : {});
|
|
236
|
+
},
|
|
237
|
+
dic,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
if (
|
|
241
|
+
typeof value === "string" ||
|
|
242
|
+
(returnObjects && Object.keys(value).length > 0)
|
|
243
|
+
) {
|
|
244
|
+
return value;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (Array.isArray(value) && returnObjects) return value;
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Control plural keys depending the {{count}} variable
|
|
253
|
+
*/
|
|
254
|
+
function getPluralisedKey(
|
|
255
|
+
pluralRules: Intl.PluralRules,
|
|
256
|
+
dic: I18n.TranslationsDictionaryLoose,
|
|
257
|
+
key: string,
|
|
258
|
+
query?: I18n.TranslationQuery | null,
|
|
259
|
+
options?: I18n.TranslationOptions,
|
|
260
|
+
): string {
|
|
261
|
+
const count = query instanceof Object ? query.count : null;
|
|
262
|
+
|
|
263
|
+
if (!query || typeof count !== "number") return key;
|
|
264
|
+
|
|
265
|
+
const numKey = \`\${key}_\${count}\`;
|
|
266
|
+
if (getDicValue(dic, numKey, query, options) !== undefined) return numKey;
|
|
267
|
+
|
|
268
|
+
const pluralKey = \`\${key}_\${pluralRules.select(count)}\`;
|
|
269
|
+
if (getDicValue(dic, pluralKey, query, options) !== undefined) {
|
|
270
|
+
return pluralKey;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const nestedNumKey = \`\${key}.\${count}\`;
|
|
274
|
+
if (getDicValue(dic, nestedNumKey, query, options) !== undefined)
|
|
275
|
+
return nestedNumKey;
|
|
276
|
+
|
|
277
|
+
const nestedKey = \`\${key}.\${pluralRules.select(count)}\`;
|
|
278
|
+
if (getDicValue(dic, nestedKey, query, options) !== undefined)
|
|
279
|
+
return nestedKey;
|
|
280
|
+
|
|
281
|
+
return key;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Replace {{variables}} to query values
|
|
286
|
+
*/
|
|
287
|
+
function interpolation(
|
|
288
|
+
text?: string,
|
|
289
|
+
query?: I18n.TranslationQuery | null,
|
|
290
|
+
_locale?: string | undefined,
|
|
291
|
+
): string {
|
|
292
|
+
if (!text || !query || query === "obj") return text || "";
|
|
293
|
+
|
|
294
|
+
return tInterpolateParams(text, query);
|
|
295
|
+
// return Object.keys(query).reduce((all, key) => {
|
|
296
|
+
// // eslint-disable-next-line no-useless-escape
|
|
297
|
+
// const regex = new RegExp(\`${escapeEachChar(r)}\\s*\${key}(?:[\\s,]+([\\w-]*))?\\s*\$${escapeEachChar(a)}\`, "gm");
|
|
298
|
+
// return all.replace(regex, (_match) => query[key as keyof typeof query] as string);
|
|
299
|
+
// }, text);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function objectInterpolation(
|
|
303
|
+
obj: Record<string, string | unknown>,
|
|
304
|
+
query?: I18n.TranslationQuery | null,
|
|
305
|
+
locale?: string,
|
|
306
|
+
) {
|
|
307
|
+
if (!query || Object.keys(query).length === 0) return obj;
|
|
308
|
+
Object.keys(obj).forEach((key) => {
|
|
309
|
+
if (obj[key] instanceof Object)
|
|
310
|
+
objectInterpolation(
|
|
311
|
+
obj[key] as Record<string, string | unknown>,
|
|
312
|
+
query,
|
|
313
|
+
locale,
|
|
314
|
+
);
|
|
315
|
+
if (typeof obj[key] === "string")
|
|
316
|
+
obj[key] = interpolation(obj[key] as string, query, locale);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
return obj;
|
|
320
|
+
}
|
|
321
|
+
`;
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
var n$6 = (({})=>`
|
|
325
|
+
import type { I18n } from "./types";
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @internal
|
|
329
|
+
*/
|
|
330
|
+
export const defaultI18nMetadata: I18n.Metadata = {
|
|
331
|
+
canonical: "",
|
|
332
|
+
alternates: {}
|
|
333
|
+
}
|
|
334
|
+
`);
|
|
335
|
+
|
|
336
|
+
var a$7 = (({ config: e })=>`
|
|
337
|
+
import type { I18n } from "./types";
|
|
338
|
+
|
|
339
|
+
export const defaultLocale: I18n.Locale = "${e.defaultLocale}";
|
|
340
|
+
|
|
341
|
+
export default defaultLocale;
|
|
342
|
+
`);
|
|
343
|
+
|
|
344
|
+
var f$4 = (({ config: { baseUrl: a, trailingSlash: e } })=>`
|
|
345
|
+
/**
|
|
346
|
+
* @param pathname Normalised, always prepended with a locale (if needed) and a slash
|
|
347
|
+
*/
|
|
348
|
+
export const formatUrl = (pathname: string) => "${a}" + ${e ? "pathname" : '(pathname === "/" ? "" : pathname)'};
|
|
349
|
+
|
|
350
|
+
export default formatUrl;
|
|
351
|
+
`);
|
|
352
|
+
|
|
353
|
+
var i$8 = (({})=>`
|
|
354
|
+
import { defaultLocale } from "./defaultLocale";
|
|
355
|
+
// import { loadTranslations } from "./loadTranslations";
|
|
356
|
+
import type { I18n } from "./types";
|
|
357
|
+
|
|
358
|
+
type GetI18nDictionariesOptions = {
|
|
359
|
+
locale?: I18n.Locale;
|
|
360
|
+
namespaces?: I18n.TranslateNamespace[];
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
export async function getI18nDictionaries({
|
|
364
|
+
locale = defaultLocale,
|
|
365
|
+
namespaces = [],
|
|
366
|
+
}: GetI18nDictionariesOptions) {
|
|
367
|
+
const translations =
|
|
368
|
+
(await Promise.all(
|
|
369
|
+
namespaces.map((namespace) =>
|
|
370
|
+
// prettier-ignore
|
|
371
|
+
import(\`./translations/\${locale}/\${namespace}.json\`).then((m) => m.default)
|
|
372
|
+
// loadTranslations(locale, namespace)
|
|
373
|
+
.catch(() => ({}))),
|
|
374
|
+
)) || [];
|
|
375
|
+
|
|
376
|
+
return namespaces.reduce((dictionaries, ns, idx) => {
|
|
377
|
+
dictionaries[ns] =
|
|
378
|
+
translations[idx] ||
|
|
379
|
+
(null as unknown as I18n.TranslationsDictionaryLoose);
|
|
380
|
+
return dictionaries;
|
|
381
|
+
}, {} as I18n.Dictionaries);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export default getI18nDictionaries;
|
|
385
|
+
`);
|
|
386
|
+
|
|
387
|
+
var s$8 = (({})=>`
|
|
388
|
+
import { defaultI18nMetadata } from "./defaultI18nMetadata";
|
|
389
|
+
import { defaultLocale } from "./defaultLocale";
|
|
390
|
+
import { formatUrl } from "./formatUrl";
|
|
391
|
+
import { locales } from "./locales";
|
|
392
|
+
import { type RouteIdError, isErrorRoute } from "./routesError";
|
|
393
|
+
import { to } from "./to";
|
|
394
|
+
import type { I18n } from "./types";
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* - All localised variants should always be included (despite the current lang)
|
|
398
|
+
* - We use the defaultLocale's URL as the \`x-default\` alternate value
|
|
399
|
+
*
|
|
400
|
+
* @internal
|
|
401
|
+
* @see https://developers.google.com/search/docs/specialty/international/localized-versions#html
|
|
402
|
+
*/
|
|
403
|
+
type GetI18nMetadataOptions<TRouteId extends I18n.RouteId | RouteIdError> =
|
|
404
|
+
{
|
|
405
|
+
locale: I18n.Locale;
|
|
406
|
+
} & I18n.RouteArgs<TRouteId>;
|
|
407
|
+
|
|
408
|
+
export function getI18nMetadata<
|
|
409
|
+
TRouteId extends I18n.RouteId | RouteIdError,
|
|
410
|
+
>({ locale: currentLocale, id, params }: GetI18nMetadataOptions<TRouteId>) {
|
|
411
|
+
if (isErrorRoute(id)) return defaultI18nMetadata;
|
|
412
|
+
const alternates: I18n.Alternates = {
|
|
413
|
+
"x-default": formatUrl(
|
|
414
|
+
params ? to(id, params, defaultLocale) : to(id, defaultLocale),
|
|
415
|
+
),
|
|
416
|
+
};
|
|
417
|
+
locales
|
|
418
|
+
.forEach((locale) => {
|
|
419
|
+
alternates[locale] = formatUrl(
|
|
420
|
+
params ? to(id, params, locale) : to(id, locale),
|
|
421
|
+
);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
return {
|
|
425
|
+
alternates,
|
|
426
|
+
canonical: formatUrl(
|
|
427
|
+
params ? to(id, params, currentLocale) : to(id, currentLocale)
|
|
428
|
+
)
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export default getI18nMetadata;
|
|
433
|
+
`);
|
|
434
|
+
|
|
435
|
+
var p$5 = (({})=>`
|
|
436
|
+
import { createT } from "./createT";
|
|
437
|
+
// import { loadTranslations } from "./loadTranslations";
|
|
438
|
+
import type { I18n } from "./types";
|
|
439
|
+
|
|
440
|
+
export async function getT<TNamespace extends I18n.TranslateNamespace>(
|
|
441
|
+
locale: I18n.Locale,
|
|
442
|
+
namespace: TNamespace,
|
|
443
|
+
) {
|
|
444
|
+
// prettier-ignore
|
|
445
|
+
const translations = await import(\`./translations/\${locale}/\${namespace}.json\`).then((m) => m.default);
|
|
446
|
+
// const translations = await loadTranslations(locale, namespace);
|
|
447
|
+
const pluralRules = new Intl.PluralRules(locale);
|
|
448
|
+
|
|
449
|
+
const t = createT({ [namespace]: translations }, pluralRules, locale);
|
|
450
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
451
|
+
return ((i18nKey: string, ...args: any[]) =>
|
|
452
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
453
|
+
(t as any)(
|
|
454
|
+
\`\${namespace}:\${i18nKey}\`,
|
|
455
|
+
...args,
|
|
456
|
+
)) as I18n.TranslateNamespaced<TNamespace>;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export default getT;
|
|
460
|
+
|
|
461
|
+
`);
|
|
462
|
+
|
|
463
|
+
var x$4 = (({})=>`
|
|
464
|
+
import { locales } from "./locales";
|
|
465
|
+
import type { I18n } from "./types";
|
|
466
|
+
|
|
467
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
468
|
+
export const isLocale = (payload: any): payload is I18n.Locale =>
|
|
469
|
+
locales.includes(payload);
|
|
470
|
+
|
|
471
|
+
export default isLocale;
|
|
472
|
+
`);
|
|
473
|
+
|
|
474
|
+
var d$6 = (({})=>`
|
|
475
|
+
import type { I18n } from "./types";
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* @internal
|
|
479
|
+
*/
|
|
480
|
+
export const loadTranslations = (
|
|
481
|
+
locale: I18n.Locale,
|
|
482
|
+
namespace: I18n.TranslateNamespace,
|
|
483
|
+
) =>
|
|
484
|
+
import(\`./translations/\${locale}/\${namespace}.json\`).then(
|
|
485
|
+
(m) => m.default,
|
|
486
|
+
);
|
|
487
|
+
`);
|
|
488
|
+
|
|
489
|
+
var l$4 = (({ config: e })=>{
|
|
490
|
+
let l = `[${e.locales.map((e)=>`"${e}"`).join(", ")}]`;
|
|
491
|
+
return `
|
|
492
|
+
export const locales = ${l} as const;
|
|
493
|
+
|
|
494
|
+
export default locales;
|
|
495
|
+
`;
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
var c$3 = (({ options: t })=>{
|
|
499
|
+
let { idDelimiter: a, optionalCatchAll: r, catchAll: o } = t.routes.tokens;
|
|
500
|
+
return `
|
|
501
|
+
/**
|
|
502
|
+
* Convert a URL like pathname to a "named route"
|
|
503
|
+
* E.g. it transforms:
|
|
504
|
+
* - \`/dashboard/user/[id]\` into \`dashboard.user.[id]\`
|
|
505
|
+
*/
|
|
506
|
+
export const pathnameToRouteId = (pathname: string) =>
|
|
507
|
+
pathname
|
|
508
|
+
.replace(/^\\//g, "")
|
|
509
|
+
.replace(/\\//g, "${a}")
|
|
510
|
+
.replace(/${utils.escapeRegExp(a)}${utils.escapeRegExp(r.start)}.+$/, "")
|
|
511
|
+
.replace(/${utils.escapeRegExp(a)}${utils.escapeRegExp(o.start)}.+$/, "")
|
|
512
|
+
.replace(/\\/index$/, "");
|
|
513
|
+
|
|
514
|
+
export default pathnameToRouteId;
|
|
515
|
+
`;
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
var u$2 = (({ routes: t })=>{
|
|
519
|
+
let e = JSON.stringify(Object.fromEntries(Object.entries(t.byId).map(([t, { pathnames: e }])=>[
|
|
520
|
+
t,
|
|
521
|
+
e
|
|
522
|
+
]).sort()), null, 2);
|
|
523
|
+
return `
|
|
524
|
+
/**
|
|
525
|
+
* @internal
|
|
526
|
+
*/
|
|
527
|
+
export const routes = ${e} as const;
|
|
528
|
+
|
|
529
|
+
// export default routes;
|
|
530
|
+
`;
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
var g$2 = (({})=>`
|
|
534
|
+
|
|
535
|
+
export type RouteIdError = (typeof routesError)[number];
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* @internal
|
|
539
|
+
*/
|
|
540
|
+
export const routesError = [
|
|
541
|
+
"404",
|
|
542
|
+
"500",
|
|
543
|
+
"403"
|
|
544
|
+
] as const;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* @internal
|
|
548
|
+
*/
|
|
549
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
550
|
+
export const isErrorRoute = (payload: any): payload is RouteIdError =>
|
|
551
|
+
routesError.includes(payload);
|
|
552
|
+
|
|
553
|
+
// export default routesError;
|
|
554
|
+
`);
|
|
555
|
+
|
|
556
|
+
var I$3 = (({ routes: t })=>{
|
|
557
|
+
let e = JSON.stringify(Object.fromEntries(Object.entries(t.byId).map(([t, { pathnamesSlim: e, pathnames: r }])=>[
|
|
558
|
+
t,
|
|
559
|
+
e || r
|
|
560
|
+
]).sort()), null, 2);
|
|
561
|
+
return `
|
|
562
|
+
/**
|
|
563
|
+
* @internal
|
|
564
|
+
*/
|
|
565
|
+
export const routesSlim = ${e} as const;
|
|
566
|
+
|
|
567
|
+
// export default routesSlim;
|
|
568
|
+
`;
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
var T$2 = (({ routes: t })=>{
|
|
572
|
+
let e = JSON.stringify(Object.fromEntries(Object.entries(t.byId).filter(([, { pathnamesSpa: t }])=>!!t).map(([t, { pathnamesSpa: e }])=>[
|
|
573
|
+
t,
|
|
574
|
+
e
|
|
575
|
+
]).sort()), null, 2);
|
|
576
|
+
return `
|
|
577
|
+
/**
|
|
578
|
+
* @internal
|
|
579
|
+
*/
|
|
580
|
+
export const routesSpa = ${e} as const;
|
|
581
|
+
|
|
582
|
+
export default routesSpa;
|
|
583
|
+
`;
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
// /**
|
|
587
|
+
// * Control plural keys depending the {{count}} variable
|
|
588
|
+
// */
|
|
589
|
+
// function plural(
|
|
590
|
+
// pluralRules: Intl.PluralRules,
|
|
591
|
+
// dic: I18nDictionary,
|
|
592
|
+
// key: string,
|
|
593
|
+
// config: I18nConfig,
|
|
594
|
+
// query?: TranslationQuery | null,
|
|
595
|
+
// options?: {
|
|
596
|
+
// returnObjects?: boolean
|
|
597
|
+
// fallback?: string | string[]
|
|
598
|
+
// }
|
|
599
|
+
// ): string {
|
|
600
|
+
// if (!query || typeof query.count !== 'number') return key
|
|
601
|
+
// const numKey = `${key}_${query.count}`
|
|
602
|
+
// if (getDicValue(dic, numKey, config, options) !== undefined) return numKey
|
|
603
|
+
// const pluralKey = `${key}_${pluralRules.select(query.count)}`
|
|
604
|
+
// if (getDicValue(dic, pluralKey, config, options) !== undefined) {
|
|
605
|
+
// return pluralKey
|
|
606
|
+
// }
|
|
607
|
+
// const nestedNumKey = `${key}.${query.count}`
|
|
608
|
+
// if (getDicValue(dic, nestedNumKey, config, options) !== undefined)
|
|
609
|
+
// return nestedNumKey
|
|
610
|
+
// const nestedKey = `${key}.${pluralRules.select(query.count)}`
|
|
611
|
+
// if (getDicValue(dic, nestedKey, config, options) !== undefined)
|
|
612
|
+
// return nestedKey
|
|
613
|
+
// return key
|
|
614
|
+
// }
|
|
615
|
+
// const getP = (dic) => {
|
|
616
|
+
// return
|
|
617
|
+
// }
|
|
618
|
+
let i$7 = (t)=>utils.isString(t) || utils.isNumber(t) ? `"${t}"` : utils.isBoolean(t) ? `${t}` : utils.isArray(t) ? JSON.stringify(t) : `(${JSON.stringify(t)})`, s$7 = (e, r)=>utils.areEqual(e, r), p$4 = (t, e)=>{
|
|
619
|
+
let { defaultLocale: r } = t, l = "";
|
|
620
|
+
for(let t in e){
|
|
621
|
+
let o = e[t];
|
|
622
|
+
t === r || s$7(o, e[r]) || (l += `locale === "${t}" ? ${i$7(o)} : `);
|
|
623
|
+
}
|
|
624
|
+
return l + i$7(e[r]);
|
|
625
|
+
};
|
|
626
|
+
var S = (({ config: t, options: e, translations: r })=>{
|
|
627
|
+
let l = `
|
|
628
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
629
|
+
/* eslint-disable prefer-const */
|
|
630
|
+
import type { I18n } from "./types";
|
|
631
|
+
import { tInterpolateParams } from "./tInterpolateParams";
|
|
632
|
+
import { tPluralise } from "./tPluralise";
|
|
633
|
+
|
|
634
|
+
`, n = [], s = [];
|
|
635
|
+
for(let l in r){
|
|
636
|
+
let m = "", { values: u, params: f, plural: $ } = r[l], c = `${e.translations.fnsPrefix}${l}`;
|
|
637
|
+
$ && (f ? f.count = "number" : f = {
|
|
638
|
+
count: "number"
|
|
639
|
+
});
|
|
640
|
+
let P = [
|
|
641
|
+
f ? `params: { ${dataParamsToTsInterfaceBody(f)} }` : "",
|
|
642
|
+
// for ergonomy always allow the user to pass the locale
|
|
643
|
+
"locale?: I18n.Locale"
|
|
644
|
+
].filter(Boolean).join(", ");
|
|
645
|
+
// const formatArgParams = params ? ", params" : "";
|
|
646
|
+
m += `export let ${c} = (${P}) => `;
|
|
647
|
+
let d = "";
|
|
648
|
+
utils.isPrimitive(u) ? d += i$7(u) : d += p$4(t, u), $ && (d = `tPluralise(${d}, params.count)`), m += d = f ? `tInterpolateParams(${d}, params);` : `${d};`, n.push(m), s.push(c);
|
|
649
|
+
}
|
|
650
|
+
return l + (n.join("\n") + // TODO: verify the impact of the following on bundle size, its relation to
|
|
651
|
+
// modularizeImports and maybe make this controllable through an adapter
|
|
652
|
+
// option
|
|
653
|
+
`\n\n` + `export const t = {\n ${s.join(",\n ")}\n};` + `\n\n`) + "export default t;";
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
var F = (({ options: a })=>{
|
|
657
|
+
let { start: t, end: r } = a.translations.tokens.dynamicDelimiters;
|
|
658
|
+
return `
|
|
659
|
+
/**
|
|
660
|
+
* @internal
|
|
661
|
+
*/
|
|
662
|
+
/* eslint-disable prefer-const */
|
|
663
|
+
export let tInterpolateParams = (
|
|
664
|
+
value: string,
|
|
665
|
+
params?: object,
|
|
666
|
+
) =>
|
|
667
|
+
params ? value.replace(
|
|
668
|
+
/${escapeEachChar(t)}(.*?)${escapeEachChar(r)}/g,
|
|
669
|
+
(_, key) =>
|
|
670
|
+
params[key.trim() as keyof typeof params] + "",
|
|
671
|
+
) : value;
|
|
672
|
+
|
|
673
|
+
// export default tInterpolateParams;
|
|
674
|
+
`;
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
var L = (({})=>`
|
|
678
|
+
/* eslint-disable prefer-const */
|
|
679
|
+
let pluralRules = new Intl.PluralRules();
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* @internal
|
|
683
|
+
*/
|
|
684
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
685
|
+
export let tPluralise = (values: any, count: number) =>
|
|
686
|
+
values[count] || values[pluralRules.select(count)] || (count === 0 ? values.zero : values["other"]);
|
|
687
|
+
|
|
688
|
+
// export default tPluralise;
|
|
689
|
+
`);
|
|
690
|
+
|
|
691
|
+
var M = (({})=>`
|
|
692
|
+
import { defaultLocale } from "./defaultLocale";
|
|
693
|
+
import { isLocale } from "./isLocale";
|
|
694
|
+
import { toFormat } from "./toFormat";
|
|
695
|
+
import { routesSlim } from "./routesSlim";
|
|
696
|
+
import type { I18n } from "./types";
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* *To* route utility
|
|
700
|
+
*
|
|
701
|
+
* @returns A localised relative URL based on your i18nCompiler configuration
|
|
702
|
+
*/
|
|
703
|
+
export function to<Id extends I18n.RouteId>(
|
|
704
|
+
id: Id,
|
|
705
|
+
...args: Id extends I18n.RouteIdDynamic
|
|
706
|
+
?
|
|
707
|
+
| [I18n.RouteParams[Id]]
|
|
708
|
+
| [I18n.RouteParams[Id], I18n.Locale]
|
|
709
|
+
: [] | [I18n.Locale]
|
|
710
|
+
) {
|
|
711
|
+
const locale = (isLocale(args[0]) ? args[0] : args[1]) || defaultLocale;
|
|
712
|
+
|
|
713
|
+
return toFormat(
|
|
714
|
+
locale,
|
|
715
|
+
(routesSlim[id] as Record<string, string>)[locale] ??
|
|
716
|
+
(routesSlim[id] as Record<string, string>)[defaultLocale] ??
|
|
717
|
+
routesSlim[id],
|
|
718
|
+
isLocale(args[0]) ? undefined : args[0]
|
|
719
|
+
) as I18n.RoutePathnames[Id];
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export default to;
|
|
723
|
+
`);
|
|
724
|
+
|
|
725
|
+
let e = (t, o)=>{
|
|
726
|
+
let { defaultLocale: e } = t, r = "";
|
|
727
|
+
for(let t in o){
|
|
728
|
+
let l = o[t];
|
|
729
|
+
t !== e && l !== o[e] && (r += `locale === "${t}" ? "${l}" : `);
|
|
730
|
+
}
|
|
731
|
+
return r + ('"' + o[e]) + '"';
|
|
732
|
+
};
|
|
733
|
+
var P = (({ config: r, routes: l, options: n })=>{
|
|
734
|
+
let a = 1 === r.locales.length, s = `
|
|
735
|
+
/* eslint-disable prefer-const */
|
|
736
|
+
import { toFormat } from "./toFormat";
|
|
737
|
+
import type { I18n } from "./types";
|
|
738
|
+
|
|
739
|
+
`, $ = [], i = [];
|
|
740
|
+
for(let s in l.byId){
|
|
741
|
+
let p = "", { pathnames: m, params: f } = l.byId[s], u = `${n.routes.fnsPrefix}${utils.changeCaseSnake(s)}`, c = `I18n.RouteParams["${s}"]`, F = [
|
|
742
|
+
f ? `params: ${c}` : "",
|
|
743
|
+
a ? "" : "locale?: I18n.Locale"
|
|
744
|
+
].filter(Boolean).join(", "), d = a ? '""' : "locale", x = f ? ", params" : "";
|
|
745
|
+
p += `export let ${u} = (${F}) => `, utils.isString(m) ? p += `toFormat(${d}, "${m}"${x});` : p += `toFormat(${d}, ${e(r, m)}${x});`, $.push(p), i.push(u);
|
|
746
|
+
}
|
|
747
|
+
return s + ($.join("\n") + // TODO: verify the impact of the following on bundle size, its relation to
|
|
748
|
+
// modularizeImports and maybe make this controllable through an adapter
|
|
749
|
+
// option
|
|
750
|
+
`\n\n` + `export const toFns = {\n ${i.join(",\n ")}\n};` + `\n\n`) + "export default toFns;";
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
var j = (({ config: a })=>`
|
|
754
|
+
import { defaultLocale } from "./defaultLocale";
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* @internal
|
|
758
|
+
*/
|
|
759
|
+
export function toFormat(
|
|
760
|
+
locale: string | undefined,
|
|
761
|
+
pathname: string,
|
|
762
|
+
params?: object,
|
|
763
|
+
) {
|
|
764
|
+
locale = locale || defaultLocale;
|
|
765
|
+
if (process.env["NODE_ENV"] === "development") {
|
|
766
|
+
if (params) {
|
|
767
|
+
pathname.replace(/\\[(.*?)\\]/g, (_, dynamicKey) => {
|
|
768
|
+
const key = dynamicKey as Extract<keyof typeof params, string>;
|
|
769
|
+
|
|
770
|
+
if (!(key in params)) {
|
|
771
|
+
console.warn(
|
|
772
|
+
"[@koine/i18n]::toFormat, using '" +
|
|
773
|
+
pathname +
|
|
774
|
+
"' without param '" +
|
|
775
|
+
key +
|
|
776
|
+
"'",
|
|
777
|
+
{ params }
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (!["string", "number"].includes(typeof params[key])) {
|
|
782
|
+
console.warn(
|
|
783
|
+
"[@koine/i18n]::toFormat, using '" +
|
|
784
|
+
pathname +
|
|
785
|
+
"' with unserializable param '" +
|
|
786
|
+
key +
|
|
787
|
+
"' (type '" +
|
|
788
|
+
Object.prototype.toString.call((params[key])).slice(8, -1) +
|
|
789
|
+
"')",
|
|
790
|
+
);
|
|
791
|
+
}
|
|
792
|
+
return "";
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
if (params) {
|
|
798
|
+
pathname = pathname.replace(
|
|
799
|
+
/\\[(.*?)\\]/g,
|
|
800
|
+
(_, key) =>
|
|
801
|
+
params[key as keyof typeof params] + "",
|
|
802
|
+
)
|
|
803
|
+
}
|
|
804
|
+
${a.hideDefaultLocaleInUrl ? `
|
|
805
|
+
if (locale !== defaultLocale) {
|
|
806
|
+
return "/" + locale + (pathname === "/" ? "" : pathname);
|
|
807
|
+
}
|
|
808
|
+
` : ""}
|
|
809
|
+
return pathname;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// export default toFormat;
|
|
813
|
+
`);
|
|
814
|
+
|
|
815
|
+
var h$3 = (({ config: o, options: t })=>{
|
|
816
|
+
let { idDelimiter: e } = t.routes.tokens;
|
|
817
|
+
return `
|
|
818
|
+
import { defaultLocale } from "./defaultLocale";
|
|
819
|
+
import { isLocale } from "./isLocale";
|
|
820
|
+
import { routesSpa } from "./routesSpa";
|
|
821
|
+
import { toFormat } from "./toFormat";
|
|
822
|
+
import type { I18n } from "./types";
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* *To spa* route utility
|
|
826
|
+
*
|
|
827
|
+
* @returns A localised relative URL based on your i18nCompiler configuration
|
|
828
|
+
*/
|
|
829
|
+
export function toSpa<
|
|
830
|
+
Root extends keyof I18n.RouteSpa,
|
|
831
|
+
Path extends Extract<keyof I18n.RouteSpa[Root], string>,
|
|
832
|
+
>(
|
|
833
|
+
rootId: Root,
|
|
834
|
+
pathId: Path,
|
|
835
|
+
...args: I18n.RouteJoinedId<Root, Path> extends I18n.RouteIdDynamic
|
|
836
|
+
?
|
|
837
|
+
| [I18n.RouteParams[I18n.RouteJoinedId<Root, Path>]]
|
|
838
|
+
| [I18n.RouteParams[I18n.RouteJoinedId<Root, Path>], I18n.Locale]
|
|
839
|
+
: [] | [I18n.Locale]
|
|
840
|
+
) {
|
|
841
|
+
const locale = (isLocale(args[0]) ? args[0] : args[1]) || defaultLocale;
|
|
842
|
+
const fullId = \`\${rootId}${e}\${pathId}\` as I18n.RouteJoinedId<Root, Path>;
|
|
843
|
+
return toFormat(
|
|
844
|
+
// FIXME: actually the locale will be prepended if hideDefaultLocaleInUrl will be false
|
|
845
|
+
"", // do not pass the locale so that won't be prepended
|
|
846
|
+
(routesSpa[fullId] as Record<string, string>)[locale],
|
|
847
|
+
args.length === 2
|
|
848
|
+
? args[0]
|
|
849
|
+
: args[0] && !isLocale(args[0])
|
|
850
|
+
? args[0]
|
|
851
|
+
: void 0,
|
|
852
|
+
) as I18n.RouteSpa[Root][Path];
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
export default toSpa;
|
|
856
|
+
`;
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* @see https://github.com/aralroca/next-translate?tab=readme-ov-file#5-plurals
|
|
861
|
+
*/ let s$6 = [
|
|
862
|
+
"zero",
|
|
863
|
+
"one",
|
|
864
|
+
"two",
|
|
865
|
+
"few",
|
|
866
|
+
"many",
|
|
867
|
+
"other"
|
|
868
|
+
], i$6 = "other";
|
|
869
|
+
/**
|
|
870
|
+
* Is the given string a valid plural suffix?
|
|
871
|
+
*/ let isPluralSuffix = (e)=>s$6.includes(e) || utils.isNumericLiteral(e);
|
|
872
|
+
/**
|
|
873
|
+
* Remove plural suffix from string
|
|
874
|
+
*/ let removePluralSuffix = (e)=>{
|
|
875
|
+
let [l] = utils.splitReverse(e, "_");
|
|
876
|
+
return l ? e.replace(`_${l}`, "") : e;
|
|
877
|
+
};
|
|
878
|
+
/**
|
|
879
|
+
* Get plural suffix from string
|
|
880
|
+
*/ let getPluralSuffix = (e)=>utils.splitReverse(e, "_")[0];
|
|
881
|
+
/**
|
|
882
|
+
* Is the translation value object key a plural form?
|
|
883
|
+
*
|
|
884
|
+
* Using `splitReverse` ensures to get the last underscore prefixed suffix
|
|
885
|
+
* even in a string with multiple underscores.
|
|
886
|
+
*/ let isPluralKey = (e)=>{
|
|
887
|
+
let [l] = utils.splitReverse(e, "_");
|
|
888
|
+
return isPluralSuffix(l);
|
|
889
|
+
};
|
|
890
|
+
let a$6 = (e)=>{
|
|
891
|
+
let l = {};
|
|
892
|
+
return e.forEach((e)=>{
|
|
893
|
+
let [r] = utils.split(e, "_");
|
|
894
|
+
l[r] = l[r] || [], l[r].push(e);
|
|
895
|
+
}), l;
|
|
896
|
+
};
|
|
897
|
+
/**
|
|
898
|
+
* Some translations keys won't be used directly and should be omitted
|
|
899
|
+
* from the generated types, e.g. the plural versions of the same string.
|
|
900
|
+
*/ let transformKeysForPlurals = (l)=>{
|
|
901
|
+
// only transform if we have the required plural suffix in the keys
|
|
902
|
+
if (l.some(hasRequiredPluralSuffix) || l.includes(i$6)) {
|
|
903
|
+
let r = l.filter(isPluralKey);
|
|
904
|
+
if (r.length) {
|
|
905
|
+
let t = [
|
|
906
|
+
...l
|
|
907
|
+
];
|
|
908
|
+
return utils.forin(a$6(r), (e, r)=>{
|
|
909
|
+
// add the plural root
|
|
910
|
+
l.includes(e) || t.push(e), // remove the plurals variations
|
|
911
|
+
r.forEach((e)=>{
|
|
912
|
+
l.includes(e) && (t = t.filter((l)=>l !== e));
|
|
913
|
+
});
|
|
914
|
+
}), t;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return l;
|
|
918
|
+
};
|
|
919
|
+
/**
|
|
920
|
+
* Check if the given key has the required plural suffix
|
|
921
|
+
*/ let hasRequiredPluralSuffix = (e)=>isPluralKey(e) && getPluralSuffix(e) === i$6;
|
|
922
|
+
/**
|
|
923
|
+
* Does the translation value object has plurals version?
|
|
924
|
+
*
|
|
925
|
+
* NB: here we check only for the **required** plural suffix,
|
|
926
|
+
*/ let hasPlurals = (e)=>Object.keys(e).some(hasRequiredPluralSuffix) || Object.keys(e).includes(i$6);
|
|
927
|
+
/**
|
|
928
|
+
* Is the translation value object only enumerating plurals version?
|
|
929
|
+
*/ let hasOnlyPluralKeys = (e)=>!!hasPlurals(e) && 0 === pickNonPluralKeys(e).length;
|
|
930
|
+
/**
|
|
931
|
+
* Pick the translation value object keys that _have no_ to do with pluralisation
|
|
932
|
+
*/ let pickNonPluralKeys = (e)=>Object.keys(e).filter((e)=>!isPluralSuffix(e));
|
|
933
|
+
/**
|
|
934
|
+
* Narrows the translation value object picking only keys that _have no_ to do
|
|
935
|
+
* with pluralisation
|
|
936
|
+
*/ let pickNonPluralValue = (e)=>hasPlurals(e) ? utils.objectPick(e, pickNonPluralKeys(e)) : e;
|
|
937
|
+
|
|
938
|
+
let c$2 = (e, a)=>!utils.isArray(a) && utils.isObject(a) && hasPlurals(a) ? hasOnlyPluralKeys(a) ? `"${e}": string;` : `"${e}": ${d$5(pickNonPluralValue(a))}` : `"${e}": ${d$5(a)}`, d$5 = (e)=>{
|
|
939
|
+
let o = "", r = "";
|
|
940
|
+
if (utils.isBoolean(e) ? r = "boolean" : utils.isString(e) && (r = "string"), r) o += r + ";";
|
|
941
|
+
else if (e) {
|
|
942
|
+
if (utils.isArray(e)) {
|
|
943
|
+
let t = e[0];
|
|
944
|
+
o += `${d$5(t)}[];`;
|
|
945
|
+
} else if (utils.isObject(e)) {
|
|
946
|
+
o += "{";
|
|
947
|
+
let t = transformKeysForPlurals(Object.keys(e));
|
|
948
|
+
for(let a = 0; a < t.length; a++){
|
|
949
|
+
let s = t[a], // fallback to a string otherwise plurals without root definition would
|
|
950
|
+
// not get a type otherwise, e.g. ` pluralNoDefault_...` in __mocks__
|
|
951
|
+
n = e[s] || "";
|
|
952
|
+
o += c$2(s, n);
|
|
953
|
+
}
|
|
954
|
+
o += "};";
|
|
955
|
+
}
|
|
956
|
+
} else o += "";
|
|
957
|
+
return(// adjust syntax
|
|
958
|
+
(o = o.replace(/;\[\];/g, "[];")).replace(/;+/g, ";"));
|
|
959
|
+
}, u$1 = (e, t)=>{
|
|
960
|
+
let { translationFiles: a } = t, { defaultLocale: s } = e, n = a.filter((e)=>e.locale === s), o = [];
|
|
961
|
+
for(let e = 0; e < n.length; e++){
|
|
962
|
+
let { path: t, data: a } = n[e], s = t.replace(".json", "");
|
|
963
|
+
o.push(`"${s}": ${d$5(a)}`);
|
|
964
|
+
}
|
|
965
|
+
return o.sort();
|
|
966
|
+
}, h$2 = (t)=>{
|
|
967
|
+
let a = [];
|
|
968
|
+
return utils.forin(t.byId, (e, { params: t })=>{
|
|
969
|
+
t && a.push(`"${e}": { ${dataParamsToTsInterfaceBody(t)} };`);
|
|
970
|
+
}), a;
|
|
971
|
+
}, y$1 = (e)=>e.sort().map((e)=>`"${e}"`).join(" | "), T$1 = (e, t)=>y$1(Object.keys(e.byId).filter((a)=>t(a, e.byId[a]))), m$5 = (e)=>Object.keys(e.byId).reduce((t, a)=>{
|
|
972
|
+
if (e.byId[a].inWildcard) for(let s = 0; s < e.wildcardIds.length; s++){
|
|
973
|
+
let n = e.wildcardIds[s];
|
|
974
|
+
a.startsWith(n) && (t[n] = t[n] || [], t[n].push(a));
|
|
975
|
+
}
|
|
976
|
+
return t;
|
|
977
|
+
}, {}), f$3 = (e, t, a)=>{
|
|
978
|
+
let s = m$5(t), n = [];
|
|
979
|
+
for(let o in s){
|
|
980
|
+
let r = s[o].map(// remove the root id portion and the first character which is always
|
|
981
|
+
// the route `idDelimiter`
|
|
982
|
+
(e)=>e.split(o)[1].slice(1)), i = t.byId[o].pathnames[e.defaultLocale], l = [];
|
|
983
|
+
for(let s = 0; s < r.length; s++){
|
|
984
|
+
let n = r[s], p = `${o}${a.routes.tokens.idDelimiter}${n}`, c = t.byId[p].pathnames[e.defaultLocale].split(i)[1];
|
|
985
|
+
l.push(`"${n}": "${c}";`);
|
|
986
|
+
}
|
|
987
|
+
n.push(`"${o}": { ${l.join(" ")} }`);
|
|
988
|
+
}
|
|
989
|
+
return n;
|
|
990
|
+
}, g$1 = (e, t)=>{
|
|
991
|
+
let a = [];
|
|
992
|
+
for(let s in t.byId){
|
|
993
|
+
let n = t.byId[s];
|
|
994
|
+
a.push(`"${n.id}": "${n.pathnames[e.defaultLocale]}";`);
|
|
995
|
+
}
|
|
996
|
+
return a;
|
|
997
|
+
};
|
|
998
|
+
// TODO: maybe move the Translate types into the various adapters unless we
|
|
999
|
+
// will use the same api for all of them
|
|
1000
|
+
var y$2 = (({ config: e, input: t, routes: a, options: s })=>{
|
|
1001
|
+
let n = T$1(a, (e, { params: t })=>!t), o = T$1(a, (e, { params: t })=>!!t), // const routeIdSpa = buildRoutesUnion(routes, (_, { inWildcard }) => inWildcard);
|
|
1002
|
+
{ idDelimiter: r } = s.routes.tokens;
|
|
1003
|
+
return `
|
|
1004
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
1005
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1006
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
1007
|
+
import type { Split } from "@koine/utils";
|
|
1008
|
+
import type { I18nUtils } from "@koine/i18n";
|
|
1009
|
+
import type { RouteIdError } from "./routesError";
|
|
1010
|
+
|
|
1011
|
+
export namespace I18n {
|
|
1012
|
+
/**
|
|
1013
|
+
* Any of the available locale code
|
|
1014
|
+
*/
|
|
1015
|
+
export type Locale = ${e.locales.map((e)=>`"${e}"`).join(" | ")};
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* Utility to map values by all available locales
|
|
1019
|
+
*
|
|
1020
|
+
* @usecase I need to map zendesk URLs to my project's locales
|
|
1021
|
+
*/
|
|
1022
|
+
export type LocalesMap<T = any> = Record<Locale, T>;
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* Any of the available route id
|
|
1026
|
+
*/
|
|
1027
|
+
export type RouteId = RouteIdStatic | RouteIdDynamic;
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* The static routes available ids
|
|
1031
|
+
*/
|
|
1032
|
+
export type RouteIdStatic = ${n};
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* The dynamic routes available ids
|
|
1036
|
+
*/
|
|
1037
|
+
export type RouteIdDynamic = ${o};
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Map every SPA path divided by their roots to their actual pathname value for the default locale
|
|
1041
|
+
*/
|
|
1042
|
+
export type RouteSpa = {
|
|
1043
|
+
${f$3(e, a, s).join("\n ")}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Map every route id to its actual pathanem value for the default locale
|
|
1048
|
+
*/
|
|
1049
|
+
export type RoutePathnames = {
|
|
1050
|
+
${g$1(e, a).join("\n ")}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Route dynamic params dictionary for each dynamic route id
|
|
1055
|
+
*/
|
|
1056
|
+
export type RouteParams = {
|
|
1057
|
+
${h$2(a).join("\n ")}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Utility to join two route ids
|
|
1062
|
+
*/
|
|
1063
|
+
export type RouteJoinedId<Root extends string, Tail extends string> = \`\${Root}${r}\${Tail}\` extends RouteId ? \`\${Root}${r}\${Tail}\` : never;
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* Extract all children routes that starts with the given string
|
|
1067
|
+
*
|
|
1068
|
+
* This is useful to get the subroutes of an application area, e.g. all subroutes
|
|
1069
|
+
* of a dashboard, using it with: \` type DashboardRoutes = RoutesChildrenOf<"dashboard">;\`
|
|
1070
|
+
*/
|
|
1071
|
+
export type RoutesChildrenOf<
|
|
1072
|
+
TStarts extends string,
|
|
1073
|
+
T extends string = RouteId,
|
|
1074
|
+
> = T extends \`\${TStarts}.\${infer First}\` ? \`\${TStarts}.\${First}\` : never;
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* @internal
|
|
1078
|
+
*/
|
|
1079
|
+
export type TranslationsDictionaryLoose = {
|
|
1080
|
+
[key: string]: string | TranslationsDictionaryLoose;
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* The types extracted from the translations JSON files, this is a little
|
|
1085
|
+
* more sophisticated than the type result of \`typeof "./en/messages.json"\`
|
|
1086
|
+
*/
|
|
1087
|
+
export type TranslationsDictionary = {
|
|
1088
|
+
${u$1(e, t).join("\n ")}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Any of the available translations namespaces
|
|
1093
|
+
*/
|
|
1094
|
+
export type TranslateNamespace = Extract<keyof TranslationsDictionary, string>;
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* Translation **value** found at a specific _path_ in the given _namespace_
|
|
1098
|
+
*
|
|
1099
|
+
* \`TPath\` can be any of all possible paths:
|
|
1100
|
+
* - \`myKey\` sub dictionaries within a namespace
|
|
1101
|
+
* - \`myKey.nested\` whatever nested level of nesting within a namespace
|
|
1102
|
+
*/
|
|
1103
|
+
export type TranslationAtPathFromNamespace<
|
|
1104
|
+
TNamespace extends TranslateNamespace,
|
|
1105
|
+
TPath extends TranslationsPaths<TranslationsDictionary[TNamespace]>,
|
|
1106
|
+
> = TNamespace extends TranslateNamespace
|
|
1107
|
+
? TPath extends string // TranslationsPaths<TranslationsDictionary[TNamespace]>
|
|
1108
|
+
? I18nUtils.Get<TranslationsDictionary[TNamespace], TPath>
|
|
1109
|
+
: TranslationsDictionary[TNamespace]
|
|
1110
|
+
: never;
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* The generic type passed and to use with {@link TranslationAtPath} when you
|
|
1114
|
+
* want to build a type extending that
|
|
1115
|
+
*/
|
|
1116
|
+
export type TranslationAtPathGeneric =
|
|
1117
|
+
| TranslateNamespace
|
|
1118
|
+
| TranslationsAllPaths;
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* Translation **value** found at a _path_
|
|
1122
|
+
*
|
|
1123
|
+
* \`TPath\` can be any of all possible paths begininng with a namespace:
|
|
1124
|
+
* - \`namespace\` only a namespace
|
|
1125
|
+
* - \`namespace:myKey\` sub dictionaries within a namespace
|
|
1126
|
+
* - \`namespace:myKey.nested\` whatever nested level of nesting
|
|
1127
|
+
*/
|
|
1128
|
+
export type TranslationAtPath<TPath extends TranslationAtPathGeneric> =
|
|
1129
|
+
TPath extends TranslateNamespace
|
|
1130
|
+
? TranslationsDictionary[TPath]
|
|
1131
|
+
: TPath extends \`\${infer Namespace}:\${infer Path}\`
|
|
1132
|
+
? Namespace extends TranslateNamespace
|
|
1133
|
+
? I18nUtils.Get<TranslationsDictionary[Namespace], Path>
|
|
1134
|
+
: never
|
|
1135
|
+
: never;
|
|
1136
|
+
|
|
1137
|
+
/**
|
|
1138
|
+
* All translations paths from the given _path_
|
|
1139
|
+
*
|
|
1140
|
+
* \`TPath\` can be any of all possible paths begininng with a namespace:
|
|
1141
|
+
* - \`namespace\` only a namespace
|
|
1142
|
+
* - \`namespace:myKey\` sub dictionaries within a namespace
|
|
1143
|
+
* - \`namespace:myKey.nested\` whatever nested level of nesting
|
|
1144
|
+
*/
|
|
1145
|
+
export type TranslationsPathsFrom<TPath extends TranslationAtPathGeneric> =
|
|
1146
|
+
TPath extends TranslateNamespace
|
|
1147
|
+
? TranslationsPaths<TranslationsDictionary[TPath]>
|
|
1148
|
+
: TPath extends \`\${infer Namespace}:\${infer Path}\`
|
|
1149
|
+
? Namespace extends TranslateNamespace
|
|
1150
|
+
? I18nUtils.Get<TranslationsDictionary[Namespace], Path> extends object
|
|
1151
|
+
? TranslationsPaths<I18nUtils.Get<TranslationsDictionary[Namespace], Path>>
|
|
1152
|
+
: TranslationsPaths<TranslationsDictionary[Namespace]>
|
|
1153
|
+
: never
|
|
1154
|
+
: never;
|
|
1155
|
+
|
|
1156
|
+
/**
|
|
1157
|
+
* All translations _paths_ of the given one, e.g. if \`TPath\` would be
|
|
1158
|
+
* \`"dashboard.users.[id].edit"\` the generated type would be the union
|
|
1159
|
+
* \`"dashboard.users.[id]" | "dashboard.users" | "dashboard"\`.
|
|
1160
|
+
*/
|
|
1161
|
+
export type TranslationsPathsAncestors<
|
|
1162
|
+
TPath extends string,
|
|
1163
|
+
TSeparator extends string = ".",
|
|
1164
|
+
> = I18nUtils.BuildRecursiveJoin<Split<TPath, TSeparator>, TSeparator>;
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* Recursive mapped type to extract all usable string paths from a translation
|
|
1168
|
+
* definition object (usually from a JSON file).
|
|
1169
|
+
*/
|
|
1170
|
+
export type TranslationsPaths<T, TAsObj extends boolean = true> = I18nUtils.Paths<T, TAsObj>;
|
|
1171
|
+
|
|
1172
|
+
/**
|
|
1173
|
+
* Recursive mapped type of all usable string paths from the whole translations
|
|
1174
|
+
* dictionary.
|
|
1175
|
+
*/
|
|
1176
|
+
export type TranslationsAllPaths = I18nUtils.AllPaths<TranslationsDictionary>;
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Unlike in \`next-translate\` we allow passing some predefined arguments as
|
|
1180
|
+
* shortcuts for common use cases:
|
|
1181
|
+
* - \`"obj"\` as a shortcut for \`{ returnObjects: true }\`
|
|
1182
|
+
* - \`""\` as a shortcut for \`{ fallback: "" }\`
|
|
1183
|
+
*
|
|
1184
|
+
*/
|
|
1185
|
+
type TranslationShortcut = "obj" | "";
|
|
1186
|
+
|
|
1187
|
+
/**
|
|
1188
|
+
* Query object to populate the returned translated string interpolating data
|
|
1189
|
+
* or a TranslationShortcut.
|
|
1190
|
+
*
|
|
1191
|
+
* NOTE: when using a shortcut passing TranslationOptions to \`t()\` is not supported
|
|
1192
|
+
* TODO: type safe this behaviour of the third argument (options).
|
|
1193
|
+
*/
|
|
1194
|
+
type TranslationQuery =
|
|
1195
|
+
| undefined
|
|
1196
|
+
| null
|
|
1197
|
+
| TranslationShortcut
|
|
1198
|
+
| {
|
|
1199
|
+
[key: string]: string | number | boolean;
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Options of the translate function or a TranslationShortcut.
|
|
1204
|
+
*
|
|
1205
|
+
* NOTE: when using a shortcut passing TranslationOptions to \`t()\` is not supported
|
|
1206
|
+
* TODO: type safe this behaviour of the third argument (options).
|
|
1207
|
+
*/
|
|
1208
|
+
type TranslationOptions =
|
|
1209
|
+
| undefined
|
|
1210
|
+
| TranslationShortcut
|
|
1211
|
+
| {
|
|
1212
|
+
returnObjects?: boolean;
|
|
1213
|
+
fallback?: string | string[];
|
|
1214
|
+
default?: string;
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Translate function which optionally accept a namespace as first argument
|
|
1219
|
+
*/
|
|
1220
|
+
export type Translate<
|
|
1221
|
+
TNamespace extends TranslateNamespace | undefined = TranslateNamespace,
|
|
1222
|
+
> = TNamespace extends TranslateNamespace
|
|
1223
|
+
? TranslateNamespaced<TNamespace>
|
|
1224
|
+
: TranslateDefault;
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Translate function **without** namespace, it allows to select any of the all
|
|
1228
|
+
* available strings in _all_ namespaces.
|
|
1229
|
+
*/
|
|
1230
|
+
export type TranslateDefault = <
|
|
1231
|
+
TPath extends TranslationsAllPaths,
|
|
1232
|
+
TReturn = TranslationAtPath<TPath>,
|
|
1233
|
+
>(
|
|
1234
|
+
path: TPath,
|
|
1235
|
+
query?: TranslationQuery,
|
|
1236
|
+
options?: TranslationOptions,
|
|
1237
|
+
) => TReturn;
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Translate function **with** namespace, it allows to select all available
|
|
1241
|
+
* strings _only_ in the given namespace.
|
|
1242
|
+
*/
|
|
1243
|
+
export type TranslateNamespaced<TNamespace extends TranslateNamespace> = <
|
|
1244
|
+
TPath extends TranslationsPaths<TranslationsDictionary[TNamespace]>,
|
|
1245
|
+
TReturn = TranslationAtPathFromNamespace<TNamespace, TPath>,
|
|
1246
|
+
>(
|
|
1247
|
+
path: TPath,
|
|
1248
|
+
query?: TranslationQuery,
|
|
1249
|
+
options?: TranslationOptions,
|
|
1250
|
+
) => TReturn;
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Translate function _loose_ type, to use only in implementations that uses
|
|
1254
|
+
* the \`t\` function indirectly without needng knowledge of the string it needs
|
|
1255
|
+
* to output.
|
|
1256
|
+
*/
|
|
1257
|
+
export type TranslateLoose<TReturn = string> = (
|
|
1258
|
+
path?: any,
|
|
1259
|
+
query?: TranslationQuery,
|
|
1260
|
+
options?: TranslationOptions,
|
|
1261
|
+
) => TReturn;
|
|
1262
|
+
|
|
1263
|
+
/**
|
|
1264
|
+
* Translate function _loosest_ type it allows to return string or object or array
|
|
1265
|
+
* or whatever basically.
|
|
1266
|
+
*/
|
|
1267
|
+
export type TranslateLoosest<TReturn = any> = (
|
|
1268
|
+
path?: any,
|
|
1269
|
+
query?: TranslationQuery,
|
|
1270
|
+
options?: TranslationOptions,
|
|
1271
|
+
) => TReturn;
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* @internal
|
|
1275
|
+
*/
|
|
1276
|
+
export type Dictionaries = Record<string, TranslationsDictionaryLoose>;
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* @internal
|
|
1280
|
+
*/
|
|
1281
|
+
export type RouteArgs<TRouteId extends RouteId | RouteIdError> =
|
|
1282
|
+
| {
|
|
1283
|
+
id: TRouteId extends RouteIdDynamic ? TRouteId : never;
|
|
1284
|
+
params: TRouteId extends RouteIdDynamic ? RouteParams[TRouteId] : never;
|
|
1285
|
+
}
|
|
1286
|
+
| {
|
|
1287
|
+
id: TRouteId extends RouteIdStatic | RouteIdError ? TRouteId : never;
|
|
1288
|
+
params?: undefined;
|
|
1289
|
+
};
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* Params globally available from the URL/folder structure named accordingly
|
|
1293
|
+
* to the \`localeParam\` option, e.g. \`lang\` for a typical folder structure
|
|
1294
|
+
* such as \`/[lang]/my-route/page.tsx\`.
|
|
1295
|
+
*/
|
|
1296
|
+
export type Params = {
|
|
1297
|
+
${s.routes.localeParamName}: Locale;
|
|
1298
|
+
};
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Props available to each page/layout when a root \`localeParam\` is in place (e.g.
|
|
1302
|
+
* in the typical _next.js_ folder structure \`/[lang]/my-route/page.tsx\`).
|
|
1303
|
+
*/
|
|
1304
|
+
export type Props<TProps = {}> = TProps & {
|
|
1305
|
+
params: Params;
|
|
1306
|
+
};
|
|
1307
|
+
|
|
1308
|
+
/**
|
|
1309
|
+
* Dictionary to generate SEO friendly alternate URLs \`<links>\` where:
|
|
1310
|
+
*
|
|
1311
|
+
* - _key_: \`x-default\` or any valid locale code (see [Google docs](https://developers.google.com/search/docs/specialty/international/localized-versions#language-codes))
|
|
1312
|
+
* - _value_: fully qualified and localised absolute URL
|
|
1313
|
+
*
|
|
1314
|
+
* It can also be an empty object, for instance with error routes.
|
|
1315
|
+
*
|
|
1316
|
+
* NOTE: this type should satisfy the nextjs type too that is:
|
|
1317
|
+
* TODO: maybe build a test for this
|
|
1318
|
+
* \`\`\`ts
|
|
1319
|
+
* import type { Metadata as NextMetadata } from "next";
|
|
1320
|
+
*
|
|
1321
|
+
* type Alternates = NonNullable<NextMetadata["alternates"]>["languages"];
|
|
1322
|
+
* \`\`\`
|
|
1323
|
+
*/
|
|
1324
|
+
export type Alternates = Record<string, string>;
|
|
1325
|
+
|
|
1326
|
+
/**
|
|
1327
|
+
* I18n/routing related SEO metadata:
|
|
1328
|
+
*
|
|
1329
|
+
* NOTE: this type should satisfy the nextjs type too that is:
|
|
1330
|
+
* TODO: maybe build a test for this
|
|
1331
|
+
* \`\`\`ts
|
|
1332
|
+
* import type { Metadata as NextMetadata } from "next";
|
|
1333
|
+
*
|
|
1334
|
+
* type Metadata = NonNullable<NextMetadata["alternates"]>;
|
|
1335
|
+
* \`\`\`
|
|
1336
|
+
*/
|
|
1337
|
+
export type Metadata = {
|
|
1338
|
+
alternates: Alternates;
|
|
1339
|
+
canonical: null | string;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
`;
|
|
1343
|
+
});
|
|
1344
|
+
|
|
1345
|
+
var t$1 = createAdapter(adapterJsOptions, ({})=>({
|
|
1346
|
+
files: [
|
|
1347
|
+
{
|
|
1348
|
+
name: "config.cjs",
|
|
1349
|
+
fn: m$6,
|
|
1350
|
+
ext: "js"
|
|
1351
|
+
},
|
|
1352
|
+
{
|
|
1353
|
+
name: "config",
|
|
1354
|
+
fn: o$8,
|
|
1355
|
+
ext: "ts",
|
|
1356
|
+
index: !0
|
|
1357
|
+
},
|
|
1358
|
+
{
|
|
1359
|
+
name: "createT",
|
|
1360
|
+
fn: r$5,
|
|
1361
|
+
ext: "ts",
|
|
1362
|
+
index: !0
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
name: "defaultI18nMetadata",
|
|
1366
|
+
fn: n$6,
|
|
1367
|
+
ext: "ts"
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
name: "defaultLocale",
|
|
1371
|
+
fn: a$7,
|
|
1372
|
+
ext: "ts",
|
|
1373
|
+
index: !0
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
name: "formatUrl",
|
|
1377
|
+
fn: f$4,
|
|
1378
|
+
ext: "ts",
|
|
1379
|
+
index: !0
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
name: "getI18nMetadata",
|
|
1383
|
+
fn: s$8,
|
|
1384
|
+
ext: "ts",
|
|
1385
|
+
index: !0
|
|
1386
|
+
},
|
|
1387
|
+
// TODO: probably remove it or move it to `i18n/client` public utils
|
|
1388
|
+
// {
|
|
1389
|
+
// name: "getI18nAlternatesFromDom",
|
|
1390
|
+
// fn: getI18nAlternatesFromDom,
|
|
1391
|
+
// ext: "ts",
|
|
1392
|
+
// index: true,
|
|
1393
|
+
// },
|
|
1394
|
+
{
|
|
1395
|
+
name: "getI18nDictionaries",
|
|
1396
|
+
fn: i$8,
|
|
1397
|
+
ext: "ts",
|
|
1398
|
+
index: !0
|
|
1399
|
+
},
|
|
1400
|
+
{
|
|
1401
|
+
name: "getT",
|
|
1402
|
+
fn: p$5,
|
|
1403
|
+
ext: "ts",
|
|
1404
|
+
index: !0
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
name: "isLocale",
|
|
1408
|
+
fn: x$4,
|
|
1409
|
+
ext: "ts",
|
|
1410
|
+
index: !0
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
name: "loadTranslations",
|
|
1414
|
+
fn: d$6,
|
|
1415
|
+
ext: "ts"
|
|
1416
|
+
},
|
|
1417
|
+
{
|
|
1418
|
+
name: "locales",
|
|
1419
|
+
fn: l$4,
|
|
1420
|
+
ext: "ts",
|
|
1421
|
+
index: !0
|
|
1422
|
+
},
|
|
1423
|
+
{
|
|
1424
|
+
name: "pathnameToRouteId",
|
|
1425
|
+
fn: c$3,
|
|
1426
|
+
ext: "ts",
|
|
1427
|
+
index: !0
|
|
1428
|
+
},
|
|
1429
|
+
{
|
|
1430
|
+
name: "routes",
|
|
1431
|
+
fn: u$2,
|
|
1432
|
+
ext: "ts"
|
|
1433
|
+
},
|
|
1434
|
+
{
|
|
1435
|
+
name: "routesError",
|
|
1436
|
+
fn: g$2,
|
|
1437
|
+
ext: "ts"
|
|
1438
|
+
},
|
|
1439
|
+
{
|
|
1440
|
+
name: "routesSlim",
|
|
1441
|
+
fn: I$3,
|
|
1442
|
+
ext: "ts"
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
name: "routesSpa",
|
|
1446
|
+
fn: T$2,
|
|
1447
|
+
ext: "ts"
|
|
1448
|
+
},
|
|
1449
|
+
{
|
|
1450
|
+
name: "t",
|
|
1451
|
+
fn: S,
|
|
1452
|
+
ext: "ts",
|
|
1453
|
+
index: !0
|
|
1454
|
+
},
|
|
1455
|
+
{
|
|
1456
|
+
name: "tInterpolateParams",
|
|
1457
|
+
fn: F,
|
|
1458
|
+
ext: "ts"
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
name: "to",
|
|
1462
|
+
fn: M,
|
|
1463
|
+
ext: "ts",
|
|
1464
|
+
index: !0
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
name: "toFns",
|
|
1468
|
+
fn: P,
|
|
1469
|
+
ext: "ts",
|
|
1470
|
+
index: !0
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
name: "toFormat",
|
|
1474
|
+
fn: j,
|
|
1475
|
+
ext: "ts"
|
|
1476
|
+
},
|
|
1477
|
+
{
|
|
1478
|
+
name: "toSpa",
|
|
1479
|
+
fn: h$3,
|
|
1480
|
+
ext: "ts",
|
|
1481
|
+
index: !0
|
|
1482
|
+
},
|
|
1483
|
+
{
|
|
1484
|
+
name: "tPluralise",
|
|
1485
|
+
fn: L,
|
|
1486
|
+
ext: "ts"
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
name: "types",
|
|
1490
|
+
fn: y$2,
|
|
1491
|
+
ext: "ts",
|
|
1492
|
+
index: !0
|
|
1493
|
+
}
|
|
1494
|
+
]
|
|
1495
|
+
}));
|
|
1496
|
+
|
|
1497
|
+
const adapterNextTranslateOptions = {};
|
|
1498
|
+
|
|
1499
|
+
var t = (({})=>`
|
|
1500
|
+
"use client";
|
|
1501
|
+
|
|
1502
|
+
import _DynamicNamespaces from "next-translate/DynamicNamespaces";
|
|
1503
|
+
|
|
1504
|
+
export const DynamicNamespaces = _DynamicNamespaces;
|
|
1505
|
+
|
|
1506
|
+
export default DynamicNamespaces;
|
|
1507
|
+
`);
|
|
1508
|
+
|
|
1509
|
+
var r$4 = (({})=>`
|
|
1510
|
+
"use client";
|
|
1511
|
+
|
|
1512
|
+
import _I18nProvider from "next-translate/I18nProvider";
|
|
1513
|
+
|
|
1514
|
+
export const I18nProvider = _I18nProvider;
|
|
1515
|
+
|
|
1516
|
+
export default I18nProvider;
|
|
1517
|
+
`);
|
|
1518
|
+
|
|
1519
|
+
var m$4 = (({})=>`
|
|
1520
|
+
"use client";
|
|
1521
|
+
|
|
1522
|
+
import type { TransProps } from "next-translate";
|
|
1523
|
+
import Trans from "next-translate/Trans";
|
|
1524
|
+
import type { I18n } from "./types";
|
|
1525
|
+
|
|
1526
|
+
export type TProps<
|
|
1527
|
+
TNamespace extends I18n.TranslateNamespace | undefined = undefined,
|
|
1528
|
+
> =
|
|
1529
|
+
| (Omit<TransProps, "i18nKey" | "ns"> & {
|
|
1530
|
+
i18nKey: I18n.TranslationsAllPaths;
|
|
1531
|
+
})
|
|
1532
|
+
| (Omit<TransProps, "i18nKey" | "ns"> & {
|
|
1533
|
+
ns: TNamespace;
|
|
1534
|
+
i18nKey: I18n.TranslationsPaths<TNamespace>;
|
|
1535
|
+
});
|
|
1536
|
+
|
|
1537
|
+
const TypedT = <
|
|
1538
|
+
TNamespace extends I18n.TranslateNamespace | undefined = undefined,
|
|
1539
|
+
>(
|
|
1540
|
+
props: TProps<TNamespace>,
|
|
1541
|
+
) =>
|
|
1542
|
+
(<Trans {...(props as TransProps)} />) as React.ReactElement<
|
|
1543
|
+
TProps<TNamespace>
|
|
1544
|
+
>;
|
|
1545
|
+
|
|
1546
|
+
export const T = Trans as typeof TypedT;
|
|
1547
|
+
|
|
1548
|
+
export default T;
|
|
1549
|
+
`);
|
|
1550
|
+
|
|
1551
|
+
var o$7 = (({})=>`
|
|
1552
|
+
"use client";
|
|
1553
|
+
|
|
1554
|
+
import _TransText from "next-translate/TransText";
|
|
1555
|
+
|
|
1556
|
+
export const TransText = _TransText;
|
|
1557
|
+
|
|
1558
|
+
export default TransText;
|
|
1559
|
+
`);
|
|
1560
|
+
|
|
1561
|
+
var s$5 = (({})=>`
|
|
1562
|
+
import _getT from "next-translate/getT";
|
|
1563
|
+
import type { I18n } from "./types";
|
|
1564
|
+
|
|
1565
|
+
export type GetT = <
|
|
1566
|
+
TNamespace extends I18n.TranslateNamespace | undefined = undefined,
|
|
1567
|
+
>(
|
|
1568
|
+
locale?: I18n.Locale,
|
|
1569
|
+
namespace?: TNamespace,
|
|
1570
|
+
) => Promise<I18n.Translate<TNamespace>>;
|
|
1571
|
+
|
|
1572
|
+
export const getT = _getT as GetT;
|
|
1573
|
+
|
|
1574
|
+
export default getT;
|
|
1575
|
+
`);
|
|
1576
|
+
|
|
1577
|
+
var a$5 = (({ config: a, adapterOptions: e })=>{
|
|
1578
|
+
let { loader: t } = e;
|
|
1579
|
+
return `
|
|
1580
|
+
/**
|
|
1581
|
+
* Get 'next-translate' configuration
|
|
1582
|
+
*
|
|
1583
|
+
* @see https://github.com/vinissimus/next-translate#how-are-translations-loaded
|
|
1584
|
+
*
|
|
1585
|
+
* @param {Omit<Partial<import("next-translate").I18nConfig>, "pages"> & { pages: Record<string, import("./types").I18n.TranslateNamespace[]> }} config
|
|
1586
|
+
*/
|
|
1587
|
+
module.exports = (config = { pages: {} }) => {
|
|
1588
|
+
return {
|
|
1589
|
+
locales: [${a.locales.map((a)=>`"${a}"`).join(", ")}],
|
|
1590
|
+
defaultLocale: "${a.defaultLocale}",
|
|
1591
|
+
logBuild: false,${t ? "\n loadLocaleFrom: (locale, namespace) => import(`./translations/${locale}/${namespace}.json`).then((m) => m.default)," : ""}
|
|
1592
|
+
...${JSON.stringify(e)},
|
|
1593
|
+
...config,
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
`;
|
|
1597
|
+
});
|
|
1598
|
+
|
|
1599
|
+
var i$5 = (({ config: e })=>`
|
|
1600
|
+
import useTranslation from "next-translate/useTranslation";
|
|
1601
|
+
import { defaultLocale } from "./defaultLocale";
|
|
1602
|
+
import type { I18n } from "./types";
|
|
1603
|
+
|
|
1604
|
+
export const useLocale = () => (useTranslation().lang as I18n.Locale) || defaultLocale;
|
|
1605
|
+
|
|
1606
|
+
export default useLocale;
|
|
1607
|
+
`);
|
|
1608
|
+
|
|
1609
|
+
var x$3 = (({})=>`
|
|
1610
|
+
"use client";
|
|
1611
|
+
|
|
1612
|
+
import { useMemo } from "react";
|
|
1613
|
+
import useTranslation from "next-translate/useTranslation";
|
|
1614
|
+
import type { I18n } from "./types";
|
|
1615
|
+
|
|
1616
|
+
/**
|
|
1617
|
+
* Wrap next-translate useTranslations for type safety and adds TranslationShortcut
|
|
1618
|
+
* as second/thir argument.
|
|
1619
|
+
*
|
|
1620
|
+
* @see https://github.com/vinissimus/next-translate/issues/513#issuecomment-779826418
|
|
1621
|
+
*
|
|
1622
|
+
* About the typescript support for translation strings see:
|
|
1623
|
+
* - https://github.com/vinissimus/next-translate/issues/721
|
|
1624
|
+
*/
|
|
1625
|
+
export const useT = <TNamespace extends I18n.TranslateNamespace>(namespace: TNamespace) => {
|
|
1626
|
+
const t = useTranslation().t;
|
|
1627
|
+
const tMemoized = useMemo(
|
|
1628
|
+
() =>
|
|
1629
|
+
function <
|
|
1630
|
+
TPath extends I18n.TranslationsPaths<I18n.TranslationsDictionary[TNamespace]>,
|
|
1631
|
+
TReturn = I18n.TranslationAtPathFromNamespace<TNamespace, TPath>,
|
|
1632
|
+
>(s: TPath, q?: I18n.TranslationQuery, o?: I18n.TranslationOptions): TReturn {
|
|
1633
|
+
return t(
|
|
1634
|
+
(namespace ? namespace + ":" + s : s) as string,
|
|
1635
|
+
q === "obj" || q === "" ? null : q,
|
|
1636
|
+
q === "obj" || o === "obj"
|
|
1637
|
+
? { returnObjects: true }
|
|
1638
|
+
: q === "" || o === ""
|
|
1639
|
+
? { fallback: "" }
|
|
1640
|
+
: o,
|
|
1641
|
+
) as TReturn;
|
|
1642
|
+
// ) as TReturn extends (undefined | never | unknown) ? TranslateReturn<I18n.TranslationQuery, I18n.TranslationOptions> : TReturn;
|
|
1643
|
+
// );
|
|
1644
|
+
},
|
|
1645
|
+
[t, namespace],
|
|
1646
|
+
);
|
|
1647
|
+
return tMemoized;
|
|
1648
|
+
};
|
|
1649
|
+
|
|
1650
|
+
export default useT;
|
|
1651
|
+
`);
|
|
1652
|
+
|
|
1653
|
+
var a$4 = createAdapter(adapterNextTranslateOptions, ({ adapterOptions: e })=>{
|
|
1654
|
+
let n = [
|
|
1655
|
+
{
|
|
1656
|
+
name: "getT",
|
|
1657
|
+
fn: s$5,
|
|
1658
|
+
ext: "ts",
|
|
1659
|
+
index: !0
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
name: "nextTranslateI18n",
|
|
1663
|
+
fn: a$5,
|
|
1664
|
+
ext: "js"
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
name: "T",
|
|
1668
|
+
fn: m$4,
|
|
1669
|
+
ext: "tsx",
|
|
1670
|
+
index: !0
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
name: "TransText",
|
|
1674
|
+
fn: o$7,
|
|
1675
|
+
ext: "tsx",
|
|
1676
|
+
index: !0
|
|
1677
|
+
},
|
|
1678
|
+
{
|
|
1679
|
+
name: "useT",
|
|
1680
|
+
fn: x$3,
|
|
1681
|
+
ext: "ts",
|
|
1682
|
+
index: !0
|
|
1683
|
+
}
|
|
1684
|
+
];
|
|
1685
|
+
return !1 === e.loader ? (n.push({
|
|
1686
|
+
name: "useLocale",
|
|
1687
|
+
fn: i$5,
|
|
1688
|
+
ext: "ts",
|
|
1689
|
+
index: !0
|
|
1690
|
+
}), n.push({
|
|
1691
|
+
name: "I18nProvider",
|
|
1692
|
+
fn: r$4,
|
|
1693
|
+
ext: "tsx",
|
|
1694
|
+
index: !0
|
|
1695
|
+
})) : // TODO: check, probably DynamicNamespaces does not work without the automatic loader?
|
|
1696
|
+
n.push({
|
|
1697
|
+
name: "DynamicNamespaces",
|
|
1698
|
+
fn: t,
|
|
1699
|
+
ext: "tsx",
|
|
1700
|
+
index: !0
|
|
1701
|
+
}), {
|
|
1702
|
+
dependsOn: [
|
|
1703
|
+
"next"
|
|
1704
|
+
],
|
|
1705
|
+
needsTranslationsFiles: !0,
|
|
1706
|
+
files: n
|
|
1707
|
+
};
|
|
1708
|
+
});
|
|
1709
|
+
|
|
1710
|
+
const adapterNextOptions = {
|
|
1711
|
+
router: "app"
|
|
1712
|
+
}; /**
|
|
1713
|
+
* @default "app"
|
|
1714
|
+
*/
|
|
1715
|
+
|
|
1716
|
+
var n$5 = (({})=>`
|
|
1717
|
+
"use client";
|
|
1718
|
+
|
|
1719
|
+
import type { AppProps } from "next/app";
|
|
1720
|
+
import { defaultI18nMetadata } from "./defaultI18nMetadata";
|
|
1721
|
+
import { defaultLocale } from "./defaultLocale";
|
|
1722
|
+
import { I18nProvider } from "./I18nProvider";
|
|
1723
|
+
import { I18nMetadataProvider } from "./I18nMetadataProvider";
|
|
1724
|
+
import { I18nEffects } from "./I18nEffects";
|
|
1725
|
+
import { I18nHead } from "./I18nHead";
|
|
1726
|
+
import type { I18n } from "./types";
|
|
1727
|
+
|
|
1728
|
+
/**
|
|
1729
|
+
* @internal
|
|
1730
|
+
*/
|
|
1731
|
+
export type I18nAppPropsData = {
|
|
1732
|
+
i18n: {
|
|
1733
|
+
locale: I18n.Locale;
|
|
1734
|
+
dictionaries: I18n.Dictionaries;
|
|
1735
|
+
metadata: I18n.Metadata;
|
|
1736
|
+
}
|
|
1737
|
+
};
|
|
1738
|
+
|
|
1739
|
+
const i18nDefaults: I18nAppPropsData["i18n"] = {
|
|
1740
|
+
locale: defaultLocale,
|
|
1741
|
+
dictionaries: {},
|
|
1742
|
+
metadata: defaultI18nMetadata
|
|
1743
|
+
};
|
|
1744
|
+
|
|
1745
|
+
type I18nAppProps = React.PropsWithChildren<
|
|
1746
|
+
AppProps<I18nAppPropsData>["pageProps"]
|
|
1747
|
+
>;
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* To use in \`_app.tsx\` file wrapping your component
|
|
1751
|
+
*
|
|
1752
|
+
* **For Pages Router only**
|
|
1753
|
+
*
|
|
1754
|
+
* NB: Consider that when using ISR with \`fallback: true\` the first load
|
|
1755
|
+
* will not have any useful i18n data (App's \`pageProps\` is an empty object),
|
|
1756
|
+
* hence we provide a \`i18nDefaults\` object.
|
|
1757
|
+
*
|
|
1758
|
+
* @usage
|
|
1759
|
+
* \`\`\`ts
|
|
1760
|
+
* export default function App(props: AppProps) {
|
|
1761
|
+
* const { Component, pageProps } = props;
|
|
1762
|
+
*
|
|
1763
|
+
* return (
|
|
1764
|
+
* <I18nApp {...pageProps}>
|
|
1765
|
+
* <Component {...pageProps} />
|
|
1766
|
+
* </I18nApp>
|
|
1767
|
+
* );
|
|
1768
|
+
* }
|
|
1769
|
+
* \`\`\`
|
|
1770
|
+
*/
|
|
1771
|
+
export const I18nApp = (props: I18nAppProps) => {
|
|
1772
|
+
const { i18n, children } = props;
|
|
1773
|
+
const { locale, dictionaries, metadata } = i18n || i18nDefaults;
|
|
1774
|
+
|
|
1775
|
+
return (
|
|
1776
|
+
<I18nProvider
|
|
1777
|
+
locale={locale}
|
|
1778
|
+
dictionaries={dictionaries}
|
|
1779
|
+
>
|
|
1780
|
+
<I18nHead metadata={metadata} />
|
|
1781
|
+
<I18nMetadataProvider metadata={metadata}>
|
|
1782
|
+
{children}
|
|
1783
|
+
</I18nMetadataProvider>
|
|
1784
|
+
<I18nEffects />
|
|
1785
|
+
</I18nProvider>
|
|
1786
|
+
);
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
export default I18nApp;
|
|
1790
|
+
`);
|
|
1791
|
+
|
|
1792
|
+
/**
|
|
1793
|
+
* We cannot re-use `I18nHeadTags` as NextHead component does needs HTML tags
|
|
1794
|
+
* to be its immediate children.
|
|
1795
|
+
*
|
|
1796
|
+
* @see https://nextjs.org/docs/pages/api-reference/components/head#use-minimal-nesting
|
|
1797
|
+
*/ var r$3 = (({})=>`
|
|
1798
|
+
"use client";
|
|
1799
|
+
|
|
1800
|
+
import Head from "next/head";
|
|
1801
|
+
import { defaultI18nMetadata } from "./defaultI18nMetadata";
|
|
1802
|
+
import type { I18nHeadTagsProps } from "./I18nHeadTags";
|
|
1803
|
+
|
|
1804
|
+
export type I18nHeadProps = I18nHeadTagsProps;
|
|
1805
|
+
|
|
1806
|
+
/**
|
|
1807
|
+
* **For Pages Router only**
|
|
1808
|
+
*
|
|
1809
|
+
* @internal
|
|
1810
|
+
*/
|
|
1811
|
+
export const I18nHead = (props: I18nHeadProps) => {
|
|
1812
|
+
const { metadata = defaultI18nMetadata } = props;
|
|
1813
|
+
const { alternates, canonical } = metadata;
|
|
1814
|
+
|
|
1815
|
+
return (
|
|
1816
|
+
<Head key="I18nHead">
|
|
1817
|
+
{canonical && (
|
|
1818
|
+
<link
|
|
1819
|
+
rel="canonical"
|
|
1820
|
+
href={canonical}
|
|
1821
|
+
key="canonical"
|
|
1822
|
+
/>
|
|
1823
|
+
)}
|
|
1824
|
+
{Object.keys(alternates).map((locale) => (
|
|
1825
|
+
<link
|
|
1826
|
+
rel="alternate"
|
|
1827
|
+
hrefLang={locale}
|
|
1828
|
+
href={alternates[locale]}
|
|
1829
|
+
key={"alternate-" + locale}
|
|
1830
|
+
/>
|
|
1831
|
+
))}
|
|
1832
|
+
</Head>
|
|
1833
|
+
);
|
|
1834
|
+
};
|
|
1835
|
+
|
|
1836
|
+
// export default I18nHead;
|
|
1837
|
+
`);
|
|
1838
|
+
|
|
1839
|
+
var o$6 = (({})=>`
|
|
1840
|
+
import { I18nProvider } from "./I18nProvider";
|
|
1841
|
+
import { defaultLocale } from "./defaultLocale";
|
|
1842
|
+
import { getI18nDictionaries } from "./getI18nDictionaries";
|
|
1843
|
+
import type { I18n } from "./types";
|
|
1844
|
+
|
|
1845
|
+
export type I18nLayoutProps = React.PropsWithChildren<{
|
|
1846
|
+
locale?: I18n.Locale;
|
|
1847
|
+
namespaces?: I18n.TranslateNamespace[];
|
|
1848
|
+
}>;
|
|
1849
|
+
|
|
1850
|
+
/**
|
|
1851
|
+
* Optionally use this _in each_ \`layout.tsx\` where you have some translations
|
|
1852
|
+
* specific to that layout and its descendant layouts and pages
|
|
1853
|
+
*
|
|
1854
|
+
* **For App Router only**
|
|
1855
|
+
*/
|
|
1856
|
+
export const I18nLayout = async ({
|
|
1857
|
+
locale = defaultLocale,
|
|
1858
|
+
namespaces = [],
|
|
1859
|
+
children,
|
|
1860
|
+
}: I18nLayoutProps) => {
|
|
1861
|
+
const dictionaries = await getI18nDictionaries({ locale, namespaces });
|
|
1862
|
+
|
|
1863
|
+
return (
|
|
1864
|
+
<I18nProvider
|
|
1865
|
+
locale={locale}
|
|
1866
|
+
dictionaries={dictionaries}
|
|
1867
|
+
>
|
|
1868
|
+
{children}
|
|
1869
|
+
</I18nProvider>
|
|
1870
|
+
);
|
|
1871
|
+
};
|
|
1872
|
+
|
|
1873
|
+
export default I18nLayout;
|
|
1874
|
+
`);
|
|
1875
|
+
|
|
1876
|
+
var m$3 = (({ config: { single: e }, options: { routes: { localeParamName: t } } })=>`
|
|
1877
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1878
|
+
import { notFound } from "next/navigation";
|
|
1879
|
+
import { I18nMetadataSetter } from "./I18nMetadataSetter";
|
|
1880
|
+
import { I18nProvider } from "./I18nProvider";
|
|
1881
|
+
import { I18nRouteSetter } from "./I18nRouteSetter";
|
|
1882
|
+
import { defaultLocale } from "./defaultLocale";
|
|
1883
|
+
import { getI18nDictionaries } from "./getI18nDictionaries";
|
|
1884
|
+
import { getI18nMetadata } from "./getI18nMetadata";
|
|
1885
|
+
import { isLocale } from "./isLocale";
|
|
1886
|
+
import type { I18n } from "./types";
|
|
1887
|
+
|
|
1888
|
+
export type I18nPageProps<TRouteId extends I18n.RouteId> =
|
|
1889
|
+
React.PropsWithChildren<
|
|
1890
|
+
{
|
|
1891
|
+
locale${e ? "?" : ""}: I18n.Locale;
|
|
1892
|
+
namespaces?: I18n.TranslateNamespace[];
|
|
1893
|
+
} & I18n.RouteArgs<TRouteId>
|
|
1894
|
+
>;
|
|
1895
|
+
|
|
1896
|
+
/**
|
|
1897
|
+
* Use this _in each_ \`page.tsx\` render function
|
|
1898
|
+
*
|
|
1899
|
+
* **For App Router only**
|
|
1900
|
+
*/
|
|
1901
|
+
export const I18nPage = async <TRouteId extends I18n.RouteId>(
|
|
1902
|
+
props: I18nPageProps<TRouteId>,
|
|
1903
|
+
) => {
|
|
1904
|
+
const {
|
|
1905
|
+
locale = defaultLocale,
|
|
1906
|
+
namespaces = [],
|
|
1907
|
+
id,
|
|
1908
|
+
params,
|
|
1909
|
+
children,
|
|
1910
|
+
} = props;
|
|
1911
|
+
// @ts-expect-error FIXME: route conditional type
|
|
1912
|
+
const metadata = getI18nMetadata({ locale, id, params });
|
|
1913
|
+
const dictionaries = await getI18nDictionaries({ locale, namespaces });
|
|
1914
|
+
|
|
1915
|
+
return (
|
|
1916
|
+
<>
|
|
1917
|
+
<I18nRouteSetter id={id} />
|
|
1918
|
+
<I18nMetadataSetter metadata={metadata} />
|
|
1919
|
+
<I18nProvider
|
|
1920
|
+
locale={locale}
|
|
1921
|
+
dictionaries={dictionaries}
|
|
1922
|
+
>
|
|
1923
|
+
{children}
|
|
1924
|
+
</I18nProvider>
|
|
1925
|
+
</>
|
|
1926
|
+
);
|
|
1927
|
+
};
|
|
1928
|
+
|
|
1929
|
+
function locale(props: any): I18n.Locale;
|
|
1930
|
+
function locale(params: I18n.Props["params"]): I18n.Locale;
|
|
1931
|
+
function locale(props: I18n.Props): I18n.Locale;
|
|
1932
|
+
function locale(paramsOrProps: I18n.Props["params"] | I18n.Props) {
|
|
1933
|
+
const params = (paramsOrProps as any)?.params || paramsOrProps;
|
|
1934
|
+
if (params) {
|
|
1935
|
+
const locale = (params as any).${t};
|
|
1936
|
+
|
|
1937
|
+
if (isLocale(locale)) {
|
|
1938
|
+
return locale;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
notFound();
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
/**
|
|
1946
|
+
* Use this _in each_ \`page.tsx\` to get the current _locale_ from the page props
|
|
1947
|
+
*
|
|
1948
|
+
* It automatically 404s with next.js's \`notFound\` if the locale does not exists.
|
|
1949
|
+
*
|
|
1950
|
+
* **For App Router only**
|
|
1951
|
+
*/
|
|
1952
|
+
I18nPage.locale = locale;
|
|
1953
|
+
|
|
1954
|
+
/**
|
|
1955
|
+
* Use this _in each_ \`page.tsx\` -> \`generateMetadata\` function
|
|
1956
|
+
*
|
|
1957
|
+
* **For App Router only**
|
|
1958
|
+
*/
|
|
1959
|
+
I18nPage.metadata = <TRouteId extends I18n.RouteId>(
|
|
1960
|
+
options: Omit<I18nPageProps<TRouteId>, "namespaces">,
|
|
1961
|
+
) => {
|
|
1962
|
+
// @ts-expect-error FIXME: route conditional type
|
|
1963
|
+
const { alternates, canonical } = getI18nMetadata(options);
|
|
1964
|
+
|
|
1965
|
+
return {
|
|
1966
|
+
alternates: {
|
|
1967
|
+
canonical,
|
|
1968
|
+
languages: alternates,
|
|
1969
|
+
},
|
|
1970
|
+
};
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
export default I18nPage;
|
|
1974
|
+
`);
|
|
1975
|
+
|
|
1976
|
+
var i$4 = (({})=>`
|
|
1977
|
+
import { defaultI18nMetadata } from "./defaultI18nMetadata";
|
|
1978
|
+
import { I18nMetadataProvider } from "./I18nMetadataProvider";
|
|
1979
|
+
import { I18nRouteProvider } from "./I18nRouteProvider";
|
|
1980
|
+
import type { I18n } from "./types";
|
|
1981
|
+
|
|
1982
|
+
type I18nRootProps = React.PropsWithChildren;
|
|
1983
|
+
|
|
1984
|
+
/**
|
|
1985
|
+
* Use this _only once_ in the root \`layout.tsx\` at root folder of your app
|
|
1986
|
+
* directory (one up than the \`[lang]\` folder).
|
|
1987
|
+
*
|
|
1988
|
+
* **For App Router only**
|
|
1989
|
+
*/
|
|
1990
|
+
export const I18nRoot = ({ children }: I18nRootProps) => {
|
|
1991
|
+
return (
|
|
1992
|
+
<I18nRouteProvider id={"" as I18n.RouteId}>
|
|
1993
|
+
<I18nMetadataProvider metadata={defaultI18nMetadata}>
|
|
1994
|
+
{children}
|
|
1995
|
+
</I18nMetadataProvider>
|
|
1996
|
+
</I18nRouteProvider>
|
|
1997
|
+
);
|
|
1998
|
+
};
|
|
1999
|
+
|
|
2000
|
+
export default I18nRoot;
|
|
2001
|
+
`);
|
|
2002
|
+
|
|
2003
|
+
var x$2 = (({ config: { single: t } })=>`
|
|
2004
|
+
"use client";
|
|
2005
|
+
|
|
2006
|
+
import { useContext, useEffect } from "react";
|
|
2007
|
+
import { I18nMetadataContext } from "./I18nMetadataContext";
|
|
2008
|
+
import { I18nHead } from "./I18nHead";
|
|
2009
|
+
import { formatUrl } from "./formatUrl";
|
|
2010
|
+
import { getI18nMetadata } from "./getI18nMetadata";
|
|
2011
|
+
import { to } from "./to";
|
|
2012
|
+
import type { I18n } from "./types";
|
|
2013
|
+
import { useLocale } from "./useLocale";
|
|
2014
|
+
|
|
2015
|
+
export type I18nSetterProps<TRouteId extends I18n.RouteId> =
|
|
2016
|
+
I18n.RouteArgs<TRouteId>;
|
|
2017
|
+
|
|
2018
|
+
/**
|
|
2019
|
+
* **For Pages Router only**
|
|
2020
|
+
*
|
|
2021
|
+
* Use this in in order to update the alternates and canonical URLs.
|
|
2022
|
+
* This is _required_ in all pages in order to update the data during navigation.
|
|
2023
|
+
*
|
|
2024
|
+
* This need is particularly evident with dynamic routes pages that use
|
|
2025
|
+
* \`fallback: true\` as the initial SSR does not have any useful i18n information
|
|
2026
|
+
* available. In those page be sure to render this component when the dynamic
|
|
2027
|
+
* data is ready, in other words when the pages router is not in fallback state
|
|
2028
|
+
* anymore: \`useRouter().isFallback === false\`.
|
|
2029
|
+
*/
|
|
2030
|
+
export const I18nSetter = <TRouteId extends I18n.RouteId>(
|
|
2031
|
+
props: I18nSetterProps<TRouteId>,
|
|
2032
|
+
) => {
|
|
2033
|
+
const { id, params } = props;
|
|
2034
|
+
const locale = useLocale();
|
|
2035
|
+
const [metadata, setMetadata] = useContext(I18nMetadataContext);
|
|
2036
|
+
|
|
2037
|
+
useEffect(() => {
|
|
2038
|
+
// @ts-expect-error FIXME: route conditional type
|
|
2039
|
+
setMetadata(getI18nMetadata({ locale, id, params }));
|
|
2040
|
+
}, [id, params, locale, setMetadata]);
|
|
2041
|
+
|
|
2042
|
+
return (
|
|
2043
|
+
<I18nHead metadata={metadata} />
|
|
2044
|
+
);
|
|
2045
|
+
};
|
|
2046
|
+
|
|
2047
|
+
export default I18nSetter;
|
|
2048
|
+
`);
|
|
2049
|
+
|
|
2050
|
+
var a$3 = (({ options: { routes: { localeParamName: t } } })=>`
|
|
2051
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2052
|
+
import type { GetStaticPathsContext, GetStaticPropsContext } from "next";
|
|
2053
|
+
import type { I18nAppPropsData } from "./I18nApp";
|
|
2054
|
+
import { defaultI18nMetadata} from "./defaultI18nMetadata";
|
|
2055
|
+
import { getI18nMetadata } from "./getI18nMetadata";
|
|
2056
|
+
import { getI18nDictionaries } from "./getI18nDictionaries";
|
|
2057
|
+
import { isLocale } from "./isLocale";
|
|
2058
|
+
import { locales } from "./locales";
|
|
2059
|
+
import { type RouteIdError, isErrorRoute } from "./routesError";
|
|
2060
|
+
import type { I18n } from "./types";
|
|
2061
|
+
|
|
2062
|
+
/**
|
|
2063
|
+
* Get current _locale_ from \`getStaticProps\` context data (its first argument)
|
|
2064
|
+
*/
|
|
2065
|
+
function locale(params: GetStaticPropsContext["params"]): I18n.Locale | undefined;
|
|
2066
|
+
function locale(ctx: GetStaticPropsContext): I18n.Locale | undefined;
|
|
2067
|
+
function locale(
|
|
2068
|
+
ctxOrParams: GetStaticPropsContext["params"] | GetStaticPropsContext,
|
|
2069
|
+
) {
|
|
2070
|
+
const params = ctxOrParams?.params || ctxOrParams;
|
|
2071
|
+
if (params) {
|
|
2072
|
+
const locale = (params as any).${t};
|
|
2073
|
+
|
|
2074
|
+
if (isLocale(locale)) {
|
|
2075
|
+
return locale;
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
return; // defaultLocale;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
/**
|
|
2083
|
+
* Get localised paths to feed into \`getStaticPaths\`
|
|
2084
|
+
*/
|
|
2085
|
+
const paths = <P extends { [key: string]: any }>(params?: P) =>
|
|
2086
|
+
locales.map((l) => ({
|
|
2087
|
+
params: { ${t}: l, ...(params || {}) },
|
|
2088
|
+
// locale: l,
|
|
2089
|
+
})) as Array<string | { params: P & { ${t}: I18n.Locale }; locale?: string }>;
|
|
2090
|
+
|
|
2091
|
+
/**
|
|
2092
|
+
* Function to use as \`getStaticPaths\` with \`fallback: false\`
|
|
2093
|
+
*/
|
|
2094
|
+
const staticPaths = (_context?: GetStaticPathsContext) => ({
|
|
2095
|
+
paths: paths(),
|
|
2096
|
+
fallback: false,
|
|
2097
|
+
});
|
|
2098
|
+
|
|
2099
|
+
type I18nPropsOptions<
|
|
2100
|
+
TRouteId extends I18n.RouteId | RouteIdError,
|
|
2101
|
+
TParams,
|
|
2102
|
+
TData,
|
|
2103
|
+
> = {
|
|
2104
|
+
namespaces: I18n.TranslateNamespace[];
|
|
2105
|
+
// routeId: TRouteId;
|
|
2106
|
+
// routeParams?: TRouteId extends I18n.RouteIdDynamic
|
|
2107
|
+
// ? I18n.RouteParams[TRouteId]
|
|
2108
|
+
// : never;
|
|
2109
|
+
params?: TParams;
|
|
2110
|
+
data?: TData;
|
|
2111
|
+
} & (
|
|
2112
|
+
// as in I18n.RouteArgs
|
|
2113
|
+
| {
|
|
2114
|
+
routeId: TRouteId extends I18n.RouteIdDynamic ? TRouteId : never;
|
|
2115
|
+
routeParams: TRouteId extends I18n.RouteIdDynamic
|
|
2116
|
+
? I18n.RouteParams[TRouteId]
|
|
2117
|
+
: never;
|
|
2118
|
+
}
|
|
2119
|
+
| {
|
|
2120
|
+
routeId: TRouteId extends I18n.RouteIdStatic | RouteIdError
|
|
2121
|
+
? TRouteId
|
|
2122
|
+
: never;
|
|
2123
|
+
routeParams?: undefined;
|
|
2124
|
+
}
|
|
2125
|
+
);
|
|
2126
|
+
|
|
2127
|
+
/**
|
|
2128
|
+
* Get page props data feed into \`getStaticProps\`'s return
|
|
2129
|
+
*/
|
|
2130
|
+
const props = async <
|
|
2131
|
+
TRouteId extends I18n.RouteId | RouteIdError,
|
|
2132
|
+
TParams,
|
|
2133
|
+
TData,
|
|
2134
|
+
>({
|
|
2135
|
+
locale,
|
|
2136
|
+
namespaces,
|
|
2137
|
+
routeId,
|
|
2138
|
+
routeParams,
|
|
2139
|
+
params,
|
|
2140
|
+
data,
|
|
2141
|
+
}: {
|
|
2142
|
+
locale: I18n.Locale;
|
|
2143
|
+
} & I18nPropsOptions<TRouteId, TParams, TData>) => {
|
|
2144
|
+
const props: I18nAppPropsData = {
|
|
2145
|
+
i18n: {
|
|
2146
|
+
locale: locale,
|
|
2147
|
+
metadata: isErrorRoute(routeId)
|
|
2148
|
+
? defaultI18nMetadata
|
|
2149
|
+
: // @ts-expect-error FIXME: route conditional type
|
|
2150
|
+
getI18nMetadata({ locale, id: routeId, params: routeParams }),
|
|
2151
|
+
dictionaries: await getI18nDictionaries({ locale, namespaces }),
|
|
2152
|
+
},
|
|
2153
|
+
};
|
|
2154
|
+
|
|
2155
|
+
return {
|
|
2156
|
+
...props,
|
|
2157
|
+
params: { ${t}: locale, ...(params || ({} as TParams)) },
|
|
2158
|
+
data: data || ({} as TData),
|
|
2159
|
+
};
|
|
2160
|
+
};
|
|
2161
|
+
|
|
2162
|
+
/**
|
|
2163
|
+
* Get page props data to use as immediate return of \`getStaticProps\`
|
|
2164
|
+
*/
|
|
2165
|
+
const staticProps = async <
|
|
2166
|
+
TRouteId extends I18n.RouteId | RouteIdError,
|
|
2167
|
+
TParams,
|
|
2168
|
+
TData,
|
|
2169
|
+
>({
|
|
2170
|
+
ctx,
|
|
2171
|
+
revalidate,
|
|
2172
|
+
...options
|
|
2173
|
+
}: {
|
|
2174
|
+
ctx: GetStaticPropsContext;
|
|
2175
|
+
revalidate?: number;
|
|
2176
|
+
} & I18nPropsOptions<TRouteId, TParams, TData>) => {
|
|
2177
|
+
const locale = ctx.params?.${t} as I18n.Locale;
|
|
2178
|
+
|
|
2179
|
+
return {
|
|
2180
|
+
// @ts-expect-error FIXME: route conditional type
|
|
2181
|
+
props: await props({ locale, ...options }),
|
|
2182
|
+
revalidate,
|
|
2183
|
+
};
|
|
2184
|
+
};
|
|
2185
|
+
|
|
2186
|
+
/**
|
|
2187
|
+
* **For Pages Router only**
|
|
2188
|
+
*/
|
|
2189
|
+
export const i18nGet = {
|
|
2190
|
+
locale,
|
|
2191
|
+
paths,
|
|
2192
|
+
staticPaths,
|
|
2193
|
+
props,
|
|
2194
|
+
staticProps,
|
|
2195
|
+
};
|
|
2196
|
+
|
|
2197
|
+
export default i18nGet;
|
|
2198
|
+
`);
|
|
2199
|
+
|
|
2200
|
+
/**
|
|
2201
|
+
* Transform the route translated either into a `pathname` or a `template`.
|
|
2202
|
+
*
|
|
2203
|
+
* Here we add the wildcard flag maybe found in the pathname to the template
|
|
2204
|
+
* name too.
|
|
2205
|
+
*
|
|
2206
|
+
* @see https://nextjs.org/docs/messages/invalid-multi-match
|
|
2207
|
+
*/ function transformPathname(e, t) {
|
|
2208
|
+
return "/" + e.split("/").filter(Boolean).map((e)=>e.startsWith("[[...") ? `:${encodeURIComponent(e.slice(5, -2))}` : e.startsWith("[[") ? `:${encodeURIComponent(e.slice(2, -2))}` : e.startsWith("[") ? `:${encodeURIComponent(e.slice(1, -1))}` : `${encodeURIComponent(e)}`).join("/") + (t ? "/:wildcard*" : "");
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
function a$2(e) {
|
|
2212
|
+
let { localeSource: t, localeDestination: o, template: a, pathname: l, permanent: n } = e, i = formatRoutePathname.formatRoutePathname((t ? `${t}/` : "") + a), c = formatRoutePathname.formatRoutePathname((o ? `${o}/` : "") + l);
|
|
2213
|
+
// console.log(`redirect template "${source}" to pathname "${destination}"`);
|
|
2214
|
+
if (i !== c) return {
|
|
2215
|
+
source: i,
|
|
2216
|
+
destination: c,
|
|
2217
|
+
permanent: !!n
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
function generateRedirectForPathname(e, t, r, o, l) {
|
|
2221
|
+
let { defaultLocale: n, hideDefaultLocaleInUrl: i, localeParamName: c, permanentRedirects: s } = e, p = t === n, u = p && !i, m = {
|
|
2222
|
+
template: r,
|
|
2223
|
+
pathname: o,
|
|
2224
|
+
permanent: s
|
|
2225
|
+
};
|
|
2226
|
+
c ? // app router:
|
|
2227
|
+
u ? l.push(a$2({
|
|
2228
|
+
...m,
|
|
2229
|
+
localeDestination: t
|
|
2230
|
+
})) : p && i ? l.push(a$2({
|
|
2231
|
+
...m,
|
|
2232
|
+
localeSource: t
|
|
2233
|
+
})) : p ? l.push(a$2(m)) : l.push(a$2({
|
|
2234
|
+
...m,
|
|
2235
|
+
localeSource: t,
|
|
2236
|
+
localeDestination: t
|
|
2237
|
+
})) : // pages router:
|
|
2238
|
+
o !== r && (u ? l.push(a$2({
|
|
2239
|
+
...m,
|
|
2240
|
+
localeDestination: t
|
|
2241
|
+
})) : p ? l.push(a$2(m)) : l.push(a$2({
|
|
2242
|
+
...m,
|
|
2243
|
+
localeSource: t,
|
|
2244
|
+
localeDestination: t
|
|
2245
|
+
})));
|
|
2246
|
+
}
|
|
2247
|
+
/**
|
|
2248
|
+
* TODO: maybe write directly the vercel configuration?
|
|
2249
|
+
*
|
|
2250
|
+
* @see
|
|
2251
|
+
* - https://nextjs.org/docs/pages/api-reference/next-config-js/redirects
|
|
2252
|
+
* - https://vercel.com/docs/projects/project-configuration#redirects
|
|
2253
|
+
*/ let generateRedirects = (r, { localeParamName: a, permanentRedirects: l, tokens: n }, i)=>{
|
|
2254
|
+
let c = {
|
|
2255
|
+
...r,
|
|
2256
|
+
localeParamName: a,
|
|
2257
|
+
permanentRedirects: l
|
|
2258
|
+
}, s = RegExp(utils.escapeRegExp(n.idDelimiter), "g"), p = [];
|
|
2259
|
+
for(let e in i){
|
|
2260
|
+
let t = i[e], r = i[e].pathnames;
|
|
2261
|
+
for(let a in r){
|
|
2262
|
+
let l = r[a], // prettier-ignore
|
|
2263
|
+
n = transformPathname(e.replace(s, "/"), t.wildcard), i = transformPathname(l, t.wildcard);
|
|
2264
|
+
// we do not redirect urls children of wildcard urls
|
|
2265
|
+
if (t.inWildcard) break;
|
|
2266
|
+
generateRedirectForPathname(c, a, n, i, p);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
return utils.arrayUniqueByProperties(p.filter(Boolean), [
|
|
2270
|
+
"source",
|
|
2271
|
+
"destination"
|
|
2272
|
+
]).sort((e, t)=>e.source.localeCompare(t.source)).map((e)=>a ? e : {
|
|
2273
|
+
...e,
|
|
2274
|
+
locale: !1
|
|
2275
|
+
});
|
|
2276
|
+
};
|
|
2277
|
+
|
|
2278
|
+
var p$3 = (({ config: e, options: t, routes: o })=>{
|
|
2279
|
+
let l = JSON.stringify(generateRedirects(e, t.routes, o.byId), null, 2);
|
|
2280
|
+
return `module.exports = ${l}`;
|
|
2281
|
+
});
|
|
2282
|
+
|
|
2283
|
+
function o$5(e) {
|
|
2284
|
+
let { localeSource: t, localeDestination: a, template: o, pathname: l, passLocale: i } = e, n = "";
|
|
2285
|
+
t && (n = `/${t}`);
|
|
2286
|
+
let c = formatRoutePathname.formatRoutePathname(n + l), s = "";
|
|
2287
|
+
a && (s = `/${a}`);
|
|
2288
|
+
let p = formatRoutePathname.formatRoutePathname(s + o);
|
|
2289
|
+
// console.log(`rewrite pathname "${source}" to template "${destination}"`);
|
|
2290
|
+
if (c === p) return;
|
|
2291
|
+
let m = {
|
|
2292
|
+
source: c,
|
|
2293
|
+
destination: p
|
|
2294
|
+
};
|
|
2295
|
+
return !1 === i && (m.locale = !1), m;
|
|
2296
|
+
}
|
|
2297
|
+
const generateRewriteForPathname = (e, t, r, a, l)=>{
|
|
2298
|
+
let { defaultLocale: i, hideDefaultLocaleInUrl: n, localeParamName: c } = e, s = t === i && n, // TODO: maybe support other locales to be hidden in the URL other than the default?
|
|
2299
|
+
p = {
|
|
2300
|
+
template: r,
|
|
2301
|
+
pathname: a
|
|
2302
|
+
};
|
|
2303
|
+
c ? // app router:
|
|
2304
|
+
s ? l.push(o$5({
|
|
2305
|
+
...p,
|
|
2306
|
+
localeDestination: t,
|
|
2307
|
+
passLocale: !1
|
|
2308
|
+
})) : l.push(// prettier-ignore
|
|
2309
|
+
o$5({
|
|
2310
|
+
...p,
|
|
2311
|
+
localeSource: t,
|
|
2312
|
+
localeDestination: t,
|
|
2313
|
+
passLocale: !1
|
|
2314
|
+
})) : // pages router:
|
|
2315
|
+
// this condition only applies to the pages router as with the app one
|
|
2316
|
+
// even if the template matches the pathname we always need to rewrite
|
|
2317
|
+
// as the localeParam is always needed in the rewrite destination
|
|
2318
|
+
a !== r && (s ? l.push(o$5(p)) : l.push(// `passLocale` must be `false` or the locale prefixed rewrite won't
|
|
2319
|
+
// be applied and does not forward the locale to the route context
|
|
2320
|
+
// when the locale is included in the URL. In fact we explicitly
|
|
2321
|
+
// add the locale to the rewrite rule in order to get the least
|
|
2322
|
+
// amount of existing URLs which is a good SEO practice
|
|
2323
|
+
o$5({
|
|
2324
|
+
...p,
|
|
2325
|
+
localeSource: t,
|
|
2326
|
+
passLocale: !1
|
|
2327
|
+
})));
|
|
2328
|
+
};
|
|
2329
|
+
/**
|
|
2330
|
+
* TODO: maybe write directly the vercel configuration?
|
|
2331
|
+
*
|
|
2332
|
+
* @see
|
|
2333
|
+
* - https://nextjs.org/docs/pages/api-reference/next-config-js/rewrites
|
|
2334
|
+
* - https://vercel.com/docs/projects/project-configuration#rewrites
|
|
2335
|
+
*/ let generateRewrites = (r, { tokens: o, localeParamName: l, permanentRedirects: i }, n)=>{
|
|
2336
|
+
let c = {
|
|
2337
|
+
...r,
|
|
2338
|
+
localeParamName: l,
|
|
2339
|
+
permanentRedirects: i
|
|
2340
|
+
}, s = RegExp(utils.escapeRegExp(o.idDelimiter), "g"), p = [];
|
|
2341
|
+
for(let e in n){
|
|
2342
|
+
let t = n[e], r = n[e].pathnames;
|
|
2343
|
+
for(let o in r){
|
|
2344
|
+
let l = r[o], i = e.replace(s, "/");
|
|
2345
|
+
// we do not rewrite urls children of wildcard urls
|
|
2346
|
+
if (t.inWildcard) break;
|
|
2347
|
+
// we need to rewrite both the root path...
|
|
2348
|
+
generateRewriteForPathname(c, o, transformPathname(i), transformPathname(l), p), t.wildcard && // and for wildcard routes the ones with the `/:segment*` portion
|
|
2349
|
+
generateRewriteForPathname(c, o, transformPathname(i, t.wildcard), transformPathname(l, t.wildcard), p);
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
// simple sort by destination:
|
|
2353
|
+
// return a.destination.localeCompare(b.destination);
|
|
2354
|
+
// sort by locale
|
|
2355
|
+
// return a.
|
|
2356
|
+
return utils.arrayUniqueByProperties(p.filter(Boolean), [
|
|
2357
|
+
"source",
|
|
2358
|
+
"destination"
|
|
2359
|
+
]).sort((e, t)=>// simple sort by source:
|
|
2360
|
+
e.source.localeCompare(t.source));
|
|
2361
|
+
};
|
|
2362
|
+
|
|
2363
|
+
var f$2 = (({ config: e, routes: t, options: o })=>{
|
|
2364
|
+
let l = JSON.stringify(generateRewrites(e, o.routes, t.byId), null, 2);
|
|
2365
|
+
return `module.exports = ${l}`;
|
|
2366
|
+
});
|
|
2367
|
+
|
|
2368
|
+
var s$4 = (({ options: { routes: { localeParamName: t } }, adapterOptions: { router: e } })=>{
|
|
2369
|
+
let o = t ? `.replace("[${t}]/", "")` : "";
|
|
2370
|
+
switch(e){
|
|
2371
|
+
case "app":
|
|
2372
|
+
return `
|
|
2373
|
+
"use client";
|
|
2374
|
+
|
|
2375
|
+
import { useContext } from "react";
|
|
2376
|
+
import { I18nRouteContext } from "./I18nRouteContext";
|
|
2377
|
+
|
|
2378
|
+
export const useRouteId = () => useContext(I18nRouteContext)[0];
|
|
2379
|
+
|
|
2380
|
+
export default useRouteId;
|
|
2381
|
+
`;
|
|
2382
|
+
case "pages":
|
|
2383
|
+
return `
|
|
2384
|
+
import { useRouter } from "next/router";
|
|
2385
|
+
import { pathnameToRouteId } from "./pathnameToRouteId";
|
|
2386
|
+
import type { I18n } from "./types";
|
|
2387
|
+
|
|
2388
|
+
export const useRouteId = () =>
|
|
2389
|
+
pathnameToRouteId(useRouter().pathname${o}) as I18n.RouteId;
|
|
2390
|
+
|
|
2391
|
+
export default useRouteId;
|
|
2392
|
+
`;
|
|
2393
|
+
default:
|
|
2394
|
+
return `
|
|
2395
|
+
"use client";
|
|
2396
|
+
|
|
2397
|
+
import { useContext } from "react";
|
|
2398
|
+
import { usePathname } from "next/navigation";
|
|
2399
|
+
import { useRouter } from "next/router";
|
|
2400
|
+
import { I18nRouteContext } from "./I18nRouteContext";
|
|
2401
|
+
import { pathnameToRouteId } from "./pathnameToRouteId";
|
|
2402
|
+
import type { I18n } from "./types";
|
|
2403
|
+
|
|
2404
|
+
export const useRouteId = () => {
|
|
2405
|
+
const fromCtx = useContext(I18nRouteContext)[0];
|
|
2406
|
+
let fromPages = "";
|
|
2407
|
+
let fromApp = "";
|
|
2408
|
+
|
|
2409
|
+
try {
|
|
2410
|
+
fromPages = pathnameToRouteId(
|
|
2411
|
+
useRouter().pathname${o},
|
|
2412
|
+
) as I18n.RouteId;
|
|
2413
|
+
} catch (e) {
|
|
2414
|
+
fromApp = pathnameToRouteId(
|
|
2415
|
+
(usePathname() || "")${o},
|
|
2416
|
+
) as I18n.RouteId;
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
return fromCtx || fromPages || fromApp;
|
|
2420
|
+
};
|
|
2421
|
+
|
|
2422
|
+
export default useRouteId;
|
|
2423
|
+
`;
|
|
2424
|
+
}
|
|
2425
|
+
});
|
|
2426
|
+
|
|
2427
|
+
var d$4 = (({})=>`
|
|
2428
|
+
"use client";
|
|
2429
|
+
|
|
2430
|
+
import { to } from "./to";
|
|
2431
|
+
import type { I18n } from "./types";
|
|
2432
|
+
import { useLocale } from "./useLocale";
|
|
2433
|
+
|
|
2434
|
+
export type UseToReturn = ReturnType<typeof useTo>;
|
|
2435
|
+
|
|
2436
|
+
export const useTo = () => {
|
|
2437
|
+
const locale = useLocale();
|
|
2438
|
+
return <Id extends I18n.RouteId>(
|
|
2439
|
+
routeId: Id,
|
|
2440
|
+
...args: Id extends I18n.RouteIdDynamic
|
|
2441
|
+
? [params: I18n.RouteParams[Id]]
|
|
2442
|
+
: []
|
|
2443
|
+
) =>
|
|
2444
|
+
args[0]
|
|
2445
|
+
? // @ts-expect-error nevermind
|
|
2446
|
+
(to(routeId, args[0], locale) as I18n.RoutePathnames[Id])
|
|
2447
|
+
: // @ts-expect-error nevermind
|
|
2448
|
+
(to(routeId, locale) as I18n.RoutePathnames[Id]);
|
|
2449
|
+
};
|
|
2450
|
+
|
|
2451
|
+
export default useTo;
|
|
2452
|
+
`);
|
|
2453
|
+
|
|
2454
|
+
var I$2 = (({})=>`
|
|
2455
|
+
"use client";
|
|
2456
|
+
|
|
2457
|
+
import { toSpa } from "./toSpa";
|
|
2458
|
+
import type { I18n } from "./types";
|
|
2459
|
+
import { useLocale } from "./useLocale";
|
|
2460
|
+
|
|
2461
|
+
export type UseToSpaReturn = ReturnType<typeof useToSpa>;
|
|
2462
|
+
|
|
2463
|
+
export const useToSpa = () => {
|
|
2464
|
+
const locale = useLocale();
|
|
2465
|
+
return <
|
|
2466
|
+
Root extends keyof I18n.RouteSpa,
|
|
2467
|
+
Path extends Extract<keyof I18n.RouteSpa[Root], string>,
|
|
2468
|
+
>(
|
|
2469
|
+
root: Root,
|
|
2470
|
+
path: Path,
|
|
2471
|
+
...args: I18n.RouteJoinedId<Root, Path> extends I18n.RouteIdDynamic
|
|
2472
|
+
? [params: I18n.RouteParams[I18n.RouteJoinedId<Root, Path>]]
|
|
2473
|
+
: I18n.RouteJoinedId<Root, Path> extends I18n.RouteIdStatic
|
|
2474
|
+
? []
|
|
2475
|
+
: never
|
|
2476
|
+
) => {
|
|
2477
|
+
const [params] = args;
|
|
2478
|
+
return (
|
|
2479
|
+
// prettier-ignore
|
|
2480
|
+
// @ts-expect-error FIXME: types
|
|
2481
|
+
(params ? toSpa(root, path, params, locale) : toSpa(root, path, locale)) as I18n.RouteSpa[Root][Path]
|
|
2482
|
+
);
|
|
2483
|
+
};
|
|
2484
|
+
};
|
|
2485
|
+
|
|
2486
|
+
export default useToSpa;
|
|
2487
|
+
`);
|
|
2488
|
+
|
|
2489
|
+
var n$4 = createAdapter(adapterNextOptions, ({ adapterOptions: e })=>{
|
|
2490
|
+
let { router: t } = e, u = [
|
|
2491
|
+
// TODO: maybe remove these files, they are useful for debugging for now
|
|
2492
|
+
// but probably will be useless
|
|
2493
|
+
{
|
|
2494
|
+
name: "next-redirects",
|
|
2495
|
+
fn: p$3,
|
|
2496
|
+
ext: "js"
|
|
2497
|
+
},
|
|
2498
|
+
{
|
|
2499
|
+
name: "next-rewrites",
|
|
2500
|
+
fn: f$2,
|
|
2501
|
+
ext: "js"
|
|
2502
|
+
},
|
|
2503
|
+
{
|
|
2504
|
+
name: "useRouteId",
|
|
2505
|
+
fn: s$4,
|
|
2506
|
+
ext: "ts",
|
|
2507
|
+
index: !0
|
|
2508
|
+
},
|
|
2509
|
+
{
|
|
2510
|
+
name: "useTo",
|
|
2511
|
+
fn: d$4,
|
|
2512
|
+
ext: "ts",
|
|
2513
|
+
index: !0
|
|
2514
|
+
},
|
|
2515
|
+
{
|
|
2516
|
+
name: "useToSpa",
|
|
2517
|
+
fn: I$2,
|
|
2518
|
+
ext: "ts",
|
|
2519
|
+
index: !0
|
|
2520
|
+
}
|
|
2521
|
+
];
|
|
2522
|
+
return ("app" === t || "migrating" === t) && (u = u.concat([
|
|
2523
|
+
{
|
|
2524
|
+
name: "I18nLayout",
|
|
2525
|
+
fn: o$6,
|
|
2526
|
+
ext: "tsx",
|
|
2527
|
+
index: !0
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
name: "I18nPage",
|
|
2531
|
+
fn: m$3,
|
|
2532
|
+
ext: "tsx",
|
|
2533
|
+
index: !0
|
|
2534
|
+
},
|
|
2535
|
+
{
|
|
2536
|
+
name: "I18nRoot",
|
|
2537
|
+
fn: i$4,
|
|
2538
|
+
ext: "tsx",
|
|
2539
|
+
index: !0
|
|
2540
|
+
}
|
|
2541
|
+
])), ("pages" === t || "migrating" === t) && (u = u.concat([
|
|
2542
|
+
{
|
|
2543
|
+
name: "I18nSetter",
|
|
2544
|
+
fn: x$2,
|
|
2545
|
+
ext: "tsx",
|
|
2546
|
+
index: !0
|
|
2547
|
+
},
|
|
2548
|
+
{
|
|
2549
|
+
name: "I18nApp",
|
|
2550
|
+
fn: n$5,
|
|
2551
|
+
ext: "tsx",
|
|
2552
|
+
index: !0
|
|
2553
|
+
},
|
|
2554
|
+
{
|
|
2555
|
+
name: "I18nHead",
|
|
2556
|
+
fn: r$3,
|
|
2557
|
+
ext: "tsx"
|
|
2558
|
+
},
|
|
2559
|
+
{
|
|
2560
|
+
name: "i18nGet",
|
|
2561
|
+
fn: a$3,
|
|
2562
|
+
ext: "ts",
|
|
2563
|
+
index: !0
|
|
2564
|
+
}
|
|
2565
|
+
])), {
|
|
2566
|
+
dependsOn: [
|
|
2567
|
+
"react"
|
|
2568
|
+
],
|
|
2569
|
+
files: u
|
|
2570
|
+
};
|
|
2571
|
+
});
|
|
2572
|
+
|
|
2573
|
+
const adapterReactOptions = {};
|
|
2574
|
+
|
|
2575
|
+
var n$3 = (({})=>`
|
|
2576
|
+
import React from "react";
|
|
2577
|
+
import { defaultLocale } from "./defaultLocale";
|
|
2578
|
+
import type { I18n } from "./types";
|
|
2579
|
+
|
|
2580
|
+
export type I18nContextValue = {
|
|
2581
|
+
t: I18n.Translate;
|
|
2582
|
+
locale: I18n.Locale;
|
|
2583
|
+
};
|
|
2584
|
+
|
|
2585
|
+
let _I18nContext;
|
|
2586
|
+
|
|
2587
|
+
// For serverComponents (app-dir), the context cannot be used and
|
|
2588
|
+
// this makes that all the imports to here don't break the build.
|
|
2589
|
+
// The use of this context is inside each util, depending pages-dir or app-dir.
|
|
2590
|
+
if (typeof React.createContext === "function") {
|
|
2591
|
+
_I18nContext = React.createContext<I18nContextValue>({
|
|
2592
|
+
t: ((key: string) => key) as I18n.Translate,
|
|
2593
|
+
locale: defaultLocale,
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
/**
|
|
2598
|
+
* @internal
|
|
2599
|
+
*/
|
|
2600
|
+
export const I18nContext = _I18nContext as React.Context<I18nContextValue>;
|
|
2601
|
+
|
|
2602
|
+
// export default I18nContext;
|
|
2603
|
+
`);
|
|
2604
|
+
|
|
2605
|
+
var o$4 = (({})=>`
|
|
2606
|
+
"use client";
|
|
2607
|
+
|
|
2608
|
+
import { useEffect } from "react";
|
|
2609
|
+
import { dom } from "@koine/dom";
|
|
2610
|
+
import { useLocale } from "./useLocale";
|
|
2611
|
+
|
|
2612
|
+
/**
|
|
2613
|
+
* @internal
|
|
2614
|
+
*/
|
|
2615
|
+
export const I18nEffects = () => {
|
|
2616
|
+
const currentLocale = useLocale();
|
|
2617
|
+
|
|
2618
|
+
useEffect(() => {
|
|
2619
|
+
if (currentLocale) {
|
|
2620
|
+
const html = dom("html");
|
|
2621
|
+
if (html) html.lang = currentLocale;
|
|
2622
|
+
}
|
|
2623
|
+
}, [currentLocale]);
|
|
2624
|
+
|
|
2625
|
+
return null;
|
|
2626
|
+
};
|
|
2627
|
+
|
|
2628
|
+
// export default I18nEffects;
|
|
2629
|
+
`);
|
|
2630
|
+
|
|
2631
|
+
var r$2 = (({})=>`
|
|
2632
|
+
"use client";
|
|
2633
|
+
|
|
2634
|
+
import { defaultI18nMetadata } from "./defaultI18nMetadata";
|
|
2635
|
+
import type { I18n } from "./types";
|
|
2636
|
+
|
|
2637
|
+
export type I18nHeadTagsProps = {
|
|
2638
|
+
metadata?: I18n.Metadata;
|
|
2639
|
+
};
|
|
2640
|
+
|
|
2641
|
+
/**
|
|
2642
|
+
* Renders the HTML tags to use in the \`<head>\`
|
|
2643
|
+
*/
|
|
2644
|
+
export const I18nHeadTags = (props: I18nHeadTagsProps) => {
|
|
2645
|
+
const { metadata = defaultI18nMetadata } = props;
|
|
2646
|
+
const { alternates, canonical } = metadata;
|
|
2647
|
+
|
|
2648
|
+
return (
|
|
2649
|
+
<>
|
|
2650
|
+
{canonical && (
|
|
2651
|
+
<link
|
|
2652
|
+
rel="canonical"
|
|
2653
|
+
href={canonical}
|
|
2654
|
+
key="canonical"
|
|
2655
|
+
/>
|
|
2656
|
+
)}
|
|
2657
|
+
{Object.keys(alternates).map((locale) => (
|
|
2658
|
+
<link
|
|
2659
|
+
rel="alternate"
|
|
2660
|
+
hrefLang={locale}
|
|
2661
|
+
href={alternates[locale]}
|
|
2662
|
+
key={"alternate-" + locale}
|
|
2663
|
+
/>
|
|
2664
|
+
))}
|
|
2665
|
+
</>
|
|
2666
|
+
);
|
|
2667
|
+
};
|
|
2668
|
+
|
|
2669
|
+
export default I18nHeadTags;
|
|
2670
|
+
`);
|
|
2671
|
+
|
|
2672
|
+
var m$2 = (({})=>`
|
|
2673
|
+
"use client";
|
|
2674
|
+
|
|
2675
|
+
import { createContext } from "react";
|
|
2676
|
+
import { defaultI18nMetadata } from "./defaultI18nMetadata";
|
|
2677
|
+
import type { I18n } from "./types";
|
|
2678
|
+
|
|
2679
|
+
type I18nMetadataContextValue = readonly [
|
|
2680
|
+
/** metadata */
|
|
2681
|
+
I18n.Metadata,
|
|
2682
|
+
/** setMetadata */
|
|
2683
|
+
React.Dispatch<React.SetStateAction<I18n.Metadata>>,
|
|
2684
|
+
];
|
|
2685
|
+
|
|
2686
|
+
/**
|
|
2687
|
+
* @internal
|
|
2688
|
+
*/
|
|
2689
|
+
export const I18nMetadataContext = createContext<I18nMetadataContextValue>([
|
|
2690
|
+
defaultI18nMetadata,
|
|
2691
|
+
() => (defaultI18nMetadata),
|
|
2692
|
+
]);
|
|
2693
|
+
|
|
2694
|
+
// export default I18nMetadataContext;
|
|
2695
|
+
`);
|
|
2696
|
+
|
|
2697
|
+
var a$1 = (({})=>`
|
|
2698
|
+
"use client";
|
|
2699
|
+
|
|
2700
|
+
import { useMemo, useState } from "react";
|
|
2701
|
+
import type { I18n } from "@/i18n";
|
|
2702
|
+
import { I18nMetadataContext } from "./I18nMetadataContext";
|
|
2703
|
+
|
|
2704
|
+
type I18nMetadataProviderProps = React.PropsWithChildren<{
|
|
2705
|
+
metadata?: I18n.Metadata;
|
|
2706
|
+
}>;
|
|
2707
|
+
|
|
2708
|
+
/**
|
|
2709
|
+
* @internal
|
|
2710
|
+
*/
|
|
2711
|
+
export function I18nMetadataProvider(props: I18nMetadataProviderProps) {
|
|
2712
|
+
const { children } = props;
|
|
2713
|
+
const [metadata, setMetadata] = useState<I18n.Metadata>(
|
|
2714
|
+
props.metadata || ({} as I18n.Metadata),
|
|
2715
|
+
);
|
|
2716
|
+
const value = useMemo(
|
|
2717
|
+
() => [metadata, setMetadata] as const,
|
|
2718
|
+
[metadata],
|
|
2719
|
+
);
|
|
2720
|
+
|
|
2721
|
+
return (
|
|
2722
|
+
<I18nMetadataContext.Provider value={value}>
|
|
2723
|
+
{children}
|
|
2724
|
+
</I18nMetadataContext.Provider>
|
|
2725
|
+
);
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
// export default I18nMetadataProvider;
|
|
2729
|
+
`);
|
|
2730
|
+
|
|
2731
|
+
var x$1 = (({})=>`
|
|
2732
|
+
"use client";
|
|
2733
|
+
|
|
2734
|
+
import { useContext, useEffect } from "react";
|
|
2735
|
+
import { I18nMetadataContext } from "./I18nMetadataContext";
|
|
2736
|
+
import type { I18n } from "./types";
|
|
2737
|
+
|
|
2738
|
+
type I18nMetadataSetterProps = {
|
|
2739
|
+
metadata: I18n.Metadata;
|
|
2740
|
+
};
|
|
2741
|
+
|
|
2742
|
+
/**
|
|
2743
|
+
* NB: Do not use it next.js Pages router
|
|
2744
|
+
*
|
|
2745
|
+
* @internal
|
|
2746
|
+
*/
|
|
2747
|
+
export const I18nMetadataSetter = (props: I18nMetadataSetterProps) => {
|
|
2748
|
+
const { metadata } = props;
|
|
2749
|
+
const [, setMetadata] = useContext(I18nMetadataContext);
|
|
2750
|
+
|
|
2751
|
+
useEffect(() => {
|
|
2752
|
+
setMetadata(metadata);
|
|
2753
|
+
}, [metadata, setMetadata]);
|
|
2754
|
+
|
|
2755
|
+
return null;
|
|
2756
|
+
};
|
|
2757
|
+
|
|
2758
|
+
// export default I18nMetadataSetter;
|
|
2759
|
+
`);
|
|
2760
|
+
|
|
2761
|
+
var f$1 = (({})=>`
|
|
2762
|
+
"use client";
|
|
2763
|
+
|
|
2764
|
+
import { I18nContext } from "./I18nContext";
|
|
2765
|
+
import { defaultLocale } from "./defaultLocale";
|
|
2766
|
+
import { createT } from "./createT";
|
|
2767
|
+
import type { I18n } from "./types";
|
|
2768
|
+
|
|
2769
|
+
export type I18nProviderProps = React.PropsWithChildren<{
|
|
2770
|
+
locale?: I18n.Locale;
|
|
2771
|
+
dictionaries?: I18n.Dictionaries;
|
|
2772
|
+
}>;
|
|
2773
|
+
|
|
2774
|
+
export const I18nProvider = ({
|
|
2775
|
+
locale = defaultLocale,
|
|
2776
|
+
dictionaries = {},
|
|
2777
|
+
children,
|
|
2778
|
+
}: I18nProviderProps) => {
|
|
2779
|
+
const pluralRules = new Intl.PluralRules(locale);
|
|
2780
|
+
const t = createT(dictionaries, pluralRules, locale) as I18n.Translate;
|
|
2781
|
+
|
|
2782
|
+
return (
|
|
2783
|
+
<I18nContext.Provider value={{ locale, t }}>{children}</I18nContext.Provider>
|
|
2784
|
+
);
|
|
2785
|
+
};
|
|
2786
|
+
|
|
2787
|
+
export default I18nProvider;
|
|
2788
|
+
`);
|
|
2789
|
+
|
|
2790
|
+
var i$3 = (({})=>`
|
|
2791
|
+
"use client";
|
|
2792
|
+
|
|
2793
|
+
import { createContext } from "react";
|
|
2794
|
+
import type { I18n } from "./types";
|
|
2795
|
+
|
|
2796
|
+
type I18nRouteContextValue = readonly [
|
|
2797
|
+
/** routeId */
|
|
2798
|
+
I18n.RouteId,
|
|
2799
|
+
/** setRouteId */
|
|
2800
|
+
React.Dispatch<React.SetStateAction<I18n.RouteId>>,
|
|
2801
|
+
];
|
|
2802
|
+
|
|
2803
|
+
export const I18nRouteContext = createContext<I18nRouteContextValue>([
|
|
2804
|
+
"" as I18n.RouteId,
|
|
2805
|
+
() => "",
|
|
2806
|
+
]);
|
|
2807
|
+
|
|
2808
|
+
// export default I18nRouteContext;
|
|
2809
|
+
`);
|
|
2810
|
+
|
|
2811
|
+
var s$3 = (({})=>`
|
|
2812
|
+
"use client";
|
|
2813
|
+
|
|
2814
|
+
import { useMemo, useState } from "react";
|
|
2815
|
+
import type { I18n } from "@/i18n";
|
|
2816
|
+
import { I18nRouteContext } from "./I18nRouteContext";
|
|
2817
|
+
|
|
2818
|
+
type I18nRouteProviderProps = React.PropsWithChildren<{
|
|
2819
|
+
id: I18n.RouteId;
|
|
2820
|
+
}>;
|
|
2821
|
+
|
|
2822
|
+
/**
|
|
2823
|
+
* @internal
|
|
2824
|
+
*/
|
|
2825
|
+
export function I18nRouteProvider(props: I18nRouteProviderProps) {
|
|
2826
|
+
const { children } = props;
|
|
2827
|
+
const [id, setId] = useState<I18n.RouteId>(
|
|
2828
|
+
props.id || ("" as I18n.RouteId),
|
|
2829
|
+
);
|
|
2830
|
+
const value = useMemo(
|
|
2831
|
+
() => [id, setId] as const,
|
|
2832
|
+
[id],
|
|
2833
|
+
);
|
|
2834
|
+
|
|
2835
|
+
return (
|
|
2836
|
+
<I18nRouteContext.Provider value={value}>
|
|
2837
|
+
{children}
|
|
2838
|
+
</I18nRouteContext.Provider>
|
|
2839
|
+
);
|
|
2840
|
+
}
|
|
2841
|
+
|
|
2842
|
+
// export default I18nRouteProvider;
|
|
2843
|
+
`);
|
|
2844
|
+
|
|
2845
|
+
var d$3 = (({})=>`
|
|
2846
|
+
"use client";
|
|
2847
|
+
|
|
2848
|
+
import { useContext, useEffect } from "react";
|
|
2849
|
+
import { I18nRouteContext } from "./I18nRouteContext";
|
|
2850
|
+
import type { I18n } from "./types";
|
|
2851
|
+
|
|
2852
|
+
type I18nRouteSetterProps = {
|
|
2853
|
+
id: I18n.RouteId;
|
|
2854
|
+
};
|
|
2855
|
+
|
|
2856
|
+
/**
|
|
2857
|
+
* NB: Do not use it next.js Pages router
|
|
2858
|
+
*
|
|
2859
|
+
* @internal
|
|
2860
|
+
*/
|
|
2861
|
+
export const I18nRouteSetter = (props: I18nRouteSetterProps) => {
|
|
2862
|
+
const { id } = props;
|
|
2863
|
+
const [, setRouteId] = useContext(I18nRouteContext);
|
|
2864
|
+
|
|
2865
|
+
useEffect(() => {
|
|
2866
|
+
setRouteId(id);
|
|
2867
|
+
}, [id, setRouteId]);
|
|
2868
|
+
|
|
2869
|
+
return null;
|
|
2870
|
+
};
|
|
2871
|
+
|
|
2872
|
+
// export default I18nRouteSetter;
|
|
2873
|
+
`);
|
|
2874
|
+
|
|
2875
|
+
var p$2 = (({})=>`
|
|
2876
|
+
"use client";
|
|
2877
|
+
|
|
2878
|
+
import { useMemo } from "react";
|
|
2879
|
+
import { formatElements } from "./formatElements";
|
|
2880
|
+
import type { I18n } from "./types";
|
|
2881
|
+
import { useT } from "./useT";
|
|
2882
|
+
|
|
2883
|
+
export type TProps = {
|
|
2884
|
+
i18nKey: I18n.TranslationsAllPaths;
|
|
2885
|
+
components?: React.ReactElement[] | Record<string, React.ReactElement>;
|
|
2886
|
+
values?: I18n.TranslationQuery;
|
|
2887
|
+
returnObjects?: boolean;
|
|
2888
|
+
};
|
|
2889
|
+
|
|
2890
|
+
/**
|
|
2891
|
+
* Translate transforming:
|
|
2892
|
+
* <0>This is an <1>example</1><0>
|
|
2893
|
+
* to -> <h1>This is an <b>example</b><h1>
|
|
2894
|
+
*/
|
|
2895
|
+
export const T = ({
|
|
2896
|
+
i18nKey,
|
|
2897
|
+
values,
|
|
2898
|
+
components,
|
|
2899
|
+
returnObjects,
|
|
2900
|
+
}: TProps) => {
|
|
2901
|
+
const [namespace, path] = (i18nKey as string).split(":");
|
|
2902
|
+
const t = useT(namespace as I18n.TranslateNamespace) as I18n.TranslateLoose;
|
|
2903
|
+
const result = useMemo(() => {
|
|
2904
|
+
const text = t(path, values, {
|
|
2905
|
+
returnObjects,
|
|
2906
|
+
});
|
|
2907
|
+
|
|
2908
|
+
if (!text) return text;
|
|
2909
|
+
|
|
2910
|
+
if (!components || components.length === 0)
|
|
2911
|
+
return Array.isArray(text) ? text.map((item) => item) : text;
|
|
2912
|
+
|
|
2913
|
+
if (Array.isArray(text))
|
|
2914
|
+
return text.map((item) => formatElements(item, components));
|
|
2915
|
+
|
|
2916
|
+
return formatElements(text, components);
|
|
2917
|
+
}, [t, path, values, components, returnObjects]) as string;
|
|
2918
|
+
|
|
2919
|
+
return result;
|
|
2920
|
+
};
|
|
2921
|
+
|
|
2922
|
+
export default T;
|
|
2923
|
+
`);
|
|
2924
|
+
|
|
2925
|
+
var I$1 = (({})=>`
|
|
2926
|
+
"use client";
|
|
2927
|
+
|
|
2928
|
+
import { useMemo } from "react";
|
|
2929
|
+
import type { TProps } from "./T";
|
|
2930
|
+
import { formatElements } from "./formatElements";
|
|
2931
|
+
|
|
2932
|
+
export type TransTextProps = Pick<TProps, "components"> & {
|
|
2933
|
+
text: string;
|
|
2934
|
+
};
|
|
2935
|
+
|
|
2936
|
+
export const TransText = ({ text, components }: TransTextProps) => {
|
|
2937
|
+
return useMemo(
|
|
2938
|
+
() =>
|
|
2939
|
+
!components || components.length === 0
|
|
2940
|
+
? text
|
|
2941
|
+
: formatElements(text, components),
|
|
2942
|
+
[text, components],
|
|
2943
|
+
) as string;
|
|
2944
|
+
};
|
|
2945
|
+
|
|
2946
|
+
export default TransText;
|
|
2947
|
+
`);
|
|
2948
|
+
|
|
2949
|
+
var u = (({})=>`
|
|
2950
|
+
import { Fragment, cloneElement } from "react";
|
|
2951
|
+
|
|
2952
|
+
const tagParsingRegex = /<(\\w+) *>(.*?)<\\/\\1 *>|<(\\w+) *\\/>/;
|
|
2953
|
+
|
|
2954
|
+
const nlRe = /(?:\\r\\n|\\r|\\n)/g;
|
|
2955
|
+
|
|
2956
|
+
function getElements(
|
|
2957
|
+
parts: Array<string | undefined>,
|
|
2958
|
+
): Array<string | undefined>[] {
|
|
2959
|
+
if (!parts.length) return [];
|
|
2960
|
+
|
|
2961
|
+
const [paired, children, unpaired, after] = parts.slice(0, 4);
|
|
2962
|
+
|
|
2963
|
+
return [
|
|
2964
|
+
[(paired || unpaired) as string, children || ("" as string), after],
|
|
2965
|
+
].concat(getElements(parts.slice(4, parts.length)));
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
/**
|
|
2969
|
+
* @internal
|
|
2970
|
+
* @see https://github.com/aralroca/next-translate/blob/master/src/formatElements.tsx
|
|
2971
|
+
*/
|
|
2972
|
+
export function formatElements(
|
|
2973
|
+
value: string,
|
|
2974
|
+
elements: React.ReactElement[] | Record<string, React.ReactElement> = [],
|
|
2975
|
+
): string | React.ReactNode[] {
|
|
2976
|
+
const parts = value.replace(nlRe, "").split(tagParsingRegex);
|
|
2977
|
+
|
|
2978
|
+
if (parts.length === 1) return value;
|
|
2979
|
+
|
|
2980
|
+
const tree: React.ReactNode[] = [];
|
|
2981
|
+
|
|
2982
|
+
const before = parts.shift();
|
|
2983
|
+
if (before) tree.push(before);
|
|
2984
|
+
|
|
2985
|
+
getElements(parts).forEach(([key, children, after], realIndex: number) => {
|
|
2986
|
+
const element = (elements as Record<string, React.ReactElement>)[
|
|
2987
|
+
key as string
|
|
2988
|
+
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
2989
|
+
] || <Fragment />;
|
|
2990
|
+
|
|
2991
|
+
tree.push(
|
|
2992
|
+
cloneElement(
|
|
2993
|
+
element,
|
|
2994
|
+
{ key: realIndex },
|
|
2995
|
+
|
|
2996
|
+
// format children for pair tags
|
|
2997
|
+
// unpaired tags might have children if it's a component passed as a variable
|
|
2998
|
+
children ? formatElements(children, elements) : element.props.children,
|
|
2999
|
+
),
|
|
3000
|
+
);
|
|
3001
|
+
|
|
3002
|
+
if (after) tree.push(after);
|
|
3003
|
+
});
|
|
3004
|
+
|
|
3005
|
+
return tree;
|
|
3006
|
+
}
|
|
3007
|
+
|
|
3008
|
+
// export default formatElements;
|
|
3009
|
+
`);
|
|
3010
|
+
|
|
3011
|
+
var T = (({})=>`
|
|
3012
|
+
"use client";
|
|
3013
|
+
|
|
3014
|
+
import { useContext } from "react";
|
|
3015
|
+
import { I18nMetadataContext } from "./I18nMetadataContext";
|
|
3016
|
+
|
|
3017
|
+
export const useI18nSwitch = (
|
|
3018
|
+
absolute?: boolean,
|
|
3019
|
+
includeSearch?: boolean,
|
|
3020
|
+
includeHash?: boolean
|
|
3021
|
+
) => {
|
|
3022
|
+
const { alternates: urls } = useContext(I18nMetadataContext)[0];
|
|
3023
|
+
|
|
3024
|
+
if (!absolute) {
|
|
3025
|
+
try {
|
|
3026
|
+
for (const locale in urls) {
|
|
3027
|
+
const absoluteUrl = urls[locale];
|
|
3028
|
+
if (absoluteUrl) {
|
|
3029
|
+
const url = new URL(absoluteUrl);
|
|
3030
|
+
urls[locale] = url.pathname;
|
|
3031
|
+
if (includeSearch) urls[locale] += url.search;
|
|
3032
|
+
if (includeHash) urls[locale] += url.hash;
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
} catch(e) {
|
|
3036
|
+
// TODO: verify this: we could have empty/invalid languages URLs here?
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
return urls;
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
export default useI18nSwitch;
|
|
3044
|
+
`);
|
|
3045
|
+
|
|
3046
|
+
var c$1 = (({})=>`
|
|
3047
|
+
"use client";
|
|
3048
|
+
|
|
3049
|
+
import { useContext } from "react";
|
|
3050
|
+
import { defaultLocale } from "./defaultLocale";
|
|
3051
|
+
import { I18nContext } from "./I18nContext";
|
|
3052
|
+
|
|
3053
|
+
export const useLocale = () => useContext(I18nContext).locale || defaultLocale;
|
|
3054
|
+
|
|
3055
|
+
export default useLocale;
|
|
3056
|
+
`);
|
|
3057
|
+
|
|
3058
|
+
var R = (({})=>`
|
|
3059
|
+
"use client";
|
|
3060
|
+
|
|
3061
|
+
import { useContext } from "react";
|
|
3062
|
+
import { I18nRouteContext } from "./I18nRouteContext";
|
|
3063
|
+
|
|
3064
|
+
export const useRouteId = () => useContext(I18nRouteContext)[0];
|
|
3065
|
+
|
|
3066
|
+
export default useRouteId;
|
|
3067
|
+
`);
|
|
3068
|
+
|
|
3069
|
+
var l$3 = (({})=>`
|
|
3070
|
+
"use client";
|
|
3071
|
+
|
|
3072
|
+
import { useContext, useMemo } from "react";
|
|
3073
|
+
import { I18nContext } from "./I18nContext";
|
|
3074
|
+
import type { I18n } from "./types";
|
|
3075
|
+
|
|
3076
|
+
export const useT = <T extends I18n.TranslateNamespace>(namespace: T) => {
|
|
3077
|
+
const t = useContext(I18nContext).t;
|
|
3078
|
+
return useMemo(
|
|
3079
|
+
() =>
|
|
3080
|
+
(key: string, ...args) =>
|
|
3081
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3082
|
+
(t as any)(\`\${namespace}:\${key}\`, ...args),
|
|
3083
|
+
[t],
|
|
3084
|
+
) as I18n.TranslateNamespaced<T>;
|
|
3085
|
+
};
|
|
3086
|
+
|
|
3087
|
+
export default useT;
|
|
3088
|
+
|
|
3089
|
+
`);
|
|
3090
|
+
|
|
3091
|
+
var r$1 = createAdapter(adapterReactOptions, ({})=>({
|
|
3092
|
+
dependsOn: [
|
|
3093
|
+
"js"
|
|
3094
|
+
],
|
|
3095
|
+
files: [
|
|
3096
|
+
{
|
|
3097
|
+
name: "formatElements",
|
|
3098
|
+
fn: u,
|
|
3099
|
+
ext: "tsx"
|
|
3100
|
+
},
|
|
3101
|
+
{
|
|
3102
|
+
name: "I18nContext",
|
|
3103
|
+
fn: n$3,
|
|
3104
|
+
ext: "tsx"
|
|
3105
|
+
},
|
|
3106
|
+
{
|
|
3107
|
+
name: "I18nEffects",
|
|
3108
|
+
fn: o$4,
|
|
3109
|
+
ext: "tsx"
|
|
3110
|
+
},
|
|
3111
|
+
{
|
|
3112
|
+
name: "I18nHeadTags",
|
|
3113
|
+
fn: r$2,
|
|
3114
|
+
ext: "tsx",
|
|
3115
|
+
index: !0
|
|
3116
|
+
},
|
|
3117
|
+
{
|
|
3118
|
+
name: "I18nMetadataContext",
|
|
3119
|
+
fn: m$2,
|
|
3120
|
+
ext: "tsx"
|
|
3121
|
+
},
|
|
3122
|
+
{
|
|
3123
|
+
name: "I18nMetadataProvider",
|
|
3124
|
+
fn: a$1,
|
|
3125
|
+
ext: "tsx"
|
|
3126
|
+
},
|
|
3127
|
+
{
|
|
3128
|
+
name: "I18nMetadataSetter",
|
|
3129
|
+
fn: x$1,
|
|
3130
|
+
ext: "tsx"
|
|
3131
|
+
},
|
|
3132
|
+
{
|
|
3133
|
+
name: "I18nProvider",
|
|
3134
|
+
fn: f$1,
|
|
3135
|
+
ext: "tsx",
|
|
3136
|
+
index: !0
|
|
3137
|
+
},
|
|
3138
|
+
{
|
|
3139
|
+
name: "I18nRouteContext",
|
|
3140
|
+
fn: i$3,
|
|
3141
|
+
ext: "tsx"
|
|
3142
|
+
},
|
|
3143
|
+
{
|
|
3144
|
+
name: "I18nRouteProvider",
|
|
3145
|
+
fn: s$3,
|
|
3146
|
+
ext: "tsx"
|
|
3147
|
+
},
|
|
3148
|
+
{
|
|
3149
|
+
name: "I18nRouteSetter",
|
|
3150
|
+
fn: d$3,
|
|
3151
|
+
ext: "tsx"
|
|
3152
|
+
},
|
|
3153
|
+
{
|
|
3154
|
+
name: "T",
|
|
3155
|
+
fn: p$2,
|
|
3156
|
+
ext: "tsx",
|
|
3157
|
+
index: !0
|
|
3158
|
+
},
|
|
3159
|
+
{
|
|
3160
|
+
name: "TransText",
|
|
3161
|
+
fn: I$1,
|
|
3162
|
+
ext: "tsx",
|
|
3163
|
+
index: !0
|
|
3164
|
+
},
|
|
3165
|
+
{
|
|
3166
|
+
name: "useI18nSwitch",
|
|
3167
|
+
fn: T,
|
|
3168
|
+
ext: "ts",
|
|
3169
|
+
index: !0
|
|
3170
|
+
},
|
|
3171
|
+
{
|
|
3172
|
+
name: "useLocale",
|
|
3173
|
+
fn: c$1,
|
|
3174
|
+
ext: "ts",
|
|
3175
|
+
index: !0
|
|
3176
|
+
},
|
|
3177
|
+
{
|
|
3178
|
+
name: "useRouteId",
|
|
3179
|
+
fn: R,
|
|
3180
|
+
ext: "ts",
|
|
3181
|
+
index: !0
|
|
3182
|
+
},
|
|
3183
|
+
{
|
|
3184
|
+
name: "useT",
|
|
3185
|
+
fn: l$3,
|
|
3186
|
+
ext: "ts",
|
|
3187
|
+
index: !0
|
|
3188
|
+
}
|
|
3189
|
+
]
|
|
3190
|
+
}));
|
|
3191
|
+
|
|
3192
|
+
let o$3 = (e)=>{
|
|
3193
|
+
let t = "";
|
|
3194
|
+
return e.filter((e)=>e.index).sort((e, t)=>e.name.localeCompare(t.name)).forEach((e)=>{
|
|
3195
|
+
t += `export * from "./${e.name}";\n`;
|
|
3196
|
+
}), t;
|
|
3197
|
+
}, s$2 = (e)=>{
|
|
3198
|
+
switch(e){
|
|
3199
|
+
case "js":
|
|
3200
|
+
break;
|
|
3201
|
+
case "next":
|
|
3202
|
+
return n$4;
|
|
3203
|
+
case "next-translate":
|
|
3204
|
+
return a$4;
|
|
3205
|
+
case "react":
|
|
3206
|
+
return r$1;
|
|
3207
|
+
}
|
|
3208
|
+
return t$1;
|
|
3209
|
+
}, /**
|
|
3210
|
+
* Recursively builds a list of adapters to use based on the `dependsOn` array
|
|
3211
|
+
* of the choosen adapter
|
|
3212
|
+
*/ p$1 = async (t, { name: a, options: n = {} }, r = [])=>{
|
|
3213
|
+
let o = s$2(a)(t, n || {}), c = utils.isPromise(o) ? await o : o;
|
|
3214
|
+
return r = r.concat([
|
|
3215
|
+
c
|
|
3216
|
+
]), c.dependsOn && await Promise.all(c.dependsOn.map(async (e)=>{
|
|
3217
|
+
r = r.concat(await p$1(t, {
|
|
3218
|
+
name: e
|
|
3219
|
+
}));
|
|
3220
|
+
})), r;
|
|
3221
|
+
}, i$2 = (e, t)=>{
|
|
3222
|
+
let { outputFiles: a } = e.options, // TODO: prettier does probably not make sense unless one wants to keep the
|
|
3223
|
+
// auto-generated files on git, maybe allow this as an option?
|
|
3224
|
+
// // prettier breaks jest, @see https://jestjs.io/docs/ecmascript-modules
|
|
3225
|
+
// // https://github.com/jestjs/jest/issues/14305
|
|
3226
|
+
// if (!process.env["JEST_WORKER_ID"]) {
|
|
3227
|
+
// const { format } = await import("prettier");
|
|
3228
|
+
// out = await format(out, {
|
|
3229
|
+
// parser: "typescript",
|
|
3230
|
+
// });
|
|
3231
|
+
// }
|
|
3232
|
+
n = t.reduce((e, t)=>{
|
|
3233
|
+
// NOTE: we allow adapters to produce the same files as their dependent's
|
|
3234
|
+
// parent adapters (defined with `dependsOn`), here we ensure the parent
|
|
3235
|
+
// adapters files do not override their children same-named ones which
|
|
3236
|
+
// should get the priority
|
|
3237
|
+
let a = e.map((e)=>e.name + e.ext);
|
|
3238
|
+
return [
|
|
3239
|
+
...e,
|
|
3240
|
+
...t.files.filter((e)=>!a.includes(e.name + e.ext))
|
|
3241
|
+
];
|
|
3242
|
+
}, []).map((t)=>{
|
|
3243
|
+
let { fn: n, ...r } = t, o = a?.[r.name] || r.name;
|
|
3244
|
+
return {
|
|
3245
|
+
...r,
|
|
3246
|
+
name: o,
|
|
3247
|
+
content: n({
|
|
3248
|
+
...e,
|
|
3249
|
+
adapterOptions: e.options.adapter.options || {}
|
|
3250
|
+
})
|
|
3251
|
+
};
|
|
3252
|
+
});
|
|
3253
|
+
return(// automatically create an index file if the adapters want it
|
|
3254
|
+
o$3(n) && n.push({
|
|
3255
|
+
name: "index",
|
|
3256
|
+
ext: "ts",
|
|
3257
|
+
content: o$3(n)
|
|
3258
|
+
}), {
|
|
3259
|
+
files: n,
|
|
3260
|
+
// it is enough that just one adapter requires this
|
|
3261
|
+
needsTranslationsFiles: t.some((e)=>e.needsTranslationsFiles)
|
|
3262
|
+
});
|
|
3263
|
+
};
|
|
3264
|
+
let generateCode = async (e)=>i$2(e, await p$1(e, e.options.adapter));
|
|
3265
|
+
|
|
3266
|
+
let tsCompile = (o, i, s, // Set<string>,
|
|
3267
|
+
r)=>{
|
|
3268
|
+
let l = Array.from(s).filter((e)=>e.endsWith(".ts") || e.endsWith(".tsx")).map((t)=>node_path.join(o, i, t)), n = {
|
|
3269
|
+
noEmitOnError: !0,
|
|
3270
|
+
noImplicitAny: !0,
|
|
3271
|
+
declaration: !0,
|
|
3272
|
+
// target: ts.ScriptTarget.ES5,
|
|
3273
|
+
target: t__namespace.ScriptTarget.ESNext,
|
|
3274
|
+
// module: ts.ModuleKind.CommonJS,
|
|
3275
|
+
module: t__namespace.ModuleKind.ESNext,
|
|
3276
|
+
moduleResolution: t__namespace.ModuleResolutionKind.Bundler,
|
|
3277
|
+
resolveJsonModule: !0,
|
|
3278
|
+
allowJs: !1,
|
|
3279
|
+
esModuleInterop: !0,
|
|
3280
|
+
jsx: t__namespace.JsxEmit.ReactJSX,
|
|
3281
|
+
outDir: node_path.join(o, i),
|
|
3282
|
+
skipLibCheck: !0,
|
|
3283
|
+
noEmitHelpers: !0,
|
|
3284
|
+
importHelpers: !0,
|
|
3285
|
+
...r || {}
|
|
3286
|
+
}, // Create a Program with an in-memory emit
|
|
3287
|
+
// const createdFiles: Record<string, string> = {};
|
|
3288
|
+
// const host = ts.createCompilerHost(compilerOptions);
|
|
3289
|
+
// host.writeFile = (fileName: string, contents: string) => createdFiles[fileName] = contents;
|
|
3290
|
+
a = t__namespace.createProgram(l, n), /* , host */ m = a.emit();
|
|
3291
|
+
return(// .concat(emitResultCjs.diagnostics);
|
|
3292
|
+
// const programCjs = ts.createProgram(rootNames, {
|
|
3293
|
+
// ...compilerOptions,
|
|
3294
|
+
// module: ts.ModuleKind.CommonJS,
|
|
3295
|
+
// moduleResolution: ts.ModuleResolutionKind.Classic,
|
|
3296
|
+
// declaration: false,
|
|
3297
|
+
// });
|
|
3298
|
+
// const emitResultCjs = programCjs.emit();
|
|
3299
|
+
t__namespace.getPreEmitDiagnostics(a).concat(m.diagnostics).forEach((e)=>{
|
|
3300
|
+
if (e.file) {
|
|
3301
|
+
let { line: o, character: i } = t__namespace.getLineAndCharacterOfPosition(e.file, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
3302
|
+
e.start), s = t__namespace.flattenDiagnosticMessageText(e.messageText, "\n");
|
|
3303
|
+
console.log(`${e.file.fileName} (${o + 1},${i + 1}): ${s}`);
|
|
3304
|
+
} else console.log(t__namespace.flattenDiagnosticMessageText(e.messageText, "\n"));
|
|
3305
|
+
}), m);
|
|
3306
|
+
};
|
|
3307
|
+
|
|
3308
|
+
let n$2 = async (e, r, s, i)=>Promise.all(s.files.map(async ({ name: s, ext: o, content: n })=>{
|
|
3309
|
+
let l = `${s}.${o}`, d = node_path.join(e, r, l);
|
|
3310
|
+
await node.fsWrite(d, n), i.add(l);
|
|
3311
|
+
})), d$2 = (a, r, s)=>{
|
|
3312
|
+
let i = Array.from(s).filter((e)=>e.endsWith(".ts") || e.endsWith(".tsx"));
|
|
3313
|
+
tsCompile(a, r, i), i.forEach((i)=>{
|
|
3314
|
+
s.add(i.replace(/\.tsx?$/, ".js")), s.add(i.replace(/\.tsx?$/, ".d.ts")), // remove TypeScript files
|
|
3315
|
+
s.delete(i), node_fs.rmSync(node_path.join(a, r, i), {
|
|
3316
|
+
force: !0
|
|
3317
|
+
});
|
|
3318
|
+
});
|
|
3319
|
+
}, m$1 = async (e, r, { translationFiles: s }, i)=>Promise.all(s.map(async ({ data: s, locale: o, path: n })=>{
|
|
3320
|
+
let l = node_path.join("translations", o);
|
|
3321
|
+
await node.fsWrite(node_path.join(e, r, l, n), JSON.stringify(s)), i.add(l);
|
|
3322
|
+
})), f = (e, a, r, s)=>[
|
|
3323
|
+
node_path.join(e, a, ".gitignore"),
|
|
3324
|
+
Array.from(new Set([
|
|
3325
|
+
...r,
|
|
3326
|
+
...s
|
|
3327
|
+
])).sort().map((e)=>`/${e}`).join(`\n`)
|
|
3328
|
+
];
|
|
3329
|
+
/**
|
|
3330
|
+
* @default process.cwd()
|
|
3331
|
+
*/ /**
|
|
3332
|
+
* Relative to the given `cwd`.
|
|
3333
|
+
*
|
|
3334
|
+
* Use a _dot_ named folder in order to be automatically ignored when your
|
|
3335
|
+
* i18n source files live in the same folder as the generated code
|
|
3336
|
+
*/ let writeCode = async (e, t)=>{
|
|
3337
|
+
let { cwd: r = process.cwd(), output: i, skipTsCompile: o, skipGitignore: l, skipTranslations: p } = e, c = await generateCode(t), w = new Set(), y = new Set();
|
|
3338
|
+
await n$2(r, i, c, w), o || d$2(r, i, w), c.needsTranslationsFiles && !p && await m$1(r, i, t.input, y), l || await node.fsWrite(...f(r, i, y, w));
|
|
3339
|
+
};
|
|
3340
|
+
|
|
3341
|
+
const codeDataRoutesOptions = {
|
|
3342
|
+
/**
|
|
3343
|
+
* Set this to true once your routing setup is ready for production.
|
|
3344
|
+
*
|
|
3345
|
+
* @default false
|
|
3346
|
+
*/ permanentRedirects: !1,
|
|
3347
|
+
/**
|
|
3348
|
+
* The name of the locale dynamic segment in the URL usually represented as
|
|
3349
|
+
* `[lang]/my-slugs` but without neither brackets nor slashes, so just `lang`
|
|
3350
|
+
*
|
|
3351
|
+
* @default "lang"
|
|
3352
|
+
*/ localeParamName: "lang",
|
|
3353
|
+
/** @default "~.json" */ translationJsonFileName: "~.json",
|
|
3354
|
+
/**
|
|
3355
|
+
* Generated `route_id()` functions prefix, prepended to the automatically
|
|
3356
|
+
* generated function names.
|
|
3357
|
+
*
|
|
3358
|
+
* @default ""
|
|
3359
|
+
*/ fnsPrefix: "",
|
|
3360
|
+
tokens: {
|
|
3361
|
+
/** @default "^" */ parentReference: "^",
|
|
3362
|
+
/** @default "." */ idDelimiter: ".",
|
|
3363
|
+
/**
|
|
3364
|
+
* @see https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments
|
|
3365
|
+
*/ catchAll: {
|
|
3366
|
+
/** @default "[..." */ start: "[...",
|
|
3367
|
+
/** @default "]" */ end: "]"
|
|
3368
|
+
},
|
|
3369
|
+
/**
|
|
3370
|
+
* @see https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments
|
|
3371
|
+
*/ optionalCatchAll: {
|
|
3372
|
+
/** @default "[[..." */ start: "[[...",
|
|
3373
|
+
/** @default "]]" */ end: "]]"
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
};
|
|
3377
|
+
let r = (t, a)=>{
|
|
3378
|
+
let { idDelimiter: l, parentReference: n, catchAll: r, optionalCatchAll: d } = a.tokens;
|
|
3379
|
+
return {
|
|
3380
|
+
...t,
|
|
3381
|
+
...a,
|
|
3382
|
+
reg: {
|
|
3383
|
+
trailingDelimiter: RegExp(`${utils.escapeRegExp(l)}+$`),
|
|
3384
|
+
indexEnd: RegExp(`${utils.escapeRegExp(l)}index$`),
|
|
3385
|
+
parentReference: RegExp(`^/${utils.escapeRegExp(n)}`),
|
|
3386
|
+
catchAll: RegExp(`${utils.escapeRegExp(r.start)}(.+)${utils.escapeRegExp(r.end)}$`),
|
|
3387
|
+
optionalCatchAll: RegExp(`${utils.escapeRegExp(d.start)}(.+)${utils.escapeRegExp(d.end)}$`)
|
|
3388
|
+
}
|
|
3389
|
+
};
|
|
3390
|
+
}, /**
|
|
3391
|
+
* Normalise user defined route id
|
|
3392
|
+
*
|
|
3393
|
+
* 1) remove ending `.index`
|
|
3394
|
+
*/ d$1 = (e, { reg: t })=>{
|
|
3395
|
+
let a = e.replace(t.indexEnd, ""), l = t.optionalCatchAll.test(e), n = t.catchAll.test(e);
|
|
3396
|
+
return l && (a = a.replace(t.optionalCatchAll, "")), n && (a = a.replace(t.catchAll, "")), {
|
|
3397
|
+
routeId: a = a.replace(t.trailingDelimiter, ""),
|
|
3398
|
+
isCatchAll: n,
|
|
3399
|
+
isOptionalCatchAll: l
|
|
3400
|
+
};
|
|
3401
|
+
}, /**
|
|
3402
|
+
* Normalise user defined route pathname
|
|
3403
|
+
*
|
|
3404
|
+
* - ensures beginning slash
|
|
3405
|
+
* - replaces too many consecutive slashes
|
|
3406
|
+
* - removes the trailing slash
|
|
3407
|
+
* - removes `*` wildcard token
|
|
3408
|
+
* - normalises to `/my/[id]` dynamic params defined in any of these shapes:
|
|
3409
|
+
* - `/my/{{id}}`
|
|
3410
|
+
* - `/my/{{ id }}`
|
|
3411
|
+
* - `/my/[id]`
|
|
3412
|
+
* - `/my/[ id ]`
|
|
3413
|
+
* - `/my/{id}`
|
|
3414
|
+
* - `/my/{ id }`
|
|
3415
|
+
*
|
|
3416
|
+
* TODO: support also `/my/:id` syntax?
|
|
3417
|
+
*/ i$1 = (e, t)=>formatRoutePathname.formatRoutePathname(e.replace(/\*/g, "").replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g, (e, t)=>`[${t.trim()}]`), t), /**
|
|
3418
|
+
* Gathers a dictionary with the params extracted from the given (normalised)
|
|
3419
|
+
* route id
|
|
3420
|
+
*/ s$1 = (e)=>{
|
|
3421
|
+
let t = e.match(/\[.*?\]/g);
|
|
3422
|
+
if (t) return t.map((e)=>e.slice(1, -1).trim()).reduce((e, t)=>(// TODO: maybe determine the more specific type with some kind of special
|
|
3423
|
+
// token used in the route id `[dynamicParam]` portion
|
|
3424
|
+
e[t] = "stringOrNumber", e), {});
|
|
3425
|
+
}, /**
|
|
3426
|
+
* Recursively replace `/^` references with the parent route value
|
|
3427
|
+
*/ p = (e, t, a, l, n)=>{
|
|
3428
|
+
let { tokens: { parentReference: r, idDelimiter: d }, reg: i } = t, s = e.byId[l], o = s.pathnames[a];
|
|
3429
|
+
// beginning slash is always present here as the route value is already
|
|
3430
|
+
// normalised at this point
|
|
3431
|
+
if (o.startsWith(`/${r}`)) {
|
|
3432
|
+
// removes the slash + token
|
|
3433
|
+
o = o.replace(i.parentReference, "");
|
|
3434
|
+
// grab the parent id
|
|
3435
|
+
let r = l.split(d).slice(0, -1).join(d);
|
|
3436
|
+
if (!n || n && n(s, r)) {
|
|
3437
|
+
if (r) o = p(e, t, a, r, n) + o;
|
|
3438
|
+
else throw Error("Used a parent route token reference without a matching parent route");
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3441
|
+
return o;
|
|
3442
|
+
}, /**
|
|
3443
|
+
* Mutate the routes data replacing the parent route tokens
|
|
3444
|
+
* NB: it mutates the data
|
|
3445
|
+
*/ o$2 = (e, t)=>{
|
|
3446
|
+
for(let a in e.byId)for(let l in e.byId[a].pathnames)e.byId[a].pathnames[l] = p(e, t, l, a);
|
|
3447
|
+
}, /**
|
|
3448
|
+
* Mutate the routes data replacing the parent route tokens
|
|
3449
|
+
* NB: it mutates the data
|
|
3450
|
+
*/ c = (e, t)=>{
|
|
3451
|
+
let a = (t, a)=>t.inWildcard && !e.wildcardIds.includes(a);
|
|
3452
|
+
for(let l in e.byId){
|
|
3453
|
+
let { inWildcard: n } = e.byId[l];
|
|
3454
|
+
if (n && e.byId[l].pathnamesSpa) for(let n in e.byId[l].pathnamesSpa)// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
3455
|
+
e.byId[l].pathnamesSpa[n] = p(e, t, n, l, a);
|
|
3456
|
+
else // discard unneeded data
|
|
3457
|
+
delete e.byId[l].pathnamesSpa;
|
|
3458
|
+
}
|
|
3459
|
+
}, /**
|
|
3460
|
+
* Optimize the route map by collapsing pathnames that are equal to the one for
|
|
3461
|
+
* the default locale
|
|
3462
|
+
*
|
|
3463
|
+
* NB: It mutates the data
|
|
3464
|
+
*
|
|
3465
|
+
* ```json
|
|
3466
|
+
* {
|
|
3467
|
+
* // from
|
|
3468
|
+
* "about": {
|
|
3469
|
+
* "en": "/about",
|
|
3470
|
+
* "nl": "/about"
|
|
3471
|
+
* },
|
|
3472
|
+
* "account.user.[id]": {
|
|
3473
|
+
* "en": "/account/user/{{ id }}",
|
|
3474
|
+
* "fi": "/account/user/{{ id }}",
|
|
3475
|
+
* "nl": "/rekening/gebruiker/{{ id }}"
|
|
3476
|
+
* },
|
|
3477
|
+
* // to
|
|
3478
|
+
* "about": "/about",
|
|
3479
|
+
* "account.user.[id]": {
|
|
3480
|
+
* "en": "/account/user/{{ id }}",
|
|
3481
|
+
* "nl": "/rekening/gebruiker/{{ id }}"
|
|
3482
|
+
* }
|
|
3483
|
+
* }
|
|
3484
|
+
* ```
|
|
3485
|
+
*/ m = (e, t)=>{
|
|
3486
|
+
let { defaultLocale: a, locales: n } = t;
|
|
3487
|
+
for(let t in e.byId){
|
|
3488
|
+
let r = e.byId[t].pathnames, d = r[a], i = {};
|
|
3489
|
+
for(let e in r){
|
|
3490
|
+
let t = r[e];
|
|
3491
|
+
t !== d && (i[e] = t);
|
|
3492
|
+
}
|
|
3493
|
+
Object.keys(i).length === n.length - 1 || (// if we have the same number of optimized/non-optimized pathnames we do
|
|
3494
|
+
// not add the data
|
|
3495
|
+
Object.keys(i).length >= 1 ? (// if we have more than one optimized pathnames we do add the default locale one
|
|
3496
|
+
i[a] = d, e.byId[t].pathnamesSlim = utils.objectSortByKeysMatching(i, a)) : // otherwise it means that the pathname is the same for all locales
|
|
3497
|
+
e.byId[t].pathnamesSlim = d);
|
|
3498
|
+
}
|
|
3499
|
+
}, /**
|
|
3500
|
+
* Flag routes that are children of wildcards, a.k.a. child SPA routes
|
|
3501
|
+
*
|
|
3502
|
+
* NB: It mutates the data
|
|
3503
|
+
*/ h$1 = (e)=>{
|
|
3504
|
+
if (e.wildcardIds.length) for(let t in e.byId)e.wildcardIds.some((e)=>t.startsWith(e) && e !== t) && (e.byId[t].inWildcard = !0);
|
|
3505
|
+
}, I = (e, n, r, p)=>{
|
|
3506
|
+
let o = utils.objectFlat(e, r.tokens.idDelimiter);
|
|
3507
|
+
for(let e in o){
|
|
3508
|
+
let t = o[e], // as I18nCompiler.RoutePathname;
|
|
3509
|
+
{ routeId: a, isCatchAll: c, isOptionalCatchAll: m } = d$1(e, r);
|
|
3510
|
+
// if (isCatchAll || isOptionalCatchAll) console.log({ routeId, key });
|
|
3511
|
+
// if is the first pass for this routeId
|
|
3512
|
+
if (!p.byId[a]) {
|
|
3513
|
+
p.byId[a] = p.byId[a] || {};
|
|
3514
|
+
let e = s$1(a);
|
|
3515
|
+
p.byId[a].id = a, e && (p.byId[a].params = e), (c || m) && (p.byId[a].wildcard = !0, p.wildcardIds.push(a));
|
|
3516
|
+
}
|
|
3517
|
+
p.byId[a].pathnames = p.byId[a].pathnames || {}, // prettier-ignore
|
|
3518
|
+
p.byId[a].pathnames[n] = i$1(t, r), // prettier-ignore
|
|
3519
|
+
p.byId[a].pathnames = utils.objectSortByKeysMatching(p.byId[a].pathnames, r.defaultLocale), // just copy them for now, the difference treatment happens when resolving
|
|
3520
|
+
// the parent tokens
|
|
3521
|
+
p.byId[a].pathnamesSpa = {
|
|
3522
|
+
...p.byId[a].pathnames
|
|
3523
|
+
};
|
|
3524
|
+
}
|
|
3525
|
+
// sort by route name
|
|
3526
|
+
p.byId = utils.objectSort(p.byId);
|
|
3527
|
+
};
|
|
3528
|
+
/**
|
|
3529
|
+
* Get routes data
|
|
3530
|
+
*/ let getCodeDataRoutes = (e, t, { translationFiles: a })=>{
|
|
3531
|
+
let l = {
|
|
3532
|
+
byId: {},
|
|
3533
|
+
wildcardIds: []
|
|
3534
|
+
}, n = r(e, t);
|
|
3535
|
+
for(let e = 0; e < a.length; e++){
|
|
3536
|
+
let { path: r, locale: d, data: i } = a[e];
|
|
3537
|
+
r === t.translationJsonFileName && I(i, d, n, l);
|
|
3538
|
+
}
|
|
3539
|
+
return(// the order in which these mutations run matters!
|
|
3540
|
+
h$1(l), c(l, n), o$2(l, n), m(l, n), l);
|
|
3541
|
+
}; // /**
|
|
3542
|
+
// * Route id to TypeScript valid type/interface name
|
|
3543
|
+
// *
|
|
3544
|
+
// * @deprecated
|
|
3545
|
+
// */
|
|
3546
|
+
// const routeIdToTypeName = (routeId: string) =>
|
|
3547
|
+
// capitalize(changeCaseCamel(routeId));
|
|
3548
|
+
|
|
3549
|
+
const codeDataTranslationsOptions = {
|
|
3550
|
+
/**
|
|
3551
|
+
* A list of globs to run against source files, those that are matched will be
|
|
3552
|
+
* ignored
|
|
3553
|
+
*
|
|
3554
|
+
* @see https://www.npmjs.com/package/minimatch
|
|
3555
|
+
*/ ignorePaths: [],
|
|
3556
|
+
/**
|
|
3557
|
+
* Given a translation value as `"myKey": ["two", "words"]`:
|
|
3558
|
+
* - when `true`: it outputs `t_myKey_0` and `t_myKey_1` functions
|
|
3559
|
+
* - when `false`: if `fnsAsDataCodes` is `true` it outputs `t_myKey` otherwise
|
|
3560
|
+
* it outputs nothing (TODO: maybe we could log this info in this case)
|
|
3561
|
+
*
|
|
3562
|
+
* NB: It is quite unlikely that you want to set this to `true`.
|
|
3563
|
+
*
|
|
3564
|
+
* @default false
|
|
3565
|
+
*/ createArrayIndexBasedFns: !1,
|
|
3566
|
+
// TODO: add pluralisation config
|
|
3567
|
+
/**
|
|
3568
|
+
* It creates `t_` functions that returns objects and arrays to use as
|
|
3569
|
+
* data source.
|
|
3570
|
+
*
|
|
3571
|
+
* NB: this greatly increased the generated code, tree shaking will still
|
|
3572
|
+
* apply though.
|
|
3573
|
+
*
|
|
3574
|
+
* @default true
|
|
3575
|
+
*/ fnsAsDataCodes: !0,
|
|
3576
|
+
/**
|
|
3577
|
+
* Generated `namespace_tKey()` functions prefix, prepended to the automatically
|
|
3578
|
+
* generated function names.
|
|
3579
|
+
*
|
|
3580
|
+
* @default ""
|
|
3581
|
+
*/ fnsPrefix: "",
|
|
3582
|
+
tokens: {
|
|
3583
|
+
/** @default ":" */ namespaceDelimiter: ":",
|
|
3584
|
+
dynamicDelimiters: {
|
|
3585
|
+
/** @default "{{" */ start: "{{",
|
|
3586
|
+
/** @default "}}" */ end: "}}"
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
};
|
|
3590
|
+
let g = RegExp(node_path.sep, "g"), /**
|
|
3591
|
+
* Normalise translation key
|
|
3592
|
+
*/ v = (e)=>{
|
|
3593
|
+
let t = e.// replace tilde with dollar
|
|
3594
|
+
replace(/~/g, "$").// replace dash with underscore
|
|
3595
|
+
replace(/-/g, "_").replace(g, "_").// collapse consecutive underscores
|
|
3596
|
+
replace(/_+/g, "_").// ensure valid js identifier, allow only alphanumeric characters and few symbols
|
|
3597
|
+
replace(/[^a-zA-Z0-9_$]/gi, "");
|
|
3598
|
+
// ensure the key does not start with a number (invalid js)
|
|
3599
|
+
return /^[0-9]/.test(t) ? "$" + t : t;
|
|
3600
|
+
}, h = (e, t)=>{
|
|
3601
|
+
if (utils.isString(t)) {
|
|
3602
|
+
let { start: r, end: a } = e.tokens.dynamicDelimiters, l = RegExp(`${r}(.*?)${a}`, "gm"), s = t.match(l);
|
|
3603
|
+
if (s) return s.map((e)=>e.replace(r, "").replace(a, "").trim()).reduce((e, t)=>(// TODO: maybe determine the more specific type with some kind of special
|
|
3604
|
+
// token used in the route id `[dynamicParam]` portion
|
|
3605
|
+
e[t] = "stringOrNumber", e), {});
|
|
3606
|
+
}
|
|
3607
|
+
}, /**
|
|
3608
|
+
* This was an experiment to extract params to interpolate from non-flat
|
|
3609
|
+
* translations values, but that does not seem really needed as one
|
|
3610
|
+
* can always use `tInterpolateParams` directly on whatever string
|
|
3611
|
+
*
|
|
3612
|
+
* @deprecated
|
|
3613
|
+
*/ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3614
|
+
y = (e, t, r = {})=>{
|
|
3615
|
+
if (utils.isPrimitive(t)) {
|
|
3616
|
+
let a = h(e, t);
|
|
3617
|
+
return a && (r = {
|
|
3618
|
+
...r,
|
|
3619
|
+
...a
|
|
3620
|
+
}), r;
|
|
3621
|
+
}
|
|
3622
|
+
if (utils.isArray(t)) for(let a = 0; a < t.length; a++){
|
|
3623
|
+
let l = h(e, t[a]);
|
|
3624
|
+
l && (r = {
|
|
3625
|
+
...r,
|
|
3626
|
+
...l
|
|
3627
|
+
});
|
|
3628
|
+
}
|
|
3629
|
+
else for(let a in t){
|
|
3630
|
+
let l = y(e, t[a], r);
|
|
3631
|
+
l && (r = {
|
|
3632
|
+
...r,
|
|
3633
|
+
...l
|
|
3634
|
+
});
|
|
3635
|
+
}
|
|
3636
|
+
return {};
|
|
3637
|
+
}, // const addDataTranslationEntryForObjectValue = (
|
|
3638
|
+
// options: CodeDataTranslationsOptions,
|
|
3639
|
+
// id: string,
|
|
3640
|
+
// locale: I18nCompiler.Locale,
|
|
3641
|
+
// value: Exclude<Extract<I18nCompiler.DataTranslationValue, object>, string[]>,
|
|
3642
|
+
// dataTranslations: I18nCompiler.DataTranslations,
|
|
3643
|
+
// ) => {
|
|
3644
|
+
// // if (hasOnlyPluralKeys(value)) {
|
|
3645
|
+
// // return `'${key}': string;`;
|
|
3646
|
+
// // }
|
|
3647
|
+
// // if (!isArray(value) && isObject(value)) {
|
|
3648
|
+
// // if (hasOnlyPluralKeys(value)) {
|
|
3649
|
+
// // return `'${key}': string;`;
|
|
3650
|
+
// // }
|
|
3651
|
+
// // if (hasPlurals(value)) {
|
|
3652
|
+
// // return `'${key}': string | ${buildTypeForValue(pickNonPluralValue(value))}`;
|
|
3653
|
+
// // }
|
|
3654
|
+
// // }
|
|
3655
|
+
// // return `'${key}': ${buildTypeForValue(value)}`;
|
|
3656
|
+
// };
|
|
3657
|
+
/**
|
|
3658
|
+
* At this point the data translations have been calculated, this happens in a
|
|
3659
|
+
* second pass as we need to know all the translations keys to look for plural
|
|
3660
|
+
* variations.
|
|
3661
|
+
*
|
|
3662
|
+
* NB: we mutate the `dataTranslations`
|
|
3663
|
+
*/ _ = (e, t)=>(Object.keys(t).filter(isPluralKey).forEach((r)=>{
|
|
3664
|
+
let a = removePluralSuffix(r), l = getPluralSuffix(r);
|
|
3665
|
+
// we only need to rearrange plurals defined as `x_one`, `x_other`, if plurals
|
|
3666
|
+
// are instead defined as objects `{ one: "", other: "" }` we just keep that
|
|
3667
|
+
// object structure for `values`
|
|
3668
|
+
if (// we need to create it if we only have `x_one` `x_other` but not `x`
|
|
3669
|
+
t[a] = t[a] || {}, t[r]) {
|
|
3670
|
+
let s = t[a].values || {};
|
|
3671
|
+
utils.forin(t[r].values, (r, i)=>{
|
|
3672
|
+
// we need to ensure the value is an object for pluralisation, so if
|
|
3673
|
+
// we encounter this structure:
|
|
3674
|
+
// { "plural": "Plural", "plural_one": "One", "plural_other": "Some" }
|
|
3675
|
+
// we just remove the first `plural` value as that key is instead used
|
|
3676
|
+
// to grab the right pluralised version from the object value we build
|
|
3677
|
+
// from the other plural-suffixed keys. TODO: maybe we could warn the
|
|
3678
|
+
// developer of improper usage of `plural` translation key, which is
|
|
3679
|
+
// simply useless
|
|
3680
|
+
// prettier-ignore
|
|
3681
|
+
s[r] = utils.isObject(s[r]) ? s[r] : {}, // prettier-ignore
|
|
3682
|
+
s[r][l] = i;
|
|
3683
|
+
let n = y(e, i);
|
|
3684
|
+
n && (t[a].params = {
|
|
3685
|
+
...t[a].params || {},
|
|
3686
|
+
...n
|
|
3687
|
+
});
|
|
3688
|
+
}), Object.keys(s).length && (t[a].values = s, t[a].plural = !0), // TODO: probaly here we should remove the non-plural keys from `values`
|
|
3689
|
+
// as they are anyway accessible from "deeper" functions e.g.
|
|
3690
|
+
// `withPluralAndOtherKeys({ count: 3 }) => "One" | "Many"`
|
|
3691
|
+
// `withPluralAndOtherKeys_nonPluralKey()` => "Yes"
|
|
3692
|
+
// delete ids that we re-arranged in the plural-ready object value
|
|
3693
|
+
delete t[r];
|
|
3694
|
+
}
|
|
3695
|
+
}), t), /**
|
|
3696
|
+
* Add entry to translations data
|
|
3697
|
+
*/ x = (e, t, r, a, l)=>{
|
|
3698
|
+
if (utils.isPrimitive(a)) {
|
|
3699
|
+
l[t] = l[t] || {}, l[t].values = l[t].values || {}, l[t].values[r] = a, l[t].typeValue = "Primitive";
|
|
3700
|
+
let s = h(e, a);
|
|
3701
|
+
s && (l[t].params = s);
|
|
3702
|
+
} else {
|
|
3703
|
+
if (e.fnsAsDataCodes) {
|
|
3704
|
+
let e = utils.isArray(a) ? "Array" : "Object";
|
|
3705
|
+
l[t] = l[t] || {}, l[t].values = l[t].values || {}, l[t].values[r] = a, l[t].typeValue = e;
|
|
3706
|
+
}
|
|
3707
|
+
// @see comment on `extractTranslationParamsFromValue`
|
|
3708
|
+
// const params = extractTranslationParamsFromValue(options, value);
|
|
3709
|
+
// if (params) dataTranslations[id].params = params;
|
|
3710
|
+
if (utils.isArray(a)) {
|
|
3711
|
+
if (e.createArrayIndexBasedFns) for(let s = 0; s < a.length; s++)x(e, t + "_" + s, r, a[s], l);
|
|
3712
|
+
} else for(let s in a)x(e, t + "_" + v(s), r, a[s], l);
|
|
3713
|
+
}
|
|
3714
|
+
return l;
|
|
3715
|
+
}, /**
|
|
3716
|
+
* Get translation data recursively starting from a specific file
|
|
3717
|
+
*/ D = (l, s, i)=>{
|
|
3718
|
+
let { locale: n, path: o } = s, p = node_path.join(node_path.dirname(o), node_path.basename(o, node_path.extname(o)));
|
|
3719
|
+
for(let e in s.data){
|
|
3720
|
+
let t = s.data[e];
|
|
3721
|
+
x(l, v(p + (e ? "_" + e : "")), n, t, i);
|
|
3722
|
+
}
|
|
3723
|
+
return i;
|
|
3724
|
+
};
|
|
3725
|
+
/**
|
|
3726
|
+
* Get translations data
|
|
3727
|
+
*/ let getCodeDataTranslations = (e, t, { translationFiles: r })=>{
|
|
3728
|
+
let { ignorePaths: a } = t, l = {};
|
|
3729
|
+
for(let e = 0; e < r.length; e++)(!a || a && a.every((t)=>!minimatch.minimatch(r[e].path, t))) && D(t, r[e], l);
|
|
3730
|
+
// console.log("generateTypes: outputDir", outputDir, "outputPath", outputPath);
|
|
3731
|
+
return(// sort
|
|
3732
|
+
utils.objectSort(l = _(t, l)));
|
|
3733
|
+
};
|
|
3734
|
+
|
|
3735
|
+
let l$2 = {
|
|
3736
|
+
adapter: {
|
|
3737
|
+
name: "js",
|
|
3738
|
+
options: adapterJsOptions
|
|
3739
|
+
},
|
|
3740
|
+
outputFiles: {},
|
|
3741
|
+
routes: codeDataRoutesOptions,
|
|
3742
|
+
translations: codeDataTranslationsOptions
|
|
3743
|
+
};
|
|
3744
|
+
// TODO: make this works with generics based on chosen adapter?
|
|
3745
|
+
// defaultLocale: string;
|
|
3746
|
+
// index: string;
|
|
3747
|
+
// isLocale: string;
|
|
3748
|
+
// locales: string;
|
|
3749
|
+
// routes: string;
|
|
3750
|
+
// routesSlim: string;
|
|
3751
|
+
// to: string;
|
|
3752
|
+
// toFns: string;
|
|
3753
|
+
// toFormat: string;
|
|
3754
|
+
// types: string;
|
|
3755
|
+
let getCodeData = (o, a, r)=>{
|
|
3756
|
+
let n = utils.objectMergeWithDefaults(l$2, a);
|
|
3757
|
+
return n.translations.ignorePaths.push(n.routes.translationJsonFileName), // order locales
|
|
3758
|
+
r = {
|
|
3759
|
+
...r,
|
|
3760
|
+
localesFolders: r.localesFolders.sort((t, a)=>o.defaultLocale ? -1 : t.localeCompare(a))
|
|
3761
|
+
}, {
|
|
3762
|
+
config: o,
|
|
3763
|
+
// TODO: types, remove this assertion
|
|
3764
|
+
options: n,
|
|
3765
|
+
input: r,
|
|
3766
|
+
routes: getCodeDataRoutes(o, n.routes, r),
|
|
3767
|
+
translations: getCodeDataTranslations(o, n.translations, r)
|
|
3768
|
+
};
|
|
3769
|
+
};
|
|
3770
|
+
|
|
3771
|
+
/**
|
|
3772
|
+
* Used to generate SEO optimized alternate URLs
|
|
3773
|
+
*
|
|
3774
|
+
* NB: It will be normalised and trailing slash stripped out in order to ease
|
|
3775
|
+
* and make consistent a simple concatenation with relative URLs.
|
|
3776
|
+
*/ /**
|
|
3777
|
+
* Whether we have only a single locale.
|
|
3778
|
+
*
|
|
3779
|
+
* @computed
|
|
3780
|
+
*/ const configDefaults = {
|
|
3781
|
+
baseUrl: "https://example.com",
|
|
3782
|
+
locales: [
|
|
3783
|
+
"en"
|
|
3784
|
+
],
|
|
3785
|
+
defaultLocale: "en",
|
|
3786
|
+
hideDefaultLocaleInUrl: !0,
|
|
3787
|
+
trailingSlash: !1,
|
|
3788
|
+
single: !0
|
|
3789
|
+
};
|
|
3790
|
+
/**
|
|
3791
|
+
* Get basic i18n compiler config with defaults and automatic inference from
|
|
3792
|
+
* input data
|
|
3793
|
+
*/ let getConfig = (a, o)=>{
|
|
3794
|
+
o && (o.baseUrl = utils.normaliseUrl(o.baseUrl), // dynamically define locales
|
|
3795
|
+
o.locales = o.locales || a.localesFolders, // ensure defaultLocale
|
|
3796
|
+
o.defaultLocale = o.defaultLocale || o.locales?.[0], // ensure boolean value
|
|
3797
|
+
o.hideDefaultLocaleInUrl = !!o.hideDefaultLocaleInUrl);
|
|
3798
|
+
let t = utils.objectMergeWithDefaults(configDefaults, o);
|
|
3799
|
+
return(// ensure sorted locales
|
|
3800
|
+
t.locales = t.locales.sort((l, e)=>t.defaultLocale ? -1 : l.localeCompare(e)), // compute single
|
|
3801
|
+
t.single = 1 === t.locales.length, t);
|
|
3802
|
+
};
|
|
3803
|
+
|
|
3804
|
+
/**
|
|
3805
|
+
* @default process.cwd()
|
|
3806
|
+
*/ /**
|
|
3807
|
+
* @default undefined
|
|
3808
|
+
*/ let n$1 = (e, r)=>{
|
|
3809
|
+
let { cwd: n = process.cwd(), output: i, pretty: o } = e;
|
|
3810
|
+
return [
|
|
3811
|
+
node_path.join(n, i),
|
|
3812
|
+
o ? JSON.stringify(r, null, 2) : JSON.stringify(r)
|
|
3813
|
+
];
|
|
3814
|
+
};
|
|
3815
|
+
let writeInput = async (t, r)=>{
|
|
3816
|
+
await node.fsWrite(...n$1(t, r));
|
|
3817
|
+
};
|
|
3818
|
+
|
|
3819
|
+
let l$1 = (e)=>{
|
|
3820
|
+
let { cwd: t, ignore: a } = e;
|
|
3821
|
+
return glob.glob.sync("*", {
|
|
3822
|
+
cwd: t,
|
|
3823
|
+
withFileTypes: !0,
|
|
3824
|
+
ignore: [
|
|
3825
|
+
...a,
|
|
3826
|
+
"node_modules/**"
|
|
3827
|
+
]
|
|
3828
|
+
}).// onlyDirectories: true,
|
|
3829
|
+
// @see defaults https://www.npmjs.com/package/glob#dots
|
|
3830
|
+
// dot: false,
|
|
3831
|
+
filter((e)=>e.isDirectory()).map((e)=>e.relative()).sort((e, t)=>e.localeCompare(t));
|
|
3832
|
+
};
|
|
3833
|
+
let getInputDataLocal = async (e)=>{
|
|
3834
|
+
let { cwd: r = process.cwd(), ignore: s = [], source: p } = e, i = node_path.join(r, p), c = l$1({
|
|
3835
|
+
cwd: i,
|
|
3836
|
+
ignore: s
|
|
3837
|
+
}), n = [];
|
|
3838
|
+
return await Promise.all(c.map(async (r)=>{
|
|
3839
|
+
let l = await glob.glob("**/*.json", {
|
|
3840
|
+
cwd: node_path.join(i, r),
|
|
3841
|
+
ignore: e.ignore
|
|
3842
|
+
});
|
|
3843
|
+
await Promise.all(l.map(async (e)=>{
|
|
3844
|
+
let o = node_path.join(i, r, e), l = await promises.readFile(o, "utf8");
|
|
3845
|
+
l && n.push({
|
|
3846
|
+
path: e,
|
|
3847
|
+
data: JSON.parse(l),
|
|
3848
|
+
locale: r
|
|
3849
|
+
});
|
|
3850
|
+
}));
|
|
3851
|
+
})), {
|
|
3852
|
+
localesFolders: c,
|
|
3853
|
+
translationFiles: n
|
|
3854
|
+
};
|
|
3855
|
+
};
|
|
3856
|
+
|
|
3857
|
+
/**
|
|
3858
|
+
* Our github action `knitkode/koine/actions/i18n` creates a JSON file we can
|
|
3859
|
+
* read here, github serves it as text
|
|
3860
|
+
*/ let getInputDataRemote = async (r)=>new Promise((l, o)=>{
|
|
3861
|
+
let { ignore: a = [], source: s } = r, n = s.startsWith(// import requestSync from "sync-request-curl";
|
|
3862
|
+
"https://raw.githubusercontent.com"), i = "", c = node_https.request(s, n ? {} : {
|
|
3863
|
+
headers: {
|
|
3864
|
+
Accept: "application/json"
|
|
3865
|
+
}
|
|
3866
|
+
}, (e)=>{
|
|
3867
|
+
e.setEncoding("utf8"), e.on("data", (e)=>{
|
|
3868
|
+
i += e;
|
|
3869
|
+
}), e.on("end", ()=>{
|
|
3870
|
+
try {
|
|
3871
|
+
let e = n ? JSON.parse(i) : i;
|
|
3872
|
+
l({
|
|
3873
|
+
...e,
|
|
3874
|
+
localesFolders: a.length ? e.localesFolders.filter((e)=>a.every((r)=>!minimatch.minimatch(e, r))) : e.localesFolders,
|
|
3875
|
+
translationFiles: a.length ? e.translationFiles.filter((e)=>a.every((r)=>!minimatch.minimatch(e.path, r))) : e.translationFiles
|
|
3876
|
+
});
|
|
3877
|
+
} catch (e) {
|
|
3878
|
+
throw Error(`Failed to parse JSON from ${s}`);
|
|
3879
|
+
}
|
|
3880
|
+
});
|
|
3881
|
+
});
|
|
3882
|
+
c.on("error", (e)=>{
|
|
3883
|
+
console.error(e), o("");
|
|
3884
|
+
}), c.end();
|
|
3885
|
+
});
|
|
3886
|
+
|
|
3887
|
+
let getInputData = async (e)=>{
|
|
3888
|
+
let { source: o } = e;
|
|
3889
|
+
return utils$1.isAbsoluteUrl(o) ? await getInputDataRemote(e) : await getInputDataLocal(e);
|
|
3890
|
+
};
|
|
3891
|
+
|
|
3892
|
+
let o$1 = (e, t = {})=>{
|
|
3893
|
+
let r = "";
|
|
3894
|
+
if (e && "string" == typeof e) r += " " + e.trim();
|
|
3895
|
+
else if (Array.isArray(e)) for(let l = 0; l < e.length; l++)r += o$1(e[l], t);
|
|
3896
|
+
else if ("object" == typeof e) for(let l in e)r += o$1(e[l], t);
|
|
3897
|
+
return r;
|
|
3898
|
+
}, s = (e, t)=>{
|
|
3899
|
+
let { locale: r, path: l } = t, s = `${e}/${r}/${l}`, a = o$1(t.data), i = a.split(" ").filter(Boolean).length;
|
|
3900
|
+
return {
|
|
3901
|
+
characters: a.split(" ").filter(Boolean).join("").length,
|
|
3902
|
+
locale: r,
|
|
3903
|
+
path: l,
|
|
3904
|
+
url: s,
|
|
3905
|
+
words: i
|
|
3906
|
+
};
|
|
3907
|
+
};
|
|
3908
|
+
const summaryDataOptions = {};
|
|
3909
|
+
/**
|
|
3910
|
+
* Usually this is an absolute URL where to view the translation file
|
|
3911
|
+
*/ let getSummaryData = (o, a, { translationFiles: i })=>{
|
|
3912
|
+
let { defaultLocale: f } = o, n = {};
|
|
3913
|
+
for(let e = 0; e < i.length; e++){
|
|
3914
|
+
let t = i[e], { locale: r } = t, l = s(a.sourceUrl, t);
|
|
3915
|
+
n[r] = n[r] || {}, n[r].files = n[r].files || [], n[r].files.push(l);
|
|
3916
|
+
}
|
|
3917
|
+
return utils.forin(// sort by default locale
|
|
3918
|
+
n = utils.objectSortByKeysMatching(n, f), (t, l)=>{
|
|
3919
|
+
n[t].characters = utils.arraySum(l.files.map((e)=>e.characters)), // sort files by path
|
|
3920
|
+
n[t].files = n[t].files.sort((e, t)=>e.path.localeCompare(t.path)), n[t].words = utils.arraySum(l.files.map((e)=>e.words)), // sort object keys
|
|
3921
|
+
n[t] = utils.objectSort(n[t]);
|
|
3922
|
+
}), n;
|
|
3923
|
+
};
|
|
3924
|
+
|
|
3925
|
+
let l = (e)=>{
|
|
3926
|
+
let h = {};
|
|
3927
|
+
return utils.forin(e, (t, e)=>{
|
|
3928
|
+
let { files: r } = e;
|
|
3929
|
+
for(let e = 0; e < r.length; e++){
|
|
3930
|
+
let l = r[e], { path: d } = l;
|
|
3931
|
+
h[d] = h[d] || {}, h[d][t] = l;
|
|
3932
|
+
}
|
|
3933
|
+
}), h = utils.objectSort(h);
|
|
3934
|
+
}, d = (e)=>{
|
|
3935
|
+
let r = l(e), h = "", d = "", a = [], o = 'style="border-right:1px solid grey"';
|
|
3936
|
+
return utils.forin(r, (e, r)=>{
|
|
3937
|
+
d += `<tr><td ${o}>${e}</td>`, utils.forin(r, (t, e)=>{
|
|
3938
|
+
let { characters: r, words: h, url: l } = e;
|
|
3939
|
+
a.includes(t) || a.push(t), d += `<td><a href="${l}">${t}</a></td><td>${h}</td><td ${o}>${r}</td>`;
|
|
3940
|
+
}), d += "</tr>";
|
|
3941
|
+
}), h += `<table><thead><tr><th ${o}>file path</th>` + a.map(()=>`<th>lang</th><th>words</th><th ${o}>chars</th>`).join("") + `</tr></thead><tbody>${d}</tbody></table>\n`;
|
|
3942
|
+
}, a = (e, r)=>{
|
|
3943
|
+
let h = "", l = "";
|
|
3944
|
+
return utils.forin(e, (t, e)=>{
|
|
3945
|
+
let { files: h, characters: d, words: a } = e, o = `${r.sourceUrl}/${t}`;
|
|
3946
|
+
l += `<tr><th><a href="${o}">${t}</a></th><td>${h.length}</td><td>${a}</td><td>${d}</td></tr>`;
|
|
3947
|
+
}), h += `<table><thead><tr><th>locale</th><th>files</th><th>words</th><th>chars</th></tr></thead><tbody>${l}</tbody></table>\n`;
|
|
3948
|
+
}, o = (t, e)=>"# Summary\n" + ("\n### By locale\n\n" + a(t, e) + "\n### By file path\n\n") + d(t);
|
|
3949
|
+
let generateSummary = (t, r)=>o(t, utils.objectMergeWithDefaults(summaryDataOptions, r));
|
|
3950
|
+
|
|
3951
|
+
/**
|
|
3952
|
+
* @default process.cwd()
|
|
3953
|
+
*/ /**
|
|
3954
|
+
* Relative to the given `cwd`.
|
|
3955
|
+
*/ /**
|
|
3956
|
+
* Relative to the given `cwd`.
|
|
3957
|
+
*/ /**
|
|
3958
|
+
* @default undefined
|
|
3959
|
+
*/ let i = (t, e, o, i)=>[
|
|
3960
|
+
node_path.join(o, i),
|
|
3961
|
+
t.pretty ? JSON.stringify(e, null, 2) : JSON.stringify(e)
|
|
3962
|
+
], n = (t, e, i, n)=>[
|
|
3963
|
+
node_path.join(i, n),
|
|
3964
|
+
generateSummary(e, t)
|
|
3965
|
+
];
|
|
3966
|
+
let writeSummary = async (r, e)=>{
|
|
3967
|
+
let { cwd: o = process.cwd(), outputJson: m, outputMarkdown: a, ...p } = r;
|
|
3968
|
+
return m && await node.fsWrite(...i(r, e, o, m)), a && await node.fsWrite(...n(p, e, o, a)), e;
|
|
3969
|
+
};
|
|
3970
|
+
|
|
3971
|
+
/**
|
|
3972
|
+
* i18nCompiler async api
|
|
3973
|
+
*
|
|
3974
|
+
* @public
|
|
3975
|
+
*/ let i18nCompiler = async (a)=>{
|
|
3976
|
+
let { input: u, code: w, summary: s, ...n } = a, f = [], l = await getInputData(u), c = getConfig(l, n), // it would be easy to make this optional but it's nice to be able to always
|
|
3977
|
+
// predictably return data
|
|
3978
|
+
h = getCodeData(c, w, l);
|
|
3979
|
+
return u?.write && f.push(writeInput(u.write, l)), w?.write && f.push(writeCode({
|
|
3980
|
+
...w,
|
|
3981
|
+
...w.write
|
|
3982
|
+
}, h)), s?.write && f.push(writeSummary({
|
|
3983
|
+
...s,
|
|
3984
|
+
...s.write
|
|
3985
|
+
}, getSummaryData(c, s, l))), await Promise.all(f), {
|
|
3986
|
+
config: c,
|
|
3987
|
+
input: l,
|
|
3988
|
+
code: h
|
|
3989
|
+
};
|
|
3990
|
+
}; // /**
|
|
3991
|
+
// * i18nCompiler sync api
|
|
3992
|
+
// *
|
|
3993
|
+
// * @public
|
|
3994
|
+
// */
|
|
3995
|
+
// export let i18nCompilerSync = (options: I18nCompilerOptions) => {
|
|
3996
|
+
// const {
|
|
3997
|
+
// input: optsInput,
|
|
3998
|
+
// code: optsCode,
|
|
3999
|
+
// summary: optsSummary,
|
|
4000
|
+
// ...configOptions
|
|
4001
|
+
// } = options;
|
|
4002
|
+
// const input = getInputDataSync(optsInput);
|
|
4003
|
+
// const config = getConfig(input, configOptions);
|
|
4004
|
+
// // it would be easy to make this optional but it's nice to be able to always
|
|
4005
|
+
// // predictably return data
|
|
4006
|
+
// const code = getCodeData(config, optsCode, input);
|
|
4007
|
+
// if (optsInput?.write) {
|
|
4008
|
+
// writeInputSync(optsInput.write, input);
|
|
4009
|
+
// }
|
|
4010
|
+
// if (optsCode?.write) {
|
|
4011
|
+
// writeCodeSync({ ...optsCode, ...optsCode.write }, code);
|
|
4012
|
+
// }
|
|
4013
|
+
// if (optsSummary?.write) {
|
|
4014
|
+
// writeSummarySync(
|
|
4015
|
+
// { ...optsSummary, ...optsSummary.write },
|
|
4016
|
+
// getSummaryData(config, optsSummary, input),
|
|
4017
|
+
// );
|
|
4018
|
+
// }
|
|
4019
|
+
// return { config, input, code };
|
|
4020
|
+
// };
|
|
4021
|
+
|
|
4022
|
+
exports.generateRedirectForPathname = generateRedirectForPathname;
|
|
4023
|
+
exports.generateRedirects = generateRedirects;
|
|
4024
|
+
exports.generateRewriteForPathname = generateRewriteForPathname;
|
|
4025
|
+
exports.generateRewrites = generateRewrites;
|
|
4026
|
+
exports.i18nCompiler = i18nCompiler;
|