gtx-cli 2.0.22 → 2.0.23-alpha.0
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/dist/cli/base.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export type TranslateOptions = {
|
|
|
17
17
|
experimentalHideDefaultLocale?: boolean;
|
|
18
18
|
experimentalFlattenJsonFiles?: boolean;
|
|
19
19
|
experimentalLocalizeStaticImports?: boolean;
|
|
20
|
+
experimentalExcludeStaticUrls?: string[];
|
|
20
21
|
};
|
|
21
22
|
export type LoginOptions = {
|
|
22
23
|
keyType?: 'development' | 'production';
|
|
@@ -109,10 +109,14 @@ export async function generateSettings(options, cwd = process.cwd()) {
|
|
|
109
109
|
: undefined;
|
|
110
110
|
mergedOptions = {
|
|
111
111
|
...mergedOptions,
|
|
112
|
-
experimentalLocalizeStaticImports: gtConfig.options?.experimentalLocalizeStaticImports
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
experimentalLocalizeStaticImports: gtConfig.options?.experimentalLocalizeStaticImports ||
|
|
113
|
+
options.experimentalLocalizeStaticImports,
|
|
114
|
+
experimentalLocalizeStaticUrls: gtConfig.options?.experimentalLocalizeStaticUrls ||
|
|
115
|
+
options.experimentalLocalizeStaticUrls,
|
|
116
|
+
experimentalHideDefaultLocale: gtConfig.options?.experimentalHideDefaultLocale ||
|
|
117
|
+
options.experimentalHideDefaultLocale,
|
|
118
|
+
experimentalFlattenJsonFiles: gtConfig.options?.experimentalFlattenJsonFiles ||
|
|
119
|
+
options.experimentalFlattenJsonFiles,
|
|
116
120
|
};
|
|
117
121
|
// Add additional options if provided
|
|
118
122
|
if (mergedOptions.options) {
|
|
@@ -2,8 +2,8 @@ import { getLocaleProperties } from 'generaltranslation';
|
|
|
2
2
|
import { exit, logError } from '../../console/logging.js';
|
|
3
3
|
import { JSONPath } from 'jsonpath-plus';
|
|
4
4
|
import { flattenJson } from './flattenJson.js';
|
|
5
|
-
import micromatch from 'micromatch';
|
|
6
5
|
import path from 'node:path';
|
|
6
|
+
import micromatch from 'micromatch';
|
|
7
7
|
const { isMatch } = micromatch;
|
|
8
8
|
// Find the matching source item in an array
|
|
9
9
|
// where the key matches the identifying locale property
|
package/dist/types/index.d.ts
CHANGED
|
@@ -114,6 +114,8 @@ export type AdditionalOptions = {
|
|
|
114
114
|
experimentalLocalizeStaticUrls?: boolean;
|
|
115
115
|
experimentalHideDefaultLocale?: boolean;
|
|
116
116
|
experimentalFlattenJsonFiles?: boolean;
|
|
117
|
+
experimentalExcludeStaticUrls?: string[];
|
|
118
|
+
experimentalExcludeStaticImports?: string[];
|
|
117
119
|
};
|
|
118
120
|
export type JsonSchema = {
|
|
119
121
|
preset?: 'mintlify';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import { createFileMapping } from '../formats/files/fileMapping.js';
|
|
3
3
|
import { logError } from '../console/logging.js';
|
|
4
|
+
import micromatch from 'micromatch';
|
|
5
|
+
const { isMatch } = micromatch;
|
|
4
6
|
/**
|
|
5
7
|
* Localizes static imports in content files.
|
|
6
8
|
* Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
|
|
@@ -31,38 +33,52 @@ export default async function localizeStaticImports(settings) {
|
|
|
31
33
|
// Get file content
|
|
32
34
|
const fileContent = await fs.promises.readFile(filePath, 'utf8');
|
|
33
35
|
// Localize the file
|
|
34
|
-
const localizedFile = localizeStaticImportsForFile(fileContent, settings.defaultLocale, locale, settings.options?.docsHideDefaultLocaleImport || false, settings.options?.docsImportPattern);
|
|
36
|
+
const localizedFile = localizeStaticImportsForFile(fileContent, settings.defaultLocale, locale, settings.options?.docsHideDefaultLocaleImport || false, settings.options?.docsImportPattern, settings.options?.experimentalExcludeStaticImports);
|
|
35
37
|
// Write the localized file to the target path
|
|
36
38
|
await fs.promises.writeFile(filePath, localizedFile);
|
|
37
39
|
}));
|
|
38
40
|
}));
|
|
39
41
|
}
|
|
40
42
|
// Naive find and replace, in the future, construct an AST
|
|
41
|
-
function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]' // eg /docs/[locale] or /[locale]
|
|
42
|
-
) {
|
|
43
|
+
function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
|
|
44
|
+
exclude = []) {
|
|
43
45
|
if (!pattern.startsWith('/')) {
|
|
44
46
|
pattern = '/' + pattern;
|
|
45
47
|
}
|
|
46
48
|
// 1. Search for all instances of:
|
|
47
49
|
const patternHead = pattern.split('[locale]')[0];
|
|
50
|
+
// Escape special regex characters and remove trailing slash if present
|
|
51
|
+
const escapedPatternHead = patternHead
|
|
52
|
+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
53
|
+
.replace(/\/$/, '');
|
|
48
54
|
let regex;
|
|
49
55
|
if (hideDefaultLocale) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
: patternHead;
|
|
53
|
-
// Match complete markdown links: `import { Foo } from '@/docs/[locale]/foo.md'`
|
|
54
|
-
regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${trimmedPatternHead}(.*?)\\2`, 'g');
|
|
56
|
+
// Match complete import statements: `import { Foo } from '/docs/foo.md'`
|
|
57
|
+
regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${escapedPatternHead}(?:/([^"']*?))?\\2`, 'g');
|
|
55
58
|
}
|
|
56
59
|
else {
|
|
57
|
-
// Match complete
|
|
58
|
-
regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${
|
|
60
|
+
// Match complete import statements with default locale: `import { Foo } from '/docs/${defaultLocale}/foo.md'`
|
|
61
|
+
regex = new RegExp(`import\\s+(.*?)\\s+from\\s+(["'])${escapedPatternHead}/${defaultLocale}(?:/([^"']*?))?\\2`, 'g');
|
|
59
62
|
}
|
|
60
63
|
const matches = file.match(regex);
|
|
61
64
|
if (!matches) {
|
|
62
65
|
return file;
|
|
63
66
|
}
|
|
67
|
+
exclude = exclude.map((pattern) => pattern.replace(/\[locale\]/g, defaultLocale));
|
|
64
68
|
// 2. Replace the default locale with the target locale in all matched instances
|
|
65
69
|
const localizedFile = file.replace(regex, (match, bindings, quoteType, pathContent) => {
|
|
70
|
+
// Check if this path should be excluded from localization
|
|
71
|
+
if (exclude.length > 0) {
|
|
72
|
+
let matchPath = patternHead;
|
|
73
|
+
if (pathContent) {
|
|
74
|
+
matchPath = hideDefaultLocale
|
|
75
|
+
? `${patternHead}${pathContent}`
|
|
76
|
+
: `${patternHead}${defaultLocale}/${pathContent}`;
|
|
77
|
+
}
|
|
78
|
+
if (exclude.some((pattern) => isMatch(matchPath, pattern))) {
|
|
79
|
+
return match; // Don't localize excluded paths
|
|
80
|
+
}
|
|
81
|
+
}
|
|
66
82
|
// get the quote type
|
|
67
83
|
quoteType = match.match(/["']/)?.[0] || '"';
|
|
68
84
|
if (!quoteType) {
|
|
@@ -81,12 +97,12 @@ function localizeStaticImportsForFile(file, defaultLocale, targetLocale, hideDef
|
|
|
81
97
|
if (!pathContent || pathContent === '') {
|
|
82
98
|
return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${quoteType}`;
|
|
83
99
|
}
|
|
84
|
-
return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}
|
|
100
|
+
return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}/${pathContent}${quoteType}`;
|
|
85
101
|
}
|
|
86
102
|
else {
|
|
87
103
|
// For non-hideDefaultLocale, replace defaultLocale with targetLocale
|
|
88
104
|
// pathContent contains everything after the default locale (no leading slash if present)
|
|
89
|
-
return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${pathContent}${quoteType}`;
|
|
105
|
+
return `import ${bindings} from ${quoteType}${patternHead}${targetLocale}${pathContent ? '/' + pathContent : ''}${quoteType}`;
|
|
90
106
|
}
|
|
91
107
|
});
|
|
92
108
|
return localizedFile;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import { createFileMapping } from '../formats/files/fileMapping.js';
|
|
3
|
+
import micromatch from 'micromatch';
|
|
4
|
+
const { isMatch } = micromatch;
|
|
3
5
|
/**
|
|
4
6
|
* Localizes static urls in content files.
|
|
5
7
|
* Currently only supported for md and mdx files. (/docs/ -> /[locale]/docs/)
|
|
@@ -30,16 +32,16 @@ export default async function localizeStaticUrls(settings) {
|
|
|
30
32
|
// Get file content
|
|
31
33
|
const fileContent = await fs.promises.readFile(filePath, 'utf8');
|
|
32
34
|
// Localize the file
|
|
33
|
-
const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern);
|
|
34
|
-
const localizedFileHrefs = localizeStaticHrefsForFile(localizedFile, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern);
|
|
35
|
+
const localizedFile = localizeStaticUrlsForFile(fileContent, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.experimentalExcludeStaticUrls);
|
|
36
|
+
const localizedFileHrefs = localizeStaticHrefsForFile(localizedFile, settings.defaultLocale, locale, settings.experimentalHideDefaultLocale || false, settings.options?.docsUrlPattern, settings.options?.experimentalExcludeStaticUrls);
|
|
35
37
|
// Write the localized file to the target path
|
|
36
38
|
await fs.promises.writeFile(filePath, localizedFileHrefs);
|
|
37
39
|
}));
|
|
38
40
|
}));
|
|
39
41
|
}
|
|
40
42
|
// Naive find and replace, in the future, construct an AST
|
|
41
|
-
function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]' // eg /docs/[locale] or /[locale]
|
|
42
|
-
) {
|
|
43
|
+
function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
|
|
44
|
+
exclude = []) {
|
|
43
45
|
if (!pattern.startsWith('/')) {
|
|
44
46
|
pattern = '/' + pattern;
|
|
45
47
|
}
|
|
@@ -62,8 +64,21 @@ function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaul
|
|
|
62
64
|
if (!matches) {
|
|
63
65
|
return file;
|
|
64
66
|
}
|
|
67
|
+
exclude = exclude.map((pattern) => pattern.replace(/\[locale\]/g, defaultLocale));
|
|
65
68
|
// 2. Replace the default locale with the target locale in all matched instances
|
|
66
69
|
const localizedFile = file.replace(regex, (match, pathContent) => {
|
|
70
|
+
if (exclude.length > 0) {
|
|
71
|
+
// Check if this path should be excluded from localization
|
|
72
|
+
let matchPath = patternHead;
|
|
73
|
+
if (pathContent) {
|
|
74
|
+
matchPath = hideDefaultLocale
|
|
75
|
+
? `${patternHead}${pathContent}`
|
|
76
|
+
: `${patternHead}${defaultLocale}/${pathContent}`;
|
|
77
|
+
}
|
|
78
|
+
if (exclude.some((pattern) => isMatch(matchPath, pattern))) {
|
|
79
|
+
return match; // Don't localize excluded paths
|
|
80
|
+
}
|
|
81
|
+
}
|
|
67
82
|
if (hideDefaultLocale) {
|
|
68
83
|
// For hideDefaultLocale, check if path already has target locale
|
|
69
84
|
if (pathContent) {
|
|
@@ -81,13 +96,14 @@ function localizeStaticUrlsForFile(file, defaultLocale, targetLocale, hideDefaul
|
|
|
81
96
|
else {
|
|
82
97
|
// For non-hideDefaultLocale, replace defaultLocale with targetLocale
|
|
83
98
|
// pathContent contains everything after the default locale (no leading slash if present)
|
|
84
|
-
|
|
99
|
+
const result = `](${patternHead}${targetLocale}${pathContent ? '/' + pathContent : ''})`;
|
|
100
|
+
return result;
|
|
85
101
|
}
|
|
86
102
|
});
|
|
87
103
|
return localizedFile;
|
|
88
104
|
}
|
|
89
|
-
function localizeStaticHrefsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]' // eg /docs/[locale] or /[locale]
|
|
90
|
-
) {
|
|
105
|
+
function localizeStaticHrefsForFile(file, defaultLocale, targetLocale, hideDefaultLocale, pattern = '/[locale]', // eg /docs/[locale] or /[locale]
|
|
106
|
+
exclude = []) {
|
|
91
107
|
if (!pattern.startsWith('/')) {
|
|
92
108
|
pattern = '/' + pattern;
|
|
93
109
|
}
|
|
@@ -110,8 +126,21 @@ function localizeStaticHrefsForFile(file, defaultLocale, targetLocale, hideDefau
|
|
|
110
126
|
if (!matches) {
|
|
111
127
|
return file;
|
|
112
128
|
}
|
|
129
|
+
exclude = exclude.map((pattern) => pattern.replace(/\[locale\]/g, defaultLocale));
|
|
113
130
|
// 2. Replace the default locale with the target locale in all matched instances
|
|
114
131
|
const localizedFile = file.replace(regex, (match, pathContent) => {
|
|
132
|
+
// Check if this path should be excluded from localization
|
|
133
|
+
if (exclude.length > 0) {
|
|
134
|
+
let matchPath = patternHead;
|
|
135
|
+
if (pathContent) {
|
|
136
|
+
matchPath = hideDefaultLocale
|
|
137
|
+
? `${patternHead}${pathContent}`
|
|
138
|
+
: `${patternHead}${defaultLocale}/${pathContent}`;
|
|
139
|
+
}
|
|
140
|
+
if (exclude.some((pattern) => isMatch(matchPath, pattern))) {
|
|
141
|
+
return match; // Don't localize excluded paths
|
|
142
|
+
}
|
|
143
|
+
}
|
|
115
144
|
if (hideDefaultLocale) {
|
|
116
145
|
// For hideDefaultLocale, check if path already has target locale
|
|
117
146
|
if (pathContent) {
|