@_linked/translation 0.2.2
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 +102 -0
- package/lib/cjs/data/translation.json +8 -0
- package/lib/esm/archive.d.ts +133 -0
- package/lib/esm/archive.js +567 -0
- package/lib/esm/archive.js.map +1 -0
- package/lib/esm/authorization.d.ts +12 -0
- package/lib/esm/authorization.js +10 -0
- package/lib/esm/authorization.js.map +1 -0
- package/lib/esm/backend.d.ts +1 -0
- package/lib/esm/backend.js +3 -0
- package/lib/esm/backend.js.map +1 -0
- package/lib/esm/cdn-loader.d.ts +40 -0
- package/lib/esm/cdn-loader.js +200 -0
- package/lib/esm/cdn-loader.js.map +1 -0
- package/lib/esm/checks.d.ts +56 -0
- package/lib/esm/checks.js +288 -0
- package/lib/esm/checks.js.map +1 -0
- package/lib/esm/compile.d.ts +64 -0
- package/lib/esm/compile.js +99 -0
- package/lib/esm/compile.js.map +1 -0
- package/lib/esm/core/messages.d.ts +25 -0
- package/lib/esm/core/messages.js +76 -0
- package/lib/esm/core/messages.js.map +1 -0
- package/lib/esm/data/translation.json +8 -0
- package/lib/esm/discovery.d.ts +97 -0
- package/lib/esm/discovery.js +365 -0
- package/lib/esm/discovery.js.map +1 -0
- package/lib/esm/exchange.d.ts +100 -0
- package/lib/esm/exchange.js +223 -0
- package/lib/esm/exchange.js.map +1 -0
- package/lib/esm/export.d.ts +28 -0
- package/lib/esm/export.js +92 -0
- package/lib/esm/export.js.map +1 -0
- package/lib/esm/formats/csv.d.ts +8 -0
- package/lib/esm/formats/csv.js +397 -0
- package/lib/esm/formats/csv.js.map +1 -0
- package/lib/esm/formats/json.d.ts +30 -0
- package/lib/esm/formats/json.js +459 -0
- package/lib/esm/formats/json.js.map +1 -0
- package/lib/esm/formats/xliff.d.ts +12 -0
- package/lib/esm/formats/xliff.js +577 -0
- package/lib/esm/formats/xliff.js.map +1 -0
- package/lib/esm/import.d.ts +197 -0
- package/lib/esm/import.js +391 -0
- package/lib/esm/import.js.map +1 -0
- package/lib/esm/index.d.ts +42 -0
- package/lib/esm/index.js +34 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/key-sync-node.d.ts +29 -0
- package/lib/esm/key-sync-node.js +174 -0
- package/lib/esm/key-sync-node.js.map +1 -0
- package/lib/esm/key-sync.d.ts +46 -0
- package/lib/esm/key-sync.js +114 -0
- package/lib/esm/key-sync.js.map +1 -0
- package/lib/esm/key-version.d.ts +50 -0
- package/lib/esm/key-version.js +134 -0
- package/lib/esm/key-version.js.map +1 -0
- package/lib/esm/languages.d.ts +18 -0
- package/lib/esm/languages.js +74 -0
- package/lib/esm/languages.js.map +1 -0
- package/lib/esm/linked-discovery.d.ts +44 -0
- package/lib/esm/linked-discovery.js +267 -0
- package/lib/esm/linked-discovery.js.map +1 -0
- package/lib/esm/message-format.d.ts +41 -0
- package/lib/esm/message-format.js +133 -0
- package/lib/esm/message-format.js.map +1 -0
- package/lib/esm/mt.d.ts +111 -0
- package/lib/esm/mt.js +142 -0
- package/lib/esm/mt.js.map +1 -0
- package/lib/esm/ontologies/translation.d.ts +203 -0
- package/lib/esm/ontologies/translation.js +219 -0
- package/lib/esm/ontologies/translation.js.map +1 -0
- package/lib/esm/package.d.ts +4 -0
- package/lib/esm/package.js +11 -0
- package/lib/esm/package.js.map +1 -0
- package/lib/esm/react.d.ts +55 -0
- package/lib/esm/react.js +127 -0
- package/lib/esm/react.js.map +1 -0
- package/lib/esm/records.d.ts +151 -0
- package/lib/esm/records.js +2 -0
- package/lib/esm/records.js.map +1 -0
- package/lib/esm/release.d.ts +198 -0
- package/lib/esm/release.js +435 -0
- package/lib/esm/release.js.map +1 -0
- package/lib/esm/shape-catalog.d.ts +79 -0
- package/lib/esm/shape-catalog.js +118 -0
- package/lib/esm/shape-catalog.js.map +1 -0
- package/lib/esm/shapes/GlossaryTerm.d.ts +28 -0
- package/lib/esm/shapes/GlossaryTerm.js +94 -0
- package/lib/esm/shapes/GlossaryTerm.js.map +1 -0
- package/lib/esm/shapes/TranslationInventoryOrigin.d.ts +33 -0
- package/lib/esm/shapes/TranslationInventoryOrigin.js +209 -0
- package/lib/esm/shapes/TranslationInventoryOrigin.js.map +1 -0
- package/lib/esm/shapes/TranslationKey.d.ts +92 -0
- package/lib/esm/shapes/TranslationKey.js +194 -0
- package/lib/esm/shapes/TranslationKey.js.map +1 -0
- package/lib/esm/shapes/TranslationKeyVersion.d.ts +19 -0
- package/lib/esm/shapes/TranslationKeyVersion.js +125 -0
- package/lib/esm/shapes/TranslationKeyVersion.js.map +1 -0
- package/lib/esm/shapes/TranslationLanguage.d.ts +15 -0
- package/lib/esm/shapes/TranslationLanguage.js +102 -0
- package/lib/esm/shapes/TranslationLanguage.js.map +1 -0
- package/lib/esm/shapes/TranslationProvider.d.ts +409 -0
- package/lib/esm/shapes/TranslationProvider.js +1376 -0
- package/lib/esm/shapes/TranslationProvider.js.map +1 -0
- package/lib/esm/shapes/TranslationRelease.d.ts +36 -0
- package/lib/esm/shapes/TranslationRelease.js +149 -0
- package/lib/esm/shapes/TranslationRelease.js.map +1 -0
- package/lib/esm/shapes/TranslationRevision.d.ts +39 -0
- package/lib/esm/shapes/TranslationRevision.js +159 -0
- package/lib/esm/shapes/TranslationRevision.js.map +1 -0
- package/lib/esm/shapes/TranslationUnit.d.ts +26 -0
- package/lib/esm/shapes/TranslationUnit.js +111 -0
- package/lib/esm/shapes/TranslationUnit.js.map +1 -0
- package/package.json +134 -0
- package/src/archive.ts +894 -0
- package/src/authorization.ts +33 -0
- package/src/backend.ts +2 -0
- package/src/cdn-loader.ts +264 -0
- package/src/checks.ts +413 -0
- package/src/compile.ts +168 -0
- package/src/core/messages.ts +106 -0
- package/src/data/translation.json +8 -0
- package/src/discovery.ts +594 -0
- package/src/exchange.ts +428 -0
- package/src/export.ts +135 -0
- package/src/formats/csv.ts +459 -0
- package/src/formats/json.ts +587 -0
- package/src/formats/xliff.ts +708 -0
- package/src/import.ts +648 -0
- package/src/index.ts +207 -0
- package/src/key-sync-node.ts +269 -0
- package/src/key-sync.ts +168 -0
- package/src/key-version.ts +206 -0
- package/src/languages.ts +102 -0
- package/src/linked-discovery.ts +385 -0
- package/src/message-format.ts +214 -0
- package/src/mt.ts +248 -0
- package/src/ontologies/translation.ts +234 -0
- package/src/package.ts +19 -0
- package/src/react.tsx +250 -0
- package/src/records.ts +180 -0
- package/src/release.ts +726 -0
- package/src/shape-catalog.ts +198 -0
- package/src/shapes/GlossaryTerm.ts +61 -0
- package/src/shapes/TranslationInventoryOrigin.ts +131 -0
- package/src/shapes/TranslationKey.ts +174 -0
- package/src/shapes/TranslationKeyVersion.ts +77 -0
- package/src/shapes/TranslationLanguage.ts +51 -0
- package/src/shapes/TranslationProvider.ts +1755 -0
- package/src/shapes/TranslationRelease.ts +114 -0
- package/src/shapes/TranslationRevision.ts +105 -0
- package/src/shapes/TranslationUnit.ts +72 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type TranslationLanguageDefinition } from './languages.js';
|
|
2
|
+
/**
|
|
3
|
+
* Compile app translations into publishable per-language payloads + a manifest
|
|
4
|
+
* (Plan 016 P2.2, AD-K/AD-I). Pure and I/O-free: it takes the same
|
|
5
|
+
* `TranslationEntryRecord[]` that `TranslationProvider.listEntries` already
|
|
6
|
+
* produces and emits the `{lang}.json` maps + a content-hashed `manifest.json`.
|
|
7
|
+
* The R2 publish route (P2.3) and the eject-honest CLI (R11) are thin wrappers
|
|
8
|
+
* that read the entries, call this, and write the result.
|
|
9
|
+
*
|
|
10
|
+
* Only `kind:'ui'` keys are published; `kind:'content'` resolves query-time from
|
|
11
|
+
* the app's own dataset (AD-I). Per-language publish policy (AD-K/R9): a
|
|
12
|
+
* `reviewedOnly` language ships the reviewed value else falls back to the English
|
|
13
|
+
* `sourceText` — never a machine/stale draft. Every payload is a COMPLETE
|
|
14
|
+
* catalog (English fallback for anything missing), so it stands alone without the
|
|
15
|
+
* app's inline defaults.
|
|
16
|
+
*/
|
|
17
|
+
import { type TranslationMessages } from './core/messages.js';
|
|
18
|
+
import type { TranslationEntryRecord } from './records.js';
|
|
19
|
+
export type TranslationPayload = TranslationMessages;
|
|
20
|
+
export interface TranslationManifestEntry {
|
|
21
|
+
hash: string;
|
|
22
|
+
dir: 'ltr' | 'rtl';
|
|
23
|
+
count: number;
|
|
24
|
+
}
|
|
25
|
+
export interface TranslationManifest {
|
|
26
|
+
schemaVersion: 1;
|
|
27
|
+
defaultLanguage: string;
|
|
28
|
+
generatedAt?: string;
|
|
29
|
+
languageResources?: TranslationLanguageDefinition[];
|
|
30
|
+
languages: Record<string, TranslationManifestEntry>;
|
|
31
|
+
}
|
|
32
|
+
export interface CompileOptions {
|
|
33
|
+
languageResources?: TranslationLanguageDefinition[];
|
|
34
|
+
languages: string[];
|
|
35
|
+
defaultLanguage: string;
|
|
36
|
+
/** BCP-47 tags published reviewed-only (absence ⇒ machine-ok). */
|
|
37
|
+
reviewedOnlyLanguages?: Iterable<string>;
|
|
38
|
+
/** Stamp the manifest; omit for deterministic output (tests). */
|
|
39
|
+
generatedAt?: string;
|
|
40
|
+
}
|
|
41
|
+
/** Deterministic FNV-1a (32-bit) hex over a string — dep-free, browser-safe. */
|
|
42
|
+
export declare function hashString(input: string): string;
|
|
43
|
+
/** Canonical JSON with sorted keys, so the hash is stable across runs. */
|
|
44
|
+
export declare function stableStringify(payload: TranslationPayload): string;
|
|
45
|
+
/** Content hash of a payload (drives the `{lang}.{hash}.json` filename). */
|
|
46
|
+
export declare function hashPayload(payload: TranslationPayload): string;
|
|
47
|
+
/**
|
|
48
|
+
* Compile one language's complete catalog from the app's UI entries, honoring
|
|
49
|
+
* publish policy. The default/source language emits `sourceText` for every key.
|
|
50
|
+
*/
|
|
51
|
+
export declare function compileLanguage(entries: TranslationEntryRecord[], language: string, options: {
|
|
52
|
+
defaultLanguage: string;
|
|
53
|
+
reviewedOnly?: boolean;
|
|
54
|
+
languageResources?: TranslationLanguageDefinition[];
|
|
55
|
+
}): TranslationPayload;
|
|
56
|
+
/** Compile every requested language + a content-hashed manifest. */
|
|
57
|
+
export declare function compileCatalogs(entries: TranslationEntryRecord[], options: CompileOptions): {
|
|
58
|
+
payloads: Record<string, TranslationPayload>;
|
|
59
|
+
manifest: TranslationManifest;
|
|
60
|
+
};
|
|
61
|
+
/** Filename for a compiled payload: `{lang}.json` (simple) or `{lang}.{hash}.json`. */
|
|
62
|
+
export declare function payloadFileName(language: string, hash: string, opts?: {
|
|
63
|
+
hashed?: boolean;
|
|
64
|
+
}): string;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { languageFallbacks, } from './languages.js';
|
|
2
|
+
/**
|
|
3
|
+
* Compile app translations into publishable per-language payloads + a manifest
|
|
4
|
+
* (Plan 016 P2.2, AD-K/AD-I). Pure and I/O-free: it takes the same
|
|
5
|
+
* `TranslationEntryRecord[]` that `TranslationProvider.listEntries` already
|
|
6
|
+
* produces and emits the `{lang}.json` maps + a content-hashed `manifest.json`.
|
|
7
|
+
* The R2 publish route (P2.3) and the eject-honest CLI (R11) are thin wrappers
|
|
8
|
+
* that read the entries, call this, and write the result.
|
|
9
|
+
*
|
|
10
|
+
* Only `kind:'ui'` keys are published; `kind:'content'` resolves query-time from
|
|
11
|
+
* the app's own dataset (AD-I). Per-language publish policy (AD-K/R9): a
|
|
12
|
+
* `reviewedOnly` language ships the reviewed value else falls back to the English
|
|
13
|
+
* `sourceText` — never a machine/stale draft. Every payload is a COMPLETE
|
|
14
|
+
* catalog (English fallback for anything missing), so it stands alone without the
|
|
15
|
+
* app's inline defaults.
|
|
16
|
+
*/
|
|
17
|
+
import { directionFor, } from './core/messages.js';
|
|
18
|
+
/** Deterministic FNV-1a (32-bit) hex over a string — dep-free, browser-safe. */
|
|
19
|
+
export function hashString(input) {
|
|
20
|
+
let h = 0x811c9dc5;
|
|
21
|
+
for (let i = 0; i < input.length; i++) {
|
|
22
|
+
h ^= input.charCodeAt(i);
|
|
23
|
+
h = Math.imul(h, 0x01000193);
|
|
24
|
+
}
|
|
25
|
+
return (h >>> 0).toString(16).padStart(8, '0');
|
|
26
|
+
}
|
|
27
|
+
/** Canonical JSON with sorted keys, so the hash is stable across runs. */
|
|
28
|
+
export function stableStringify(payload) {
|
|
29
|
+
const keys = Object.keys(payload).sort();
|
|
30
|
+
return JSON.stringify(Object.fromEntries(keys.map((k) => [k, payload[k]])));
|
|
31
|
+
}
|
|
32
|
+
/** Content hash of a payload (drives the `{lang}.{hash}.json` filename). */
|
|
33
|
+
export function hashPayload(payload) {
|
|
34
|
+
return hashString(stableStringify(payload));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compile one language's complete catalog from the app's UI entries, honoring
|
|
38
|
+
* publish policy. The default/source language emits `sourceText` for every key.
|
|
39
|
+
*/
|
|
40
|
+
export function compileLanguage(entries, language, options) {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
const isSource = language === options.defaultLanguage;
|
|
43
|
+
const payload = {};
|
|
44
|
+
const valueFor = (entry, message) => entry.format === 'icu' ? { message, format: 'icu' } : message;
|
|
45
|
+
for (const entry of entries) {
|
|
46
|
+
if (entry.kind !== 'ui')
|
|
47
|
+
continue; // AD-I: content is query-time, not published.
|
|
48
|
+
const source = (_a = entry.sourceText) !== null && _a !== void 0 ? _a : '';
|
|
49
|
+
if (isSource) {
|
|
50
|
+
payload[entry.key] = valueFor(entry, source);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const candidates = languageFallbacks(language, options.defaultLanguage, options.languageResources);
|
|
54
|
+
const unit = candidates
|
|
55
|
+
.filter((code) => code !== options.defaultLanguage)
|
|
56
|
+
.map((code) => { var _a; return (_a = entry.units) === null || _a === void 0 ? void 0 : _a[code]; })
|
|
57
|
+
.find((candidate) => (candidate === null || candidate === void 0 ? void 0 : candidate.text) &&
|
|
58
|
+
(!options.reviewedOnly || candidate.state === 'reviewed'));
|
|
59
|
+
payload[entry.key] = valueFor(entry, (_b = unit === null || unit === void 0 ? void 0 : unit.text) !== null && _b !== void 0 ? _b : source);
|
|
60
|
+
}
|
|
61
|
+
return payload;
|
|
62
|
+
}
|
|
63
|
+
/** Compile every requested language + a content-hashed manifest. */
|
|
64
|
+
export function compileCatalogs(entries, options) {
|
|
65
|
+
var _a, _b, _c, _d;
|
|
66
|
+
const reviewedOnly = new Set((_a = options.reviewedOnlyLanguages) !== null && _a !== void 0 ? _a : []);
|
|
67
|
+
const payloads = {};
|
|
68
|
+
const languages = {};
|
|
69
|
+
for (const language of options.languages) {
|
|
70
|
+
const payload = compileLanguage(entries, language, {
|
|
71
|
+
defaultLanguage: options.defaultLanguage,
|
|
72
|
+
reviewedOnly: reviewedOnly.has(language),
|
|
73
|
+
languageResources: options.languageResources,
|
|
74
|
+
});
|
|
75
|
+
payloads[language] = payload;
|
|
76
|
+
languages[language] = {
|
|
77
|
+
hash: hashPayload(payload),
|
|
78
|
+
dir: (_d = (_c = (_b = options.languageResources) === null || _b === void 0 ? void 0 : _b.find((item) => item.code === language)) === null || _c === void 0 ? void 0 : _c.direction) !== null && _d !== void 0 ? _d : directionFor(language),
|
|
79
|
+
count: Object.keys(payload).length,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
payloads,
|
|
84
|
+
manifest: {
|
|
85
|
+
schemaVersion: 1,
|
|
86
|
+
defaultLanguage: options.defaultLanguage,
|
|
87
|
+
...(options.languageResources
|
|
88
|
+
? { languageResources: options.languageResources }
|
|
89
|
+
: {}),
|
|
90
|
+
...(options.generatedAt ? { generatedAt: options.generatedAt } : {}),
|
|
91
|
+
languages,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** Filename for a compiled payload: `{lang}.json` (simple) or `{lang}.{hash}.json`. */
|
|
96
|
+
export function payloadFileName(language, hash, opts = {}) {
|
|
97
|
+
return opts.hashed ? `${language}.${hash}.json` : `${language}.json`;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type MessageFormat = 'simple' | 'icu';
|
|
2
|
+
/** ICU keys retain their format beside the string in mixed-format catalogs. */
|
|
3
|
+
export interface FormattedTranslationMessage {
|
|
4
|
+
message: string;
|
|
5
|
+
format: MessageFormat;
|
|
6
|
+
}
|
|
7
|
+
export type TranslationMessage = string | FormattedTranslationMessage;
|
|
8
|
+
/** key → message template, for a single language. */
|
|
9
|
+
export type TranslationMessages = Record<string, TranslationMessage>;
|
|
10
|
+
/** FormatSimple: replace `{name}` placeholders with `params.name`. Unknown → left as-is. */
|
|
11
|
+
export declare function interpolate(template: string, params?: Record<string, unknown>): string;
|
|
12
|
+
/**
|
|
13
|
+
* Full ICU MessageFormat using the active locale's CLDR plural rules. Invalid
|
|
14
|
+
* authoring data never crashes the host app: the unformatted template remains
|
|
15
|
+
* visible and Translation Studio reports the syntax error for repair.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatIcu(template: string, params?: Record<string, unknown>, locale?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve `key` against a message map, falling back to the inline default (then
|
|
20
|
+
* the key itself), and format with params. This is what the client `t()` calls.
|
|
21
|
+
*/
|
|
22
|
+
export declare function translate(messages: TranslationMessages, key: string, defaultValue?: string, params?: Record<string, unknown>, format?: MessageFormat, locale?: string): string;
|
|
23
|
+
/** @deprecated Use directionFor; this historical set is not a support boundary. */
|
|
24
|
+
export declare const RTL_LANGUAGES: Set<string>;
|
|
25
|
+
export declare function directionFor(language: string): 'ltr' | 'rtl';
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-light translation core (Plan 014, P1.5). Pure TS, dependency-free —
|
|
3
|
+
* the portable heart shared by the React subpath and any non-React consumer, so
|
|
4
|
+
* a hosted app can use it without pulling React.
|
|
5
|
+
*
|
|
6
|
+
* Preserves Tolgee's `t(key, defaultValue?, params?)` semantics so serve's
|
|
7
|
+
* ~1,302 call sites (with inline English defaults) are a drop-in swap:
|
|
8
|
+
* - default formatting is FormatSimple-style `{named}` interpolation (exactly
|
|
9
|
+
* what serve uses today), so imported strings render identically;
|
|
10
|
+
* - keys marked `format:'icu'` use standards-based ICU MessageFormat with
|
|
11
|
+
* the active BCP-47 locale, including plural/select/selectordinal.
|
|
12
|
+
*/
|
|
13
|
+
import { localeDirection } from '../languages.js';
|
|
14
|
+
import IntlMessageFormat from 'intl-messageformat';
|
|
15
|
+
/** FormatSimple: replace `{name}` placeholders with `params.name`. Unknown → left as-is. */
|
|
16
|
+
export function interpolate(template, params) {
|
|
17
|
+
if (!params)
|
|
18
|
+
return template;
|
|
19
|
+
return template.replace(/\{\s*([\p{L}\p{N}_][\p{L}\p{N}\p{M}_.-]*)\s*\}/gu, (whole, name) => { var _a; return name in params ? String((_a = params[name]) !== null && _a !== void 0 ? _a : '') : whole; });
|
|
20
|
+
}
|
|
21
|
+
const ICU_CACHE_LIMIT = 500;
|
|
22
|
+
const icuCache = new Map();
|
|
23
|
+
function compiledIcu(template, locale) {
|
|
24
|
+
const key = `${locale}\u0000${template}`;
|
|
25
|
+
const cached = icuCache.get(key);
|
|
26
|
+
if (cached)
|
|
27
|
+
return cached;
|
|
28
|
+
const compiled = new IntlMessageFormat(template, locale, undefined, {
|
|
29
|
+
ignoreTag: true,
|
|
30
|
+
});
|
|
31
|
+
if (icuCache.size >= ICU_CACHE_LIMIT) {
|
|
32
|
+
icuCache.delete(icuCache.keys().next().value);
|
|
33
|
+
}
|
|
34
|
+
icuCache.set(key, compiled);
|
|
35
|
+
return compiled;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Full ICU MessageFormat using the active locale's CLDR plural rules. Invalid
|
|
39
|
+
* authoring data never crashes the host app: the unformatted template remains
|
|
40
|
+
* visible and Translation Studio reports the syntax error for repair.
|
|
41
|
+
*/
|
|
42
|
+
export function formatIcu(template, params, locale = 'en') {
|
|
43
|
+
try {
|
|
44
|
+
const result = compiledIcu(template, locale).format(params);
|
|
45
|
+
return Array.isArray(result) ? result.join('') : String(result);
|
|
46
|
+
}
|
|
47
|
+
catch (_a) {
|
|
48
|
+
return interpolate(template, params);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve `key` against a message map, falling back to the inline default (then
|
|
53
|
+
* the key itself), and format with params. This is what the client `t()` calls.
|
|
54
|
+
*/
|
|
55
|
+
export function translate(messages, key, defaultValue, params, format = 'simple', locale = 'en') {
|
|
56
|
+
var _a, _b;
|
|
57
|
+
const stored = messages[key];
|
|
58
|
+
const template = typeof stored === 'string'
|
|
59
|
+
? stored
|
|
60
|
+
: (_b = (_a = stored === null || stored === void 0 ? void 0 : stored.message) !== null && _a !== void 0 ? _a : defaultValue) !== null && _b !== void 0 ? _b : key;
|
|
61
|
+
const resolvedFormat = typeof stored === 'object' ? stored.format : format;
|
|
62
|
+
return resolvedFormat === 'icu'
|
|
63
|
+
? formatIcu(template, params, locale)
|
|
64
|
+
: interpolate(template, params);
|
|
65
|
+
}
|
|
66
|
+
/** @deprecated Use directionFor; this historical set is not a support boundary. */
|
|
67
|
+
export const RTL_LANGUAGES = new Set(['ar', 'ur']);
|
|
68
|
+
export function directionFor(language) {
|
|
69
|
+
try {
|
|
70
|
+
return localeDirection(language);
|
|
71
|
+
}
|
|
72
|
+
catch (_a) {
|
|
73
|
+
return 'ltr';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/core/messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { MessageFormat } from './core/messages.js';
|
|
2
|
+
import type { TranslationBuildDeclaration, TranslationDeclarationKind } from './exchange.js';
|
|
3
|
+
export type TranslationDeclarationSource = 'code' | 'manifest' | 'package' | 'linked' | 'import' | 'runtime';
|
|
4
|
+
export interface TranslationDeclarationProvenance {
|
|
5
|
+
source: TranslationDeclarationSource;
|
|
6
|
+
sourceId: string;
|
|
7
|
+
authoritative: boolean;
|
|
8
|
+
file?: string;
|
|
9
|
+
line?: number;
|
|
10
|
+
ownerIri?: string;
|
|
11
|
+
shapeIri?: string;
|
|
12
|
+
propertyIri?: string;
|
|
13
|
+
nodeIri?: string;
|
|
14
|
+
fromPackage?: string;
|
|
15
|
+
targetClass?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TranslationDeclaration {
|
|
18
|
+
schemaVersion: 1;
|
|
19
|
+
key: string;
|
|
20
|
+
sourceText: string;
|
|
21
|
+
namespace?: string;
|
|
22
|
+
kind: TranslationDeclarationKind;
|
|
23
|
+
format: MessageFormat;
|
|
24
|
+
description?: string;
|
|
25
|
+
provenance: TranslationDeclarationProvenance;
|
|
26
|
+
}
|
|
27
|
+
export interface TranslationDiscoveryContext {
|
|
28
|
+
appId: string;
|
|
29
|
+
branchId?: string;
|
|
30
|
+
sourceRoot?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface TranslationDiscoverySource {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
discover(context: TranslationDiscoveryContext): AsyncIterable<TranslationDeclaration>;
|
|
35
|
+
}
|
|
36
|
+
export type TranslationInventoryStatus = 'confirmed' | 'pending' | 'conflict' | 'orphaned';
|
|
37
|
+
export interface TranslationInventoryItem {
|
|
38
|
+
identity: string;
|
|
39
|
+
appId: string;
|
|
40
|
+
key: string;
|
|
41
|
+
sourceText: string;
|
|
42
|
+
namespace?: string;
|
|
43
|
+
kind: TranslationDeclarationKind;
|
|
44
|
+
format: MessageFormat;
|
|
45
|
+
description?: string;
|
|
46
|
+
status: TranslationInventoryStatus;
|
|
47
|
+
authoritative: boolean;
|
|
48
|
+
exchangeEligible: boolean;
|
|
49
|
+
buildEligible: boolean;
|
|
50
|
+
origins: TranslationDeclarationProvenance[];
|
|
51
|
+
}
|
|
52
|
+
export interface TranslationInventoryConflict {
|
|
53
|
+
identity: string;
|
|
54
|
+
declarations: TranslationDeclaration[];
|
|
55
|
+
}
|
|
56
|
+
export interface TranslationInventorySnapshot {
|
|
57
|
+
schemaVersion: 1;
|
|
58
|
+
appId: string;
|
|
59
|
+
branchId?: string;
|
|
60
|
+
items: TranslationInventoryItem[];
|
|
61
|
+
conflicts: TranslationInventoryConflict[];
|
|
62
|
+
buildDeclarations: TranslationBuildDeclaration[];
|
|
63
|
+
}
|
|
64
|
+
export interface TranslationDiscoveryManifestEntry {
|
|
65
|
+
key: string;
|
|
66
|
+
sourceText: string;
|
|
67
|
+
namespace?: string;
|
|
68
|
+
kind?: TranslationDeclarationKind;
|
|
69
|
+
format?: MessageFormat;
|
|
70
|
+
description?: string;
|
|
71
|
+
ownerIri?: string;
|
|
72
|
+
shapeIri?: string;
|
|
73
|
+
propertyIri?: string;
|
|
74
|
+
nodeIri?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface TranslationDiscoveryManifest {
|
|
77
|
+
schemaVersion: 1;
|
|
78
|
+
sourceId: string;
|
|
79
|
+
declarations: TranslationDiscoveryManifestEntry[];
|
|
80
|
+
}
|
|
81
|
+
export interface DiscoverTranslationInventoryOptions {
|
|
82
|
+
previous?: TranslationInventorySnapshot;
|
|
83
|
+
}
|
|
84
|
+
/** Parse the portable v1 manifest used to declare dynamic translation keys. */
|
|
85
|
+
export declare function parseTranslationDiscoveryManifest(value: unknown): TranslationDiscoveryManifest;
|
|
86
|
+
/** Turn a portable manifest into an authoritative discovery source. */
|
|
87
|
+
export declare function manifestTranslationDiscoverySource(value: unknown): TranslationDiscoverySource;
|
|
88
|
+
/** Stable identity: UI/semantic by namespace+key; content by node+field IRI. */
|
|
89
|
+
export declare function translationDeclarationIdentity(appId: string, declaration: TranslationDeclaration): string;
|
|
90
|
+
/** Build-facing confirmed subset of a persisted or freshly discovered inventory. */
|
|
91
|
+
export declare function translationBuildDeclarationsFromInventory(items: Iterable<TranslationInventoryItem>): TranslationBuildDeclaration[];
|
|
92
|
+
/**
|
|
93
|
+
* Discover and deterministically merge every source. This function is pure
|
|
94
|
+
* with respect to storage: hosts decide how snapshots and lifecycle changes
|
|
95
|
+
* are persisted.
|
|
96
|
+
*/
|
|
97
|
+
export declare function discoverTranslationInventory(sources: Iterable<TranslationDiscoverySource>, context: TranslationDiscoveryContext, options?: DiscoverTranslationInventoryOptions): Promise<TranslationInventorySnapshot>;
|