gtx-cli 2.6.5 → 2.6.7
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 +14 -0
- package/dist/api/collectUserEditDiffs.js +12 -1
- package/dist/cli/flags.js +3 -1
- package/dist/config/generateSettings.js +8 -4
- package/dist/formats/json/extractJson.d.ts +15 -0
- package/dist/formats/json/extractJson.js +92 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.6.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#975](https://github.com/generaltranslation/gt/pull/975) [`18d6672`](https://github.com/generaltranslation/gt/commit/18d6672c45d1cafe93817aec67fa60c70a1c7567) Thanks [@brian-lou](https://github.com/brian-lou)! - Add branch config options
|
|
8
|
+
|
|
9
|
+
- [#978](https://github.com/generaltranslation/gt/pull/978) [`73238cf`](https://github.com/generaltranslation/gt/commit/73238cf4d55e8b42c10c870c6a525df9ff36c338) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Fixing `save-local` behavior for composite JSONs
|
|
10
|
+
|
|
11
|
+
## 2.6.6
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#974](https://github.com/generaltranslation/gt/pull/974) [`ba07f07`](https://github.com/generaltranslation/gt/commit/ba07f078079a4ae0d07231fb98fee1a4668a5a39) Thanks [@fernando-aviles](https://github.com/fernando-aviles)! - Fixing `save-local` behavior for composite JSONs
|
|
16
|
+
|
|
3
17
|
## 2.6.5
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -7,6 +7,7 @@ import { gt } from '../utils/gt.js';
|
|
|
7
7
|
import os from 'node:os';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
9
|
import { hashStringSync } from '../utils/hash.js';
|
|
10
|
+
import { extractJson } from '../formats/json/extractJson.js';
|
|
10
11
|
const findLatestDownloadedVersion = (downloadedVersions, branchId, fileId, locale) => {
|
|
11
12
|
const versionsForFile = downloadedVersions.entries?.[branchId]?.[fileId] ?? undefined;
|
|
12
13
|
if (!versionsForFile)
|
|
@@ -125,7 +126,17 @@ export async function collectAndSendUserEditDiffs(files, settings) {
|
|
|
125
126
|
}
|
|
126
127
|
catch { }
|
|
127
128
|
if (diff && diff.trim().length > 0) {
|
|
128
|
-
const
|
|
129
|
+
const rawLocalContent = await fs.promises.readFile(c.outputPath, 'utf8');
|
|
130
|
+
// For JSON files with jsonSchema config, extract to composite format
|
|
131
|
+
let localContent = rawLocalContent;
|
|
132
|
+
if (c.fileName.endsWith('.json') &&
|
|
133
|
+
settings.options?.jsonSchema &&
|
|
134
|
+
c.locale !== settings.defaultLocale) {
|
|
135
|
+
const extractedContent = extractJson(rawLocalContent, c.fileName, settings.options, c.locale, settings.defaultLocale);
|
|
136
|
+
if (extractedContent) {
|
|
137
|
+
localContent = extractedContent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
129
140
|
collectedDiffs.push({
|
|
130
141
|
fileName: c.fileName,
|
|
131
142
|
locale: c.locale,
|
package/dist/cli/flags.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import findFilepath from '../fs/findFilepath.js';
|
|
2
|
+
import { DEFAULT_GIT_REMOTE_NAME } from '../utils/constants.js';
|
|
2
3
|
const DEFAULT_TIMEOUT = 600;
|
|
3
4
|
export function attachSharedFlags(command) {
|
|
4
5
|
command
|
|
@@ -35,7 +36,8 @@ export function attachTranslateFlags(command) {
|
|
|
35
36
|
.option('--experimental-clear-locale-dirs', 'Clear locale directories before downloading new translations', false)
|
|
36
37
|
.option('--branch <branch>', 'Specify a custom branch to use for translations')
|
|
37
38
|
.option('--disable-branch-detection', 'Disable additional branch detection and optimizations and use the manually specified branch', false)
|
|
38
|
-
.option('--enable-branching', 'Enable branching for the project', false)
|
|
39
|
+
.option('--enable-branching', 'Enable branching for the project', false) // disabled by default for now
|
|
40
|
+
.option('--remote-name <name>', 'Specify a custom remote name to use for branch detection', DEFAULT_GIT_REMOTE_NAME);
|
|
39
41
|
return command;
|
|
40
42
|
}
|
|
41
43
|
export function attachAdditionalReactTranslateFlags(command) {
|
|
@@ -5,7 +5,7 @@ import fs from 'node:fs';
|
|
|
5
5
|
import { createOrUpdateConfig } from '../fs/config/setupConfig.js';
|
|
6
6
|
import { resolveFiles } from '../fs/config/parseFilesConfig.js';
|
|
7
7
|
import { validateSettings } from './validateSettings.js';
|
|
8
|
-
import { GT_DASHBOARD_URL } from '../utils/constants.js';
|
|
8
|
+
import { DEFAULT_GIT_REMOTE_NAME, GT_DASHBOARD_URL, } from '../utils/constants.js';
|
|
9
9
|
import { resolveProjectId } from '../fs/utils.js';
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import chalk from 'chalk';
|
|
@@ -175,13 +175,17 @@ export async function generateSettings(flags, cwd = process.cwd()) {
|
|
|
175
175
|
];
|
|
176
176
|
// Add branch options if not provided
|
|
177
177
|
const branchOptions = mergedOptions.branchOptions || {};
|
|
178
|
-
branchOptions.enabled =
|
|
178
|
+
branchOptions.enabled =
|
|
179
|
+
flags.enableBranching ?? gtConfig.branchOptions?.enabled ?? false;
|
|
179
180
|
branchOptions.currentBranch =
|
|
180
181
|
flags.branch ?? gtConfig.branchOptions?.currentBranch ?? undefined;
|
|
181
182
|
branchOptions.autoDetectBranches = flags.disableBranchDetection
|
|
182
183
|
? false
|
|
183
|
-
: true;
|
|
184
|
-
branchOptions.remoteName =
|
|
184
|
+
: (gtConfig.branchOptions?.autoDetectBranches ?? true);
|
|
185
|
+
branchOptions.remoteName =
|
|
186
|
+
flags.remoteName ??
|
|
187
|
+
gtConfig.branchOptions?.remoteName ??
|
|
188
|
+
DEFAULT_GIT_REMOTE_NAME;
|
|
185
189
|
mergedOptions.branchOptions = branchOptions;
|
|
186
190
|
// if there's no existing config file, creates one
|
|
187
191
|
// does not include the API key to avoid exposing it
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AdditionalOptions } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts translated values from a full JSON file back into composite JSON format.
|
|
4
|
+
* This is the inverse of mergeJson - it takes a merged/reconstructed JSON file
|
|
5
|
+
* and extracts the values for a specific locale into the composite structure
|
|
6
|
+
* that the server expects.
|
|
7
|
+
*
|
|
8
|
+
* @param localContent - The full JSON content from the user's local file
|
|
9
|
+
* @param inputPath - The path to the file (used for matching jsonSchema)
|
|
10
|
+
* @param options - Additional options containing jsonSchema config
|
|
11
|
+
* @param targetLocale - The locale to extract values for
|
|
12
|
+
* @param defaultLocale - The default/source locale
|
|
13
|
+
* @returns The composite JSON string, or null if no extraction needed
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractJson(localContent: string, inputPath: string, options: AdditionalOptions, targetLocale: string, defaultLocale: string): string | null;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { logger } from '../../console/logger.js';
|
|
2
|
+
import { findMatchingItemArray, findMatchingItemObject, generateSourceObjectPointers, validateJsonSchema, } from './utils.js';
|
|
3
|
+
import { flattenJsonWithStringFilter } from './flattenJson.js';
|
|
4
|
+
import { gt } from '../../utils/gt.js';
|
|
5
|
+
/**
|
|
6
|
+
* Extracts translated values from a full JSON file back into composite JSON format.
|
|
7
|
+
* This is the inverse of mergeJson - it takes a merged/reconstructed JSON file
|
|
8
|
+
* and extracts the values for a specific locale into the composite structure
|
|
9
|
+
* that the server expects.
|
|
10
|
+
*
|
|
11
|
+
* @param localContent - The full JSON content from the user's local file
|
|
12
|
+
* @param inputPath - The path to the file (used for matching jsonSchema)
|
|
13
|
+
* @param options - Additional options containing jsonSchema config
|
|
14
|
+
* @param targetLocale - The locale to extract values for
|
|
15
|
+
* @param defaultLocale - The default/source locale
|
|
16
|
+
* @returns The composite JSON string, or null if no extraction needed
|
|
17
|
+
*/
|
|
18
|
+
export function extractJson(localContent, inputPath, options, targetLocale, defaultLocale) {
|
|
19
|
+
const jsonSchema = validateJsonSchema(options, inputPath);
|
|
20
|
+
if (!jsonSchema) {
|
|
21
|
+
// No schema
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
let localJson;
|
|
25
|
+
try {
|
|
26
|
+
localJson = JSON.parse(localContent);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
logger.error(`Invalid JSON file: ${inputPath}`);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const useCanonicalLocaleKeys = options?.experimentalCanonicalLocaleKeys ?? false;
|
|
33
|
+
const canonicalTargetLocale = useCanonicalLocaleKeys
|
|
34
|
+
? gt.resolveCanonicalLocale(targetLocale)
|
|
35
|
+
: targetLocale;
|
|
36
|
+
// Handle include-style schemas (simple path-based extraction)
|
|
37
|
+
if (jsonSchema.include) {
|
|
38
|
+
const extracted = flattenJsonWithStringFilter(localJson, jsonSchema.include);
|
|
39
|
+
return JSON.stringify(extracted, null, 2);
|
|
40
|
+
}
|
|
41
|
+
if (!jsonSchema.composite) {
|
|
42
|
+
logger.error('No include or composite property found in JSON schema');
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
// Handle composite schemas
|
|
46
|
+
const compositeResult = {};
|
|
47
|
+
// Generate source object pointers from the local JSON
|
|
48
|
+
const sourceObjectPointers = generateSourceObjectPointers(jsonSchema.composite, localJson);
|
|
49
|
+
for (const [sourceObjectPointer, { sourceObjectValue, sourceObjectOptions },] of Object.entries(sourceObjectPointers)) {
|
|
50
|
+
if (sourceObjectOptions.type === 'array') {
|
|
51
|
+
if (!Array.isArray(sourceObjectValue)) {
|
|
52
|
+
logger.warn(`Source object value is not an array at path: ${sourceObjectPointer}`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Find the matching items for the target locale
|
|
56
|
+
const matchingTargetLocaleItems = findMatchingItemArray(canonicalTargetLocale, sourceObjectOptions, sourceObjectPointer, sourceObjectValue);
|
|
57
|
+
if (!Object.keys(matchingTargetLocaleItems).length) {
|
|
58
|
+
logger.warn(`No matching items found for locale ${targetLocale} at path: ${sourceObjectPointer}`);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
// Initialize the nested structure for this source object pointer
|
|
62
|
+
if (!compositeResult[sourceObjectPointer]) {
|
|
63
|
+
compositeResult[sourceObjectPointer] = {};
|
|
64
|
+
}
|
|
65
|
+
// For each matching item, extract the included values
|
|
66
|
+
for (const [itemPointer, { sourceItem }] of Object.entries(matchingTargetLocaleItems)) {
|
|
67
|
+
// Extract values at the include paths
|
|
68
|
+
const extractedValues = flattenJsonWithStringFilter(sourceItem, sourceObjectOptions.include);
|
|
69
|
+
// Store under the item pointer (e.g., "/0")
|
|
70
|
+
compositeResult[sourceObjectPointer][itemPointer] = extractedValues;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Object type
|
|
75
|
+
if (typeof sourceObjectValue !== 'object' || sourceObjectValue === null) {
|
|
76
|
+
logger.warn(`Source object value is not an object at path: ${sourceObjectPointer}`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
// Find the matching item for the target locale
|
|
80
|
+
const matchingTargetItem = findMatchingItemObject(canonicalTargetLocale, sourceObjectPointer, sourceObjectOptions, sourceObjectValue);
|
|
81
|
+
if (!matchingTargetItem.sourceItem) {
|
|
82
|
+
logger.warn(`No matching item found for locale ${targetLocale} at path: ${sourceObjectPointer}`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
// Extract values at the include paths
|
|
86
|
+
const extractedValues = flattenJsonWithStringFilter(matchingTargetItem.sourceItem, sourceObjectOptions.include);
|
|
87
|
+
// Store the extracted values
|
|
88
|
+
compositeResult[sourceObjectPointer] = extractedValues;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return JSON.stringify(compositeResult, null, 2);
|
|
92
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.6.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.6.7";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.6.
|
|
2
|
+
export const PACKAGE_VERSION = '2.6.7';
|
|
@@ -2,3 +2,4 @@ export declare const GT_DASHBOARD_URL = "https://dash.generaltranslation.com";
|
|
|
2
2
|
export declare const GT_CONFIG_SCHEMA_URL = "https://assets.gtx.dev/config-schema.json";
|
|
3
3
|
export declare const TEMPLATE_FILE_NAME = "__INTERNAL_GT_TEMPLATE_NAME__";
|
|
4
4
|
export declare const TEMPLATE_FILE_ID: string;
|
|
5
|
+
export declare const DEFAULT_GIT_REMOTE_NAME = "origin";
|
package/dist/utils/constants.js
CHANGED
|
@@ -3,3 +3,4 @@ export const GT_DASHBOARD_URL = 'https://dash.generaltranslation.com';
|
|
|
3
3
|
export const GT_CONFIG_SCHEMA_URL = 'https://assets.gtx.dev/config-schema.json';
|
|
4
4
|
export const TEMPLATE_FILE_NAME = '__INTERNAL_GT_TEMPLATE_NAME__';
|
|
5
5
|
export const TEMPLATE_FILE_ID = hashStringSync(TEMPLATE_FILE_NAME);
|
|
6
|
+
export const DEFAULT_GIT_REMOTE_NAME = 'origin';
|