@nckdv/translation-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ // src/interpolate.ts
4
+ var PLACEHOLDER = /\{(\w+)\}/g;
5
+ function interpolate(template, values) {
6
+ if (!values) return template;
7
+ return template.replace(PLACEHOLDER, (match, token) => {
8
+ const value = values[token];
9
+ return value === void 0 ? match : String(value);
10
+ });
11
+ }
12
+
13
+ // src/translator.ts
14
+ function createTranslator(options) {
15
+ const {
16
+ language,
17
+ messages,
18
+ fallback = {},
19
+ onMissingKey = (key) => key
20
+ } = options;
21
+ return function t(key, values) {
22
+ const template = messages[key] ?? fallback[key];
23
+ if (template === void 0) {
24
+ return onMissingKey(key, language);
25
+ }
26
+ return interpolate(template, values);
27
+ };
28
+ }
29
+
30
+ exports.createTranslator = createTranslator;
31
+ exports.interpolate = interpolate;
32
+ //# sourceMappingURL=index.cjs.map
33
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interpolate.ts","../src/translator.ts"],"names":[],"mappings":";;;AAEA,IAAM,WAAA,GAAc,YAAA;AASb,SAAS,WAAA,CACd,UACA,MAAA,EACQ;AACR,EAAA,IAAI,CAAC,QAAQ,OAAO,QAAA;AAEpB,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,WAAA,EAAa,CAAC,OAAO,KAAA,KAAkB;AAC7D,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,OAAO,KAAA,KAAU,MAAA,GAAY,KAAA,GAAQ,MAAA,CAAO,KAAK,CAAA;AAAA,EACnD,CAAC,CAAA;AACH;;;ACNO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAW,EAAC;AAAA,IACZ,YAAA,GAAe,CAAC,GAAA,KAAQ;AAAA,GAC1B,GAAI,OAAA;AAEJ,EAAA,OAAO,SAAS,CAAA,CAAE,GAAA,EAAK,MAAA,EAAQ;AAC7B,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAG,CAAA,IAAK,SAAS,GAAG,CAAA;AAE9C,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,OAAO,YAAA,CAAa,KAAK,QAAQ,CAAA;AAAA,IACnC;AAEA,IAAA,OAAO,WAAA,CAAY,UAAU,MAAM,CAAA;AAAA,EACrC,CAAA;AACF","file":"index.cjs","sourcesContent":["import type { InterpolationValues } from \"./types.js\";\n\nconst PLACEHOLDER = /\\{(\\w+)\\}/g;\n\n/**\n * Replaces `{name}` placeholders in `template` with values from `values`.\n * Unknown placeholders are left untouched so they surface during development.\n *\n * @example\n * interpolate(\"Hello {name}\", { name: \"World\" }) // \"Hello World\"\n */\nexport function interpolate(\n template: string,\n values?: InterpolationValues,\n): string {\n if (!values) return template;\n\n return template.replace(PLACEHOLDER, (match, token: string) => {\n const value = values[token];\n return value === undefined ? match : String(value);\n });\n}\n","import { interpolate } from \"./interpolate.js\";\nimport type { TranslateFn, TranslatorOptions } from \"./types.js\";\n\n/**\n * Creates a `t()` function bound to a language and its message map.\n *\n * Lookup order for a key:\n * 1. `messages` (active language)\n * 2. `fallback` (default language), if provided\n * 3. `onMissingKey` result (defaults to the key itself)\n *\n * The engine is deliberately framework-agnostic and does no I/O — callers\n * supply already-loaded messages. This keeps the SDK boundary clean so the\n * same engine works on the server, in the browser, and in any framework.\n */\nexport function createTranslator(options: TranslatorOptions): TranslateFn {\n const {\n language,\n messages,\n fallback = {},\n onMissingKey = (key) => key,\n } = options;\n\n return function t(key, values) {\n const template = messages[key] ?? fallback[key];\n\n if (template === undefined) {\n return onMissingKey(key, language);\n }\n\n return interpolate(template, values);\n };\n}\n"]}
@@ -0,0 +1,52 @@
1
+ /** A single translated string, e.g. "Willkommen". */
2
+ type TranslationValue = string;
3
+ /**
4
+ * A flat map of translation keys to their translated values for one language.
5
+ * Keys are dot-namespaced by convention, e.g. "home.title".
6
+ */
7
+ type TranslationMap = Record<string, TranslationValue>;
8
+ /** Values injected into `{placeholder}` slots during interpolation. */
9
+ type InterpolationValues = Record<string, string | number>;
10
+ interface TranslatorOptions {
11
+ /** The active language code, e.g. "de". */
12
+ language: string;
13
+ /** Translations for the active language. */
14
+ messages: TranslationMap;
15
+ /**
16
+ * Optional fallback translations, consulted when a key is missing from
17
+ * `messages`. Typically the default language (e.g. English).
18
+ */
19
+ fallback?: TranslationMap;
20
+ /**
21
+ * Called when a key is found in neither `messages` nor `fallback`.
22
+ * Defaults to returning the key itself.
23
+ */
24
+ onMissingKey?: (key: string, language: string) => string;
25
+ }
26
+ /** Looks up and interpolates a translation by key. */
27
+ type TranslateFn = (key: string, values?: InterpolationValues) => string;
28
+
29
+ /**
30
+ * Creates a `t()` function bound to a language and its message map.
31
+ *
32
+ * Lookup order for a key:
33
+ * 1. `messages` (active language)
34
+ * 2. `fallback` (default language), if provided
35
+ * 3. `onMissingKey` result (defaults to the key itself)
36
+ *
37
+ * The engine is deliberately framework-agnostic and does no I/O — callers
38
+ * supply already-loaded messages. This keeps the SDK boundary clean so the
39
+ * same engine works on the server, in the browser, and in any framework.
40
+ */
41
+ declare function createTranslator(options: TranslatorOptions): TranslateFn;
42
+
43
+ /**
44
+ * Replaces `{name}` placeholders in `template` with values from `values`.
45
+ * Unknown placeholders are left untouched so they surface during development.
46
+ *
47
+ * @example
48
+ * interpolate("Hello {name}", { name: "World" }) // "Hello World"
49
+ */
50
+ declare function interpolate(template: string, values?: InterpolationValues): string;
51
+
52
+ export { type InterpolationValues, type TranslateFn, type TranslationMap, type TranslationValue, type TranslatorOptions, createTranslator, interpolate };
@@ -0,0 +1,52 @@
1
+ /** A single translated string, e.g. "Willkommen". */
2
+ type TranslationValue = string;
3
+ /**
4
+ * A flat map of translation keys to their translated values for one language.
5
+ * Keys are dot-namespaced by convention, e.g. "home.title".
6
+ */
7
+ type TranslationMap = Record<string, TranslationValue>;
8
+ /** Values injected into `{placeholder}` slots during interpolation. */
9
+ type InterpolationValues = Record<string, string | number>;
10
+ interface TranslatorOptions {
11
+ /** The active language code, e.g. "de". */
12
+ language: string;
13
+ /** Translations for the active language. */
14
+ messages: TranslationMap;
15
+ /**
16
+ * Optional fallback translations, consulted when a key is missing from
17
+ * `messages`. Typically the default language (e.g. English).
18
+ */
19
+ fallback?: TranslationMap;
20
+ /**
21
+ * Called when a key is found in neither `messages` nor `fallback`.
22
+ * Defaults to returning the key itself.
23
+ */
24
+ onMissingKey?: (key: string, language: string) => string;
25
+ }
26
+ /** Looks up and interpolates a translation by key. */
27
+ type TranslateFn = (key: string, values?: InterpolationValues) => string;
28
+
29
+ /**
30
+ * Creates a `t()` function bound to a language and its message map.
31
+ *
32
+ * Lookup order for a key:
33
+ * 1. `messages` (active language)
34
+ * 2. `fallback` (default language), if provided
35
+ * 3. `onMissingKey` result (defaults to the key itself)
36
+ *
37
+ * The engine is deliberately framework-agnostic and does no I/O — callers
38
+ * supply already-loaded messages. This keeps the SDK boundary clean so the
39
+ * same engine works on the server, in the browser, and in any framework.
40
+ */
41
+ declare function createTranslator(options: TranslatorOptions): TranslateFn;
42
+
43
+ /**
44
+ * Replaces `{name}` placeholders in `template` with values from `values`.
45
+ * Unknown placeholders are left untouched so they surface during development.
46
+ *
47
+ * @example
48
+ * interpolate("Hello {name}", { name: "World" }) // "Hello World"
49
+ */
50
+ declare function interpolate(template: string, values?: InterpolationValues): string;
51
+
52
+ export { type InterpolationValues, type TranslateFn, type TranslationMap, type TranslationValue, type TranslatorOptions, createTranslator, interpolate };
package/dist/index.js ADDED
@@ -0,0 +1,30 @@
1
+ // src/interpolate.ts
2
+ var PLACEHOLDER = /\{(\w+)\}/g;
3
+ function interpolate(template, values) {
4
+ if (!values) return template;
5
+ return template.replace(PLACEHOLDER, (match, token) => {
6
+ const value = values[token];
7
+ return value === void 0 ? match : String(value);
8
+ });
9
+ }
10
+
11
+ // src/translator.ts
12
+ function createTranslator(options) {
13
+ const {
14
+ language,
15
+ messages,
16
+ fallback = {},
17
+ onMissingKey = (key) => key
18
+ } = options;
19
+ return function t(key, values) {
20
+ const template = messages[key] ?? fallback[key];
21
+ if (template === void 0) {
22
+ return onMissingKey(key, language);
23
+ }
24
+ return interpolate(template, values);
25
+ };
26
+ }
27
+
28
+ export { createTranslator, interpolate };
29
+ //# sourceMappingURL=index.js.map
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interpolate.ts","../src/translator.ts"],"names":[],"mappings":";AAEA,IAAM,WAAA,GAAc,YAAA;AASb,SAAS,WAAA,CACd,UACA,MAAA,EACQ;AACR,EAAA,IAAI,CAAC,QAAQ,OAAO,QAAA;AAEpB,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,WAAA,EAAa,CAAC,OAAO,KAAA,KAAkB;AAC7D,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,OAAO,KAAA,KAAU,MAAA,GAAY,KAAA,GAAQ,MAAA,CAAO,KAAK,CAAA;AAAA,EACnD,CAAC,CAAA;AACH;;;ACNO,SAAS,iBAAiB,OAAA,EAAyC;AACxE,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAW,EAAC;AAAA,IACZ,YAAA,GAAe,CAAC,GAAA,KAAQ;AAAA,GAC1B,GAAI,OAAA;AAEJ,EAAA,OAAO,SAAS,CAAA,CAAE,GAAA,EAAK,MAAA,EAAQ;AAC7B,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAG,CAAA,IAAK,SAAS,GAAG,CAAA;AAE9C,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,OAAO,YAAA,CAAa,KAAK,QAAQ,CAAA;AAAA,IACnC;AAEA,IAAA,OAAO,WAAA,CAAY,UAAU,MAAM,CAAA;AAAA,EACrC,CAAA;AACF","file":"index.js","sourcesContent":["import type { InterpolationValues } from \"./types.js\";\n\nconst PLACEHOLDER = /\\{(\\w+)\\}/g;\n\n/**\n * Replaces `{name}` placeholders in `template` with values from `values`.\n * Unknown placeholders are left untouched so they surface during development.\n *\n * @example\n * interpolate(\"Hello {name}\", { name: \"World\" }) // \"Hello World\"\n */\nexport function interpolate(\n template: string,\n values?: InterpolationValues,\n): string {\n if (!values) return template;\n\n return template.replace(PLACEHOLDER, (match, token: string) => {\n const value = values[token];\n return value === undefined ? match : String(value);\n });\n}\n","import { interpolate } from \"./interpolate.js\";\nimport type { TranslateFn, TranslatorOptions } from \"./types.js\";\n\n/**\n * Creates a `t()` function bound to a language and its message map.\n *\n * Lookup order for a key:\n * 1. `messages` (active language)\n * 2. `fallback` (default language), if provided\n * 3. `onMissingKey` result (defaults to the key itself)\n *\n * The engine is deliberately framework-agnostic and does no I/O — callers\n * supply already-loaded messages. This keeps the SDK boundary clean so the\n * same engine works on the server, in the browser, and in any framework.\n */\nexport function createTranslator(options: TranslatorOptions): TranslateFn {\n const {\n language,\n messages,\n fallback = {},\n onMissingKey = (key) => key,\n } = options;\n\n return function t(key, values) {\n const template = messages[key] ?? fallback[key];\n\n if (template === undefined) {\n return onMissingKey(key, language);\n }\n\n return interpolate(template, values);\n };\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@nckdv/translation-core",
3
+ "version": "0.1.0",
4
+ "description": "Framework-agnostic translation engine: lookup, fallback, interpolation.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs"
12
+ }
13
+ },
14
+ "main": "./dist/index.cjs",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "devDependencies": {
26
+ "tsup": "^8.3.0",
27
+ "typescript": "^5.6.0"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/NiklasErath/nck-translation.git",
35
+ "directory": "packages/core"
36
+ },
37
+ "homepage": "https://github.com/NiklasErath/nck-translation#readme",
38
+ "keywords": [
39
+ "i18n",
40
+ "translation",
41
+ "internationalization",
42
+ "localization"
43
+ ]
44
+ }