@koine/i18n 2.0.0-beta.82 → 2.0.0-beta.83

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/api.cjs.js CHANGED
@@ -70,7 +70,8 @@ export const defaultLocale: I18n.Locale = "${e.defaultLocale}";
70
70
  export default defaultLocale;
71
71
  `);
72
72
 
73
- var m$5 = (()=>`
73
+ // import type { I18nCompiler } from "../../compiler/types";
74
+ var m$5 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
74
75
  import { locales } from "./locales";
75
76
  import { to } from "./to";
76
77
  import type { I18n } from "./types";
@@ -149,7 +150,8 @@ export const deriveLocalisedPathnames = (routeId: I18n.RouteId, locationLike: Lo
149
150
  export default deriveLocalisedPathnames;
150
151
  `);
151
152
 
152
- var n$6 = (()=>`
153
+ // import type { I18nCompiler } from "../../compiler/types";
154
+ var n$6 = (()=>/* {}: I18nCompiler.AdapterArg */ `
153
155
  import { locales } from "./locales";
154
156
  import type { I18n } from "./types";
155
157
 
@@ -224,7 +226,12 @@ export default routesSpa;
224
226
  `;
225
227
  });
226
228
 
227
- let dataParamsToTsInterfaceBody = (e)=>Object.keys(e).reduce((r, t)=>{
229
+ /**
230
+ * TODO: maybe use `params` to determine the right type with some kind of special
231
+ * token used in the route id
232
+ *
233
+ * NB: wrap the output of this function, e.g. `type A = {${dataParamsToTsInterfaceBody(params)}}`
234
+ */ let dataParamsToTsInterfaceBody = (e)=>Object.keys(e).reduce((r, t)=>{
228
235
  let a = e[t], s = "";
229
236
  switch(a){
230
237
  case "number":
@@ -239,6 +246,38 @@ let dataParamsToTsInterfaceBody = (e)=>Object.keys(e).reduce((r, t)=>{
239
246
  return r.push(`${t}: ${s};`), r;
240
247
  }, []).join(" ");
241
248
 
249
+ // /**
250
+ // * Control plural keys depending the {{count}} variable
251
+ // */
252
+ // function plural(
253
+ // pluralRules: Intl.PluralRules,
254
+ // dic: I18nDictionary,
255
+ // key: string,
256
+ // config: I18nConfig,
257
+ // query?: TranslationQuery | null,
258
+ // options?: {
259
+ // returnObjects?: boolean
260
+ // fallback?: string | string[]
261
+ // }
262
+ // ): string {
263
+ // if (!query || typeof query.count !== 'number') return key
264
+ // const numKey = `${key}_${query.count}`
265
+ // if (getDicValue(dic, numKey, config, options) !== undefined) return numKey
266
+ // const pluralKey = `${key}_${pluralRules.select(query.count)}`
267
+ // if (getDicValue(dic, pluralKey, config, options) !== undefined) {
268
+ // return pluralKey
269
+ // }
270
+ // const nestedNumKey = `${key}.${query.count}`
271
+ // if (getDicValue(dic, nestedNumKey, config, options) !== undefined)
272
+ // return nestedNumKey
273
+ // const nestedKey = `${key}.${pluralRules.select(query.count)}`
274
+ // if (getDicValue(dic, nestedKey, config, options) !== undefined)
275
+ // return nestedKey
276
+ // return key
277
+ // }
278
+ // const getP = (dic) => {
279
+ // return
280
+ // }
242
281
  let i$4 = (t)=>utils.isString(t) || utils.isNumber(t) ? `"${t}"` : utils.isBoolean(t) ? `${t}` : utils.isArray(t) ? JSON.stringify(t) : `(${JSON.stringify(t)})`, s$6 = (e, r)=>utils.areEqual(e, r), p$2 = (t, e)=>{
243
282
  let { defaultLocale: r } = t, l = "";
244
283
  for(let t in e){
@@ -263,11 +302,22 @@ import { tPluralise } from "./tPluralise";
263
302
  });
264
303
  let $ = [
265
304
  m ? `params: { ${dataParamsToTsInterfaceBody(m)} }` : "",
305
+ // for ergonomy always allow the user to pass the locale
266
306
  "locale?: I18n.Locale"
267
307
  ].filter(Boolean).join(", ");
308
+ // const formatArgParams = params ? ", params" : "";
268
309
  l += `export let ${u} = (${$}) => `;
269
310
  let c = "";
270
- utils.isPrimitive(s) ? c += i$4(s) : c += p$2(t, s), f && (c = `tPluralise(${c}, params.count)`), l += (c = m ? `tInterpolateParams(${c}, params);` : `${c};`) + `\n`;
311
+ utils.isPrimitive(s) ? c += i$4(s) : c += p$2(t, s), f && (c = `tPluralise(${c}, params.count)`), // TODO: t interpolation and pluralisation
312
+ // if (isString(values)) {
313
+ // output += `toFormat(${formatArgLocale}, "${values}"${formatArgParams});`;
314
+ // } else {
315
+ // output += `toFormat(${formatArgLocale}, ${getFunctionBodyWithLocales(
316
+ // data,
317
+ // values,
318
+ // )}${formatArgParams});`;
319
+ // }
320
+ l += (c = m ? `tInterpolateParams(${c}, params);` : `${c};`) + `\n`;
271
321
  }
272
322
  return l;
273
323
  });
@@ -291,7 +341,8 @@ export default tInterpolateParams;
291
341
  `;
292
342
  });
293
343
 
294
- var l$3 = (()=>`
344
+ // import type { I18nCompiler } from "../../compiler/types";
345
+ var l$3 = (()=>/* {}: I18nCompiler.AdapterArg */ `
295
346
  /* eslint-disable prefer-const */
296
347
  let pluralRules = new Intl.PluralRules();
297
348
 
@@ -460,7 +511,9 @@ export default toSpa;
460
511
  `;
461
512
  });
462
513
 
463
- let s$5 = [
514
+ /**
515
+ * @see https://github.com/aralroca/next-translate?tab=readme-ov-file#5-plurals
516
+ */ let s$5 = [
464
517
  "zero",
465
518
  "one",
466
519
  "two",
@@ -468,13 +521,24 @@ let s$5 = [
468
521
  "many",
469
522
  "other"
470
523
  ], i$3 = "other";
471
- let isPluralSuffix = (e)=>s$5.includes(e) || utils.isNumericLiteral(e);
472
- let removePluralSuffix = (e)=>{
524
+ /**
525
+ * Is the given string a valid plural suffix?
526
+ */ let isPluralSuffix = (e)=>s$5.includes(e) || utils.isNumericLiteral(e);
527
+ /**
528
+ * Remove plural suffix from string
529
+ */ let removePluralSuffix = (e)=>{
473
530
  let [l] = utils.splitReverse(e, "_");
474
531
  return l ? e.replace(`_${l}`, "") : e;
475
532
  };
476
- let getPluralSuffix = (e)=>utils.splitReverse(e, "_")[0];
477
- let isPluralKey = (e)=>{
533
+ /**
534
+ * Get plural suffix from string
535
+ */ let getPluralSuffix = (e)=>utils.splitReverse(e, "_")[0];
536
+ /**
537
+ * Is the translation value object key a plural form?
538
+ *
539
+ * Using `splitReverse` ensures to get the last underscore prefixed suffix
540
+ * even in a string with multiple underscores.
541
+ */ let isPluralKey = (e)=>{
478
542
  let [l] = utils.splitReverse(e, "_");
479
543
  return isPluralSuffix(l);
480
544
  };
@@ -485,7 +549,11 @@ let a$3 = (e)=>{
485
549
  l[r] = l[r] || [], l[r].push(e);
486
550
  }), l;
487
551
  };
488
- let transformKeysForPlurals = (l)=>{
552
+ /**
553
+ * Some translations keys won't be used directly and should be omitted
554
+ * from the generated types, e.g. the plural versions of the same string.
555
+ */ let transformKeysForPlurals = (l)=>{
556
+ // only transform if we have the required plural suffix in the keys
489
557
  if (l.some(hasRequiredPluralSuffix) || l.includes(i$3)) {
490
558
  let r = l.filter(isPluralKey);
491
559
  if (r.length) {
@@ -493,7 +561,9 @@ let transformKeysForPlurals = (l)=>{
493
561
  ...l
494
562
  ];
495
563
  return utils.forin(a$3(r), (e, r)=>{
496
- l.includes(e) || t.push(e), r.forEach((e)=>{
564
+ // add the plural root
565
+ l.includes(e) || t.push(e), // remove the plurals variations
566
+ r.forEach((e)=>{
497
567
  l.includes(e) && (t = t.filter((l)=>l !== e));
498
568
  });
499
569
  }), t;
@@ -501,11 +571,24 @@ let transformKeysForPlurals = (l)=>{
501
571
  }
502
572
  return l;
503
573
  };
504
- let hasRequiredPluralSuffix = (e)=>isPluralKey(e) && getPluralSuffix(e) === i$3;
505
- let hasPlurals = (e)=>Object.keys(e).some(hasRequiredPluralSuffix) || Object.keys(e).includes(i$3);
506
- let hasOnlyPluralKeys = (e)=>!!hasPlurals(e) && 0 === pickNonPluralKeys(e).length;
507
- let pickNonPluralKeys = (e)=>Object.keys(e).filter((e)=>!isPluralSuffix(e));
508
- let pickNonPluralValue = (e)=>hasPlurals(e) ? utils.objectPick(e, pickNonPluralKeys(e)) : e;
574
+ /**
575
+ * Check if the given key has the required plural suffix
576
+ */ let hasRequiredPluralSuffix = (e)=>isPluralKey(e) && getPluralSuffix(e) === i$3;
577
+ /**
578
+ * Does the translation value object has plurals version?
579
+ *
580
+ * NB: here we check only for the **required** plural suffix,
581
+ */ let hasPlurals = (e)=>Object.keys(e).some(hasRequiredPluralSuffix) || Object.keys(e).includes(i$3);
582
+ /**
583
+ * Is the translation value object only enumerating plurals version?
584
+ */ let hasOnlyPluralKeys = (e)=>!!hasPlurals(e) && 0 === pickNonPluralKeys(e).length;
585
+ /**
586
+ * Pick the translation value object keys that _have no_ to do with pluralisation
587
+ */ let pickNonPluralKeys = (e)=>Object.keys(e).filter((e)=>!isPluralSuffix(e));
588
+ /**
589
+ * Narrows the translation value object picking only keys that _have no_ to do
590
+ * with pluralisation
591
+ */ let pickNonPluralValue = (e)=>hasPlurals(e) ? utils.objectPick(e, pickNonPluralKeys(e)) : e;
509
592
 
510
593
  let c$1 = (e, a)=>!utils.isArray(a) && utils.isObject(a) && hasPlurals(a) ? hasOnlyPluralKeys(a) ? `"${e}": string;` : `"${e}": ${h$2(pickNonPluralValue(a))}` : `"${e}": ${h$2(a)}`, h$2 = (e)=>{
511
594
  let o = "", i = "";
@@ -518,13 +601,16 @@ let c$1 = (e, a)=>!utils.isArray(a) && utils.isObject(a) && hasPlurals(a) ? hasO
518
601
  o += "{";
519
602
  let t = transformKeysForPlurals(Object.keys(e));
520
603
  for(let a = 0; a < t.length; a++){
521
- let s = t[a], n = e[s] || "";
604
+ let s = t[a], // fallback to a string otherwise plurals without root definition would
605
+ // not get a type otherwise, e.g. ` pluralNoDefault_...` in __mocks__
606
+ n = e[s] || "";
522
607
  o += c$1(s, n);
523
608
  }
524
609
  o += "};";
525
610
  }
526
611
  } else o += "";
527
- return (o = o.replace(/;\[\];/g, "[];")).replace(/;+/g, ";");
612
+ return(// adjust syntax
613
+ (o = o.replace(/;\[\];/g, "[];")).replace(/;+/g, ";"));
528
614
  }, d$3 = (e, t)=>{
529
615
  let { translationFiles: a } = t, { defaultLocale: s } = e, n = a.filter((e)=>e.locale === s), o = [];
530
616
  for(let e = 0; e < n.length; e++){
@@ -546,7 +632,9 @@ let c$1 = (e, a)=>!utils.isArray(a) && utils.isObject(a) && hasPlurals(a) ? hasO
546
632
  }, {}), f$1 = (e, t, a)=>{
547
633
  let s = m$4(t), n = [];
548
634
  for(let o in s){
549
- let i = s[o].map((e)=>e.split(o)[1].slice(1)), r = t.byId[o].pathnames[e.defaultLocale], l = [];
635
+ let i = s[o].map(// remove the root id portion and the first character which is always
636
+ // the route `idDelimiter`
637
+ (e)=>e.split(o)[1].slice(1)), r = t.byId[o].pathnames[e.defaultLocale], l = [];
550
638
  for(let s = 0; s < i.length; s++){
551
639
  let n = i[s], p = `${o}${a.routes.tokens.idDelimiter}${n}`, c = t.byId[p].pathnames[e.defaultLocale].split(r)[1];
552
640
  l.push(`"${n}": "${c}";`);
@@ -562,8 +650,11 @@ let c$1 = (e, a)=>!utils.isArray(a) && utils.isObject(a) && hasPlurals(a) ? hasO
562
650
  }
563
651
  return a;
564
652
  };
653
+ // TODO: probably move the Translate types into the adapter-next-translate
654
+ // unless we will use the same api for other adapters
565
655
  var L = (({ config: e, input: t, routes: a, options: s })=>{
566
- let n = y$1(a, (e, { params: t })=>!t), o = y$1(a, (e, { params: t })=>!!t), { idDelimiter: i } = s.routes.tokens;
656
+ let n = y$1(a, (e, { params: t })=>!t), o = y$1(a, (e, { params: t })=>!!t), // const routeIdSpa = buildRoutesUnion(routes, (_, { inWildcard }) => inWildcard);
657
+ { idDelimiter: i } = s.routes.tokens;
567
658
  return `
568
659
  /* eslint-disable @typescript-eslint/no-namespace */
569
660
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -938,7 +1029,8 @@ var t$2 = (()=>({
938
1029
  ]
939
1030
  }));
940
1031
 
941
- var e$2 = (()=>`
1032
+ // import type { I18nCompiler } from "../../compiler/types";
1033
+ var e$2 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
942
1034
  "use client";
943
1035
 
944
1036
  import _DynamicNamespaces from "next-translate/DynamicNamespaces";
@@ -948,7 +1040,8 @@ export const DynamicNamespaces = _DynamicNamespaces;
948
1040
  export default DynamicNamespaces;
949
1041
  `);
950
1042
 
951
- var n$5 = (()=>`
1043
+ // import type { I18nCompiler } from "../../compiler/types";
1044
+ var n$5 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
952
1045
  "use client";
953
1046
 
954
1047
  import type { TransProps } from "next-translate";
@@ -980,7 +1073,8 @@ export const T = Trans as typeof TypedT;
980
1073
  export default T;
981
1074
  `);
982
1075
 
983
- var t$1 = (()=>`
1076
+ // import type { I18nCompiler } from "../../compiler/types";
1077
+ var t$1 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
984
1078
  "use client";
985
1079
 
986
1080
  import _TransText from "next-translate/TransText";
@@ -990,7 +1084,8 @@ export const TransText = _TransText;
990
1084
  export default TransText;
991
1085
  `);
992
1086
 
993
- var m$3 = (()=>`
1087
+ // import type { I18nCompiler } from "../../compiler/types";
1088
+ var m$3 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
994
1089
  import _getT from "next-translate/getT";
995
1090
  import type { I18n } from "./types";
996
1091
 
@@ -1026,7 +1121,8 @@ module.exports = (config = { pages: {} }) => {
1026
1121
  }
1027
1122
  `);
1028
1123
 
1029
- var a$2 = (()=>`
1124
+ // import type { I18nCompiler } from "../../compiler/types";
1125
+ var a$2 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
1030
1126
  "use client";
1031
1127
 
1032
1128
  import { useMemo } from "react";
@@ -1114,31 +1210,48 @@ var a$1 = (()=>({
1114
1210
  ]
1115
1211
  }));
1116
1212
 
1117
- function transformPathname(e, t) {
1213
+ /**
1214
+ * Transform the route translated either into a `pathname` or a `template`.
1215
+ *
1216
+ * Here we add the wildcard flag maybe found in the pathname to the template
1217
+ * name too.
1218
+ *
1219
+ * @see https://nextjs.org/docs/messages/invalid-multi-match
1220
+ */ function transformPathname(e, t) {
1118
1221
  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*" : "");
1119
1222
  }
1120
1223
 
1121
1224
  function r$3(e) {
1122
1225
  let { localeSource: o, localeDestination: l, template: r, pathname: i, permanent: a } = e, n = formatRoutePathname.formatRoutePathname((o ? `${o}/` : "") + r), c = formatRoutePathname.formatRoutePathname((l ? `${l}/` : "") + i);
1226
+ // console.log(`redirect template "${source}" to pathname "${destination}"`);
1123
1227
  if (n !== c) return {
1124
1228
  source: n,
1125
1229
  destination: c,
1126
1230
  permanent: !!a
1127
1231
  };
1128
1232
  }
1129
- let generateRedirects = (t, i, a, n = "", c = !1)=>{
1233
+ /**
1234
+ * TODO: maybe write directly the vercel configuration?
1235
+ *
1236
+ * @see
1237
+ * - https://nextjs.org/docs/pages/api-reference/next-config-js/redirects
1238
+ * - https://vercel.com/docs/projects/project-configuration#redirects
1239
+ */ let generateRedirects = (t, i, a, n = "", c = !1)=>{
1130
1240
  let { defaultLocale: s, hideDefaultLocaleInUrl: p } = t, u = RegExp(utils.escapeRegExp(a.tokens.idDelimiter), "g"), m = [];
1131
1241
  for(let e in i){
1132
1242
  let o = i[e], t = i[e].pathnames;
1133
1243
  for(let i in t){
1134
- let a = t[i], f = transformPathname(e.replace(u, "/"), o.wildcard), d = transformPathname(a, o.wildcard);
1244
+ let a = t[i], // prettier-ignore
1245
+ f = transformPathname(e.replace(u, "/"), o.wildcard), d = transformPathname(a, o.wildcard);
1246
+ // we do not redirect urls children of wildcard urls
1135
1247
  if (o.inWildcard) break;
1136
1248
  let h = i === s, D = h && !p, g = h && p, k = {
1137
1249
  template: f,
1138
1250
  pathname: d,
1139
1251
  permanent: c
1140
1252
  };
1141
- n ? D ? m.push(r$3({
1253
+ n ? // app router:
1254
+ D ? m.push(r$3({
1142
1255
  ...k,
1143
1256
  localeDestination: i
1144
1257
  })) : g ? m.push(r$3({
@@ -1148,7 +1261,8 @@ let generateRedirects = (t, i, a, n = "", c = !1)=>{
1148
1261
  ...k,
1149
1262
  localeSource: i,
1150
1263
  localeDestination: i
1151
- })) : d !== f && (D ? m.push(r$3({
1264
+ })) : // pages router:
1265
+ d !== f && (D ? m.push(r$3({
1152
1266
  ...k,
1153
1267
  localeDestination: i
1154
1268
  })) : h ? m.push(r$3(k)) : m.push(r$3({
@@ -1177,47 +1291,75 @@ function o$5(e) {
1177
1291
  t && (a = `/${t}`);
1178
1292
  let n = formatRoutePathname.formatRoutePathname(a + i), c = "";
1179
1293
  r && (c = `/${r}`);
1294
+ // else if (localeParam) destinationPrefix = `/:${localeParam}`;
1180
1295
  let s = formatRoutePathname.formatRoutePathname(c + o);
1296
+ // console.log(`rewrite pathname "${source}" to template "${destination}"`);
1181
1297
  if (n !== s) return {
1182
1298
  source: n,
1183
1299
  destination: s
1184
1300
  };
1185
1301
  }
1186
1302
  let i$2 = (e, t = "", l, r, i, a)=>{
1187
- let { defaultLocale: n, hideDefaultLocaleInUrl: c } = e, s = l === n && c, u = {
1303
+ let { defaultLocale: n, hideDefaultLocaleInUrl: c } = e, s = l === n && c, // TODO: maybe support other locales to be hidden in the URL other than the default?
1304
+ u = {
1188
1305
  config: e,
1189
1306
  template: r,
1190
1307
  pathname: i
1191
1308
  };
1192
- t ? s ? a.push(o$5({
1309
+ t ? // app router:
1310
+ s ? a.push(o$5({
1193
1311
  ...u,
1194
1312
  localeDestination: l
1195
- })) : a.push(o$5({
1313
+ })) : a.push(// prettier-ignore
1314
+ o$5({
1196
1315
  ...u,
1197
1316
  localeSource: l,
1198
1317
  localeDestination: l
1199
- })) : i !== r && (s ? a.push(o$5(u)) : a.push({
1318
+ })) : // pages router:
1319
+ // this condition only applies to the pages router as with the app one
1320
+ // even if the template matches the pathname we always need to rewrite
1321
+ // as the localeParam is always needed in the rewrite destination
1322
+ i !== r && (s ? a.push(o$5(u)) : a.push({
1200
1323
  ...o$5({
1201
1324
  ...u,
1202
1325
  localeSource: l
1203
1326
  }),
1327
+ // this must be `false` or the locale prefixed rewrite won't be
1328
+ // applied and does not forward the locale to the route context
1329
+ // when the locale is included in the URL. In fact we explicitly
1330
+ // add the locale to the rewrite rule in order to get the least
1331
+ // amount of existing URLs which is a good SEO practice
1204
1332
  locale: !1
1205
1333
  }));
1206
1334
  };
1207
- let generateRewrites = (l, o, a, n = "")=>{
1335
+ /**
1336
+ * TODO: maybe write directly the vercel configuration?
1337
+ *
1338
+ * @see
1339
+ * - https://nextjs.org/docs/pages/api-reference/next-config-js/rewrites
1340
+ * - https://vercel.com/docs/projects/project-configuration#rewrites
1341
+ */ let generateRewrites = (l, o, a, n = "")=>{
1208
1342
  let c = RegExp(utils.escapeRegExp(a.tokens.idDelimiter), "g"), s = [];
1209
1343
  for(let e in o){
1210
1344
  let t = o[e], a = o[e].pathnames;
1211
1345
  for(let o in a){
1212
1346
  let u = a[o], p = e.replace(c, "/");
1347
+ // we do not rewrite urls children of wildcard urls
1213
1348
  if (t.inWildcard) break;
1214
- i$2(l, n, o, transformPathname(p), transformPathname(u), s), t.wildcard && i$2(l, n, o, transformPathname(p, t.wildcard), transformPathname(u, t.wildcard), s);
1349
+ // we need to rewrite both the root path...
1350
+ i$2(l, n, o, transformPathname(p), transformPathname(u), s), t.wildcard && // and for wildcard routes the ones with the `/:segment*` portion
1351
+ i$2(l, n, o, transformPathname(p, t.wildcard), transformPathname(u, t.wildcard), s);
1215
1352
  }
1216
1353
  }
1354
+ // simple sort by destination:
1355
+ // return a.destination.localeCompare(b.destination);
1356
+ // sort by locale
1357
+ // return a.
1217
1358
  return utils.arrayUniqueByProperties(s.filter(Boolean), [
1218
1359
  "source",
1219
1360
  "destination"
1220
- ]).sort((e, t)=>e.source.localeCompare(t.source));
1361
+ ]).sort((e, t)=>// simple sort by source:
1362
+ e.source.localeCompare(t.source));
1221
1363
  };
1222
1364
 
1223
1365
  var t = (({ config: e, routes: t, options: o })=>{
@@ -1225,7 +1367,8 @@ var t = (({ config: e, routes: t, options: o })=>{
1225
1367
  return `module.exports = ${l}`;
1226
1368
  });
1227
1369
 
1228
- var n$4 = (()=>`
1370
+ // import type { I18nCompiler } from "../../compiler/types";
1371
+ var n$4 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
1229
1372
  "use client";
1230
1373
 
1231
1374
  import { useEffect, useState } from "react";
@@ -1255,7 +1398,8 @@ export const useLocale = () => (useRouter().locale as I18n.Locale) || "${e.defau
1255
1398
  export default useLocale;
1256
1399
  `);
1257
1400
 
1258
- var r$2 = (()=>`
1401
+ // import type { I18nCompiler } from "../../compiler/types";
1402
+ var r$2 = (()=>/* {}: I18nCompiler.AdapterArg, */ `
1259
1403
  import { useRouter } from "next/router";
1260
1404
  import type { I18n } from "./types";
1261
1405
  import { pathnameToRouteId } from "./pathnameToRouteId";
@@ -1266,7 +1410,8 @@ export const useRouteId = () =>
1266
1410
  export default useRouteId;
1267
1411
  `);
1268
1412
 
1269
- var o$4 = (()=>`
1413
+ // import type { I18nCompiler } from "../../compiler/types";
1414
+ var o$4 = (()=>/* {}: I18nCompiler.AdapterArg */ `
1270
1415
  "use client";
1271
1416
 
1272
1417
  import { to } from "./to";
@@ -1293,7 +1438,8 @@ export const useTo = () => {
1293
1438
  export default useTo;
1294
1439
  `);
1295
1440
 
1296
- var m$2 = (()=>`
1441
+ // import type { I18nCompiler } from "../../compiler/types";
1442
+ var m$2 = (()=>/* {}: I18nCompiler.AdapterArg */ `
1297
1443
  "use client";
1298
1444
 
1299
1445
  import { toSpa } from "./toSpa";
@@ -1333,6 +1479,8 @@ var n$3 = (()=>({
1333
1479
  "js"
1334
1480
  ],
1335
1481
  files: [
1482
+ // TODO: maybe remove these files, they are useful for debugging for now
1483
+ // but probably will be useless
1336
1484
  {
1337
1485
  name: "next-redirects",
1338
1486
  fn: e$1,
@@ -1385,13 +1533,26 @@ let r$1 = {
1385
1533
  return e.filter((e)=>e.index).sort((e, t)=>e.name.localeCompare(t.name)).forEach((e)=>{
1386
1534
  t += `export * from "./${e.name}";\n`;
1387
1535
  }), t;
1388
- }, s$2 = async (t, a, n = [])=>{
1536
+ }, /**
1537
+ * Recursively builds a list of adapters to use based on the `dependsOn` array
1538
+ * of the choosen adapter
1539
+ */ s$2 = async (t, a, n = [])=>{
1389
1540
  let o = (0, r$1[a])(t), d = utils.isPromise(o) ? await o : o;
1390
1541
  return n = n.concat(d), d.dependsOn && await Promise.all(d.dependsOn.map(async (e)=>{
1391
1542
  n = n.concat(await s$2(t, e));
1392
1543
  })), n;
1393
1544
  }, l$2 = (e, t, a)=>{
1394
- let { outputFiles: n } = t, r = a.reduce((e, t)=>[
1545
+ let { outputFiles: n } = t, // TODO: prettier does probably not make sense unless one wants to keep the
1546
+ // auto-generated files on git, maybe allow this as an option?
1547
+ // // prettier breaks jest, @see https://jestjs.io/docs/ecmascript-modules
1548
+ // // https://github.com/jestjs/jest/issues/14305
1549
+ // if (!process.env["JEST_WORKER_ID"]) {
1550
+ // const { format } = await import("prettier");
1551
+ // out = await format(out, {
1552
+ // parser: "typescript",
1553
+ // });
1554
+ // }
1555
+ r = a.reduce((e, t)=>[
1395
1556
  ...e,
1396
1557
  ...t.files
1397
1558
  ], []).map((t)=>{
@@ -1402,23 +1563,39 @@ let r$1 = {
1402
1563
  content: a(e)
1403
1564
  };
1404
1565
  });
1405
- return o$3(r) && r.push({
1566
+ return(// automatically create an index file if the adapters want it
1567
+ o$3(r) && r.push({
1406
1568
  name: "index",
1407
1569
  ext: "ts",
1408
1570
  content: o$3(r)
1409
1571
  }), {
1410
1572
  files: r,
1573
+ // it is enough that just one adapter requires this
1411
1574
  needsTranslationsFiles: a.some((e)=>e.needsTranslationsFiles)
1412
- };
1575
+ });
1413
1576
  };
1577
+ // TODO: make this works with generics based on chosen adapter?
1578
+ // defaultLocale: string;
1579
+ // index: string;
1580
+ // isLocale: string;
1581
+ // locales: string;
1582
+ // routes: string;
1583
+ // routesSlim: string;
1584
+ // to: string;
1585
+ // toFns: string;
1586
+ // toFormat: string;
1587
+ // types: string;
1414
1588
  let generateCode = async (e, t)=>l$2(e, t, await s$2(e, t.adapter));
1415
1589
 
1416
- let tsCompile = (o, i, s, r)=>{
1590
+ let tsCompile = (o, i, s, // Set<string>,
1591
+ r)=>{
1417
1592
  let l = Array.from(s).filter((e)=>e.endsWith(".ts") || e.endsWith(".tsx")).map((t)=>node_path.join(o, i, t)), n = {
1418
1593
  noEmitOnError: !0,
1419
1594
  noImplicitAny: !0,
1420
1595
  declaration: !0,
1596
+ // target: ts.ScriptTarget.ES5,
1421
1597
  target: t__namespace.ScriptTarget.ESNext,
1598
+ // module: ts.ModuleKind.CommonJS,
1422
1599
  module: t__namespace.ModuleKind.ESNext,
1423
1600
  moduleResolution: t__namespace.ModuleResolutionKind.Bundler,
1424
1601
  resolveJsonModule: !0,
@@ -1430,13 +1607,26 @@ let tsCompile = (o, i, s, r)=>{
1430
1607
  noEmitHelpers: !0,
1431
1608
  importHelpers: !0,
1432
1609
  ...r || {}
1433
- }, a = t__namespace.createProgram(l, n), m = a.emit();
1434
- return t__namespace.getPreEmitDiagnostics(a).concat(m.diagnostics).forEach((e)=>{
1610
+ }, // Create a Program with an in-memory emit
1611
+ // const createdFiles: Record<string, string> = {};
1612
+ // const host = ts.createCompilerHost(compilerOptions);
1613
+ // host.writeFile = (fileName: string, contents: string) => createdFiles[fileName] = contents;
1614
+ a = t__namespace.createProgram(l, n), /* , host */ m = a.emit();
1615
+ return(// .concat(emitResultCjs.diagnostics);
1616
+ // const programCjs = ts.createProgram(rootNames, {
1617
+ // ...compilerOptions,
1618
+ // module: ts.ModuleKind.CommonJS,
1619
+ // moduleResolution: ts.ModuleResolutionKind.Classic,
1620
+ // declaration: false,
1621
+ // });
1622
+ // const emitResultCjs = programCjs.emit();
1623
+ t__namespace.getPreEmitDiagnostics(a).concat(m.diagnostics).forEach((e)=>{
1435
1624
  if (e.file) {
1436
- let { line: o, character: i } = t__namespace.getLineAndCharacterOfPosition(e.file, e.start), s = t__namespace.flattenDiagnosticMessageText(e.messageText, "\n");
1625
+ let { line: o, character: i } = t__namespace.getLineAndCharacterOfPosition(e.file, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1626
+ e.start), s = t__namespace.flattenDiagnosticMessageText(e.messageText, "\n");
1437
1627
  console.log(`${e.file.fileName} (${o + 1},${i + 1}): ${s}`);
1438
1628
  } else console.log(t__namespace.flattenDiagnosticMessageText(e.messageText, "\n"));
1439
- }), m;
1629
+ }), m);
1440
1630
  };
1441
1631
 
1442
1632
  let n$2 = async (e, r, s, i)=>Promise.all(s.files.map(async ({ name: s, ext: o, content: n })=>{
@@ -1445,7 +1635,8 @@ let n$2 = async (e, r, s, i)=>Promise.all(s.files.map(async ({ name: s, ext: o,
1445
1635
  })), d$2 = (a, r, s)=>{
1446
1636
  let i = Array.from(s).filter((e)=>e.endsWith(".ts") || e.endsWith(".tsx"));
1447
1637
  tsCompile(a, r, i), i.forEach((i)=>{
1448
- s.add(i.replace(/\.tsx?$/, ".js")), s.add(i.replace(/\.tsx?$/, ".d.ts")), s.delete(i), node_fs.rmSync(node_path.join(a, r, i), {
1638
+ s.add(i.replace(/\.tsx?$/, ".js")), s.add(i.replace(/\.tsx?$/, ".d.ts")), // remove TypeScript files
1639
+ s.delete(i), node_fs.rmSync(node_path.join(a, r, i), {
1449
1640
  force: !0
1450
1641
  });
1451
1642
  });
@@ -1459,24 +1650,40 @@ let n$2 = async (e, r, s, i)=>Promise.all(s.files.map(async ({ name: s, ext: o,
1459
1650
  ...s
1460
1651
  ])).sort().map((e)=>`/${e}`).join(`\n`)
1461
1652
  ];
1462
- let writeCode = async (e, t)=>{
1653
+ /**
1654
+ * @default process.cwd()
1655
+ */ /**
1656
+ * Relative to the given `cwd`.
1657
+ *
1658
+ * Use a _dot_ named folder in order to be automatically ignored when your
1659
+ * i18n source files live in the same folder as the generated code
1660
+ */ let writeCode = async (e, t)=>{
1463
1661
  let { cwd: r = process.cwd(), output: i, skipTsCompile: o, skipGitignore: l, skipTranslations: p, ...c } = e, w = await generateCode(t, c), y = new Set(), S = new Set();
1464
1662
  await n$2(r, i, w, y), o || d$2(r, i, y), w.needsTranslationsFiles && !p && await m$1(r, i, t.input, S), l || await node.fsWrite(...f(r, i, S, y));
1465
1663
  };
1466
1664
 
1467
1665
  const codeDataRoutesOptions = {
1468
- translationJsonFileName: "~.json",
1469
- fnsPrefix: "",
1666
+ /** @default "~.json" */ translationJsonFileName: "~.json",
1667
+ /**
1668
+ * Generated `route_id()` functions prefix, prepended to the automatically
1669
+ * generated function names.
1670
+ *
1671
+ * @default ""
1672
+ */ fnsPrefix: "",
1470
1673
  tokens: {
1471
- parentReference: "^",
1472
- idDelimiter: ".",
1473
- catchAll: {
1474
- start: "[...",
1475
- end: "]"
1674
+ /** @default "^" */ parentReference: "^",
1675
+ /** @default "." */ idDelimiter: ".",
1676
+ /**
1677
+ * @see https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments
1678
+ */ catchAll: {
1679
+ /** @default "[..." */ start: "[...",
1680
+ /** @default "]" */ end: "]"
1476
1681
  },
1477
- optionalCatchAll: {
1478
- start: "[[...",
1479
- end: "]]"
1682
+ /**
1683
+ * @see https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-segments
1684
+ */ optionalCatchAll: {
1685
+ /** @default "[[..." */ start: "[[...",
1686
+ /** @default "]]" */ end: "]]"
1480
1687
  }
1481
1688
  }
1482
1689
  };
@@ -1493,20 +1700,51 @@ let r = (t, a)=>{
1493
1700
  optionalCatchAll: RegExp(`${utils.escapeRegExp(d.start)}(.+)${utils.escapeRegExp(d.end)}$`)
1494
1701
  }
1495
1702
  };
1496
- }, d$1 = (e, { reg: t })=>{
1703
+ }, /**
1704
+ * Normalise user defined route id
1705
+ *
1706
+ * 1) remove ending `.index`
1707
+ */ d$1 = (e, { reg: t })=>{
1497
1708
  let a = e.replace(t.indexEnd, ""), l = t.optionalCatchAll.test(e), n = t.catchAll.test(e);
1498
1709
  return l && (a = a.replace(t.optionalCatchAll, "")), n && (a = a.replace(t.catchAll, "")), {
1499
1710
  routeId: a = a.replace(t.trailingDelimiter, ""),
1500
1711
  isCatchAll: n,
1501
1712
  isOptionalCatchAll: l
1502
1713
  };
1503
- }, i$1 = (e)=>formatRoutePathname.formatRoutePathname(e.replace(/\*/g, "").replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g, (e, t)=>`[${t.trim()}]`)), s$1 = (e)=>{
1714
+ }, /**
1715
+ * Normalise user defined route pathname
1716
+ *
1717
+ * - ensures beginning slash
1718
+ * - replaces too many consecutive slashes
1719
+ * - removes the trailing slash
1720
+ * - removes `*` wildcard token
1721
+ * - normalises to `/my/[id]` dynamic params defined in any of these shapes:
1722
+ * - `/my/{{id}}`
1723
+ * - `/my/{{ id }}`
1724
+ * - `/my/[id]`
1725
+ * - `/my/[ id ]`
1726
+ * - `/my/{id}`
1727
+ * - `/my/{ id }`
1728
+ *
1729
+ * TODO: support also `/my/:id` syntax?
1730
+ */ i$1 = (e)=>formatRoutePathname.formatRoutePathname(e.replace(/\*/g, "").replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g, (e, t)=>`[${t.trim()}]`)), /**
1731
+ * Gathers a dictionary with the params extracted from the given (normalised)
1732
+ * route id
1733
+ */ s$1 = (e)=>{
1504
1734
  let t = e.match(/\[.*?\]/g);
1505
- if (t) return t.map((e)=>e.slice(1, -1).trim()).reduce((e, t)=>(e[t] = "stringOrNumber", e), {});
1506
- }, p = (e, t, a, l, n)=>{
1735
+ 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
1736
+ // token used in the route id `[dynamicParam]` portion
1737
+ e[t] = "stringOrNumber", e), {});
1738
+ }, /**
1739
+ * Recursively replace `/^` references with the parent route value
1740
+ */ p = (e, t, a, l, n)=>{
1507
1741
  let { tokens: { parentReference: r, idDelimiter: d }, reg: i } = t, s = e.byId[l], o = s.pathnames[a];
1742
+ // beginning slash is always present here as the route value is already
1743
+ // normalised at this point
1508
1744
  if (o.startsWith(`/${r}`)) {
1745
+ // removes the slash + token
1509
1746
  o = o.replace(i.parentReference, "");
1747
+ // grab the parent id
1510
1748
  let r = l.split(d).slice(0, -1).join(d);
1511
1749
  if (!n || n && n(s, r)) {
1512
1750
  if (r) o = p(e, t, a, r, n) + o;
@@ -1514,16 +1752,50 @@ let r = (t, a)=>{
1514
1752
  }
1515
1753
  }
1516
1754
  return o;
1517
- }, o$2 = (e, t)=>{
1755
+ }, /**
1756
+ * Mutate the routes data replacing the parent route tokens
1757
+ * NB: it mutates the data
1758
+ */ o$2 = (e, t)=>{
1518
1759
  for(let a in e.byId)for(let l in e.byId[a].pathnames)e.byId[a].pathnames[l] = p(e, t, l, a);
1519
- }, c = (e, t)=>{
1760
+ }, /**
1761
+ * Mutate the routes data replacing the parent route tokens
1762
+ * NB: it mutates the data
1763
+ */ c = (e, t)=>{
1520
1764
  let a = (t, a)=>t.inWildcard && !e.wildcardIds.includes(a);
1521
1765
  for(let l in e.byId){
1522
1766
  let { inWildcard: n } = e.byId[l];
1523
- if (n && e.byId[l].pathnamesSpa) for(let n in e.byId[l].pathnamesSpa)e.byId[l].pathnamesSpa[n] = p(e, t, n, l, a);
1524
- else delete e.byId[l].pathnamesSpa;
1767
+ if (n && e.byId[l].pathnamesSpa) for(let n in e.byId[l].pathnamesSpa)// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1768
+ e.byId[l].pathnamesSpa[n] = p(e, t, n, l, a);
1769
+ else // discard unneeded data
1770
+ delete e.byId[l].pathnamesSpa;
1525
1771
  }
1526
- }, m = (e, t)=>{
1772
+ }, /**
1773
+ * Optimize the route map by collapsing pathnames that are equal to the one for
1774
+ * the default locale
1775
+ *
1776
+ * NB: It mutates the data
1777
+ *
1778
+ * ```json
1779
+ * {
1780
+ * // from
1781
+ * "about": {
1782
+ * "en": "/about",
1783
+ * "nl": "/about"
1784
+ * },
1785
+ * "account.user.[id]": {
1786
+ * "en": "/account/user/{{ id }}",
1787
+ * "fi": "/account/user/{{ id }}",
1788
+ * "nl": "/rekening/gebruiker/{{ id }}"
1789
+ * },
1790
+ * // to
1791
+ * "about": "/about",
1792
+ * "account.user.[id]": {
1793
+ * "en": "/account/user/{{ id }}",
1794
+ * "nl": "/rekening/gebruiker/{{ id }}"
1795
+ * }
1796
+ * }
1797
+ * ```
1798
+ */ m = (e, t)=>{
1527
1799
  let { defaultLocale: a, locales: n } = t;
1528
1800
  for(let t in e.byId){
1529
1801
  let r = e.byId[t].pathnames, d = r[a], i = {};
@@ -1531,26 +1803,44 @@ let r = (t, a)=>{
1531
1803
  let t = r[e];
1532
1804
  t !== d && (i[e] = t);
1533
1805
  }
1534
- Object.keys(i).length === n.length - 1 || (Object.keys(i).length >= 1 ? (i[a] = d, e.byId[t].pathnamesSlim = utils.objectSortByKeysMatching(i, a)) : e.byId[t].pathnamesSlim = d);
1806
+ Object.keys(i).length === n.length - 1 || (// if we have the same number of optimized/non-optimized pathnames we do
1807
+ // not add the data
1808
+ Object.keys(i).length >= 1 ? (// if we have more than one optimized pathnames we do add the default locale one
1809
+ i[a] = d, e.byId[t].pathnamesSlim = utils.objectSortByKeysMatching(i, a)) : // otherwise it means that the pathname is the same for all locales
1810
+ e.byId[t].pathnamesSlim = d);
1535
1811
  }
1536
- }, h$1 = (e)=>{
1812
+ }, /**
1813
+ * Flag routes that are children of wildcards, a.k.a. child SPA routes
1814
+ *
1815
+ * NB: It mutates the data
1816
+ */ h$1 = (e)=>{
1537
1817
  if (e.wildcardIds.length) for(let t in e.byId)e.wildcardIds.some((e)=>t.startsWith(e) && e !== t) && (e.byId[t].inWildcard = !0);
1538
1818
  }, I = (e, n, r, p)=>{
1539
1819
  let o = utils.objectFlat(e, r.tokens.idDelimiter);
1540
1820
  for(let e in o){
1541
- let t = o[e], { routeId: a, isCatchAll: c, isOptionalCatchAll: m } = d$1(e, r);
1821
+ let t = o[e], // as I18nCompiler.RoutePathname;
1822
+ { routeId: a, isCatchAll: c, isOptionalCatchAll: m } = d$1(e, r);
1823
+ // if (isCatchAll || isOptionalCatchAll) console.log({ routeId, key });
1824
+ // if is the first pass for this routeId
1542
1825
  if (!p.byId[a]) {
1543
1826
  p.byId[a] = p.byId[a] || {};
1544
1827
  let e = s$1(a);
1545
1828
  p.byId[a].id = a, e && (p.byId[a].params = e), (c || m) && (p.byId[a].wildcard = !0, p.wildcardIds.push(a));
1546
1829
  }
1547
- p.byId[a].pathnames = p.byId[a].pathnames || {}, p.byId[a].pathnames[n] = i$1(t), p.byId[a].pathnames = utils.objectSortByKeysMatching(p.byId[a].pathnames, r.defaultLocale), p.byId[a].pathnamesSpa = {
1830
+ p.byId[a].pathnames = p.byId[a].pathnames || {}, // prettier-ignore
1831
+ p.byId[a].pathnames[n] = i$1(t), // prettier-ignore
1832
+ p.byId[a].pathnames = utils.objectSortByKeysMatching(p.byId[a].pathnames, r.defaultLocale), // just copy them for now, the difference treatment happens when resolving
1833
+ // the parent tokens
1834
+ p.byId[a].pathnamesSpa = {
1548
1835
  ...p.byId[a].pathnames
1549
1836
  };
1550
1837
  }
1838
+ // sort by route name
1551
1839
  p.byId = utils.objectSort(p.byId);
1552
1840
  };
1553
- let getCodeDataRoutes = (e, t, { translationFiles: a })=>{
1841
+ /**
1842
+ * Get routes data
1843
+ */ let getCodeDataRoutes = (e, t, { translationFiles: a })=>{
1554
1844
  let l = {
1555
1845
  byId: {},
1556
1846
  wildcardIds: []
@@ -1559,28 +1849,79 @@ let getCodeDataRoutes = (e, t, { translationFiles: a })=>{
1559
1849
  let { path: r, locale: d, data: i } = a[e];
1560
1850
  r === t.translationJsonFileName && I(i, d, n, l);
1561
1851
  }
1562
- return h$1(l), c(l, n), o$2(l, n), m(l, n), l;
1563
- };
1852
+ return(// the order in which these mutations run matters!
1853
+ h$1(l), c(l, n), o$2(l, n), m(l, n), l);
1854
+ }; // /**
1855
+ // * Route id to TypeScript valid type/interface name
1856
+ // *
1857
+ // * @deprecated
1858
+ // */
1859
+ // const routeIdToTypeName = (routeId: string) =>
1860
+ // capitalize(changeCaseCamel(routeId));
1564
1861
 
1565
1862
  const codeDataTranslationsOptions = {
1566
- ignorePaths: [],
1863
+ /**
1864
+ * A list of globs to run against source files, those that are matched will be
1865
+ * ignored
1866
+ *
1867
+ * @see https://www.npmjs.com/package/minimatch
1868
+ */ ignorePaths: [],
1567
1869
  dynamicDelimiters: {
1568
1870
  start: "{{",
1569
1871
  end: "}}"
1570
1872
  },
1571
- fnsAsDataCodes: !0,
1572
- fnsPrefix: "",
1573
- createArrayIndexBasedFns: !1
1873
+ // TODO: add pluralisation config
1874
+ /**
1875
+ * It creates `t_` functions that returns objects and arrays to use as
1876
+ * data source.
1877
+ *
1878
+ * NB: this greatly increased the generated code, tree shaking will still
1879
+ * apply though.
1880
+ *
1881
+ * @default true
1882
+ */ fnsAsDataCodes: !0,
1883
+ /**
1884
+ * Generated `namespace_tKey()` functions prefix, prepended to the automatically
1885
+ * generated function names.
1886
+ *
1887
+ * @default ""
1888
+ */ fnsPrefix: "",
1889
+ /**
1890
+ * Given a translation value as `"myKey": ["two", "words"]`:
1891
+ * - when `true`: it outputs `t_myKey_0` and `t_myKey_1` functions
1892
+ * - when `false`: if `fnsAsDataCodes` is `true` it outputs `t_myKey` otherwise
1893
+ * it outputs nothing (TODO: maybe we could log this info in this case)
1894
+ *
1895
+ * NB: It is quite unlikely that you want to set this to `true`.
1896
+ *
1897
+ * @default false
1898
+ */ createArrayIndexBasedFns: !1
1574
1899
  };
1575
- let g = RegExp(node_path.sep, "g"), v = (e)=>{
1576
- let t = e.replace(/~/g, "$").replace(/-/g, "_").replace(g, "_").replace(/_+/g, "_").replace(/[^a-zA-Z0-9_$]/gi, "");
1900
+ let g = RegExp(node_path.sep, "g"), /**
1901
+ * Normalise translation key
1902
+ */ v = (e)=>{
1903
+ let t = e.// replace tilde with dollar
1904
+ replace(/~/g, "$").// replace dash with underscore
1905
+ replace(/-/g, "_").replace(g, "_").// collapse consecutive underscores
1906
+ replace(/_+/g, "_").// ensure valid js identifier, allow only alphanumeric characters and few symbols
1907
+ replace(/[^a-zA-Z0-9_$]/gi, "");
1908
+ // ensure the key does not start with a number (invalid js)
1577
1909
  return /^[0-9]/.test(t) ? "$" + t : t;
1578
1910
  }, h = (e, t)=>{
1579
1911
  if (utils.isString(t)) {
1580
1912
  let { start: r, end: a } = e.dynamicDelimiters, l = RegExp(`${r}(.*?)${a}`, "gm"), s = t.match(l);
1581
- if (s) return s.map((e)=>e.replace(r, "").replace(a, "").trim()).reduce((e, t)=>(e[t] = "stringOrNumber", e), {});
1913
+ 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
1914
+ // token used in the route id `[dynamicParam]` portion
1915
+ e[t] = "stringOrNumber", e), {});
1582
1916
  }
1583
- }, y = (e, t, r = {})=>{
1917
+ }, /**
1918
+ * This was an experiment to extract params to interpolate from non-flat
1919
+ * translations values, but that does not seem really needed as one
1920
+ * can always use `tInterpolateParams` directly on whatever string
1921
+ *
1922
+ * @deprecated
1923
+ */ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1924
+ y = (e, t, r = {})=>{
1584
1925
  if (utils.isPrimitive(t)) {
1585
1926
  let a = h(e, t);
1586
1927
  return a && (r = {
@@ -1603,20 +1944,67 @@ let g = RegExp(node_path.sep, "g"), v = (e)=>{
1603
1944
  });
1604
1945
  }
1605
1946
  return {};
1606
- }, _ = (e, t)=>(Object.keys(t).filter(isPluralKey).forEach((r)=>{
1947
+ }, // const addDataTranslationEntryForObjectValue = (
1948
+ // options: CodeDataTranslationsOptions,
1949
+ // id: string,
1950
+ // locale: I18nCompiler.Locale,
1951
+ // value: Exclude<Extract<I18nCompiler.DataTranslationValue, object>, string[]>,
1952
+ // dataTranslations: I18nCompiler.DataTranslations,
1953
+ // ) => {
1954
+ // // if (hasOnlyPluralKeys(value)) {
1955
+ // // return `'${key}': string;`;
1956
+ // // }
1957
+ // // if (!isArray(value) && isObject(value)) {
1958
+ // // if (hasOnlyPluralKeys(value)) {
1959
+ // // return `'${key}': string;`;
1960
+ // // }
1961
+ // // if (hasPlurals(value)) {
1962
+ // // return `'${key}': string | ${buildTypeForValue(pickNonPluralValue(value))}`;
1963
+ // // }
1964
+ // // }
1965
+ // // return `'${key}': ${buildTypeForValue(value)}`;
1966
+ // };
1967
+ /**
1968
+ * At this point the data translations have been calculated, this happens in a
1969
+ * second pass as we need to know all the translations keys to look for plural
1970
+ * variations.
1971
+ *
1972
+ * NB: we mutate the `dataTranslations`
1973
+ */ _ = (e, t)=>(Object.keys(t).filter(isPluralKey).forEach((r)=>{
1607
1974
  let a = removePluralSuffix(r), l = getPluralSuffix(r);
1608
- if (t[a] = t[a] || {}, t[r]) {
1975
+ // we only need to rearrange plurals defined as `x_one`, `x_other`, if plurals
1976
+ // are instead defined as objects `{ one: "", other: "" }` we just keep that
1977
+ // object structure for `values`
1978
+ if (// we need to create it if we only have `x_one` `x_other` but not `x`
1979
+ t[a] = t[a] || {}, t[r]) {
1609
1980
  let s = t[a].values || {};
1610
1981
  utils.forin(t[r].values, (r, i)=>{
1611
- s[r] = utils.isObject(s[r]) ? s[r] : {}, s[r][l] = i;
1982
+ // we need to ensure the value is an object for pluralisation, so if
1983
+ // we encounter this structure:
1984
+ // { "plural": "Plural", "plural_one": "One", "plural_other": "Some" }
1985
+ // we just remove the first `plural` value as that key is instead used
1986
+ // to grab the right pluralised version from the object value we build
1987
+ // from the other plural-suffixed keys. TODO: maybe we could warn the
1988
+ // developer of improper usage of `plural` translation key, which is
1989
+ // simply useless
1990
+ // prettier-ignore
1991
+ s[r] = utils.isObject(s[r]) ? s[r] : {}, // prettier-ignore
1992
+ s[r][l] = i;
1612
1993
  let n = y(e, i);
1613
1994
  n && (t[a].params = {
1614
1995
  ...t[a].params || {},
1615
1996
  ...n
1616
1997
  });
1617
- }), Object.keys(s).length && (t[a].values = s, t[a].plural = !0), delete t[r];
1998
+ }), Object.keys(s).length && (t[a].values = s, t[a].plural = !0), // TODO: probaly here we should remove the non-plural keys from `values`
1999
+ // as they are anyway accessible from "deeper" functions e.g.
2000
+ // `withPluralAndOtherKeys({ count: 3 }) => "One" | "Many"`
2001
+ // `withPluralAndOtherKeys_nonPluralKey()` => "Yes"
2002
+ // delete ids that we re-arranged in the plural-ready object value
2003
+ delete t[r];
1618
2004
  }
1619
- }), t), x = (e, t, r, a, l)=>{
2005
+ }), t), /**
2006
+ * Add entry to translations data
2007
+ */ x = (e, t, r, a, l)=>{
1620
2008
  if (utils.isPrimitive(a)) {
1621
2009
  l[t] = l[t] || {}, l[t].values = l[t].values || {}, l[t].values[r] = a, l[t].typeValue = "Primitive";
1622
2010
  let s = h(e, a);
@@ -1626,12 +2014,17 @@ let g = RegExp(node_path.sep, "g"), v = (e)=>{
1626
2014
  let e = utils.isArray(a) ? "Array" : "Object";
1627
2015
  l[t] = l[t] || {}, l[t].values = l[t].values || {}, l[t].values[r] = a, l[t].typeValue = e;
1628
2016
  }
2017
+ // @see comment on `extractTranslationParamsFromValue`
2018
+ // const params = extractTranslationParamsFromValue(options, value);
2019
+ // if (params) dataTranslations[id].params = params;
1629
2020
  if (utils.isArray(a)) {
1630
2021
  if (e.createArrayIndexBasedFns) for(let s = 0; s < a.length; s++)x(e, t + "_" + s, r, a[s], l);
1631
2022
  } else for(let s in a)x(e, t + "_" + v(s), r, a[s], l);
1632
2023
  }
1633
2024
  return l;
1634
- }, A = (l, s, i)=>{
2025
+ }, /**
2026
+ * Get translation data recursively starting from a specific file
2027
+ */ A = (l, s, i)=>{
1635
2028
  let { locale: n, path: o } = s, p = node_path.join(node_path.dirname(o), node_path.basename(o, node_path.extname(o)));
1636
2029
  for(let e in s.data){
1637
2030
  let t = s.data[e];
@@ -1639,10 +2032,14 @@ let g = RegExp(node_path.sep, "g"), v = (e)=>{
1639
2032
  }
1640
2033
  return i;
1641
2034
  };
1642
- let getCodeDataTranslations = (e, t, { translationFiles: r })=>{
2035
+ /**
2036
+ * Get translations data
2037
+ */ let getCodeDataTranslations = (e, t, { translationFiles: r })=>{
1643
2038
  let { ignorePaths: a } = t, l = {};
1644
2039
  for(let e = 0; e < r.length; e++)(!a || a && a.every((t)=>!minimatch.minimatch(r[e].path, t))) && A(t, r[e], l);
1645
- return utils.objectSort(l = _(t, l));
2040
+ // console.log("generateTypes: outputDir", outputDir, "outputPath", outputPath);
2041
+ return(// sort
2042
+ utils.objectSort(l = _(t, l)));
1646
2043
  };
1647
2044
 
1648
2045
  let e = {
@@ -1651,7 +2048,8 @@ let e = {
1651
2048
  };
1652
2049
  let getCodeData = (o, s, l)=>{
1653
2050
  let n = utils.objectMergeWithDefaults(e, s);
1654
- return n.translations.ignorePaths.push(n.routes.translationJsonFileName), l = {
2051
+ return n.translations.ignorePaths.push(n.routes.translationJsonFileName), // order locales
2052
+ l = {
1655
2053
  ...l,
1656
2054
  localesFolders: l.localesFolders.sort((t, a)=>o.defaultLocale ? -1 : t.localeCompare(a))
1657
2055
  }, {
@@ -1670,13 +2068,24 @@ const configDefaults = {
1670
2068
  defaultLocale: "en",
1671
2069
  hideDefaultLocaleInUrl: !0
1672
2070
  };
1673
- let getConfig = (e, o = {})=>{
1674
- o.locales = o.locales || e.localesFolders, o.defaultLocale = o.defaultLocale || o.locales?.[0], o.hideDefaultLocaleInUrl = !!o.hideDefaultLocaleInUrl;
2071
+ /**
2072
+ * Get basic i18n compiler config with defaults and automatic inference from
2073
+ * input data
2074
+ */ let getConfig = (e, o = {})=>{
2075
+ // dynamically define locales
2076
+ o.locales = o.locales || e.localesFolders, // ensure defaultLocale
2077
+ o.defaultLocale = o.defaultLocale || o.locales?.[0], // ensure boolean value
2078
+ o.hideDefaultLocaleInUrl = !!o.hideDefaultLocaleInUrl;
1675
2079
  let a = utils.objectMergeWithDefaults(configDefaults, o);
1676
- return a.locales = a.locales.sort((l, e)=>a.defaultLocale ? -1 : l.localeCompare(e)), a;
2080
+ return(// ensure sorted locales
2081
+ a.locales = a.locales.sort((l, e)=>a.defaultLocale ? -1 : l.localeCompare(e)), a);
1677
2082
  };
1678
2083
 
1679
- let n$1 = (e, r)=>{
2084
+ /**
2085
+ * @default process.cwd()
2086
+ */ /**
2087
+ * @default undefined
2088
+ */ let n$1 = (e, r)=>{
1680
2089
  let { cwd: n = process.cwd(), output: i, pretty: o } = e;
1681
2090
  return [
1682
2091
  node_path.join(n, i),
@@ -1696,7 +2105,10 @@ let l$1 = (e)=>{
1696
2105
  ...a,
1697
2106
  "node_modules/**"
1698
2107
  ]
1699
- }).filter((e)=>e.isDirectory()).map((e)=>e.relative()).sort((e, t)=>e.localeCompare(t));
2108
+ }).// onlyDirectories: true,
2109
+ // @see defaults https://www.npmjs.com/package/glob#dots
2110
+ // dot: false,
2111
+ filter((e)=>e.isDirectory()).map((e)=>e.relative()).sort((e, t)=>e.localeCompare(t));
1700
2112
  };
1701
2113
  let getInputDataLocal = async (e)=>{
1702
2114
  let { cwd: r = process.cwd(), ignore: s = [], source: p } = e, i = node_path.join(r, p), c = l$1({
@@ -1722,8 +2134,12 @@ let getInputDataLocal = async (e)=>{
1722
2134
  };
1723
2135
  };
1724
2136
 
1725
- let getInputDataRemote = async (r)=>new Promise((l, o)=>{
1726
- let { ignore: a = [], source: s } = r, n = s.startsWith("https://raw.githubusercontent.com"), i = "", c = node_https.request(s, n ? {} : {
2137
+ /**
2138
+ * Our github action `knitkode/koine/actions/i18n` creates a JSON file we can
2139
+ * read here, github serves it as text
2140
+ */ let getInputDataRemote = async (r)=>new Promise((l, o)=>{
2141
+ let { ignore: a = [], source: s } = r, n = s.startsWith(// import requestSync from "sync-request-curl";
2142
+ "https://raw.githubusercontent.com"), i = "", c = node_https.request(s, n ? {} : {
1727
2143
  headers: {
1728
2144
  Accept: "application/json"
1729
2145
  }
@@ -1770,14 +2186,19 @@ let o$1 = (e, t = {})=>{
1770
2186
  };
1771
2187
  };
1772
2188
  const summaryDataOptions = {};
1773
- let getSummaryData = (o, a, { translationFiles: i })=>{
2189
+ /**
2190
+ * Usually this is an absolute URL where to view the translation file
2191
+ */ let getSummaryData = (o, a, { translationFiles: i })=>{
1774
2192
  let { defaultLocale: f } = o, n = {};
1775
2193
  for(let e = 0; e < i.length; e++){
1776
2194
  let t = i[e], { locale: r } = t, l = s(a.sourceUrl, t);
1777
2195
  n[r] = n[r] || {}, n[r].files = n[r].files || [], n[r].files.push(l);
1778
2196
  }
1779
- return utils.forin(n = utils.objectSortByKeysMatching(n, f), (t, l)=>{
1780
- n[t].characters = utils.arraySum(l.files.map((e)=>e.characters)), 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)), n[t] = utils.objectSort(n[t]);
2197
+ return utils.forin(// sort by default locale
2198
+ n = utils.objectSortByKeysMatching(n, f), (t, l)=>{
2199
+ n[t].characters = utils.arraySum(l.files.map((e)=>e.characters)), // sort files by path
2200
+ 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
2201
+ n[t] = utils.objectSort(n[t]);
1781
2202
  }), n;
1782
2203
  };
1783
2204
 
@@ -1807,7 +2228,15 @@ let l = (e)=>{
1807
2228
  }, o = (t, e)=>"# Summary\n" + ("\n### By locale\n\n" + a(t, e) + "\n### By file path\n\n") + d(t);
1808
2229
  let generateSummary = (t, r)=>o(t, utils.objectMergeWithDefaults(summaryDataOptions, r));
1809
2230
 
1810
- let i = (t, e, o, i)=>[
2231
+ /**
2232
+ * @default process.cwd()
2233
+ */ /**
2234
+ * Relative to the given `cwd`.
2235
+ */ /**
2236
+ * Relative to the given `cwd`.
2237
+ */ /**
2238
+ * @default undefined
2239
+ */ let i = (t, e, o, i)=>[
1811
2240
  node_path.join(o, i),
1812
2241
  t.pretty ? JSON.stringify(e, null, 2) : JSON.stringify(e)
1813
2242
  ], n = (t, e, i, n)=>[
@@ -1819,8 +2248,14 @@ let writeSummary = async (r, e)=>{
1819
2248
  return m && await node.fsWrite(...i(r, e, o, m)), a && await node.fsWrite(...n(p, e, o, a)), e;
1820
2249
  };
1821
2250
 
1822
- let i18nCompiler = async (a)=>{
1823
- let { input: u, code: w, summary: s, ...n } = a, f = [], l = await getInputData(u), c = getConfig(l, n), h = getCodeData(c, w, l);
2251
+ /**
2252
+ * i18nCompiler async api
2253
+ *
2254
+ * @public
2255
+ */ let i18nCompiler = async (a)=>{
2256
+ 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
2257
+ // predictably return data
2258
+ h = getCodeData(c, w, l);
1824
2259
  return u?.write && f.push(writeInput(u.write, l)), w?.write && f.push(writeCode({
1825
2260
  ...w,
1826
2261
  ...w.write
@@ -1832,7 +2267,37 @@ let i18nCompiler = async (a)=>{
1832
2267
  input: l,
1833
2268
  code: h
1834
2269
  };
1835
- };
2270
+ }; // /**
2271
+ // * i18nCompiler sync api
2272
+ // *
2273
+ // * @public
2274
+ // */
2275
+ // export let i18nCompilerSync = (options: I18nCompilerOptions) => {
2276
+ // const {
2277
+ // input: optsInput,
2278
+ // code: optsCode,
2279
+ // summary: optsSummary,
2280
+ // ...configOptions
2281
+ // } = options;
2282
+ // const input = getInputDataSync(optsInput);
2283
+ // const config = getConfig(input, configOptions);
2284
+ // // it would be easy to make this optional but it's nice to be able to always
2285
+ // // predictably return data
2286
+ // const code = getCodeData(config, optsCode, input);
2287
+ // if (optsInput?.write) {
2288
+ // writeInputSync(optsInput.write, input);
2289
+ // }
2290
+ // if (optsCode?.write) {
2291
+ // writeCodeSync({ ...optsCode, ...optsCode.write }, code);
2292
+ // }
2293
+ // if (optsSummary?.write) {
2294
+ // writeSummarySync(
2295
+ // { ...optsSummary, ...optsSummary.write },
2296
+ // getSummaryData(config, optsSummary, input),
2297
+ // );
2298
+ // }
2299
+ // return { config, input, code };
2300
+ // };
1836
2301
 
1837
2302
  exports.generateRedirects = generateRedirects;
1838
2303
  exports.generateRewrites = generateRewrites;