gtx-cli 2.1.5-alpha.2 → 2.1.5-alpha.5

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.
Files changed (59) hide show
  1. package/dist/api/checkFileTranslations.d.ts +4 -1
  2. package/dist/api/checkFileTranslations.js +35 -32
  3. package/dist/api/downloadFile.d.ts +9 -0
  4. package/dist/api/downloadFile.js +74 -0
  5. package/dist/api/downloadFileBatch.d.ts +0 -1
  6. package/dist/api/fetchTranslations.d.ts +7 -0
  7. package/dist/api/fetchTranslations.js +18 -0
  8. package/dist/api/sendFiles.d.ts +13 -2
  9. package/dist/api/sendFiles.js +8 -15
  10. package/dist/api/sendUpdates.d.ts +19 -0
  11. package/dist/api/sendUpdates.js +48 -0
  12. package/dist/api/waitForUpdates.d.ts +9 -0
  13. package/dist/api/waitForUpdates.js +89 -0
  14. package/dist/cli/base.d.ts +17 -5
  15. package/dist/cli/base.js +75 -48
  16. package/dist/cli/next.js +1 -0
  17. package/dist/cli/react.d.ts +5 -2
  18. package/dist/cli/react.js +153 -13
  19. package/dist/config/generateSettings.js +6 -11
  20. package/dist/console/index.d.ts +0 -1
  21. package/dist/console/index.js +0 -1
  22. package/dist/console/logging.d.ts +0 -1
  23. package/dist/console/logging.js +0 -3
  24. package/dist/formats/files/fileMapping.d.ts +1 -2
  25. package/dist/formats/files/fileMapping.js +0 -6
  26. package/dist/formats/files/translate.d.ts +13 -4
  27. package/dist/formats/files/translate.js +142 -30
  28. package/dist/formats/files/upload.js +75 -1
  29. package/dist/formats/gt/save.d.ts +2 -1
  30. package/dist/formats/gt/save.js +5 -2
  31. package/dist/fs/config/setupConfig.d.ts +0 -1
  32. package/dist/fs/config/setupConfig.js +0 -1
  33. package/dist/fs/config/updateConfig.d.ts +2 -1
  34. package/dist/fs/config/updateConfig.js +1 -1
  35. package/dist/fs/copyFile.d.ts +2 -1
  36. package/dist/translation/parse.d.ts +2 -2
  37. package/dist/translation/parse.js +6 -4
  38. package/dist/translation/stage.d.ts +5 -2
  39. package/dist/translation/stage.js +55 -13
  40. package/dist/translation/translate.d.ts +2 -0
  41. package/dist/translation/translate.js +18 -0
  42. package/dist/types/index.d.ts +4 -27
  43. package/dist/utils/flattenJsonFiles.d.ts +2 -2
  44. package/dist/utils/localizeStaticImports.d.ts +2 -2
  45. package/dist/utils/localizeStaticUrls.d.ts +6 -2
  46. package/dist/utils/localizeStaticUrls.js +119 -96
  47. package/package.json +2 -2
  48. package/dist/cli/commands/stage.d.ts +0 -5
  49. package/dist/cli/commands/stage.js +0 -100
  50. package/dist/cli/commands/translate.d.ts +0 -6
  51. package/dist/cli/commands/translate.js +0 -54
  52. package/dist/cli/flags.d.ts +0 -3
  53. package/dist/cli/flags.js +0 -37
  54. package/dist/fs/config/updateVersions.d.ts +0 -10
  55. package/dist/fs/config/updateVersions.js +0 -30
  56. package/dist/types/files.d.ts +0 -1
  57. package/dist/types/files.js +0 -1
  58. package/dist/utils/hash.d.ts +0 -6
  59. package/dist/utils/hash.js +0 -11
@@ -7,6 +7,7 @@ import remarkMdx from 'remark-mdx';
7
7
  import remarkFrontmatter from 'remark-frontmatter';
8
8
  import remarkStringify from 'remark-stringify';
9
9
  import { visit } from 'unist-util-visit';
10
+ import { logMessage } from '../console/logging.js';
10
11
  const { isMatch } = micromatch;
11
12
  /**
12
13
  * Localizes static urls in content files.
@@ -21,19 +22,25 @@ const { isMatch } = micromatch;
21
22
  * - Support more file types
22
23
  * - Support more complex paths
23
24
  */
24
- export default async function localizeStaticUrls(settings) {
25
+ export default async function localizeStaticUrls(settings, targetLocales // Optional filter for specific locales
26
+ ) {
25
27
  if (!settings.files ||
26
28
  (Object.keys(settings.files.placeholderPaths).length === 1 &&
27
29
  settings.files.placeholderPaths.gt)) {
28
30
  return;
29
31
  }
30
32
  const { resolvedPaths: sourceFiles } = settings.files;
31
- const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.locales, settings.defaultLocale);
33
+ // Use filtered locales if provided, otherwise use all locales
34
+ const locales = targetLocales || settings.locales;
35
+ const fileMapping = createFileMapping(sourceFiles, settings.files.placeholderPaths, settings.files.transformPaths, settings.locales, // Always use all locales for mapping, filter later
36
+ settings.defaultLocale);
32
37
  // Process all file types at once with a single call
33
38
  const processPromises = [];
34
39
  // First, process default locale files (from source files)
35
40
  // This is needed because they might not be in the fileMapping if they're not being translated
36
- if (!fileMapping[settings.defaultLocale]) {
41
+ // Only process default locale if it's in the target locales filter
42
+ if (!fileMapping[settings.defaultLocale] &&
43
+ locales.includes(settings.defaultLocale)) {
37
44
  const defaultLocaleFiles = [];
38
45
  // Collect all .md and .mdx files from sourceFiles
39
46
  if (sourceFiles.md) {
@@ -48,7 +55,7 @@ export default async function localizeStaticUrls(settings) {
48
55
  const fileContent = await fs.promises.readFile(filePath, 'utf8');
49
56
  // Localize the file using default locale
50
57
  const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, settings.defaultLocale, // Process as default locale
51
- settings.options?.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.excludeStaticUrls);
58
+ settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.excludeStaticUrls, settings.options?.baseDomain);
52
59
  // Write the localized file back to the same path
53
60
  await fs.promises.writeFile(filePath, localizedFile);
54
61
  }));
@@ -56,7 +63,9 @@ export default async function localizeStaticUrls(settings) {
56
63
  }
57
64
  }
58
65
  // Then process all other locales from fileMapping
59
- const mappingPromises = Object.entries(fileMapping).map(async ([locale, filesMap]) => {
66
+ const mappingPromises = Object.entries(fileMapping)
67
+ .filter(([locale, filesMap]) => locales.includes(locale)) // Filter by target locales
68
+ .map(async ([locale, filesMap]) => {
60
69
  // Get all files that are md or mdx
61
70
  const targetFiles = Object.values(filesMap).filter((path) => path.endsWith('.md') || path.endsWith('.mdx'));
62
71
  // Replace the placeholder path with the target path
@@ -64,7 +73,7 @@ export default async function localizeStaticUrls(settings) {
64
73
  // Get file content
65
74
  const fileContent = await fs.promises.readFile(filePath, 'utf8');
66
75
  // Localize the file (handles both URLs and hrefs in single AST pass)
67
- const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.options?.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.excludeStaticUrls);
76
+ const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.excludeStaticUrls, settings.options?.baseDomain);
68
77
  // Write the localized file to the target path
69
78
  await fs.promises.writeFile(filePath, localizedFile);
70
79
  }));
@@ -75,21 +84,28 @@ export default async function localizeStaticUrls(settings) {
75
84
  /**
76
85
  * Determines if a URL should be processed based on pattern matching
77
86
  */
78
- function shouldProcessUrl(originalUrl, patternHead, targetLocale, defaultLocale) {
79
- // Skip absolute URLs (http://, https://, //, etc.)
80
- if (originalUrl.includes(':')) {
81
- return false;
82
- }
87
+ function shouldProcessUrl(originalUrl, patternHead, targetLocale, defaultLocale, baseDomain) {
83
88
  const patternWithoutSlash = patternHead.replace(/\/$/, '');
89
+ // Handle absolute URLs with baseDomain
90
+ let urlToCheck = originalUrl;
91
+ if (baseDomain && originalUrl.startsWith(baseDomain)) {
92
+ urlToCheck = originalUrl.substring(baseDomain.length);
93
+ }
84
94
  if (targetLocale === defaultLocale) {
85
95
  // For default locale processing, check if URL contains the pattern
86
- return originalUrl.includes(patternWithoutSlash);
96
+ return urlToCheck.includes(patternWithoutSlash);
87
97
  }
88
98
  else {
89
99
  // For non-default locales, check if URL starts with pattern
90
- return originalUrl.startsWith(patternWithoutSlash);
100
+ return urlToCheck.startsWith(patternWithoutSlash);
91
101
  }
92
102
  }
103
+ /**
104
+ * Determines if a URL should be processed based on the base domain
105
+ */
106
+ function shouldProcessAbsoluteUrl(originalUrl, baseDomain) {
107
+ return originalUrl.startsWith(baseDomain);
108
+ }
93
109
  /**
94
110
  * Checks if a URL should be excluded based on exclusion patterns
95
111
  */
@@ -98,102 +114,79 @@ function isUrlExcluded(originalUrl, exclude, defaultLocale) {
98
114
  return excludePatterns.some((pattern) => isMatch(originalUrl, pattern));
99
115
  }
100
116
  /**
101
- * Transforms URL for default locale processing
102
- */
103
- function transformDefaultLocaleUrl(originalUrl, patternHead, defaultLocale, hideDefaultLocale) {
104
- if (hideDefaultLocale) {
105
- // Remove locale from URLs that have it: '/docs/en/file' -> '/docs/file'
106
- if (originalUrl.includes(`/${defaultLocale}/`)) {
107
- return originalUrl.replace(`/${defaultLocale}/`, '/');
108
- }
109
- else if (originalUrl.endsWith(`/${defaultLocale}`)) {
110
- return originalUrl.replace(`/${defaultLocale}`, '');
111
- }
112
- return null; // URL doesn't have default locale
113
- }
114
- else {
115
- // Add locale to URLs that don't have it: '/docs/file' -> '/docs/en/file'
116
- if (originalUrl.includes(`/${defaultLocale}/`) ||
117
- originalUrl.endsWith(`/${defaultLocale}`)) {
118
- return null; // Already has default locale
119
- }
120
- if (originalUrl.startsWith(patternHead)) {
121
- const pathAfterHead = originalUrl.slice(patternHead.length);
122
- if (pathAfterHead) {
123
- return `${patternHead}${defaultLocale}/${pathAfterHead}`;
124
- }
125
- else {
126
- return `${patternHead.replace(/\/$/, '')}/${defaultLocale}`;
127
- }
128
- }
129
- return null; // URL doesn't match pattern
130
- }
131
- }
132
- /**
133
- * Transforms URL for non-default locale processing with hideDefaultLocale=true
117
+ * Main URL transformation function that delegates to specific scenarios
134
118
  */
135
- function transformNonDefaultLocaleUrlWithHidden(originalUrl, patternHead, targetLocale, defaultLocale) {
136
- // Check if already localized
137
- if (originalUrl.startsWith(`${patternHead}${targetLocale}/`) ||
138
- originalUrl === `${patternHead}${targetLocale}`) {
119
+ export function transformUrlPath(originalUrl, patternHead, targetLocale, defaultLocale, hideDefaultLocale) {
120
+ const originalPathArray = originalUrl
121
+ .split('/')
122
+ .filter((path) => path !== '');
123
+ const patternHeadArray = patternHead.split('/').filter((path) => path !== '');
124
+ // check if the pattern head matches the original path
125
+ if (!checkIfPathMatchesPattern(originalPathArray, patternHeadArray)) {
139
126
  return null;
140
127
  }
141
- // Replace default locale with target locale
142
- const expectedPathWithDefaultLocale = `${patternHead}${defaultLocale}`;
143
- if (originalUrl.startsWith(`${expectedPathWithDefaultLocale}/`) ||
144
- originalUrl === expectedPathWithDefaultLocale) {
145
- return originalUrl.replace(`${patternHead}${defaultLocale}`, `${patternHead}${targetLocale}`);
146
- }
147
- // Handle exact pattern match
148
- if (originalUrl === patternHead.replace(/\/$/, '')) {
149
- return `${patternHead.replace(/\/$/, '')}/${targetLocale}`;
128
+ if (patternHeadArray.length > originalPathArray.length) {
129
+ return null; // Pattern is longer than the URL path
150
130
  }
151
- // Add target locale to URL without any locale
152
- const pathAfterHead = originalUrl.slice(originalUrl.startsWith(patternHead) ? patternHead.length : 0);
153
- return pathAfterHead
154
- ? `${patternHead}${targetLocale}/${pathAfterHead}`
155
- : `${patternHead}${targetLocale}`;
156
- }
157
- /**
158
- * Transforms URL for non-default locale processing with hideDefaultLocale=false
159
- */
160
- function transformNonDefaultLocaleUrl(originalUrl, patternHead, targetLocale, defaultLocale) {
161
- const expectedPathWithLocale = `${patternHead}${defaultLocale}`;
162
- if (originalUrl.startsWith(`${expectedPathWithLocale}/`) ||
163
- originalUrl === expectedPathWithLocale) {
164
- // Replace existing default locale with target locale
165
- return originalUrl.replace(`${patternHead}${defaultLocale}`, `${patternHead}${targetLocale}`);
166
- }
167
- else if (originalUrl.startsWith(patternHead)) {
168
- // Add target locale to URL that doesn't have any locale
169
- const pathAfterHead = originalUrl.slice(patternHead.length);
170
- if (pathAfterHead) {
171
- return `${patternHead}${targetLocale}/${pathAfterHead}`;
131
+ let result = null;
132
+ if (targetLocale === defaultLocale) {
133
+ if (hideDefaultLocale) {
134
+ // check if default locale is already present
135
+ if (originalPathArray?.[patternHeadArray.length] !== defaultLocale) {
136
+ return null;
137
+ }
138
+ // remove default locale
139
+ const newPathArray = [
140
+ ...originalPathArray.slice(0, patternHeadArray.length),
141
+ ...originalPathArray.slice(patternHeadArray.length + 1),
142
+ ];
143
+ result = newPathArray.join('/');
172
144
  }
173
145
  else {
174
- return `${patternHead.replace(/\/$/, '')}/${targetLocale}`;
146
+ // check if default locale is already present
147
+ if (originalPathArray?.[patternHeadArray.length] === defaultLocale) {
148
+ return null;
149
+ }
150
+ // insert default locale
151
+ const newPathArray = [
152
+ ...originalPathArray.slice(0, patternHeadArray.length),
153
+ defaultLocale,
154
+ ...originalPathArray.slice(patternHeadArray.length),
155
+ ];
156
+ result = newPathArray.join('/');
175
157
  }
176
158
  }
177
- return null; // URL doesn't match pattern
178
- }
179
- /**
180
- * Main URL transformation function that delegates to specific scenarios
181
- */
182
- function transformUrlPath(originalUrl, patternHead, targetLocale, defaultLocale, hideDefaultLocale) {
183
- if (targetLocale === defaultLocale) {
184
- return transformDefaultLocaleUrl(originalUrl, patternHead, defaultLocale, hideDefaultLocale);
185
- }
186
159
  else if (hideDefaultLocale) {
187
- return transformNonDefaultLocaleUrlWithHidden(originalUrl, patternHead, targetLocale, defaultLocale);
160
+ const newPathArray = [
161
+ ...originalPathArray.slice(0, patternHeadArray.length),
162
+ targetLocale,
163
+ ...originalPathArray.slice(patternHeadArray.length),
164
+ ];
165
+ result = newPathArray.join('/');
188
166
  }
189
167
  else {
190
- return transformNonDefaultLocaleUrl(originalUrl, patternHead, targetLocale, defaultLocale);
168
+ // check default locale
169
+ if (originalPathArray?.[patternHeadArray.length] !== defaultLocale) {
170
+ return null;
171
+ }
172
+ // replace default locale with target locale
173
+ const newPathArray = [...originalPathArray];
174
+ newPathArray[patternHeadArray.length] = targetLocale;
175
+ result = newPathArray.join('/');
176
+ }
177
+ // check for leading and trailing slashes
178
+ if (originalUrl.startsWith('/')) {
179
+ result = '/' + result;
180
+ }
181
+ if (originalUrl.endsWith('/')) {
182
+ result = result + '/';
191
183
  }
184
+ return result;
192
185
  }
193
186
  /**
194
187
  * AST-based transformation for MDX files using remark-mdx
195
188
  */
196
- function transformMdxUrls(mdxContent, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', exclude = []) {
189
+ function transformMdxUrls(mdxContent, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', exclude = [], baseDomain) {
197
190
  const transformedUrls = [];
198
191
  if (!pattern.startsWith('/')) {
199
192
  pattern = '/' + pattern;
@@ -246,7 +239,21 @@ function transformMdxUrls(mdxContent, defaultLocale, targetLocale, hideDefaultLo
246
239
  // Helper function to transform URL based on pattern
247
240
  const transformUrl = (originalUrl, linkType) => {
248
241
  // Check if URL should be processed
249
- if (!shouldProcessUrl(originalUrl, patternHead, targetLocale, defaultLocale)) {
242
+ if (!shouldProcessUrl(originalUrl, patternHead, targetLocale, defaultLocale, baseDomain)) {
243
+ return null;
244
+ }
245
+ // Skip absolute URLs (http://, https://, //, etc.)
246
+ if (baseDomain && shouldProcessAbsoluteUrl(originalUrl, baseDomain)) {
247
+ // Get everything after the base domain
248
+ logMessage(`originalUrl: ${originalUrl}`);
249
+ logMessage(`baseDomain: ${baseDomain}`);
250
+ const afterDomain = originalUrl.substring(baseDomain.length);
251
+ logMessage(`afterDomain: ${afterDomain}`);
252
+ const transformedPath = transformUrlPath(afterDomain, patternHead, targetLocale, defaultLocale, hideDefaultLocale);
253
+ return transformedPath ? baseDomain + transformedPath : null;
254
+ }
255
+ // Exclude colon-prefixed URLs (http://, https://, //, etc.)
256
+ if (originalUrl.split('?')[0].includes(':')) {
250
257
  return null;
251
258
  }
252
259
  // Transform the URL based on locale and configuration
@@ -381,8 +388,24 @@ function transformMdxUrls(mdxContent, defaultLocale, targetLocale, hideDefaultLo
381
388
  }
382
389
  // AST-based transformation for MDX files using remark
383
390
  function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
384
- exclude = []) {
391
+ exclude = [], baseDomain) {
385
392
  // Use AST-based transformation for MDX files
386
- const result = transformMdxUrls(file, defaultLocale, targetLocale, hideDefaultLocale, pattern, exclude);
393
+ const result = transformMdxUrls(file, defaultLocale, targetLocale, hideDefaultLocale, pattern, exclude, baseDomain || '');
387
394
  return result.content;
388
395
  }
396
+ function cleanPath(path) {
397
+ let cleanedPath = path.startsWith('/') ? path.slice(1) : path;
398
+ cleanedPath = cleanedPath.endsWith('/')
399
+ ? cleanedPath.slice(0, -1)
400
+ : cleanedPath;
401
+ return cleanedPath;
402
+ }
403
+ function checkIfPathMatchesPattern(originalUrlArray, patternHeadArray) {
404
+ // check if the pattern head matches the original path
405
+ for (let i = 0; i < patternHeadArray.length; i++) {
406
+ if (patternHeadArray[i] !== originalUrlArray?.[i]) {
407
+ return false;
408
+ }
409
+ }
410
+ return true;
411
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtx-cli",
3
- "version": "2.1.5-alpha.2",
3
+ "version": "2.1.5-alpha.5",
4
4
  "main": "dist/index.js",
5
5
  "bin": "dist/main.js",
6
6
  "files": [
@@ -87,7 +87,7 @@
87
87
  "esbuild": "^0.25.4",
88
88
  "fast-glob": "^3.3.3",
89
89
  "form-data": "^4.0.4",
90
- "generaltranslation": "^7.4.1-alpha.1",
90
+ "generaltranslation": "^7.4.0",
91
91
  "json-pointer": "^0.6.2",
92
92
  "jsonpath-plus": "^10.3.0",
93
93
  "jsonpointer": "^5.0.1",
@@ -1,5 +0,0 @@
1
- import { Settings, SupportedLibraries, TranslateFlags } from '../../types/index.js';
2
- import { SendFilesResult } from '../../api/sendFiles.js';
3
- export declare const TEMPLATE_FILE_NAME = "__INTERNAL_GT_TEMPLATE_NAME__";
4
- export declare const TEMPLATE_FILE_ID: string;
5
- export declare function handleStage(options: TranslateFlags, settings: Settings, library: SupportedLibraries, stage: boolean): Promise<SendFilesResult | undefined>;
@@ -1,100 +0,0 @@
1
- import { logErrorAndExit, logSuccess } from '../../console/logging.js';
2
- import { noLocalesError, noDefaultLocaleError, noApiKeyError, noProjectIdError, devApiKeyError, invalidConfigurationError, } from '../../console/index.js';
3
- import { aggregateFiles } from '../../formats/files/translate.js';
4
- import { aggregateReactTranslations } from '../../translation/stage.js';
5
- import { sendFiles } from '../../api/sendFiles.js';
6
- import { updateVersions } from '../../fs/config/updateVersions.js';
7
- import updateConfig from '../../fs/config/updateConfig.js';
8
- import { hashStringSync } from '../../utils/hash.js';
9
- export const TEMPLATE_FILE_NAME = '__INTERNAL_GT_TEMPLATE_NAME__';
10
- export const TEMPLATE_FILE_ID = hashStringSync(TEMPLATE_FILE_NAME);
11
- export async function handleStage(options, settings, library, stage) {
12
- // Validate required settings are present if not in dry run
13
- if (!options.dryRun) {
14
- if (!settings.locales) {
15
- logErrorAndExit(noLocalesError);
16
- }
17
- if (!settings.defaultLocale) {
18
- logErrorAndExit(noDefaultLocaleError);
19
- }
20
- if (!settings.apiKey) {
21
- logErrorAndExit(noApiKeyError);
22
- }
23
- if (settings.apiKey.startsWith('gtx-dev-')) {
24
- logErrorAndExit(devApiKeyError);
25
- }
26
- if (!settings.projectId) {
27
- logErrorAndExit(noProjectIdError);
28
- }
29
- }
30
- // Aggregate files
31
- const allFiles = await aggregateFiles(settings);
32
- // Parse for React components
33
- let reactComponents = 0;
34
- if (library === 'gt-react' || library === 'gt-next') {
35
- const updates = await aggregateReactTranslations(options, settings, library);
36
- if (updates.length > 0) {
37
- if (!options.dryRun &&
38
- !settings.publish &&
39
- !settings.files?.placeholderPaths.gt) {
40
- logErrorAndExit(invalidConfigurationError);
41
- }
42
- reactComponents = updates.length;
43
- // Convert updates to a file object
44
- const fileData = {};
45
- const fileMetadata = {};
46
- // Convert updates to the proper data format
47
- for (const update of updates) {
48
- const { source, metadata, dataFormat } = update;
49
- metadata.dataFormat = dataFormat; // add the data format to the metadata
50
- const { hash, id } = metadata;
51
- if (id) {
52
- fileData[id] = source;
53
- fileMetadata[id] = metadata;
54
- }
55
- else {
56
- fileData[hash] = source;
57
- fileMetadata[hash] = metadata;
58
- }
59
- }
60
- allFiles.push({
61
- fileName: TEMPLATE_FILE_NAME,
62
- content: JSON.stringify(fileData),
63
- fileFormat: 'GTJSON',
64
- formatMetadata: fileMetadata,
65
- });
66
- }
67
- }
68
- // Dry run
69
- if (options.dryRun) {
70
- const fileNames = allFiles
71
- .map((file) => {
72
- if (file.fileName === TEMPLATE_FILE_NAME) {
73
- return `- <React Elements> (${reactComponents})`;
74
- }
75
- return `- ${file.fileName}`;
76
- })
77
- .join('\n');
78
- logSuccess(`Dry run: No files were sent to General Translation. Found files:\n${fileNames}`);
79
- return undefined;
80
- }
81
- // Send translations to General Translation
82
- let filesTranslationResponse;
83
- if (allFiles.length > 0) {
84
- filesTranslationResponse = await sendFiles(allFiles, options, settings);
85
- if (stage) {
86
- await updateVersions({
87
- configDirectory: settings.configDirectory,
88
- versionData: filesTranslationResponse.data,
89
- });
90
- }
91
- const { versionId } = filesTranslationResponse.data[TEMPLATE_FILE_ID];
92
- if (versionId) {
93
- await updateConfig({
94
- configFilepath: settings.config,
95
- _versionId: versionId,
96
- });
97
- }
98
- }
99
- return filesTranslationResponse;
100
- }
@@ -1,6 +0,0 @@
1
- import { SendFilesResult } from '../../api/sendFiles.js';
2
- import { TranslateFlags } from '../../types/index.js';
3
- import { Settings } from '../../types/index.js';
4
- export declare function handleTranslate(options: TranslateFlags, settings: Settings, filesTranslationResponse: SendFilesResult | undefined): Promise<void>;
5
- export declare function handleDownload(options: TranslateFlags, settings: Settings): Promise<void>;
6
- export declare function postProcessTranslations(settings: Settings): Promise<void>;
@@ -1,54 +0,0 @@
1
- import { checkFileTranslations } from '../../api/checkFileTranslations.js';
2
- import { createFileMapping } from '../../formats/files/fileMapping.js';
3
- import { logError } from '../../console/logging.js';
4
- import { getStagedVersions } from '../../fs/config/updateVersions.js';
5
- import copyFile from '../../fs/copyFile.js';
6
- import localizeStaticImports from '../../utils/localizeStaticImports.js';
7
- import flattenJsonFiles from '../../utils/flattenJsonFiles.js';
8
- import localizeStaticUrls from '../../utils/localizeStaticUrls.js';
9
- import { noFilesError, noVersionIdError } from '../../console/index.js';
10
- // Downloads translations that were completed
11
- export async function handleTranslate(options, settings, filesTranslationResponse) {
12
- if (filesTranslationResponse && settings.files) {
13
- const { resolvedPaths, placeholderPaths, transformPaths } = settings.files;
14
- const fileMapping = createFileMapping(resolvedPaths, placeholderPaths, transformPaths, settings.locales, settings.defaultLocale);
15
- const { data } = filesTranslationResponse;
16
- // Check for remaining translations
17
- await checkFileTranslations(data, settings.locales, options.timeout, (sourcePath, locale) => fileMapping[locale][sourcePath] ?? null, settings);
18
- }
19
- }
20
- // Downloads translations that were originally staged
21
- export async function handleDownload(options, settings) {
22
- if (!settings._versionId) {
23
- logError(noVersionIdError);
24
- process.exit(1);
25
- }
26
- if (!settings.files) {
27
- logError(noFilesError);
28
- process.exit(1);
29
- }
30
- // Files
31
- const { resolvedPaths, placeholderPaths, transformPaths } = settings.files;
32
- const fileMapping = createFileMapping(resolvedPaths, placeholderPaths, transformPaths, settings.locales, settings.defaultLocale);
33
- const stagedVersionData = await getStagedVersions(settings.configDirectory);
34
- // Check for remaining translations
35
- await checkFileTranslations(stagedVersionData, settings.locales, options.timeout, (sourcePath, locale) => fileMapping[locale][sourcePath] ?? null, settings);
36
- }
37
- export async function postProcessTranslations(settings) {
38
- // Localize static urls (/docs -> /[locale]/docs)
39
- if (settings.options?.experimentalLocalizeStaticUrls) {
40
- await localizeStaticUrls(settings);
41
- }
42
- // Localize static imports (/docs -> /[locale]/docs)
43
- if (settings.options?.experimentalLocalizeStaticImports) {
44
- await localizeStaticImports(settings);
45
- }
46
- // Flatten json files into a single file
47
- if (settings.options?.experimentalFlattenJsonFiles) {
48
- await flattenJsonFiles(settings);
49
- }
50
- // Copy files to the target locale
51
- if (settings.options?.copyFiles) {
52
- await copyFile(settings);
53
- }
54
- }
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function attachTranslateFlags(command: Command): Command;
3
- export declare function attachAdditionalReactTranslateFlags(command: Command): Command;
package/dist/cli/flags.js DELETED
@@ -1,37 +0,0 @@
1
- import findFilepath from '../fs/findFilepath.js';
2
- const DEFAULT_TIMEOUT = 600;
3
- export function attachTranslateFlags(command) {
4
- command
5
- .option('-c, --config <path>', 'Filepath to config file, by default gt.config.json', findFilepath(['gt.config.json']))
6
- .option('--api-key <key>', 'API key for General Translation cloud service')
7
- .option('--project-id <id>', 'General Translation project ID')
8
- .option('--version-id <id>', 'General Translation version ID')
9
- .option('--default-language, --default-locale <locale>', 'Default locale (e.g., en)')
10
- .option('--new, --locales <locales...>', 'Space-separated list of locales (e.g., en fr es)')
11
- .option('--dry-run', 'Dry run, do not send updates to the General Translation API', false)
12
- .option('--timeout <seconds>', 'Translation wait timeout in seconds', (value) => {
13
- const parsedValue = parseInt(value, 10);
14
- if (isNaN(parsedValue)) {
15
- throw new Error('Not a number.');
16
- }
17
- if (parsedValue < 0) {
18
- throw new Error('Timeout must be a positive number.');
19
- }
20
- return parsedValue;
21
- }, DEFAULT_TIMEOUT)
22
- .option('--publish', 'Publish translations to the CDN', false)
23
- .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)
24
- .option('--experimental-hide-default-locale', 'When localizing static locales, hide the default locale from the path', false)
25
- .option('--experimental-flatten-json-files', 'Triggering this will flatten the json files into a single file. This is useful for projects that have a lot of json files.', false)
26
- .option('--experimental-localize-static-imports', 'Triggering this will run a script after the cli tool that localizes all static imports in content files. Currently only supported for md and mdx files.', false);
27
- return command;
28
- }
29
- export function attachAdditionalReactTranslateFlags(command) {
30
- command
31
- .option('--tsconfig, --jsconfig <path>', 'Path to custom jsconfig or tsconfig file', findFilepath(['./tsconfig.json', './jsconfig.json']))
32
- .option('--dictionary <path>', 'Path to dictionary file')
33
- .option('--src <paths...>', "Space-separated list of glob patterns containing the app's source code, by default 'src/**/*.{js,jsx,ts,tsx}' 'app/**/*.{js,jsx,ts,tsx}' 'pages/**/*.{js,jsx,ts,tsx}' 'components/**/*.{js,jsx,ts,tsx}'")
34
- .option('--inline', 'Include inline <T> tags in addition to dictionary file', true)
35
- .option('--ignore-errors', 'Ignore errors encountered while scanning for <T> tags', false);
36
- return command;
37
- }
@@ -1,10 +0,0 @@
1
- type StagedVersionData = Record<string, {
2
- fileName: string;
3
- versionId: string;
4
- }>;
5
- export declare function updateVersions({ configDirectory, versionData, }: {
6
- configDirectory: string;
7
- versionData: StagedVersionData;
8
- }): Promise<void>;
9
- export declare function getStagedVersions(configDirectory: string): Promise<StagedVersionData>;
10
- export {};
@@ -1,30 +0,0 @@
1
- import fs from 'node:fs';
2
- import { displayUpdatedVersionsFile } from '../../console/logging.js';
3
- import { logError } from '../../console/logging.js';
4
- import path from 'node:path';
5
- const STAGED_VERSIONS_FILE = 'staged-versions.json';
6
- // Update the versions.json file with the new version ids
7
- // of the translations that were sent to the API
8
- export async function updateVersions({ configDirectory, versionData, }) {
9
- const versionFilepath = path.join(configDirectory, STAGED_VERSIONS_FILE);
10
- try {
11
- fs.mkdirSync(configDirectory, { recursive: true });
12
- fs.writeFileSync(versionFilepath, JSON.stringify(versionData, null, 2));
13
- // show update in console
14
- displayUpdatedVersionsFile(versionFilepath);
15
- }
16
- catch (error) {
17
- logError(`An error occurred while updating ${versionFilepath}: ${error}`);
18
- }
19
- }
20
- export async function getStagedVersions(configDirectory) {
21
- try {
22
- const versionFilepath = path.join(configDirectory, STAGED_VERSIONS_FILE);
23
- const versionData = JSON.parse(fs.readFileSync(versionFilepath, 'utf8'));
24
- return versionData;
25
- }
26
- catch (error) {
27
- logError(`An error occurred while getting staged versions: ${error}`);
28
- return {};
29
- }
30
- }
@@ -1 +0,0 @@
1
- export type FileMapping = Record<string, Record<string, string>>;
@@ -1 +0,0 @@
1
- export {};
@@ -1,6 +0,0 @@
1
- /**
2
- * Hashes a string using SHA-256 algorithm.
3
- * @param {string} string - The string to be hashed.
4
- * @returns {string} The hashed string.
5
- */
6
- export declare function hashStringSync(string: string): string;
@@ -1,11 +0,0 @@
1
- import crypto from 'crypto';
2
- /**
3
- * Hashes a string using SHA-256 algorithm.
4
- * @param {string} string - The string to be hashed.
5
- * @returns {string} The hashed string.
6
- */
7
- export function hashStringSync(string) {
8
- const hash = crypto.createHash('sha256');
9
- hash.update(string);
10
- return hash.digest('hex');
11
- }