@oscarpalmer/atoms 0.82.0 → 0.83.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/color/hex.js +1 -1
- package/dist/i18n.cjs +106 -0
- package/dist/i18n.js +106 -0
- package/dist/index.cjs +3 -1
- package/dist/index.js +4 -2
- package/dist/random.cjs +2 -2
- package/dist/random.js +2 -2
- package/package.json +16 -13
- package/src/i18n.ts +272 -0
- package/src/index.ts +1 -0
- package/src/random.ts +2 -2
- package/types/i18n.d.cts +35 -0
- package/types/i18n.d.ts +32 -0
- package/types/index.d.cts +362 -1081
- package/types/index.d.ts +1 -0
- package/types/models.d.cts +207 -482
- package/types/random.d.cts +2 -2
- package/types/random.d.ts +2 -2
- package/types/value/get.d.cts +207 -484
- package/types/value/index.d.cts +227 -540
- package/types/value/set.d.cts +167 -358
- package/types/value/smush.d.cts +206 -478
package/dist/color/hex.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import {
|
|
4
|
+
import { getNormalisedHex, anyPattern, hexToRgb } from "./functions.js";
|
|
5
5
|
class HexColor {
|
|
6
6
|
constructor(value) {
|
|
7
7
|
__publicField(this, "state");
|
package/dist/i18n.cjs
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b, _c;
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
+
const defaults = {
|
|
5
|
+
delimiter: "",
|
|
6
|
+
languages: {
|
|
7
|
+
fallback: null,
|
|
8
|
+
preferred: null
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
function getKey(value, languages) {
|
|
12
|
+
if ((languages == null ? void 0 : languages.fallback) == null && (languages == null ? void 0 : languages.preferred) == null) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const { fallback, preferred } = languages;
|
|
16
|
+
switch (true) {
|
|
17
|
+
case (preferred != null && preferred.full in value):
|
|
18
|
+
return preferred.full;
|
|
19
|
+
case (preferred != null && preferred.region != null && preferred.base in value):
|
|
20
|
+
return preferred.base;
|
|
21
|
+
case (fallback != null && fallback.full in value):
|
|
22
|
+
return fallback.full;
|
|
23
|
+
case (fallback != null && fallback.region != null && fallback.base in value):
|
|
24
|
+
return fallback.base;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function getLanguage(value) {
|
|
28
|
+
if (typeof value !== "string") {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const [full, base, region] = /^([a-z]{2,3})(?:-([A-Z]{2}))?$/.exec(value) ?? [];
|
|
32
|
+
if (full != null) {
|
|
33
|
+
return { base, full, region };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function getTranslation(value, key) {
|
|
37
|
+
if (typeof value !== "object" || value == null || key == null) {
|
|
38
|
+
return "";
|
|
39
|
+
}
|
|
40
|
+
const translation = value[key];
|
|
41
|
+
return typeof translation === "string" ? translation : String(translation);
|
|
42
|
+
}
|
|
43
|
+
function setLanguage(key, value) {
|
|
44
|
+
const language = getLanguage(value);
|
|
45
|
+
if (language != null) {
|
|
46
|
+
defaults.languages[key] = language;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function translate(value, options) {
|
|
50
|
+
return translateValue(value, null, null, options);
|
|
51
|
+
}
|
|
52
|
+
translate.configure = (configuration) => {
|
|
53
|
+
if (typeof configuration.delimiter === "string") {
|
|
54
|
+
defaults.delimiter = configuration.delimiter;
|
|
55
|
+
}
|
|
56
|
+
if (typeof configuration.fallback === "string") {
|
|
57
|
+
setLanguage("fallback", configuration.fallback);
|
|
58
|
+
}
|
|
59
|
+
if (typeof configuration.language === "string") {
|
|
60
|
+
setLanguage("preferred", configuration.language);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
translate.configuration = () => {
|
|
64
|
+
return {
|
|
65
|
+
delimiter: String(defaults.delimiter),
|
|
66
|
+
fallback: String(defaults.languages.fallback.full),
|
|
67
|
+
language: String(defaults.languages.preferred.full)
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
function translatePrimitive(value) {
|
|
71
|
+
let actual = value;
|
|
72
|
+
if (typeof value === "function") {
|
|
73
|
+
actual = value();
|
|
74
|
+
}
|
|
75
|
+
return actual == null ? "" : typeof actual === "string" ? actual : String(actual);
|
|
76
|
+
}
|
|
77
|
+
function translateTranslatable(value, delimiter, languages, options) {
|
|
78
|
+
let actualDelimiter = delimiter ?? defaults.delimiter;
|
|
79
|
+
let actualLanguages = languages;
|
|
80
|
+
if (options != null) {
|
|
81
|
+
actualDelimiter = typeof options.delimiter === "string" ? options.delimiter : defaults.delimiter;
|
|
82
|
+
actualLanguages = {
|
|
83
|
+
fallback: getLanguage(options.fallback),
|
|
84
|
+
preferred: getLanguage(options.language)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
return value.map((item) => translateValue(item, actualDelimiter, actualLanguages)).filter((translated) => translated.trim().length > 0).join(actualDelimiter);
|
|
89
|
+
}
|
|
90
|
+
return getTranslation(
|
|
91
|
+
value,
|
|
92
|
+
getKey(value, actualLanguages) ?? getKey(value, defaults.languages)
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
function translateValue(value, delimiter, language, options) {
|
|
96
|
+
return typeof value !== "object" || value == null ? translatePrimitive(value) : translateTranslatable(
|
|
97
|
+
value,
|
|
98
|
+
delimiter,
|
|
99
|
+
language,
|
|
100
|
+
options
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const defaultLanguage = (((_c = (_b = (_a = document == null ? void 0 : document.documentElement) == null ? void 0 : _a.lang) == null ? void 0 : _b.trim()) == null ? void 0 : _c.length) ?? 0) > 0 ? document.documentElement.lang : (navigator == null ? void 0 : navigator.language) ?? "en";
|
|
104
|
+
setLanguage("fallback", defaultLanguage);
|
|
105
|
+
setLanguage("preferred", defaultLanguage);
|
|
106
|
+
exports.translate = translate;
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
var _a, _b, _c;
|
|
2
|
+
const defaults = {
|
|
3
|
+
delimiter: "",
|
|
4
|
+
languages: {
|
|
5
|
+
fallback: null,
|
|
6
|
+
preferred: null
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
function getKey(value, languages) {
|
|
10
|
+
if ((languages == null ? void 0 : languages.fallback) == null && (languages == null ? void 0 : languages.preferred) == null) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const { fallback, preferred } = languages;
|
|
14
|
+
switch (true) {
|
|
15
|
+
case (preferred != null && preferred.full in value):
|
|
16
|
+
return preferred.full;
|
|
17
|
+
case (preferred != null && preferred.region != null && preferred.base in value):
|
|
18
|
+
return preferred.base;
|
|
19
|
+
case (fallback != null && fallback.full in value):
|
|
20
|
+
return fallback.full;
|
|
21
|
+
case (fallback != null && fallback.region != null && fallback.base in value):
|
|
22
|
+
return fallback.base;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function getLanguage(value) {
|
|
26
|
+
if (typeof value !== "string") {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const [full, base, region] = /^([a-z]{2,3})(?:-([A-Z]{2}))?$/.exec(value) ?? [];
|
|
30
|
+
if (full != null) {
|
|
31
|
+
return { base, full, region };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function getTranslation(value, key) {
|
|
35
|
+
if (typeof value !== "object" || value == null || key == null) {
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
const translation = value[key];
|
|
39
|
+
return typeof translation === "string" ? translation : String(translation);
|
|
40
|
+
}
|
|
41
|
+
function setLanguage(key, value) {
|
|
42
|
+
const language = getLanguage(value);
|
|
43
|
+
if (language != null) {
|
|
44
|
+
defaults.languages[key] = language;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function translate(value, options) {
|
|
48
|
+
return translateValue(value, null, null, options);
|
|
49
|
+
}
|
|
50
|
+
translate.configure = (configuration) => {
|
|
51
|
+
if (typeof configuration.delimiter === "string") {
|
|
52
|
+
defaults.delimiter = configuration.delimiter;
|
|
53
|
+
}
|
|
54
|
+
if (typeof configuration.fallback === "string") {
|
|
55
|
+
setLanguage("fallback", configuration.fallback);
|
|
56
|
+
}
|
|
57
|
+
if (typeof configuration.language === "string") {
|
|
58
|
+
setLanguage("preferred", configuration.language);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
translate.configuration = () => {
|
|
62
|
+
return {
|
|
63
|
+
delimiter: String(defaults.delimiter),
|
|
64
|
+
fallback: String(defaults.languages.fallback.full),
|
|
65
|
+
language: String(defaults.languages.preferred.full)
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
function translatePrimitive(value) {
|
|
69
|
+
let actual = value;
|
|
70
|
+
if (typeof value === "function") {
|
|
71
|
+
actual = value();
|
|
72
|
+
}
|
|
73
|
+
return actual == null ? "" : typeof actual === "string" ? actual : String(actual);
|
|
74
|
+
}
|
|
75
|
+
function translateTranslatable(value, delimiter, languages, options) {
|
|
76
|
+
let actualDelimiter = delimiter ?? defaults.delimiter;
|
|
77
|
+
let actualLanguages = languages;
|
|
78
|
+
if (options != null) {
|
|
79
|
+
actualDelimiter = typeof options.delimiter === "string" ? options.delimiter : defaults.delimiter;
|
|
80
|
+
actualLanguages = {
|
|
81
|
+
fallback: getLanguage(options.fallback),
|
|
82
|
+
preferred: getLanguage(options.language)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
return value.map((item) => translateValue(item, actualDelimiter, actualLanguages)).filter((translated) => translated.trim().length > 0).join(actualDelimiter);
|
|
87
|
+
}
|
|
88
|
+
return getTranslation(
|
|
89
|
+
value,
|
|
90
|
+
getKey(value, actualLanguages) ?? getKey(value, defaults.languages)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
function translateValue(value, delimiter, language, options) {
|
|
94
|
+
return typeof value !== "object" || value == null ? translatePrimitive(value) : translateTranslatable(
|
|
95
|
+
value,
|
|
96
|
+
delimiter,
|
|
97
|
+
language,
|
|
98
|
+
options
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const defaultLanguage = (((_c = (_b = (_a = document == null ? void 0 : document.documentElement) == null ? void 0 : _a.lang) == null ? void 0 : _b.trim()) == null ? void 0 : _c.length) ?? 0) > 0 ? document.documentElement.lang : (navigator == null ? void 0 : navigator.language) ?? "en";
|
|
102
|
+
setLanguage("fallback", defaultLanguage);
|
|
103
|
+
setLanguage("preferred", defaultLanguage);
|
|
104
|
+
export {
|
|
105
|
+
translate
|
|
106
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ const array_index = require("./array/index.cjs");
|
|
|
4
4
|
const color_index = require("./color/index.cjs");
|
|
5
5
|
const emitter = require("./emitter.cjs");
|
|
6
6
|
const _function = require("./function.cjs");
|
|
7
|
+
const i18n = require("./i18n.cjs");
|
|
7
8
|
const is = require("./is.cjs");
|
|
8
9
|
const logger = require("./logger.cjs");
|
|
9
10
|
const math = require("./math.cjs");
|
|
@@ -54,6 +55,7 @@ exports.debounce = _function.debounce;
|
|
|
54
55
|
exports.memoise = _function.memoise;
|
|
55
56
|
exports.noop = _function.noop;
|
|
56
57
|
exports.throttle = _function.throttle;
|
|
58
|
+
exports.translate = i18n.translate;
|
|
57
59
|
exports.isArrayOrPlainObject = is.isArrayOrPlainObject;
|
|
58
60
|
exports.isEmpty = is.isEmpty;
|
|
59
61
|
exports.isKey = is.isKey;
|
|
@@ -79,7 +81,7 @@ exports.toQuery = query.toQuery;
|
|
|
79
81
|
exports.queue = queue.queue;
|
|
80
82
|
exports.getRandomBoolean = random.getRandomBoolean;
|
|
81
83
|
exports.getRandomCharacters = random.getRandomCharacters;
|
|
82
|
-
exports.
|
|
84
|
+
exports.getRandomColor = random.getRandomColor;
|
|
83
85
|
exports.getRandomFloat = random.getRandomFloat;
|
|
84
86
|
exports.getRandomHex = random.getRandomHex;
|
|
85
87
|
exports.getRandomInteger = random.getRandomInteger;
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,14 @@ import { flatten, push } from "./array/index.js";
|
|
|
2
2
|
import { getForegroundColor } from "./color/index.js";
|
|
3
3
|
import { emitter } from "./emitter.js";
|
|
4
4
|
import { debounce, memoise, noop, throttle } from "./function.js";
|
|
5
|
+
import { translate } from "./i18n.js";
|
|
5
6
|
import { isArrayOrPlainObject, isEmpty, isKey, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isPlainObject, isPrimitive } from "./is.js";
|
|
6
7
|
import { logger } from "./logger.js";
|
|
7
8
|
import { average, max, min, round, sum } from "./math.js";
|
|
8
9
|
import { between, clamp, getNumber } from "./number.js";
|
|
9
10
|
import { fromQuery, toQuery } from "./query.js";
|
|
10
11
|
import { queue } from "./queue.js";
|
|
11
|
-
import { getRandomBoolean, getRandomCharacters,
|
|
12
|
+
import { getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems } from "./random.js";
|
|
12
13
|
import { SizedMap, SizedSet } from "./sized.js";
|
|
13
14
|
import { createUuid, getString, join, parse, truncate, words } from "./string/index.js";
|
|
14
15
|
import "./touch.js";
|
|
@@ -77,7 +78,7 @@ export {
|
|
|
77
78
|
getRGBColor,
|
|
78
79
|
getRandomBoolean,
|
|
79
80
|
getRandomCharacters,
|
|
80
|
-
|
|
81
|
+
getRandomColor,
|
|
81
82
|
getRandomFloat,
|
|
82
83
|
getRandomHex,
|
|
83
84
|
getRandomInteger,
|
|
@@ -134,6 +135,7 @@ export {
|
|
|
134
135
|
toMap,
|
|
135
136
|
toQuery,
|
|
136
137
|
toRecord,
|
|
138
|
+
translate,
|
|
137
139
|
truncate,
|
|
138
140
|
unique,
|
|
139
141
|
unsmush,
|
package/dist/random.cjs
CHANGED
|
@@ -15,7 +15,7 @@ function getRandomCharacters(length, selection) {
|
|
|
15
15
|
}
|
|
16
16
|
return characters;
|
|
17
17
|
}
|
|
18
|
-
function
|
|
18
|
+
function getRandomColor() {
|
|
19
19
|
return `#${Array.from({ length: 6 }, getRandomHex).join("")}`;
|
|
20
20
|
}
|
|
21
21
|
function getRandomFloat(min, max) {
|
|
@@ -39,7 +39,7 @@ function getRandomItems(array, amount) {
|
|
|
39
39
|
}
|
|
40
40
|
exports.getRandomBoolean = getRandomBoolean;
|
|
41
41
|
exports.getRandomCharacters = getRandomCharacters;
|
|
42
|
-
exports.
|
|
42
|
+
exports.getRandomColor = getRandomColor;
|
|
43
43
|
exports.getRandomFloat = getRandomFloat;
|
|
44
44
|
exports.getRandomHex = getRandomHex;
|
|
45
45
|
exports.getRandomInteger = getRandomInteger;
|
package/dist/random.js
CHANGED
|
@@ -13,7 +13,7 @@ function getRandomCharacters(length, selection) {
|
|
|
13
13
|
}
|
|
14
14
|
return characters;
|
|
15
15
|
}
|
|
16
|
-
function
|
|
16
|
+
function getRandomColor() {
|
|
17
17
|
return `#${Array.from({ length: 6 }, getRandomHex).join("")}`;
|
|
18
18
|
}
|
|
19
19
|
function getRandomFloat(min, max) {
|
|
@@ -38,7 +38,7 @@ function getRandomItems(array, amount) {
|
|
|
38
38
|
export {
|
|
39
39
|
getRandomBoolean,
|
|
40
40
|
getRandomCharacters,
|
|
41
|
-
|
|
41
|
+
getRandomColor,
|
|
42
42
|
getRandomFloat,
|
|
43
43
|
getRandomHex,
|
|
44
44
|
getRandomInteger,
|
package/package.json
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"description": "Atomic utilities for making your JavaScript better.",
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@biomejs/biome": "^1.9",
|
|
12
|
-
"@types/node": "^22.
|
|
12
|
+
"@types/node": "^22.13",
|
|
13
13
|
"@vitest/coverage-istanbul": "^3",
|
|
14
14
|
"dts-bundle-generator": "^9.5",
|
|
15
15
|
"glob": "^11",
|
|
16
|
-
"happy-dom": "^
|
|
16
|
+
"happy-dom": "^17",
|
|
17
17
|
"typescript": "^5.7",
|
|
18
|
-
"vite": "^6",
|
|
18
|
+
"vite": "^6.1",
|
|
19
19
|
"vitest": "^3"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
@@ -70,6 +70,16 @@
|
|
|
70
70
|
"default": "./dist/function.cjs"
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
+
"./i18n": {
|
|
74
|
+
"import": {
|
|
75
|
+
"types": "./types/i18n.d.ts",
|
|
76
|
+
"default": "./dist/i18n.js"
|
|
77
|
+
},
|
|
78
|
+
"require": {
|
|
79
|
+
"types": "./types/i18n.d.cts",
|
|
80
|
+
"default": "./dist/i18n.cjs"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
73
83
|
"./is": {
|
|
74
84
|
"import": {
|
|
75
85
|
"types": "./types/is.d.ts",
|
|
@@ -179,15 +189,8 @@
|
|
|
179
189
|
}
|
|
180
190
|
}
|
|
181
191
|
},
|
|
182
|
-
"files": [
|
|
183
|
-
|
|
184
|
-
"src",
|
|
185
|
-
"types"
|
|
186
|
-
],
|
|
187
|
-
"keywords": [
|
|
188
|
-
"helper",
|
|
189
|
-
"utility"
|
|
190
|
-
],
|
|
192
|
+
"files": ["dist", "src", "types"],
|
|
193
|
+
"keywords": ["helper", "utility"],
|
|
191
194
|
"license": "MIT",
|
|
192
195
|
"main": "./dist/index.cjs",
|
|
193
196
|
"module": "./dist/index.js",
|
|
@@ -205,5 +208,5 @@
|
|
|
205
208
|
},
|
|
206
209
|
"type": "module",
|
|
207
210
|
"types": "./types/index.d.cts",
|
|
208
|
-
"version": "0.
|
|
211
|
+
"version": "0.83.0"
|
|
209
212
|
}
|
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import type {PlainObject} from './models';
|
|
2
|
+
|
|
3
|
+
type Defaults = {
|
|
4
|
+
/**
|
|
5
|
+
* Delimiter to use when translating an array of translatable values
|
|
6
|
+
*/
|
|
7
|
+
delimiter: string;
|
|
8
|
+
/**
|
|
9
|
+
* Languages to use when translating
|
|
10
|
+
*/
|
|
11
|
+
languages: Languages;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type Language = {
|
|
15
|
+
/**
|
|
16
|
+
* Language code _(e.g. `en`, `es`, `fr`, `ja`, `zh`)_
|
|
17
|
+
*/
|
|
18
|
+
readonly base: string;
|
|
19
|
+
/**
|
|
20
|
+
* Language code with region _(e.g. `en-US`, `es-ES`, `fr-FR`, `ja-JP`, `zh-CN`)_
|
|
21
|
+
*/
|
|
22
|
+
readonly full: string;
|
|
23
|
+
/**
|
|
24
|
+
* Region code _(e.g. `US`, `ES`, `FR`, `JP`, `CN`)_
|
|
25
|
+
*/
|
|
26
|
+
readonly region?: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type Languages = {
|
|
30
|
+
/**
|
|
31
|
+
* Language to use when no translation is found
|
|
32
|
+
*/
|
|
33
|
+
fallback: Language;
|
|
34
|
+
/**
|
|
35
|
+
* Language to use when translating
|
|
36
|
+
*/
|
|
37
|
+
preferred: Language;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
type TranslateConfiguration = TranslateOptions;
|
|
41
|
+
|
|
42
|
+
export type TranslateOptions = {
|
|
43
|
+
/**
|
|
44
|
+
* Delimiter to use when translating an array of translatable values
|
|
45
|
+
*/
|
|
46
|
+
delimiter: string;
|
|
47
|
+
/**
|
|
48
|
+
* Language to use when no translation is found
|
|
49
|
+
*/
|
|
50
|
+
fallback: string;
|
|
51
|
+
/**
|
|
52
|
+
* Language to use when translating
|
|
53
|
+
*/
|
|
54
|
+
language: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A translatable object
|
|
59
|
+
*/
|
|
60
|
+
export type Translatable = Record<string, unknown>;
|
|
61
|
+
|
|
62
|
+
const defaults: Defaults = {
|
|
63
|
+
delimiter: '',
|
|
64
|
+
languages: {
|
|
65
|
+
fallback: null as never,
|
|
66
|
+
preferred: null as never,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get translation key for a translatable object
|
|
72
|
+
*/
|
|
73
|
+
function getKey(
|
|
74
|
+
value: PlainObject,
|
|
75
|
+
languages: Partial<Languages>,
|
|
76
|
+
): string | undefined {
|
|
77
|
+
if (languages?.fallback == null && languages?.preferred == null) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const {fallback, preferred} = languages;
|
|
82
|
+
|
|
83
|
+
switch (true) {
|
|
84
|
+
case preferred != null && preferred.full in value:
|
|
85
|
+
return preferred.full;
|
|
86
|
+
|
|
87
|
+
case preferred != null &&
|
|
88
|
+
preferred.region != null &&
|
|
89
|
+
preferred.base in value:
|
|
90
|
+
return preferred.base;
|
|
91
|
+
|
|
92
|
+
case fallback != null && fallback.full in value:
|
|
93
|
+
return fallback.full;
|
|
94
|
+
|
|
95
|
+
case fallback != null && fallback.region != null && fallback.base in value:
|
|
96
|
+
return fallback.base;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get a _Language_ from a value
|
|
102
|
+
*/
|
|
103
|
+
function getLanguage(value: unknown): Language | undefined {
|
|
104
|
+
if (typeof value !== 'string') {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const [full, base, region] =
|
|
109
|
+
/^([a-z]{2,3})(?:-([A-Z]{2}))?$/.exec(value) ?? [];
|
|
110
|
+
|
|
111
|
+
if (full != null) {
|
|
112
|
+
return {base, full, region};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get translation for a key from a translatable object
|
|
118
|
+
*/
|
|
119
|
+
function getTranslation(value: unknown, key?: string): string {
|
|
120
|
+
if (typeof value !== 'object' || value == null || key == null) {
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const translation = (value as PlainObject)[key];
|
|
125
|
+
|
|
126
|
+
return typeof translation === 'string' ? translation : String(translation);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Set a _Language_ for a key
|
|
131
|
+
*/
|
|
132
|
+
function setLanguage(key: keyof Languages, value: string): void {
|
|
133
|
+
const language = getLanguage(value);
|
|
134
|
+
|
|
135
|
+
if (language != null) {
|
|
136
|
+
defaults.languages[key] = language;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Translates a value _(with optional options, but defaulting to configuration)_
|
|
142
|
+
*/
|
|
143
|
+
export function translate(
|
|
144
|
+
value: unknown,
|
|
145
|
+
options?: Partial<TranslateOptions>,
|
|
146
|
+
): string;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Translates an array of values _(with optional options, but defaulting to configuration)_
|
|
150
|
+
*/
|
|
151
|
+
export function translate(
|
|
152
|
+
value: unknown[],
|
|
153
|
+
options?: Partial<TranslateOptions>,
|
|
154
|
+
): string;
|
|
155
|
+
|
|
156
|
+
export function translate(
|
|
157
|
+
value: unknown | unknown[],
|
|
158
|
+
options?: Partial<TranslateOptions>,
|
|
159
|
+
): string {
|
|
160
|
+
return translateValue(value, null as never, null as never, options);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Configures the translation options _(used as defaults when translating)_
|
|
165
|
+
*/
|
|
166
|
+
translate.configure = (
|
|
167
|
+
configuration: Partial<TranslateConfiguration>,
|
|
168
|
+
): void => {
|
|
169
|
+
if (typeof configuration.delimiter === 'string') {
|
|
170
|
+
defaults.delimiter = configuration.delimiter;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (typeof configuration.fallback === 'string') {
|
|
174
|
+
setLanguage('fallback', configuration.fallback);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (typeof configuration.language === 'string') {
|
|
178
|
+
setLanguage('preferred', configuration.language);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Gets the current translation configuration
|
|
184
|
+
*/
|
|
185
|
+
translate.configuration = (): TranslateConfiguration => {
|
|
186
|
+
return {
|
|
187
|
+
delimiter: String(defaults.delimiter),
|
|
188
|
+
fallback: String(defaults.languages.fallback.full),
|
|
189
|
+
language: String(defaults.languages.preferred.full),
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Translates a primitive value _(into a string)_
|
|
195
|
+
*/
|
|
196
|
+
function translatePrimitive(value: unknown): string {
|
|
197
|
+
let actual = value;
|
|
198
|
+
|
|
199
|
+
if (typeof value === 'function') {
|
|
200
|
+
actual = value();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return actual == null
|
|
204
|
+
? ''
|
|
205
|
+
: typeof actual === 'string'
|
|
206
|
+
? actual
|
|
207
|
+
: String(actual);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Translates a translatable object _(or array of translatable objects)_ into a string
|
|
212
|
+
*/
|
|
213
|
+
function translateTranslatable(
|
|
214
|
+
value: PlainObject | PlainObject[],
|
|
215
|
+
delimiter: string,
|
|
216
|
+
languages: Partial<Languages>,
|
|
217
|
+
options?: Partial<TranslateOptions>,
|
|
218
|
+
): string {
|
|
219
|
+
let actualDelimiter = delimiter ?? defaults.delimiter;
|
|
220
|
+
let actualLanguages = languages;
|
|
221
|
+
|
|
222
|
+
if (options != null) {
|
|
223
|
+
actualDelimiter =
|
|
224
|
+
typeof options.delimiter === 'string'
|
|
225
|
+
? options.delimiter
|
|
226
|
+
: defaults.delimiter;
|
|
227
|
+
|
|
228
|
+
actualLanguages = {
|
|
229
|
+
fallback: getLanguage(options.fallback),
|
|
230
|
+
preferred: getLanguage(options.language),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (Array.isArray(value)) {
|
|
235
|
+
return value
|
|
236
|
+
.map(item => translateValue(item, actualDelimiter, actualLanguages))
|
|
237
|
+
.filter(translated => translated.trim().length > 0)
|
|
238
|
+
.join(actualDelimiter);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return getTranslation(
|
|
242
|
+
value,
|
|
243
|
+
getKey(value, actualLanguages) ?? getKey(value, defaults.languages),
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Translates a value _(into a string)_
|
|
249
|
+
*/
|
|
250
|
+
function translateValue(
|
|
251
|
+
value: unknown,
|
|
252
|
+
delimiter: string,
|
|
253
|
+
language: Partial<Languages>,
|
|
254
|
+
options?: Partial<TranslateOptions>,
|
|
255
|
+
): string {
|
|
256
|
+
return typeof value !== 'object' || value == null
|
|
257
|
+
? translatePrimitive(value)
|
|
258
|
+
: translateTranslatable(
|
|
259
|
+
value as PlainObject | PlainObject[],
|
|
260
|
+
delimiter,
|
|
261
|
+
language,
|
|
262
|
+
options,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const defaultLanguage =
|
|
267
|
+
(document?.documentElement?.lang?.trim()?.length ?? 0) > 0
|
|
268
|
+
? document.documentElement.lang
|
|
269
|
+
: (navigator?.language ?? 'en');
|
|
270
|
+
|
|
271
|
+
setLanguage('fallback', defaultLanguage);
|
|
272
|
+
setLanguage('preferred', defaultLanguage);
|
package/src/index.ts
CHANGED
package/src/random.ts
CHANGED
|
@@ -34,9 +34,9 @@ export function getRandomCharacters(
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Get a random hexadecimal
|
|
37
|
+
* Get a random hexadecimal color
|
|
38
38
|
*/
|
|
39
|
-
export function
|
|
39
|
+
export function getRandomColor(): string {
|
|
40
40
|
return `#${Array.from({length: 6}, getRandomHex).join('')}`;
|
|
41
41
|
}
|
|
42
42
|
|