@koine/i18n 2.0.0-beta.26 → 2.0.0-beta.28

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/_helpers.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { ToRoute, ToRouteDynamic, ToRouteStatic } from "./types.js";
2
+ export declare function routeHasDynamicPortion(routeIdOrPortion: string): boolean;
3
+ export declare function isStaticRouteId(routeId: ToRoute): routeId is ToRouteStatic;
4
+ export declare function isDynamicRouteId(routeId: ToRoute): routeId is ToRouteDynamic;
package/_helpers.js ADDED
@@ -0,0 +1,9 @@
1
+ export function routeHasDynamicPortion(routeIdOrPortion) {
2
+ return /\[/.test(routeIdOrPortion);
3
+ }
4
+ export function isStaticRouteId(routeId) {
5
+ return !routeHasDynamicPortion(routeId);
6
+ }
7
+ export function isDynamicRouteId(routeId) {
8
+ return routeHasDynamicPortion(routeId);
9
+ }
package/createTo.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { ToRoute, ToRouteDynamicParams, ToTranslate } from "./types.js";
2
+ export declare const createTo: <TLocales extends readonly string[] | string[]>(_locales: TLocales, defaultLocale: TLocales[number], hideDefaultLocaleInUrl?: boolean) => <TRoute extends ToRoute>(locale: TLocales[number], t: ToTranslate, routeId: TRoute, routeParams?: ToRouteDynamicParams<TRoute> | undefined) => string;
3
+ export default createTo;
package/createTo.js ADDED
@@ -0,0 +1,18 @@
1
+ export var createTo = function (_locales, defaultLocale, hideDefaultLocaleInUrl) {
2
+ return function (locale, t, routeId, routeParams) {
3
+ var relative = "";
4
+ if (routeParams) {
5
+ relative = t(routeId, routeParams).replace("*", "");
6
+ }
7
+ else {
8
+ relative = t(routeId);
9
+ }
10
+ if (hideDefaultLocaleInUrl) {
11
+ if (locale !== defaultLocale) {
12
+ return "/".concat(locale).concat(relative);
13
+ }
14
+ }
15
+ return relative;
16
+ };
17
+ };
18
+ export default createTo;
@@ -0,0 +1,28 @@
1
+ import type { I18nIndexedFile } from "./types.js";
2
+ export type I18nGenerateSummaryConfig = {
3
+ defaultLocale: string;
4
+ sourceUrl: string;
5
+ };
6
+ type Locale = string & {
7
+ branded: true;
8
+ };
9
+ type I18nGenerateSummaryOptions = I18nGenerateSummaryConfig & {
10
+ files: I18nIndexedFile[];
11
+ };
12
+ type I18nSummary = Record<Locale, {
13
+ words: number;
14
+ characters: number;
15
+ files: I18nSummaryFile[];
16
+ }>;
17
+ type I18nSummaryFile = {
18
+ locale: Locale;
19
+ path: string;
20
+ url: string;
21
+ words: number;
22
+ characters: number;
23
+ };
24
+ export declare function i18nGenerateSummary(options: I18nGenerateSummaryOptions): Promise<{
25
+ data: I18nSummary;
26
+ md: string;
27
+ }>;
28
+ export {};
@@ -0,0 +1,131 @@
1
+ import { __awaiter, __generator, __read } from "tslib";
2
+ import { arraySum, forin } from "@koine/utils";
3
+ function getWords(value, options) {
4
+ if (options === void 0) { options = {}; }
5
+ var out = "";
6
+ if (value && typeof value === "string") {
7
+ out += " " + value.trim();
8
+ }
9
+ else if (Array.isArray(value)) {
10
+ for (var i = 0; i < value.length; i++) {
11
+ out += getWords(value[i], options);
12
+ }
13
+ }
14
+ else if (typeof value === "object") {
15
+ for (var _key in value) {
16
+ var key = _key;
17
+ var single = value[key];
18
+ out += getWords(single, options);
19
+ }
20
+ }
21
+ return out;
22
+ }
23
+ function i18nSummaryGetDataEntry(options, file) {
24
+ var locale = file.locale, path = file.path;
25
+ var url = "".concat(options.sourceUrl, "/").concat(locale, "/").concat(path);
26
+ var words = getWords(file.data);
27
+ var wordsCount = words.split(" ").filter(Boolean).length;
28
+ var characters = words.split(" ").filter(Boolean).join("").length;
29
+ return {
30
+ locale: locale,
31
+ path: path,
32
+ url: url,
33
+ words: wordsCount,
34
+ characters: characters,
35
+ };
36
+ }
37
+ function i18nSummaryGetData(options) {
38
+ var files = options.files, defaultLocale = options.defaultLocale;
39
+ var data = {};
40
+ for (var i = 0; i < files.length; i++) {
41
+ var file = files[i];
42
+ var locale = file.locale;
43
+ var entry = i18nSummaryGetDataEntry(options, file);
44
+ data[locale] = data[locale] || {};
45
+ data[locale].files = data[locale].files || [];
46
+ data[locale].files.push(entry);
47
+ }
48
+ data = Object.fromEntries(Object.entries(data).sort(function (_a) {
49
+ var _b = __read(_a, 1), a = _b[0];
50
+ return a === defaultLocale ? -1 : 1;
51
+ }));
52
+ forin(data, function (locale, dataPerLocale) {
53
+ data[locale].words = arraySum(dataPerLocale.files.map(function (f) { return f.words; }));
54
+ data[locale].characters = arraySum(dataPerLocale.files.map(function (f) { return f.characters; }));
55
+ });
56
+ return data;
57
+ }
58
+ function i18nSummaryGetDataByPath(data) {
59
+ var out = {};
60
+ forin(data, function (locale, dataPerLocale) {
61
+ var files = dataPerLocale.files;
62
+ for (var i = 0; i < files.length; i++) {
63
+ var file = files[i];
64
+ var path = file.path;
65
+ out[path] = out[path] || {};
66
+ out[path][locale] = file;
67
+ }
68
+ });
69
+ return out;
70
+ }
71
+ function i18nGenerateSummaryMarkdownByPath(_options, data) {
72
+ var dataByPath = i18nSummaryGetDataByPath(data);
73
+ var output = "";
74
+ var body = "";
75
+ var locales = [];
76
+ var styleBorder = "style=\"border-right:1px solid grey\"";
77
+ forin(dataByPath, function (path, dataPerPath) {
78
+ body += "<tr>";
79
+ body += "<td ".concat(styleBorder, ">").concat(path, "</td>");
80
+ forin(dataPerPath, function (locale, file) {
81
+ var characters = file.characters, words = file.words, url = file.url;
82
+ if (!locales.includes(locale))
83
+ locales.push(locale);
84
+ body += "<td><a href=\"".concat(url, "\">").concat(locale, "</a></td>");
85
+ body += "<td>".concat(words, "</td>");
86
+ body += "<td ".concat(styleBorder, ">").concat(characters, "</td>");
87
+ });
88
+ body += "</tr>";
89
+ });
90
+ output += "<table><thead><tr>";
91
+ output += "<th ".concat(styleBorder, ">file path</th>");
92
+ output += locales.map(function () { return "<th>lang</th><th>words</th><th ".concat(styleBorder, ">chars</th>"); });
93
+ output += "</tr></thead><tbody>".concat(body, "</tbody></table>\n");
94
+ return output;
95
+ }
96
+ function i18nGenerateSummaryMarkdownByLocale(options, data) {
97
+ var output = "";
98
+ var body = "";
99
+ forin(data, function (locale, dataPerLocale) {
100
+ var files = dataPerLocale.files, characters = dataPerLocale.characters, words = dataPerLocale.words;
101
+ var url = "".concat(options.sourceUrl, "/").concat(locale);
102
+ body += "<tr>";
103
+ body += "<th><a href=\"".concat(url, "\">").concat(locale, "</a></th>");
104
+ body += "<td>".concat(files.length, "</td>");
105
+ body += "<td>".concat(words, "</td>");
106
+ body += "<td>".concat(characters, "</td>");
107
+ body += "</tr>";
108
+ });
109
+ output += "<table><thead><tr>";
110
+ output += "<th>locale</th><th>files</th><th>words</th><th>chars</th>";
111
+ output += "</tr></thead><tbody>".concat(body, "</tbody></table>\n");
112
+ return output;
113
+ }
114
+ function i18nGenerateSummaryMarkdown(options, data) {
115
+ var output = "# Summary\n";
116
+ output += "\n### By locale\n\n";
117
+ output += i18nGenerateSummaryMarkdownByLocale(options, data);
118
+ output += "\n### By file path\n\n";
119
+ output += i18nGenerateSummaryMarkdownByPath(options, data);
120
+ return output;
121
+ }
122
+ export function i18nGenerateSummary(options) {
123
+ return __awaiter(this, void 0, void 0, function () {
124
+ var data, md;
125
+ return __generator(this, function (_a) {
126
+ data = i18nSummaryGetData(options);
127
+ md = i18nGenerateSummaryMarkdown(options, data);
128
+ return [2, { data: data, md: md }];
129
+ });
130
+ });
131
+ }
@@ -1,4 +1,4 @@
1
- import { I18nIndexedFile } from "./i18nGetFsData.js";
1
+ import type { I18nIndexedFile } from "./types.js";
2
2
  export declare function i18nGenerateTypes(options: {
3
3
  defaultLocale: string;
4
4
  files: I18nIndexedFile[];
@@ -1,7 +1,12 @@
1
1
  import { __awaiter, __generator } from "tslib";
2
- import { format } from "prettier";
2
+ var pluralSuffixes = ["_zero", "_one", "_two", "_few", "_many", "_other"];
3
3
  var filterTranslationKey = function (key) {
4
- return key.endsWith("_one") || key.endsWith("_zero") || key.endsWith("_other");
4
+ var parts = key.split("_").filter(Boolean);
5
+ if (parts.length > 1) {
6
+ var lastPart = parts[parts.length - 1];
7
+ return /^[0-9]+$/.test(lastPart) || pluralSuffixes.includes(lastPart);
8
+ }
9
+ return false;
5
10
  };
6
11
  function getType(value, options) {
7
12
  if (options === void 0) { options = {}; }
@@ -42,26 +47,20 @@ export function i18nGenerateTypes(options) {
42
47
  return __awaiter(this, void 0, void 0, function () {
43
48
  var defaultLocale, files, defaultLocaleFiles, header, footer, out, i, _a, path, data, namespace;
44
49
  return __generator(this, function (_b) {
45
- switch (_b.label) {
46
- case 0:
47
- defaultLocale = options.defaultLocale, files = options.files;
48
- defaultLocaleFiles = files.filter(function (f) { return f.locale === defaultLocale; });
49
- header = "\n/* eslint-disable @typescript-eslint/ban-types */\n/* eslint-disable @typescript-eslint/no-namespace */\n\ndeclare namespace Koine {\n interface Translations {\n";
50
- footer = "\n }\n}\n";
51
- out = header;
52
- for (i = 0; i < defaultLocaleFiles.length; i++) {
53
- _a = defaultLocaleFiles[i], path = _a.path, data = _a.data;
54
- namespace = path.replace(".json", "");
55
- out += "\"".concat(namespace, "\": ").concat(getType(data), "\n");
56
- }
57
- out += footer;
58
- return [4, format(out, {
59
- parser: "typescript",
60
- })];
61
- case 1:
62
- out = _b.sent();
63
- return [2, out];
50
+ defaultLocale = options.defaultLocale, files = options.files;
51
+ defaultLocaleFiles = files.filter(function (f) { return f.locale === defaultLocale; });
52
+ header = "\n/* eslint-disable @typescript-eslint/ban-types */\n/* eslint-disable @typescript-eslint/no-namespace */\n\ndeclare namespace Koine {\n interface Translations {\n";
53
+ footer = "\n }\n}\n";
54
+ out = header;
55
+ for (i = 0; i < defaultLocaleFiles.length; i++) {
56
+ _a = defaultLocaleFiles[i], path = _a.path, data = _a.data;
57
+ namespace = path.replace(".json", "");
58
+ out += "\"".concat(namespace, "\": ").concat(getType(data), "\n");
59
+ }
60
+ out += footer;
61
+ if (!process.env["JEST_WORKER_ID"]) {
64
62
  }
63
+ return [2, out];
65
64
  });
66
65
  });
67
66
  }
@@ -1,11 +1,4 @@
1
- import { I18nIndexedLocale } from "./i18nGetLocalesFolders.js";
2
- export type I18nIndexedFile = {
3
- path: string;
4
- locale: string;
5
- data: {
6
- [key: string]: any;
7
- };
8
- };
1
+ import type { I18nIndexedFile, I18nIndexedLocale } from "./types.js";
9
2
  type I18nGetFsDataOutput = {
10
3
  locales: I18nIndexedLocale[];
11
4
  files: I18nIndexedFile[];
package/i18nGetFsData.js CHANGED
@@ -2,7 +2,7 @@ import { __awaiter, __generator } from "tslib";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { glob } from "glob";
5
- import { i18nGetLocalesFolders, } from "./i18nGetLocalesFolders.js";
5
+ import { i18nGetLocalesFolders } from "./i18nGetLocalesFolders.js";
6
6
  export function i18nGetFsData(options) {
7
7
  return __awaiter(this, void 0, void 0, function () {
8
8
  var cwd, _a, onlyFilesForLocales, locales, dataOutput;
@@ -15,8 +15,9 @@ export function i18nGetFsData(options) {
15
15
  case 1:
16
16
  locales = _b.sent();
17
17
  dataOutput = { locales: locales, files: [] };
18
- if (onlyFilesForLocales)
18
+ if (onlyFilesForLocales.length) {
19
19
  locales = locales.filter(function (l) { return onlyFilesForLocales.includes(l.code); });
20
+ }
20
21
  return [4, Promise.all(locales.map(function (locale) { return __awaiter(_this, void 0, void 0, function () {
21
22
  var jsonFiles;
22
23
  var _this = this;
@@ -1,7 +1,4 @@
1
- export type I18nIndexedLocale = {
2
- path: string;
3
- code: string;
4
- };
1
+ import type { I18nIndexedLocale } from "./types.js";
5
2
  export declare function i18nGetLocalesFolders(options: {
6
3
  cwd: string;
7
4
  }): Promise<I18nIndexedLocale[]>;
@@ -0,0 +1,9 @@
1
+ import { type I18nGenerateSummaryConfig } from "./i18nGenerateSummary.js";
2
+ export declare function i18nWriteSummary(options: {
3
+ cwd: string;
4
+ outputJson: string;
5
+ outputMarkdown: string;
6
+ } & I18nGenerateSummaryConfig): Promise<{
7
+ locales: import("./types").I18nIndexedLocale[];
8
+ files: import("./types").I18nIndexedFile[];
9
+ }>;
@@ -0,0 +1,35 @@
1
+ import { __awaiter, __generator } from "tslib";
2
+ import { join } from "node:path";
3
+ import { fsWrite } from "@koine/node";
4
+ import { i18nGenerateSummary, } from "./i18nGenerateSummary.js";
5
+ import { i18nGetFsData } from "./i18nGetFsData.js";
6
+ export function i18nWriteSummary(options) {
7
+ return __awaiter(this, void 0, void 0, function () {
8
+ var cwd, defaultLocale, outputJson, outputMarkdown, sourceUrl, data, summary;
9
+ return __generator(this, function (_a) {
10
+ switch (_a.label) {
11
+ case 0:
12
+ cwd = options.cwd, defaultLocale = options.defaultLocale, outputJson = options.outputJson, outputMarkdown = options.outputMarkdown, sourceUrl = options.sourceUrl;
13
+ return [4, i18nGetFsData({
14
+ cwd: cwd,
15
+ })];
16
+ case 1:
17
+ data = _a.sent();
18
+ return [4, i18nGenerateSummary({
19
+ files: data.files,
20
+ defaultLocale: defaultLocale,
21
+ sourceUrl: sourceUrl,
22
+ })];
23
+ case 2:
24
+ summary = _a.sent();
25
+ return [4, fsWrite(join(cwd, outputJson), JSON.stringify(summary.data, null, 2))];
26
+ case 3:
27
+ _a.sent();
28
+ return [4, fsWrite(join(cwd, outputMarkdown), summary.md)];
29
+ case 4:
30
+ _a.sent();
31
+ return [2, data];
32
+ }
33
+ });
34
+ });
35
+ }
@@ -3,6 +3,6 @@ export declare function i18nWriteTypes(options: {
3
3
  defaultLocale: string;
4
4
  outputTypes: string;
5
5
  }): Promise<{
6
- locales: import("./i18nGetLocalesFolders").I18nIndexedLocale[];
7
- files: import("./i18nGetFsData").I18nIndexedFile[];
6
+ locales: import("./types").I18nIndexedLocale[];
7
+ files: import("./types").I18nIndexedFile[];
8
8
  }>;
package/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
+ export { createTo } from "./createTo.js";
2
+ export { i18nGenerateSummary } from "./i18nGenerateSummary.js";
1
3
  export { i18nGenerateTypes } from "./i18nGenerateTypes.js";
2
4
  export { i18nGetFsData } from "./i18nGetFsData.js";
3
5
  export { i18nGetLocalesFolders } from "./i18nGetLocalesFolders.js";
4
6
  export { i18nWriteTypes } from "./i18nWriteTypes.js";
7
+ export { i18nWriteSummary } from "./i18nWriteSummary.js";
8
+ export * from "./types.js";
package/index.js CHANGED
@@ -1,4 +1,8 @@
1
+ export { createTo } from "./createTo.js";
2
+ export { i18nGenerateSummary } from "./i18nGenerateSummary.js";
1
3
  export { i18nGenerateTypes } from "./i18nGenerateTypes.js";
2
4
  export { i18nGetFsData } from "./i18nGetFsData.js";
3
5
  export { i18nGetLocalesFolders } from "./i18nGetLocalesFolders.js";
4
6
  export { i18nWriteTypes } from "./i18nWriteTypes.js";
7
+ export { i18nWriteSummary } from "./i18nWriteSummary.js";
8
+ export * from "./types.js";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@koine/i18n",
3
3
  "sideEffects": false,
4
4
  "dependencies": {
5
- "@koine/node": "2.0.0-beta.26"
5
+ "@koine/node": "2.0.0-beta.28"
6
6
  },
7
7
  "module": "./index.js",
8
8
  "type": "module",
@@ -10,6 +10,12 @@
10
10
  ".": {
11
11
  "import": "./index.js"
12
12
  },
13
+ "./createTo": {
14
+ "import": "./createTo.js"
15
+ },
16
+ "./i18nGenerateSummary": {
17
+ "import": "./i18nGenerateSummary.js"
18
+ },
13
19
  "./i18nGenerateTypes": {
14
20
  "import": "./i18nGenerateTypes.js"
15
21
  },
@@ -19,10 +25,16 @@
19
25
  "./i18nGetLocalesFolders": {
20
26
  "import": "./i18nGetLocalesFolders.js"
21
27
  },
28
+ "./i18nWriteSummary": {
29
+ "import": "./i18nWriteSummary.js"
30
+ },
22
31
  "./i18nWriteTypes": {
23
32
  "import": "./i18nWriteTypes.js"
33
+ },
34
+ "./types": {
35
+ "import": "./types.js"
24
36
  }
25
37
  },
26
38
  "peerDependencies": {},
27
- "version": "2.0.0-beta.26"
39
+ "version": "2.0.0-beta.28"
28
40
  }
package/types.d.ts ADDED
@@ -0,0 +1,80 @@
1
+ import type { Split } from "@koine/utils";
2
+ export type I18nLocale = string & {
3
+ branded: true;
4
+ };
5
+ export type I18nIndexedFile = {
6
+ path: string;
7
+ locale: I18nLocale;
8
+ data: {
9
+ [key: string]: any;
10
+ };
11
+ };
12
+ export type I18nIndexedLocale = {
13
+ path: string;
14
+ code: I18nLocale;
15
+ };
16
+ type MergeDictionaries<T, K> = Omit<T, keyof K> & K;
17
+ type Join<A, Sep extends string = "", R extends string = ""> = A extends [
18
+ infer First,
19
+ ...infer Rest
20
+ ] ? Join<Rest, Sep, R extends "" ? `${First & string}` : `${R}${Sep}${First & string}`> : R;
21
+ type BuildRecursiveJoin<TList, TSeparator extends string> = Exclude<TList extends [...infer ButLast, unknown] ? Join<ButLast, TSeparator> | BuildRecursiveJoin<ButLast, TSeparator> : never, "">;
22
+ type JoinObjectPath<S1, S2> = S1 extends string ? S2 extends string ? `${S1}.${S2}` : S1 : never;
23
+ type GetWithPath<BaseType, Keys extends readonly string[]> = Keys extends [] ? BaseType : Keys extends readonly [infer Head, ...infer Tail] ? GetWithPath<Head extends keyof BaseType ? BaseType[Head] : unknown, Extract<Tail, string[]>> : never;
24
+ type Get<BaseType, Path extends string | readonly string[]> = GetWithPath<BaseType, Path extends string ? Split<Path, "."> : Path>;
25
+ type TranslationsDictionaryDefault = {
26
+ "~": {
27
+ test: string;
28
+ static: string;
29
+ dynamic: {
30
+ static: string;
31
+ "[key]": {
32
+ index: string;
33
+ "[id]": string;
34
+ };
35
+ };
36
+ };
37
+ };
38
+ export type TranslationsDictionary = MergeDictionaries<TranslationsDictionaryDefault, Koine.Translations>;
39
+ export type TranslateNamespace = Extract<keyof TranslationsDictionary, string>;
40
+ export type TranslationAtPathFromNamespace<TNamespace extends TranslateNamespace, TPath extends TranslationsPaths<TranslationsDictionary[TNamespace]>> = TNamespace extends TranslateNamespace ? TPath extends string ? Get<TranslationsDictionary[TNamespace], TPath> : TranslationsDictionary[TNamespace] : never;
41
+ export type TranslationAtPathGeneric = TranslateNamespace | TranslationsAllPaths;
42
+ export type TranslationAtPath<TPath extends TranslationAtPathGeneric> = TPath extends TranslateNamespace ? TranslationsDictionary[TPath] : TPath extends `${infer Namespace}:${infer Path}` ? Namespace extends TranslateNamespace ? Get<TranslationsDictionary[Namespace], Path> : never : never;
43
+ export type TranslationPathsFrom<TPath extends TranslationAtPathGeneric> = TPath extends TranslateNamespace ? TranslationsPaths<TranslationsDictionary[TPath]> : TPath extends `${infer Namespace}:${infer Path}` ? Namespace extends TranslateNamespace ? Get<TranslationsDictionary[Namespace], Path> extends object ? TranslationsPaths<Get<TranslationsDictionary[Namespace], Path>> : TranslationsPaths<TranslationsDictionary[Namespace]> : never : never;
44
+ export type TranslationsPathsAncestors<TPath extends string, TSeparator extends string = "."> = BuildRecursiveJoin<Split<TPath, TSeparator>, TSeparator>;
45
+ export type TranslationsPaths<T, TAsObj extends boolean = true> = {
46
+ [K in Extract<keyof T, string>]: T[K] extends Record<string, never> | never[] | "" ? never : T[K] extends Record<string, unknown> ? (TAsObj extends true ? `${K}` : never) | JoinObjectPath<K, TranslationsPaths<T[K], TAsObj>> : T[K] extends string | number | boolean | Array<string | number | boolean | object> ? `${K}` : never;
47
+ }[Extract<keyof T, string>] extends infer O ? O : never;
48
+ export type TranslationsAllPaths = {
49
+ [N in Extract<keyof TranslationsDictionary, string>]: {
50
+ [K in Extract<keyof TranslationsDictionary[N], string>]: TranslationsDictionary[N][K] extends Record<string, never> | never[] | "" ? never : TranslationsDictionary[N][K] extends Record<string, unknown> ? `${N}:${K}` | JoinObjectPath<K extends string ? `${N}:${K}` : `${N}:`, TranslationsPaths<TranslationsDictionary[N][K]>> : TranslationsDictionary[N][K] extends string | number | boolean | Array<string | number | boolean | object> ? `${N}:${K}` : never;
51
+ }[Extract<keyof TranslationsDictionary[N], string>];
52
+ }[Extract<keyof TranslationsDictionary, string>] extends infer O ? O : never;
53
+ export type TranslationShortcut = "obj" | "";
54
+ export type TranslationQuery = undefined | null | TranslationShortcut | {
55
+ [key: string]: string | number | boolean;
56
+ };
57
+ export type TranslationOptions = undefined | TranslationShortcut | {
58
+ returnObjects?: boolean;
59
+ fallback?: string | string[];
60
+ default?: string;
61
+ };
62
+ export type Translate<TNamespace extends TranslateNamespace | undefined = TranslateNamespace> = TNamespace extends TranslateNamespace ? TranslateNamespaced<TNamespace> : TranslateDefault;
63
+ export type TranslateDefault = <TPath extends TranslationsAllPaths>(s: TPath, q?: TranslationQuery, o?: TranslationOptions) => TranslationAtPath<TPath>;
64
+ export type TranslateNamespaced<TNamespace extends TranslateNamespace> = <TPath extends TranslationsPaths<TranslationsDictionary[TNamespace]>>(s: TPath, q?: TranslationQuery, o?: TranslationOptions) => TranslationAtPathFromNamespace<TNamespace, TPath>;
65
+ export type TranslateLoose = (s?: any, q?: TranslationQuery, o?: TranslationOptions) => string;
66
+ export type TranslatedRoute = TranslationsPaths<TranslationsDictionary["~"], false>;
67
+ export type TranslatedRoutesChildrenOf<TStarts extends string, T extends string = TranslatedRoute> = T extends `${TStarts}.${infer First}.${infer Second}` ? First | `${First}.${Second}` : T extends `${TStarts}.${infer First}` ? First : never;
68
+ type OnlyStatic<T extends string> = T extends `${string}.[${string}].${string}` | `${string}.[${string}]` | `[${string}].${string}` | `[${string}]` ? never : T;
69
+ type OnlyDynamic<T extends string> = T extends `${string}.[${string}].${string}` | `${string}.[${string}]` | `[${string}].${string}` | `[${string}]` ? T : never;
70
+ export type ToRouteDynamicParams<T extends string> = string extends T ? Record<string, string> : T extends `${string}[${infer Param}].${infer Rest}` ? {
71
+ [k in Param | keyof ToRouteDynamicParams<Rest>]: string | number;
72
+ } : T extends `${string}[${infer Param}]` ? {
73
+ [k in Param]: string | number;
74
+ } : {};
75
+ export type ToTranslate = TranslateNamespaced<"~">;
76
+ export type ToRouteDynamic = OnlyDynamic<TranslatedRoute>;
77
+ export type ToRouteStatic = OnlyStatic<TranslatedRoute>;
78
+ export type ToRoute = ToRouteDynamic | ToRouteStatic;
79
+ export type ToArgs<TRoute extends ToRoute> = TRoute extends ToRouteDynamic ? [TRoute, ToRouteDynamicParams<TRoute>] : [TRoute];
80
+ export {};
package/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/typings.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Types specifically related to `@koine/i18n` exposed on the global unique
3
+ * namespace `Koine`. Most of the types here should be prefixed by `I18n`, e.g.
4
+ * `I18nSomeFeature` accessible anywhere from `Koine.I18nSomeFeature`
5
+ */
6
+ declare namespace Koine {
7
+ /**
8
+ * Translations dictionary extracted from JSON files.
9
+ * You need to augment this type with something like:
10
+ *
11
+ * ```ts
12
+ * declare namespace Koine {
13
+ * interface Translations {
14
+ * "~": typeof import("./locales/en/~.json");
15
+ * "_": typeof import("./locales/en/_.json");
16
+ * "$team": typeof import("./locales/en/$team.json");
17
+ * "home": typeof import("./locales/en/home.json");
18
+ * "Header": typeof import("./locales/en/Header.json");
19
+ * }
20
+ * }
21
+ * ```
22
+ *
23
+ * Best to follow a convention to name the files which become the namespaces:
24
+ *
25
+ * - `~`: for app wide **urls** translated definitions
26
+ * - `_`: for app wide **common** translations
27
+ * - `${data}`: dollar prefix for static **data** like arrays, objects, .etc
28
+ * - `{route-name}`: lower cased for **route** specific data
29
+ * - `{ComponentName}`: pascal cased for **components** specific data
30
+ *
31
+ * This works through using [type augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
32
+ * and [merging interfaces](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces).
33
+ */
34
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
35
+ interface Translations {}
36
+ }