@koine/i18n 2.0.0-beta.37 → 2.0.0-beta.39

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.
Files changed (88) hide show
  1. package/README.md +1 -0
  2. package/client/index.d.ts +1 -0
  3. package/client/interpolateTo.d.ts +3 -0
  4. package/generate/generateSource.d.ts +7 -0
  5. package/generate/generateSummary.d.ts +5 -11
  6. package/generate/getConfig.d.ts +2 -0
  7. package/generate/getFsData.d.ts +5 -9
  8. package/generate/getLocalesFolders.d.ts +4 -2
  9. package/generate/getRoutesData.d.ts +5 -0
  10. package/generate/sortObjectKeysMatching.d.ts +3 -0
  11. package/generate/source/adapter-js/config.d.ts +3 -0
  12. package/generate/source/adapter-js/defaultLocale.d.ts +3 -0
  13. package/generate/source/adapter-js/deriveLocalisedPathnames.d.ts +2 -0
  14. package/generate/source/adapter-js/index.d.ts +3 -0
  15. package/generate/source/adapter-js/isLocale.d.ts +2 -0
  16. package/generate/source/adapter-js/locales.d.ts +3 -0
  17. package/generate/source/adapter-js/pathnameToRouteId.d.ts +2 -0
  18. package/generate/source/adapter-js/routes.d.ts +3 -0
  19. package/generate/source/adapter-js/routesSlim.d.ts +3 -0
  20. package/generate/source/adapter-js/to.d.ts +3 -0
  21. package/generate/source/adapter-js/toFns.d.ts +3 -0
  22. package/generate/source/adapter-js/toFormat.d.ts +3 -0
  23. package/generate/source/adapter-js/types-translations.d.ts +5 -0
  24. package/generate/source/adapter-js/types.d.ts +3 -0
  25. package/generate/source/adapter-next/index.d.ts +3 -0
  26. package/generate/source/adapter-next/next-redirects.d.ts +17 -0
  27. package/generate/source/adapter-next/next-rewrites.d.ts +19 -0
  28. package/generate/source/adapter-next/transformPathname.d.ts +2 -0
  29. package/generate/source/adapter-next/useCurrentLocalisedPathnames.d.ts +2 -0
  30. package/generate/source/adapter-next/useRouteId.d.ts +2 -0
  31. package/generate/source/adapter-next/withI18n.d.ts +3 -0
  32. package/generate/source/adapter-next-translate/DynamicNamespaces.d.ts +2 -0
  33. package/generate/source/adapter-next-translate/T.d.ts +2 -0
  34. package/generate/source/adapter-next-translate/TransText.d.ts +2 -0
  35. package/generate/source/adapter-next-translate/getT.d.ts +2 -0
  36. package/generate/source/adapter-next-translate/index.d.ts +3 -0
  37. package/generate/source/adapter-next-translate/nextTranslateI18n.d.ts +3 -0
  38. package/generate/source/adapter-next-translate/useLocale.d.ts +3 -0
  39. package/generate/source/adapter-next-translate/useT.d.ts +2 -0
  40. package/generate/source/adapter-next-translate/useTo.d.ts +2 -0
  41. package/generate/types.d.ts +57 -14
  42. package/generate/write.d.ts +13 -0
  43. package/generate/writeSource.d.ts +10 -0
  44. package/generate/writeSourceCompiled.d.ts +8 -0
  45. package/generate/writeSummary.d.ts +4 -6
  46. package/generate.cjs.d.ts +1 -0
  47. package/generate.cjs.default.js +1 -0
  48. package/generate.cjs.js +67 -0
  49. package/generate.cjs.mjs +2 -0
  50. package/generate.d.ts +10 -0
  51. package/generate.esm.js +35 -0
  52. package/index.cjs.d.ts +1 -0
  53. package/index.cjs.default.js +1 -0
  54. package/index.cjs.js +12 -0
  55. package/index.cjs.mjs +2 -0
  56. package/index.d.ts +3 -5
  57. package/index.esm.js +7 -0
  58. package/package.json +31 -49
  59. package/routeHasDynamicPortion.cjs.js +8 -0
  60. package/routeHasDynamicPortion.esm.js +5 -0
  61. package/shared/formatRoutePathname.d.ts +3 -0
  62. package/shared/index.d.ts +2 -0
  63. package/shared/routeHasDynamicPortion.d.ts +1 -0
  64. package/summary.md +10 -0
  65. package/types.d.ts +1 -15
  66. package/typesRouting.d.ts +32 -0
  67. package/createTo.d.ts +0 -3
  68. package/createTo.js +0 -18
  69. package/generate/generateSummary.js +0 -139
  70. package/generate/generateTypes.d.ts +0 -5
  71. package/generate/generateTypes.js +0 -133
  72. package/generate/getFsData.js +0 -63
  73. package/generate/getLocalesFolders.js +0 -29
  74. package/generate/index.d.ts +0 -7
  75. package/generate/index.js +0 -7
  76. package/generate/types.js +0 -1
  77. package/generate/writeSummary.js +0 -35
  78. package/generate/writeTypes.d.ts +0 -8
  79. package/generate/writeTypes.js +0 -29
  80. package/index.js +0 -5
  81. package/isDynamicRouteId.d.ts +0 -3
  82. package/isDynamicRouteId.js +0 -5
  83. package/isStaticRouteId.d.ts +0 -3
  84. package/isStaticRouteId.js +0 -5
  85. package/routeHasDynamicPortion.d.ts +0 -2
  86. package/routeHasDynamicPortion.js +0 -4
  87. package/types.js +0 -1
  88. package/typings.d.ts +0 -38
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @koine/i18n
@@ -0,0 +1 @@
1
+ export { interpolateTo } from "./interpolateTo";
@@ -0,0 +1,3 @@
1
+ import type { DynamicParams } from "../typesRouting";
2
+ export declare function interpolateTo<TRouteId extends string>(value: TRouteId): string;
3
+ export declare function interpolateTo<TRouteId extends string>(value: TRouteId, params: DynamicParams<TRouteId>): string;
@@ -0,0 +1,7 @@
1
+ import type { I18nGenerate } from "./types";
2
+ export type I18nGenerateSourceConfig = Pick<I18nGenerate.Config, "defaultLocale" | "hideDefaultLocaleInUrl"> & {
3
+ adapter: I18nGenerate.BuiltinAdapters;
4
+ outputFiles?: Partial<{}>;
5
+ };
6
+ export type I18nGenerateSourceOptions = I18nGenerate.Data & I18nGenerateSourceConfig;
7
+ export declare function generateSource(options: I18nGenerateSourceOptions): Promise<I18nGenerate.SourceFile[]>;
@@ -1,21 +1,15 @@
1
- import type { I18nIndexedFile } from "./types.js";
2
- export type I18nGenerateSummaryConfig = {
3
- defaultLocale: string;
1
+ import type { I18nGenerate } from "./types";
2
+ export type I18nGenerateSummaryConfig = Pick<I18nGenerate.Config, "defaultLocale"> & {
4
3
  sourceUrl: string;
5
4
  };
6
- type Locale = string & {
7
- branded: true;
8
- };
9
- type I18nGenerateSummaryOptions = I18nGenerateSummaryConfig & {
10
- files: I18nIndexedFile[];
11
- };
12
- type I18nSummary = Record<Locale, {
5
+ type I18nGenerateSummaryOptions = I18nGenerate.Data & I18nGenerateSummaryConfig;
6
+ type I18nSummary = Record<I18nGenerate.Locale, {
13
7
  words: number;
14
8
  characters: number;
15
9
  files: I18nSummaryFile[];
16
10
  }>;
17
11
  type I18nSummaryFile = {
18
- locale: Locale;
12
+ locale: I18nGenerate.Locale;
19
13
  path: string;
20
14
  url: string;
21
15
  words: number;
@@ -0,0 +1,2 @@
1
+ import type { I18nGenerate } from "./types";
2
+ export declare function getConfig(options: Partial<I18nGenerate.Config>): I18nGenerate.Config;
@@ -1,10 +1,6 @@
1
- import type { I18nIndexedFile, I18nIndexedLocale } from "./types.js";
2
- type I18nGetFsDataOutput = {
3
- locales: I18nIndexedLocale[];
4
- files: I18nIndexedFile[];
5
- };
6
- export declare function getFsData(options: {
1
+ import type { I18nGenerate } from "./types";
2
+ export type GetFsDataOptions = Partial<I18nGenerate.Config> & {
7
3
  cwd: string;
8
- onlyFilesForLocales?: string[];
9
- }): Promise<I18nGetFsDataOutput>;
10
- export {};
4
+ ignore?: string[];
5
+ };
6
+ export declare function getFsData(options: GetFsDataOptions): Promise<I18nGenerate.Data>;
@@ -1,4 +1,6 @@
1
- import type { I18nIndexedLocale } from "./types.js";
1
+ import type { I18nGenerate } from "./types";
2
2
  export declare function getLocalesFolders(options: {
3
3
  cwd: string;
4
- }): Promise<I18nIndexedLocale[]>;
4
+ ignore?: string[];
5
+ defaultLocale?: string;
6
+ }): Promise<I18nGenerate.LocalesFolders[]>;
@@ -0,0 +1,5 @@
1
+ import type { I18nGenerate } from "./types";
2
+ export declare const getRoutesData: (options: Pick<I18nGenerate.Config, "defaultLocale"> & {
3
+ defaultLocale: I18nGenerate.Locale;
4
+ files: I18nGenerate.TranslationFile[];
5
+ }) => I18nGenerate.DataRoutes;
@@ -0,0 +1,3 @@
1
+ export declare const sortObjectKeysMatching: <T extends object>(data: T, keyMatch: keyof T) => {
2
+ [k: string]: any;
3
+ };
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const adapter: I18nGenerate.Adpater;
3
+ export default adapter;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ export type I18nGenerateTypesConfig = Pick<I18nGenerate.Config, "defaultLocale">;
3
+ type I18nGenerateTypesOptions = I18nGenerate.Data & I18nGenerateTypesConfig;
4
+ export declare function generateTypesTranslations(options: I18nGenerateTypesOptions): string;
5
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const adapter: I18nGenerate.Adpater;
3
+ export default adapter;
@@ -0,0 +1,17 @@
1
+ import type { Redirect as _Redirect } from "next/dist/lib/load-custom-routes";
2
+ import type { I18nGenerate } from "../../types";
3
+ type Redirect = Omit<_Redirect, "locale"> & {
4
+ locale?: boolean;
5
+ };
6
+ export declare function getPathRedirect(arg: {
7
+ localeSource?: I18nGenerate.Locale;
8
+ localeDestination?: I18nGenerate.Locale;
9
+ route: I18nGenerate.DataRoute;
10
+ template: string;
11
+ pathname: string;
12
+ localeParam?: string;
13
+ permanent?: boolean;
14
+ }): Redirect | undefined;
15
+ export declare function getRedirects(data: I18nGenerate.Data, localeParam?: string, permanent?: boolean): Redirect[];
16
+ declare const _default: (data: I18nGenerate.Data) => string;
17
+ export default _default;
@@ -0,0 +1,19 @@
1
+ import type { Rewrite as _Rewrite } from "next/dist/lib/load-custom-routes";
2
+ import type { I18nGenerate } from "../../types";
3
+ type Rewrite = Omit<_Rewrite, "locale"> & {
4
+ locale?: boolean;
5
+ };
6
+ export declare function getPathRewrite(arg: {
7
+ localeSource?: I18nGenerate.Locale;
8
+ localeDestination?: I18nGenerate.Locale;
9
+ route: I18nGenerate.DataRoute;
10
+ template: string;
11
+ pathname: string;
12
+ localeParam?: string;
13
+ }): {
14
+ source: string;
15
+ destination: string;
16
+ } | undefined;
17
+ export declare function getRewrites(data: I18nGenerate.Data, localeParam?: string): Rewrite[];
18
+ declare const _default: (data: I18nGenerate.Data) => string;
19
+ export default _default;
@@ -0,0 +1,2 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ export declare function transformPathname(route: I18nGenerate.DataRoute, rawPathnameOrTemplate: string): string;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const adapter: I18nGenerate.Adpater;
3
+ export default adapter;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ import type { I18nGenerate } from "../../types";
2
+ declare const _default: (data: I18nGenerate.Data) => string;
3
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => string;
2
+ export default _default;
@@ -1,14 +1,57 @@
1
- export type I18nLocale = string & {
2
- branded: true;
3
- };
4
- export type I18nIndexedFile = {
5
- path: string;
6
- locale: I18nLocale;
7
- data: {
8
- [key: string]: any;
9
- };
10
- };
11
- export type I18nIndexedLocale = {
12
- path: string;
13
- code: I18nLocale;
14
- };
1
+ export declare namespace I18nGenerate {
2
+ type Config = {
3
+ locales: Locale[];
4
+ defaultLocale: Locale;
5
+ hideDefaultLocaleInUrl: boolean;
6
+ };
7
+ type Locale = string;
8
+ type RouteId = string;
9
+ type RoutePathname = string;
10
+ type TranslationFile = {
11
+ path: string;
12
+ locale: Locale;
13
+ data: {
14
+ [key: string]: any;
15
+ };
16
+ };
17
+ type LocalesFolders = {
18
+ path: string;
19
+ code: Locale;
20
+ };
21
+ type DataRoutes = Record<RouteId, DataRoute>;
22
+ type DataRoute = {
23
+ id: RouteId;
24
+ typeName: string;
25
+ pathnames: Record<Locale, RoutePathname>;
26
+ optimizedPathnames: string | Record<Locale, RoutePathname>;
27
+ params: undefined | DataRoutesParams;
28
+ paramsNames: undefined | string[];
29
+ dynamic: boolean;
30
+ wildcard: boolean;
31
+ inWildcard: boolean;
32
+ };
33
+ type DataRoutesParams = Record<string, "string" | "number" | "stringOrNumber">;
34
+ type Data = {
35
+ locales: Locale[];
36
+ defaultLocale: Locale;
37
+ hideDefaultLocaleInUrl: boolean;
38
+ localesFolders: LocalesFolders[];
39
+ files: TranslationFile[];
40
+ routes: DataRoutes;
41
+ };
42
+ type BuiltinAdapters = "js" | "next" | "next-translate";
43
+ type Adpater = (data: Data) => {
44
+ dependsOn?: BuiltinAdapters[];
45
+ files: AdpaterFiles;
46
+ };
47
+ type AdpaterFiles = AdpaterFile[];
48
+ type AdpaterFile = {
49
+ name: string;
50
+ ext: "ts" | "tsx" | "mjs" | "js" | "json";
51
+ fn: (data: Data) => string;
52
+ index?: boolean;
53
+ };
54
+ type SourceFile = Omit<AdpaterFile, "fn"> & {
55
+ content: string;
56
+ };
57
+ }
@@ -0,0 +1,13 @@
1
+ import { type GetFsDataOptions } from "./getFsData";
2
+ import type { I18nGenerate } from "./types";
3
+ import { type WriteSourceOptions } from "./writeSource";
4
+ import { type WriteSummaryOptions } from "./writeSummary";
5
+ type SharedOptions = Pick<I18nGenerate.Config, "defaultLocale" | "hideDefaultLocaleInUrl"> & GetFsDataOptions;
6
+ type WithOptionalSharedOptions<T extends {
7
+ [key: string]: any;
8
+ }> = Partial<Pick<T, keyof SharedOptions>> & Omit<T, keyof SharedOptions>;
9
+ export declare function write(options: SharedOptions & {
10
+ source: WithOptionalSharedOptions<WriteSourceOptions>;
11
+ summary: WithOptionalSharedOptions<WriteSummaryOptions>;
12
+ }): Promise<I18nGenerate.Data>;
13
+ export {};
@@ -0,0 +1,10 @@
1
+ import { type I18nGenerateSourceConfig } from "./generateSource";
2
+ import { I18nGenerate } from "./types";
3
+ export type WriteSourceOptions = {
4
+ cwd: string;
5
+ output: string;
6
+ skipTsCompile?: boolean;
7
+ skipGitignore?: boolean;
8
+ skipTranslations?: boolean;
9
+ } & I18nGenerateSourceConfig;
10
+ export declare function writeSource(options: WriteSourceOptions): Promise<I18nGenerate.Data>;
@@ -0,0 +1,8 @@
1
+ import * as ts from "typescript";
2
+ import { type I18nGenerateSourceConfig, generateSource } from "./generateSource";
3
+ export type WriteSourceOptions = {
4
+ cwd: string;
5
+ output: string;
6
+ outputTs?: Partial<Record<keyof Awaited<ReturnType<typeof generateSource>>, string>>;
7
+ } & I18nGenerateSourceConfig;
8
+ export declare function writeSourceCompiled(options: WriteSourceOptions, relativePaths: string[], tsOptions?: ts.CompilerOptions): Promise<void>;
@@ -1,9 +1,7 @@
1
- import { type I18nGenerateSummaryConfig } from "./generateSummary.js";
2
- export declare function writeSummary(options: {
1
+ import { type I18nGenerateSummaryConfig } from "./generateSummary";
2
+ export type WriteSummaryOptions = {
3
3
  cwd: string;
4
4
  outputJson: string;
5
5
  outputMarkdown: string;
6
- } & I18nGenerateSummaryConfig): Promise<{
7
- locales: import("./types").I18nIndexedLocale[];
8
- files: import("./types").I18nIndexedFile[];
9
- }>;
6
+ } & I18nGenerateSummaryConfig;
7
+ export declare function writeSummary(options: WriteSummaryOptions): Promise<import("./types").I18nGenerate.Data>;
@@ -0,0 +1 @@
1
+ export * from "./generate";
@@ -0,0 +1 @@
1
+ exports._default = require('./generate.cjs.js').default;
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var utils = require('@koine/utils');
6
+ var promises = require('node:fs/promises');
7
+ var node_path = require('node:path');
8
+ var glob = require('glob');
9
+ var routeHasDynamicPortion = require('./routeHasDynamicPortion.cjs.js');
10
+ var node = require('@koine/node');
11
+ var t$1 = require('typescript');
12
+
13
+ function _interopNamespace(e) {
14
+ if (e && e.__esModule) return e;
15
+ var n = Object.create(null);
16
+ if (e) {
17
+ Object.keys(e).forEach(function (k) {
18
+ if (k !== 'default') {
19
+ var d = Object.getOwnPropertyDescriptor(e, k);
20
+ Object.defineProperty(n, k, d.get ? d : {
21
+ enumerable: true,
22
+ get: function () { return e[k]; }
23
+ });
24
+ }
25
+ });
26
+ }
27
+ n["default"] = e;
28
+ return Object.freeze(n);
29
+ }
30
+
31
+ var t__namespace = /*#__PURE__*/_interopNamespace(t$1);
32
+
33
+ let e=e=>{let t="";return e.filter(e=>e.index).sort((e,t)=>e.name.localeCompare(t.name)).forEach(e=>{t+=`export * from "./${e.name}";
34
+ `;}),t},t=async(e,a,n=[])=>{let{dependsOn:r,files:o}=(await (function (t) { return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(t)); }); })(`./source/adapter-${a}`).then(e=>e.default))(e);return n=n.concat(o),r&&await Promise.all(r.map(async a=>{n=n.concat(await t(e,a));})),n};async function generateSource(a){let{adapter:n,outputFiles:r}=a,o=(await t(a,n)).map(e=>{let{fn:t,...n}=e,o=r?.[n.name]||n.name;return {...n,name:o,content:t(a)}});return o.push({name:"index",ext:"ts",content:e(o)}),o}
35
+
36
+ const sortObjectKeysMatching=(e,t)=>Object.fromEntries(Object.entries(e).sort(([e],[o])=>e===t?-1:e.localeCompare(o)));
37
+
38
+ async function generateSummary(l){let o,a;let n=function(l){let{files:o,defaultLocale:a}=l,n={};for(let t=0;t<o.length;t++){let e=o[t],{locale:r}=e,a=function(t,e){let{locale:r,path:l}=e,o=`${t.sourceUrl}/${r}/${l}`,a=function t(e,r={}){let l="";if(e&&"string"==typeof e)l+=" "+e.trim();else if(Array.isArray(e))for(let o=0;o<e.length;o++)l+=t(e[o],r);else if("object"==typeof e)for(let o in e)l+=t(e[o],r);return l}(e.data),n=a.split(" ").filter(Boolean).length;return {characters:a.split(" ").filter(Boolean).join("").length,locale:r,path:l,url:o,words:n}}(l,e);n[r]=n[r]||{},n[r].files=n[r].files||[],n[r].files.push(a);}return utils.forin(n=sortObjectKeysMatching(n,a),(e,r)=>{n[e].characters=utils.arraySum(r.files.map(t=>t.characters)),n[e].files=n[e].files.sort((t,e)=>t.path.localeCompare(e.path)),n[e].words=utils.arraySum(r.files.map(t=>t.words)),n[e]=Object.fromEntries(Object.entries(n[e]).sort());}),n}(l),h="# Summary\n\n### By locale\n\n"+(o="",a="",utils.forin(n,(t,e)=>{let{files:r,characters:o,words:n}=e,h=`${l.sourceUrl}/${t}`;a+=`<tr><th><a href="${h}">${t}</a></th><td>${r.length}</td><td>${n}</td><td>${o}</td></tr>`;}),o+=`<table><thead><tr><th>locale</th><th>files</th><th>words</th><th>chars</th></tr></thead><tbody>${a}</tbody></table>
39
+ `)+"\n### By file path\n\n"+function(t,r){let l;let o=(l={},utils.forin(r,(t,e)=>{let{files:r}=e;for(let e=0;e<r.length;e++){let o=r[e],{path:a}=o;l[a]=l[a]||{},l[a][t]=o;}}),l=Object.fromEntries(Object.entries(l).sort())),a="",n="",h=[],s='style="border-right:1px solid grey"';return utils.forin(o,(t,r)=>{n+=`<tr><td ${s}>${t}</td>`,utils.forin(r,(t,e)=>{let{characters:r,words:l,url:o}=e;h.includes(t)||h.push(t),n+=`<td><a href="${o}">${t}</a></td><td>${l}</td><td ${s}>${r}</td>`;}),n+="</tr>";}),a+=`<table><thead><tr><th ${s}>file path</th>`+h.map(()=>`<th>lang</th><th>words</th><th ${s}>chars</th>`).join("")+`</tr></thead><tbody>${n}</tbody></table>
40
+ `}(0,n);return {data:n,md:h}}
41
+
42
+ function getConfig(e){return {locales:e.locales||["en"],defaultLocale:e.defaultLocale||"en",hideDefaultLocaleInUrl:!!e.hideDefaultLocaleInUrl}}
43
+
44
+ async function getLocalesFolders(r){let{cwd:t,ignore:a=[],defaultLocale:i}=r;return (await glob.glob("*",{cwd:t,withFileTypes:!0,ignore:[...a,"node_modules/**"]})).filter(e=>e.isDirectory()).map(e=>e.relative()).sort((e,o)=>e===i?-1:e.localeCompare(o)).map(o=>({path:node_path.join(t,o),code:o}))}
45
+
46
+ let l=e=>e.replace(/\.index$/,""),m=e=>routeHasDynamicPortion.formatRoutePathname(e.replace(/\*/g,"").replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g,(e,t)=>`[${t.trim()}]`)),o=r=>utils.capitalize(utils.changeCaseCamel(r)),p=(e,t,r)=>{let a=e[r].pathnames[t];if(a.startsWith("/^")){let i=RegExp("^\\/\\^");a=a.replace(i,"");let n=r.split(".").slice(0,-1).join(".");if(n)a=p(e,t,n)+a;else throw Error("Used a parent route token reference without a matching parent route")}return a},h=e=>{utils.forin(e,(t,a)=>{utils.forin(a.pathnames,r=>{e[t].pathnames[r]=p(e,r,t);});});},c=e=>{let t=e.match(/\[.*?\]/g);if(t){let e=t.map(e=>e.slice(1,-1).trim()),r=e.reduce((e,t)=>(e[t]="stringOrNumber",e),{});return {paramsNames:e,params:r}}return {}},f=(e,t)=>{let{defaultLocale:r}=e;for(let e in t){let a=t[e].pathnames,i=a[r],n={};for(let e in a){let t=a[e];t!==i&&(n[e]=t);}Object.keys(n).length>=1?(n[r]=i,t[e].optimizedPathnames=n):t[e].optimizedPathnames=i;}};const getRoutesData=e=>{let{defaultLocale:t,files:r}=e,i=[],p={};for(let e=0;e<r.length;e++){let{path:h,locale:f,data:d}=r[e];if("~.json"===h){let e=utils.objectFlat(d,".");for(let r in e){let a=e[r],h=l(r);if(!p[h]){p[h]=p[h]||{};let e=o(h),{paramsNames:t,params:r}=c(h),s=a.includes("*");s&&i.push(h),p[h].id=h,p[h].typeName=e,p[h].paramsNames=t,p[h].params=r,p[h].dynamic=routeHasDynamicPortion.routeHasDynamicPortion(h),p[h].wildcard=s;}p[h].pathnames=p[h].pathnames||{},p[h].pathnames[f]=m(a),p[h].pathnames=sortObjectKeysMatching(p[h].pathnames,t);}}}if(h(p),f(e,p),i.length)for(let e in p)p[e].inWildcard=i.some(t=>e.startsWith(t)&&t!==e);return Object.fromEntries(Object.entries(p).sort())};
47
+
48
+ async function getFsData(r){let{cwd:i,ignore:m}=r,p=await getLocalesFolders({cwd:i,ignore:m,defaultLocale:r.defaultLocale}),s=p.map(a=>a.code),c=r.defaultLocale||s[0],f=[];return await Promise.all(p.map(async o=>{let l=await glob.glob("**/*.json",{cwd:o.path});await Promise.all(l.map(async e=>{let l=node_path.join(o.path,e),r=await promises.readFile(l,"utf8");r&&f.push({path:e,data:JSON.parse(r),locale:o.code});}));})),{locales:s,defaultLocale:c,hideDefaultLocaleInUrl:!!r.hideDefaultLocaleInUrl,localesFolders:p,files:f,routes:getRoutesData({defaultLocale:c,files:f})}}
49
+
50
+ async function writeSourceCompiled(o,i,s){let{cwd:r,output:n}=o,a=Array.from(i).filter(e=>e.endsWith(".ts")||e.endsWith(".tsx")).map(t=>node_path.join(r,n,t)),l={noEmitOnError:!0,noImplicitAny:!0,declaration:!0,target:t__namespace.ScriptTarget.ESNext,module:t__namespace.ModuleKind.CommonJS,resolveJsonModule:!0,allowJs:!1,esModuleInterop:!0,jsx:t__namespace.JsxEmit.ReactJSX,outDir:node_path.join(r,n),skipLibCheck:!0,noEmitHelpers:!0,importHelpers:!0,...s||{}},m=t__namespace.createProgram(a,l),c=m.emit();t__namespace.getPreEmitDiagnostics(m).concat(c.diagnostics).forEach(e=>{if(e.file){let{line:o,character:i}=t__namespace.getLineAndCharacterOfPosition(e.file,e.start),s=t__namespace.flattenDiagnosticMessageText(e.messageText,"\n");console.log(`${e.file.fileName} (${o+1},${i+1}): ${s}`);}else console.log(t__namespace.flattenDiagnosticMessageText(e.messageText,"\n"));});}
51
+
52
+ async function writeSource(r){let{cwd:n,output:m,skipTsCompile:d,skipGitignore:p,skipTranslations:c,...l}=r,f=await getFsData({...r,ignore:[m+"/**"]}),w=await generateSource({...f,...l}),u=new Set,y=new Set;return await Promise.all(w.map(async({name:r,ext:t,content:o})=>{let i=`${r}.${t}`,s=node_path.join(n,m,i);await node.fsWrite(s,o),u.add(i);})),d||(await writeSourceCompiled(r,Array.from(u).filter(r=>r.endsWith(".ts")||r.endsWith(".tsx"))),Array.from(u).forEach(r=>{u.add(r.replace(".tsx",".js")),u.add(r.replace(".ts",".js")),u.add(r.replace(".ts",".d.ts"));})),c||(await s(r,f)).forEach(r=>{y.add(r);}),p||await node.fsWrite(node_path.join(n,m,".gitignore"),Array.from(new Set([...y,...u])).sort().map(r=>`/${r}`).join(`
53
+ `)),f}async function s(a,t){let{cwd:o,output:i}=a;return await Promise.all(t.localesFolders.map(async({path:a,code:t})=>{let s=node_path.join("translations",t);return await promises.cp(a,node_path.join(o,i,s),{recursive:!0,force:!0,preserveTimestamps:!0}),s}))}
54
+
55
+ async function writeSummary(m){let{cwd:o,outputJson:e,outputMarkdown:n,sourceUrl:f}=m,p=await getFsData(m),u=await generateSummary({...p,sourceUrl:f});return await node.fsWrite(node_path.join(o,e),JSON.stringify(u.data,null,2)),await node.fsWrite(node_path.join(o,n),u.md),p}
56
+
57
+ async function write(e){let i=await getFsData({...e,ignore:[e.source.output]});return await Promise.all([writeSource({...e,...i,...e.source}),writeSummary({...e,...i,...e.summary})]),i}
58
+
59
+ exports.generateSource = generateSource;
60
+ exports.generateSummary = generateSummary;
61
+ exports.getConfig = getConfig;
62
+ exports.getFsData = getFsData;
63
+ exports.getLocalesFolders = getLocalesFolders;
64
+ exports.getRoutesData = getRoutesData;
65
+ exports.write = write;
66
+ exports.writeSource = writeSource;
67
+ exports.writeSummary = writeSummary;
@@ -0,0 +1,2 @@
1
+ export * from './generate.cjs.js';
2
+ export { _default as default } from './generate.cjs.default.js';
package/generate.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export { generateSource } from "./generate/generateSource";
2
+ export { generateSummary } from "./generate/generateSummary";
3
+ export { getConfig } from "./generate/getConfig";
4
+ export { getFsData } from "./generate/getFsData";
5
+ export { getRoutesData } from "./generate/getRoutesData";
6
+ export { getLocalesFolders } from "./generate/getLocalesFolders";
7
+ export { write } from "./generate/write";
8
+ export { writeSource } from "./generate/writeSource";
9
+ export { writeSummary } from "./generate/writeSummary";
10
+ export type { I18nGenerate } from "./generate/types";
@@ -0,0 +1,35 @@
1
+ import { forin, arraySum, objectFlat, capitalize, changeCaseCamel } from '@koine/utils';
2
+ import { readFile, cp } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { glob } from 'glob';
5
+ import { r as routeHasDynamicPortion, f as formatRoutePathname } from './routeHasDynamicPortion.esm.js';
6
+ import { fsWrite } from '@koine/node';
7
+ import * as t$1 from 'typescript';
8
+
9
+ let e=e=>{let t="";return e.filter(e=>e.index).sort((e,t)=>e.name.localeCompare(t.name)).forEach(e=>{t+=`export * from "./${e.name}";
10
+ `;}),t},t=async(e,a,n=[])=>{let{dependsOn:r,files:o}=(await import(`./source/adapter-${a}`).then(e=>e.default))(e);return n=n.concat(o),r&&await Promise.all(r.map(async a=>{n=n.concat(await t(e,a));})),n};async function generateSource(a){let{adapter:n,outputFiles:r}=a,o=(await t(a,n)).map(e=>{let{fn:t,...n}=e,o=r?.[n.name]||n.name;return {...n,name:o,content:t(a)}});return o.push({name:"index",ext:"ts",content:e(o)}),o}
11
+
12
+ const sortObjectKeysMatching=(e,t)=>Object.fromEntries(Object.entries(e).sort(([e],[o])=>e===t?-1:e.localeCompare(o)));
13
+
14
+ async function generateSummary(l){let o,a;let n=function(l){let{files:o,defaultLocale:a}=l,n={};for(let t=0;t<o.length;t++){let e=o[t],{locale:r}=e,a=function(t,e){let{locale:r,path:l}=e,o=`${t.sourceUrl}/${r}/${l}`,a=function t(e,r={}){let l="";if(e&&"string"==typeof e)l+=" "+e.trim();else if(Array.isArray(e))for(let o=0;o<e.length;o++)l+=t(e[o],r);else if("object"==typeof e)for(let o in e)l+=t(e[o],r);return l}(e.data),n=a.split(" ").filter(Boolean).length;return {characters:a.split(" ").filter(Boolean).join("").length,locale:r,path:l,url:o,words:n}}(l,e);n[r]=n[r]||{},n[r].files=n[r].files||[],n[r].files.push(a);}return forin(n=sortObjectKeysMatching(n,a),(e,r)=>{n[e].characters=arraySum(r.files.map(t=>t.characters)),n[e].files=n[e].files.sort((t,e)=>t.path.localeCompare(e.path)),n[e].words=arraySum(r.files.map(t=>t.words)),n[e]=Object.fromEntries(Object.entries(n[e]).sort());}),n}(l),h="# Summary\n\n### By locale\n\n"+(o="",a="",forin(n,(t,e)=>{let{files:r,characters:o,words:n}=e,h=`${l.sourceUrl}/${t}`;a+=`<tr><th><a href="${h}">${t}</a></th><td>${r.length}</td><td>${n}</td><td>${o}</td></tr>`;}),o+=`<table><thead><tr><th>locale</th><th>files</th><th>words</th><th>chars</th></tr></thead><tbody>${a}</tbody></table>
15
+ `)+"\n### By file path\n\n"+function(t,r){let l;let o=(l={},forin(r,(t,e)=>{let{files:r}=e;for(let e=0;e<r.length;e++){let o=r[e],{path:a}=o;l[a]=l[a]||{},l[a][t]=o;}}),l=Object.fromEntries(Object.entries(l).sort())),a="",n="",h=[],s='style="border-right:1px solid grey"';return forin(o,(t,r)=>{n+=`<tr><td ${s}>${t}</td>`,forin(r,(t,e)=>{let{characters:r,words:l,url:o}=e;h.includes(t)||h.push(t),n+=`<td><a href="${o}">${t}</a></td><td>${l}</td><td ${s}>${r}</td>`;}),n+="</tr>";}),a+=`<table><thead><tr><th ${s}>file path</th>`+h.map(()=>`<th>lang</th><th>words</th><th ${s}>chars</th>`).join("")+`</tr></thead><tbody>${n}</tbody></table>
16
+ `}(0,n);return {data:n,md:h}}
17
+
18
+ function getConfig(e){return {locales:e.locales||["en"],defaultLocale:e.defaultLocale||"en",hideDefaultLocaleInUrl:!!e.hideDefaultLocaleInUrl}}
19
+
20
+ async function getLocalesFolders(r){let{cwd:t,ignore:a=[],defaultLocale:i}=r;return (await glob("*",{cwd:t,withFileTypes:!0,ignore:[...a,"node_modules/**"]})).filter(e=>e.isDirectory()).map(e=>e.relative()).sort((e,o)=>e===i?-1:e.localeCompare(o)).map(o=>({path:join(t,o),code:o}))}
21
+
22
+ let l=e=>e.replace(/\.index$/,""),m=e=>formatRoutePathname(e.replace(/\*/g,"").replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g,(e,t)=>`[${t.trim()}]`)),o=r=>capitalize(changeCaseCamel(r)),p=(e,t,r)=>{let a=e[r].pathnames[t];if(a.startsWith("/^")){let i=RegExp("^\\/\\^");a=a.replace(i,"");let n=r.split(".").slice(0,-1).join(".");if(n)a=p(e,t,n)+a;else throw Error("Used a parent route token reference without a matching parent route")}return a},h=e=>{forin(e,(t,a)=>{forin(a.pathnames,r=>{e[t].pathnames[r]=p(e,r,t);});});},c=e=>{let t=e.match(/\[.*?\]/g);if(t){let e=t.map(e=>e.slice(1,-1).trim()),r=e.reduce((e,t)=>(e[t]="stringOrNumber",e),{});return {paramsNames:e,params:r}}return {}},f=(e,t)=>{let{defaultLocale:r}=e;for(let e in t){let a=t[e].pathnames,i=a[r],n={};for(let e in a){let t=a[e];t!==i&&(n[e]=t);}Object.keys(n).length>=1?(n[r]=i,t[e].optimizedPathnames=n):t[e].optimizedPathnames=i;}};const getRoutesData=e=>{let{defaultLocale:t,files:r}=e,i=[],p={};for(let e=0;e<r.length;e++){let{path:h,locale:f,data:d}=r[e];if("~.json"===h){let e=objectFlat(d,".");for(let r in e){let a=e[r],h=l(r);if(!p[h]){p[h]=p[h]||{};let e=o(h),{paramsNames:t,params:r}=c(h),s=a.includes("*");s&&i.push(h),p[h].id=h,p[h].typeName=e,p[h].paramsNames=t,p[h].params=r,p[h].dynamic=routeHasDynamicPortion(h),p[h].wildcard=s;}p[h].pathnames=p[h].pathnames||{},p[h].pathnames[f]=m(a),p[h].pathnames=sortObjectKeysMatching(p[h].pathnames,t);}}}if(h(p),f(e,p),i.length)for(let e in p)p[e].inWildcard=i.some(t=>e.startsWith(t)&&t!==e);return Object.fromEntries(Object.entries(p).sort())};
23
+
24
+ async function getFsData(r){let{cwd:i,ignore:m}=r,p=await getLocalesFolders({cwd:i,ignore:m,defaultLocale:r.defaultLocale}),s=p.map(a=>a.code),c=r.defaultLocale||s[0],f=[];return await Promise.all(p.map(async o=>{let l=await glob("**/*.json",{cwd:o.path});await Promise.all(l.map(async e=>{let l=join(o.path,e),r=await readFile(l,"utf8");r&&f.push({path:e,data:JSON.parse(r),locale:o.code});}));})),{locales:s,defaultLocale:c,hideDefaultLocaleInUrl:!!r.hideDefaultLocaleInUrl,localesFolders:p,files:f,routes:getRoutesData({defaultLocale:c,files:f})}}
25
+
26
+ async function writeSourceCompiled(o,i,s){let{cwd:r,output:n}=o,a=Array.from(i).filter(e=>e.endsWith(".ts")||e.endsWith(".tsx")).map(t=>join(r,n,t)),l={noEmitOnError:!0,noImplicitAny:!0,declaration:!0,target:t$1.ScriptTarget.ESNext,module:t$1.ModuleKind.CommonJS,resolveJsonModule:!0,allowJs:!1,esModuleInterop:!0,jsx:t$1.JsxEmit.ReactJSX,outDir:join(r,n),skipLibCheck:!0,noEmitHelpers:!0,importHelpers:!0,...s||{}},m=t$1.createProgram(a,l),c=m.emit();t$1.getPreEmitDiagnostics(m).concat(c.diagnostics).forEach(e=>{if(e.file){let{line:o,character:i}=t$1.getLineAndCharacterOfPosition(e.file,e.start),s=t$1.flattenDiagnosticMessageText(e.messageText,"\n");console.log(`${e.file.fileName} (${o+1},${i+1}): ${s}`);}else console.log(t$1.flattenDiagnosticMessageText(e.messageText,"\n"));});}
27
+
28
+ async function writeSource(r){let{cwd:n,output:m,skipTsCompile:d,skipGitignore:p,skipTranslations:c,...l}=r,f=await getFsData({...r,ignore:[m+"/**"]}),w=await generateSource({...f,...l}),u=new Set,y=new Set;return await Promise.all(w.map(async({name:r,ext:t,content:o})=>{let i=`${r}.${t}`,s=join(n,m,i);await fsWrite(s,o),u.add(i);})),d||(await writeSourceCompiled(r,Array.from(u).filter(r=>r.endsWith(".ts")||r.endsWith(".tsx"))),Array.from(u).forEach(r=>{u.add(r.replace(".tsx",".js")),u.add(r.replace(".ts",".js")),u.add(r.replace(".ts",".d.ts"));})),c||(await s(r,f)).forEach(r=>{y.add(r);}),p||await fsWrite(join(n,m,".gitignore"),Array.from(new Set([...y,...u])).sort().map(r=>`/${r}`).join(`
29
+ `)),f}async function s(a,t){let{cwd:o,output:i}=a;return await Promise.all(t.localesFolders.map(async({path:a,code:t})=>{let s=join("translations",t);return await cp(a,join(o,i,s),{recursive:!0,force:!0,preserveTimestamps:!0}),s}))}
30
+
31
+ async function writeSummary(m){let{cwd:o,outputJson:e,outputMarkdown:n,sourceUrl:f}=m,p=await getFsData(m),u=await generateSummary({...p,sourceUrl:f});return await fsWrite(join(o,e),JSON.stringify(u.data,null,2)),await fsWrite(join(o,n),u.md),p}
32
+
33
+ async function write(e){let i=await getFsData({...e,ignore:[e.source.output]});return await Promise.all([writeSource({...e,...i,...e.source}),writeSummary({...e,...i,...e.summary})]),i}
34
+
35
+ export { generateSource, generateSummary, getConfig, getFsData, getLocalesFolders, getRoutesData, write, writeSource, writeSummary };
package/index.cjs.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./index";
@@ -0,0 +1 @@
1
+ exports._default = require('./index.cjs.js').default;
package/index.cjs.js ADDED
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var utils = require('@koine/utils');
6
+ var routeHasDynamicPortion = require('./routeHasDynamicPortion.cjs.js');
7
+
8
+ function interpolateTo(i,t){let o=i.replace(/\./g,"/");return "development"===process.env.NODE_ENV&&t&&o.replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g,(r,o)=>{if(!(o in t))throw Error("[@koine/i18n]::interpolateTo, using '"+i+"' without param '"+o+"'");if(!["string","number"].includes(typeof t[o]))throw Error("[@koine/i18n]::interpolateTo, using '"+i+"' with unserializable param '"+o+"' (type '"+utils.getType(t[o])+"')");return ""}),routeHasDynamicPortion.formatRoutePathname(o=o?t?o.replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g,(e,r)=>t[r.trim()]+""):o:"/")}
9
+
10
+ exports.formatRoutePathname = routeHasDynamicPortion.formatRoutePathname;
11
+ exports.routeHasDynamicPortion = routeHasDynamicPortion.routeHasDynamicPortion;
12
+ exports.interpolateTo = interpolateTo;
package/index.cjs.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from './index.cjs.js';
2
+ export { _default as default } from './index.cjs.default.js';
package/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- export { createTo } from "./createTo.js";
2
- export { isDynamicRouteId } from "./isDynamicRouteId.js";
3
- export { isStaticRouteId } from "./isStaticRouteId.js";
4
- export { routeHasDynamicPortion } from "./routeHasDynamicPortion.js";
5
- export * from "./types.js";
1
+ export * from "./client";
2
+ export * from "./shared";
3
+ export * from "./types";
package/index.esm.js ADDED
@@ -0,0 +1,7 @@
1
+ import { getType } from '@koine/utils';
2
+ import { f as formatRoutePathname } from './routeHasDynamicPortion.esm.js';
3
+ export { f as formatRoutePathname, r as routeHasDynamicPortion } from './routeHasDynamicPortion.esm.js';
4
+
5
+ function interpolateTo(i,t){let o=i.replace(/\./g,"/");return "development"===process.env.NODE_ENV&&t&&o.replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g,(r,o)=>{if(!(o in t))throw Error("[@koine/i18n]::interpolateTo, using '"+i+"' without param '"+o+"'");if(!["string","number"].includes(typeof t[o]))throw Error("[@koine/i18n]::interpolateTo, using '"+i+"' with unserializable param '"+o+"' (type '"+getType(t[o])+"')");return ""}),formatRoutePathname(o=o?t?o.replace(/[[{]{1,2}(.*?)[\]}]{1,2}/g,(e,r)=>t[r.trim()]+""):o:"/")}
6
+
7
+ export { interpolateTo };