@proveanything/smartlinks 1.9.2 → 1.9.4
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 +3 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/translations.d.ts +12 -0
- package/dist/api/translations.js +217 -0
- package/dist/docs/API_SUMMARY.md +176 -1
- package/dist/docs/overview.md +1 -0
- package/dist/docs/translations.md +253 -0
- package/dist/index.d.ts +1 -0
- package/dist/openapi.yaml +364 -0
- package/dist/translationCache.d.ts +38 -0
- package/dist/translationCache.js +298 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/translations.d.ts +107 -0
- package/dist/types/translations.js +1 -0
- package/docs/API_SUMMARY.md +176 -1
- package/docs/overview.md +1 -0
- package/docs/translations.md +253 -0
- package/openapi.yaml +364 -0
- package/package.json +1 -1
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
const DB_NAME = 'smartlinks-sdk-translations';
|
|
2
|
+
const STORE_NAME = 'translations';
|
|
3
|
+
const DB_VERSION = 1;
|
|
4
|
+
const DEFAULT_LOCAL_TRANSLATION_TTL_MS = 90 * 24 * 60 * 60000;
|
|
5
|
+
let dbPromise = null;
|
|
6
|
+
const memoryTranslationCache = new Map();
|
|
7
|
+
export function getDefaultTranslationCacheTtlMs() {
|
|
8
|
+
return DEFAULT_LOCAL_TRANSLATION_TTL_MS;
|
|
9
|
+
}
|
|
10
|
+
function isIndexedDbAvailable() {
|
|
11
|
+
try {
|
|
12
|
+
return typeof indexedDB !== 'undefined' && indexedDB !== null;
|
|
13
|
+
}
|
|
14
|
+
catch (_a) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function openDb() {
|
|
19
|
+
if (dbPromise)
|
|
20
|
+
return dbPromise;
|
|
21
|
+
dbPromise = new Promise((resolve, reject) => {
|
|
22
|
+
try {
|
|
23
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
24
|
+
request.onupgradeneeded = (event) => {
|
|
25
|
+
const db = event.target.result;
|
|
26
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
27
|
+
db.createObjectStore(STORE_NAME);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
request.onsuccess = (event) => {
|
|
31
|
+
resolve(event.target.result);
|
|
32
|
+
};
|
|
33
|
+
request.onerror = () => {
|
|
34
|
+
dbPromise = null;
|
|
35
|
+
reject(request.error);
|
|
36
|
+
};
|
|
37
|
+
request.onblocked = () => {
|
|
38
|
+
dbPromise = null;
|
|
39
|
+
reject(new Error('[smartlinks] Translation IndexedDB open blocked'));
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
dbPromise = null;
|
|
44
|
+
reject(error);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return dbPromise;
|
|
48
|
+
}
|
|
49
|
+
function stableContextKey(context) {
|
|
50
|
+
if (!context)
|
|
51
|
+
return null;
|
|
52
|
+
const entries = Object.entries(context)
|
|
53
|
+
.filter(([, value]) => value !== undefined)
|
|
54
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
55
|
+
if (entries.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
if (typeof context.surface === 'string' && typeof context.field === 'string') {
|
|
58
|
+
return `${context.surface}:${context.field}`;
|
|
59
|
+
}
|
|
60
|
+
return entries
|
|
61
|
+
.map(([key, value]) => `${key}=${String(value)}`)
|
|
62
|
+
.join('|');
|
|
63
|
+
}
|
|
64
|
+
export function deriveTranslationContextKey(context) {
|
|
65
|
+
return stableContextKey(context);
|
|
66
|
+
}
|
|
67
|
+
export function normalizeTranslationText(text, options = {}) {
|
|
68
|
+
const { trim = true, collapseWhitespace = false, unicodeNormalization = 'NFC', } = options;
|
|
69
|
+
let normalized = text.replace(/\r\n?/g, '\n');
|
|
70
|
+
if (trim) {
|
|
71
|
+
normalized = normalized.trim();
|
|
72
|
+
}
|
|
73
|
+
if (collapseWhitespace) {
|
|
74
|
+
normalized = normalized.replace(/[\t\f\v ]+/g, ' ');
|
|
75
|
+
}
|
|
76
|
+
if (unicodeNormalization) {
|
|
77
|
+
normalized = normalized.normalize(unicodeNormalization);
|
|
78
|
+
}
|
|
79
|
+
return normalized;
|
|
80
|
+
}
|
|
81
|
+
function toHex(buffer) {
|
|
82
|
+
const bytes = new Uint8Array(buffer);
|
|
83
|
+
let output = '';
|
|
84
|
+
for (const byte of bytes) {
|
|
85
|
+
output += byte.toString(16).padStart(2, '0');
|
|
86
|
+
}
|
|
87
|
+
return output;
|
|
88
|
+
}
|
|
89
|
+
export async function hashTranslationText(text, options = {}) {
|
|
90
|
+
var _a;
|
|
91
|
+
const normalized = normalizeTranslationText(text, options);
|
|
92
|
+
const subtle = (_a = globalThis.crypto) === null || _a === void 0 ? void 0 : _a.subtle;
|
|
93
|
+
if (!subtle) {
|
|
94
|
+
throw new Error('[smartlinks] Web Crypto is required for translation hashing');
|
|
95
|
+
}
|
|
96
|
+
const encoded = new TextEncoder().encode(normalized);
|
|
97
|
+
const digest = await subtle.digest('SHA-256', encoded);
|
|
98
|
+
return `sha256:${toHex(digest)}`;
|
|
99
|
+
}
|
|
100
|
+
function buildLocalCacheKey(params) {
|
|
101
|
+
var _a;
|
|
102
|
+
return [
|
|
103
|
+
params.collectionId,
|
|
104
|
+
params.sourceLanguage,
|
|
105
|
+
params.targetLanguage,
|
|
106
|
+
params.contentType,
|
|
107
|
+
(_a = params.contextKey) !== null && _a !== void 0 ? _a : '',
|
|
108
|
+
params.hash,
|
|
109
|
+
].join('::');
|
|
110
|
+
}
|
|
111
|
+
function isExpired(entry) {
|
|
112
|
+
return entry.expiresAt <= Date.now();
|
|
113
|
+
}
|
|
114
|
+
async function getEntry(key) {
|
|
115
|
+
const memoryEntry = memoryTranslationCache.get(key);
|
|
116
|
+
if (memoryEntry) {
|
|
117
|
+
if (isExpired(memoryEntry)) {
|
|
118
|
+
memoryTranslationCache.delete(key);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return memoryEntry;
|
|
122
|
+
}
|
|
123
|
+
if (!isIndexedDbAvailable())
|
|
124
|
+
return null;
|
|
125
|
+
try {
|
|
126
|
+
const db = await openDb();
|
|
127
|
+
return await new Promise((resolve) => {
|
|
128
|
+
try {
|
|
129
|
+
const tx = db.transaction(STORE_NAME, 'readonly');
|
|
130
|
+
const request = tx.objectStore(STORE_NAME).get(key);
|
|
131
|
+
request.onsuccess = () => {
|
|
132
|
+
var _a;
|
|
133
|
+
const result = (_a = request.result) !== null && _a !== void 0 ? _a : null;
|
|
134
|
+
if (!result) {
|
|
135
|
+
resolve(null);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (isExpired(result)) {
|
|
139
|
+
memoryTranslationCache.delete(key);
|
|
140
|
+
void deleteEntries([key]);
|
|
141
|
+
resolve(null);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
memoryTranslationCache.set(key, result);
|
|
145
|
+
resolve(result);
|
|
146
|
+
};
|
|
147
|
+
request.onerror = () => resolve(null);
|
|
148
|
+
}
|
|
149
|
+
catch (_a) {
|
|
150
|
+
resolve(null);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (_a) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export async function getCachedTranslations(params) {
|
|
159
|
+
const entries = await Promise.all(params.hashes.map(async (hash) => {
|
|
160
|
+
const key = buildLocalCacheKey(Object.assign(Object.assign({}, params), { hash }));
|
|
161
|
+
const entry = await getEntry(key);
|
|
162
|
+
return entry ? [hash, entry] : null;
|
|
163
|
+
}));
|
|
164
|
+
return new Map(entries.filter((entry) => entry !== null));
|
|
165
|
+
}
|
|
166
|
+
async function setEntries(entries) {
|
|
167
|
+
for (const [key, entry] of entries) {
|
|
168
|
+
memoryTranslationCache.set(key, entry);
|
|
169
|
+
}
|
|
170
|
+
if (!isIndexedDbAvailable())
|
|
171
|
+
return;
|
|
172
|
+
try {
|
|
173
|
+
const db = await openDb();
|
|
174
|
+
await new Promise((resolve) => {
|
|
175
|
+
try {
|
|
176
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
177
|
+
const store = tx.objectStore(STORE_NAME);
|
|
178
|
+
for (const [key, entry] of entries) {
|
|
179
|
+
store.put(entry, key);
|
|
180
|
+
}
|
|
181
|
+
tx.oncomplete = () => resolve();
|
|
182
|
+
tx.onerror = () => resolve();
|
|
183
|
+
tx.onabort = () => resolve();
|
|
184
|
+
}
|
|
185
|
+
catch (_a) {
|
|
186
|
+
resolve();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (_a) {
|
|
191
|
+
// Best-effort persistence only.
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
export async function setCachedTranslations(params) {
|
|
195
|
+
var _a;
|
|
196
|
+
const ttlMs = (_a = params.ttlMs) !== null && _a !== void 0 ? _a : DEFAULT_LOCAL_TRANSLATION_TTL_MS;
|
|
197
|
+
const now = Date.now();
|
|
198
|
+
const entries = params.items.map(({ hash, item }) => {
|
|
199
|
+
const key = buildLocalCacheKey({
|
|
200
|
+
collectionId: params.collectionId,
|
|
201
|
+
sourceLanguage: params.sourceLanguage,
|
|
202
|
+
targetLanguage: params.targetLanguage,
|
|
203
|
+
contentType: params.contentType,
|
|
204
|
+
contextKey: params.contextKey,
|
|
205
|
+
hash,
|
|
206
|
+
});
|
|
207
|
+
const entry = {
|
|
208
|
+
collectionId: params.collectionId,
|
|
209
|
+
sourceLanguage: params.sourceLanguage,
|
|
210
|
+
targetLanguage: params.targetLanguage,
|
|
211
|
+
contentType: params.contentType,
|
|
212
|
+
contextKey: params.contextKey,
|
|
213
|
+
hash,
|
|
214
|
+
item: Object.assign(Object.assign({}, item), { expiresAt: now + ttlMs }),
|
|
215
|
+
cachedAt: now,
|
|
216
|
+
expiresAt: now + ttlMs,
|
|
217
|
+
};
|
|
218
|
+
return [key, entry];
|
|
219
|
+
});
|
|
220
|
+
await setEntries(entries);
|
|
221
|
+
}
|
|
222
|
+
async function deleteEntries(keys) {
|
|
223
|
+
for (const key of keys) {
|
|
224
|
+
memoryTranslationCache.delete(key);
|
|
225
|
+
}
|
|
226
|
+
if (!isIndexedDbAvailable() || keys.length === 0)
|
|
227
|
+
return;
|
|
228
|
+
try {
|
|
229
|
+
const db = await openDb();
|
|
230
|
+
await new Promise((resolve) => {
|
|
231
|
+
try {
|
|
232
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
233
|
+
const store = tx.objectStore(STORE_NAME);
|
|
234
|
+
for (const key of keys) {
|
|
235
|
+
store.delete(key);
|
|
236
|
+
}
|
|
237
|
+
tx.oncomplete = () => resolve();
|
|
238
|
+
tx.onerror = () => resolve();
|
|
239
|
+
tx.onabort = () => resolve();
|
|
240
|
+
}
|
|
241
|
+
catch (_a) {
|
|
242
|
+
resolve();
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
catch (_a) {
|
|
247
|
+
// Ignore deletion failures.
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
export async function clearCachedTranslations(collectionId) {
|
|
251
|
+
const memoryKeys = Array.from(memoryTranslationCache.keys());
|
|
252
|
+
const keysToDelete = collectionId
|
|
253
|
+
? memoryKeys.filter((key) => key.startsWith(`${collectionId}::`))
|
|
254
|
+
: memoryKeys;
|
|
255
|
+
await deleteEntries(keysToDelete);
|
|
256
|
+
if (!isIndexedDbAvailable())
|
|
257
|
+
return;
|
|
258
|
+
try {
|
|
259
|
+
const db = await openDb();
|
|
260
|
+
if (!collectionId) {
|
|
261
|
+
await new Promise((resolve) => {
|
|
262
|
+
try {
|
|
263
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
264
|
+
tx.objectStore(STORE_NAME).clear();
|
|
265
|
+
tx.oncomplete = () => resolve();
|
|
266
|
+
tx.onerror = () => resolve();
|
|
267
|
+
tx.onabort = () => resolve();
|
|
268
|
+
}
|
|
269
|
+
catch (_a) {
|
|
270
|
+
resolve();
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
await new Promise((resolve) => {
|
|
276
|
+
try {
|
|
277
|
+
const tx = db.transaction(STORE_NAME, 'readwrite');
|
|
278
|
+
const store = tx.objectStore(STORE_NAME);
|
|
279
|
+
const request = store.getAllKeys();
|
|
280
|
+
request.onsuccess = () => {
|
|
281
|
+
for (const key of request.result) {
|
|
282
|
+
if (key.startsWith(`${collectionId}::`)) {
|
|
283
|
+
store.delete(key);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
resolve();
|
|
287
|
+
};
|
|
288
|
+
request.onerror = () => resolve();
|
|
289
|
+
}
|
|
290
|
+
catch (_a) {
|
|
291
|
+
resolve();
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
catch (_a) {
|
|
296
|
+
// Ignore deletion failures.
|
|
297
|
+
}
|
|
298
|
+
}
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export type TranslationLookupMode = 'cache-fill' | 'cache-only';
|
|
2
|
+
export type TranslationContentType = 'text/plain' | 'text/html' | 'text/x-liquid' | (string & {});
|
|
3
|
+
export type TranslationQuality = 'machine' | 'human' | 'passthrough' | (string & {});
|
|
4
|
+
export type TranslationItemStatus = 'cached' | 'generated' | 'miss' | 'passthrough' | 'local-cache' | (string & {});
|
|
5
|
+
export type TranslationContextValue = string | number | boolean | null;
|
|
6
|
+
export interface TranslationContext {
|
|
7
|
+
surface?: string;
|
|
8
|
+
field?: string;
|
|
9
|
+
[key: string]: TranslationContextValue | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface TranslationLookupRequestBase {
|
|
12
|
+
targetLanguage: string;
|
|
13
|
+
sourceLanguage?: string;
|
|
14
|
+
mode?: TranslationLookupMode;
|
|
15
|
+
contentType?: TranslationContentType;
|
|
16
|
+
context?: TranslationContext;
|
|
17
|
+
returnMeta?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface TranslationLookupSingleRequest extends TranslationLookupRequestBase {
|
|
20
|
+
text: string;
|
|
21
|
+
texts?: never;
|
|
22
|
+
}
|
|
23
|
+
export interface TranslationLookupBatchRequest extends TranslationLookupRequestBase {
|
|
24
|
+
text?: never;
|
|
25
|
+
texts: string[];
|
|
26
|
+
}
|
|
27
|
+
export type TranslationLookupRequest = TranslationLookupSingleRequest | TranslationLookupBatchRequest;
|
|
28
|
+
export interface TranslationLookupItem {
|
|
29
|
+
index: number;
|
|
30
|
+
hash: string;
|
|
31
|
+
sourceText: string;
|
|
32
|
+
translatedText?: string;
|
|
33
|
+
status?: TranslationItemStatus;
|
|
34
|
+
provider?: string;
|
|
35
|
+
model?: string;
|
|
36
|
+
isOverride?: boolean;
|
|
37
|
+
quality?: TranslationQuality;
|
|
38
|
+
createdAt?: string;
|
|
39
|
+
updatedAt?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface TranslationLookupResponse {
|
|
42
|
+
targetLanguage: string;
|
|
43
|
+
sourceLanguage?: string;
|
|
44
|
+
mode?: TranslationLookupMode;
|
|
45
|
+
items: TranslationLookupItem[];
|
|
46
|
+
}
|
|
47
|
+
export interface ResolvedTranslationItem extends TranslationLookupItem {
|
|
48
|
+
cacheSource?: 'local' | 'remote';
|
|
49
|
+
expiresAt?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface ResolvedTranslationResponse {
|
|
52
|
+
targetLanguage: string;
|
|
53
|
+
sourceLanguage?: string;
|
|
54
|
+
mode?: TranslationLookupMode;
|
|
55
|
+
items: ResolvedTranslationItem[];
|
|
56
|
+
}
|
|
57
|
+
export interface TranslationHashOptions {
|
|
58
|
+
trim?: boolean;
|
|
59
|
+
collapseWhitespace?: boolean;
|
|
60
|
+
unicodeNormalization?: 'NFC' | 'NFKC' | false;
|
|
61
|
+
}
|
|
62
|
+
export interface TranslationResolveOptions {
|
|
63
|
+
useLocalCache?: boolean;
|
|
64
|
+
refreshLocalCache?: boolean;
|
|
65
|
+
localCacheTtlMs?: number;
|
|
66
|
+
hashOptions?: TranslationHashOptions;
|
|
67
|
+
}
|
|
68
|
+
export interface TranslationRecord {
|
|
69
|
+
id: string;
|
|
70
|
+
collectionId: string;
|
|
71
|
+
sourceHash: string;
|
|
72
|
+
sourceText: string;
|
|
73
|
+
sourceLanguage?: string;
|
|
74
|
+
targetLanguage: string;
|
|
75
|
+
contentType: string;
|
|
76
|
+
contextKey?: string | null;
|
|
77
|
+
translatedText: string;
|
|
78
|
+
provider?: string | null;
|
|
79
|
+
model?: string | null;
|
|
80
|
+
quality: TranslationQuality;
|
|
81
|
+
isOverride: boolean;
|
|
82
|
+
metadata?: Record<string, any>;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
updatedAt: string;
|
|
85
|
+
}
|
|
86
|
+
export interface TranslationListParams {
|
|
87
|
+
targetLanguage?: string;
|
|
88
|
+
sourceLanguage?: string;
|
|
89
|
+
contentType?: string;
|
|
90
|
+
contextKey?: string;
|
|
91
|
+
q?: string;
|
|
92
|
+
isOverride?: boolean;
|
|
93
|
+
limit?: number;
|
|
94
|
+
offset?: number;
|
|
95
|
+
}
|
|
96
|
+
export interface TranslationListResponse {
|
|
97
|
+
items: TranslationRecord[];
|
|
98
|
+
total?: number;
|
|
99
|
+
limit?: number;
|
|
100
|
+
offset?: number;
|
|
101
|
+
}
|
|
102
|
+
export interface TranslationUpdateRequest {
|
|
103
|
+
translatedText?: string;
|
|
104
|
+
isOverride?: boolean;
|
|
105
|
+
quality?: TranslationQuality;
|
|
106
|
+
metadata?: Record<string, any>;
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/docs/API_SUMMARY.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Smartlinks API Summary
|
|
2
2
|
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.4 | Generated: 2026-03-23T19:52:46.756Z
|
|
4
4
|
|
|
5
5
|
This is a concise summary of all available API functions and types.
|
|
6
6
|
|
|
@@ -110,6 +110,7 @@ The Smartlinks SDK is organized into the following namespaces:
|
|
|
110
110
|
- **realtime** - Functions for realtime operations
|
|
111
111
|
- **tags** - Functions for tags operations
|
|
112
112
|
- **template** - Functions for template operations
|
|
113
|
+
- **translations** - Functions for translations operations
|
|
113
114
|
|
|
114
115
|
## HTTP Utilities
|
|
115
116
|
|
|
@@ -6343,6 +6344,153 @@ interface TemplateRenderSourceResponse {
|
|
|
6343
6344
|
|
|
6344
6345
|
**TemplatePublic** = `TemplateBase`
|
|
6345
6346
|
|
|
6347
|
+
### translations
|
|
6348
|
+
|
|
6349
|
+
**TranslationContext** (interface)
|
|
6350
|
+
```typescript
|
|
6351
|
+
interface TranslationContext {
|
|
6352
|
+
surface?: string
|
|
6353
|
+
field?: string
|
|
6354
|
+
[key: string]: TranslationContextValue | undefined
|
|
6355
|
+
}
|
|
6356
|
+
```
|
|
6357
|
+
|
|
6358
|
+
**TranslationLookupRequestBase** (interface)
|
|
6359
|
+
```typescript
|
|
6360
|
+
interface TranslationLookupRequestBase {
|
|
6361
|
+
targetLanguage: string
|
|
6362
|
+
sourceLanguage?: string
|
|
6363
|
+
mode?: TranslationLookupMode
|
|
6364
|
+
contentType?: TranslationContentType
|
|
6365
|
+
context?: TranslationContext
|
|
6366
|
+
returnMeta?: boolean
|
|
6367
|
+
}
|
|
6368
|
+
```
|
|
6369
|
+
|
|
6370
|
+
**TranslationLookupItem** (interface)
|
|
6371
|
+
```typescript
|
|
6372
|
+
interface TranslationLookupItem {
|
|
6373
|
+
index: number
|
|
6374
|
+
hash: string
|
|
6375
|
+
sourceText: string
|
|
6376
|
+
translatedText?: string
|
|
6377
|
+
status?: TranslationItemStatus
|
|
6378
|
+
provider?: string
|
|
6379
|
+
model?: string
|
|
6380
|
+
isOverride?: boolean
|
|
6381
|
+
quality?: TranslationQuality
|
|
6382
|
+
createdAt?: string
|
|
6383
|
+
updatedAt?: string
|
|
6384
|
+
}
|
|
6385
|
+
```
|
|
6386
|
+
|
|
6387
|
+
**TranslationLookupResponse** (interface)
|
|
6388
|
+
```typescript
|
|
6389
|
+
interface TranslationLookupResponse {
|
|
6390
|
+
targetLanguage: string
|
|
6391
|
+
sourceLanguage?: string
|
|
6392
|
+
mode?: TranslationLookupMode
|
|
6393
|
+
items: TranslationLookupItem[]
|
|
6394
|
+
}
|
|
6395
|
+
```
|
|
6396
|
+
|
|
6397
|
+
**ResolvedTranslationResponse** (interface)
|
|
6398
|
+
```typescript
|
|
6399
|
+
interface ResolvedTranslationResponse {
|
|
6400
|
+
targetLanguage: string
|
|
6401
|
+
sourceLanguage?: string
|
|
6402
|
+
mode?: TranslationLookupMode
|
|
6403
|
+
items: ResolvedTranslationItem[]
|
|
6404
|
+
}
|
|
6405
|
+
```
|
|
6406
|
+
|
|
6407
|
+
**TranslationHashOptions** (interface)
|
|
6408
|
+
```typescript
|
|
6409
|
+
interface TranslationHashOptions {
|
|
6410
|
+
trim?: boolean
|
|
6411
|
+
collapseWhitespace?: boolean
|
|
6412
|
+
unicodeNormalization?: 'NFC' | 'NFKC' | false
|
|
6413
|
+
}
|
|
6414
|
+
```
|
|
6415
|
+
|
|
6416
|
+
**TranslationResolveOptions** (interface)
|
|
6417
|
+
```typescript
|
|
6418
|
+
interface TranslationResolveOptions {
|
|
6419
|
+
useLocalCache?: boolean
|
|
6420
|
+
refreshLocalCache?: boolean
|
|
6421
|
+
localCacheTtlMs?: number
|
|
6422
|
+
hashOptions?: TranslationHashOptions
|
|
6423
|
+
}
|
|
6424
|
+
```
|
|
6425
|
+
|
|
6426
|
+
**TranslationRecord** (interface)
|
|
6427
|
+
```typescript
|
|
6428
|
+
interface TranslationRecord {
|
|
6429
|
+
id: string
|
|
6430
|
+
collectionId: string
|
|
6431
|
+
sourceHash: string
|
|
6432
|
+
sourceText: string
|
|
6433
|
+
sourceLanguage?: string
|
|
6434
|
+
targetLanguage: string
|
|
6435
|
+
contentType: string
|
|
6436
|
+
contextKey?: string | null
|
|
6437
|
+
translatedText: string
|
|
6438
|
+
provider?: string | null
|
|
6439
|
+
model?: string | null
|
|
6440
|
+
quality: TranslationQuality
|
|
6441
|
+
isOverride: boolean
|
|
6442
|
+
metadata?: Record<string, any>
|
|
6443
|
+
createdAt: string
|
|
6444
|
+
updatedAt: string
|
|
6445
|
+
}
|
|
6446
|
+
```
|
|
6447
|
+
|
|
6448
|
+
**TranslationListParams** (interface)
|
|
6449
|
+
```typescript
|
|
6450
|
+
interface TranslationListParams {
|
|
6451
|
+
targetLanguage?: string
|
|
6452
|
+
sourceLanguage?: string
|
|
6453
|
+
contentType?: string
|
|
6454
|
+
contextKey?: string
|
|
6455
|
+
q?: string
|
|
6456
|
+
isOverride?: boolean
|
|
6457
|
+
limit?: number
|
|
6458
|
+
offset?: number
|
|
6459
|
+
}
|
|
6460
|
+
```
|
|
6461
|
+
|
|
6462
|
+
**TranslationListResponse** (interface)
|
|
6463
|
+
```typescript
|
|
6464
|
+
interface TranslationListResponse {
|
|
6465
|
+
items: TranslationRecord[]
|
|
6466
|
+
total?: number
|
|
6467
|
+
limit?: number
|
|
6468
|
+
offset?: number
|
|
6469
|
+
}
|
|
6470
|
+
```
|
|
6471
|
+
|
|
6472
|
+
**TranslationUpdateRequest** (interface)
|
|
6473
|
+
```typescript
|
|
6474
|
+
interface TranslationUpdateRequest {
|
|
6475
|
+
translatedText?: string
|
|
6476
|
+
isOverride?: boolean
|
|
6477
|
+
quality?: TranslationQuality
|
|
6478
|
+
metadata?: Record<string, any>
|
|
6479
|
+
}
|
|
6480
|
+
```
|
|
6481
|
+
|
|
6482
|
+
**TranslationLookupMode** = `'cache-fill' | 'cache-only'`
|
|
6483
|
+
|
|
6484
|
+
**TranslationContentType** = `'text/plain' | 'text/html' | 'text/x-liquid' | (string & {})`
|
|
6485
|
+
|
|
6486
|
+
**TranslationQuality** = `'machine' | 'human' | 'passthrough' | (string & {})`
|
|
6487
|
+
|
|
6488
|
+
**TranslationItemStatus** = `'cached' | 'generated' | 'miss' | 'passthrough' | 'local-cache' | (string & {})`
|
|
6489
|
+
|
|
6490
|
+
**TranslationContextValue** = `string | number | boolean | null`
|
|
6491
|
+
|
|
6492
|
+
**TranslationLookupRequest** = `TranslationLookupSingleRequest | TranslationLookupBatchRequest`
|
|
6493
|
+
|
|
6346
6494
|
### variant
|
|
6347
6495
|
|
|
6348
6496
|
**VariantResponse** = `any`
|
|
@@ -8169,6 +8317,33 @@ Reverse lookup by ref via POST (public). `POST /public/collection/:collectionId/
|
|
|
8169
8317
|
**renderSource**(collectionId: string,
|
|
8170
8318
|
body: TemplateRenderSourceRequest) → `Promise<TemplateRenderSourceResponse>`
|
|
8171
8319
|
|
|
8320
|
+
### translations
|
|
8321
|
+
|
|
8322
|
+
**hashText**(text: string, options?: TranslationHashOptions) → `Promise<string>`
|
|
8323
|
+
|
|
8324
|
+
**hashTexts**(texts: string[], options?: TranslationHashOptions) → `Promise<string[]>`
|
|
8325
|
+
|
|
8326
|
+
**normalizeText**(text: string, options?: TranslationHashOptions) → `string`
|
|
8327
|
+
|
|
8328
|
+
**lookup**(collectionId: string,
|
|
8329
|
+
body: TranslationLookupRequest) → `Promise<TranslationLookupResponse>`
|
|
8330
|
+
|
|
8331
|
+
**resolve**(collectionId: string,
|
|
8332
|
+
body: TranslationLookupRequest,
|
|
8333
|
+
options: TranslationResolveOptions = {}) → `Promise<ResolvedTranslationResponse>`
|
|
8334
|
+
|
|
8335
|
+
**list**(collectionId: string,
|
|
8336
|
+
params?: TranslationListParams) → `Promise<TranslationListResponse>`
|
|
8337
|
+
|
|
8338
|
+
**get**(collectionId: string,
|
|
8339
|
+
translationId: string) → `Promise<TranslationRecord>`
|
|
8340
|
+
|
|
8341
|
+
**update**(collectionId: string,
|
|
8342
|
+
translationId: string,
|
|
8343
|
+
body: TranslationUpdateRequest) → `Promise<TranslationRecord>`
|
|
8344
|
+
|
|
8345
|
+
**clearLocalCache**(collectionId?: string) → `Promise<void>`
|
|
8346
|
+
|
|
8172
8347
|
### tts
|
|
8173
8348
|
|
|
8174
8349
|
**generate**(collectionId: string,
|
package/docs/overview.md
CHANGED
|
@@ -49,6 +49,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
|
|
|
49
49
|
| **Multi-Page Architecture** | `docs/mpa.md` | Build pipeline, entry points, multi-page setup, content hashing |
|
|
50
50
|
| **AI & Chat** | `docs/ai.md` | Chat completions, RAG, streaming, tool calling, voice, podcasts, TTS |
|
|
51
51
|
| **Analytics** | `docs/analytics.md` | Fire-and-forget page/click/tag analytics plus admin dashboard queries |
|
|
52
|
+
| **Translations** | `docs/translations.md` | Runtime translation lookup, local-first IndexedDB caching, and translation admin APIs |
|
|
52
53
|
| **Theming** | `docs/theme.system.md` | Implementing dynamic themes via URL params or postMessage |
|
|
53
54
|
| **Theme Defaults** | `docs/theme-defaults.md` | Default colour values for light/dark modes |
|
|
54
55
|
| **Internationalization** | `docs/i18n.md` | Adding multi-language support, translation patterns |
|