generaltranslation 9.1.13 → 9.2.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/CHANGELOG.md +31 -0
- package/dist/api.cjs +9 -0
- package/dist/api.d.cts +1 -0
- package/dist/api.d.mts +1 -0
- package/dist/api.d.ts +1 -0
- package/dist/api.js +1 -0
- package/dist/api.mjs +2 -0
- package/dist/{derive-C3nzgrzy.mjs → derive-BRvTJxLf.mjs} +3 -2
- package/dist/{derive-C3nzgrzy.mjs.map → derive-BRvTJxLf.mjs.map} +1 -1
- package/dist/{file-D7gKavRj.cjs → file-B37WkCqM.cjs} +6 -6
- package/dist/file-B37WkCqM.cjs.map +1 -0
- package/dist/{file-Cgk1Xk9d.mjs → file-Dga6cyM8.mjs} +6 -6
- package/dist/file-Dga6cyM8.mjs.map +1 -0
- package/dist/id.d.cts +1 -1
- package/dist/id.d.mts +1 -1
- package/dist/index.cjs +130 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +109 -5
- package/dist/index.mjs.map +1 -1
- package/dist/internal.cjs +16 -8
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +18 -6
- package/dist/internal.d.mts +18 -6
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +1 -0
- package/dist/internal.mjs +3 -3
- package/dist/openapi.json +6184 -0
- package/dist/{runtime-hWpzl6v_.mjs → runtime-CqKaoInO.mjs} +23 -114
- package/dist/runtime-CqKaoInO.mjs.map +1 -0
- package/dist/{runtime-DoOLkKJT.cjs → runtime-DeF1Ef5w.cjs} +45 -136
- package/dist/{runtime-DoOLkKJT.cjs.map → runtime-DeF1Ef5w.cjs.map} +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.d.cts +1 -1
- package/dist/runtime.d.mts +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/settings/settingsUrls.d.ts +2 -2
- package/dist/settings/settingsUrls.js +2 -2
- package/dist/translate/api.d.ts +4 -1
- package/dist/translate/api.js +4 -1
- package/dist/translate/translateMany.js +34 -13
- package/dist/translate/utils/apiRequest.js +3 -3
- package/dist/translate/utils/fetchWithTimeout.js +7 -2
- package/dist/translate/utils/unwrapApiResult.d.ts +15 -0
- package/dist/translate/utils/unwrapApiResult.js +30 -0
- package/dist/{types-C8sSACgY.d.mts → types-BUNfoXph.d.mts} +6 -6
- package/dist/{types-DO3dc8ST.d.cts → types-Do446qa9.d.cts} +6 -6
- package/dist/types-dir/api/file.d.ts +4 -4
- package/dist/types-dir/api/file.js +5 -5
- package/dist/types.cjs +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types.mjs +1 -1
- package/dist/{api-rqq7klYe.mjs → unwrapApiResult-BzGfPw75.mjs} +24 -6
- package/dist/unwrapApiResult-BzGfPw75.mjs.map +1 -0
- package/dist/{api-tMgy8sHj.cjs → unwrapApiResult-Dv6Mfw_K.cjs} +41 -11
- package/dist/unwrapApiResult-Dv6Mfw_K.cjs.map +1 -0
- package/package.json +16 -2
- package/dist/api-rqq7klYe.mjs.map +0 -1
- package/dist/api-tMgy8sHj.cjs.map +0 -1
- package/dist/file-Cgk1Xk9d.mjs.map +0 -1
- package/dist/file-D7gKavRj.cjs.map +0 -1
- package/dist/runtime-hWpzl6v_.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# generaltranslation
|
|
2
2
|
|
|
3
|
+
## 9.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2179](https://github.com/generaltranslation/gt/pull/2179) [`4496e16`](https://github.com/generaltranslation/gt/commit/4496e161d7885f329bdfd7f4d04a7a58ed12d9d1) Thanks [@chenxin-yan](https://github.com/chenxin-yan)! - Expose the generated API SDK from the `generaltranslation/api` subpath.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#2233](https://github.com/generaltranslation/gt/pull/2233) [`8725a5c`](https://github.com/generaltranslation/gt/commit/8725a5c9235926cf1653a9306cca44045874c0dc) Thanks [@eoinest](https://github.com/eoinest)! - Fix UTF-16 `.strings` and `.stringsdict` files being corrupted or rejected on upload.
|
|
12
|
+
|
|
13
|
+
Older Xcode wrote both formats as UTF-16, and legacy repositories still contain them. The CLI read every file as UTF-8 text, so a UTF-16 `.stringsdict` reached the API as mojibake and its XML parser rejected it outright — the file could not be uploaded at all. A UTF-16 `.strings` file did upload, but came back as byte-order-mark-less UTF-8, so every one of them showed as rewritten in `git diff`.
|
|
14
|
+
|
|
15
|
+
Encoding is now handled entirely by the CLI, which is the only part of the pipeline that touches the filesystem, and within the CLI by a single module at the disk boundary. Reads decode by byte order mark, so the API only ever receives UTF-8 text. Writes re-encode to the source file's own encoding, which the CLI already knows because it just read that file, so a UTF-16 repository stays UTF-16 and a UTF-8 one gains no byte order mark. This also fixes re-downloading a UTF-16 `.stringsdict` source, which previously produced a file `plutil` rejected with `Unexpected character ã at line 1`.
|
|
16
|
+
|
|
17
|
+
If the source file has been moved or deleted since it was uploaded, the translation already on disk is used as the record of the encoding instead, so those files keep their encoding rather than being rewritten as UTF-8.
|
|
18
|
+
|
|
19
|
+
The content hash recorded for a downloaded translation is now taken from its decoded text as well, so a file stored in UTF-16 stops reading as edited on every run because its hash had been computed from bytes read as UTF-8.
|
|
20
|
+
|
|
21
|
+
A file with no byte order mark is treated as UTF-8 even when its bytes are plainly UTF-16, matching Foundation: `plutil` rejects those files too, so guessing would translate content the platform itself cannot read.
|
|
22
|
+
|
|
23
|
+
`DOT_STRINGS` leaves `BINARY_FILE_FORMATS`, which now contains only `LOTTIE`. Every `.strings` file's version id changes once, because it is now hashed from the decoded text rather than the base64 payload, so each one re-translates a single time.
|
|
24
|
+
|
|
25
|
+
- [#2240](https://github.com/generaltranslation/gt/pull/2240) [`0e5d7e0`](https://github.com/generaltranslation/gt/commit/0e5d7e0efd48f98659a8229f7e48273070981f5b) Thanks [@eoinest](https://github.com/eoinest)! - Send default API and runtime translation requests to `https://api.gtx.dev` while preserving their existing paths and custom URL overrides.
|
|
26
|
+
|
|
27
|
+
- [#2180](https://github.com/generaltranslation/gt/pull/2180) [`3c33a75`](https://github.com/generaltranslation/gt/commit/3c33a75c738c2f433cfdf4e19d75b189c0100f38) Thanks [@chenxin-yan](https://github.com/chenxin-yan)! - Route runtime and Sanity API requests through the generated General Translation API SDK while preserving the existing public interfaces and caller-configured runtime timeouts.
|
|
28
|
+
|
|
29
|
+
- [#2202](https://github.com/generaltranslation/gt/pull/2202) [`6ac4ba3`](https://github.com/generaltranslation/gt/commit/6ac4ba33a0230fb8aecae7c7677cfd38c361bd9c) Thanks [@chenxin-yan](https://github.com/chenxin-yan)! - Expose `spec/openapi.json` through the API and core package exports.
|
|
30
|
+
|
|
31
|
+
- Updated dependencies [[`3c33a75`](https://github.com/generaltranslation/gt/commit/3c33a75c738c2f433cfdf4e19d75b189c0100f38), [`6ac4ba3`](https://github.com/generaltranslation/gt/commit/6ac4ba33a0230fb8aecae7c7677cfd38c361bd9c), [`33ea383`](https://github.com/generaltranslation/gt/commit/33ea383b5d1593793b0a704b35b8a750ea8c3274)]:
|
|
32
|
+
- @generaltranslation/api@0.1.0
|
|
33
|
+
|
|
3
34
|
## 9.1.13
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/dist/api.cjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
var _generaltranslation_api = require("@generaltranslation/api");
|
|
2
|
+
Object.keys(_generaltranslation_api).forEach(function(k) {
|
|
3
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
4
|
+
enumerable: true,
|
|
5
|
+
get: function() {
|
|
6
|
+
return _generaltranslation_api[k];
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
});
|
package/dist/api.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@generaltranslation/api";
|
package/dist/api.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@generaltranslation/api";
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@generaltranslation/api';
|
package/dist/api.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@generaltranslation/api';
|
package/dist/api.mjs
ADDED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { API_VERSION } from "@generaltranslation/api";
|
|
1
2
|
import { TYPE, parse } from "@generaltranslation/icu";
|
|
2
3
|
//#region src/utils/isSupportedFileFormatTransform.ts
|
|
3
4
|
const SUPPORTED_TRANSFORMATIONS = {
|
|
@@ -219,6 +220,6 @@ function derive(content) {
|
|
|
219
220
|
return content;
|
|
220
221
|
}
|
|
221
222
|
//#endregion
|
|
222
|
-
export { isGTUnindexedSelectElement as a, decode as c, isGTIndexedSelectElement as i, encode as l, declareVar as n, VAR_IDENTIFIER as o, decodeVars as r, traverseIcu as s, derive as t, isSupportedFileFormatTransform as u };
|
|
223
|
+
export { isGTUnindexedSelectElement as a, decode as c, API_VERSION as d, isGTIndexedSelectElement as i, encode as l, declareVar as n, VAR_IDENTIFIER as o, decodeVars as r, traverseIcu as s, derive as t, isSupportedFileFormatTransform as u };
|
|
223
224
|
|
|
224
|
-
//# sourceMappingURL=derive-
|
|
225
|
+
//# sourceMappingURL=derive-BRvTJxLf.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive-C3nzgrzy.mjs","names":[],"sources":["../src/utils/isSupportedFileFormatTransform.ts","../src/utils/base64.ts","../src/derive/utils/traverseIcu.ts","../src/derive/utils/constants.ts","../src/derive/utils/regex.ts","../src/derive/utils/traverseHelpers.ts","../src/derive/decodeVars.ts","../src/derive/utils/sanitizeVar.ts","../src/derive/declareVar.ts","../src/derive/derive.ts"],"sourcesContent":["import type { FileFormat } from '../types-dir/api/file';\n\nconst SUPPORTED_TRANSFORMATIONS = {\n GTJSON: ['GTJSON'],\n JSON: ['JSON'],\n PO: ['PO'],\n // POT templates can produce translated PO catalog files.\n POT: ['POT', 'PO'],\n YAML: ['YAML'],\n MDX: ['MDX'],\n MD: ['MD'],\n TS: ['TS'],\n JS: ['JS'],\n HTML: ['HTML'],\n TXT: ['TXT'],\n TWILIO_CONTENT_JSON: ['TWILIO_CONTENT_JSON'],\n LOTTIE: ['LOTTIE'],\n SVG: ['SVG'],\n DOT_STRINGS: ['DOT_STRINGS'],\n DOT_STRINGSDICT: ['DOT_STRINGSDICT'],\n ANDROID_STRINGS: ['ANDROID_STRINGS'],\n} as const satisfies Record<FileFormat, FileFormat[]>;\n\n/**\n * This function checks if a file format transformation is supported during translation\n * @param from - The source file format.\n * @param to - The target file format.\n * @returns True if the transformation is supported, false otherwise\n */\nexport function isSupportedFileFormatTransform(\n from: FileFormat,\n to: FileFormat\n): boolean {\n const toFormats: FileFormat[] | undefined = SUPPORTED_TRANSFORMATIONS[from];\n return toFormats?.includes(to) ?? false;\n}\n","// Encode a string to base64\nexport function encode(data: string): string {\n if (typeof Buffer !== 'undefined') {\n // Node.js path.\n return Buffer.from(data, 'utf8').toString('base64');\n }\n // Browser path.\n const bytes = new TextEncoder().encode(data);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n// Decode a base64 string to a string\nexport function decode(base64: string): string {\n if (typeof Buffer !== 'undefined') {\n // Node.js path.\n return Buffer.from(base64, 'base64').toString('utf8');\n }\n // Browser path.\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n","import {\n parse,\n TYPE,\n type MessageFormatElement,\n type ParserOptions,\n} from '@generaltranslation/icu';\n\ntype TraverseIcuOptions = ParserOptions & {\n recurseIntoVisited?: boolean;\n};\n\n/**\n * Given an ICU string, traverse the AST and call the visitor function for each element that matches the type T\n * @param icu - The ICU string to traverse\n * @param shouldVisit - A function that returns true if the element should be visited\n * @param visitor - A function that is called for each element that matches the type T\n * @returns The modified AST of the ICU string.\n *\n * @note This function is a heavy operation, use sparingly\n */\nexport function traverseIcu<T extends MessageFormatElement>({\n icuString,\n shouldVisit,\n visitor,\n options: { recurseIntoVisited = true, ...otherOptions },\n}: {\n icuString: string;\n shouldVisit: (element: MessageFormatElement) => element is T;\n visitor: (element: T) => void;\n options: TraverseIcuOptions;\n}): MessageFormatElement[] {\n const ast = parse(icuString, otherOptions);\n handleChildren(ast);\n return ast;\n\n function handleChildren(children: MessageFormatElement[]): void {\n children.map(handleChild);\n }\n\n function handleChild(child: MessageFormatElement) {\n // handle select var\n let visited = false;\n if (shouldVisit(child)) {\n visitor(child);\n visited = true;\n }\n // recurse on children\n if (!visited || recurseIntoVisited) {\n if (child.type === TYPE.select || child.type === TYPE.plural) {\n Object.values(child.options)\n .map((option) => option.value)\n .map(handleChildren);\n } else if (child.type === TYPE.tag) {\n handleChildren(child.children);\n }\n }\n }\n}\n","export const VAR_IDENTIFIER = '_gt_';\nexport const VAR_NAME_IDENTIFIER = '_gt_var_name';\n","import { VAR_IDENTIFIER } from './constants';\n\n// Regex for _gt_# select\nexport const GT_INDEXED_IDENTIFIER_REGEX = new RegExp(\n `^${VAR_IDENTIFIER}\\\\d+$`\n);\n\nexport const GT_UNINDEXED_IDENTIFIER_REGEX = new RegExp(`^${VAR_IDENTIFIER}$`);\n","import {\n GT_INDEXED_IDENTIFIER_REGEX,\n GT_UNINDEXED_IDENTIFIER_REGEX,\n} from './regex';\nimport { GTIndexedSelectElement, GTUnindexedSelectElement } from './types';\nimport { TYPE, type MessageFormatElement } from '@generaltranslation/icu';\n\n// Visit any _gt_# select\nexport function isGTIndexedSelectElement(\n child: MessageFormatElement\n): child is GTIndexedSelectElement {\n return (\n child.type === TYPE.select &&\n GT_INDEXED_IDENTIFIER_REGEX.test(child.value) &&\n !!child.options.other &&\n (child.options.other.value.length === 0 ||\n (child.options.other.value.length > 0 &&\n child.options.other.value[0]?.type === TYPE.literal))\n );\n}\n\n// Visit any _gt_ select\nexport function isGTUnindexedSelectElement(\n child: MessageFormatElement\n): child is GTUnindexedSelectElement {\n return (\n child.type === TYPE.select &&\n GT_UNINDEXED_IDENTIFIER_REGEX.test(child.value) &&\n !!child.options.other &&\n (child.options.other.value.length === 0 ||\n (child.options.other.value.length > 0 &&\n child.options.other.value[0]?.type === TYPE.literal))\n );\n}\n","import { traverseIcu } from './utils/traverseIcu';\nimport { VAR_IDENTIFIER } from './utils/constants';\nimport { GTUnindexedSelectElement } from './utils/types';\nimport { isGTUnindexedSelectElement } from './utils/traverseHelpers';\n\ntype Location = {\n start: number;\n end: number;\n value: string;\n};\n\n/**\n * Given an encoded ICU string, interpolate only _gt_ variables that have been marked with declareVar()\n * @example\n * const encodedIcu = \"Hi\" + declareVar(\"Brian\") + \", my name is {name}\"\n * // 'Hi {_gt_, select, other {Brian}}, my name is {name}'\n * decodeVars(encodedIcu)\n * // 'Hi Brian, my name is {name}'\n */\nexport function decodeVars(icuString: string): string {\n // Check if the string contains _gt_\n if (!icuString.includes(VAR_IDENTIFIER)) {\n return icuString;\n }\n\n // Record the location of the variable\n const variableLocations: Location[] = [];\n function visitor(child: GTUnindexedSelectElement): void {\n variableLocations.push({\n start: child.location?.start.offset ?? 0,\n end: child.location?.end.offset ?? 0,\n value:\n child.options.other.value.length > 0\n ? child.options.other.value[0].value\n : '',\n });\n }\n\n // Find all variable identifiers.\n traverseIcu({\n icuString,\n shouldVisit: isGTUnindexedSelectElement,\n visitor,\n options: {\n recurseIntoVisited: false,\n captureLocation: true,\n },\n });\n\n // Construct output string\n let previousIndex = 0;\n const outputList = [];\n for (let i = 0; i < variableLocations.length; i++) {\n outputList.push(icuString.slice(previousIndex, variableLocations[i].start));\n outputList.push(variableLocations[i].value);\n previousIndex = variableLocations[i].end;\n }\n if (previousIndex < icuString.length) {\n outputList.push(icuString.slice(previousIndex));\n }\n const outputString = outputList.join('');\n\n return outputString;\n}\n","/**\n * Sanitizes string by escaping ICU syntax\n *\n * Sanitize arbitrary string so it does not break the following ICU message syntax:\n * {_gt_, select, other {string_here}}\n *\n * Escapes ICU special characters by:\n * 1. Doubling all single quotes (U+0027 ')\n * 2. Adding a single quote before the first special character ({}<>)\n * 3. Adding a single quote after the last special character ({}<>)\n */\nexport function sanitizeVar(string: string): string {\n // First, double all single quotes (both ASCII and Unicode).\n let result = string.replace(/'/g, \"''\");\n\n // Find first and last positions of special characters\n const specialChars = /[{}<>]/;\n const firstSpecialIndex = result.search(specialChars);\n\n if (firstSpecialIndex === -1) {\n // No special characters; return with just doubled quotes.\n return result;\n }\n\n // Find last special character position\n let lastSpecialIndex = -1;\n for (let i = result.length - 1; i >= 0; i--) {\n if (specialChars.test(result[i])) {\n lastSpecialIndex = i;\n break;\n }\n }\n\n // Insert quotes around the special character region.\n result =\n result.slice(0, firstSpecialIndex) +\n \"'\" +\n result.slice(firstSpecialIndex, lastSpecialIndex + 1) +\n \"'\" +\n result.slice(lastSpecialIndex + 1);\n\n return result;\n}\n","import { VAR_IDENTIFIER, VAR_NAME_IDENTIFIER } from './utils/constants';\nimport { sanitizeVar } from './utils/sanitizeVar';\n\n/**\n * Mark as a non-translatable string. Use within a derive() call to mark content as not derivable (e.g., not possible to statically analyze).\n *\n * @example\n * function nonDerivableFunction() {\n * return Math.random();\n * }\n *\n * function derivableFunction() {\n * if (condition) {\n * return declareVar(nonDerivableFunction())\n * }\n * return 'John Doe';\n * }\n *\n * const gt = useGT();\n * gt(`My name is ${derive(derivableFunction())}`);\n *\n * @param {string | number | boolean | null | undefined} variable - The variable to sanitize.\n * @param {Object} [options] - The options for the sanitization.\n * @param {string} [options.$name] - The name of the variable.\n * @returns {string} The sanitized value.\n */\nexport function declareVar(\n variable: string | number | boolean | null | undefined,\n options?: { $name?: string }\n): string {\n // Variable section.\n const sanitizedVariable = sanitizeVar(String(variable ?? ''));\n const variableSection = ` other {${sanitizedVariable}}`;\n\n // Name section.\n let nameSection = '';\n if (options?.$name) {\n const sanitizedName = sanitizeVar(options.$name);\n nameSection = ` ${VAR_NAME_IDENTIFIER} {${sanitizedName}}`;\n }\n\n // interpolate\n return `{${VAR_IDENTIFIER}, select,${variableSection}${nameSection}}`;\n}\n","/**\n * Marks content as derivable by the GT compiler and CLI.\n *\n * Use `derive()` when a translation string or context needs content that is\n * computed from source code, but should still be discovered during extraction\n * instead of treated as a runtime interpolation variable. The CLI attempts to\n * resolve the derivable expression into every possible static value and\n * includes those values in the source content that gets translated.\n *\n * `derive()` returns its argument unchanged at runtime.\n *\n * Run `gt validate` after adding or changing `derive()` calls to verify that\n * each derivable expression can be resolved by the CLI before translating or\n * building.\n *\n * @example\n * ```jsx\n * function getSubject() {\n * return (Math.random() > 0.5) ? \"Alice\" : \"Brian\";\n * }\n * ...\n * gt(`My name is ${derive(getSubject())}`);\n * ```\n *\n * @param {T extends string | boolean | number | null | undefined} content - Content to derive for translation extraction.\n * @returns {T} The same content, unchanged at runtime.\n */\nexport function derive<T extends string | boolean | number | null | undefined>(\n content: T\n): T {\n return content;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"derive-BRvTJxLf.mjs","names":[],"sources":["../src/utils/isSupportedFileFormatTransform.ts","../src/utils/base64.ts","../src/derive/utils/traverseIcu.ts","../src/derive/utils/constants.ts","../src/derive/utils/regex.ts","../src/derive/utils/traverseHelpers.ts","../src/derive/decodeVars.ts","../src/derive/utils/sanitizeVar.ts","../src/derive/declareVar.ts","../src/derive/derive.ts"],"sourcesContent":["import type { FileFormat } from '../types-dir/api/file';\n\nconst SUPPORTED_TRANSFORMATIONS = {\n GTJSON: ['GTJSON'],\n JSON: ['JSON'],\n PO: ['PO'],\n // POT templates can produce translated PO catalog files.\n POT: ['POT', 'PO'],\n YAML: ['YAML'],\n MDX: ['MDX'],\n MD: ['MD'],\n TS: ['TS'],\n JS: ['JS'],\n HTML: ['HTML'],\n TXT: ['TXT'],\n TWILIO_CONTENT_JSON: ['TWILIO_CONTENT_JSON'],\n LOTTIE: ['LOTTIE'],\n SVG: ['SVG'],\n DOT_STRINGS: ['DOT_STRINGS'],\n DOT_STRINGSDICT: ['DOT_STRINGSDICT'],\n ANDROID_STRINGS: ['ANDROID_STRINGS'],\n} as const satisfies Record<FileFormat, FileFormat[]>;\n\n/**\n * This function checks if a file format transformation is supported during translation\n * @param from - The source file format.\n * @param to - The target file format.\n * @returns True if the transformation is supported, false otherwise\n */\nexport function isSupportedFileFormatTransform(\n from: FileFormat,\n to: FileFormat\n): boolean {\n const toFormats: FileFormat[] | undefined = SUPPORTED_TRANSFORMATIONS[from];\n return toFormats?.includes(to) ?? false;\n}\n","// Encode a string to base64\nexport function encode(data: string): string {\n if (typeof Buffer !== 'undefined') {\n // Node.js path.\n return Buffer.from(data, 'utf8').toString('base64');\n }\n // Browser path.\n const bytes = new TextEncoder().encode(data);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n// Decode a base64 string to a string\nexport function decode(base64: string): string {\n if (typeof Buffer !== 'undefined') {\n // Node.js path.\n return Buffer.from(base64, 'base64').toString('utf8');\n }\n // Browser path.\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n","import {\n parse,\n TYPE,\n type MessageFormatElement,\n type ParserOptions,\n} from '@generaltranslation/icu';\n\ntype TraverseIcuOptions = ParserOptions & {\n recurseIntoVisited?: boolean;\n};\n\n/**\n * Given an ICU string, traverse the AST and call the visitor function for each element that matches the type T\n * @param icu - The ICU string to traverse\n * @param shouldVisit - A function that returns true if the element should be visited\n * @param visitor - A function that is called for each element that matches the type T\n * @returns The modified AST of the ICU string.\n *\n * @note This function is a heavy operation, use sparingly\n */\nexport function traverseIcu<T extends MessageFormatElement>({\n icuString,\n shouldVisit,\n visitor,\n options: { recurseIntoVisited = true, ...otherOptions },\n}: {\n icuString: string;\n shouldVisit: (element: MessageFormatElement) => element is T;\n visitor: (element: T) => void;\n options: TraverseIcuOptions;\n}): MessageFormatElement[] {\n const ast = parse(icuString, otherOptions);\n handleChildren(ast);\n return ast;\n\n function handleChildren(children: MessageFormatElement[]): void {\n children.map(handleChild);\n }\n\n function handleChild(child: MessageFormatElement) {\n // handle select var\n let visited = false;\n if (shouldVisit(child)) {\n visitor(child);\n visited = true;\n }\n // recurse on children\n if (!visited || recurseIntoVisited) {\n if (child.type === TYPE.select || child.type === TYPE.plural) {\n Object.values(child.options)\n .map((option) => option.value)\n .map(handleChildren);\n } else if (child.type === TYPE.tag) {\n handleChildren(child.children);\n }\n }\n }\n}\n","export const VAR_IDENTIFIER = '_gt_';\nexport const VAR_NAME_IDENTIFIER = '_gt_var_name';\n","import { VAR_IDENTIFIER } from './constants';\n\n// Regex for _gt_# select\nexport const GT_INDEXED_IDENTIFIER_REGEX = new RegExp(\n `^${VAR_IDENTIFIER}\\\\d+$`\n);\n\nexport const GT_UNINDEXED_IDENTIFIER_REGEX = new RegExp(`^${VAR_IDENTIFIER}$`);\n","import {\n GT_INDEXED_IDENTIFIER_REGEX,\n GT_UNINDEXED_IDENTIFIER_REGEX,\n} from './regex';\nimport { GTIndexedSelectElement, GTUnindexedSelectElement } from './types';\nimport { TYPE, type MessageFormatElement } from '@generaltranslation/icu';\n\n// Visit any _gt_# select\nexport function isGTIndexedSelectElement(\n child: MessageFormatElement\n): child is GTIndexedSelectElement {\n return (\n child.type === TYPE.select &&\n GT_INDEXED_IDENTIFIER_REGEX.test(child.value) &&\n !!child.options.other &&\n (child.options.other.value.length === 0 ||\n (child.options.other.value.length > 0 &&\n child.options.other.value[0]?.type === TYPE.literal))\n );\n}\n\n// Visit any _gt_ select\nexport function isGTUnindexedSelectElement(\n child: MessageFormatElement\n): child is GTUnindexedSelectElement {\n return (\n child.type === TYPE.select &&\n GT_UNINDEXED_IDENTIFIER_REGEX.test(child.value) &&\n !!child.options.other &&\n (child.options.other.value.length === 0 ||\n (child.options.other.value.length > 0 &&\n child.options.other.value[0]?.type === TYPE.literal))\n );\n}\n","import { traverseIcu } from './utils/traverseIcu';\nimport { VAR_IDENTIFIER } from './utils/constants';\nimport { GTUnindexedSelectElement } from './utils/types';\nimport { isGTUnindexedSelectElement } from './utils/traverseHelpers';\n\ntype Location = {\n start: number;\n end: number;\n value: string;\n};\n\n/**\n * Given an encoded ICU string, interpolate only _gt_ variables that have been marked with declareVar()\n * @example\n * const encodedIcu = \"Hi\" + declareVar(\"Brian\") + \", my name is {name}\"\n * // 'Hi {_gt_, select, other {Brian}}, my name is {name}'\n * decodeVars(encodedIcu)\n * // 'Hi Brian, my name is {name}'\n */\nexport function decodeVars(icuString: string): string {\n // Check if the string contains _gt_\n if (!icuString.includes(VAR_IDENTIFIER)) {\n return icuString;\n }\n\n // Record the location of the variable\n const variableLocations: Location[] = [];\n function visitor(child: GTUnindexedSelectElement): void {\n variableLocations.push({\n start: child.location?.start.offset ?? 0,\n end: child.location?.end.offset ?? 0,\n value:\n child.options.other.value.length > 0\n ? child.options.other.value[0].value\n : '',\n });\n }\n\n // Find all variable identifiers.\n traverseIcu({\n icuString,\n shouldVisit: isGTUnindexedSelectElement,\n visitor,\n options: {\n recurseIntoVisited: false,\n captureLocation: true,\n },\n });\n\n // Construct output string\n let previousIndex = 0;\n const outputList = [];\n for (let i = 0; i < variableLocations.length; i++) {\n outputList.push(icuString.slice(previousIndex, variableLocations[i].start));\n outputList.push(variableLocations[i].value);\n previousIndex = variableLocations[i].end;\n }\n if (previousIndex < icuString.length) {\n outputList.push(icuString.slice(previousIndex));\n }\n const outputString = outputList.join('');\n\n return outputString;\n}\n","/**\n * Sanitizes string by escaping ICU syntax\n *\n * Sanitize arbitrary string so it does not break the following ICU message syntax:\n * {_gt_, select, other {string_here}}\n *\n * Escapes ICU special characters by:\n * 1. Doubling all single quotes (U+0027 ')\n * 2. Adding a single quote before the first special character ({}<>)\n * 3. Adding a single quote after the last special character ({}<>)\n */\nexport function sanitizeVar(string: string): string {\n // First, double all single quotes (both ASCII and Unicode).\n let result = string.replace(/'/g, \"''\");\n\n // Find first and last positions of special characters\n const specialChars = /[{}<>]/;\n const firstSpecialIndex = result.search(specialChars);\n\n if (firstSpecialIndex === -1) {\n // No special characters; return with just doubled quotes.\n return result;\n }\n\n // Find last special character position\n let lastSpecialIndex = -1;\n for (let i = result.length - 1; i >= 0; i--) {\n if (specialChars.test(result[i])) {\n lastSpecialIndex = i;\n break;\n }\n }\n\n // Insert quotes around the special character region.\n result =\n result.slice(0, firstSpecialIndex) +\n \"'\" +\n result.slice(firstSpecialIndex, lastSpecialIndex + 1) +\n \"'\" +\n result.slice(lastSpecialIndex + 1);\n\n return result;\n}\n","import { VAR_IDENTIFIER, VAR_NAME_IDENTIFIER } from './utils/constants';\nimport { sanitizeVar } from './utils/sanitizeVar';\n\n/**\n * Mark as a non-translatable string. Use within a derive() call to mark content as not derivable (e.g., not possible to statically analyze).\n *\n * @example\n * function nonDerivableFunction() {\n * return Math.random();\n * }\n *\n * function derivableFunction() {\n * if (condition) {\n * return declareVar(nonDerivableFunction())\n * }\n * return 'John Doe';\n * }\n *\n * const gt = useGT();\n * gt(`My name is ${derive(derivableFunction())}`);\n *\n * @param {string | number | boolean | null | undefined} variable - The variable to sanitize.\n * @param {Object} [options] - The options for the sanitization.\n * @param {string} [options.$name] - The name of the variable.\n * @returns {string} The sanitized value.\n */\nexport function declareVar(\n variable: string | number | boolean | null | undefined,\n options?: { $name?: string }\n): string {\n // Variable section.\n const sanitizedVariable = sanitizeVar(String(variable ?? ''));\n const variableSection = ` other {${sanitizedVariable}}`;\n\n // Name section.\n let nameSection = '';\n if (options?.$name) {\n const sanitizedName = sanitizeVar(options.$name);\n nameSection = ` ${VAR_NAME_IDENTIFIER} {${sanitizedName}}`;\n }\n\n // interpolate\n return `{${VAR_IDENTIFIER}, select,${variableSection}${nameSection}}`;\n}\n","/**\n * Marks content as derivable by the GT compiler and CLI.\n *\n * Use `derive()` when a translation string or context needs content that is\n * computed from source code, but should still be discovered during extraction\n * instead of treated as a runtime interpolation variable. The CLI attempts to\n * resolve the derivable expression into every possible static value and\n * includes those values in the source content that gets translated.\n *\n * `derive()` returns its argument unchanged at runtime.\n *\n * Run `gt validate` after adding or changing `derive()` calls to verify that\n * each derivable expression can be resolved by the CLI before translating or\n * building.\n *\n * @example\n * ```jsx\n * function getSubject() {\n * return (Math.random() > 0.5) ? \"Alice\" : \"Brian\";\n * }\n * ...\n * gt(`My name is ${derive(getSubject())}`);\n * ```\n *\n * @param {T extends string | boolean | number | null | undefined} content - Content to derive for translation extraction.\n * @returns {T} The same content, unchanged at runtime.\n */\nexport function derive<T extends string | boolean | number | null | undefined>(\n content: T\n): T {\n return content;\n}\n"],"mappings":";;;AAEA,MAAM,4BAA4B;CAChC,QAAQ,CAAC,SAAS;CAClB,MAAM,CAAC,OAAO;CACd,IAAI,CAAC,KAAK;CAEV,KAAK,CAAC,OAAO,KAAK;CAClB,MAAM,CAAC,OAAO;CACd,KAAK,CAAC,MAAM;CACZ,IAAI,CAAC,KAAK;CACV,IAAI,CAAC,KAAK;CACV,IAAI,CAAC,KAAK;CACV,MAAM,CAAC,OAAO;CACd,KAAK,CAAC,MAAM;CACZ,qBAAqB,CAAC,sBAAsB;CAC5C,QAAQ,CAAC,SAAS;CAClB,KAAK,CAAC,MAAM;CACZ,aAAa,CAAC,cAAc;CAC5B,iBAAiB,CAAC,kBAAkB;CACpC,iBAAiB,CAAC,kBAAkB;CACrC;;;;;;;AAQD,SAAgB,+BACd,MACA,IACS;AAET,QAD4C,0BAA0B,OACpD,SAAS,GAAG,IAAI;;;;ACjCpC,SAAgB,OAAO,MAAsB;AAC3C,KAAI,OAAO,WAAW,YAEpB,QAAO,OAAO,KAAK,MAAM,OAAO,CAAC,SAAS,SAAS;CAGrD,MAAM,QAAQ,IAAI,aAAa,CAAC,OAAO,KAAK;CAC5C,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IAChC,WAAU,OAAO,aAAa,MAAM,GAAG;AAEzC,QAAO,KAAK,OAAO;;AAIrB,SAAgB,OAAO,QAAwB;AAC7C,KAAI,OAAO,WAAW,YAEpB,QAAO,OAAO,KAAK,QAAQ,SAAS,CAAC,SAAS,OAAO;CAGvD,MAAM,SAAS,KAAK,OAAO;CAC3B,MAAM,QAAQ,IAAI,WAAW,OAAO,OAAO;AAC3C,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,IACjC,OAAM,KAAK,OAAO,WAAW,EAAE;AAEjC,QAAO,IAAI,aAAa,CAAC,OAAO,MAAM;;;;;;;;;;;;;ACPxC,SAAgB,YAA4C,EAC1D,WACA,aACA,SACA,SAAS,EAAE,qBAAqB,MAAM,GAAG,kBAMhB;CACzB,MAAM,MAAM,MAAM,WAAW,aAAa;AAC1C,gBAAe,IAAI;AACnB,QAAO;CAEP,SAAS,eAAe,UAAwC;AAC9D,WAAS,IAAI,YAAY;;CAG3B,SAAS,YAAY,OAA6B;EAEhD,IAAI,UAAU;AACd,MAAI,YAAY,MAAM,EAAE;AACtB,WAAQ,MAAM;AACd,aAAU;;AAGZ,MAAI,CAAC,WAAW;OACV,MAAM,SAAS,KAAK,UAAU,MAAM,SAAS,KAAK,OACpD,QAAO,OAAO,MAAM,QAAQ,CACzB,KAAK,WAAW,OAAO,MAAM,CAC7B,IAAI,eAAe;YACb,MAAM,SAAS,KAAK,IAC7B,gBAAe,MAAM,SAAS;;;;;;ACrDtC,MAAa,iBAAiB;AAC9B,MAAa,sBAAsB;;;ACEnC,MAAa,8BAA8B,IAAI,OAC7C,IAAI,eAAe,OACpB;AAED,MAAa,gCAAgC,IAAI,OAAO,IAAI,eAAe,GAAG;;;ACC9E,SAAgB,yBACd,OACiC;AACjC,QACE,MAAM,SAAS,KAAK,UACpB,4BAA4B,KAAK,MAAM,MAAM,IAC7C,CAAC,CAAC,MAAM,QAAQ,UACf,MAAM,QAAQ,MAAM,MAAM,WAAW,KACnC,MAAM,QAAQ,MAAM,MAAM,SAAS,KAClC,MAAM,QAAQ,MAAM,MAAM,IAAI,SAAS,KAAK;;AAKpD,SAAgB,2BACd,OACmC;AACnC,QACE,MAAM,SAAS,KAAK,UACpB,8BAA8B,KAAK,MAAM,MAAM,IAC/C,CAAC,CAAC,MAAM,QAAQ,UACf,MAAM,QAAQ,MAAM,MAAM,WAAW,KACnC,MAAM,QAAQ,MAAM,MAAM,SAAS,KAClC,MAAM,QAAQ,MAAM,MAAM,IAAI,SAAS,KAAK;;;;;;;;;;;;ACZpD,SAAgB,WAAW,WAA2B;AAEpD,KAAI,CAAC,UAAU,SAAA,OAAwB,CACrC,QAAO;CAIT,MAAM,oBAAgC,EAAE;CACxC,SAAS,QAAQ,OAAuC;AACtD,oBAAkB,KAAK;GACrB,OAAO,MAAM,UAAU,MAAM,UAAU;GACvC,KAAK,MAAM,UAAU,IAAI,UAAU;GACnC,OACE,MAAM,QAAQ,MAAM,MAAM,SAAS,IAC/B,MAAM,QAAQ,MAAM,MAAM,GAAG,QAC7B;GACP,CAAC;;AAIJ,aAAY;EACV;EACA,aAAa;EACb;EACA,SAAS;GACP,oBAAoB;GACpB,iBAAiB;GAClB;EACF,CAAC;CAGF,IAAI,gBAAgB;CACpB,MAAM,aAAa,EAAE;AACrB,MAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAAK;AACjD,aAAW,KAAK,UAAU,MAAM,eAAe,kBAAkB,GAAG,MAAM,CAAC;AAC3E,aAAW,KAAK,kBAAkB,GAAG,MAAM;AAC3C,kBAAgB,kBAAkB,GAAG;;AAEvC,KAAI,gBAAgB,UAAU,OAC5B,YAAW,KAAK,UAAU,MAAM,cAAc,CAAC;AAIjD,QAFqB,WAAW,KAAK,GAElB;;;;;;;;;;;;;;;ACnDrB,SAAgB,YAAY,QAAwB;CAElD,IAAI,SAAS,OAAO,QAAQ,MAAM,KAAK;CAGvC,MAAM,eAAe;CACrB,MAAM,oBAAoB,OAAO,OAAO,aAAa;AAErD,KAAI,sBAAsB,GAExB,QAAO;CAIT,IAAI,mBAAmB;AACvB,MAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,IACtC,KAAI,aAAa,KAAK,OAAO,GAAG,EAAE;AAChC,qBAAmB;AACnB;;AAKJ,UACE,OAAO,MAAM,GAAG,kBAAkB,GAClC,MACA,OAAO,MAAM,mBAAmB,mBAAmB,EAAE,GACrD,MACA,OAAO,MAAM,mBAAmB,EAAE;AAEpC,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;ACfT,SAAgB,WACd,UACA,SACQ;CAGR,MAAM,kBAAkB,WADE,YAAY,OAAO,YAAY,GAAG,CACR,CAAC;CAGrD,IAAI,cAAc;AAClB,KAAI,SAAS,MAEX,eAAc,IAAI,oBAAoB,IADhB,YAAY,QAAQ,MACa,CAAC;AAI1D,QAAO,IAAI,eAAe,WAAW,kBAAkB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACfrE,SAAgB,OACd,SACG;AACH,QAAO"}
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* base64-encoded, so the usual UTF-8 encode/decode steps are skipped and the
|
|
5
5
|
* bytes reach the API unaltered.
|
|
6
6
|
*
|
|
7
|
-
* LOTTIE qualifies because it is a zip bundle.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* LOTTIE qualifies because it is a zip bundle. Apple's `.strings` and
|
|
8
|
+
* `.stringsdict` do not: they are text in whichever encoding Xcode wrote, and
|
|
9
|
+
* the client decodes that to UTF-8 before upload and restores it on write, so
|
|
10
|
+
* only the client ever handles their bytes.
|
|
11
11
|
*/
|
|
12
|
-
const BINARY_FILE_FORMATS = new Set(["LOTTIE"
|
|
12
|
+
const BINARY_FILE_FORMATS = new Set(["LOTTIE"]);
|
|
13
13
|
/**
|
|
14
14
|
* Whether a file format's content is carried as base64 end-to-end rather than
|
|
15
15
|
* as a UTF-8 text string.
|
|
@@ -31,4 +31,4 @@ Object.defineProperty(exports, "isBinaryFileFormat", {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
//# sourceMappingURL=file-
|
|
34
|
+
//# sourceMappingURL=file-B37WkCqM.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-B37WkCqM.cjs","names":[],"sources":["../src/types-dir/api/file.ts"],"sourcesContent":["import type { DataFormat } from '@generaltranslation/format/types';\nimport { Updates } from './enqueueFiles';\nimport type { JsonObject } from './json';\n\nexport type FileFormat = import('@generaltranslation/api').FileFormat;\n\n/**\n * File formats whose content travels through the pipeline already\n * base64-encoded, so the usual UTF-8 encode/decode steps are skipped and the\n * bytes reach the API unaltered.\n *\n * LOTTIE qualifies because it is a zip bundle. Apple's `.strings` and\n * `.stringsdict` do not: they are text in whichever encoding Xcode wrote, and\n * the client decodes that to UTF-8 before upload and restores it on write, so\n * only the client ever handles their bytes.\n */\nexport const BINARY_FILE_FORMATS: ReadonlySet<FileFormat> = new Set<FileFormat>(\n ['LOTTIE']\n);\n\n/**\n * Whether a file format's content is carried as base64 end-to-end rather than\n * as a UTF-8 text string.\n */\nexport function isBinaryFileFormat(fileFormat: FileFormat): boolean {\n return BINARY_FILE_FORMATS.has(fileFormat);\n}\n\n/**\n * Metadata for files or entries.\n */\nexport type FormatMetadata = JsonObject | Updates[number]['metadata'];\n\n/**\n * File object structure for uploading files.\n * @see {@link FileReferenceOptionalBranchId}\n * @property {string} content - Content of the file.\n * @property {string} locale - The locale of the file (e.g. 'en', 'de', 'es', etc.)\n * @property {FormatMetadata} [formatMetadata] - Optional metadata for the file, specific to the format of the file\n * @property {string} [incomingBranchId] - The ID of the incoming branch of the file.\n * @property {string} [checkedOutBranchId] - The ID of the checked-out branch of the file.\n */\nexport type FileToUpload = Omit<FileReference, 'branchId'> & {\n content: string;\n locale: string;\n // Optional output format requested for generated translations.\n transformFormat?: FileFormat;\n formatMetadata?: FormatMetadata;\n branchId?: string;\n incomingBranchId?: string;\n checkedOutBranchId?: string;\n};\n\n/**\n * File object structure for referencing files.\n * @property {string} fileId - The ID of the file.\n * @property {string} versionId - The ID of the version of the file\n * @property {string} branchId - The ID of the branch of the file\n * @property {string} locale - The locale of the file (e.g. 'en', 'de', 'es', etc.)\n * @property {string} fileName - The name of the file.\n * @property {FileFormat} fileFormat - The format of the file (JSON, MDX, MD, etc.).\n * @property {DataFormat} [dataFormat] - Optional format of the data within the file.\n */\nexport type FileReference = {\n fileId: string;\n versionId: string;\n branchId: string;\n fileName: string;\n fileFormat: FileFormat;\n // Optional output format requested for generated translations.\n transformFormat?: FileFormat;\n dataFormat?: DataFormat;\n};\n\n/**\n * File reference object structure for referencing files.\n * @see {@link FileReference}\n * @property {string} [branchId] - The ID of the branch of the file\n */\nexport type FileReferenceIds = Omit<\n FileReference,\n 'branchId' | 'fileName' | 'fileFormat' | 'dataFormat'\n> & {\n branchId?: string;\n fileName?: string;\n fileFormat?: FileFormat;\n transformFormat?: FileFormat;\n dataFormat?: DataFormat;\n};\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,sBAA+C,IAAI,IAC9D,CAAC,SAAS,CACX;;;;;AAMD,SAAgB,mBAAmB,YAAiC;AAClE,QAAO,oBAAoB,IAAI,WAAW"}
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* base64-encoded, so the usual UTF-8 encode/decode steps are skipped and the
|
|
5
5
|
* bytes reach the API unaltered.
|
|
6
6
|
*
|
|
7
|
-
* LOTTIE qualifies because it is a zip bundle.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* LOTTIE qualifies because it is a zip bundle. Apple's `.strings` and
|
|
8
|
+
* `.stringsdict` do not: they are text in whichever encoding Xcode wrote, and
|
|
9
|
+
* the client decodes that to UTF-8 before upload and restores it on write, so
|
|
10
|
+
* only the client ever handles their bytes.
|
|
11
11
|
*/
|
|
12
|
-
const BINARY_FILE_FORMATS = new Set(["LOTTIE"
|
|
12
|
+
const BINARY_FILE_FORMATS = new Set(["LOTTIE"]);
|
|
13
13
|
/**
|
|
14
14
|
* Whether a file format's content is carried as base64 end-to-end rather than
|
|
15
15
|
* as a UTF-8 text string.
|
|
@@ -20,4 +20,4 @@ function isBinaryFileFormat(fileFormat) {
|
|
|
20
20
|
//#endregion
|
|
21
21
|
export { isBinaryFileFormat as n, BINARY_FILE_FORMATS as t };
|
|
22
22
|
|
|
23
|
-
//# sourceMappingURL=file-
|
|
23
|
+
//# sourceMappingURL=file-Dga6cyM8.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-Dga6cyM8.mjs","names":[],"sources":["../src/types-dir/api/file.ts"],"sourcesContent":["import type { DataFormat } from '@generaltranslation/format/types';\nimport { Updates } from './enqueueFiles';\nimport type { JsonObject } from './json';\n\nexport type FileFormat = import('@generaltranslation/api').FileFormat;\n\n/**\n * File formats whose content travels through the pipeline already\n * base64-encoded, so the usual UTF-8 encode/decode steps are skipped and the\n * bytes reach the API unaltered.\n *\n * LOTTIE qualifies because it is a zip bundle. Apple's `.strings` and\n * `.stringsdict` do not: they are text in whichever encoding Xcode wrote, and\n * the client decodes that to UTF-8 before upload and restores it on write, so\n * only the client ever handles their bytes.\n */\nexport const BINARY_FILE_FORMATS: ReadonlySet<FileFormat> = new Set<FileFormat>(\n ['LOTTIE']\n);\n\n/**\n * Whether a file format's content is carried as base64 end-to-end rather than\n * as a UTF-8 text string.\n */\nexport function isBinaryFileFormat(fileFormat: FileFormat): boolean {\n return BINARY_FILE_FORMATS.has(fileFormat);\n}\n\n/**\n * Metadata for files or entries.\n */\nexport type FormatMetadata = JsonObject | Updates[number]['metadata'];\n\n/**\n * File object structure for uploading files.\n * @see {@link FileReferenceOptionalBranchId}\n * @property {string} content - Content of the file.\n * @property {string} locale - The locale of the file (e.g. 'en', 'de', 'es', etc.)\n * @property {FormatMetadata} [formatMetadata] - Optional metadata for the file, specific to the format of the file\n * @property {string} [incomingBranchId] - The ID of the incoming branch of the file.\n * @property {string} [checkedOutBranchId] - The ID of the checked-out branch of the file.\n */\nexport type FileToUpload = Omit<FileReference, 'branchId'> & {\n content: string;\n locale: string;\n // Optional output format requested for generated translations.\n transformFormat?: FileFormat;\n formatMetadata?: FormatMetadata;\n branchId?: string;\n incomingBranchId?: string;\n checkedOutBranchId?: string;\n};\n\n/**\n * File object structure for referencing files.\n * @property {string} fileId - The ID of the file.\n * @property {string} versionId - The ID of the version of the file\n * @property {string} branchId - The ID of the branch of the file\n * @property {string} locale - The locale of the file (e.g. 'en', 'de', 'es', etc.)\n * @property {string} fileName - The name of the file.\n * @property {FileFormat} fileFormat - The format of the file (JSON, MDX, MD, etc.).\n * @property {DataFormat} [dataFormat] - Optional format of the data within the file.\n */\nexport type FileReference = {\n fileId: string;\n versionId: string;\n branchId: string;\n fileName: string;\n fileFormat: FileFormat;\n // Optional output format requested for generated translations.\n transformFormat?: FileFormat;\n dataFormat?: DataFormat;\n};\n\n/**\n * File reference object structure for referencing files.\n * @see {@link FileReference}\n * @property {string} [branchId] - The ID of the branch of the file\n */\nexport type FileReferenceIds = Omit<\n FileReference,\n 'branchId' | 'fileName' | 'fileFormat' | 'dataFormat'\n> & {\n branchId?: string;\n fileName?: string;\n fileFormat?: FileFormat;\n transformFormat?: FileFormat;\n dataFormat?: DataFormat;\n};\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,sBAA+C,IAAI,IAC9D,CAAC,SAAS,CACX;;;;;AAMD,SAAgB,mBAAmB,YAAiC;AAClE,QAAO,oBAAoB,IAAI,WAAW"}
|
package/dist/id.d.cts
CHANGED
package/dist/id.d.mts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,114 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_runtime = require("./runtime-
|
|
2
|
+
const require_unwrapApiResult = require("./unwrapApiResult-Dv6Mfw_K.cjs");
|
|
3
|
+
const require_runtime = require("./runtime-DeF1Ef5w.cjs");
|
|
4
4
|
const require_derive = require("./derive-bDBg-KyF.cjs");
|
|
5
|
-
const require_file = require("./file-
|
|
5
|
+
const require_file = require("./file-B37WkCqM.cjs");
|
|
6
6
|
let _generaltranslation_format = require("@generaltranslation/format");
|
|
7
|
+
let _generaltranslation_api = require("@generaltranslation/api");
|
|
8
|
+
//#region src/translate/utils/handleFetchError.ts
|
|
9
|
+
function handleFetchError(error, timeout) {
|
|
10
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
11
|
+
const errorMessage = require_runtime.translationTimeoutError(timeout);
|
|
12
|
+
require_runtime.fetchLogger.error(errorMessage);
|
|
13
|
+
throw new Error(errorMessage);
|
|
14
|
+
}
|
|
15
|
+
const errorMessage = require_runtime.translationRequestFailedError(error instanceof Error ? error.message : String(error));
|
|
16
|
+
require_runtime.fetchLogger.error(errorMessage);
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/translate/utils/generateRequestHeaders.ts
|
|
21
|
+
function generateRequestHeaders(config, excludeContentType = false) {
|
|
22
|
+
const authHeaders = {
|
|
23
|
+
...!excludeContentType && { "Content-Type": "application/json" },
|
|
24
|
+
"gt-project-id": config.projectId
|
|
25
|
+
};
|
|
26
|
+
if (config.apiKey) authHeaders["Authorization"] = `Bearer ${config.apiKey}`;
|
|
27
|
+
authHeaders["gt-api-version"] = _generaltranslation_api.API_VERSION;
|
|
28
|
+
return authHeaders;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/translate/utils/apiRequest.ts
|
|
32
|
+
const MAX_RETRIES = 3;
|
|
33
|
+
const INITIAL_DELAY_MS = 500;
|
|
34
|
+
const RATE_LIMIT_RETRY_DELAY_MS = 6e4;
|
|
35
|
+
const MS_PER_SECOND = 1e3;
|
|
36
|
+
function sleep(ms) {
|
|
37
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
38
|
+
}
|
|
39
|
+
function getRetryDelay(policy, attempt) {
|
|
40
|
+
switch (policy) {
|
|
41
|
+
case "linear": return INITIAL_DELAY_MS * (attempt + 1);
|
|
42
|
+
case "exponential": return INITIAL_DELAY_MS * 2 ** attempt;
|
|
43
|
+
default: return 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function parseDelayMs(value) {
|
|
47
|
+
if (!value) return;
|
|
48
|
+
const seconds = Number(value.split(",")[0].split(";")[0].trim());
|
|
49
|
+
if (!Number.isFinite(seconds) || seconds < 0) return;
|
|
50
|
+
return seconds * MS_PER_SECOND;
|
|
51
|
+
}
|
|
52
|
+
function parseRetryAfter(value) {
|
|
53
|
+
const delayMs = parseDelayMs(value);
|
|
54
|
+
if (delayMs !== void 0) return delayMs;
|
|
55
|
+
if (!value) return;
|
|
56
|
+
const retryDate = Date.parse(value);
|
|
57
|
+
if (Number.isNaN(retryDate)) return;
|
|
58
|
+
return Math.max(retryDate - Date.now(), 0);
|
|
59
|
+
}
|
|
60
|
+
function getRateLimitRetryDelay(response) {
|
|
61
|
+
return parseRetryAfter(response.headers.get("Retry-After")) ?? parseDelayMs(response.headers.get("RateLimit-Reset")) ?? RATE_LIMIT_RETRY_DELAY_MS;
|
|
62
|
+
}
|
|
63
|
+
function getResponseRetryDelay(response, policy, attempt) {
|
|
64
|
+
if (response.status === 429) return getRateLimitRetryDelay(response);
|
|
65
|
+
return getRetryDelay(policy, attempt);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*
|
|
70
|
+
* Makes an API request with automatic retry for 429 and 5XX errors.
|
|
71
|
+
*
|
|
72
|
+
* Encapsulates URL construction, fetch with timeout, error handling,
|
|
73
|
+
* response validation, and JSON parsing.
|
|
74
|
+
*
|
|
75
|
+
* @param config - The configuration for the API call.
|
|
76
|
+
* @param endpoint - The API endpoint path (e.g. '/v2/project/jobs/info')
|
|
77
|
+
* @param options - Optional request options.
|
|
78
|
+
* @returns The parsed JSON response.
|
|
79
|
+
*/
|
|
80
|
+
async function apiRequest(config, endpoint, options) {
|
|
81
|
+
const timeout = options?.timeout ?? 6e4;
|
|
82
|
+
const retryPolicy = options?.retryPolicy ?? "exponential";
|
|
83
|
+
const url = `${config.baseUrl || "https://api.gtx.dev"}${endpoint}`;
|
|
84
|
+
const method = options?.method ?? "POST";
|
|
85
|
+
const maxRetries = retryPolicy === "none" ? 0 : MAX_RETRIES;
|
|
86
|
+
const requestInit = {
|
|
87
|
+
method,
|
|
88
|
+
headers: generateRequestHeaders(config)
|
|
89
|
+
};
|
|
90
|
+
if (options?.body !== void 0) requestInit.body = JSON.stringify(options.body);
|
|
91
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
92
|
+
let response;
|
|
93
|
+
try {
|
|
94
|
+
response = await require_runtime.fetchWithTimeout(url, requestInit, timeout);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
if (attempt < maxRetries) {
|
|
97
|
+
await sleep(getRetryDelay(retryPolicy, attempt));
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
handleFetchError(error, timeout);
|
|
101
|
+
}
|
|
102
|
+
if ((response.status === 429 || response.status >= 500) && attempt < maxRetries) {
|
|
103
|
+
await sleep(getResponseRetryDelay(response, retryPolicy, attempt));
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
await require_runtime.validateResponse(response);
|
|
107
|
+
return await response.json();
|
|
108
|
+
}
|
|
109
|
+
throw new Error("Max retries exceeded");
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
7
112
|
//#region src/translate/setupProject.ts
|
|
8
113
|
/**
|
|
9
114
|
* @internal
|
|
@@ -14,7 +119,7 @@ let _generaltranslation_format = require("@generaltranslation/format");
|
|
|
14
119
|
* @returns The result of the API call.
|
|
15
120
|
*/
|
|
16
121
|
async function _setupProject(files, config, options) {
|
|
17
|
-
return
|
|
122
|
+
return apiRequest(config, "/v2/project/setup/generate", {
|
|
18
123
|
body: {
|
|
19
124
|
files: files.map((f) => ({
|
|
20
125
|
branchId: f.branchId,
|
|
@@ -120,7 +225,7 @@ function validateFileFormatTransforms(files) {
|
|
|
120
225
|
async function _enqueueFiles(files, options, config) {
|
|
121
226
|
validateFileFormatTransforms(files);
|
|
122
227
|
const result = await processBatches(files, async (batch) => {
|
|
123
|
-
const apiResult = await
|
|
228
|
+
const apiResult = await apiRequest(config, "/v2/project/translations/enqueue", {
|
|
124
229
|
body: {
|
|
125
230
|
files: batch.map((f) => ({
|
|
126
231
|
branchId: f.branchId,
|
|
@@ -154,7 +259,7 @@ async function _enqueueFiles(files, options, config) {
|
|
|
154
259
|
* @returns The created or updated tag.
|
|
155
260
|
*/
|
|
156
261
|
async function _createTag(options, config) {
|
|
157
|
-
return await
|
|
262
|
+
return await apiRequest(config, "/v2/project/tags/create", { body: {
|
|
158
263
|
tagId: options.tagId,
|
|
159
264
|
files: options.files,
|
|
160
265
|
...options.message && { message: options.message }
|
|
@@ -172,7 +277,7 @@ async function _createTag(options, config) {
|
|
|
172
277
|
*/
|
|
173
278
|
async function _downloadFileBatch(requests, options, config) {
|
|
174
279
|
return processBatches(requests, async (batch) => {
|
|
175
|
-
return (await
|
|
280
|
+
return (await apiRequest(config, "/v2/project/files/download", {
|
|
176
281
|
body: batch,
|
|
177
282
|
timeout: options.timeout
|
|
178
283
|
})).files.map((file) => ({
|
|
@@ -189,7 +294,7 @@ async function _downloadFileBatch(requests, options, config) {
|
|
|
189
294
|
*/
|
|
190
295
|
async function _submitUserEditDiffs(payload, config, options = {}) {
|
|
191
296
|
await processBatches(payload.diffs, async (batch) => {
|
|
192
|
-
await
|
|
297
|
+
await apiRequest(config, "/v2/project/files/diffs", {
|
|
193
298
|
body: { diffs: batch },
|
|
194
299
|
timeout: options.timeout
|
|
195
300
|
});
|
|
@@ -209,7 +314,7 @@ async function _submitUserEditDiffs(payload, config, options = {}) {
|
|
|
209
314
|
*/
|
|
210
315
|
async function _uploadSourceFiles(files, options, config) {
|
|
211
316
|
return processBatches(files, async (batch) => {
|
|
212
|
-
return (await
|
|
317
|
+
return (await apiRequest(config, "/v2/project/files/upload-files", {
|
|
213
318
|
body: {
|
|
214
319
|
data: batch.map(({ source }) => ({ source: {
|
|
215
320
|
content: require_file.isBinaryFileFormat(source.fileFormat) ? source.content : require_derive.encode(source.content),
|
|
@@ -241,7 +346,7 @@ const FONT_UPLOAD_BATCH_SIZE = 50;
|
|
|
241
346
|
*/
|
|
242
347
|
async function _uploadFonts(fonts, options, config) {
|
|
243
348
|
return processBatches(fonts, async (batch) => {
|
|
244
|
-
return (await
|
|
349
|
+
return (await apiRequest(config, "/v2/project/assets", {
|
|
245
350
|
body: { assets: batch.map((font) => ({
|
|
246
351
|
assetType: font.assetType,
|
|
247
352
|
content: font.content,
|
|
@@ -264,7 +369,7 @@ async function _uploadFonts(fonts, options, config) {
|
|
|
264
369
|
async function _uploadTranslations(files, options, config) {
|
|
265
370
|
validateFileFormatTransforms(files.map(({ source }) => source));
|
|
266
371
|
return processBatches(files, async (batch) => {
|
|
267
|
-
return (await
|
|
372
|
+
return (await apiRequest(config, "/v2/project/files/upload-translations", {
|
|
268
373
|
body: {
|
|
269
374
|
data: batch.map(({ source, translations }) => ({
|
|
270
375
|
source: {
|
|
@@ -313,7 +418,7 @@ async function _querySourceFile(query, options, config) {
|
|
|
313
418
|
const searchParams = new URLSearchParams();
|
|
314
419
|
if (branchId) searchParams.set("branchId", branchId);
|
|
315
420
|
if (versionId) searchParams.set("versionId", versionId);
|
|
316
|
-
return
|
|
421
|
+
return apiRequest(config, `/v2/project/translations/files/status/${encodeURIComponent(fileId)}?${searchParams.toString()}`, {
|
|
317
422
|
method: "GET",
|
|
318
423
|
timeout: options.timeout
|
|
319
424
|
});
|
|
@@ -330,16 +435,16 @@ async function _querySourceFile(query, options, config) {
|
|
|
330
435
|
*/
|
|
331
436
|
async function _getProjectData(projectId, options, config) {
|
|
332
437
|
const { baseUrl } = config;
|
|
333
|
-
const timeout = options.timeout ? options.timeout :
|
|
334
|
-
const url = `${baseUrl || "https://
|
|
438
|
+
const timeout = options.timeout ? options.timeout : require_unwrapApiResult.defaultTimeout;
|
|
439
|
+
const url = `${baseUrl || "https://api.gtx.dev"}/v2/project/info/${encodeURIComponent(projectId)}`;
|
|
335
440
|
let response;
|
|
336
441
|
try {
|
|
337
442
|
response = await require_runtime.fetchWithTimeout(url, {
|
|
338
443
|
method: "GET",
|
|
339
|
-
headers:
|
|
444
|
+
headers: generateRequestHeaders(config)
|
|
340
445
|
}, timeout);
|
|
341
446
|
} catch (error) {
|
|
342
|
-
|
|
447
|
+
handleFetchError(error, timeout);
|
|
343
448
|
}
|
|
344
449
|
await require_runtime.validateResponse(response);
|
|
345
450
|
return await response.json();
|
|
@@ -355,7 +460,7 @@ async function _getProjectData(projectId, options, config) {
|
|
|
355
460
|
* @returns The result of the API call.
|
|
356
461
|
*/
|
|
357
462
|
async function _checkJobStatus(jobIds, config, timeoutMs) {
|
|
358
|
-
return
|
|
463
|
+
return apiRequest(config, "/v2/project/jobs/info", {
|
|
359
464
|
body: { jobIds },
|
|
360
465
|
timeout: timeoutMs
|
|
361
466
|
});
|
|
@@ -388,7 +493,7 @@ async function _awaitJobIds(jobIds, options, config) {
|
|
|
388
493
|
if (remainingTime <= 0) break;
|
|
389
494
|
let statuses;
|
|
390
495
|
try {
|
|
391
|
-
statuses = await _checkJobStatus(Array.from(pendingJobIds), config, Math.min(remainingTime,
|
|
496
|
+
statuses = await _checkJobStatus(Array.from(pendingJobIds), config, Math.min(remainingTime, require_unwrapApiResult.defaultTimeout));
|
|
392
497
|
} catch (error) {
|
|
393
498
|
if (Date.now() >= deadline) break;
|
|
394
499
|
throw error;
|
|
@@ -434,7 +539,7 @@ async function _awaitJobIds(jobIds, options, config) {
|
|
|
434
539
|
* @returns The file data.
|
|
435
540
|
*/
|
|
436
541
|
async function _queryFileData(data, options = {}, config) {
|
|
437
|
-
return
|
|
542
|
+
return apiRequest(config, "/v2/project/files/info", {
|
|
438
543
|
body: {
|
|
439
544
|
sourceFiles: data.sourceFiles?.map((item) => ({
|
|
440
545
|
fileId: item.fileId,
|
|
@@ -461,7 +566,7 @@ async function _queryFileData(data, options = {}, config) {
|
|
|
461
566
|
* @returns The project info.
|
|
462
567
|
*/
|
|
463
568
|
async function _getProjectInfo(options, config) {
|
|
464
|
-
return
|
|
569
|
+
return apiRequest(config, `/v2/project/info/${config.projectId}`, {
|
|
465
570
|
method: "GET",
|
|
466
571
|
timeout: options.timeout
|
|
467
572
|
});
|
|
@@ -476,7 +581,7 @@ async function _getProjectInfo(options, config) {
|
|
|
476
581
|
* @returns The branch information.
|
|
477
582
|
*/
|
|
478
583
|
async function _queryBranchData(query, config) {
|
|
479
|
-
return
|
|
584
|
+
return apiRequest(config, "/v2/project/branches/info", { body: query });
|
|
480
585
|
}
|
|
481
586
|
//#endregion
|
|
482
587
|
//#region src/translate/createBranch.ts
|
|
@@ -488,7 +593,7 @@ async function _queryBranchData(query, config) {
|
|
|
488
593
|
* @returns The created branch information.
|
|
489
594
|
*/
|
|
490
595
|
async function _createBranch(query, config) {
|
|
491
|
-
return
|
|
596
|
+
return apiRequest(config, "/v2/project/branches/create", { body: query });
|
|
492
597
|
}
|
|
493
598
|
//#endregion
|
|
494
599
|
//#region src/translate/processFileMoves.ts
|
|
@@ -511,7 +616,7 @@ async function _processFileMoves(moves, options, config) {
|
|
|
511
616
|
}
|
|
512
617
|
};
|
|
513
618
|
const batchResult = await processBatches(moves, async (batch) => {
|
|
514
|
-
return (await
|
|
619
|
+
return (await apiRequest(config, "/v2/project/files/moves", {
|
|
515
620
|
body: {
|
|
516
621
|
branchId: options.branchId,
|
|
517
622
|
moves: batch
|
|
@@ -544,7 +649,7 @@ async function _processFileMoves(moves, options, config) {
|
|
|
544
649
|
* @returns The orphaned files
|
|
545
650
|
*/
|
|
546
651
|
async function _getOrphanedFiles(branchId, fileIds, options = {}, config) {
|
|
547
|
-
const makeRequest = (batchFileIds) =>
|
|
652
|
+
const makeRequest = (batchFileIds) => apiRequest(config, "/v2/project/files/orphaned", {
|
|
548
653
|
body: {
|
|
549
654
|
branchId,
|
|
550
655
|
fileIds: batchFileIds
|
|
@@ -575,7 +680,7 @@ async function _getOrphanedFiles(branchId, fileIds, options = {}, config) {
|
|
|
575
680
|
* @returns The result of the API call.
|
|
576
681
|
*/
|
|
577
682
|
async function _publishFiles(files, config) {
|
|
578
|
-
return await
|
|
683
|
+
return await apiRequest(config, "/v2/project/files/publish", { body: { files } });
|
|
579
684
|
}
|
|
580
685
|
//#endregion
|
|
581
686
|
//#region src/index.ts
|