generaltranslation 9.0.3 → 9.0.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/CHANGELOG.md +12 -0
- package/dist/derive/condenseVars.js +2 -3
- package/dist/derive/utils/traverseHelpers.d.ts +1 -1
- package/dist/derive/utils/traverseHelpers.js +1 -1
- package/dist/derive/utils/traverseIcu.d.ts +1 -1
- package/dist/derive/utils/traverseIcu.js +1 -1
- package/dist/derive/utils/types.d.ts +1 -1
- package/dist/{derive-BvtWyo5B.cjs → derive-Cbl7M1SY.cjs} +7 -7
- package/dist/derive-Cbl7M1SY.cjs.map +1 -0
- package/dist/{derive-ClAsLQOX.mjs → derive-DDwuyrKI.mjs} +2 -2
- package/dist/derive-DDwuyrKI.mjs.map +1 -0
- package/dist/id.d.cts +1 -1
- package/dist/id.d.mts +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/internal.cjs +4 -97
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.mts +1 -1
- package/dist/internal.mjs +3 -96
- package/dist/internal.mjs.map +1 -1
- package/dist/{runtime-WSpZppgm.mjs → runtime-DsKdTOSO.mjs} +2 -2
- package/dist/{runtime-WSpZppgm.mjs.map → runtime-DsKdTOSO.mjs.map} +1 -1
- package/dist/{runtime-wK7jzE9f.cjs → runtime-mKpF6P4Q.cjs} +2 -2
- package/dist/{runtime-wK7jzE9f.cjs.map → runtime-mKpF6P4Q.cjs.map} +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.d.cts +2 -2
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +3 -3
- package/dist/runtime.mjs +1 -1
- package/dist/types-dir/config.d.ts +2 -0
- package/dist/{types-algPgkHv.d.mts → types-iO493WgK.d.mts} +3 -2
- package/dist/{types-f-_m5D_X.d.cts → types-wj-Dtih8.d.cts} +3 -2
- package/dist/types.d.cts +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +3 -4
- package/dist/derive/utils/printIcuAst.d.ts +0 -12
- package/dist/derive/utils/printIcuAst.js +0 -138
- package/dist/derive-BvtWyo5B.cjs.map +0 -1
- package/dist/derive-ClAsLQOX.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# generaltranslation
|
|
2
2
|
|
|
3
|
+
## 9.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1974](https://github.com/generaltranslation/gt/pull/1974) [`bbf4eb0`](https://github.com/generaltranslation/gt/commit/bbf4eb0cf77160baa615776619acd7afe35697ba) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - Add opt-in locale routing for TanStack Start. Setting `localeRouting` in `gt.config.json` makes `gtMiddleware` prioritize locale path prefixes and updates client locale changes to keep the pathname in sync while leaving the default locale unprefixed.
|
|
8
|
+
|
|
9
|
+
- [#1929](https://github.com/generaltranslation/gt/pull/1929) [`f53bb5e`](https://github.com/generaltranslation/gt/commit/f53bb5ea4b4989a2a4ad3aebf464011f01e029ad) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - Replace the FormatJS ICU parser and runtime formatter dependencies with the new dependency-free `@generaltranslation/icu` package.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`f53bb5e`](https://github.com/generaltranslation/gt/commit/f53bb5ea4b4989a2a4ad3aebf464011f01e029ad)]:
|
|
12
|
+
- @generaltranslation/icu@0.1.0
|
|
13
|
+
- @generaltranslation/format@0.1.3
|
|
14
|
+
|
|
3
15
|
## 9.0.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { TYPE } from '@
|
|
2
|
-
import { printIcuAst } from './utils/printIcuAst';
|
|
1
|
+
import { printAST, TYPE } from '@generaltranslation/icu';
|
|
3
2
|
import { traverseIcu } from './utils/traverseIcu';
|
|
4
3
|
import { VAR_IDENTIFIER } from './utils/constants';
|
|
5
4
|
import { isGTIndexedSelectElement } from './utils/traverseHelpers';
|
|
@@ -29,5 +28,5 @@ export function condenseVars(icuString) {
|
|
|
29
28
|
options: { recurseIntoVisited: false },
|
|
30
29
|
});
|
|
31
30
|
// Serialize
|
|
32
|
-
return
|
|
31
|
+
return printAST(ast);
|
|
33
32
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { GTIndexedSelectElement, GTUnindexedSelectElement } from './types';
|
|
2
|
-
import type
|
|
2
|
+
import { type MessageFormatElement } from '@generaltranslation/icu';
|
|
3
3
|
export declare function isGTIndexedSelectElement(child: MessageFormatElement): child is GTIndexedSelectElement;
|
|
4
4
|
export declare function isGTUnindexedSelectElement(child: MessageFormatElement): child is GTUnindexedSelectElement;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GT_INDEXED_IDENTIFIER_REGEX, GT_UNINDEXED_IDENTIFIER_REGEX, } from './regex';
|
|
2
|
-
import { TYPE } from '@
|
|
2
|
+
import { TYPE } from '@generaltranslation/icu';
|
|
3
3
|
// Visit any _gt_# select
|
|
4
4
|
export function isGTIndexedSelectElement(child) {
|
|
5
5
|
var _a;
|
|
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { parse, TYPE, } from '@
|
|
12
|
+
import { parse, TYPE, } from '@generaltranslation/icu';
|
|
13
13
|
/**
|
|
14
14
|
* Given an ICU string, traverse the AST and call the visitor function for each element that matches the type T
|
|
15
15
|
* @param icu - The ICU string to traverse
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VAR_IDENTIFIER } from './constants';
|
|
2
|
-
import type { PluralOrSelectOption, LiteralElement, SelectElement } from '@
|
|
2
|
+
import type { PluralOrSelectOption, LiteralElement, SelectElement } from '@generaltranslation/icu';
|
|
3
3
|
interface GTIndexedSelectOption extends PluralOrSelectOption {
|
|
4
4
|
value: Array<LiteralElement>;
|
|
5
5
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let
|
|
1
|
+
let _generaltranslation_icu = require("@generaltranslation/icu");
|
|
2
2
|
//#region src/utils/isSupportedFileFormatTransform.ts
|
|
3
3
|
const SUPPORTED_TRANSFORMATIONS = {
|
|
4
4
|
GTJSON: ["GTJSON"],
|
|
@@ -51,7 +51,7 @@ function decode(base64) {
|
|
|
51
51
|
* @note This function is a heavy operation, use sparingly
|
|
52
52
|
*/
|
|
53
53
|
function traverseIcu({ icuString, shouldVisit, visitor, options: { recurseIntoVisited = true, ...otherOptions } }) {
|
|
54
|
-
const ast = (0,
|
|
54
|
+
const ast = (0, _generaltranslation_icu.parse)(icuString, otherOptions);
|
|
55
55
|
handleChildren(ast);
|
|
56
56
|
return ast;
|
|
57
57
|
function handleChildren(children) {
|
|
@@ -64,8 +64,8 @@ function traverseIcu({ icuString, shouldVisit, visitor, options: { recurseIntoVi
|
|
|
64
64
|
visited = true;
|
|
65
65
|
}
|
|
66
66
|
if (!visited || recurseIntoVisited) {
|
|
67
|
-
if (child.type ===
|
|
68
|
-
else if (child.type ===
|
|
67
|
+
if (child.type === _generaltranslation_icu.TYPE.select || child.type === _generaltranslation_icu.TYPE.plural) Object.values(child.options).map((option) => option.value).map(handleChildren);
|
|
68
|
+
else if (child.type === _generaltranslation_icu.TYPE.tag) handleChildren(child.children);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -80,10 +80,10 @@ const GT_UNINDEXED_IDENTIFIER_REGEX = new RegExp(`^${VAR_IDENTIFIER}$`);
|
|
|
80
80
|
//#endregion
|
|
81
81
|
//#region src/derive/utils/traverseHelpers.ts
|
|
82
82
|
function isGTIndexedSelectElement(child) {
|
|
83
|
-
return child.type ===
|
|
83
|
+
return child.type === _generaltranslation_icu.TYPE.select && GT_INDEXED_IDENTIFIER_REGEX.test(child.value) && !!child.options.other && (child.options.other.value.length === 0 || child.options.other.value.length > 0 && child.options.other.value[0]?.type === _generaltranslation_icu.TYPE.literal);
|
|
84
84
|
}
|
|
85
85
|
function isGTUnindexedSelectElement(child) {
|
|
86
|
-
return child.type ===
|
|
86
|
+
return child.type === _generaltranslation_icu.TYPE.select && GT_UNINDEXED_IDENTIFIER_REGEX.test(child.value) && !!child.options.other && (child.options.other.value.length === 0 || child.options.other.value.length > 0 && child.options.other.value[0]?.type === _generaltranslation_icu.TYPE.literal);
|
|
87
87
|
}
|
|
88
88
|
//#endregion
|
|
89
89
|
//#region src/derive/decodeVars.ts
|
|
@@ -275,4 +275,4 @@ Object.defineProperty(exports, "traverseIcu", {
|
|
|
275
275
|
}
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
//# sourceMappingURL=derive-
|
|
278
|
+
//# sourceMappingURL=derive-Cbl7M1SY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-Cbl7M1SY.cjs","names":["TYPE","TYPE"],"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} 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,4 +1,4 @@
|
|
|
1
|
-
import { TYPE, parse } from "@
|
|
1
|
+
import { TYPE, parse } from "@generaltranslation/icu";
|
|
2
2
|
//#region src/utils/isSupportedFileFormatTransform.ts
|
|
3
3
|
const SUPPORTED_TRANSFORMATIONS = {
|
|
4
4
|
GTJSON: ["GTJSON"],
|
|
@@ -216,4 +216,4 @@ function derive(content) {
|
|
|
216
216
|
//#endregion
|
|
217
217
|
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 };
|
|
218
218
|
|
|
219
|
-
//# sourceMappingURL=derive-
|
|
219
|
+
//# sourceMappingURL=derive-DDwuyrKI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-DDwuyrKI.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} 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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"}
|
package/dist/id.d.cts
CHANGED
package/dist/id.d.mts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_api = require("./api-B2fSa2JN.cjs");
|
|
3
|
-
const require_runtime = require("./runtime-
|
|
4
|
-
const require_derive = require("./derive-
|
|
3
|
+
const require_runtime = require("./runtime-mKpF6P4Q.cjs");
|
|
4
|
+
const require_derive = require("./derive-Cbl7M1SY.cjs");
|
|
5
5
|
let _generaltranslation_format = require("@generaltranslation/format");
|
|
6
6
|
//#region src/translate/setupProject.ts
|
|
7
7
|
/**
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as UploadFilesOptions, A as AwaitJobsOptions, F as MoveMapping, H as FileDataResult, L as ProcessMovesOptions, N as CheckJobStatusResult, Q as FileUpload, R as ProcessMovesResponse, U as BranchQuery, V as FileDataQuery, W as BranchDataResult, X as PublishFileEntry, Y as DownloadFileOptions, Z as PublishFilesResult, _t as CheckFileTranslationsOptions, at as CreateTagResult, ct as DownloadFileBatchRequest, et as UploadFilesResponse, ht as EnqueueFilesResult, it as CreateTagOptions, j as AwaitJobsResult, k as SubmitUserEditDiffsPayload, lt as DownloadFileBatchResult, nt as SetupProjectOptions, ot as EnqueueFilesOptions, pt as FileReferenceIds, rt as SetupProjectResult, st as DownloadFileBatchOptions, tt as SetupProjectFileReference, vt as FileQuery, yt as FileQueryResult, z as GetOrphanedFilesResult } from "./types-
|
|
1
|
+
import { $ as UploadFilesOptions, A as AwaitJobsOptions, F as MoveMapping, H as FileDataResult, L as ProcessMovesOptions, N as CheckJobStatusResult, Q as FileUpload, R as ProcessMovesResponse, U as BranchQuery, V as FileDataQuery, W as BranchDataResult, X as PublishFileEntry, Y as DownloadFileOptions, Z as PublishFilesResult, _t as CheckFileTranslationsOptions, at as CreateTagResult, ct as DownloadFileBatchRequest, et as UploadFilesResponse, ht as EnqueueFilesResult, it as CreateTagOptions, j as AwaitJobsResult, k as SubmitUserEditDiffsPayload, lt as DownloadFileBatchResult, nt as SetupProjectOptions, ot as EnqueueFilesOptions, pt as FileReferenceIds, rt as SetupProjectResult, st as DownloadFileBatchOptions, tt as SetupProjectFileReference, vt as FileQuery, yt as FileQueryResult, z as GetOrphanedFilesResult } from "./types-wj-Dtih8.cjs";
|
|
2
2
|
import { GTConstructorParams, GTRuntime } from "./runtime.cjs";
|
|
3
3
|
import { n as declareVar, r as decodeVars, t as derive } from "./derive-DBCCXTmL.cjs";
|
|
4
4
|
import { LocaleConfig, LocaleConfigConstructorParams, determineLocale, formatCurrency, formatCutoff, formatDateTime, formatList, formatListToParts, formatMessage, formatNum, formatRelativeTime, formatRelativeTimeFromDate, getLocaleDirection, getLocaleEmoji, getLocaleName, getLocaleProperties, getRegionProperties, isSameDialect, isSameLanguage, isSupersetLocale, isValidLocale, requiresTranslation, resolveAliasLocale, resolveCanonicalLocale, standardizeLocale } from "@generaltranslation/format";
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as UploadFilesOptions, A as AwaitJobsOptions, F as MoveMapping, H as FileDataResult, L as ProcessMovesOptions, N as CheckJobStatusResult, Q as FileUpload, R as ProcessMovesResponse, U as BranchQuery, V as FileDataQuery, W as BranchDataResult, X as PublishFileEntry, Y as DownloadFileOptions, Z as PublishFilesResult, _t as CheckFileTranslationsOptions, at as CreateTagResult, ct as DownloadFileBatchRequest, et as UploadFilesResponse, ht as EnqueueFilesResult, it as CreateTagOptions, j as AwaitJobsResult, k as SubmitUserEditDiffsPayload, lt as DownloadFileBatchResult, nt as SetupProjectOptions, ot as EnqueueFilesOptions, pt as FileReferenceIds, rt as SetupProjectResult, st as DownloadFileBatchOptions, tt as SetupProjectFileReference, vt as FileQuery, yt as FileQueryResult, z as GetOrphanedFilesResult } from "./types-
|
|
1
|
+
import { $ as UploadFilesOptions, A as AwaitJobsOptions, F as MoveMapping, H as FileDataResult, L as ProcessMovesOptions, N as CheckJobStatusResult, Q as FileUpload, R as ProcessMovesResponse, U as BranchQuery, V as FileDataQuery, W as BranchDataResult, X as PublishFileEntry, Y as DownloadFileOptions, Z as PublishFilesResult, _t as CheckFileTranslationsOptions, at as CreateTagResult, ct as DownloadFileBatchRequest, et as UploadFilesResponse, ht as EnqueueFilesResult, it as CreateTagOptions, j as AwaitJobsResult, k as SubmitUserEditDiffsPayload, lt as DownloadFileBatchResult, nt as SetupProjectOptions, ot as EnqueueFilesOptions, pt as FileReferenceIds, rt as SetupProjectResult, st as DownloadFileBatchOptions, tt as SetupProjectFileReference, vt as FileQuery, yt as FileQueryResult, z as GetOrphanedFilesResult } from "./types-iO493WgK.mjs";
|
|
2
2
|
import { GTConstructorParams, GTRuntime } from "./runtime.mjs";
|
|
3
3
|
import { n as declareVar, r as decodeVars, t as derive } from "./derive-VfZjYfIU.mjs";
|
|
4
4
|
import { LocaleConfig, LocaleConfigConstructorParams, determineLocale, formatCurrency, formatCutoff, formatDateTime, formatList, formatListToParts, formatMessage, formatNum, formatRelativeTime, formatRelativeTimeFromDate, getLocaleDirection, getLocaleEmoji, getLocaleName, getLocaleProperties, getRegionProperties, isSameDialect, isSameLanguage, isSupersetLocale, isValidLocale, requiresTranslation, resolveAliasLocale, resolveCanonicalLocale, standardizeLocale } from "@generaltranslation/format";
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { s as defaultTimeout } from "./api-BOEGbEF6.mjs";
|
|
2
|
-
import { a as validateResponse, c as noSourceLocaleProvidedError, i as handleFetchError, l as noTargetLocaleProvidedError, n as apiRequest, o as fetchWithTimeout, r as generateRequestHeaders, s as gtInstanceLogger, t as GTRuntime } from "./runtime-
|
|
3
|
-
import { c as decode, l as encode, n as declareVar, r as decodeVars, t as derive, u as isSupportedFileFormatTransform } from "./derive-
|
|
2
|
+
import { a as validateResponse, c as noSourceLocaleProvidedError, i as handleFetchError, l as noTargetLocaleProvidedError, n as apiRequest, o as fetchWithTimeout, r as generateRequestHeaders, s as gtInstanceLogger, t as GTRuntime } from "./runtime-DsKdTOSO.mjs";
|
|
3
|
+
import { c as decode, l as encode, n as declareVar, r as decodeVars, t as derive, u as isSupportedFileFormatTransform } from "./derive-DDwuyrKI.mjs";
|
|
4
4
|
import { LocaleConfig, determineLocale, formatCurrency, formatCutoff, formatDateTime, formatList, formatListToParts, formatMessage, formatNum, formatRelativeTime, formatRelativeTimeFromDate, getLocaleDirection, getLocaleEmoji, getLocaleName, getLocaleProperties, getRegionProperties, isSameDialect, isSameLanguage, isSupersetLocale, isValidLocale, requiresTranslation, resolveAliasLocale, resolveCanonicalLocale, standardizeLocale } from "@generaltranslation/format";
|
|
5
5
|
//#region src/translate/setupProject.ts
|
|
6
6
|
/**
|
package/dist/internal.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_api = require("./api-B2fSa2JN.cjs");
|
|
3
|
-
const require_derive = require("./derive-
|
|
3
|
+
const require_derive = require("./derive-Cbl7M1SY.cjs");
|
|
4
4
|
const require_isVariable = require("./isVariable-E-vOsD6G.cjs");
|
|
5
|
-
let
|
|
5
|
+
let _generaltranslation_icu = require("@generaltranslation/icu");
|
|
6
6
|
let _generaltranslation_format_internal = require("@generaltranslation/format/internal");
|
|
7
7
|
//#region src/settings/plurals.ts
|
|
8
8
|
const pluralForms = [
|
|
@@ -133,99 +133,6 @@ function extractVars(icuString) {
|
|
|
133
133
|
return variables;
|
|
134
134
|
}
|
|
135
135
|
//#endregion
|
|
136
|
-
//#region src/derive/utils/printIcuAst.ts
|
|
137
|
-
/*!
|
|
138
|
-
MIT License
|
|
139
|
-
|
|
140
|
-
Copyright (c) 2023 FormatJS
|
|
141
|
-
|
|
142
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
143
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
144
|
-
in the Software without restriction, including without limitation the rights
|
|
145
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
146
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
147
|
-
furnished to do so, subject to the following conditions:
|
|
148
|
-
|
|
149
|
-
The above copyright notice and this permission notice shall be included in all
|
|
150
|
-
copies or substantial portions of the Software.
|
|
151
|
-
|
|
152
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
153
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
154
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
155
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
156
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
157
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
158
|
-
SOFTWARE.
|
|
159
|
-
*/
|
|
160
|
-
/**
|
|
161
|
-
* Local copy of FormatJS `printAST` (see the license header above). The
|
|
162
|
-
* published printer subpath is CommonJS-only, which browsers and Vite-based
|
|
163
|
-
* dev servers (e.g. TanStack Start) cannot load from our ESM build, and the
|
|
164
|
-
* package's ESM variant uses extensionless relative imports that fail Node
|
|
165
|
-
* resolution.
|
|
166
|
-
*
|
|
167
|
-
* Output must stay byte-identical to FormatJS `printAST` because condensed
|
|
168
|
-
* ICU strings feed into hashing.
|
|
169
|
-
*/
|
|
170
|
-
function printIcuAst(ast) {
|
|
171
|
-
return doPrintAst(ast, false);
|
|
172
|
-
}
|
|
173
|
-
function doPrintAst(ast, isInPlural) {
|
|
174
|
-
return ast.map((el, i) => {
|
|
175
|
-
switch (el.type) {
|
|
176
|
-
case _formatjs_icu_messageformat_parser.TYPE.literal: return printLiteralElement(el, isInPlural, i === 0, i === ast.length - 1);
|
|
177
|
-
case _formatjs_icu_messageformat_parser.TYPE.argument: return `{${el.value}}`;
|
|
178
|
-
case _formatjs_icu_messageformat_parser.TYPE.date:
|
|
179
|
-
case _formatjs_icu_messageformat_parser.TYPE.time:
|
|
180
|
-
case _formatjs_icu_messageformat_parser.TYPE.number: return printSimpleFormatElement(el);
|
|
181
|
-
case _formatjs_icu_messageformat_parser.TYPE.plural: return printPluralElement(el);
|
|
182
|
-
case _formatjs_icu_messageformat_parser.TYPE.select: return printSelectElement(el);
|
|
183
|
-
case _formatjs_icu_messageformat_parser.TYPE.pound: return "#";
|
|
184
|
-
case _formatjs_icu_messageformat_parser.TYPE.tag: return printTagElement(el);
|
|
185
|
-
}
|
|
186
|
-
}).join("");
|
|
187
|
-
}
|
|
188
|
-
function printTagElement(el) {
|
|
189
|
-
return `<${el.value}>${printIcuAst(el.children)}</${el.value}>`;
|
|
190
|
-
}
|
|
191
|
-
function printEscapedMessage(message) {
|
|
192
|
-
return message.replace(/([{}](?:[\s\S]*[{}])?)/, "'$1'");
|
|
193
|
-
}
|
|
194
|
-
function printLiteralElement({ value }, isInPlural, isFirstEl, isLastEl) {
|
|
195
|
-
let escaped = value;
|
|
196
|
-
if (!isFirstEl && escaped[0] === "'") escaped = `''${escaped.slice(1)}`;
|
|
197
|
-
if (!isLastEl && escaped[escaped.length - 1] === "'") escaped = `${escaped.slice(0, escaped.length - 1)}''`;
|
|
198
|
-
escaped = printEscapedMessage(escaped);
|
|
199
|
-
return isInPlural ? escaped.replace("#", "'#'") : escaped;
|
|
200
|
-
}
|
|
201
|
-
function printSimpleFormatElement(el) {
|
|
202
|
-
return `{${el.value}, ${_formatjs_icu_messageformat_parser.TYPE[el.type]}${el.style ? `, ${printArgumentStyle(el.style)}` : ""}}`;
|
|
203
|
-
}
|
|
204
|
-
function printNumberSkeletonToken(token) {
|
|
205
|
-
const { stem, options } = token;
|
|
206
|
-
return options.length === 0 ? stem : `${stem}${options.map((o) => `/${o}`).join("")}`;
|
|
207
|
-
}
|
|
208
|
-
function printArgumentStyle(style) {
|
|
209
|
-
if (typeof style === "string") return printEscapedMessage(style);
|
|
210
|
-
else if (style.type === _formatjs_icu_messageformat_parser.SKELETON_TYPE.dateTime) return `::${style.pattern}`;
|
|
211
|
-
else return `::${style.tokens.map(printNumberSkeletonToken).join(" ")}`;
|
|
212
|
-
}
|
|
213
|
-
function printSelectElement(el) {
|
|
214
|
-
return `{${[
|
|
215
|
-
el.value,
|
|
216
|
-
"select",
|
|
217
|
-
Object.keys(el.options).map((id) => `${id}{${doPrintAst(el.options[id].value, false)}}`).join(" ")
|
|
218
|
-
].join(",")}}`;
|
|
219
|
-
}
|
|
220
|
-
function printPluralElement(el) {
|
|
221
|
-
const type = el.pluralType === "cardinal" ? "plural" : "selectordinal";
|
|
222
|
-
return `{${[
|
|
223
|
-
el.value,
|
|
224
|
-
type,
|
|
225
|
-
[el.offset ? `offset:${el.offset}` : "", ...Object.keys(el.options).map((id) => `${id}{${doPrintAst(el.options[id].value, true)}}`)].filter(Boolean).join(" ")
|
|
226
|
-
].join(",")}}`;
|
|
227
|
-
}
|
|
228
|
-
//#endregion
|
|
229
136
|
//#region src/derive/condenseVars.ts
|
|
230
137
|
const CONTAINS_INDEXED_GT_REGEX = new RegExp(`${require_derive.VAR_IDENTIFIER}\\d+`);
|
|
231
138
|
/**
|
|
@@ -239,10 +146,10 @@ const CONTAINS_INDEXED_GT_REGEX = new RegExp(`${require_derive.VAR_IDENTIFIER}\\
|
|
|
239
146
|
function condenseVars(icuString) {
|
|
240
147
|
if (!CONTAINS_INDEXED_GT_REGEX.test(icuString)) return icuString;
|
|
241
148
|
function visitor(child) {
|
|
242
|
-
child.type =
|
|
149
|
+
child.type = _generaltranslation_icu.TYPE.argument;
|
|
243
150
|
Reflect.deleteProperty(child, "options");
|
|
244
151
|
}
|
|
245
|
-
return
|
|
152
|
+
return (0, _generaltranslation_icu.printAST)(require_derive.traverseIcu({
|
|
246
153
|
icuString,
|
|
247
154
|
shouldVisit: require_derive.isGTIndexedSelectElement,
|
|
248
155
|
visitor,
|
package/dist/internal.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.cjs","names":["isGTUnindexedSelectElement","VAR_IDENTIFIER","isGTUnindexedSelectElement","TYPE","SKELETON_TYPE","VAR_IDENTIFIER","TYPE","traverseIcu","isGTIndexedSelectElement"],"sources":["../src/settings/plurals.ts","../src/locales/getPluralForm.ts","../src/utils/minify.ts","../src/derive/indexVars.ts","../src/derive/extractVars.ts","../src/derive/utils/printIcuAst.ts","../src/derive/condenseVars.ts"],"sourcesContent":["export const pluralForms = [\n 'singular',\n 'plural',\n 'dual',\n 'zero',\n 'one',\n 'two',\n 'few',\n 'many',\n 'other',\n] as const;\nexport type PluralType = (typeof pluralForms)[number];\nexport function isAcceptedPluralForm(form: string): form is PluralType {\n return pluralForms.includes(form as (typeof pluralForms)[number]);\n}\n","import { getCachedPluralRules } from '@generaltranslation/format/internal';\n\nimport { pluralForms, PluralType } from '../settings/plurals';\nimport { libraryDefaultLocale } from '../settings/settings';\n\n/**\n * Given a number and a list of allowed plural forms, return the plural form that best fits the number.\n *\n * @param {number} n - The number to determine the plural form for.\n * @param {PluralType[]} forms - The allowed plural forms.\n * @returns {PluralType} The determined plural form, or an empty string if none fit.\n */\nexport function _getPluralForm(\n n: number,\n forms: readonly PluralType[] = pluralForms,\n locales: string[] = [libraryDefaultLocale]\n): PluralType | '' {\n const pluralRules = getCachedPluralRules(locales);\n const provisionalBranchName = pluralRules.select(n);\n // aliases\n const absN = Math.abs(n);\n // 0\n if (absN === 0 && forms.includes('zero')) return 'zero'; // override\n // 1\n if (absN === 1) {\n if (forms.includes('singular')) return 'singular'; // override\n if (forms.includes('one')) return 'one'; // override\n }\n if (provisionalBranchName === 'one' && forms.includes('singular'))\n return 'singular';\n // 2\n if (absN === 2) {\n if (forms.includes('dual')) return 'dual'; // override\n if (forms.includes('two')) return 'two'; // override\n }\n if (provisionalBranchName === 'two' && forms.includes('dual')) return 'dual';\n // fallbacks\n if (forms.includes(provisionalBranchName)) return provisionalBranchName;\n // two\n if (provisionalBranchName === 'two' && forms.includes('dual')) return 'dual';\n if (provisionalBranchName === 'two' && forms.includes('plural'))\n return 'plural';\n if (provisionalBranchName === 'two' && forms.includes('other'))\n return 'other';\n // few\n if (provisionalBranchName === 'few' && forms.includes('plural'))\n return 'plural';\n if (provisionalBranchName === 'few' && forms.includes('other'))\n return 'other';\n // many\n if (provisionalBranchName === 'many' && forms.includes('plural'))\n return 'plural';\n if (provisionalBranchName === 'many' && forms.includes('other'))\n return 'other';\n // other\n if (provisionalBranchName === 'other' && forms.includes('plural'))\n return 'plural';\n return '';\n}\n","import { VariableTransformationSuffix, VariableType } from '../types';\n\nconst VARIABLE_TRANSFORMATION_SUFFIXES_TO_MINIFIED_NAMES = {\n variable: 'v',\n number: 'n',\n datetime: 'd',\n currency: 'c',\n 'relative-time': 'rt',\n} as const;\n\nexport function minifyVariableType(\n variableType: VariableTransformationSuffix\n): VariableType {\n return VARIABLE_TRANSFORMATION_SUFFIXES_TO_MINIFIED_NAMES[variableType];\n}\n","import { VAR_IDENTIFIER } from './utils/constants';\nimport { traverseIcu } from './utils/traverseIcu';\nimport { GTUnindexedSelectElement } from './utils/types';\nimport { isGTUnindexedSelectElement } from './utils/traverseHelpers';\nimport type { IcuMessage } from '@generaltranslation/format/types';\n\ntype Location = {\n start: number;\n end: number;\n otherStart: number;\n otherEnd: number;\n};\n\n/**\n * Given an ICU string adds identifiers to each _gt_ placeholder\n * indexVars('Hello {_gt_} {_gt_} World') => 'Hello {_gt_1_} {_gt_2_} World'\n */\nexport function indexVars(icuString: IcuMessage): 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 otherStart: child.options.other.location?.start.offset ?? 0,\n otherEnd: child.options.other.location?.end.offset ?? 0,\n });\n }\n\n // Find all variable identifiers.\n traverseIcu({\n icuString,\n shouldVisit: isGTUnindexedSelectElement,\n visitor,\n options: { recurseIntoVisited: false, captureLocation: true },\n });\n\n // Index each variable and collapse the other option.\n const result = [];\n let current = 0;\n for (let i = 0; i < variableLocations.length; i++) {\n const { start, end, otherStart, otherEnd } = variableLocations[i];\n // Before the variable\n result.push(icuString.slice(current, start));\n // Replace the variable with the new identifier (+1 is for the curly brace)\n result.push(icuString.slice(start, start + VAR_IDENTIFIER.length + 1));\n\n // Add the new identifier.\n result.push(String(i + 1));\n // After the variable\n result.push(icuString.slice(start + VAR_IDENTIFIER.length + 1, otherStart));\n // Before the other option\n result.push('{}');\n // The other option\n result.push(icuString.slice(otherEnd, end));\n current = end;\n }\n result.push(icuString.slice(current, icuString.length));\n\n return result.join('');\n}\n","import { VAR_IDENTIFIER } from './utils/constants';\nimport { isGTUnindexedSelectElement } from './utils/traverseHelpers';\nimport { traverseIcu } from './utils/traverseIcu';\nimport { GTUnindexedSelectElement } from './utils/types';\n/**\n * Given an unindexed ICU string, extracts all the _gt_ variables and an indexed mapping of the variable to the values\n *\n * extractVars('Hello {_gt_, select, other {World}}') => { _gt_1: 'World' }\n *\n * @param {string} icuString - The ICU string to extract variables from.\n * @returns {Record<string, string>} A mapping of the variable to the value.\n */\nexport function extractVars(icuString: string): Record<string, string> {\n // Check if the string contains _gt_\n if (!icuString.includes(VAR_IDENTIFIER)) {\n return {};\n }\n\n // Extract all the _gt_# variables\n let index = 1;\n const variables: Record<string, string> = {};\n function visitor(child: GTUnindexedSelectElement): void {\n variables[child.value + index] = child.options.other.value.length\n ? child.options.other.value[0]?.value\n : '';\n index += 1;\n }\n\n traverseIcu({\n icuString,\n shouldVisit: isGTUnindexedSelectElement,\n visitor,\n options: { recurseIntoVisited: false },\n });\n\n return variables;\n}\n","// The code in this file is adapted from the FormatJS printer,\n// https://github.com/formatjs/formatjs/blob/main/packages/icu-messageformat-parser/printer.ts\n// (published as `@formatjs/icu-messageformat-parser/printer.js`)\n// And is therefore MIT licensed\n\n/*!\nMIT License\n\nCopyright (c) 2023 FormatJS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\nimport { SKELETON_TYPE, TYPE } from '@formatjs/icu-messageformat-parser';\nimport type {\n DateElement,\n LiteralElement,\n MessageFormatElement,\n NumberElement,\n NumberSkeleton,\n PluralElement,\n SelectElement,\n TagElement,\n TimeElement,\n} from '@formatjs/icu-messageformat-parser';\n\ntype SimpleFormatStyle = NonNullable<\n (DateElement | TimeElement | NumberElement)['style']\n>;\n\n/**\n * Local copy of FormatJS `printAST` (see the license header above). The\n * published printer subpath is CommonJS-only, which browsers and Vite-based\n * dev servers (e.g. TanStack Start) cannot load from our ESM build, and the\n * package's ESM variant uses extensionless relative imports that fail Node\n * resolution.\n *\n * Output must stay byte-identical to FormatJS `printAST` because condensed\n * ICU strings feed into hashing.\n */\nexport function printIcuAst(ast: MessageFormatElement[]): string {\n return doPrintAst(ast, false);\n}\n\nfunction doPrintAst(ast: MessageFormatElement[], isInPlural: boolean): string {\n const printedNodes = ast.map((el, i) => {\n switch (el.type) {\n case TYPE.literal:\n return printLiteralElement(\n el,\n isInPlural,\n i === 0,\n i === ast.length - 1\n );\n case TYPE.argument:\n return `{${el.value}}`;\n case TYPE.date:\n case TYPE.time:\n case TYPE.number:\n return printSimpleFormatElement(el);\n case TYPE.plural:\n return printPluralElement(el);\n case TYPE.select:\n return printSelectElement(el);\n case TYPE.pound:\n return '#';\n case TYPE.tag:\n return printTagElement(el);\n }\n });\n return printedNodes.join('');\n}\n\nfunction printTagElement(el: TagElement): string {\n return `<${el.value}>${printIcuAst(el.children)}</${el.value}>`;\n}\n\nfunction printEscapedMessage(message: string): string {\n return message.replace(/([{}](?:[\\s\\S]*[{}])?)/, \"'$1'\");\n}\n\nfunction printLiteralElement(\n { value }: LiteralElement,\n isInPlural: boolean,\n isFirstEl: boolean,\n isLastEl: boolean\n): string {\n let escaped = value;\n // If this literal starts with a ' and it's not the 1st node, the node\n // before it is non-literal and the `'` needs to be re-escaped\n if (!isFirstEl && escaped[0] === \"'\") {\n escaped = `''${escaped.slice(1)}`;\n }\n // Same logic but for last el\n if (!isLastEl && escaped[escaped.length - 1] === \"'\") {\n escaped = `${escaped.slice(0, escaped.length - 1)}''`;\n }\n escaped = printEscapedMessage(escaped);\n // Upstream escapes only the first `#` (String#replace with a string\n // pattern); keep the quirk so output stays byte-identical\n return isInPlural ? escaped.replace('#', \"'#'\") : escaped;\n}\n\nfunction printSimpleFormatElement(\n el: DateElement | TimeElement | NumberElement\n): string {\n return `{${el.value}, ${TYPE[el.type]}${\n el.style ? `, ${printArgumentStyle(el.style)}` : ''\n }}`;\n}\n\nfunction printNumberSkeletonToken(\n token: NumberSkeleton['tokens'][number]\n): string {\n const { stem, options } = token;\n return options.length === 0\n ? stem\n : `${stem}${options.map((o) => `/${o}`).join('')}`;\n}\n\nfunction printArgumentStyle(style: SimpleFormatStyle): string {\n if (typeof style === 'string') {\n return printEscapedMessage(style);\n } else if (style.type === SKELETON_TYPE.dateTime) {\n return `::${style.pattern}`;\n } else {\n return `::${style.tokens.map(printNumberSkeletonToken).join(' ')}`;\n }\n}\n\nfunction printSelectElement(el: SelectElement): string {\n const msg = [\n el.value,\n 'select',\n Object.keys(el.options)\n .map((id) => `${id}{${doPrintAst(el.options[id].value, false)}}`)\n .join(' '),\n ].join(',');\n return `{${msg}}`;\n}\n\nfunction printPluralElement(el: PluralElement): string {\n const type = el.pluralType === 'cardinal' ? 'plural' : 'selectordinal';\n const msg = [\n el.value,\n type,\n [\n el.offset ? `offset:${el.offset}` : '',\n ...Object.keys(el.options).map(\n (id) => `${id}{${doPrintAst(el.options[id].value, true)}}`\n ),\n ]\n .filter(Boolean)\n .join(' '),\n ].join(',');\n return `{${msg}}`;\n}\n","import { TYPE } from '@formatjs/icu-messageformat-parser';\nimport type { ArgumentElement } from '@formatjs/icu-messageformat-parser/types.js';\nimport { printIcuAst } from './utils/printIcuAst';\nimport { traverseIcu } from './utils/traverseIcu';\nimport { VAR_IDENTIFIER } from './utils/constants';\nimport { GTIndexedSelectElement } from './utils/types';\nimport { isGTIndexedSelectElement } from './utils/traverseHelpers';\ninterface GTIndexedArgumentElement extends ArgumentElement {\n value: `${typeof VAR_IDENTIFIER}${number}`;\n}\n\nconst CONTAINS_INDEXED_GT_REGEX = new RegExp(`${VAR_IDENTIFIER}\\\\d+`);\n\n/**\n * Given an indexed ICU string, condenses any select to an argument\n * Unindexed _gt_ source strings and indexed _gt_# translation strings\n * are mutually exclusive.\n * indexVars('Hello {_gt_1, select, other {World}}') => 'Hello {_gt_1}'\n * @param {string} icuString - The ICU string to condense.\n * @returns {string} The condensed ICU string.\n */\nexport function condenseVars(icuString: string): string {\n // Check if the string contains an indexed _gt_ identifier.\n if (!CONTAINS_INDEXED_GT_REGEX.test(icuString)) {\n return icuString;\n }\n\n // Replace with argument\n function visitor(child: GTIndexedSelectElement): void {\n (child as unknown as GTIndexedArgumentElement).type = TYPE.argument;\n Reflect.deleteProperty(child, 'options');\n }\n\n const ast = traverseIcu({\n icuString,\n shouldVisit: isGTIndexedSelectElement,\n visitor,\n options: { recurseIntoVisited: false },\n });\n\n // Serialize\n return printIcuAst(ast);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"internal.cjs","names":["isGTUnindexedSelectElement","VAR_IDENTIFIER","isGTUnindexedSelectElement","VAR_IDENTIFIER","TYPE","traverseIcu","isGTIndexedSelectElement"],"sources":["../src/settings/plurals.ts","../src/locales/getPluralForm.ts","../src/utils/minify.ts","../src/derive/indexVars.ts","../src/derive/extractVars.ts","../src/derive/condenseVars.ts"],"sourcesContent":["export const pluralForms = [\n 'singular',\n 'plural',\n 'dual',\n 'zero',\n 'one',\n 'two',\n 'few',\n 'many',\n 'other',\n] as const;\nexport type PluralType = (typeof pluralForms)[number];\nexport function isAcceptedPluralForm(form: string): form is PluralType {\n return pluralForms.includes(form as (typeof pluralForms)[number]);\n}\n","import { getCachedPluralRules } from '@generaltranslation/format/internal';\n\nimport { pluralForms, PluralType } from '../settings/plurals';\nimport { libraryDefaultLocale } from '../settings/settings';\n\n/**\n * Given a number and a list of allowed plural forms, return the plural form that best fits the number.\n *\n * @param {number} n - The number to determine the plural form for.\n * @param {PluralType[]} forms - The allowed plural forms.\n * @returns {PluralType} The determined plural form, or an empty string if none fit.\n */\nexport function _getPluralForm(\n n: number,\n forms: readonly PluralType[] = pluralForms,\n locales: string[] = [libraryDefaultLocale]\n): PluralType | '' {\n const pluralRules = getCachedPluralRules(locales);\n const provisionalBranchName = pluralRules.select(n);\n // aliases\n const absN = Math.abs(n);\n // 0\n if (absN === 0 && forms.includes('zero')) return 'zero'; // override\n // 1\n if (absN === 1) {\n if (forms.includes('singular')) return 'singular'; // override\n if (forms.includes('one')) return 'one'; // override\n }\n if (provisionalBranchName === 'one' && forms.includes('singular'))\n return 'singular';\n // 2\n if (absN === 2) {\n if (forms.includes('dual')) return 'dual'; // override\n if (forms.includes('two')) return 'two'; // override\n }\n if (provisionalBranchName === 'two' && forms.includes('dual')) return 'dual';\n // fallbacks\n if (forms.includes(provisionalBranchName)) return provisionalBranchName;\n // two\n if (provisionalBranchName === 'two' && forms.includes('dual')) return 'dual';\n if (provisionalBranchName === 'two' && forms.includes('plural'))\n return 'plural';\n if (provisionalBranchName === 'two' && forms.includes('other'))\n return 'other';\n // few\n if (provisionalBranchName === 'few' && forms.includes('plural'))\n return 'plural';\n if (provisionalBranchName === 'few' && forms.includes('other'))\n return 'other';\n // many\n if (provisionalBranchName === 'many' && forms.includes('plural'))\n return 'plural';\n if (provisionalBranchName === 'many' && forms.includes('other'))\n return 'other';\n // other\n if (provisionalBranchName === 'other' && forms.includes('plural'))\n return 'plural';\n return '';\n}\n","import { VariableTransformationSuffix, VariableType } from '../types';\n\nconst VARIABLE_TRANSFORMATION_SUFFIXES_TO_MINIFIED_NAMES = {\n variable: 'v',\n number: 'n',\n datetime: 'd',\n currency: 'c',\n 'relative-time': 'rt',\n} as const;\n\nexport function minifyVariableType(\n variableType: VariableTransformationSuffix\n): VariableType {\n return VARIABLE_TRANSFORMATION_SUFFIXES_TO_MINIFIED_NAMES[variableType];\n}\n","import { VAR_IDENTIFIER } from './utils/constants';\nimport { traverseIcu } from './utils/traverseIcu';\nimport { GTUnindexedSelectElement } from './utils/types';\nimport { isGTUnindexedSelectElement } from './utils/traverseHelpers';\nimport type { IcuMessage } from '@generaltranslation/format/types';\n\ntype Location = {\n start: number;\n end: number;\n otherStart: number;\n otherEnd: number;\n};\n\n/**\n * Given an ICU string adds identifiers to each _gt_ placeholder\n * indexVars('Hello {_gt_} {_gt_} World') => 'Hello {_gt_1_} {_gt_2_} World'\n */\nexport function indexVars(icuString: IcuMessage): 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 otherStart: child.options.other.location?.start.offset ?? 0,\n otherEnd: child.options.other.location?.end.offset ?? 0,\n });\n }\n\n // Find all variable identifiers.\n traverseIcu({\n icuString,\n shouldVisit: isGTUnindexedSelectElement,\n visitor,\n options: { recurseIntoVisited: false, captureLocation: true },\n });\n\n // Index each variable and collapse the other option.\n const result = [];\n let current = 0;\n for (let i = 0; i < variableLocations.length; i++) {\n const { start, end, otherStart, otherEnd } = variableLocations[i];\n // Before the variable\n result.push(icuString.slice(current, start));\n // Replace the variable with the new identifier (+1 is for the curly brace)\n result.push(icuString.slice(start, start + VAR_IDENTIFIER.length + 1));\n\n // Add the new identifier.\n result.push(String(i + 1));\n // After the variable\n result.push(icuString.slice(start + VAR_IDENTIFIER.length + 1, otherStart));\n // Before the other option\n result.push('{}');\n // The other option\n result.push(icuString.slice(otherEnd, end));\n current = end;\n }\n result.push(icuString.slice(current, icuString.length));\n\n return result.join('');\n}\n","import { VAR_IDENTIFIER } from './utils/constants';\nimport { isGTUnindexedSelectElement } from './utils/traverseHelpers';\nimport { traverseIcu } from './utils/traverseIcu';\nimport { GTUnindexedSelectElement } from './utils/types';\n/**\n * Given an unindexed ICU string, extracts all the _gt_ variables and an indexed mapping of the variable to the values\n *\n * extractVars('Hello {_gt_, select, other {World}}') => { _gt_1: 'World' }\n *\n * @param {string} icuString - The ICU string to extract variables from.\n * @returns {Record<string, string>} A mapping of the variable to the value.\n */\nexport function extractVars(icuString: string): Record<string, string> {\n // Check if the string contains _gt_\n if (!icuString.includes(VAR_IDENTIFIER)) {\n return {};\n }\n\n // Extract all the _gt_# variables\n let index = 1;\n const variables: Record<string, string> = {};\n function visitor(child: GTUnindexedSelectElement): void {\n variables[child.value + index] = child.options.other.value.length\n ? child.options.other.value[0]?.value\n : '';\n index += 1;\n }\n\n traverseIcu({\n icuString,\n shouldVisit: isGTUnindexedSelectElement,\n visitor,\n options: { recurseIntoVisited: false },\n });\n\n return variables;\n}\n","import { printAST, TYPE, type ArgumentElement } from '@generaltranslation/icu';\nimport { traverseIcu } from './utils/traverseIcu';\nimport { VAR_IDENTIFIER } from './utils/constants';\nimport { GTIndexedSelectElement } from './utils/types';\nimport { isGTIndexedSelectElement } from './utils/traverseHelpers';\ninterface GTIndexedArgumentElement extends ArgumentElement {\n value: `${typeof VAR_IDENTIFIER}${number}`;\n}\n\nconst CONTAINS_INDEXED_GT_REGEX = new RegExp(`${VAR_IDENTIFIER}\\\\d+`);\n\n/**\n * Given an indexed ICU string, condenses any select to an argument\n * Unindexed _gt_ source strings and indexed _gt_# translation strings\n * are mutually exclusive.\n * indexVars('Hello {_gt_1, select, other {World}}') => 'Hello {_gt_1}'\n * @param {string} icuString - The ICU string to condense.\n * @returns {string} The condensed ICU string.\n */\nexport function condenseVars(icuString: string): string {\n // Check if the string contains an indexed _gt_ identifier.\n if (!CONTAINS_INDEXED_GT_REGEX.test(icuString)) {\n return icuString;\n }\n\n // Replace with argument\n function visitor(child: GTIndexedSelectElement): void {\n (child as unknown as GTIndexedArgumentElement).type = TYPE.argument;\n Reflect.deleteProperty(child, 'options');\n }\n\n const ast = traverseIcu({\n icuString,\n shouldVisit: isGTIndexedSelectElement,\n visitor,\n options: { recurseIntoVisited: false },\n });\n\n // Serialize\n return printAST(ast);\n}\n"],"mappings":"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"}
|
package/dist/internal.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as RuntimeTranslateManyOptions, C as VariableType, D as VariableTransformationSuffix, S as Variable, dt as FileFormat, g as LocaleProperties, h as JsxElement, m as JsxChildren, p as JsxChild } from "./types-
|
|
1
|
+
import { At as RuntimeTranslateManyOptions, C as VariableType, D as VariableTransformationSuffix, S as Variable, dt as FileFormat, g as LocaleProperties, h as JsxElement, m as JsxChildren, p as JsxChild } from "./types-wj-Dtih8.cjs";
|
|
2
2
|
import { n as declareVar, r as decodeVars, t as derive } from "./derive-DBCCXTmL.cjs";
|
|
3
3
|
import { IcuMessage } from "@generaltranslation/format/types";
|
|
4
4
|
|
package/dist/internal.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as RuntimeTranslateManyOptions, C as VariableType, D as VariableTransformationSuffix, S as Variable, dt as FileFormat, g as LocaleProperties, h as JsxElement, m as JsxChildren, p as JsxChild } from "./types-
|
|
1
|
+
import { At as RuntimeTranslateManyOptions, C as VariableType, D as VariableTransformationSuffix, S as Variable, dt as FileFormat, g as LocaleProperties, h as JsxElement, m as JsxChildren, p as JsxChild } from "./types-iO493WgK.mjs";
|
|
2
2
|
import { n as declareVar, r as decodeVars, t as derive } from "./derive-VfZjYfIU.mjs";
|
|
3
3
|
import { IcuMessage } from "@generaltranslation/format/types";
|
|
4
4
|
|
package/dist/internal.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as createDiagnosticMessage, c as libraryDefaultLocale, i as defaultRuntimeApiUrl, n as defaultBaseUrl, o as formatDiagnosticErrorDetails, r as defaultCacheUrl, t as API_VERSION } from "./api-BOEGbEF6.mjs";
|
|
2
|
-
import { a as isGTUnindexedSelectElement, c as decode, i as isGTIndexedSelectElement, l as encode, n as declareVar, o as VAR_IDENTIFIER, r as decodeVars, s as traverseIcu, t as derive, u as isSupportedFileFormatTransform } from "./derive-
|
|
2
|
+
import { a as isGTUnindexedSelectElement, c as decode, i as isGTIndexedSelectElement, l as encode, n as declareVar, o as VAR_IDENTIFIER, r as decodeVars, s as traverseIcu, t as derive, u as isSupportedFileFormatTransform } from "./derive-DDwuyrKI.mjs";
|
|
3
3
|
import { t as isVariable } from "./isVariable-CSPdMlAF.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { TYPE, printAST } from "@generaltranslation/icu";
|
|
5
5
|
import { getCachedPluralRules } from "@generaltranslation/format/internal";
|
|
6
6
|
//#region src/settings/plurals.ts
|
|
7
7
|
const pluralForms = [
|
|
@@ -132,99 +132,6 @@ function extractVars(icuString) {
|
|
|
132
132
|
return variables;
|
|
133
133
|
}
|
|
134
134
|
//#endregion
|
|
135
|
-
//#region src/derive/utils/printIcuAst.ts
|
|
136
|
-
/*!
|
|
137
|
-
MIT License
|
|
138
|
-
|
|
139
|
-
Copyright (c) 2023 FormatJS
|
|
140
|
-
|
|
141
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
142
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
143
|
-
in the Software without restriction, including without limitation the rights
|
|
144
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
145
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
146
|
-
furnished to do so, subject to the following conditions:
|
|
147
|
-
|
|
148
|
-
The above copyright notice and this permission notice shall be included in all
|
|
149
|
-
copies or substantial portions of the Software.
|
|
150
|
-
|
|
151
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
152
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
153
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
154
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
155
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
156
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
157
|
-
SOFTWARE.
|
|
158
|
-
*/
|
|
159
|
-
/**
|
|
160
|
-
* Local copy of FormatJS `printAST` (see the license header above). The
|
|
161
|
-
* published printer subpath is CommonJS-only, which browsers and Vite-based
|
|
162
|
-
* dev servers (e.g. TanStack Start) cannot load from our ESM build, and the
|
|
163
|
-
* package's ESM variant uses extensionless relative imports that fail Node
|
|
164
|
-
* resolution.
|
|
165
|
-
*
|
|
166
|
-
* Output must stay byte-identical to FormatJS `printAST` because condensed
|
|
167
|
-
* ICU strings feed into hashing.
|
|
168
|
-
*/
|
|
169
|
-
function printIcuAst(ast) {
|
|
170
|
-
return doPrintAst(ast, false);
|
|
171
|
-
}
|
|
172
|
-
function doPrintAst(ast, isInPlural) {
|
|
173
|
-
return ast.map((el, i) => {
|
|
174
|
-
switch (el.type) {
|
|
175
|
-
case TYPE.literal: return printLiteralElement(el, isInPlural, i === 0, i === ast.length - 1);
|
|
176
|
-
case TYPE.argument: return `{${el.value}}`;
|
|
177
|
-
case TYPE.date:
|
|
178
|
-
case TYPE.time:
|
|
179
|
-
case TYPE.number: return printSimpleFormatElement(el);
|
|
180
|
-
case TYPE.plural: return printPluralElement(el);
|
|
181
|
-
case TYPE.select: return printSelectElement(el);
|
|
182
|
-
case TYPE.pound: return "#";
|
|
183
|
-
case TYPE.tag: return printTagElement(el);
|
|
184
|
-
}
|
|
185
|
-
}).join("");
|
|
186
|
-
}
|
|
187
|
-
function printTagElement(el) {
|
|
188
|
-
return `<${el.value}>${printIcuAst(el.children)}</${el.value}>`;
|
|
189
|
-
}
|
|
190
|
-
function printEscapedMessage(message) {
|
|
191
|
-
return message.replace(/([{}](?:[\s\S]*[{}])?)/, "'$1'");
|
|
192
|
-
}
|
|
193
|
-
function printLiteralElement({ value }, isInPlural, isFirstEl, isLastEl) {
|
|
194
|
-
let escaped = value;
|
|
195
|
-
if (!isFirstEl && escaped[0] === "'") escaped = `''${escaped.slice(1)}`;
|
|
196
|
-
if (!isLastEl && escaped[escaped.length - 1] === "'") escaped = `${escaped.slice(0, escaped.length - 1)}''`;
|
|
197
|
-
escaped = printEscapedMessage(escaped);
|
|
198
|
-
return isInPlural ? escaped.replace("#", "'#'") : escaped;
|
|
199
|
-
}
|
|
200
|
-
function printSimpleFormatElement(el) {
|
|
201
|
-
return `{${el.value}, ${TYPE[el.type]}${el.style ? `, ${printArgumentStyle(el.style)}` : ""}}`;
|
|
202
|
-
}
|
|
203
|
-
function printNumberSkeletonToken(token) {
|
|
204
|
-
const { stem, options } = token;
|
|
205
|
-
return options.length === 0 ? stem : `${stem}${options.map((o) => `/${o}`).join("")}`;
|
|
206
|
-
}
|
|
207
|
-
function printArgumentStyle(style) {
|
|
208
|
-
if (typeof style === "string") return printEscapedMessage(style);
|
|
209
|
-
else if (style.type === SKELETON_TYPE.dateTime) return `::${style.pattern}`;
|
|
210
|
-
else return `::${style.tokens.map(printNumberSkeletonToken).join(" ")}`;
|
|
211
|
-
}
|
|
212
|
-
function printSelectElement(el) {
|
|
213
|
-
return `{${[
|
|
214
|
-
el.value,
|
|
215
|
-
"select",
|
|
216
|
-
Object.keys(el.options).map((id) => `${id}{${doPrintAst(el.options[id].value, false)}}`).join(" ")
|
|
217
|
-
].join(",")}}`;
|
|
218
|
-
}
|
|
219
|
-
function printPluralElement(el) {
|
|
220
|
-
const type = el.pluralType === "cardinal" ? "plural" : "selectordinal";
|
|
221
|
-
return `{${[
|
|
222
|
-
el.value,
|
|
223
|
-
type,
|
|
224
|
-
[el.offset ? `offset:${el.offset}` : "", ...Object.keys(el.options).map((id) => `${id}{${doPrintAst(el.options[id].value, true)}}`)].filter(Boolean).join(" ")
|
|
225
|
-
].join(",")}}`;
|
|
226
|
-
}
|
|
227
|
-
//#endregion
|
|
228
135
|
//#region src/derive/condenseVars.ts
|
|
229
136
|
const CONTAINS_INDEXED_GT_REGEX = new RegExp(`${VAR_IDENTIFIER}\\d+`);
|
|
230
137
|
/**
|
|
@@ -241,7 +148,7 @@ function condenseVars(icuString) {
|
|
|
241
148
|
child.type = TYPE.argument;
|
|
242
149
|
Reflect.deleteProperty(child, "options");
|
|
243
150
|
}
|
|
244
|
-
return
|
|
151
|
+
return printAST(traverseIcu({
|
|
245
152
|
icuString,
|
|
246
153
|
shouldVisit: isGTIndexedSelectElement,
|
|
247
154
|
visitor,
|