@manyducks.co/dolla 2.0.0-alpha.6 → 2.0.0-alpha.60
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/README.md +86 -591
- package/dist/core/context.d.ts +144 -0
- package/dist/core/env.d.ts +3 -0
- package/dist/core/index.d.ts +22 -0
- package/dist/core/logger.d.ts +42 -0
- package/dist/core/markup.d.ts +125 -0
- package/dist/core/mount.d.ts +15 -0
- package/dist/core/nodes/dom.d.ts +14 -0
- package/dist/core/nodes/dynamic.d.ts +29 -0
- package/dist/core/nodes/html.d.ts +24 -0
- package/dist/core/nodes/portal.d.ts +19 -0
- package/dist/core/nodes/repeat.d.ts +25 -0
- package/dist/core/nodes/view.d.ts +24 -0
- package/dist/core/ref.d.ts +18 -0
- package/dist/core/signals.d.ts +43 -0
- package/dist/core/symbols.d.ts +2 -0
- package/dist/{views → core/views}/default-crash-view.d.ts +6 -2
- package/dist/core/views/fragment.d.ts +7 -0
- package/dist/fragment-BahD_BJA.js +7 -0
- package/dist/fragment-BahD_BJA.js.map +1 -0
- package/dist/{modules/http.d.ts → http/index.d.ts} +3 -5
- package/dist/http.js +163 -0
- package/dist/http.js.map +1 -0
- package/dist/i18n/index.d.ts +134 -0
- package/dist/i18n.js +318 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.js +105 -1385
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime.d.ts +3 -2
- package/dist/jsx-dev-runtime.js +5 -12
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.d.ts +4 -3
- package/dist/jsx-runtime.js +9 -15
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/logger-MPwl-Xqu.js +524 -0
- package/dist/logger-MPwl-Xqu.js.map +1 -0
- package/dist/markup-BGlfQYQk.js +996 -0
- package/dist/markup-BGlfQYQk.js.map +1 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/router.d.ts +149 -0
- package/dist/{routing.d.ts → router/router.utils.d.ts} +17 -3
- package/dist/router/router.utils.test.d.ts +1 -0
- package/dist/router-BpuJQ6OA.js +516 -0
- package/dist/router-BpuJQ6OA.js.map +1 -0
- package/dist/router.js +8 -0
- package/dist/router.js.map +1 -0
- package/dist/typeChecking-CbltMOUt.js +71 -0
- package/dist/typeChecking-CbltMOUt.js.map +1 -0
- package/dist/typeChecking.d.ts +2 -98
- package/dist/typeChecking.test.d.ts +1 -0
- package/dist/types.d.ts +98 -25
- package/dist/utils.d.ts +20 -3
- package/docs/http.md +29 -0
- package/docs/i18n.md +43 -0
- package/docs/index.md +10 -0
- package/docs/markup.md +16 -0
- package/docs/mixins.md +32 -0
- package/docs/ref.md +93 -0
- package/docs/router.md +80 -0
- package/docs/setup.md +31 -0
- package/docs/signals.md +166 -0
- package/docs/state.md +141 -0
- package/docs/stores.md +62 -0
- package/docs/views.md +208 -0
- package/examples/webcomponent/index.html +14 -0
- package/examples/webcomponent/main.js +165 -0
- package/index.d.ts +2 -2
- package/notes/TODO.md +6 -0
- package/notes/atomic.md +452 -0
- package/notes/context-routes.md +61 -0
- package/notes/custom-nodes.md +17 -0
- package/notes/effection-idea.md +34 -0
- package/notes/elimination.md +33 -0
- package/notes/mixins.md +22 -0
- package/notes/molecule.md +35 -0
- package/notes/observable.md +180 -0
- package/notes/readme-scratch.md +45 -7
- package/notes/route-middleware.md +42 -0
- package/notes/scratch.md +353 -6
- package/notes/splitting.md +5 -0
- package/notes/stores.md +79 -0
- package/package.json +27 -12
- package/vite.config.js +5 -11
- package/build.js +0 -34
- package/dist/index.d.ts +0 -21
- package/dist/markup.d.ts +0 -100
- package/dist/modules/dolla.d.ts +0 -111
- package/dist/modules/language.d.ts +0 -41
- package/dist/modules/render.d.ts +0 -17
- package/dist/modules/router.d.ts +0 -152
- package/dist/nodes/cond.d.ts +0 -26
- package/dist/nodes/html.d.ts +0 -31
- package/dist/nodes/observer.d.ts +0 -29
- package/dist/nodes/outlet.d.ts +0 -22
- package/dist/nodes/portal.d.ts +0 -19
- package/dist/nodes/repeat.d.ts +0 -34
- package/dist/nodes/text.d.ts +0 -19
- package/dist/passthrough-CW8Ezjg-.js +0 -1244
- package/dist/passthrough-CW8Ezjg-.js.map +0 -1
- package/dist/state.d.ts +0 -101
- package/dist/view.d.ts +0 -50
- package/dist/views/passthrough.d.ts +0 -5
- package/tests/state.test.js +0 -135
- /package/dist/{routing.test.d.ts → core/signals.test.d.ts} +0 -0
package/dist/http.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
var b = Object.defineProperty;
|
|
2
|
+
var f = (r) => {
|
|
3
|
+
throw TypeError(r);
|
|
4
|
+
};
|
|
5
|
+
var g = (r, e, t) => e in r ? b(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
6
|
+
var a = (r, e, t) => g(r, typeof e != "symbol" ? e + "" : e, t), m = (r, e, t) => e.has(r) || f("Cannot " + t);
|
|
7
|
+
var d = (r, e, t) => (m(r, e, "read from private field"), t ? t.call(r) : e.get(r)), c = (r, e, t) => e.has(r) ? f("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, t);
|
|
8
|
+
var o = (r, e, t) => (m(r, e, "access private method"), t);
|
|
9
|
+
import { i as w } from "./typeChecking-CbltMOUt.js";
|
|
10
|
+
var l, p, i, h;
|
|
11
|
+
class O {
|
|
12
|
+
constructor() {
|
|
13
|
+
c(this, i);
|
|
14
|
+
c(this, l, []);
|
|
15
|
+
c(this, p, S());
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Adds a new middleware that will apply to subsequent requests.
|
|
19
|
+
* Returns a function to remove this middleware.
|
|
20
|
+
*
|
|
21
|
+
* @param middleware - A middleware function that will intercept requests.
|
|
22
|
+
*/
|
|
23
|
+
use(e) {
|
|
24
|
+
return d(this, l).push(e), () => {
|
|
25
|
+
d(this, l).splice(d(this, l).indexOf(e), 1);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async get(e, t) {
|
|
29
|
+
return o(this, i, h).call(this, "get", e, t);
|
|
30
|
+
}
|
|
31
|
+
async put(e, t) {
|
|
32
|
+
return o(this, i, h).call(this, "put", e, t);
|
|
33
|
+
}
|
|
34
|
+
async patch(e, t) {
|
|
35
|
+
return o(this, i, h).call(this, "patch", e, t);
|
|
36
|
+
}
|
|
37
|
+
async post(e, t) {
|
|
38
|
+
return o(this, i, h).call(this, "post", e, t);
|
|
39
|
+
}
|
|
40
|
+
async delete(e, t) {
|
|
41
|
+
return o(this, i, h).call(this, "delete", e, t);
|
|
42
|
+
}
|
|
43
|
+
async head(e, t) {
|
|
44
|
+
return o(this, i, h).call(this, "head", e, t);
|
|
45
|
+
}
|
|
46
|
+
async options(e, t) {
|
|
47
|
+
return o(this, i, h).call(this, "options", e, t);
|
|
48
|
+
}
|
|
49
|
+
async trace(e, t) {
|
|
50
|
+
return o(this, i, h).call(this, "trace", e, t);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
l = new WeakMap(), p = new WeakMap(), i = new WeakSet(), h = async function(e, t, s) {
|
|
54
|
+
return new x({
|
|
55
|
+
...s,
|
|
56
|
+
method: e,
|
|
57
|
+
uri: t,
|
|
58
|
+
middleware: d(this, l),
|
|
59
|
+
fetch: d(this, p)
|
|
60
|
+
}).fetch();
|
|
61
|
+
};
|
|
62
|
+
function S() {
|
|
63
|
+
if (typeof window < "u" && window.fetch)
|
|
64
|
+
return window.fetch.bind(window);
|
|
65
|
+
if (typeof global < "u" && global.fetch)
|
|
66
|
+
return global.fetch.bind(global);
|
|
67
|
+
throw new Error("Running in neither browser nor node. Please run this app in one of the supported environments.");
|
|
68
|
+
}
|
|
69
|
+
class P extends Error {
|
|
70
|
+
constructor(t) {
|
|
71
|
+
const { status: s, statusText: n, method: u, url: y } = t, _ = `${s} ${n}: Request failed (${u.toUpperCase()} ${y.toString()})`;
|
|
72
|
+
super(_);
|
|
73
|
+
a(this, "response");
|
|
74
|
+
this.response = t;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
class R {
|
|
78
|
+
constructor(e) {
|
|
79
|
+
a(this, "method");
|
|
80
|
+
a(this, "url");
|
|
81
|
+
a(this, "headers", new Headers());
|
|
82
|
+
a(this, "body");
|
|
83
|
+
this.method = e.method, this.body = e.body, e.uri.startsWith("http") ? this.url = new URL(e.uri) : this.url = new URL(e.uri, window.location.origin), this._applyHeaders(e.headers), this._applyQueryParams(e.query);
|
|
84
|
+
}
|
|
85
|
+
get isSameOrigin() {
|
|
86
|
+
return this.url.origin === window.location.origin;
|
|
87
|
+
}
|
|
88
|
+
_applyHeaders(e) {
|
|
89
|
+
if (e != null)
|
|
90
|
+
if (e instanceof Map || e instanceof Headers)
|
|
91
|
+
e.forEach((t, s) => {
|
|
92
|
+
this.headers.set(s, t);
|
|
93
|
+
});
|
|
94
|
+
else if (w(e))
|
|
95
|
+
for (const t in e) {
|
|
96
|
+
const s = e[t];
|
|
97
|
+
s instanceof Date ? this.headers.set(t, s.toISOString()) : s != null && this.headers.set(t, String(s));
|
|
98
|
+
}
|
|
99
|
+
else
|
|
100
|
+
throw new TypeError(`Unknown headers type. Got: ${e}`);
|
|
101
|
+
}
|
|
102
|
+
_applyQueryParams(e) {
|
|
103
|
+
if (e != null)
|
|
104
|
+
if (e instanceof Map || e instanceof URLSearchParams)
|
|
105
|
+
e.forEach((t, s) => {
|
|
106
|
+
this.url.searchParams.set(s, t);
|
|
107
|
+
});
|
|
108
|
+
else if (w(e))
|
|
109
|
+
for (const t in e) {
|
|
110
|
+
const s = e[t];
|
|
111
|
+
s instanceof Date ? this.url.searchParams.set(t, s.toISOString()) : s != null && this.url.searchParams.set(t, String(s));
|
|
112
|
+
}
|
|
113
|
+
else
|
|
114
|
+
throw new TypeError(`Unknown query params type. Got: ${e}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
class x {
|
|
118
|
+
constructor(e) {
|
|
119
|
+
a(this, "_middleware");
|
|
120
|
+
a(this, "_fetch");
|
|
121
|
+
a(this, "_request");
|
|
122
|
+
a(this, "_response");
|
|
123
|
+
this._middleware = e.middleware, this._fetch = e.fetch, this._request = new R(e);
|
|
124
|
+
}
|
|
125
|
+
async fetch() {
|
|
126
|
+
if (this._middleware.length > 0) {
|
|
127
|
+
const e = (t = 0) => {
|
|
128
|
+
const s = this._middleware[t], n = this._middleware[t + 1] ? e(t + 1) : this._handler.bind(this);
|
|
129
|
+
return async () => s(this._request, async () => (await n(), this._response));
|
|
130
|
+
};
|
|
131
|
+
await e()();
|
|
132
|
+
} else
|
|
133
|
+
await this._handler();
|
|
134
|
+
if (this._response.status < 200 || this._response.status >= 400)
|
|
135
|
+
throw new P(this._response);
|
|
136
|
+
return this._response;
|
|
137
|
+
}
|
|
138
|
+
// This is the function that performs the actual request after the final middleware.
|
|
139
|
+
async _handler() {
|
|
140
|
+
let e;
|
|
141
|
+
const t = this._request;
|
|
142
|
+
!t.headers.has("content-type") && w(t.body) ? (t.headers.set("content-type", "application/json"), e = JSON.stringify(t.body)) : e = t.body;
|
|
143
|
+
const s = await this._fetch(t.url.toString(), {
|
|
144
|
+
method: t.method,
|
|
145
|
+
headers: t.headers,
|
|
146
|
+
body: e
|
|
147
|
+
}), n = s.headers.get("content-type");
|
|
148
|
+
let u;
|
|
149
|
+
n != null && n.includes("application/json") ? u = await s.json() : n != null && n.includes("application/x-www-form-urlencoded") ? u = await s.formData() : u = await s.text(), this._response = {
|
|
150
|
+
method: t.method,
|
|
151
|
+
url: t.url,
|
|
152
|
+
status: s.status,
|
|
153
|
+
statusText: s.statusText,
|
|
154
|
+
headers: s.headers,
|
|
155
|
+
body: u
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
export {
|
|
160
|
+
O as HTTP,
|
|
161
|
+
P as HTTPResponseError
|
|
162
|
+
};
|
|
163
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sources":["../src/http/index.ts"],"sourcesContent":["import { isObject } from \"../typeChecking.js\";\n\n/**\n * A simple HTTP client with middleware support. Middleware applies to all requests made through this store,\n * so it's the perfect way to handle things like auth headers and permission checks for API calls.\n */\nexport class HTTP {\n #middleware: HTTPMiddleware[] = [];\n #fetch = getDefaultFetch();\n\n /**\n * Adds a new middleware that will apply to subsequent requests.\n * Returns a function to remove this middleware.\n *\n * @param middleware - A middleware function that will intercept requests.\n */\n use(fn: HTTPMiddleware) {\n this.#middleware.push(fn);\n\n // Call returned function to remove this middleware for subsequent requests.\n return () => {\n this.#middleware.splice(this.#middleware.indexOf(fn), 1);\n };\n }\n\n async get<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"get\", uri, options);\n }\n\n async put<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"put\", uri, options);\n }\n\n async patch<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"patch\", uri, options);\n }\n\n async post<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"post\", uri, options);\n }\n\n async delete<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"delete\", uri, options);\n }\n\n async head<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"head\", uri, options);\n }\n\n async options<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"options\", uri, options);\n }\n\n async trace<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"trace\", uri, options);\n }\n\n async #request<ResBody, ReqBody>(method: string, uri: string, options?: RequestOptions<any>) {\n const runner = new Runner<ResBody, ReqBody>({\n ...options,\n method,\n uri,\n middleware: this.#middleware,\n fetch: this.#fetch,\n });\n return runner.fetch();\n }\n}\n\nfunction getDefaultFetch(): typeof window.fetch {\n if (typeof window !== \"undefined\" && window.fetch) {\n return window.fetch.bind(window);\n }\n\n if (typeof global !== \"undefined\" && global.fetch) {\n return global.fetch.bind(global);\n }\n\n throw new Error(\"Running in neither browser nor node. Please run this app in one of the supported environments.\");\n}\n\n/*====================*\\\n|| Request ||\n\\*====================*/\n\nexport type HTTPMiddleware = (\n request: HTTPRequest<unknown>,\n next: () => Promise<HTTPResponse<unknown>>,\n) => void | Promise<void>;\n\nexport interface RequestOptions<ReqBody> {\n /**\n * Body to send with the request.\n */\n body?: ReqBody;\n\n /**\n * Headers to send with the request.\n */\n headers?: Record<string, any> | Headers;\n\n /**\n * Query params to interpolate into the URL.\n */\n query?: Record<string, any> | URLSearchParams;\n}\n\nexport interface HTTPRequest<Body> {\n method: string;\n url: URL;\n headers: Headers;\n body: Body;\n}\n\nexport interface HTTPResponse<Body> {\n method: string;\n url: URL;\n headers: Headers;\n status: number;\n statusText: string;\n body: Body;\n}\n\ninterface MakeRequestConfig<ReqBody> extends RequestOptions<ReqBody> {\n method: string;\n uri: string;\n middleware: HTTPMiddleware[];\n fetch: typeof window.fetch;\n}\n\nexport class HTTPResponseError extends Error {\n response;\n\n constructor(response: HTTPResponse<any>) {\n const { status, statusText, method, url } = response;\n const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${url.toString()})`;\n\n super(message);\n\n this.response = response;\n }\n}\n\nclass Request<ReqBody> implements HTTPRequest<ReqBody> {\n method: string;\n url: URL;\n headers = new Headers();\n body!: ReqBody;\n\n get isSameOrigin() {\n return this.url.origin === window.location.origin;\n }\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this.method = config.method;\n this.body = config.body!;\n if (config.uri.startsWith(\"http\")) {\n this.url = new URL(config.uri);\n } else {\n this.url = new URL(config.uri, window.location.origin);\n }\n\n this._applyHeaders(config.headers);\n this._applyQueryParams(config.query);\n }\n\n private _applyHeaders(headers: any) {\n if (headers == null) return;\n\n if (headers instanceof Map || headers instanceof Headers) {\n headers.forEach((value, key) => {\n this.headers.set(key, value);\n });\n } else if (isObject(headers)) {\n for (const name in headers) {\n const value = headers[name];\n if (value instanceof Date) {\n this.headers.set(name, value.toISOString());\n } else if (value != null) {\n this.headers.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown headers type. Got: ${headers}`);\n }\n }\n\n private _applyQueryParams(query: any) {\n if (query == null) return;\n\n if (query instanceof Map || query instanceof URLSearchParams) {\n query.forEach((value, key) => {\n this.url.searchParams.set(key, value);\n });\n } else if (isObject(query)) {\n for (const name in query) {\n const value = query[name];\n if (value instanceof Date) {\n this.url.searchParams.set(name, value.toISOString());\n } else if (value != null) {\n this.url.searchParams.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown query params type. Got: ${query}`);\n }\n }\n}\n\nclass Runner<ResBody, ReqBody> {\n private _middleware;\n private _fetch;\n\n private _request: Request<ReqBody>;\n private _response?: HTTPResponse<ResBody>;\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this._middleware = config.middleware;\n this._fetch = config.fetch;\n\n this._request = new Request(config);\n }\n\n async fetch() {\n if (this._middleware.length > 0) {\n const mount = (index = 0) => {\n const current = this._middleware[index];\n const next = this._middleware[index + 1] ? mount(index + 1) : this._handler.bind(this);\n\n return async () =>\n current(this._request, async () => {\n await next();\n return this._response!;\n });\n };\n\n await mount()();\n } else {\n await this._handler();\n }\n\n if (this._response!.status < 200 || this._response!.status >= 400) {\n throw new HTTPResponseError(this._response!);\n }\n\n return this._response!;\n }\n\n // This is the function that performs the actual request after the final middleware.\n private async _handler() {\n let reqBody: BodyInit;\n\n const req = this._request;\n\n if (!req.headers.has(\"content-type\") && isObject(req.body)) {\n // Auto-detect JSON bodies and encode as a string with correct headers.\n req.headers.set(\"content-type\", \"application/json\");\n reqBody = JSON.stringify(req.body);\n } else {\n reqBody = req.body as BodyInit;\n }\n\n const fetched = await this._fetch(req.url.toString(), {\n method: req.method,\n headers: req.headers,\n body: reqBody,\n });\n\n // Auto-parse response body based on content-type header\n const contentType = fetched.headers.get(\"content-type\");\n\n let body: ResBody;\n\n if (contentType?.includes(\"application/json\")) {\n body = await fetched.json();\n } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n body = (await fetched.formData()) as ResBody;\n } else {\n body = (await fetched.text()) as ResBody;\n }\n\n this._response = {\n method: req.method,\n url: req.url,\n status: fetched.status,\n statusText: fetched.statusText,\n headers: fetched.headers,\n body,\n };\n }\n}\n"],"names":["HTTP","__privateAdd","_HTTP_instances","_middleware","_fetch","getDefaultFetch","fn","__privateGet","uri","options","__privateMethod","request_fn","method","Runner","HTTPResponseError","response","status","statusText","url","message","__publicField","Request","config","headers","value","key","isObject","name","query","mount","index","current","next","reqBody","req","fetched","contentType","body"],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { type MaybeSignal, type Signal } from "../core/signals.js";
|
|
2
|
+
/**
|
|
3
|
+
* A JSON object of translated strings. Values can be string templates or nested objects.
|
|
4
|
+
*/
|
|
5
|
+
interface LocalizedStrings extends Record<string, string | LocalizedStrings> {
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A formatter to be applied to a variable.
|
|
9
|
+
*/
|
|
10
|
+
type Format = {
|
|
11
|
+
name: string;
|
|
12
|
+
options: Record<string, any>;
|
|
13
|
+
};
|
|
14
|
+
export interface TranslationConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Name of the locale this translation is for (BCP 47 locale names recommended).
|
|
17
|
+
*/
|
|
18
|
+
locale: string;
|
|
19
|
+
/**
|
|
20
|
+
* An object with translated strings for this language.
|
|
21
|
+
*/
|
|
22
|
+
strings?: LocalizedStrings;
|
|
23
|
+
/**
|
|
24
|
+
* A callback function that returns a Promise that resolves to the translation object for this language.
|
|
25
|
+
*/
|
|
26
|
+
fetch?: () => Promise<LocalizedStrings>;
|
|
27
|
+
/**
|
|
28
|
+
* Path to a JSON file with translated strings for this language.
|
|
29
|
+
*/
|
|
30
|
+
path?: string;
|
|
31
|
+
}
|
|
32
|
+
export type I18nSetupOptions = {
|
|
33
|
+
/**
|
|
34
|
+
* Default locale to load on startup
|
|
35
|
+
*/
|
|
36
|
+
locale?: string | null;
|
|
37
|
+
translations: TranslationConfig[];
|
|
38
|
+
};
|
|
39
|
+
export type TOptions = {
|
|
40
|
+
/**
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
count?: MaybeSignal<number>;
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
context?: MaybeSignal<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Override formats specified in the template with the ones in the array for each named variable.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* t("example_key", {
|
|
53
|
+
* count: 5,
|
|
54
|
+
* formatOverrides: {
|
|
55
|
+
* count: [ { name: "datetime", options: { style: "currency", currency: "JPY" } } ]
|
|
56
|
+
* }
|
|
57
|
+
* });
|
|
58
|
+
*/
|
|
59
|
+
formatOverrides?: MaybeSignal<Record<string, Record<string, Format[]>>>;
|
|
60
|
+
[value: string]: MaybeSignal<any>;
|
|
61
|
+
};
|
|
62
|
+
export type Formatter = (locale: string, value: unknown, options: Record<string, any>) => string;
|
|
63
|
+
/**
|
|
64
|
+
* Dolla's I(nternationalizatio)n module. Manages language translations and locale-based formatting.
|
|
65
|
+
*/
|
|
66
|
+
declare class I18n {
|
|
67
|
+
#private;
|
|
68
|
+
readonly $locale: Signal<string>;
|
|
69
|
+
constructor();
|
|
70
|
+
get locales(): string[];
|
|
71
|
+
setup(options: I18nSetupOptions): Promise<void>;
|
|
72
|
+
setLocale(name: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Returns a State containing the value at `key`.
|
|
75
|
+
|
|
76
|
+
* @param selector - Key to the translated value.
|
|
77
|
+
* @param options - A map of `{{placeholder}}` names and the values to replace them with.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* const $value = t("your.key.here", { count: 5 });
|
|
81
|
+
*/
|
|
82
|
+
t(selector: string, options?: TOptions): Signal<string>;
|
|
83
|
+
/**
|
|
84
|
+
* Add a custom format callback.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* Dolla.i18n.addFormat("uppercase", (locale, value, options) => {
|
|
88
|
+
* return value.toUpperCase();
|
|
89
|
+
* });
|
|
90
|
+
*
|
|
91
|
+
* {
|
|
92
|
+
* "greeting": "Hello, {{name|uppercase}}!"
|
|
93
|
+
* }
|
|
94
|
+
*
|
|
95
|
+
* t("greeting", {name: "world"}); // State<"Hello, WORLD!">
|
|
96
|
+
*/
|
|
97
|
+
addFormat(name: string, callback: (locale: string, value: unknown, options: Record<string, any>) => string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Creates an `Intl.Collator` configured for the current locale.
|
|
100
|
+
* NOTE: The locale is tracked if called within a signal tracking context.
|
|
101
|
+
*
|
|
102
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#options
|
|
103
|
+
*/
|
|
104
|
+
collator(options?: Intl.CollatorOptions): Intl.Collator;
|
|
105
|
+
/**
|
|
106
|
+
* Formats a number for the current locale. Uses `Intl.NumberFormat` under the hood.
|
|
107
|
+
*
|
|
108
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
|
|
109
|
+
*/
|
|
110
|
+
number(count: MaybeSignal<number | bigint>, options?: Intl.NumberFormatOptions): Signal<string>;
|
|
111
|
+
/**
|
|
112
|
+
* Formats a date for the current locale. Uses `Intl.DateTimeFormat` under the hood.
|
|
113
|
+
*
|
|
114
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* const date = new Date();
|
|
118
|
+
* const $formatted = Dolla.i18n.dateTime(date, { dateFormat: "short" });
|
|
119
|
+
*/
|
|
120
|
+
dateTime(date?: MaybeSignal<string | number | Date | undefined>, options?: Intl.DateTimeFormatOptions): Signal<string>;
|
|
121
|
+
/**
|
|
122
|
+
* Formats a list for the current locale. Uses `Intl.ListFormat` under the hood.
|
|
123
|
+
*
|
|
124
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* const list = new Date();
|
|
128
|
+
* const $formatted = Dolla.i18n.list(list, { });
|
|
129
|
+
*/
|
|
130
|
+
list(list: MaybeSignal<Iterable<string>>, options?: Intl.ListFormatOptions): Signal<string>;
|
|
131
|
+
}
|
|
132
|
+
export declare const i18n: I18n;
|
|
133
|
+
export declare const t: (selector: string, options?: TOptions) => Signal<string>;
|
|
134
|
+
export {};
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
var B = Object.defineProperty;
|
|
2
|
+
var D = (o) => {
|
|
3
|
+
throw TypeError(o);
|
|
4
|
+
};
|
|
5
|
+
var J = (o, t, e) => t in o ? B(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
6
|
+
var O = (o, t, e) => J(o, typeof t != "symbol" ? t + "" : t, e), _ = (o, t, e) => t.has(o) || D("Cannot " + e);
|
|
7
|
+
var i = (o, t, e) => (_(o, t, "read from private field"), e ? e.call(o) : t.get(o)), m = (o, t, e) => t.has(o) ? D("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(o) : t.set(o, e), N = (o, t, e, n) => (_(o, t, "write to private field"), n ? n.call(o, e) : t.set(o, e), e), g = (o, t, e) => (_(o, t, "access private method"), e);
|
|
8
|
+
import { $, h as K, d as Q, g as x } from "./logger-MPwl-Xqu.js";
|
|
9
|
+
import { b as C, i as j, c as U, t as P } from "./typeChecking-CbltMOUt.js";
|
|
10
|
+
var I, F, p, S, G;
|
|
11
|
+
class W {
|
|
12
|
+
constructor(t) {
|
|
13
|
+
m(this, p);
|
|
14
|
+
O(this, "config");
|
|
15
|
+
m(this, I, !1);
|
|
16
|
+
m(this, F, /* @__PURE__ */ new Map());
|
|
17
|
+
this.config = t;
|
|
18
|
+
}
|
|
19
|
+
async load() {
|
|
20
|
+
let t;
|
|
21
|
+
if (!i(this, I)) {
|
|
22
|
+
if (j(this.config.strings))
|
|
23
|
+
t = this.config.strings;
|
|
24
|
+
else if (U(this.config.fetch)) {
|
|
25
|
+
if (t = await this.config.fetch(), !j(t))
|
|
26
|
+
throw new Error(`Fetch function did not return an object of language strings: ${t}`);
|
|
27
|
+
} else if (C(this.config.path)) {
|
|
28
|
+
const e = await fetch(this.config.path);
|
|
29
|
+
if (e.ok) {
|
|
30
|
+
const n = await e.json();
|
|
31
|
+
if (j(n))
|
|
32
|
+
t = n;
|
|
33
|
+
else
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Language path '${this.config.path}' did not return an object of language strings: ${n}`
|
|
36
|
+
);
|
|
37
|
+
} else
|
|
38
|
+
throw new Error("HTTP request failed.");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (t) {
|
|
42
|
+
const e = g(this, p, S).call(this, t);
|
|
43
|
+
for (const n of e)
|
|
44
|
+
i(this, F).set(n[0], n[1]);
|
|
45
|
+
} else
|
|
46
|
+
throw new Error("Language could not be loaded.");
|
|
47
|
+
}
|
|
48
|
+
getTemplate(t) {
|
|
49
|
+
return i(this, F).get(t) ?? {
|
|
50
|
+
segments: [{ type: 0, text: `[MISSING: ${t}]` }]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
hasTemplate(t) {
|
|
54
|
+
return i(this, F).has(t);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
I = new WeakMap(), F = new WeakMap(), p = new WeakSet(), S = function(t, e = []) {
|
|
58
|
+
const n = [];
|
|
59
|
+
for (const a in t)
|
|
60
|
+
switch (P(t[a])) {
|
|
61
|
+
case "string":
|
|
62
|
+
n.push([[...e, a].join("."), g(this, p, G).call(this, t[a])]);
|
|
63
|
+
break;
|
|
64
|
+
case "object":
|
|
65
|
+
n.push(...g(this, p, S).call(this, t[a], [...e, a]));
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Expected to find a string or object at ${[...e, a].join(".")}. Got: ${P(t[a])}`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return n;
|
|
73
|
+
}, G = function(t) {
|
|
74
|
+
let e;
|
|
75
|
+
((f) => {
|
|
76
|
+
f[f.Static = 0] = "Static", f[f.ValueName = 1] = "ValueName", f[f.FormatName = 2] = "FormatName", f[f.FormatOptionName = 3] = "FormatOptionName", f[f.FormatOptionValue = 4] = "FormatOptionValue", f[f.FormatOptionEnd = 5] = "FormatOptionEnd";
|
|
77
|
+
})(e || (e = {}));
|
|
78
|
+
const n = {
|
|
79
|
+
segments: []
|
|
80
|
+
};
|
|
81
|
+
let a = "", s = 0, r = 0, c, w, l;
|
|
82
|
+
const k = () => {
|
|
83
|
+
c = {
|
|
84
|
+
type: 1,
|
|
85
|
+
name: "",
|
|
86
|
+
formats: []
|
|
87
|
+
};
|
|
88
|
+
}, y = () => {
|
|
89
|
+
w = {
|
|
90
|
+
name: "",
|
|
91
|
+
options: {}
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
for (; s < t.length; ) {
|
|
95
|
+
if (r !== 0 && t[s] === " ") {
|
|
96
|
+
s++;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
switch (r) {
|
|
100
|
+
case 0:
|
|
101
|
+
t[s] === "{" && t[s + 1] === "{" ? (r = 1, s += 2, a.length > 0 && (n.segments.push({ type: 0, text: a }), a = ""), k()) : (a += t[s], s++);
|
|
102
|
+
break;
|
|
103
|
+
case 1:
|
|
104
|
+
t[s] === "|" ? (r = 2, s += 1, c.name = a, a = "", y()) : t[s] === "}" && t[s + 1] === "}" ? (r = 0, s += 2, c.name = a, a = "", n.segments.push(c)) : (a += t[s], s++);
|
|
105
|
+
break;
|
|
106
|
+
case 2:
|
|
107
|
+
t[s] === "(" ? (r = 3, s += 1, w.name = a, a = "") : t[s] === "}" && t[s + 1] === "}" ? (r = 0, s += 2, c.formats.push(w), n.segments.push(c)) : (a += t[s], s++);
|
|
108
|
+
break;
|
|
109
|
+
case 3:
|
|
110
|
+
t[s] === ")" || (t[s] === ":" ? (r = 4, s += 1, l = a, a = "") : t[s] === "}" && t[s + 1] === "}" || (a += t[s], s++));
|
|
111
|
+
break;
|
|
112
|
+
case 4:
|
|
113
|
+
t[s] === ")" ? (r = 5, s += 1, w.options[l] = a, a = "", c.formats.push(w)) : t[s] === "," ? (r = 3, s += 1, w.options[l] = a, a = "") : t[s] === "}" && t[s + 1] === "}" || (a += t[s], s++);
|
|
114
|
+
break;
|
|
115
|
+
case 5:
|
|
116
|
+
t[s] === "|" ? (r = 2, s += 1, y()) : t[s] === "}" && t[s + 1] === "}" && (r = 0, s += 2, n.segments.push(c));
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return r === 0 && a.length > 0 && n.segments.push({ type: 0, text: a }), n;
|
|
121
|
+
};
|
|
122
|
+
var b, h, E, T, v, d, u, H, L, V, M, A;
|
|
123
|
+
class X {
|
|
124
|
+
constructor() {
|
|
125
|
+
m(this, u);
|
|
126
|
+
m(this, b);
|
|
127
|
+
m(this, h, /* @__PURE__ */ new Map());
|
|
128
|
+
m(this, E, []);
|
|
129
|
+
m(this, T, /* @__PURE__ */ new Map());
|
|
130
|
+
m(this, v, "auto");
|
|
131
|
+
m(this, d, $("en"));
|
|
132
|
+
O(this, "$locale", $(i(this, d)));
|
|
133
|
+
N(this, b, K("dolla.i18n")), this.addFormat("number", (t, e, n) => g(this, u, L).call(this, Number(e), n)), this.addFormat("datetime", (t, e, n) => g(this, u, V).call(this, e, n)), this.addFormat("list", (t, e, n) => g(this, u, M).call(this, e, n));
|
|
134
|
+
}
|
|
135
|
+
get locales() {
|
|
136
|
+
return [...i(this, h).keys()];
|
|
137
|
+
}
|
|
138
|
+
async setup(t) {
|
|
139
|
+
if (t.translations.forEach((e) => {
|
|
140
|
+
i(this, h).set(e.locale, new W(e));
|
|
141
|
+
}), t.locale && t.locale !== "auto") {
|
|
142
|
+
if (!t.translations.some((n) => n.locale === t.locale))
|
|
143
|
+
throw new Error(`Initial locale '${t.locale}' is not registered in the locales array.`);
|
|
144
|
+
N(this, v, t.locale);
|
|
145
|
+
}
|
|
146
|
+
i(this, b).info(
|
|
147
|
+
`${i(this, h).size} language${i(this, h).size === 1 ? "" : "s"} supported: '${[...i(this, h).keys()].join("', '")}'`
|
|
148
|
+
), i(this, h).size > 0 && await this.setLocale(i(this, v));
|
|
149
|
+
}
|
|
150
|
+
async setLocale(t) {
|
|
151
|
+
var a;
|
|
152
|
+
let e;
|
|
153
|
+
if (t === "auto") {
|
|
154
|
+
let s = [];
|
|
155
|
+
if (typeof navigator < "u") {
|
|
156
|
+
const r = navigator;
|
|
157
|
+
((a = r.languages) == null ? void 0 : a.length) > 0 ? s.push(...r.languages) : r.language ? s.push(r.language) : r.browserLanguage ? s.push(r.browserLanguage) : r.userLanguage && s.push(r.userLanguage);
|
|
158
|
+
}
|
|
159
|
+
for (const r of s)
|
|
160
|
+
i(this, h).has(r) && (e = r);
|
|
161
|
+
} else
|
|
162
|
+
i(this, h).has(t) && (e = t);
|
|
163
|
+
if (e == null) {
|
|
164
|
+
const s = i(this, h).keys().next().value;
|
|
165
|
+
s && (e = s);
|
|
166
|
+
}
|
|
167
|
+
if (!e || !i(this, h).has(e))
|
|
168
|
+
throw new Error(`Locale '${t}' has no translation.`);
|
|
169
|
+
const n = i(this, h).get(e);
|
|
170
|
+
try {
|
|
171
|
+
await n.load(), N(this, E, []), i(this, d).call(this, e), i(this, b).info("set language to " + e);
|
|
172
|
+
} catch (s) {
|
|
173
|
+
s instanceof Error && i(this, b).crash(s);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Returns a State containing the value at `key`.
|
|
178
|
+
|
|
179
|
+
* @param selector - Key to the translated value.
|
|
180
|
+
* @param options - A map of `{{placeholder}}` names and the values to replace them with.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* const $value = t("your.key.here", { count: 5 });
|
|
184
|
+
*/
|
|
185
|
+
t(t, e) {
|
|
186
|
+
if (this === void 0)
|
|
187
|
+
throw new Error(
|
|
188
|
+
`The 't' function cannot be destructured. If you need a standalone version you can import it like so: 'import { t } from "@manyducks.co/dolla"'`
|
|
189
|
+
);
|
|
190
|
+
return $(() => {
|
|
191
|
+
const n = {};
|
|
192
|
+
for (const a in e)
|
|
193
|
+
n[a] = x(e[a]);
|
|
194
|
+
return g(this, u, H).call(this, i(this, d).call(this), t, n);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Add a custom format callback.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* Dolla.i18n.addFormat("uppercase", (locale, value, options) => {
|
|
202
|
+
* return value.toUpperCase();
|
|
203
|
+
* });
|
|
204
|
+
*
|
|
205
|
+
* {
|
|
206
|
+
* "greeting": "Hello, {{name|uppercase}}!"
|
|
207
|
+
* }
|
|
208
|
+
*
|
|
209
|
+
* t("greeting", {name: "world"}); // State<"Hello, WORLD!">
|
|
210
|
+
*/
|
|
211
|
+
addFormat(t, e) {
|
|
212
|
+
i(this, T).set(t, e);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Creates an `Intl.Collator` configured for the current locale.
|
|
216
|
+
* NOTE: The locale is tracked if called within a signal tracking context.
|
|
217
|
+
*
|
|
218
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#options
|
|
219
|
+
*/
|
|
220
|
+
collator(t) {
|
|
221
|
+
return new Intl.Collator(i(this, d).call(this), t);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Formats a number for the current locale. Uses `Intl.NumberFormat` under the hood.
|
|
225
|
+
*
|
|
226
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
|
|
227
|
+
*/
|
|
228
|
+
number(t, e) {
|
|
229
|
+
return $(() => g(this, u, L).call(this, x(t), e));
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Formats a date for the current locale. Uses `Intl.DateTimeFormat` under the hood.
|
|
233
|
+
*
|
|
234
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* const date = new Date();
|
|
238
|
+
* const $formatted = Dolla.i18n.dateTime(date, { dateFormat: "short" });
|
|
239
|
+
*/
|
|
240
|
+
dateTime(t, e) {
|
|
241
|
+
return $(() => g(this, u, V).call(this, x(t), e));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Formats a list for the current locale. Uses `Intl.ListFormat` under the hood.
|
|
245
|
+
*
|
|
246
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* const list = new Date();
|
|
250
|
+
* const $formatted = Dolla.i18n.list(list, { });
|
|
251
|
+
*/
|
|
252
|
+
list(t, e) {
|
|
253
|
+
return $(() => g(this, u, M).call(this, x(t), e));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
b = new WeakMap(), h = new WeakMap(), E = new WeakMap(), T = new WeakMap(), v = new WeakMap(), d = new WeakMap(), u = new WeakSet(), H = function(t, e, n) {
|
|
257
|
+
var w;
|
|
258
|
+
const a = g(this, u, A).call(this, e, n);
|
|
259
|
+
if (a) return a;
|
|
260
|
+
const s = i(this, h).get(t);
|
|
261
|
+
if (n.context != null && (e += "_" + n.context), n.count != null)
|
|
262
|
+
if (n.ordinal) {
|
|
263
|
+
const l = `${e}_ordinal_(=${n.count})`;
|
|
264
|
+
s.hasTemplate(l) ? e = l : e += "_ordinal_" + new Intl.PluralRules(t, { type: "ordinal" }).select(n.count);
|
|
265
|
+
} else {
|
|
266
|
+
const l = `${e}_(=${n.count})`;
|
|
267
|
+
s.hasTemplate(l) ? e = l : e += "_" + new Intl.PluralRules(t).select(n.count);
|
|
268
|
+
}
|
|
269
|
+
const r = s.getTemplate(e);
|
|
270
|
+
let c = "";
|
|
271
|
+
for (const l of r.segments)
|
|
272
|
+
if (l.type === 0)
|
|
273
|
+
c += l.text;
|
|
274
|
+
else if (l.type === 1) {
|
|
275
|
+
let k = Y(n, l.name);
|
|
276
|
+
const y = ((w = n.formatOverrides) == null ? void 0 : w[l.name]) ?? [...l.formats];
|
|
277
|
+
l.name === "count" && y.length === 0 && y.push({ name: "number", options: {} });
|
|
278
|
+
for (const f of y) {
|
|
279
|
+
const R = i(this, T).get(f.name);
|
|
280
|
+
if (R == null) {
|
|
281
|
+
const z = new Error(
|
|
282
|
+
`Failed to load format '${f.name}' when processing '${e}', template: ${r}`
|
|
283
|
+
);
|
|
284
|
+
throw i(this, b).crash(z), z;
|
|
285
|
+
}
|
|
286
|
+
k = R(t, k, f.options);
|
|
287
|
+
}
|
|
288
|
+
c += k;
|
|
289
|
+
}
|
|
290
|
+
return c;
|
|
291
|
+
}, L = function(t, e) {
|
|
292
|
+
return new Intl.NumberFormat(i(this, d).call(this), e).format(t);
|
|
293
|
+
}, V = function(t, e) {
|
|
294
|
+
return new Intl.DateTimeFormat(i(this, d).call(this), e).format(C(t) ? new Date(t) : t);
|
|
295
|
+
}, M = function(t, e) {
|
|
296
|
+
return new Intl.ListFormat(i(this, d).call(this), e).format(t);
|
|
297
|
+
}, // relativeTime(): State<string> {
|
|
298
|
+
// }
|
|
299
|
+
A = function(t, e) {
|
|
300
|
+
for (const n of i(this, E))
|
|
301
|
+
if (n[0] === t && Q(n[1], e))
|
|
302
|
+
return n[2];
|
|
303
|
+
};
|
|
304
|
+
function Y(o, t) {
|
|
305
|
+
const e = String(t).split(/[\.\[\]]/).filter((a) => a.trim() !== "");
|
|
306
|
+
let n = o;
|
|
307
|
+
for (; e.length > 0; ) {
|
|
308
|
+
const a = e.shift();
|
|
309
|
+
n != null ? n = n[a] : n = void 0;
|
|
310
|
+
}
|
|
311
|
+
return n;
|
|
312
|
+
}
|
|
313
|
+
const q = new X(), st = q.t.bind(q);
|
|
314
|
+
export {
|
|
315
|
+
q as i18n,
|
|
316
|
+
st as t
|
|
317
|
+
};
|
|
318
|
+
//# sourceMappingURL=i18n.js.map
|