@_linked/translation 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -17
- package/lib/esm/archive.d.ts +2 -2
- package/lib/esm/archive.js +2 -2
- package/lib/esm/archive.js.map +1 -1
- package/lib/esm/authorization.d.ts +1 -1
- package/lib/esm/authorization.js +1 -1
- package/lib/esm/authorization.js.map +1 -1
- package/lib/esm/cdn-loader.d.ts +1 -1
- package/lib/esm/cdn-loader.js.map +1 -1
- package/lib/esm/core/messages.d.ts +14 -1
- package/lib/esm/core/messages.js +33 -2
- package/lib/esm/core/messages.js.map +1 -1
- package/lib/esm/exchange.d.ts +1 -1
- package/lib/esm/exchange.js +1 -1
- package/lib/esm/exchange.js.map +1 -1
- package/lib/esm/export.js +4 -1
- package/lib/esm/export.js.map +1 -1
- package/lib/esm/formats/xliff.js +1 -1
- package/lib/esm/formats/xliff.js.map +1 -1
- package/lib/esm/key-sync.d.ts +12 -0
- package/lib/esm/key-sync.js +32 -7
- package/lib/esm/key-sync.js.map +1 -1
- package/lib/esm/mt.js +1 -1
- package/lib/esm/mt.js.map +1 -1
- package/lib/esm/ontologies/translation.d.ts +3 -1
- package/lib/esm/ontologies/translation.js +4 -2
- package/lib/esm/ontologies/translation.js.map +1 -1
- package/lib/esm/package.js +4 -9
- package/lib/esm/package.js.map +1 -1
- package/lib/esm/react.d.ts +38 -2
- package/lib/esm/react.js +98 -15
- package/lib/esm/react.js.map +1 -1
- package/lib/esm/records.d.ts +2 -1
- package/lib/esm/records.js.map +1 -1
- package/lib/esm/release.d.ts +3 -1
- package/lib/esm/release.js +21 -4
- package/lib/esm/release.js.map +1 -1
- package/lib/esm/shape-catalog.d.ts +1 -1
- package/lib/esm/shape-catalog.js.map +1 -1
- package/lib/esm/shapes/TranslationKey.d.ts +10 -5
- package/lib/esm/shapes/TranslationKey.js +16 -5
- package/lib/esm/shapes/TranslationKey.js.map +1 -1
- package/lib/esm/shapes/TranslationProvider.d.ts +25 -8
- package/lib/esm/shapes/TranslationProvider.js +50 -19
- package/lib/esm/shapes/TranslationProvider.js.map +1 -1
- package/package.json +3 -3
- package/src/archive.ts +2 -2
- package/src/authorization.ts +1 -1
- package/src/cdn-loader.ts +1 -1
- package/src/core/messages.ts +35 -2
- package/src/exchange.ts +1 -1
- package/src/export.ts +4 -1
- package/src/formats/xliff.ts +1 -1
- package/src/key-sync.ts +46 -6
- package/src/mt.ts +1 -1
- package/src/ontologies/translation.ts +4 -2
- package/src/package.ts +4 -9
- package/src/react.tsx +158 -35
- package/src/records.ts +2 -1
- package/src/release.ts +31 -3
- package/src/shape-catalog.ts +1 -1
- package/src/shapes/TranslationKey.ts +14 -5
- package/src/shapes/TranslationProvider.ts +73 -13
|
@@ -82,6 +82,12 @@ export class TranslationKey extends Shape {
|
|
|
82
82
|
return '';
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/** Arbitrary declared semantic resource, such as an action or condition. */
|
|
86
|
+
@objectProperty({ path: tr.ofResource, maxCount: 1 })
|
|
87
|
+
get ofResource(): string {
|
|
88
|
+
return '';
|
|
89
|
+
}
|
|
90
|
+
|
|
85
91
|
/** Reusable package that supplied the seed value. */
|
|
86
92
|
@literalProperty({ path: tr.fromPackage, maxCount: 1 })
|
|
87
93
|
get fromPackage(): string {
|
|
@@ -89,10 +95,11 @@ export class TranslationKey extends Shape {
|
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
/**
|
|
92
|
-
* True when this app copy of a
|
|
93
|
-
*
|
|
98
|
+
* True when this app copy of a declaration-owned key has been edited locally
|
|
99
|
+
* (shape, property or named package resource, including help) and should NOT
|
|
100
|
+
* be overwritten by declaration refresh or shape-route propagation (AD-N: "never
|
|
94
101
|
* overwrites an app's own override"). Set when the per-app editor changes the
|
|
95
|
-
* source of a key
|
|
102
|
+
* source of a key with declared ownership.
|
|
96
103
|
*/
|
|
97
104
|
@literalProperty({ path: tr.overridden, maxCount: 1 })
|
|
98
105
|
get overridden(): boolean {
|
|
@@ -100,9 +107,10 @@ export class TranslationKey extends Shape {
|
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
/**
|
|
103
|
-
* The
|
|
110
|
+
* The declaration's canonical source captured when this app first overrode the
|
|
104
111
|
* key — what "clear override" reverts to when no non-overridden sibling copy is
|
|
105
|
-
* available to read the current canonical from (AD-N).
|
|
112
|
+
* available to read the current canonical from (AD-N). The historic predicate
|
|
113
|
+
* name stays compatible; resource-owned help does not invent a second carrier.
|
|
106
114
|
*/
|
|
107
115
|
@literalProperty({ path: tr.shapeSource, maxCount: 1 })
|
|
108
116
|
get shapeSource(): string {
|
|
@@ -151,6 +159,7 @@ export class TranslationKey extends Shape {
|
|
|
151
159
|
ofField?: string;
|
|
152
160
|
ofShape?: string;
|
|
153
161
|
ofProperty?: string;
|
|
162
|
+
ofResource?: string;
|
|
154
163
|
fromPackage?: string;
|
|
155
164
|
format?: 'simple' | 'icu';
|
|
156
165
|
}): Promise<{ id: string }> {
|
|
@@ -44,6 +44,7 @@ export interface TranslationKeyInput {
|
|
|
44
44
|
ofField?: string;
|
|
45
45
|
ofShape?: string;
|
|
46
46
|
ofProperty?: string;
|
|
47
|
+
ofResource?: string;
|
|
47
48
|
fromPackage?: string;
|
|
48
49
|
/** Force the override flag; when omitted it is derived (see upsertTranslationKey). */
|
|
49
50
|
overridden?: boolean;
|
|
@@ -51,6 +52,25 @@ export interface TranslationKeyInput {
|
|
|
51
52
|
sourceLanguage?: string;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/** Trusted caller context, not a client payload flag. Package discovery and
|
|
56
|
+
* explicit app authoring have different ownership semantics. */
|
|
57
|
+
export interface TranslationKeyWriteContext {
|
|
58
|
+
createdBy?: string;
|
|
59
|
+
/**
|
|
60
|
+
* `'declaration-sync'` is a refresh from code/package declarations: it never
|
|
61
|
+
* marks a key overridden, and it leaves an existing app override untouched
|
|
62
|
+
* (answering `preservedOverride: true`). Anything else is an app edit.
|
|
63
|
+
*/
|
|
64
|
+
source?: 'app-edit' | 'declaration-sync';
|
|
65
|
+
}
|
|
66
|
+
export interface TranslationKeyWriteResult {
|
|
67
|
+
id: string;
|
|
68
|
+
versionId: string;
|
|
69
|
+
versionCreated: boolean;
|
|
70
|
+
/** Present when a declaration refresh kept the app's override and wrote nothing. */
|
|
71
|
+
preservedOverride?: true;
|
|
72
|
+
}
|
|
73
|
+
|
|
54
74
|
export interface TranslationUnitInput {
|
|
55
75
|
appId: string;
|
|
56
76
|
key: string;
|
|
@@ -313,6 +333,7 @@ export function groupTranslationEntries(
|
|
|
313
333
|
format: row.format === 'icu' ? 'icu' : 'simple',
|
|
314
334
|
ofShape: iri(row.ofShape),
|
|
315
335
|
ofProperty: iri(row.ofProperty),
|
|
336
|
+
ofResource: iri(row.ofResource),
|
|
316
337
|
fromPackage: row.fromPackage || undefined,
|
|
317
338
|
overridden:
|
|
318
339
|
(row as any).overridden === true || (row as any).overridden === 'true'
|
|
@@ -397,6 +418,7 @@ export async function listTranslationKeys(data: { appId: string }) {
|
|
|
397
418
|
k.ofField,
|
|
398
419
|
k.ofShape,
|
|
399
420
|
k.ofProperty,
|
|
421
|
+
k.ofResource,
|
|
400
422
|
k.fromPackage,
|
|
401
423
|
k.overridden,
|
|
402
424
|
k.format,
|
|
@@ -423,6 +445,7 @@ export async function listTranslationEntries(data: {
|
|
|
423
445
|
k.format,
|
|
424
446
|
k.ofShape,
|
|
425
447
|
k.ofProperty,
|
|
448
|
+
k.ofResource,
|
|
426
449
|
k.fromPackage,
|
|
427
450
|
k.overridden,
|
|
428
451
|
k.currentVersion,
|
|
@@ -1061,8 +1084,8 @@ export async function decideTranslationProposal(
|
|
|
1061
1084
|
*/
|
|
1062
1085
|
export async function upsertTranslationKey(
|
|
1063
1086
|
data: TranslationKeyInput,
|
|
1064
|
-
authorship:
|
|
1065
|
-
): Promise<
|
|
1087
|
+
authorship: TranslationKeyWriteContext = {},
|
|
1088
|
+
): Promise<TranslationKeyWriteResult> {
|
|
1066
1089
|
const appId = requireText(data.appId, 'appId');
|
|
1067
1090
|
const key = requireText(data.key, 'key');
|
|
1068
1091
|
requireText(data.sourceText, 'sourceText');
|
|
@@ -1078,29 +1101,59 @@ export async function upsertTranslationKey(
|
|
|
1078
1101
|
ofField: data.ofField,
|
|
1079
1102
|
ofShape: data.ofShape ? { id: data.ofShape } : undefined,
|
|
1080
1103
|
ofProperty: data.ofProperty ? { id: data.ofProperty } : undefined,
|
|
1104
|
+
ofResource: data.ofResource ? { id: data.ofResource } : undefined,
|
|
1081
1105
|
fromPackage: data.fromPackage,
|
|
1082
|
-
overridden: data.overridden
|
|
1106
|
+
overridden: data.overridden,
|
|
1083
1107
|
format: data.format ?? 'simple',
|
|
1084
1108
|
} as any;
|
|
1109
|
+
// No catch: a failed read is not permission to create or overwrite the key.
|
|
1085
1110
|
const existing = await TranslationKey.select((k) => [
|
|
1086
1111
|
k.sourceText,
|
|
1087
1112
|
k.format,
|
|
1088
1113
|
k.ofShape,
|
|
1114
|
+
k.ofProperty,
|
|
1115
|
+
k.ofResource,
|
|
1116
|
+
k.fromPackage,
|
|
1089
1117
|
k.overridden,
|
|
1090
1118
|
k.currentVersion,
|
|
1091
1119
|
])
|
|
1092
1120
|
.where((k) => k.equals({ id } as any))
|
|
1093
|
-
.one()
|
|
1094
|
-
.catch(() => null);
|
|
1121
|
+
.one();
|
|
1095
1122
|
if (existing) {
|
|
1096
1123
|
const sourceChanged = (existing as any).sourceText !== data.sourceText;
|
|
1124
|
+
const formatChanged =
|
|
1125
|
+
((existing as any).format ?? 'simple') !== (data.format ?? 'simple');
|
|
1097
1126
|
const wasOverridden = (existing as any).overridden === true;
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1127
|
+
if (authorship.source === 'declaration-sync' && wasOverridden) {
|
|
1128
|
+
const versionId = iri((existing as any).currentVersion);
|
|
1129
|
+
if (!versionId)
|
|
1130
|
+
throw new Error(
|
|
1131
|
+
`Translation override ${id} has no current version; refresh refused without changing its source.`
|
|
1132
|
+
);
|
|
1133
|
+
// No key write, version creation or unit invalidation. The declaration
|
|
1134
|
+
// inventory still records the package's current source independently.
|
|
1135
|
+
return { id, versionId, versionCreated: false, preservedOverride: true };
|
|
1136
|
+
}
|
|
1137
|
+
// AD-N ownership also covers property/resource/package declarations (help,
|
|
1138
|
+
// actions, groups), not only shapes. App edits preserve the first canonical
|
|
1139
|
+
// wording in the existing shapeSource carrier. Only an explicit app edit
|
|
1140
|
+
// may clear the override; automatic discovery cannot clear it by payload.
|
|
1141
|
+
const isDeclaredKey = !!(
|
|
1142
|
+
(existing as any).ofShape ||
|
|
1143
|
+
(existing as any).ofProperty ||
|
|
1144
|
+
(existing as any).ofResource ||
|
|
1145
|
+
(existing as any).fromPackage ||
|
|
1146
|
+
data.ofShape ||
|
|
1147
|
+
data.ofProperty ||
|
|
1148
|
+
data.ofResource ||
|
|
1149
|
+
data.fromPackage
|
|
1150
|
+
);
|
|
1151
|
+
if (
|
|
1152
|
+
authorship.source !== 'declaration-sync' &&
|
|
1153
|
+
data.overridden === undefined &&
|
|
1154
|
+
isDeclaredKey &&
|
|
1155
|
+
(sourceChanged || formatChanged)
|
|
1156
|
+
) {
|
|
1104
1157
|
values.overridden = true;
|
|
1105
1158
|
// Snapshot the canonical at FIRST divergence so "clear override" has a
|
|
1106
1159
|
// value to revert to even for a single-app project. Later edits keep the
|
|
@@ -1134,7 +1187,14 @@ export async function upsertTranslationKey(
|
|
|
1134
1187
|
})
|
|
1135
1188
|
: currentVersion;
|
|
1136
1189
|
values.currentVersion = { id: nextVersion.id };
|
|
1137
|
-
|
|
1190
|
+
// In the Linked mutation DSL an explicitly present `undefined` removes
|
|
1191
|
+
// that predicate. A partial source edit has not requested removal of the
|
|
1192
|
+
// declaration owner, help description, or existing override flag. Omit
|
|
1193
|
+
// untouched fields; an explicit false (reset) remains a real write.
|
|
1194
|
+
const patch = Object.fromEntries(
|
|
1195
|
+
Object.entries(values).filter(([, value]) => value !== undefined)
|
|
1196
|
+
);
|
|
1197
|
+
await TranslationKey.update(patch as any).for({ id } as any);
|
|
1138
1198
|
if (decision.action === 'create-version') {
|
|
1139
1199
|
await TranslationUnit.update({ state: 'stale' } as any).where((u) =>
|
|
1140
1200
|
u.ofKey.equals({ id } as any),
|
|
@@ -1491,7 +1551,7 @@ export class TranslationProvider extends ShapeProvider {
|
|
|
1491
1551
|
|
|
1492
1552
|
/**
|
|
1493
1553
|
* Authoring gate. Reads `linkedAuth` off the request the LINKED server already
|
|
1494
|
-
* populates, so this stays portable (no
|
|
1554
|
+
* populates, so this stays portable (no host-application import, AD-G).
|
|
1495
1555
|
*
|
|
1496
1556
|
* Every method except `getMessages` resolves the caller once, synchronously,
|
|
1497
1557
|
* before its first `await`, and uses that value for both the permission check
|