@_linked/translation 0.7.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 +15 -16
- 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/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/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
|
@@ -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
|