gtx-cli 2.4.8 → 2.4.10

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,17 @@
1
1
  # gtx-cli
2
2
 
3
+ ## 2.4.10
4
+
5
+ ### Patch Changes
6
+
7
+ - [#778](https://github.com/generaltranslation/gt/pull/778) [`0d8f414`](https://github.com/generaltranslation/gt/commit/0d8f4144696873b15f0aaa6744bdb7390d472279) Thanks [@SamEggert](https://github.com/SamEggert)! - skip dynamic expressions for HTML content props in parseJSX
8
+
9
+ ## 2.4.9
10
+
11
+ ### Patch Changes
12
+
13
+ - [#774](https://github.com/generaltranslation/gt/pull/774) [`87dab40`](https://github.com/generaltranslation/gt/commit/87dab40efc9469d6ba3b3dc143d7d7a27422f7b0) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Hiding saving local translations behind the --save-local flag
14
+
3
15
  ## 2.4.8
4
16
 
5
17
  ### Patch Changes
@@ -86,18 +86,20 @@ export async function sendFiles(files, options, settings) {
86
86
  setupSpinner.stop(chalk.yellow(`Setup ${setupFailedMessage ? 'failed' : 'timed out'} — proceeding without setup${setupFailedMessage ? ` (${setupFailedMessage})` : ''}`));
87
87
  }
88
88
  }
89
- // Step 3: Prior to enqueue, detect and submit user edit diffs (minimal UX)
90
- const prepSpinner = createSpinner('dots');
91
- currentSpinner = prepSpinner;
92
- prepSpinner.start('Updating translations...');
93
- try {
94
- await collectAndSendUserEditDiffs(upload.uploadedFiles, settings);
95
- }
96
- catch {
97
- // Non-fatal; keep going to enqueue
98
- }
99
- finally {
100
- prepSpinner.stop('Updated translations');
89
+ // Step 3 (optional): Prior to enqueue, detect and submit user edit diffs
90
+ if (options?.saveLocal) {
91
+ const prepSpinner = createSpinner('dots');
92
+ currentSpinner = prepSpinner;
93
+ prepSpinner.start('Updating translations...');
94
+ try {
95
+ await collectAndSendUserEditDiffs(upload.uploadedFiles, settings);
96
+ }
97
+ catch {
98
+ // Non-fatal; keep going to enqueue
99
+ }
100
+ finally {
101
+ prepSpinner.stop('Updated translations');
102
+ }
101
103
  }
102
104
  // Step 4: Enqueue translations by reference
103
105
  const enqueueSpinner = createSpinner('dots');
package/dist/cli/flags.js CHANGED
@@ -20,6 +20,7 @@ export function attachTranslateFlags(command) {
20
20
  }
21
21
  return parsedValue;
22
22
  }, DEFAULT_TIMEOUT)
23
+ .option('--save-local', 'Detect and save local edits before enqueuing translations', false)
23
24
  .option('--publish', 'Publish translations to the CDN', false)
24
25
  .option('--experimental-localize-static-urls', 'Triggering this will run a script after the cli tool that localizes all urls in content files. Currently only supported for md and mdx files.', false)
25
26
  .option('--experimental-hide-default-locale', 'When localizing static locales, hide the default locale from the path', false)
@@ -8,6 +8,7 @@ import { isAcceptedPluralForm } from 'generaltranslation/internal';
8
8
  import { handleChildrenWhitespace } from '../trimJsxStringChildren.js';
9
9
  import { isStaticExpression } from '../evaluateJsx.js';
10
10
  import { GT_ATTRIBUTES, mapAttributeName, VARIABLE_COMPONENTS, } from './constants.js';
11
+ import { HTML_CONTENT_PROPS } from 'generaltranslation/types';
11
12
  /**
12
13
  * Builds a JSX tree from a given node, recursively handling children.
13
14
  * @param node - The node to build the tree from
@@ -80,15 +81,29 @@ export function buildJSXTree(importAliases, node, unwrappedExpressions, updates,
80
81
  attrValue = attr.value.value;
81
82
  }
82
83
  else if (t.isJSXExpressionContainer(attr.value)) {
83
- if ((elementIsPlural && isAcceptedPluralForm(attrName)) ||
84
- (elementIsBranch && attrName !== 'branch')) {
85
- // Make sure that variable strings like {`I have ${count} book`} are invalid!
86
- if (t.isTemplateLiteral(attr.value.expression) &&
87
- !isStaticExpression(attr.value.expression).isStatic) {
88
- unwrappedExpressions.push(generate(attr.value).code);
84
+ // Check if this is an HTML content prop (title, placeholder, alt, etc.)
85
+ const isHtmlContentProp = Object.values(HTML_CONTENT_PROPS).includes(attrName);
86
+ if (isHtmlContentProp) {
87
+ // For HTML content props, only accept static string expressions
88
+ const staticAnalysis = isStaticExpression(attr.value.expression);
89
+ if (staticAnalysis.isStatic &&
90
+ staticAnalysis.value !== undefined) {
91
+ attrValue = staticAnalysis.value;
89
92
  }
93
+ // Otherwise attrValue stays null and won't be included
94
+ }
95
+ else {
96
+ // For non-HTML-content props, validate plural/branch then build tree
97
+ if ((elementIsPlural && isAcceptedPluralForm(attrName)) ||
98
+ (elementIsBranch && attrName !== 'branch')) {
99
+ // Make sure that variable strings like {`I have ${count} book`} are invalid!
100
+ if (t.isTemplateLiteral(attr.value.expression) &&
101
+ !isStaticExpression(attr.value.expression).isStatic) {
102
+ unwrappedExpressions.push(generate(attr.value).code);
103
+ }
104
+ }
105
+ attrValue = buildJSXTree(importAliases, attr.value.expression, unwrappedExpressions, updates, errors, warnings, file, true);
90
106
  }
91
- attrValue = buildJSXTree(importAliases, attr.value.expression, unwrappedExpressions, updates, errors, warnings, file, true);
92
107
  }
93
108
  }
94
109
  props[attrName] = attrValue;
@@ -39,6 +39,7 @@ export type TranslateFlags = {
39
39
  src?: string[];
40
40
  timeout: number;
41
41
  dryRun: boolean;
42
+ saveLocal?: boolean;
42
43
  stageTranslations?: boolean;
43
44
  publish?: boolean;
44
45
  force?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.4.8",
3
+ "version": "2.4.10",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [