gt 2.12.1 → 2.13.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/CHANGELOG.md +6 -0
- package/dist/config/defaults.d.ts +11 -0
- package/dist/config/defaults.js +13 -0
- package/dist/config/generateSettings.js +10 -2
- package/dist/console/index.d.ts +1 -0
- package/dist/console/index.js +1 -0
- package/dist/console/logging.d.ts +1 -0
- package/dist/console/logging.js +4 -0
- package/dist/fs/config/parseFilesConfig.d.ts +2 -12
- package/dist/fs/config/parseFilesConfig.js +17 -4
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/react/jsx/utils/parseStringFunction.js +44 -5
- package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.d.ts +4 -1
- package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.js +23 -2
- package/dist/react/jsx/utils/stringParsing/derivation/index.js +1 -0
- package/dist/react/jsx/utils/stringParsing/types.d.ts +7 -0
- package/dist/react/parse/createInlineUpdates.d.ts +2 -2
- package/dist/react/parse/createInlineUpdates.js +5 -3
- package/dist/translation/parse.d.ts +2 -2
- package/dist/translation/parse.js +2 -2
- package/dist/translation/stage.js +1 -1
- package/dist/translation/validate.js +2 -2
- package/dist/types/index.d.ts +13 -1
- package/dist/types/parsing.d.ts +43 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1141](https://github.com/generaltranslation/gt/pull/1141) [`4820643`](https://github.com/generaltranslation/gt/commit/4820643665d5aecacc34c52707c0c81bf4da18ca) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - feat: auto derive for the t() function
|
|
8
|
+
|
|
3
9
|
## 2.12.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseParsingFlags, GTParsingFlags } from '../types/parsing.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default parsing flags for GT files
|
|
4
|
+
* @property {boolean} autoDerive - Whether to enable auto-derive for the t() function. (true -> 'AUTO', false -> 'DISABLED' {@link ParsingConfig['autoDeriveMethod']})
|
|
5
|
+
* @property {boolean} includeSourceCodeContext - Include surrounding source code lines as context for translations.
|
|
6
|
+
*/
|
|
7
|
+
export declare const GT_PARSING_FLAGS_DEFAULT: GTParsingFlags;
|
|
8
|
+
/**
|
|
9
|
+
* Default parsing flags for all files
|
|
10
|
+
*/
|
|
11
|
+
export declare const BASE_PARSING_FLAGS_DEFAULT: BaseParsingFlags;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default parsing flags for GT files
|
|
3
|
+
* @property {boolean} autoDerive - Whether to enable auto-derive for the t() function. (true -> 'AUTO', false -> 'DISABLED' {@link ParsingConfig['autoDeriveMethod']})
|
|
4
|
+
* @property {boolean} includeSourceCodeContext - Include surrounding source code lines as context for translations.
|
|
5
|
+
*/
|
|
6
|
+
export const GT_PARSING_FLAGS_DEFAULT = {
|
|
7
|
+
autoDerive: true,
|
|
8
|
+
includeSourceCodeContext: false,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Default parsing flags for all files
|
|
12
|
+
*/
|
|
13
|
+
export const BASE_PARSING_FLAGS_DEFAULT = {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { displayProjectId, exitSync, logErrorAndExit, warnApiKeyInConfig, } from '../console/logging.js';
|
|
1
|
+
import { displayProjectId, exitSync, logErrorAndExit, warnApiKeyInConfig, warnDeprecatedField, } from '../console/logging.js';
|
|
2
2
|
import { loadConfig } from '../fs/config/loadConfig.js';
|
|
3
3
|
import { defaultBaseUrl, libraryDefaultLocale, } from 'generaltranslation/internal';
|
|
4
4
|
import fs from 'node:fs';
|
|
@@ -12,6 +12,7 @@ import chalk from 'chalk';
|
|
|
12
12
|
import { resolveConfig } from './resolveConfig.js';
|
|
13
13
|
import { gt } from '../utils/gt.js';
|
|
14
14
|
import { generatePreset } from './optionPresets.js';
|
|
15
|
+
import { GT_PARSING_FLAGS_DEFAULT } from './defaults.js';
|
|
15
16
|
export const DEFAULT_SRC_PATTERNS = [
|
|
16
17
|
'src/**/*.{js,jsx,ts,tsx}',
|
|
17
18
|
'app/**/*.{js,jsx,ts,tsx}',
|
|
@@ -85,6 +86,10 @@ export async function generateSettings(flags, cwd = process.cwd()) {
|
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
}
|
|
89
|
+
// Warn on deprecated includeSourceCodeContext
|
|
90
|
+
if (gtConfig.files?.gt?.includeSourceCodeContext != null) {
|
|
91
|
+
warnDeprecatedField('files.gt.includeSourceCodeContext', 'files.gt.parsingFlags.includeSourceCodeContext');
|
|
92
|
+
}
|
|
88
93
|
// merge options
|
|
89
94
|
const mergedOptions = { ...gtConfig, ...flags };
|
|
90
95
|
// Add defaultLocale if not provided
|
|
@@ -141,7 +146,10 @@ export async function generateSettings(flags, cwd = process.cwd()) {
|
|
|
141
146
|
transformPaths: {},
|
|
142
147
|
publishPaths: new Set(),
|
|
143
148
|
unpublishPaths: new Set(),
|
|
144
|
-
|
|
149
|
+
parsingFlags: {},
|
|
150
|
+
gtJson: {
|
|
151
|
+
parsingFlags: GT_PARSING_FLAGS_DEFAULT,
|
|
152
|
+
},
|
|
145
153
|
};
|
|
146
154
|
mergedOptions.options = {
|
|
147
155
|
...(mergedOptions.options || {}),
|
package/dist/console/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare const warnRecursiveFunctionCallSync: (file: string, functionName:
|
|
|
23
23
|
export declare const warnDeriveFunctionNotWrappedSync: (file: string, functionName: string, location?: string) => string;
|
|
24
24
|
export declare const warnDeriveNonConstVariableSync: (file: string, varName: string, kind: string, location?: string) => string;
|
|
25
25
|
export declare const warnDeriveFunctionNoResultsSync: (file: string, functionName: string, location?: string) => string;
|
|
26
|
+
export declare const warnAutoDeriveNoResultsSync: (file: string, expression: string, location?: string) => string;
|
|
26
27
|
export declare const warnDeriveUnresolvableValueSync: (file: string, key: string, location?: string) => string;
|
|
27
28
|
export declare const warnDeriveCircularSpreadSync: (file: string, varName: string, location?: string) => string;
|
|
28
29
|
export declare const warnDeriveDestructuringSync: (file: string, varName: string, location?: string) => string;
|
package/dist/console/index.js
CHANGED
|
@@ -34,6 +34,7 @@ export const warnRecursiveFunctionCallSync = (file, functionName, location) => w
|
|
|
34
34
|
export const warnDeriveFunctionNotWrappedSync = (file, functionName, location) => withLocation(file, withDeriveFunctionError(`Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. This call is not wrapped in derive() (formerly declareStatic()). Ensure the function is properly wrapped with derive() and does not have circular import dependencies.`), location);
|
|
35
35
|
export const warnDeriveNonConstVariableSync = (file, varName, kind, location) => withLocation(file, withDeriveFunctionError(`Variable ${colorizeFunctionName(varName)} is declared with '${kind}' but only 'const' declarations can be resolved statically. Change it to 'const'.`), location);
|
|
36
36
|
export const warnDeriveFunctionNoResultsSync = (file, functionName, location) => withLocation(file, withDeriveFunctionError(`Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. derive() (formerly declareStatic()) can only receive function invocations and cannot use undefined values or looped calls to construct its result.`), location);
|
|
37
|
+
export const warnAutoDeriveNoResultsSync = (file, expression, location) => withLocation(file, `Auto-derive could not resolve ${colorizeFunctionName(formatCodeClamp(expression))}. Only function calls with statically determinable return values can be used directly in t(). Consider wrapping with derive() for explicit derivation, or use an interpolation variable instead.`, location);
|
|
37
38
|
export const warnDeriveUnresolvableValueSync = (file, key, location) => withLocation(file, withDeriveFunctionError(`Object property ${colorizeFunctionName(formatCodeClamp(key))} could not be resolved to a static string value. Only string literals, template literals, conditionals, and function calls returning strings are supported.`), location);
|
|
38
39
|
export const warnDeriveCircularSpreadSync = (file, varName, location) => withLocation(file, withDeriveFunctionError(`Circular spread detected involving ${colorizeFunctionName(varName)}. Spread references that form a cycle cannot be resolved statically.`), location);
|
|
39
40
|
export const warnDeriveDestructuringSync = (file, varName, location) => withLocation(file, withDeriveFunctionError(`Variable ${colorizeFunctionName(varName)} uses destructuring syntax, which is not yet supported in derive(). Assign the value to a const variable directly instead.`), location);
|
|
@@ -45,6 +45,7 @@ export declare function warnNoId(file: string): void;
|
|
|
45
45
|
export declare function warnHasUnwrappedExpression(file: string, id: string, unwrappedExpressions: string[]): void;
|
|
46
46
|
export declare function warnTemplateLiteral(file: string, value: string): void;
|
|
47
47
|
export declare function warnTernary(file: string): void;
|
|
48
|
+
export declare function warnDeprecatedField(deprecatedField: string, replacement: string): void;
|
|
48
49
|
/**
|
|
49
50
|
* Helper: Log all collected files
|
|
50
51
|
*/
|
package/dist/console/logging.js
CHANGED
|
@@ -154,6 +154,10 @@ export function warnTernary(file) {
|
|
|
154
154
|
logger.warn(`Found ternary expression in ${chalk.cyan(file)}. ` +
|
|
155
155
|
chalk.white('A Branch component may be more appropriate here.'));
|
|
156
156
|
}
|
|
157
|
+
export function warnDeprecatedField(deprecatedField, replacement) {
|
|
158
|
+
logger.warn(`${chalk.green(deprecatedField)} is deprecated. ` +
|
|
159
|
+
chalk.white(`Use ${chalk.green(replacement)} instead.`));
|
|
160
|
+
}
|
|
157
161
|
/**
|
|
158
162
|
* Helper: Log all collected files
|
|
159
163
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FilesOptions, IncludePattern, ResolvedFiles,
|
|
1
|
+
import { FilesOptions, IncludePattern, ResolvedFiles, Settings, TransformOption } from '../../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Resolves the files from the files object
|
|
4
4
|
* Replaces [locale] with the actual locale in the files
|
|
@@ -25,17 +25,7 @@ export declare function normalizeIncludePatterns(patterns: IncludePattern[]): {
|
|
|
25
25
|
* @param files - The files object
|
|
26
26
|
* @returns The resolved files
|
|
27
27
|
*/
|
|
28
|
-
export declare function resolveFiles(files: FilesOptions, locale: string, locales: string[], cwd: string, compositePatterns?: string[]):
|
|
29
|
-
resolvedPaths: ResolvedFiles;
|
|
30
|
-
placeholderPaths: ResolvedFiles;
|
|
31
|
-
transformPaths: TransformFiles;
|
|
32
|
-
publishPaths: Set<string>;
|
|
33
|
-
unpublishPaths: Set<string>;
|
|
34
|
-
gtJson: {
|
|
35
|
-
publish?: boolean;
|
|
36
|
-
includeSourceCodeContext?: boolean;
|
|
37
|
-
};
|
|
38
|
-
};
|
|
28
|
+
export declare function resolveFiles(files: FilesOptions, locale: string, locales: string[], cwd: string, compositePatterns?: string[]): Settings['files'];
|
|
39
29
|
export declare function expandGlobPatterns(cwd: string, includePatterns: string[], excludePatterns: string[], locale: string, locales: string[], transformPatterns?: TransformOption | string | TransformOption[], compositePatterns?: string[]): {
|
|
40
30
|
resolvedPaths: string[];
|
|
41
31
|
placeholderPaths: string[];
|
|
@@ -4,6 +4,7 @@ import { SUPPORTED_FILE_EXTENSIONS } from '../../formats/files/supportedFiles.js
|
|
|
4
4
|
import { logger } from '../../console/logger.js';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import micromatch from 'micromatch';
|
|
7
|
+
import { BASE_PARSING_FLAGS_DEFAULT, GT_PARSING_FLAGS_DEFAULT, } from '../../config/defaults.js';
|
|
7
8
|
/**
|
|
8
9
|
* Resolves the files from the files object
|
|
9
10
|
* Replaces [locale] with the actual locale in the files
|
|
@@ -55,11 +56,12 @@ export function normalizeIncludePatterns(patterns) {
|
|
|
55
56
|
*/
|
|
56
57
|
export function resolveFiles(files, locale, locales, cwd, compositePatterns) {
|
|
57
58
|
// Initialize result object with empty arrays for each file type
|
|
58
|
-
const
|
|
59
|
+
const resolvedPaths = {};
|
|
59
60
|
const placeholderResult = {};
|
|
60
61
|
const transformPaths = {};
|
|
61
62
|
const publishPaths = new Set();
|
|
62
63
|
const unpublishPaths = new Set();
|
|
64
|
+
const parsingFlags = {};
|
|
63
65
|
// Process GT files
|
|
64
66
|
if (files.gt?.output) {
|
|
65
67
|
placeholderResult.gt = path.resolve(cwd, files.gt.output);
|
|
@@ -77,21 +79,32 @@ export function resolveFiles(files, locale, locales, cwd, compositePatterns) {
|
|
|
77
79
|
if (files[fileType]?.include) {
|
|
78
80
|
const { paths, publishPatterns, unpublishPatterns } = normalizeIncludePatterns(files[fileType].include);
|
|
79
81
|
const filePaths = expandGlobPatterns(cwd, paths, files[fileType]?.exclude || [], locale, locales, transformPaths[fileType] || undefined, compositePatterns);
|
|
80
|
-
|
|
82
|
+
resolvedPaths[fileType] = filePaths.resolvedPaths;
|
|
81
83
|
placeholderResult[fileType] = filePaths.placeholderPaths;
|
|
82
84
|
// Classify resolved paths into publish/unpublish sets
|
|
83
85
|
classifyPublishPaths(filePaths.resolvedPaths, publishPatterns, unpublishPatterns, cwd, locale, publishPaths, unpublishPaths);
|
|
84
86
|
}
|
|
87
|
+
// ==== OTHER ==== //
|
|
88
|
+
if (files[fileType]?.parsingFlags) {
|
|
89
|
+
parsingFlags[fileType] = {
|
|
90
|
+
...BASE_PARSING_FLAGS_DEFAULT,
|
|
91
|
+
...files[fileType].parsingFlags,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
85
94
|
}
|
|
86
95
|
return {
|
|
87
|
-
resolvedPaths
|
|
96
|
+
resolvedPaths,
|
|
88
97
|
placeholderPaths: placeholderResult,
|
|
89
98
|
transformPaths: transformPaths,
|
|
90
99
|
publishPaths,
|
|
91
100
|
unpublishPaths,
|
|
101
|
+
parsingFlags,
|
|
92
102
|
gtJson: {
|
|
93
103
|
publish: files.gt?.publish,
|
|
94
|
-
|
|
104
|
+
parsingFlags: {
|
|
105
|
+
...GT_PARSING_FLAGS_DEFAULT,
|
|
106
|
+
...(files.gt?.parsingFlags || {}),
|
|
107
|
+
},
|
|
95
108
|
},
|
|
96
109
|
};
|
|
97
110
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.13.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.
|
|
2
|
+
export const PACKAGE_VERSION = '2.13.0';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from '@babel/types';
|
|
2
|
-
import { INLINE_TRANSLATION_HOOK, INLINE_TRANSLATION_HOOK_ASYNC, INLINE_MESSAGE_HOOK, INLINE_MESSAGE_HOOK_ASYNC, STRING_REGISTRATION_FUNCS, T_GLOBAL_REGISTRATION_FUNCTION_MARKER, } from './constants.js';
|
|
2
|
+
import { INLINE_TRANSLATION_HOOK, INLINE_TRANSLATION_HOOK_ASYNC, INLINE_MESSAGE_HOOK, INLINE_MESSAGE_HOOK_ASYNC, STRING_REGISTRATION_FUNCS, T_GLOBAL_REGISTRATION_FUNCTION_MARKER, T_REGISTRATION_FUNCTION, } from './constants.js';
|
|
3
3
|
import { warnAsyncUseGT, warnSyncGetGT } from '../../../console/index.js';
|
|
4
4
|
import traverseModule from '@babel/traverse';
|
|
5
5
|
// Handle CommonJS/ESM interop
|
|
@@ -80,8 +80,8 @@ export function resolveVariableAliases(scope, variableName, visited = new Set())
|
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Handles how translation callbacks are used within code.
|
|
83
|
-
* This covers both direct translation calls (
|
|
84
|
-
* where the translation callback is passed to other functions (getData(
|
|
83
|
+
* This covers both direct translation calls (gt('hello')) and prop drilling
|
|
84
|
+
* where the translation callback is passed to other functions (getData(gt)).
|
|
85
85
|
*/
|
|
86
86
|
function handleFunctionCall(tPath, config, state, output) {
|
|
87
87
|
if (tPath.parent.type === 'CallExpression' &&
|
|
@@ -278,9 +278,16 @@ function processFunctionInFile(filePath, functionName, argIndex, config, state,
|
|
|
278
278
|
*/
|
|
279
279
|
export function parseStrings(importName, originalName, path, config, output) {
|
|
280
280
|
// Handle global t macro directly — path is already the tag identifier
|
|
281
|
+
// NOTE: if we decide to add support for a global t() function in addition to the macro,
|
|
282
|
+
// then we need to add support for skipDeriveInvocation here
|
|
281
283
|
if (originalName === T_GLOBAL_REGISTRATION_FUNCTION_MARKER) {
|
|
282
284
|
if (!config.ignoreGlobalTaggedTemplates) {
|
|
283
|
-
processTaggedTemplateCall(path,
|
|
285
|
+
processTaggedTemplateCall(path, {
|
|
286
|
+
...config,
|
|
287
|
+
autoDeriveMethod: config.autoDeriveMethod === 'AUTO'
|
|
288
|
+
? 'DISABLED'
|
|
289
|
+
: config.autoDeriveMethod,
|
|
290
|
+
}, output);
|
|
284
291
|
}
|
|
285
292
|
return;
|
|
286
293
|
}
|
|
@@ -300,11 +307,39 @@ export function parseStrings(importName, originalName, path, config, output) {
|
|
|
300
307
|
includeSourceCodeContext: config.includeSourceCodeContext,
|
|
301
308
|
ignoreTaggedTemplates: false,
|
|
302
309
|
ignoreGlobalTaggedTemplates: false,
|
|
310
|
+
// User configurable, otherwise default to AUTO
|
|
311
|
+
autoDeriveMethod: config.autoDeriveMethod === 'AUTO'
|
|
312
|
+
? 'DISABLED'
|
|
313
|
+
: config.autoDeriveMethod,
|
|
303
314
|
};
|
|
304
315
|
// Check if this is a direct call to msg('string') or t('string')
|
|
305
316
|
if (refPath.parent.type === 'CallExpression' &&
|
|
306
317
|
refPath.parent.callee === refPath.node) {
|
|
307
|
-
|
|
318
|
+
/**
|
|
319
|
+
* SPECIAL CASE: Auto-derive t() function
|
|
320
|
+
* The t() function, will treat variable content as if it was marked for derivation
|
|
321
|
+
* without explicit calls to derive().
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* const derivedValue = 'John';
|
|
325
|
+
* const interpolatedValue = "Ernest"
|
|
326
|
+
* t(
|
|
327
|
+
* "Hello, " + derivedValue + "! My name is {interpolatedValue}",
|
|
328
|
+
* { interpolatedValue }
|
|
329
|
+
* );
|
|
330
|
+
* // "Hello, John! My name is {interpolatedValue}"
|
|
331
|
+
*/
|
|
332
|
+
if (originalName === T_REGISTRATION_FUNCTION) {
|
|
333
|
+
processTranslationCall(refPath, config.autoDeriveMethod === 'AUTO'
|
|
334
|
+
? {
|
|
335
|
+
...stringRegistrationConfig,
|
|
336
|
+
autoDeriveMethod: 'ENABLED',
|
|
337
|
+
}
|
|
338
|
+
: stringRegistrationConfig, output);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
processTranslationCall(refPath, stringRegistrationConfig, output);
|
|
342
|
+
}
|
|
308
343
|
}
|
|
309
344
|
else if (!stringRegistrationConfig.ignoreTaggedTemplates &&
|
|
310
345
|
refPath.parent.type === 'TaggedTemplateExpression' &&
|
|
@@ -348,6 +383,10 @@ export function parseStrings(importName, originalName, path, config, output) {
|
|
|
348
383
|
includeSourceCodeContext: config.includeSourceCodeContext,
|
|
349
384
|
ignoreTaggedTemplates: false,
|
|
350
385
|
ignoreGlobalTaggedTemplates: false,
|
|
386
|
+
// User configurable, otherwise default to DISABLED
|
|
387
|
+
autoDeriveMethod: config.autoDeriveMethod === 'AUTO'
|
|
388
|
+
? 'DISABLED'
|
|
389
|
+
: config.autoDeriveMethod,
|
|
351
390
|
};
|
|
352
391
|
const effectiveParent = parentPath?.node.type === 'AwaitExpression'
|
|
353
392
|
? parentPath.parentPath
|
|
@@ -12,13 +12,15 @@ export type StringTree = (string | StringTree)[];
|
|
|
12
12
|
* @param parsingOptions - Parsing configuration
|
|
13
13
|
* @param errors - Errors to add to
|
|
14
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
|
+
* @param skipDeriveInvocation - If true, skip derive invocation check
|
|
15
16
|
* @returns Node | null - The parsed node, or null if invalid
|
|
16
17
|
*
|
|
17
18
|
* @note runtimeInterpolationState
|
|
18
19
|
* - Only provide at entry for template macros, otherwise omit
|
|
19
20
|
* - t`Hello {nonDerivableValue}` -> t`Hello {0}`
|
|
21
|
+
*
|
|
20
22
|
*/
|
|
21
|
-
export declare function handleDerivation({ expr, tPath, file, parsingOptions, errors, warnings, runtimeInterpolationState, }: {
|
|
23
|
+
export declare function handleDerivation({ expr, tPath, file, parsingOptions, errors, warnings, runtimeInterpolationState, skipDeriveInvocation, }: {
|
|
22
24
|
expr: t.Expression;
|
|
23
25
|
tPath: NodePath;
|
|
24
26
|
file: string;
|
|
@@ -28,4 +30,5 @@ export declare function handleDerivation({ expr, tPath, file, parsingOptions, er
|
|
|
28
30
|
runtimeInterpolationState?: {
|
|
29
31
|
index: number;
|
|
30
32
|
};
|
|
33
|
+
skipDeriveInvocation?: boolean;
|
|
31
34
|
}): StringNode | null;
|
|
@@ -4,7 +4,7 @@ import { buildImportMap } from '../../buildImportMap.js';
|
|
|
4
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';
|
|
7
|
+
import { warnFunctionNotFoundSync, warnDeriveFunctionNoResultsSync, warnDeriveFunctionNotWrappedSync, warnAutoDeriveNoResultsSync, } from '../../../../../console/index.js';
|
|
8
8
|
import traverseModule from '@babel/traverse';
|
|
9
9
|
import generateModule from '@babel/generator';
|
|
10
10
|
import { isDeriveCall } from './isDeriveCall.js';
|
|
@@ -32,13 +32,15 @@ const processFunctionCache = new Map();
|
|
|
32
32
|
* @param parsingOptions - Parsing configuration
|
|
33
33
|
* @param errors - Errors to add to
|
|
34
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.
|
|
35
|
+
* @param skipDeriveInvocation - If true, skip derive invocation check
|
|
35
36
|
* @returns Node | null - The parsed node, or null if invalid
|
|
36
37
|
*
|
|
37
38
|
* @note runtimeInterpolationState
|
|
38
39
|
* - Only provide at entry for template macros, otherwise omit
|
|
39
40
|
* - t`Hello {nonDerivableValue}` -> t`Hello {0}`
|
|
41
|
+
*
|
|
40
42
|
*/
|
|
41
|
-
export function handleDerivation({ expr, tPath, file, parsingOptions, errors, warnings, runtimeInterpolationState, }) {
|
|
43
|
+
export function handleDerivation({ expr, tPath, file, parsingOptions, errors, warnings, runtimeInterpolationState, skipDeriveInvocation, }) {
|
|
42
44
|
if (!expr) {
|
|
43
45
|
return null;
|
|
44
46
|
}
|
|
@@ -115,6 +117,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, wa
|
|
|
115
117
|
errors,
|
|
116
118
|
warnings,
|
|
117
119
|
runtimeInterpolationState,
|
|
120
|
+
skipDeriveInvocation,
|
|
118
121
|
});
|
|
119
122
|
if (result === null)
|
|
120
123
|
return null;
|
|
@@ -143,6 +146,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, wa
|
|
|
143
146
|
errors,
|
|
144
147
|
warnings,
|
|
145
148
|
runtimeInterpolationState,
|
|
149
|
+
skipDeriveInvocation,
|
|
146
150
|
});
|
|
147
151
|
const rightResult = handleDerivation({
|
|
148
152
|
expr: expr.right,
|
|
@@ -152,6 +156,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, wa
|
|
|
152
156
|
errors,
|
|
153
157
|
warnings,
|
|
154
158
|
runtimeInterpolationState,
|
|
159
|
+
skipDeriveInvocation,
|
|
155
160
|
});
|
|
156
161
|
if (leftResult === null || rightResult === null) {
|
|
157
162
|
return null;
|
|
@@ -168,6 +173,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, wa
|
|
|
168
173
|
errors,
|
|
169
174
|
warnings,
|
|
170
175
|
runtimeInterpolationState,
|
|
176
|
+
skipDeriveInvocation,
|
|
171
177
|
});
|
|
172
178
|
}
|
|
173
179
|
// Handle numeric literals by converting them to strings
|
|
@@ -204,6 +210,21 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, wa
|
|
|
204
210
|
if (t.isNullLiteral(expr)) {
|
|
205
211
|
return { type: 'text', text: 'null' };
|
|
206
212
|
}
|
|
213
|
+
// Non-static expression
|
|
214
|
+
if (skipDeriveInvocation) {
|
|
215
|
+
// Skip pass a `derive()` invocation to do derivation
|
|
216
|
+
const variants = resolveCallStringVariants(expr, tPath, file, parsingOptions, errors, warnings);
|
|
217
|
+
if (variants) {
|
|
218
|
+
return {
|
|
219
|
+
type: 'choice',
|
|
220
|
+
nodes: variants.map((v) => ({ type: 'text', text: v })),
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// Auto-derive had no resolvable results
|
|
224
|
+
const code = generate(expr).code;
|
|
225
|
+
errors.push(warnAutoDeriveNoResultsSync(file, code, `${expr.loc?.start?.line}:${expr.loc?.start?.column}`));
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
207
228
|
// Not a derivable expression
|
|
208
229
|
if (runtimeInterpolationState) {
|
|
209
230
|
return { type: 'text', text: `{${runtimeInterpolationState.index++}}` };
|
|
@@ -31,6 +31,7 @@ export function deriveExpression({ tPath, expr, metadata, config, output, index,
|
|
|
31
31
|
runtimeInterpolationState: enableRuntimeInterpolation
|
|
32
32
|
? { index: 0 }
|
|
33
33
|
: undefined,
|
|
34
|
+
skipDeriveInvocation: config.autoDeriveMethod === 'ENABLED',
|
|
34
35
|
});
|
|
35
36
|
// Nothing returned, push error
|
|
36
37
|
if (!stringNode) {
|
|
@@ -35,6 +35,13 @@ export type ParsingConfig = {
|
|
|
35
35
|
* If true, ignore global tagged template expressions (t`hello` without import)
|
|
36
36
|
*/
|
|
37
37
|
ignoreGlobalTaggedTemplates: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Skip requirement for a derive() invocation to trigger derivation
|
|
40
|
+
* - ENABLED: Always auto-derive
|
|
41
|
+
* - DISABLED: Never auto-derive
|
|
42
|
+
* - AUTO: Only auto-derive for the t() function
|
|
43
|
+
*/
|
|
44
|
+
autoDeriveMethod: 'ENABLED' | 'DISABLED' | 'AUTO';
|
|
38
45
|
};
|
|
39
46
|
/**
|
|
40
47
|
* Mutable state for tracking parsing progress.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Updates } from '../../types/index.js';
|
|
2
|
-
import type { ParsingConfigOptions } from '../../types/parsing.js';
|
|
2
|
+
import type { ParsingConfigOptions, GTParsingFlags } from '../../types/parsing.js';
|
|
3
3
|
import { GTLibrary } from '../../types/libraries.js';
|
|
4
4
|
import { dedupeUpdates } from '../../extraction/postProcess.js';
|
|
5
|
-
export declare function createInlineUpdates(pkg: GTLibrary, validate: boolean, filePatterns: string[] | undefined,
|
|
5
|
+
export declare function createInlineUpdates(pkg: GTLibrary, validate: boolean, filePatterns: string[] | undefined, parsingFlags: GTParsingFlags, parsingOptions: ParsingConfigOptions): Promise<{
|
|
6
6
|
updates: Updates;
|
|
7
7
|
errors: string[];
|
|
8
8
|
warnings: string[];
|
|
@@ -8,7 +8,7 @@ import { DEFAULT_SRC_PATTERNS } from '../../config/generateSettings.js';
|
|
|
8
8
|
import { getPathsAndAliases } from '../jsx/utils/getPathsAndAliases.js';
|
|
9
9
|
import { GT_LIBRARIES_UPSTREAM, REACT_LIBRARIES, } from '../../types/libraries.js';
|
|
10
10
|
import { calculateHashes, dedupeUpdates, linkDeriveUpdates, } from '../../extraction/postProcess.js';
|
|
11
|
-
export async function createInlineUpdates(pkg, validate, filePatterns,
|
|
11
|
+
export async function createInlineUpdates(pkg, validate, filePatterns, parsingFlags, parsingOptions) {
|
|
12
12
|
const updates = [];
|
|
13
13
|
const errors = [];
|
|
14
14
|
const warnings = new Set();
|
|
@@ -39,9 +39,11 @@ export async function createInlineUpdates(pkg, validate, filePatterns, parsingOp
|
|
|
39
39
|
ignoreDynamicContent: false,
|
|
40
40
|
ignoreInvalidIcu: false,
|
|
41
41
|
ignoreInlineListContent: false,
|
|
42
|
-
includeSourceCodeContext,
|
|
42
|
+
includeSourceCodeContext: parsingFlags.includeSourceCodeContext,
|
|
43
43
|
ignoreTaggedTemplates: false,
|
|
44
44
|
ignoreGlobalTaggedTemplates: false,
|
|
45
|
+
// User configurable, otherwise default to AUTO
|
|
46
|
+
autoDeriveMethod: parsingFlags.autoDerive ? 'AUTO' : 'DISABLED',
|
|
45
47
|
}, { updates, errors, warnings });
|
|
46
48
|
}
|
|
47
49
|
// Parse <T> components
|
|
@@ -57,7 +59,7 @@ export async function createInlineUpdates(pkg, validate, filePatterns, parsingOp
|
|
|
57
59
|
parsingOptions,
|
|
58
60
|
pkgs,
|
|
59
61
|
file,
|
|
60
|
-
includeSourceCodeContext,
|
|
62
|
+
includeSourceCodeContext: parsingFlags.includeSourceCodeContext,
|
|
61
63
|
},
|
|
62
64
|
output: {
|
|
63
65
|
errors,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Updates, TranslateFlags } from '../types/index.js';
|
|
2
|
-
import type { ParsingConfigOptions } from '../types/parsing.js';
|
|
2
|
+
import type { ParsingConfigOptions, GTParsingFlags } from '../types/parsing.js';
|
|
3
3
|
import { InlineLibrary } from '../types/libraries.js';
|
|
4
4
|
/**
|
|
5
5
|
* Searches for gt-react or gt-next dictionary files and creates updates for them,
|
|
@@ -10,7 +10,7 @@ import { InlineLibrary } from '../types/libraries.js';
|
|
|
10
10
|
* @param pkg - The package name
|
|
11
11
|
* @returns An object containing the updates and errors
|
|
12
12
|
*/
|
|
13
|
-
export declare function createUpdates(options: TranslateFlags, src: string[] | undefined, sourceDictionary: string | undefined, pkg: InlineLibrary, validate: boolean,
|
|
13
|
+
export declare function createUpdates(options: TranslateFlags, src: string[] | undefined, sourceDictionary: string | undefined, pkg: InlineLibrary, validate: boolean, parsingFlags: GTParsingFlags, parsingOptions: ParsingConfigOptions): Promise<{
|
|
14
14
|
updates: Updates;
|
|
15
15
|
errors: string[];
|
|
16
16
|
warnings: string[];
|
|
@@ -17,7 +17,7 @@ import { isPythonLibrary } from '../types/libraries.js';
|
|
|
17
17
|
* @param pkg - The package name
|
|
18
18
|
* @returns An object containing the updates and errors
|
|
19
19
|
*/
|
|
20
|
-
export async function createUpdates(options, src, sourceDictionary, pkg, validate,
|
|
20
|
+
export async function createUpdates(options, src, sourceDictionary, pkg, validate, parsingFlags, parsingOptions) {
|
|
21
21
|
let updates = [];
|
|
22
22
|
let errors = [];
|
|
23
23
|
let warnings = [];
|
|
@@ -53,7 +53,7 @@ export async function createUpdates(options, src, sourceDictionary, pkg, validat
|
|
|
53
53
|
// Scan through project for translatable content
|
|
54
54
|
const { updates: newUpdates, errors: newErrors, warnings: newWarnings, } = isPythonLibrary(pkg)
|
|
55
55
|
? await createPythonInlineUpdates(src)
|
|
56
|
-
: await createInlineUpdates(pkg, validate, src,
|
|
56
|
+
: await createInlineUpdates(pkg, validate, src, parsingFlags, parsingOptions);
|
|
57
57
|
errors = [...errors, ...newErrors];
|
|
58
58
|
warnings = [...warnings, ...newWarnings];
|
|
59
59
|
updates = [...updates, ...newUpdates];
|
|
@@ -15,7 +15,7 @@ export async function aggregateInlineTranslations(options, settings, library) {
|
|
|
15
15
|
]);
|
|
16
16
|
}
|
|
17
17
|
// ---- CREATING UPDATES ---- //
|
|
18
|
-
const { updates, errors, warnings } = await createUpdates(options, settings.src, options.dictionary, library, false, settings.
|
|
18
|
+
const { updates, errors, warnings } = await createUpdates(options, settings.src, options.dictionary, library, false, settings.files.gtJson.parsingFlags, settings.parsingOptions);
|
|
19
19
|
if (warnings.length > 0) {
|
|
20
20
|
logger.warn(chalk.yellow(`CLI tool encountered ${warnings.length} warnings while scanning for translatable content.\n` +
|
|
21
21
|
warnings
|
|
@@ -10,7 +10,7 @@ import { Libraries } from '../types/libraries.js';
|
|
|
10
10
|
*/
|
|
11
11
|
async function runValidation(settings, pkg, files) {
|
|
12
12
|
if (files && files.length > 0) {
|
|
13
|
-
return createInlineUpdates(pkg, true, files, settings.
|
|
13
|
+
return createInlineUpdates(pkg, true, files, settings.files.gtJson.parsingFlags, settings.parsingOptions);
|
|
14
14
|
}
|
|
15
15
|
// Full project validation
|
|
16
16
|
// Use local variable to avoid mutating caller's settings object
|
|
@@ -23,7 +23,7 @@ async function runValidation(settings, pkg, files) {
|
|
|
23
23
|
'./dictionary.ts',
|
|
24
24
|
'./src/dictionary.ts',
|
|
25
25
|
]);
|
|
26
|
-
return createUpdates(settings, settings.src, dictionary, pkg, true, settings.
|
|
26
|
+
return createUpdates(settings, settings.src, dictionary, pkg, true, settings.files.gtJson.parsingFlags, settings.parsingOptions);
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Parse file path from error/warning string in withLocation format: "filepath (line:col): message"
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CustomMapping } from 'generaltranslation/types';
|
|
2
2
|
import { SUPPORTED_FILE_EXTENSIONS } from '../formats/files/supportedFiles.js';
|
|
3
|
-
import { ParsingConfigOptions } from './parsing.js';
|
|
3
|
+
import { ParsingConfigOptions, GTParsingFlags, BaseParsingFlags, ParseFlagsByFileType } from './parsing.js';
|
|
4
4
|
import { Libraries, InlineLibrary } from './libraries.js';
|
|
5
5
|
export type { Updates } from 'generaltranslation/types';
|
|
6
6
|
export type Options = {
|
|
@@ -142,11 +142,17 @@ export type FilesOptions = {
|
|
|
142
142
|
include: IncludePattern[];
|
|
143
143
|
exclude?: string[];
|
|
144
144
|
transform?: string | TransformOption | TransformOption[];
|
|
145
|
+
parsingFlags?: BaseParsingFlags;
|
|
145
146
|
};
|
|
146
147
|
} & {
|
|
147
148
|
gt?: {
|
|
148
149
|
output: string;
|
|
149
150
|
publish?: boolean;
|
|
151
|
+
parsingFlags?: Partial<GTParsingFlags>;
|
|
152
|
+
/**
|
|
153
|
+
* @deprecated
|
|
154
|
+
* use `files.gt.parsingFlags.includeSourceCodeContext` instead
|
|
155
|
+
*/
|
|
150
156
|
includeSourceCodeContext?: boolean;
|
|
151
157
|
};
|
|
152
158
|
};
|
|
@@ -166,8 +172,14 @@ export type Settings = {
|
|
|
166
172
|
transformPaths: TransformFiles;
|
|
167
173
|
publishPaths: Set<string>;
|
|
168
174
|
unpublishPaths: Set<string>;
|
|
175
|
+
parsingFlags: ParseFlagsByFileType;
|
|
169
176
|
gtJson: {
|
|
170
177
|
publish?: boolean;
|
|
178
|
+
parsingFlags: GTParsingFlags;
|
|
179
|
+
/**
|
|
180
|
+
* @deprecated
|
|
181
|
+
* use {@link files.gt.GTParsingFlags.parsingFlags.includeSourceCodeContext} instead
|
|
182
|
+
*/
|
|
171
183
|
includeSourceCodeContext?: boolean;
|
|
172
184
|
};
|
|
173
185
|
};
|
package/dist/types/parsing.d.ts
CHANGED
|
@@ -1,3 +1,46 @@
|
|
|
1
|
+
import { SupportedFileExtension } from './index.js';
|
|
2
|
+
/**
|
|
3
|
+
* For monorepo projects, checking for extra exports fields in resolved internal packages.
|
|
4
|
+
* For instance, an exported path may be labeled as 'browser' or 'module' or 'default'.
|
|
5
|
+
* These can resolve to different files in the compiled package. This helps us know
|
|
6
|
+
* which files to check when we do resolution.
|
|
7
|
+
*
|
|
8
|
+
* @property conditionNames - The condition names to check for in the resolved package.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* {
|
|
12
|
+
* conditionNames: ['development', 'browser', 'module', 'import', 'require', 'default']
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
1
15
|
export type ParsingConfigOptions = {
|
|
2
16
|
conditionNames: string[];
|
|
3
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Base parsing flags for all files.
|
|
20
|
+
* Currently no supported properties
|
|
21
|
+
*
|
|
22
|
+
* Future ideas for flags:
|
|
23
|
+
* - flag for extraction of file name
|
|
24
|
+
* - flag for extraction of last modified timestamp
|
|
25
|
+
* - flag for extraction of git history
|
|
26
|
+
*/
|
|
27
|
+
export type BaseParsingFlags = Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* Flags for parsing content. Not to be confused with ParsingConfig which helps us enable/disable
|
|
30
|
+
* parsing features depending on the function being parsed. Parsing flags is for users to override
|
|
31
|
+
* some of these defaults or enable/disable other features.
|
|
32
|
+
*
|
|
33
|
+
* @property {boolean} autoDerive - Whether to enable auto-derive for the t() function. (true -> 'AUTO', false -> 'DISABLED' {@link ParsingConfig['autoDeriveMethod']})
|
|
34
|
+
* @property {boolean} includeSourceCodeContext - Include surrounding source code lines as context for translations.
|
|
35
|
+
*/
|
|
36
|
+
export type GTParsingFlags = BaseParsingFlags & {
|
|
37
|
+
autoDerive: boolean;
|
|
38
|
+
includeSourceCodeContext: boolean;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Flags for parsing content with each filetype having its own flags
|
|
42
|
+
* This is really a helper type that helps us map across filetypes
|
|
43
|
+
*/
|
|
44
|
+
export type ParseFlagsByFileType = {
|
|
45
|
+
[K in SupportedFileExtension]?: BaseParsingFlags;
|
|
46
|
+
};
|