gt 2.11.0 → 2.11.1

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1129](https://github.com/generaltranslation/gt/pull/1129) [`aabe764`](https://github.com/generaltranslation/gt/commit/aabe76422bfbba80ed3453667f82f01b1a195281) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - feat: derivation support for the t macro
8
+
9
+ - Updated dependencies [[`aabe764`](https://github.com/generaltranslation/gt/commit/aabe76422bfbba80ed3453667f82f01b1a195281), [`84c1443`](https://github.com/generaltranslation/gt/commit/84c1443bda85ccbd8d8dbf56ede341de974db522)]:
10
+ - @generaltranslation/python-extractor@0.1.5
11
+ - generaltranslation@8.1.19
12
+
3
13
  ## 2.11.0
4
14
 
5
15
  ### Minor Changes
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "2.11.0";
1
+ export declare const PACKAGE_VERSION = "2.11.1";
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated. Do not edit manually.
2
- export const PACKAGE_VERSION = '2.11.0';
2
+ export const PACKAGE_VERSION = '2.11.1';
@@ -20,6 +20,7 @@ export declare const DERIVE_COMPONENT = "Derive";
20
20
  export declare const BRANCH_COMPONENT = "Branch";
21
21
  export declare const GT_TRANSLATION_FUNCS: string[];
22
22
  export declare const STRING_REGISTRATION_FUNCS: readonly ["msg", "t"];
23
+ export declare const GT_DERIVE_STRING_FUNCTIONS: string[];
23
24
  export declare const VARIABLE_COMPONENTS: string[];
24
25
  export declare const GT_ATTRIBUTES_WITH_SUGAR: readonly ["$id", "$context", "$maxChars"];
25
26
  export declare const GT_ATTRIBUTES: readonly ["id", "context", "maxChars", "$id", "$context", "$maxChars"];
@@ -44,6 +44,11 @@ export const STRING_REGISTRATION_FUNCS = [
44
44
  MSG_REGISTRATION_FUNCTION,
45
45
  T_REGISTRATION_FUNCTION,
46
46
  ];
47
+ // Derive functions that are imported from GT
48
+ export const GT_DERIVE_STRING_FUNCTIONS = [
49
+ DECLARE_STATIC_FUNCTION,
50
+ DERIVE_FUNCTION,
51
+ ];
47
52
  // Valid variable components
48
53
  export const VARIABLE_COMPONENTS = [
49
54
  'Var',
@@ -0,0 +1,30 @@
1
+ import * as t from '@babel/types';
2
+ import { NodePath } from '@babel/traverse';
3
+ import { ParsingConfigOptions } from '../../../../../types/parsing.js';
4
+ import { StringNode } from '../../types.js';
5
+ export type StringTree = (string | StringTree)[];
6
+ /**
7
+ * Extracts content if an expression is derivable (statically analyzable) or uses derive()
8
+ * Returns a Node representing the parsed expression
9
+ * @param expr - The expression to check
10
+ * @param tPath - NodePath for scope resolution
11
+ * @param file - Current file path
12
+ * @param parsingOptions - Parsing configuration
13
+ * @param errors - Errors to add to
14
+ * @param runtimeInterpolationState - When provided, non-derive dynamic expressions become {n} placeholders instead of errors. Pass { index: 0 } at the entry point for template macros.
15
+ * @returns Node | null - The parsed node, or null if invalid
16
+ *
17
+ * @note runtimeInterpolationState
18
+ * - Only provide at entry for template macros, otherwise omit
19
+ * - t`Hello {nonDerivableValue}` -> t`Hello {0}`
20
+ */
21
+ export declare function handleDerivation({ expr, tPath, file, parsingOptions, errors, runtimeInterpolationState, }: {
22
+ expr: t.Expression;
23
+ tPath: NodePath;
24
+ file: string;
25
+ parsingOptions: ParsingConfigOptions;
26
+ errors: string[];
27
+ runtimeInterpolationState?: {
28
+ index: number;
29
+ };
30
+ }): StringNode | null;
@@ -1,13 +1,13 @@
1
1
  import * as t from '@babel/types';
2
- import { parseStringExpression, nodeToStrings } from './parseString.js';
3
- import { buildImportMap } from './buildImportMap.js';
4
- import { resolveImportPath } from './resolveImportPath.js';
2
+ import { parseStringExpression, nodeToStrings } from '../../parseString.js';
3
+ import { buildImportMap } from '../../buildImportMap.js';
4
+ import { resolveImportPath } from '../../resolveImportPath.js';
5
5
  import { parse } from '@babel/parser';
6
6
  import fs from 'node:fs';
7
- import { warnFunctionNotFoundSync, warnDeriveFunctionNoResultsSync, warnDeriveFunctionNotWrappedSync, } from '../../../console/index.js';
8
- import { DECLARE_STATIC_FUNCTION, DERIVE_FUNCTION } from './constants.js';
7
+ import { warnFunctionNotFoundSync, warnDeriveFunctionNoResultsSync, warnDeriveFunctionNotWrappedSync, } from '../../../../../console/index.js';
9
8
  import traverseModule from '@babel/traverse';
10
9
  import generateModule from '@babel/generator';
10
+ import { isDeriveCall } from './isDeriveCall.js';
11
11
  // Handle CommonJS/ESM interop
12
12
  const traverse = traverseModule.default || traverseModule;
13
13
  const generate = generateModule.default || generateModule;
@@ -30,27 +30,49 @@ const processFunctionCache = new Map();
30
30
  * @param tPath - NodePath for scope resolution
31
31
  * @param file - Current file path
32
32
  * @param parsingOptions - Parsing configuration
33
+ * @param errors - Errors to add to
34
+ * @param runtimeInterpolationState - When provided, non-derive dynamic expressions become {n} placeholders instead of errors. Pass { index: 0 } at the entry point for template macros.
33
35
  * @returns Node | null - The parsed node, or null if invalid
36
+ *
37
+ * @note runtimeInterpolationState
38
+ * - Only provide at entry for template macros, otherwise omit
39
+ * - t`Hello {nonDerivableValue}` -> t`Hello {0}`
34
40
  */
35
- export function handleDeriveExpression(expr, tPath, file, parsingOptions, errors) {
41
+ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, runtimeInterpolationState, }) {
36
42
  if (!expr) {
37
43
  return null;
38
44
  }
39
45
  // Handle expressions
40
46
  if (t.isCallExpression(expr)) {
41
- const variants = getDeriveVariants(expr, tPath, file, parsingOptions, errors);
42
- if (variants) {
43
- // We found derive() -> return as ChoiceNode
44
- return {
45
- type: 'choice',
46
- nodes: variants.map((v) => ({ type: 'text', text: v })),
47
- };
47
+ if (isDeriveCall({ expr, tPath })) {
48
+ const variants = getDeriveVariants({
49
+ call: expr,
50
+ tPath,
51
+ file,
52
+ parsingOptions,
53
+ errors,
54
+ });
55
+ if (variants) {
56
+ return {
57
+ type: 'choice',
58
+ nodes: variants.map((v) => ({ type: 'text', text: v })),
59
+ };
60
+ }
61
+ // derive() had no resolvable results
62
+ const code = expr.arguments.length > 0
63
+ ? generate(expr.arguments[0]).code
64
+ : 'no arguments';
65
+ errors.push(warnDeriveFunctionNoResultsSync(file, code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
66
+ return null;
67
+ }
68
+ // Non-derive call
69
+ if (runtimeInterpolationState) {
70
+ return { type: 'text', text: `{${runtimeInterpolationState.index++}}` };
48
71
  }
49
- // Call has no results
50
- const code = expr.arguments.length > 0
51
- ? generate(expr.arguments[0]).code
52
- : 'no arguments';
53
- errors.push(warnDeriveFunctionNoResultsSync(file, code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
72
+ const calleeName = t.isIdentifier(expr.callee)
73
+ ? expr.callee.name
74
+ : generate(expr.callee).code;
75
+ errors.push(warnDeriveFunctionNotWrappedSync(file, calleeName, `${expr.callee.loc?.start?.line}:${expr.callee.loc?.start?.column}`));
54
76
  return null;
55
77
  }
56
78
  // Handle direct string literals
@@ -68,12 +90,33 @@ export function handleDeriveExpression(expr, tPath, file, parsingOptions, errors
68
90
  }
69
91
  const exprNode = expr.expressions[index];
70
92
  if (exprNode && t.isExpression(exprNode)) {
71
- const result = handleDeriveExpression(exprNode, tPath, file, parsingOptions, errors);
72
- if (result === null) {
73
- // Early bailout if we can't handle something inside interpolation
74
- return null;
93
+ if (isDeriveCall({ expr: exprNode, tPath })) {
94
+ // Derive — resolve fully (no runtime interpolation forwarding)
95
+ const result = handleDerivation({
96
+ expr: exprNode,
97
+ tPath,
98
+ file,
99
+ parsingOptions,
100
+ errors,
101
+ });
102
+ if (result === null)
103
+ return null;
104
+ parts.push(result);
105
+ }
106
+ else {
107
+ // Non-derive — recurse with runtime interpolation forwarded
108
+ const result = handleDerivation({
109
+ expr: exprNode,
110
+ tPath,
111
+ file,
112
+ parsingOptions,
113
+ errors,
114
+ runtimeInterpolationState,
115
+ });
116
+ if (result === null)
117
+ return null;
118
+ parts.push(result);
75
119
  }
76
- parts.push(result);
77
120
  }
78
121
  }
79
122
  if (parts.length === 0) {
@@ -89,8 +132,22 @@ export function handleDeriveExpression(expr, tPath, file, parsingOptions, errors
89
132
  if (!t.isExpression(expr.left) || !t.isExpression(expr.right)) {
90
133
  return null;
91
134
  }
92
- const leftResult = handleDeriveExpression(expr.left, tPath, file, parsingOptions, errors);
93
- const rightResult = handleDeriveExpression(expr.right, tPath, file, parsingOptions, errors);
135
+ const leftResult = handleDerivation({
136
+ expr: expr.left,
137
+ tPath,
138
+ file,
139
+ parsingOptions,
140
+ errors,
141
+ runtimeInterpolationState,
142
+ });
143
+ const rightResult = handleDerivation({
144
+ expr: expr.right,
145
+ tPath,
146
+ file,
147
+ parsingOptions,
148
+ errors,
149
+ runtimeInterpolationState,
150
+ });
94
151
  if (leftResult === null || rightResult === null) {
95
152
  return null;
96
153
  }
@@ -98,7 +155,14 @@ export function handleDeriveExpression(expr, tPath, file, parsingOptions, errors
98
155
  }
99
156
  // Handle parenthesized expressions
100
157
  if (t.isParenthesizedExpression(expr)) {
101
- return handleDeriveExpression(expr.expression, tPath, file, parsingOptions, errors);
158
+ return handleDerivation({
159
+ expr: expr.expression,
160
+ tPath,
161
+ file,
162
+ parsingOptions,
163
+ errors,
164
+ runtimeInterpolationState,
165
+ });
102
166
  }
103
167
  // Handle numeric literals by converting them to strings
104
168
  if (t.isNumericLiteral(expr)) {
@@ -135,6 +199,9 @@ export function handleDeriveExpression(expr, tPath, file, parsingOptions, errors
135
199
  return { type: 'text', text: 'null' };
136
200
  }
137
201
  // Not a derivable expression
202
+ if (runtimeInterpolationState) {
203
+ return { type: 'text', text: `{${runtimeInterpolationState.index++}}` };
204
+ }
138
205
  return null;
139
206
  }
140
207
  /**
@@ -147,37 +214,13 @@ export function handleDeriveExpression(expr, tPath, file, parsingOptions, errors
147
214
  *
148
215
  * Returns null if it can't be resolved.
149
216
  */
150
- function getDeriveVariants(call, tPath, file, parsingOptions, errors) {
217
+ function getDeriveVariants({ call, tPath, file, parsingOptions, errors, }) {
151
218
  // --- Validate Callee --- //
152
- // Must be derive(...) or an alias of it
153
- if (!t.isIdentifier(call.callee)) {
154
- const code = call.arguments.length > 0
155
- ? generate(call.arguments[0]).code
156
- : 'no arguments';
157
- errors.push(warnDeriveFunctionNotWrappedSync(file, code, `${call.callee.loc?.start?.line}:${call.callee.loc?.start?.column}`));
158
- return null;
159
- }
160
- // Check if this is derive by name or by checking the import
161
- const calleeName = call.callee.name;
162
- const calleeBinding = tPath.scope.getBinding(calleeName);
163
- // If it's not literally named 'derive', check if it's imported from GT
164
- if (!calleeBinding) {
165
- return null;
166
- }
167
- // Check if it's imported from a GT package
168
- if (calleeBinding.path.isImportSpecifier()) {
169
- const imported = calleeBinding.path.node.imported;
170
- const originalName = t.isIdentifier(imported)
171
- ? imported.name
172
- : imported.value;
173
- // Only proceed if the original name is 'derive' (or the deprecated 'declareStatic')
174
- if (originalName !== DECLARE_STATIC_FUNCTION &&
175
- originalName !== DERIVE_FUNCTION) {
176
- return null;
177
- }
178
- }
179
- else {
180
- // Not an import specifier, so it's not derive
219
+ // Must be a derive(...) call or an alias of it
220
+ if (!isDeriveCall({ expr: call, tPath })) {
221
+ const calleeName = t.isIdentifier(call.callee)
222
+ ? call.callee.name
223
+ : generate(call.callee).code;
181
224
  errors.push(warnDeriveFunctionNotWrappedSync(file, calleeName, `${call.callee.loc?.start?.line}:${call.callee.loc?.start?.column}`));
182
225
  return null;
183
226
  }
@@ -507,13 +550,3 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
507
550
  processFunctionCache.set(cacheKey, result);
508
551
  return result;
509
552
  }
510
- /**
511
- * Handle cond ? "a" : "b"
512
- * Collects string literals from both branches of a conditional expression
513
- */
514
- function collectConditionalStringVariants(cond, out) {
515
- if (t.isStringLiteral(cond.consequent))
516
- out.add(cond.consequent.value);
517
- if (t.isStringLiteral(cond.alternate))
518
- out.add(cond.alternate.value);
519
- }
@@ -0,0 +1,25 @@
1
+ import { NodePath } from '@babel/traverse';
2
+ import * as t from '@babel/types';
3
+ import { InlineMetadata } from '../processTranslationCall/extractStringEntryMetadata.js';
4
+ import { ParsingConfig } from '../types.js';
5
+ import { ParsingOutput } from '../types.js';
6
+ /**
7
+ * Registers an expression with support for derive
8
+ * Entry point for string derivation
9
+ *
10
+ * @param tPath - The path to the tag identifier
11
+ * @param expr - The expression to parse
12
+ * @param metadata - Extracted metadata (empty for tagged templates)
13
+ * @param config - Parsing configuration
14
+ * @param output - Parsing output collectors
15
+ * @param enableRuntimeInterpolation - For template macros, enables runtime interpolation for non-derive calls
16
+ */
17
+ export declare function deriveExpression({ tPath, expr, metadata, config, output, index, enableRuntimeInterpolation, }: {
18
+ tPath: NodePath;
19
+ expr: t.Expression;
20
+ metadata: InlineMetadata;
21
+ config: ParsingConfig;
22
+ output: ParsingOutput;
23
+ index?: number;
24
+ enableRuntimeInterpolation?: boolean;
25
+ }): void;
@@ -0,0 +1,63 @@
1
+ import { handleDerivation } from './handleDerivation.js';
2
+ import { warnNonStringSync } from '../../../../../console/index.js';
3
+ import { nodeToStrings } from '../../parseString.js';
4
+ import generateModule from '@babel/generator';
5
+ import { indexVars } from 'generaltranslation/internal';
6
+ import { randomUUID } from 'node:crypto';
7
+ import { isValidIcu } from '../../../evaluateJsx.js';
8
+ import { warnInvalidIcuSync } from '../../../../../console/index.js';
9
+ // Handle CommonJS/ESM interop
10
+ const generate = generateModule.default || generateModule;
11
+ /**
12
+ * Registers an expression with support for derive
13
+ * Entry point for string derivation
14
+ *
15
+ * @param tPath - The path to the tag identifier
16
+ * @param expr - The expression to parse
17
+ * @param metadata - Extracted metadata (empty for tagged templates)
18
+ * @param config - Parsing configuration
19
+ * @param output - Parsing output collectors
20
+ * @param enableRuntimeInterpolation - For template macros, enables runtime interpolation for non-derive calls
21
+ */
22
+ export function deriveExpression({ tPath, expr, metadata, config, output, index, enableRuntimeInterpolation = false, }) {
23
+ // parse derivable expression
24
+ const stringNode = handleDerivation({
25
+ expr,
26
+ tPath,
27
+ file: config.file,
28
+ parsingOptions: config.parsingOptions,
29
+ errors: output.errors,
30
+ runtimeInterpolationState: enableRuntimeInterpolation
31
+ ? { index: 0 }
32
+ : undefined,
33
+ });
34
+ // Nothing returned, push error
35
+ if (!stringNode) {
36
+ output.errors.push(warnNonStringSync(config.file, generate(expr).code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
37
+ return;
38
+ }
39
+ // validate ICU
40
+ const strings = nodeToStrings(stringNode).map(indexVars);
41
+ if (!config.ignoreInvalidIcu) {
42
+ for (const string of strings) {
43
+ const { isValid, error } = isValidIcu(string);
44
+ if (!isValid) {
45
+ output.warnings.add(warnInvalidIcuSync(config.file, string, error ?? 'Unknown error', `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
46
+ return;
47
+ }
48
+ }
49
+ }
50
+ const temporaryDeriveId = `derive-temp-id-${randomUUID()}`;
51
+ for (const string of strings) {
52
+ output.updates.push({
53
+ dataFormat: 'ICU',
54
+ source: string,
55
+ metadata: {
56
+ ...metadata,
57
+ // Add the index if an id and index is provided (for handling when registering an array of strings)
58
+ ...(metadata.id && index != null && { id: `${metadata.id}.${index}` }),
59
+ staticId: temporaryDeriveId,
60
+ },
61
+ });
62
+ }
63
+ }
@@ -0,0 +1,11 @@
1
+ import * as t from '@babel/types';
2
+ import { NodePath } from '@babel/traverse';
3
+ /**
4
+ * Given an expression, determine if it is a derive call
5
+ * @param expr - The expression to check
6
+ * @returns True if the expression is a derive call, false otherwise
7
+ */
8
+ export declare function isDeriveCall({ expr, tPath, }: {
9
+ expr: t.Expression;
10
+ tPath: NodePath;
11
+ }): boolean;
@@ -0,0 +1,38 @@
1
+ import * as t from '@babel/types';
2
+ import { GT_DERIVE_STRING_FUNCTIONS } from '../../constants.js';
3
+ import { GT_LIBRARIES } from '../../../../../types/libraries.js';
4
+ /**
5
+ * Given an expression, determine if it is a derive call
6
+ * @param expr - The expression to check
7
+ * @returns True if the expression is a derive call, false otherwise
8
+ */
9
+ export function isDeriveCall({ expr, tPath, }) {
10
+ // Check if the expression is a call expression
11
+ if (!t.isCallExpression(expr))
12
+ return false;
13
+ const callee = expr.callee;
14
+ if (!t.isIdentifier(callee))
15
+ return false;
16
+ // Fail if no binding
17
+ const calleeName = callee.name;
18
+ const binding = tPath.scope.getBinding(calleeName);
19
+ if (!binding)
20
+ return false;
21
+ // Check if the callee is imported from GT
22
+ if (!binding.path.isImportSpecifier())
23
+ return false;
24
+ const source = binding.path.parentPath?.isImportDeclaration()
25
+ ? binding.path.parentPath?.node.source.value
26
+ : undefined;
27
+ if (!GT_LIBRARIES.includes(source))
28
+ return false;
29
+ // Fail if the original name is not 'derive' (or the deprecated 'declareStatic')
30
+ const imported = binding.path.node.imported;
31
+ const originalName = t.isIdentifier(imported)
32
+ ? imported.name
33
+ : imported.value;
34
+ if (!GT_DERIVE_STRING_FUNCTIONS.includes(originalName)) {
35
+ return false;
36
+ }
37
+ return true;
38
+ }
@@ -1,6 +1,7 @@
1
1
  import * as t from '@babel/types';
2
2
  import { ParsingConfig, ParsingOutput } from '../types.js';
3
3
  import { InlineMetadata } from '../processTranslationCall/extractStringEntryMetadata.js';
4
+ import { NodePath } from '@babel/traverse';
4
5
  /**
5
6
  * Extracts a translatable message from a TaggedTemplateExpression.
6
7
  *
@@ -10,12 +11,14 @@ import { InlineMetadata } from '../processTranslationCall/extractStringEntryMeta
10
11
  * - Creates numeric placeholders ({0}, {1}, etc.) for each expression
11
12
  * - Joins all parts into the final source string
12
13
  *
14
+ * @param tPath - The path to the tag identifier
13
15
  * @param quasi - The TemplateLiteral from the TaggedTemplateExpression
14
16
  * @param metadata - Extracted metadata (empty for tagged templates)
15
17
  * @param config - Parsing configuration
16
18
  * @param output - Parsing output collectors
17
19
  */
18
- export declare function handleTaggedTemplateTranslationCall({ quasi, metadata, config, output, }: {
20
+ export declare function handleTaggedTemplateTranslationCall({ tPath, quasi, metadata, config, output, }: {
21
+ tPath: NodePath;
19
22
  quasi: t.TemplateLiteral;
20
23
  metadata: InlineMetadata;
21
24
  config: ParsingConfig;
@@ -1,5 +1,4 @@
1
- import { isValidIcu } from '../../../evaluateJsx.js';
2
- import { warnInvalidIcuSync } from '../../../../../console/index.js';
1
+ import { deriveExpression } from '../derivation/index.js';
3
2
  /**
4
3
  * Extracts a translatable message from a TaggedTemplateExpression.
5
4
  *
@@ -9,34 +8,19 @@ import { warnInvalidIcuSync } from '../../../../../console/index.js';
9
8
  * - Creates numeric placeholders ({0}, {1}, etc.) for each expression
10
9
  * - Joins all parts into the final source string
11
10
  *
11
+ * @param tPath - The path to the tag identifier
12
12
  * @param quasi - The TemplateLiteral from the TaggedTemplateExpression
13
13
  * @param metadata - Extracted metadata (empty for tagged templates)
14
14
  * @param config - Parsing configuration
15
15
  * @param output - Parsing output collectors
16
16
  */
17
- export function handleTaggedTemplateTranslationCall({ quasi, metadata, config, output, }) {
18
- const parts = [];
19
- let varIndex = 0;
20
- for (let i = 0; i < quasi.quasis.length; i++) {
21
- parts.push(quasi.quasis[i].value.cooked ?? quasi.quasis[i].value.raw);
22
- if (i < quasi.expressions.length) {
23
- const key = varIndex.toString();
24
- parts.push(`{${key}}`);
25
- varIndex++;
26
- }
27
- }
28
- const source = parts.join('');
29
- // Validate ICU format
30
- if (!config.ignoreInvalidIcu) {
31
- const { isValid, error } = isValidIcu(source);
32
- if (!isValid) {
33
- output.warnings.add(warnInvalidIcuSync(config.file, source, error ?? 'Unknown error', `${quasi.loc?.start?.line}:${quasi.loc?.start?.column}`));
34
- return;
35
- }
36
- }
37
- output.updates.push({
38
- dataFormat: 'ICU',
39
- source,
17
+ export function handleTaggedTemplateTranslationCall({ tPath, quasi, metadata, config, output, }) {
18
+ deriveExpression({
19
+ tPath,
20
+ expr: quasi,
40
21
  metadata,
22
+ config,
23
+ output,
24
+ enableRuntimeInterpolation: true,
41
25
  });
42
26
  }
@@ -16,6 +16,7 @@ export function processTaggedTemplateCall(tPath, config, output) {
16
16
  return;
17
17
  }
18
18
  handleTaggedTemplateTranslationCall({
19
+ tPath,
19
20
  quasi: tPath.parent.quasi,
20
21
  metadata: {},
21
22
  config,
@@ -1,12 +1,4 @@
1
- import { handleDeriveExpression } from '../../parseDerive.js';
2
- import { nodeToStrings } from '../../parseString.js';
3
- import { indexVars } from 'generaltranslation/internal';
4
- import { isValidIcu } from '../../../evaluateJsx.js';
5
- import { warnInvalidIcuSync, warnNonStringSync, } from '../../../../../console/index.js';
6
- import generateModule from '@babel/generator';
7
- import { randomUUID } from 'node:crypto';
8
- // Handle CommonJS/ESM interop
9
- const generate = generateModule.default || generateModule;
1
+ import { deriveExpression } from '../derivation/index.js';
10
2
  /**
11
3
  * For the processTranslationCall function, this function handles the case where a string with derive is used.
12
4
  * @param arg - The argument to parse
@@ -17,35 +9,12 @@ const generate = generateModule.default || generateModule;
17
9
  * @param index - Current index in array of strings being extracted
18
10
  */
19
11
  export function handleDeriveTranslationCall({ arg, metadata, tPath, config, output, index, }) {
20
- // parse derivable expression
21
- const result = handleDeriveExpression(arg, tPath, config.file, config.parsingOptions, output.errors);
22
- // Nothing returned, push error
23
- if (!result) {
24
- output.errors.push(warnNonStringSync(config.file, generate(arg).code, `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
25
- return;
26
- }
27
- // validate ICU
28
- const strings = nodeToStrings(result).map(indexVars);
29
- if (!config.ignoreInvalidIcu) {
30
- for (const string of strings) {
31
- const { isValid, error } = isValidIcu(string);
32
- if (!isValid) {
33
- output.warnings.add(warnInvalidIcuSync(config.file, string, error ?? 'Unknown error', `${arg.loc?.start?.line}:${arg.loc?.start?.column}`));
34
- return;
35
- }
36
- }
37
- }
38
- const temporaryDeriveId = `derive-temp-id-${randomUUID()}`;
39
- for (const string of strings) {
40
- output.updates.push({
41
- dataFormat: 'ICU',
42
- source: string,
43
- metadata: {
44
- ...metadata,
45
- // Add the index if an id and index is provided (for handling when registering an array of strings)
46
- ...(metadata.id && index != null && { id: `${metadata.id}.${index}` }),
47
- staticId: temporaryDeriveId,
48
- },
49
- });
50
- }
12
+ deriveExpression({
13
+ tPath,
14
+ expr: arg,
15
+ metadata,
16
+ config,
17
+ output,
18
+ index,
19
+ });
51
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gt",
3
- "version": "2.11.0",
3
+ "version": "2.11.1",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -110,8 +110,8 @@
110
110
  "unified": "^11.0.5",
111
111
  "unist-util-visit": "^5.0.0",
112
112
  "yaml": "^2.8.0",
113
- "@generaltranslation/python-extractor": "0.1.4",
114
- "generaltranslation": "8.1.18",
113
+ "@generaltranslation/python-extractor": "0.1.5",
114
+ "generaltranslation": "8.1.19",
115
115
  "gt-remark": "1.0.5"
116
116
  },
117
117
  "devDependencies": {
@@ -1,15 +0,0 @@
1
- import * as t from '@babel/types';
2
- import { NodePath } from '@babel/traverse';
3
- import { ParsingConfigOptions } from '../../../types/parsing.js';
4
- import { StringNode } from './types.js';
5
- export type StringTree = (string | StringTree)[];
6
- /**
7
- * Extracts content if an expression is derivable (statically analyzable) or uses derive()
8
- * Returns a Node representing the parsed expression
9
- * @param expr - The expression to check
10
- * @param tPath - NodePath for scope resolution
11
- * @param file - Current file path
12
- * @param parsingOptions - Parsing configuration
13
- * @returns Node | null - The parsed node, or null if invalid
14
- */
15
- export declare function handleDeriveExpression(expr: t.Expression, tPath: NodePath, file: string, parsingOptions: ParsingConfigOptions, errors: string[]): StringNode | null;