@_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,74 @@
|
|
|
1
|
+
export function canonicalLocale(code) {
|
|
2
|
+
return (Intl.getCanonicalLocales(code.trim())[0] ||
|
|
3
|
+
(() => {
|
|
4
|
+
throw new Error('Language code is required.');
|
|
5
|
+
})());
|
|
6
|
+
}
|
|
7
|
+
export function localeDirection(code) {
|
|
8
|
+
var _a, _b, _c, _d;
|
|
9
|
+
const locale = new Intl.Locale(canonicalLocale(code));
|
|
10
|
+
const info = (_c = (_b = (_a = locale).getTextInfo) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : locale.textInfo;
|
|
11
|
+
if (info === null || info === void 0 ? void 0 : info.direction)
|
|
12
|
+
return info.direction;
|
|
13
|
+
// Script fallback for engines without Intl.Locale text information. This is
|
|
14
|
+
// a script property, not a closed list of supported languages.
|
|
15
|
+
return /^(Adlm|Arab|Hebr|Nkoo|Rohg|Samr|Syrc|Thaa)$/.test((_d = locale.maximize().script) !== null && _d !== void 0 ? _d : '')
|
|
16
|
+
? 'rtl'
|
|
17
|
+
: 'ltr';
|
|
18
|
+
}
|
|
19
|
+
export function defineLanguage(code, input = {}) {
|
|
20
|
+
var _a, _b, _c, _d;
|
|
21
|
+
code = canonicalLocale(code);
|
|
22
|
+
const base = new Intl.Locale(code).language;
|
|
23
|
+
const name = (locale) => { var _a; return (_a = new Intl.DisplayNames([locale], { type: 'language' }).of(code)) !== null && _a !== void 0 ? _a : code; };
|
|
24
|
+
return {
|
|
25
|
+
id: (_a = input.id) !== null && _a !== void 0 ? _a : `https://id.linked.cm/language/${code}`,
|
|
26
|
+
code,
|
|
27
|
+
nativeName: input.nativeName || name(code),
|
|
28
|
+
englishName: input.englishName || name('en'),
|
|
29
|
+
direction: (_b = input.direction) !== null && _b !== void 0 ? _b : localeDirection(code),
|
|
30
|
+
...(base !== code ? { parent: base } : {}),
|
|
31
|
+
...input,
|
|
32
|
+
enabled: (_c = input.enabled) !== null && _c !== void 0 ? _c : true,
|
|
33
|
+
supported: (_d = input.supported) !== null && _d !== void 0 ? _d : true,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Ordered explicit fallback chain, ending at the source; safe against cycles. */
|
|
37
|
+
export function languageFallbacks(code, source, definitions = []) {
|
|
38
|
+
var _a;
|
|
39
|
+
const byCode = new Map(definitions.map((language) => [language.code, language]));
|
|
40
|
+
const chain = [];
|
|
41
|
+
let current = canonicalLocale(code);
|
|
42
|
+
while (current && !chain.includes(current) && current !== source) {
|
|
43
|
+
chain.push(current);
|
|
44
|
+
current = (_a = byCode.get(current)) === null || _a === void 0 ? void 0 : _a.fallback;
|
|
45
|
+
}
|
|
46
|
+
if (!chain.includes(source))
|
|
47
|
+
chain.push(source);
|
|
48
|
+
return chain;
|
|
49
|
+
}
|
|
50
|
+
export function validateLanguageDefinitions(definitions) {
|
|
51
|
+
var _a;
|
|
52
|
+
const byCode = new Map(definitions.map((language) => [language.code, language]));
|
|
53
|
+
if (byCode.size !== definitions.length)
|
|
54
|
+
throw new Error('Duplicate language resources.');
|
|
55
|
+
for (const language of definitions) {
|
|
56
|
+
if (canonicalLocale(language.code) !== language.code)
|
|
57
|
+
throw new Error('Use canonical BCP-47 codes.');
|
|
58
|
+
if (!['ltr', 'rtl'].includes(language.direction))
|
|
59
|
+
throw new Error('Language direction must be ltr or rtl.');
|
|
60
|
+
for (const relation of ['fallback', 'parent']) {
|
|
61
|
+
const visited = new Set([language.code]);
|
|
62
|
+
let target = language[relation];
|
|
63
|
+
while (target) {
|
|
64
|
+
if (visited.has(target))
|
|
65
|
+
throw new Error(`Cyclic language ${relation}: ${language.code}`);
|
|
66
|
+
visited.add(target);
|
|
67
|
+
if (!byCode.has(target))
|
|
68
|
+
throw new Error(`Missing ${relation} language resource: ${target}`);
|
|
69
|
+
target = (_a = byCode.get(target)) === null || _a === void 0 ? void 0 : _a[relation];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=languages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.js","sourceRoot":"","sources":["../../src/languages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { MessageFormat } from './core/messages.js';
|
|
2
|
+
import type { TranslationDiscoverySource } from './discovery.js';
|
|
3
|
+
import { type ShapeTranslationCatalog } from './shape-catalog.js';
|
|
4
|
+
export type LinkedSemanticEntryType = 'label' | 'help' | 'validation' | 'controlled-value' | 'workflow-role' | 'skos-concept';
|
|
5
|
+
export interface LinkedSemanticCatalogEntry {
|
|
6
|
+
key: string;
|
|
7
|
+
sourceText: string;
|
|
8
|
+
ownerIri: string;
|
|
9
|
+
namespace?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
format?: MessageFormat;
|
|
12
|
+
shapeIri?: string;
|
|
13
|
+
propertyIri?: string;
|
|
14
|
+
targetClass?: string;
|
|
15
|
+
type?: LinkedSemanticEntryType;
|
|
16
|
+
}
|
|
17
|
+
export interface LinkedComponentTranslationCatalog {
|
|
18
|
+
componentIri: string;
|
|
19
|
+
targetClass?: string;
|
|
20
|
+
entries: Array<Omit<LinkedSemanticCatalogEntry, 'ownerIri'>>;
|
|
21
|
+
}
|
|
22
|
+
export interface LinkedContentTranslationCatalogEntry {
|
|
23
|
+
key: string;
|
|
24
|
+
sourceText: string;
|
|
25
|
+
nodeIri: string;
|
|
26
|
+
propertyIri: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
format?: MessageFormat;
|
|
29
|
+
}
|
|
30
|
+
export interface LinkedPackageTranslationCatalog {
|
|
31
|
+
schemaVersion: 1;
|
|
32
|
+
packageName: string;
|
|
33
|
+
shapes: ShapeTranslationCatalog[];
|
|
34
|
+
components: LinkedComponentTranslationCatalog[];
|
|
35
|
+
labels: LinkedSemanticCatalogEntry[];
|
|
36
|
+
controlledValues: LinkedSemanticCatalogEntry[];
|
|
37
|
+
workflowRoles: LinkedSemanticCatalogEntry[];
|
|
38
|
+
skosConcepts: LinkedSemanticCatalogEntry[];
|
|
39
|
+
content: LinkedContentTranslationCatalogEntry[];
|
|
40
|
+
}
|
|
41
|
+
/** Parse serialized JSON only; package JavaScript is never imported or run. */
|
|
42
|
+
export declare function parseLinkedPackageTranslationCatalog(input: string | Uint8Array): LinkedPackageTranslationCatalog;
|
|
43
|
+
/** Discover safe serialized LINKED package metadata without code execution. */
|
|
44
|
+
export declare function linkedPackageTranslationDiscoverySource(input: string | Uint8Array): TranslationDiscoverySource;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { defineShapeTranslationCatalog, shapeCatalogTranslationDiscoverySource, } from './shape-catalog.js';
|
|
2
|
+
function record(value, label) {
|
|
3
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
4
|
+
throw new Error(`${label} must be an object.`);
|
|
5
|
+
}
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
function requiredString(value, label) {
|
|
9
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
10
|
+
throw new Error(`${label} is required.`);
|
|
11
|
+
}
|
|
12
|
+
return value.trim();
|
|
13
|
+
}
|
|
14
|
+
function optionalString(value, label) {
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
18
|
+
throw new Error(`${label} must be a non-empty string when supplied.`);
|
|
19
|
+
}
|
|
20
|
+
return value.trim();
|
|
21
|
+
}
|
|
22
|
+
function format(value, label) {
|
|
23
|
+
if (value === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
if (value !== 'simple' && value !== 'icu') {
|
|
26
|
+
throw new Error(`${label} must be "simple" or "icu".`);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
function array(value, label) {
|
|
31
|
+
if (value === undefined)
|
|
32
|
+
return [];
|
|
33
|
+
if (!Array.isArray(value))
|
|
34
|
+
throw new Error(`${label} must be an array.`);
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
function semanticEntry(value, label, expectedType) {
|
|
38
|
+
var _a;
|
|
39
|
+
const entry = record(value, label);
|
|
40
|
+
const type = ((_a = entry.type) !== null && _a !== void 0 ? _a : expectedType);
|
|
41
|
+
if (type !== undefined &&
|
|
42
|
+
type !== 'label' &&
|
|
43
|
+
type !== 'help' &&
|
|
44
|
+
type !== 'validation' &&
|
|
45
|
+
type !== 'controlled-value' &&
|
|
46
|
+
type !== 'workflow-role' &&
|
|
47
|
+
type !== 'skos-concept') {
|
|
48
|
+
throw new Error(`${label}.type is invalid.`);
|
|
49
|
+
}
|
|
50
|
+
if (typeof entry.sourceText !== 'string') {
|
|
51
|
+
throw new Error(`${label}.sourceText must be a string.`);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
key: requiredString(entry.key, `${label}.key`),
|
|
55
|
+
sourceText: entry.sourceText,
|
|
56
|
+
ownerIri: requiredString(entry.ownerIri, `${label}.ownerIri`),
|
|
57
|
+
...(optionalString(entry.namespace, `${label}.namespace`)
|
|
58
|
+
? { namespace: entry.namespace }
|
|
59
|
+
: {}),
|
|
60
|
+
...(optionalString(entry.description, `${label}.description`)
|
|
61
|
+
? { description: entry.description }
|
|
62
|
+
: {}),
|
|
63
|
+
...(format(entry.format, `${label}.format`)
|
|
64
|
+
? { format: entry.format }
|
|
65
|
+
: {}),
|
|
66
|
+
...(optionalString(entry.shapeIri, `${label}.shapeIri`)
|
|
67
|
+
? { shapeIri: entry.shapeIri }
|
|
68
|
+
: {}),
|
|
69
|
+
...(optionalString(entry.propertyIri, `${label}.propertyIri`)
|
|
70
|
+
? { propertyIri: entry.propertyIri }
|
|
71
|
+
: {}),
|
|
72
|
+
...(optionalString(entry.targetClass, `${label}.targetClass`)
|
|
73
|
+
? { targetClass: entry.targetClass }
|
|
74
|
+
: {}),
|
|
75
|
+
...(type ? { type } : {}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function component(value, index) {
|
|
79
|
+
const item = record(value, `components[${index}]`);
|
|
80
|
+
const componentIri = requiredString(item.componentIri, `components[${index}].componentIri`);
|
|
81
|
+
const entries = array(item.entries, `components[${index}].entries`).map((raw, entryIndex) => {
|
|
82
|
+
const parsed = semanticEntry({
|
|
83
|
+
...record(raw, `components[${index}].entries[${entryIndex}]`),
|
|
84
|
+
ownerIri: componentIri,
|
|
85
|
+
}, `components[${index}].entries[${entryIndex}]`);
|
|
86
|
+
const { ownerIri: _ownerIri, ...entry } = parsed;
|
|
87
|
+
return entry;
|
|
88
|
+
});
|
|
89
|
+
return {
|
|
90
|
+
componentIri,
|
|
91
|
+
entries,
|
|
92
|
+
...(optionalString(item.targetClass, `components[${index}].targetClass`)
|
|
93
|
+
? { targetClass: item.targetClass }
|
|
94
|
+
: {}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function contentEntry(value, index) {
|
|
98
|
+
const entry = record(value, `content[${index}]`);
|
|
99
|
+
if (typeof entry.sourceText !== 'string') {
|
|
100
|
+
throw new Error(`content[${index}].sourceText must be a string.`);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
key: requiredString(entry.key, `content[${index}].key`),
|
|
104
|
+
sourceText: entry.sourceText,
|
|
105
|
+
nodeIri: requiredString(entry.nodeIri, `content[${index}].nodeIri`),
|
|
106
|
+
propertyIri: requiredString(entry.propertyIri, `content[${index}].propertyIri`),
|
|
107
|
+
...(optionalString(entry.description, `content[${index}].description`)
|
|
108
|
+
? { description: entry.description }
|
|
109
|
+
: {}),
|
|
110
|
+
...(format(entry.format, `content[${index}].format`)
|
|
111
|
+
? { format: entry.format }
|
|
112
|
+
: {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function shapeCatalog(value, index) {
|
|
116
|
+
const shape = record(value, `shapes[${index}]`);
|
|
117
|
+
return defineShapeTranslationCatalog({
|
|
118
|
+
schemaVersion: shape.schemaVersion,
|
|
119
|
+
packageName: requiredString(shape.packageName, `shapes[${index}].packageName`),
|
|
120
|
+
shapeIri: requiredString(shape.shapeIri, `shapes[${index}].shapeIri`),
|
|
121
|
+
...(optionalString(shape.targetClass, `shapes[${index}].targetClass`)
|
|
122
|
+
? { targetClass: shape.targetClass }
|
|
123
|
+
: {}),
|
|
124
|
+
entries: array(shape.entries, `shapes[${index}].entries`),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function assertNoDuplicateIdentities(catalog) {
|
|
128
|
+
const messages = new Set();
|
|
129
|
+
const add = (key, namespace = '') => {
|
|
130
|
+
const identity = JSON.stringify([namespace, key]);
|
|
131
|
+
if (messages.has(identity)) {
|
|
132
|
+
throw new Error(`Duplicate linked translation key "${key}".`);
|
|
133
|
+
}
|
|
134
|
+
messages.add(identity);
|
|
135
|
+
};
|
|
136
|
+
for (const shape of catalog.shapes) {
|
|
137
|
+
for (const entry of shape.entries)
|
|
138
|
+
add(entry.key, entry.namespace);
|
|
139
|
+
}
|
|
140
|
+
for (const component of catalog.components) {
|
|
141
|
+
for (const entry of component.entries)
|
|
142
|
+
add(entry.key, entry.namespace);
|
|
143
|
+
}
|
|
144
|
+
for (const entries of [
|
|
145
|
+
catalog.labels,
|
|
146
|
+
catalog.controlledValues,
|
|
147
|
+
catalog.workflowRoles,
|
|
148
|
+
catalog.skosConcepts,
|
|
149
|
+
]) {
|
|
150
|
+
for (const entry of entries)
|
|
151
|
+
add(entry.key, entry.namespace);
|
|
152
|
+
}
|
|
153
|
+
const content = new Set();
|
|
154
|
+
for (const entry of catalog.content) {
|
|
155
|
+
const identity = JSON.stringify([entry.nodeIri, entry.propertyIri]);
|
|
156
|
+
if (content.has(identity)) {
|
|
157
|
+
throw new Error(`Duplicate linked content translation field "${entry.nodeIri}" / "${entry.propertyIri}".`);
|
|
158
|
+
}
|
|
159
|
+
content.add(identity);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** Parse serialized JSON only; package JavaScript is never imported or run. */
|
|
163
|
+
export function parseLinkedPackageTranslationCatalog(input) {
|
|
164
|
+
let value;
|
|
165
|
+
try {
|
|
166
|
+
value = JSON.parse(typeof input === 'string' ? input : new TextDecoder().decode(input));
|
|
167
|
+
}
|
|
168
|
+
catch (_a) {
|
|
169
|
+
throw new Error('Linked translation catalog must be valid JSON.');
|
|
170
|
+
}
|
|
171
|
+
const raw = record(value, 'catalog');
|
|
172
|
+
if (raw.schemaVersion !== 1) {
|
|
173
|
+
throw new Error('Linked translation catalog schemaVersion must be 1.');
|
|
174
|
+
}
|
|
175
|
+
const catalog = {
|
|
176
|
+
schemaVersion: 1,
|
|
177
|
+
packageName: requiredString(raw.packageName, 'catalog.packageName'),
|
|
178
|
+
shapes: array(raw.shapes, 'catalog.shapes').map(shapeCatalog),
|
|
179
|
+
components: array(raw.components, 'catalog.components').map(component),
|
|
180
|
+
labels: array(raw.labels, 'catalog.labels').map((entry, index) => semanticEntry(entry, `labels[${index}]`, 'label')),
|
|
181
|
+
controlledValues: array(raw.controlledValues, 'catalog.controlledValues').map((entry, index) => semanticEntry(entry, `controlledValues[${index}]`, 'controlled-value')),
|
|
182
|
+
workflowRoles: array(raw.workflowRoles, 'catalog.workflowRoles').map((entry, index) => semanticEntry(entry, `workflowRoles[${index}]`, 'workflow-role')),
|
|
183
|
+
skosConcepts: array(raw.skosConcepts, 'catalog.skosConcepts').map((entry, index) => semanticEntry(entry, `skosConcepts[${index}]`, 'skos-concept')),
|
|
184
|
+
content: array(raw.content, 'catalog.content').map(contentEntry),
|
|
185
|
+
};
|
|
186
|
+
for (const shape of catalog.shapes) {
|
|
187
|
+
if (shape.packageName !== catalog.packageName) {
|
|
188
|
+
throw new Error(`Shape catalog package "${shape.packageName}" does not match "${catalog.packageName}".`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
assertNoDuplicateIdentities(catalog);
|
|
192
|
+
return catalog;
|
|
193
|
+
}
|
|
194
|
+
function semanticDeclaration(packageName, category, entry) {
|
|
195
|
+
var _a;
|
|
196
|
+
return {
|
|
197
|
+
schemaVersion: 1,
|
|
198
|
+
key: entry.key,
|
|
199
|
+
sourceText: entry.sourceText,
|
|
200
|
+
kind: 'semantic',
|
|
201
|
+
format: (_a = entry.format) !== null && _a !== void 0 ? _a : 'simple',
|
|
202
|
+
...(entry.namespace ? { namespace: entry.namespace } : {}),
|
|
203
|
+
...(entry.description ? { description: entry.description } : {}),
|
|
204
|
+
provenance: {
|
|
205
|
+
source: 'linked',
|
|
206
|
+
sourceId: `${packageName}:${category}:${entry.ownerIri}`,
|
|
207
|
+
authoritative: true,
|
|
208
|
+
ownerIri: entry.ownerIri,
|
|
209
|
+
fromPackage: packageName,
|
|
210
|
+
...(entry.shapeIri ? { shapeIri: entry.shapeIri } : {}),
|
|
211
|
+
...(entry.propertyIri ? { propertyIri: entry.propertyIri } : {}),
|
|
212
|
+
...(entry.targetClass ? { targetClass: entry.targetClass } : {}),
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/** Discover safe serialized LINKED package metadata without code execution. */
|
|
217
|
+
export function linkedPackageTranslationDiscoverySource(input) {
|
|
218
|
+
const catalog = parseLinkedPackageTranslationCatalog(input);
|
|
219
|
+
return {
|
|
220
|
+
name: `linked-package:${catalog.packageName}`,
|
|
221
|
+
async *discover(context) {
|
|
222
|
+
var _a, _b;
|
|
223
|
+
for (const shape of catalog.shapes) {
|
|
224
|
+
yield* shapeCatalogTranslationDiscoverySource(shape).discover(context);
|
|
225
|
+
}
|
|
226
|
+
for (const component of catalog.components) {
|
|
227
|
+
for (const entry of component.entries) {
|
|
228
|
+
yield semanticDeclaration(catalog.packageName, 'component', {
|
|
229
|
+
...entry,
|
|
230
|
+
ownerIri: component.componentIri,
|
|
231
|
+
targetClass: (_a = entry.targetClass) !== null && _a !== void 0 ? _a : component.targetClass,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
for (const [category, entries] of [
|
|
236
|
+
['label', catalog.labels],
|
|
237
|
+
['controlled-value', catalog.controlledValues],
|
|
238
|
+
['workflow-role', catalog.workflowRoles],
|
|
239
|
+
['skos-concept', catalog.skosConcepts],
|
|
240
|
+
]) {
|
|
241
|
+
for (const entry of entries) {
|
|
242
|
+
yield semanticDeclaration(catalog.packageName, category, entry);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
for (const entry of catalog.content) {
|
|
246
|
+
yield {
|
|
247
|
+
schemaVersion: 1,
|
|
248
|
+
key: entry.key,
|
|
249
|
+
sourceText: entry.sourceText,
|
|
250
|
+
kind: 'content',
|
|
251
|
+
format: (_b = entry.format) !== null && _b !== void 0 ? _b : 'simple',
|
|
252
|
+
...(entry.description ? { description: entry.description } : {}),
|
|
253
|
+
provenance: {
|
|
254
|
+
source: 'linked',
|
|
255
|
+
sourceId: `${catalog.packageName}:content:${entry.nodeIri}:${entry.propertyIri}`,
|
|
256
|
+
authoritative: true,
|
|
257
|
+
ownerIri: entry.nodeIri,
|
|
258
|
+
nodeIri: entry.nodeIri,
|
|
259
|
+
propertyIri: entry.propertyIri,
|
|
260
|
+
fromPackage: catalog.packageName,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=linked-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linked-discovery.js","sourceRoot":"","sources":["../../src/linked-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { MessageFormat } from './core/messages.js';
|
|
2
|
+
export type MessageArgumentKind = 'argument' | 'number' | 'date' | 'time' | 'select' | 'plural' | 'selectordinal';
|
|
3
|
+
export interface MessageArgument {
|
|
4
|
+
name: string;
|
|
5
|
+
kinds: MessageArgumentKind[];
|
|
6
|
+
}
|
|
7
|
+
export interface MessageAnalysis {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
arguments: MessageArgument[];
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MessageArgumentComparison {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
missing: string[];
|
|
15
|
+
extra: string[];
|
|
16
|
+
typeMismatches: Array<{
|
|
17
|
+
name: string;
|
|
18
|
+
source: MessageArgumentKind[];
|
|
19
|
+
target: MessageArgumentKind[];
|
|
20
|
+
}>;
|
|
21
|
+
sourceError?: string;
|
|
22
|
+
targetError?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface LegacyPluralSuffix {
|
|
25
|
+
countArgument: string;
|
|
26
|
+
suffixArgument: string;
|
|
27
|
+
}
|
|
28
|
+
/** Parse the variables a translator must preserve in a simple or ICU message. */
|
|
29
|
+
export declare function analyzeMessage(text: string, format?: MessageFormat): MessageAnalysis;
|
|
30
|
+
/**
|
|
31
|
+
* Compare runtime arguments without requiring identical word order or plural
|
|
32
|
+
* categories. Categories legitimately differ by language; variable names and
|
|
33
|
+
* their ICU roles may not.
|
|
34
|
+
*/
|
|
35
|
+
export declare function compareMessageArguments(source: string, target: string, format?: MessageFormat): MessageArgumentComparison;
|
|
36
|
+
/**
|
|
37
|
+
* Detect the legacy English suffix idiom (`{n} mission{s}`). `{s}` is not a
|
|
38
|
+
* plural operator; callers merely pass either "s" or "". Other languages may
|
|
39
|
+
* omit it, and the key should eventually be rewritten as an ICU plural.
|
|
40
|
+
*/
|
|
41
|
+
export declare function detectLegacyPluralSuffixes(text: string): LegacyPluralSuffix[];
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { isArgumentElement, isDateElement, isNumberElement, isPluralElement, isSelectElement, isTagElement, isTimeElement, parse, } from '@formatjs/icu-messageformat-parser';
|
|
2
|
+
/**
|
|
3
|
+
* FormatSimple remains intentionally looser than ICU identifiers: existing
|
|
4
|
+
* apps may use positional (`{0}`), dotted (`{user.name}`), hyphenated
|
|
5
|
+
* (`{item-count}`), or Unicode (`{名前}`) variable names.
|
|
6
|
+
*/
|
|
7
|
+
const SIMPLE_ARGUMENT_RE = /\{\s*([\p{L}\p{N}_][\p{L}\p{N}\p{M}_.-]*)\s*\}/gu;
|
|
8
|
+
function argumentKind(element) {
|
|
9
|
+
if (isArgumentElement(element))
|
|
10
|
+
return 'argument';
|
|
11
|
+
if (isNumberElement(element))
|
|
12
|
+
return 'number';
|
|
13
|
+
if (isDateElement(element))
|
|
14
|
+
return 'date';
|
|
15
|
+
if (isTimeElement(element))
|
|
16
|
+
return 'time';
|
|
17
|
+
if (isSelectElement(element))
|
|
18
|
+
return 'select';
|
|
19
|
+
if (isPluralElement(element)) {
|
|
20
|
+
return element.pluralType === 'ordinal' ? 'selectordinal' : 'plural';
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function collectIcuArguments(elements, found) {
|
|
25
|
+
var _a;
|
|
26
|
+
for (const element of elements) {
|
|
27
|
+
const kind = argumentKind(element);
|
|
28
|
+
if (kind && 'value' in element) {
|
|
29
|
+
const kinds = (_a = found.get(element.value)) !== null && _a !== void 0 ? _a : new Set();
|
|
30
|
+
kinds.add(kind);
|
|
31
|
+
found.set(element.value, kinds);
|
|
32
|
+
}
|
|
33
|
+
if (isPluralElement(element) || isSelectElement(element)) {
|
|
34
|
+
for (const option of Object.values(element.options)) {
|
|
35
|
+
collectIcuArguments(option.value, found);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (isTagElement(element)) {
|
|
39
|
+
collectIcuArguments(element.children, found);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const toArguments = (found) => [...found.entries()]
|
|
44
|
+
.map(([name, kinds]) => ({ name, kinds: [...kinds].sort() }))
|
|
45
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
46
|
+
/** Parse the variables a translator must preserve in a simple or ICU message. */
|
|
47
|
+
export function analyzeMessage(text, format = 'simple') {
|
|
48
|
+
const found = new Map();
|
|
49
|
+
if (format === 'simple') {
|
|
50
|
+
for (const match of text.matchAll(SIMPLE_ARGUMENT_RE)) {
|
|
51
|
+
found.set(match[1], new Set(['argument']));
|
|
52
|
+
}
|
|
53
|
+
return { valid: true, arguments: toArguments(found) };
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
collectIcuArguments(parse(text, { ignoreTag: true, requiresOtherClause: true }), found);
|
|
57
|
+
return { valid: true, arguments: toArguments(found) };
|
|
58
|
+
}
|
|
59
|
+
catch (cause) {
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
arguments: [],
|
|
63
|
+
error: cause instanceof Error ? cause.message : String(cause),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Compare runtime arguments without requiring identical word order or plural
|
|
69
|
+
* categories. Categories legitimately differ by language; variable names and
|
|
70
|
+
* their ICU roles may not.
|
|
71
|
+
*/
|
|
72
|
+
export function compareMessageArguments(source, target, format = 'simple') {
|
|
73
|
+
const sourceAnalysis = analyzeMessage(source, format);
|
|
74
|
+
const targetAnalysis = analyzeMessage(target, format);
|
|
75
|
+
const sourceByName = new Map(sourceAnalysis.arguments.map((argument) => [argument.name, argument]));
|
|
76
|
+
const targetByName = new Map(targetAnalysis.arguments.map((argument) => [argument.name, argument]));
|
|
77
|
+
const optionalLegacySuffixes = format === 'simple'
|
|
78
|
+
? new Set(detectLegacyPluralSuffixes(source).map(({ suffixArgument }) => suffixArgument))
|
|
79
|
+
: new Set();
|
|
80
|
+
const missing = [...sourceByName.keys()]
|
|
81
|
+
.filter((name) => !targetByName.has(name) && !optionalLegacySuffixes.has(name))
|
|
82
|
+
.sort();
|
|
83
|
+
const extra = [...targetByName.keys()]
|
|
84
|
+
.filter((name) => !sourceByName.has(name))
|
|
85
|
+
.sort();
|
|
86
|
+
const typeMismatches = [...sourceByName.keys()]
|
|
87
|
+
.filter((name) => targetByName.has(name))
|
|
88
|
+
.flatMap((name) => {
|
|
89
|
+
const sourceKinds = sourceByName.get(name).kinds;
|
|
90
|
+
const targetKinds = targetByName.get(name).kinds;
|
|
91
|
+
return sourceKinds.length === targetKinds.length &&
|
|
92
|
+
sourceKinds.every((kind, index) => kind === targetKinds[index])
|
|
93
|
+
? []
|
|
94
|
+
: [{ name, source: sourceKinds, target: targetKinds }];
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
valid: sourceAnalysis.valid &&
|
|
98
|
+
targetAnalysis.valid &&
|
|
99
|
+
missing.length === 0 &&
|
|
100
|
+
extra.length === 0 &&
|
|
101
|
+
typeMismatches.length === 0,
|
|
102
|
+
missing,
|
|
103
|
+
extra,
|
|
104
|
+
typeMismatches,
|
|
105
|
+
sourceError: sourceAnalysis.error,
|
|
106
|
+
targetError: targetAnalysis.error,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Detect the legacy English suffix idiom (`{n} mission{s}`). `{s}` is not a
|
|
111
|
+
* plural operator; callers merely pass either "s" or "". Other languages may
|
|
112
|
+
* omit it, and the key should eventually be rewritten as an ICU plural.
|
|
113
|
+
*/
|
|
114
|
+
export function detectLegacyPluralSuffixes(text) {
|
|
115
|
+
const countArguments = [
|
|
116
|
+
...text.matchAll(/\{\s*([\p{L}\p{N}_][\p{L}\p{N}\p{M}_.-]*)\s*\}/gu),
|
|
117
|
+
].map((match) => match[1]);
|
|
118
|
+
if (countArguments.length < 2)
|
|
119
|
+
return [];
|
|
120
|
+
const suffixes = [
|
|
121
|
+
...text.matchAll(/[\p{L}\p{N}]\{\s*([\p{L}\p{N}_][\p{L}\p{N}\p{M}_.-]*)\s*\}/gu),
|
|
122
|
+
].map((match) => match[1]);
|
|
123
|
+
if (suffixes.length === 0)
|
|
124
|
+
return [];
|
|
125
|
+
const countArgument = countArguments.find((name) => !suffixes.includes(name));
|
|
126
|
+
if (!countArgument)
|
|
127
|
+
return [];
|
|
128
|
+
return [...new Set(suffixes)].map((suffixArgument) => ({
|
|
129
|
+
countArgument,
|
|
130
|
+
suffixArgument,
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=message-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-format.js","sourceRoot":"","sources":["../../src/message-format.ts"],"names":[],"mappings":"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"}
|