@babelize/engine 0.0.0-stage → 0.1.2
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/LICENSE +202 -0
- package/dist/BabelizeEngine.d.ts +12 -0
- package/dist/BabelizeEngine.js +47 -0
- package/dist/analysis/analyze.d.ts +106 -0
- package/dist/analysis/analyze.js +323 -0
- package/dist/config/env.d.ts +9 -0
- package/dist/config/env.js +16 -0
- package/dist/config.d.ts +74 -0
- package/dist/config.js +47 -0
- package/dist/detection/stack.d.ts +42 -0
- package/dist/detection/stack.js +277 -0
- package/dist/django/catalog.d.ts +92 -0
- package/dist/django/catalog.js +677 -0
- package/dist/django/extract.d.ts +20 -0
- package/dist/django/extract.js +79 -0
- package/dist/django/inject-file.d.ts +6 -0
- package/dist/django/inject-file.js +52 -0
- package/dist/django/inject.d.ts +11 -0
- package/dist/django/inject.js +205 -0
- package/dist/django/keys.d.ts +21 -0
- package/dist/django/keys.js +63 -0
- package/dist/django/locale-names.d.ts +13 -0
- package/dist/django/locale-names.js +60 -0
- package/dist/django/mo-file.d.ts +6 -0
- package/dist/django/mo-file.js +60 -0
- package/dist/django/plural-forms.d.ts +34 -0
- package/dist/django/plural-forms.js +216 -0
- package/dist/django/po-file.d.ts +38 -0
- package/dist/django/po-file.js +273 -0
- package/dist/django/python-extract.d.ts +34 -0
- package/dist/django/python-extract.js +619 -0
- package/dist/django/python-lexer.d.ts +65 -0
- package/dist/django/python-lexer.js +398 -0
- package/dist/django/template-extract.d.ts +32 -0
- package/dist/django/template-extract.js +680 -0
- package/dist/django/types.d.ts +49 -0
- package/dist/django/types.js +15 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +140 -0
- package/dist/injection/InjectionStrategy.d.ts +62 -0
- package/dist/injection/InjectionStrategy.js +2 -0
- package/dist/injection/StrategyFactory.d.ts +4 -0
- package/dist/injection/StrategyFactory.js +29 -0
- package/dist/injection/html/html-injector.d.ts +11 -0
- package/dist/injection/html/html-injector.js +173 -0
- package/dist/injection/strategies/NextIntlStrategy.d.ts +25 -0
- package/dist/injection/strategies/NextIntlStrategy.js +141 -0
- package/dist/injection/strategies/ReactI18nextStrategy.d.ts +19 -0
- package/dist/injection/strategies/ReactI18nextStrategy.js +116 -0
- package/dist/injection/strategies/VanillaStrategy.d.ts +11 -0
- package/dist/injection/strategies/VanillaStrategy.js +73 -0
- package/dist/injection/strategies/VueI18nStrategy.d.ts +11 -0
- package/dist/injection/strategies/VueI18nStrategy.js +84 -0
- package/dist/local/formatter.d.ts +26 -0
- package/dist/local/formatter.js +105 -0
- package/dist/local/git.d.ts +23 -0
- package/dist/local/git.js +136 -0
- package/dist/local/hosted-provider.d.ts +68 -0
- package/dist/local/hosted-provider.js +215 -0
- package/dist/local/index.d.ts +23 -0
- package/dist/local/index.js +75 -0
- package/dist/local/provider.d.ts +56 -0
- package/dist/local/provider.js +119 -0
- package/dist/local/pseudo-provider.d.ts +18 -0
- package/dist/local/pseudo-provider.js +208 -0
- package/dist/local/report.d.ts +177 -0
- package/dist/local/report.js +186 -0
- package/dist/local/translate-core.d.ts +218 -0
- package/dist/local/translate-core.js +499 -0
- package/dist/local/translate-messages.d.ts +49 -0
- package/dist/local/translate-messages.js +89 -0
- package/dist/local/workspace-copy.d.ts +91 -0
- package/dist/local/workspace-copy.js +355 -0
- package/dist/modules/extractor/extract.d.ts +20 -0
- package/dist/modules/extractor/extract.js +709 -0
- package/dist/modules/extractor/index.d.ts +2 -0
- package/dist/modules/extractor/index.js +63 -0
- package/dist/modules/finalization/django-finalize.d.ts +28 -0
- package/dist/modules/finalization/django-finalize.js +412 -0
- package/dist/modules/finalization/finalize.d.ts +38 -0
- package/dist/modules/finalization/finalize.js +745 -0
- package/dist/modules/finalization/index.d.ts +1 -0
- package/dist/modules/finalization/index.js +5 -0
- package/dist/modules/finalization/nextjs-finalize.d.ts +40 -0
- package/dist/modules/finalization/nextjs-finalize.js +328 -0
- package/dist/modules/finalization/static-runtime.d.ts +9 -0
- package/dist/modules/finalization/static-runtime.js +261 -0
- package/dist/modules/finalization/writes.d.ts +29 -0
- package/dist/modules/finalization/writes.js +78 -0
- package/dist/modules/format-injection/index.d.ts +19 -0
- package/dist/modules/format-injection/index.js +273 -0
- package/dist/modules/format-injection/inject-formats.d.ts +31 -0
- package/dist/modules/format-injection/inject-formats.js +208 -0
- package/dist/modules/glossary/index.d.ts +2 -0
- package/dist/modules/glossary/index.js +16 -0
- package/dist/modules/glossary/rules.d.ts +81 -0
- package/dist/modules/glossary/rules.js +244 -0
- package/dist/modules/glossary/types.d.ts +22 -0
- package/dist/modules/glossary/types.js +2 -0
- package/dist/modules/injection/index.d.ts +1 -0
- package/dist/modules/injection/index.js +6 -0
- package/dist/modules/injection/inject.d.ts +29 -0
- package/dist/modules/injection/inject.js +1050 -0
- package/dist/modules/keygen/index.d.ts +1 -0
- package/dist/modules/keygen/index.js +11 -0
- package/dist/modules/keygen/keygen.d.ts +4 -0
- package/dist/modules/keygen/keygen.js +123 -0
- package/dist/modules/keygen/locale-data.d.ts +7 -0
- package/dist/modules/keygen/locale-data.js +73 -0
- package/dist/modules/keygen/public.d.ts +2 -0
- package/dist/modules/keygen/public.js +12 -0
- package/dist/modules/locale-builder/index.d.ts +1 -0
- package/dist/modules/locale-builder/index.js +7 -0
- package/dist/modules/locale-builder/locales.d.ts +13 -0
- package/dist/modules/locale-builder/locales.js +130 -0
- package/dist/modules/lockfile/hasher.d.ts +7 -0
- package/dist/modules/lockfile/hasher.js +13 -0
- package/dist/modules/lockfile/index.d.ts +3 -0
- package/dist/modules/lockfile/index.js +22 -0
- package/dist/modules/lockfile/lockfile-manager.d.ts +99 -0
- package/dist/modules/lockfile/lockfile-manager.js +497 -0
- package/dist/modules/lockfile/schema.d.ts +196 -0
- package/dist/modules/lockfile/schema.js +56 -0
- package/dist/modules/parser/index.d.ts +2 -0
- package/dist/modules/parser/index.js +9 -0
- package/dist/modules/summary/index.d.ts +1 -0
- package/dist/modules/summary/index.js +7 -0
- package/dist/modules/summary/summary.d.ts +9 -0
- package/dist/modules/summary/summary.js +195 -0
- package/dist/modules/sync-detector/index.d.ts +2 -0
- package/dist/modules/sync-detector/index.js +7 -0
- package/dist/modules/sync-detector/reporter.d.ts +3 -0
- package/dist/modules/sync-detector/reporter.js +16 -0
- package/dist/modules/sync-detector/sync-detector.d.ts +39 -0
- package/dist/modules/sync-detector/sync-detector.js +374 -0
- package/dist/modules/translator/batch-optimizer.d.ts +12 -0
- package/dist/modules/translator/batch-optimizer.js +30 -0
- package/dist/modules/translator/client/byok.provider.d.ts +64 -0
- package/dist/modules/translator/client/byok.provider.js +319 -0
- package/dist/modules/translator/client/direct-translator.client.d.ts +12 -0
- package/dist/modules/translator/client/direct-translator.client.js +71 -0
- package/dist/modules/translator/client/gemini.provider.d.ts +1 -0
- package/dist/modules/translator/client/gemini.provider.js +110 -0
- package/dist/modules/translator/client/groq.provider.d.ts +1 -0
- package/dist/modules/translator/client/groq.provider.js +111 -0
- package/dist/modules/translator/client/request.types.d.ts +1 -0
- package/dist/modules/translator/client/request.types.js +2 -0
- package/dist/modules/translator/client/retry.d.ts +29 -0
- package/dist/modules/translator/client/retry.js +94 -0
- package/dist/modules/translator/client/test-utils/mock.client.d.ts +31 -0
- package/dist/modules/translator/client/test-utils/mock.client.js +59 -0
- package/dist/modules/translator/client/translator.interface.d.ts +1 -0
- package/dist/modules/translator/client/translator.interface.js +2 -0
- package/dist/modules/translator/icu-branches.d.ts +138 -0
- package/dist/modules/translator/icu-branches.js +393 -0
- package/dist/modules/translator/language-codes/errors.d.ts +10 -0
- package/dist/modules/translator/language-codes/errors.js +18 -0
- package/dist/modules/translator/language-codes/flores-map.d.ts +1 -0
- package/dist/modules/translator/language-codes/flores-map.js +107 -0
- package/dist/modules/translator/language-codes/index.d.ts +11 -0
- package/dist/modules/translator/language-codes/index.js +24 -0
- package/dist/modules/translator/language-codes/language-mapper.d.ts +25 -0
- package/dist/modules/translator/language-codes/language-mapper.js +132 -0
- package/dist/modules/translator/language-codes/rtl-languages.d.ts +2 -0
- package/dist/modules/translator/language-codes/rtl-languages.js +9 -0
- package/dist/modules/translator/memory/memory-matcher.d.ts +8 -0
- package/dist/modules/translator/memory/memory-matcher.js +218 -0
- package/dist/modules/translator/memory/types.d.ts +22 -0
- package/dist/modules/translator/memory/types.js +2 -0
- package/dist/modules/translator/translate.d.ts +74 -0
- package/dist/modules/translator/translate.js +1047 -0
- package/dist/modules/vue/migrate.d.ts +13 -0
- package/dist/modules/vue/migrate.js +40 -0
- package/dist/modules/vue/script-inject.d.ts +16 -0
- package/dist/modules/vue/script-inject.js +115 -0
- package/dist/modules/vue/sfc.d.ts +11 -0
- package/dist/modules/vue/sfc.js +51 -0
- package/dist/modules/vue/template-rewrite.d.ts +25 -0
- package/dist/modules/vue/template-rewrite.js +76 -0
- package/dist/modules/vue/template-scan.d.ts +29 -0
- package/dist/modules/vue/template-scan.js +264 -0
- package/dist/modules/workspace/index.d.ts +1 -0
- package/dist/modules/workspace/index.js +5 -0
- package/dist/modules/workspace/validate.d.ts +13 -0
- package/dist/modules/workspace/validate.js +333 -0
- package/dist/orchestrator.d.ts +13 -0
- package/dist/orchestrator.js +727 -0
- package/dist/providers/default-translation-provider.d.ts +20 -0
- package/dist/providers/default-translation-provider.js +30 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +21 -0
- package/dist/providers/types.d.ts +153 -0
- package/dist/providers/types.js +2 -0
- package/dist/qa/check-project.d.ts +50 -0
- package/dist/qa/check-project.js +193 -0
- package/dist/qa/gettext-files.d.ts +15 -0
- package/dist/qa/gettext-files.js +115 -0
- package/dist/qa/locale-files.d.ts +44 -0
- package/dist/qa/locale-files.js +159 -0
- package/dist/qa/locale-qa.d.ts +61 -0
- package/dist/qa/locale-qa.js +342 -0
- package/dist/qa/review.d.ts +43 -0
- package/dist/qa/review.js +175 -0
- package/dist/runtime/config.d.ts +8 -0
- package/dist/runtime/config.js +37 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/types.d.ts +427 -0
- package/dist/runtime/types.js +38 -0
- package/dist/types.d.ts +134 -0
- package/dist/types.js +12 -0
- package/dist/utils/ast-helpers.d.ts +57 -0
- package/dist/utils/ast-helpers.js +608 -0
- package/dist/utils/cache-keys.d.ts +8 -0
- package/dist/utils/cache-keys.js +18 -0
- package/dist/utils/circuit-breaker.d.ts +43 -0
- package/dist/utils/circuit-breaker.js +119 -0
- package/dist/utils/concurrent-map.d.ts +4 -0
- package/dist/utils/concurrent-map.js +21 -0
- package/dist/utils/detect-format.d.ts +5 -0
- package/dist/utils/detect-format.js +125 -0
- package/dist/utils/extraction-options.d.ts +29 -0
- package/dist/utils/extraction-options.js +33 -0
- package/dist/utils/file-utils.d.ts +33 -0
- package/dist/utils/file-utils.js +267 -0
- package/dist/utils/glossary-match.d.ts +9 -0
- package/dist/utils/glossary-match.js +25 -0
- package/dist/utils/html-extractor.d.ts +8 -0
- package/dist/utils/html-extractor.js +317 -0
- package/dist/utils/i18next-icu.d.ts +38 -0
- package/dist/utils/i18next-icu.js +159 -0
- package/dist/utils/icu-message.d.ts +65 -0
- package/dist/utils/icu-message.js +346 -0
- package/dist/utils/icu-spans.d.ts +10 -0
- package/dist/utils/icu-spans.js +126 -0
- package/dist/utils/jsx-message.d.ts +93 -0
- package/dist/utils/jsx-message.js +628 -0
- package/dist/utils/key-usage.d.ts +35 -0
- package/dist/utils/key-usage.js +247 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.js +33 -0
- package/dist/utils/metadata.d.ts +82 -0
- package/dist/utils/metadata.js +261 -0
- package/dist/utils/module-constants.d.ts +30 -0
- package/dist/utils/module-constants.js +265 -0
- package/dist/utils/not-injected.d.ts +6 -0
- package/dist/utils/not-injected.js +38 -0
- package/dist/utils/placeholder-protection.d.ts +74 -0
- package/dist/utils/placeholder-protection.js +181 -0
- package/dist/utils/pseudo-markers.d.ts +9 -0
- package/dist/utils/pseudo-markers.js +16 -0
- package/dist/utils/string-utils.d.ts +52 -0
- package/dist/utils/string-utils.js +270 -0
- package/dist/utils/translation-quality.d.ts +34 -0
- package/dist/utils/translation-quality.js +156 -0
- package/dist/utils/translation-sanitizer.d.ts +11 -0
- package/dist/utils/translation-sanitizer.js +71 -0
- package/dist/utils/translator-caller.d.ts +32 -0
- package/dist/utils/translator-caller.js +217 -0
- package/dist/utils/translator-load-balancer.d.ts +73 -0
- package/dist/utils/translator-load-balancer.js +297 -0
- package/dist/utils/ui-copy.d.ts +32 -0
- package/dist/utils/ui-copy.js +126 -0
- package/dist/utils/untranslated.d.ts +15 -0
- package/dist/utils/untranslated.js +34 -0
- package/dist/utils/workspace.d.ts +14 -0
- package/dist/utils/workspace.js +89 -0
- package/package.json +64 -4
- package/schemas/translate-report.schema.json +297 -0
- package/README.md +0 -3
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.traverse = exports.t = exports.generate = void 0;
|
|
40
|
+
exports.parseCode = parseCode;
|
|
41
|
+
exports.generateCode = generateCode;
|
|
42
|
+
exports.placeStatementsOnOwnLines = placeStatementsOnOwnLines;
|
|
43
|
+
exports.isJSXText = isJSXText;
|
|
44
|
+
exports.isAlreadyTranslated = isAlreadyTranslated;
|
|
45
|
+
exports.isNonTranslatableContext = isNonTranslatableContext;
|
|
46
|
+
exports.getComponentName = getComponentName;
|
|
47
|
+
exports.isInsideComponent = isInsideComponent;
|
|
48
|
+
exports.findComponentBody = findComponentBody;
|
|
49
|
+
exports.hasTranslationImport = hasTranslationImport;
|
|
50
|
+
exports.hasTranslationHook = hasTranslationHook;
|
|
51
|
+
exports.createTranslationImport = createTranslationImport;
|
|
52
|
+
exports.createTranslationHook = createTranslationHook;
|
|
53
|
+
exports.createTCall = createTCall;
|
|
54
|
+
exports.createJSXTCall = createJSXTCall;
|
|
55
|
+
exports.extractJSXTextContent = extractJSXTextContent;
|
|
56
|
+
exports.getParentContext = getParentContext;
|
|
57
|
+
exports.extractExpressionContent = extractExpressionContent;
|
|
58
|
+
exports.extractConditionalContent = extractConditionalContent;
|
|
59
|
+
exports.hasUseClientDirective = hasUseClientDirective;
|
|
60
|
+
const generator_1 = __importDefault(require("@babel/generator"));
|
|
61
|
+
exports.generate = generator_1.default;
|
|
62
|
+
const parser = __importStar(require("@babel/parser"));
|
|
63
|
+
const traverse_1 = __importDefault(require("@babel/traverse"));
|
|
64
|
+
exports.traverse = traverse_1.default;
|
|
65
|
+
const t = __importStar(require("@babel/types"));
|
|
66
|
+
exports.t = t;
|
|
67
|
+
function parseCode(code, options = {}) {
|
|
68
|
+
const { sourceType = 'module', isTypeScript = options.filename ? !/\.jsx?$/i.test(options.filename) : true, isJSX = true } = options;
|
|
69
|
+
const plugins = [];
|
|
70
|
+
if (isJSX)
|
|
71
|
+
plugins.push('jsx');
|
|
72
|
+
if (isTypeScript)
|
|
73
|
+
plugins.push('typescript');
|
|
74
|
+
plugins.push('decorators-legacy', 'classProperties', 'classPrivateProperties', 'classPrivateMethods', 'exportDefaultFrom', 'exportNamespaceFrom', 'dynamicImport', 'nullishCoalescingOperator', 'optionalChaining', 'objectRestSpread');
|
|
75
|
+
return parser.parse(code, {
|
|
76
|
+
sourceType,
|
|
77
|
+
plugins,
|
|
78
|
+
errorRecovery: true,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function generateCode(ast, originalCode) {
|
|
82
|
+
const result = (0, generator_1.default)(ast, {
|
|
83
|
+
retainLines: true,
|
|
84
|
+
retainFunctionParens: true,
|
|
85
|
+
comments: true,
|
|
86
|
+
compact: false,
|
|
87
|
+
}, originalCode);
|
|
88
|
+
let code = result.code;
|
|
89
|
+
code = code.replace(/;import /g, ';\nimport ');
|
|
90
|
+
code = code.replace(/(^import .+;\n)([^i\n])/gm, '$1\n$2');
|
|
91
|
+
// An added import glued to the first statement: `import x from "y";export …`.
|
|
92
|
+
code = code.replace(/^(import\b[^\n]*?["'];)(?=[^\s/])/gm, '$1\n\n');
|
|
93
|
+
code = splitClosingBraces(code);
|
|
94
|
+
code = code.replace(/\n{3,}/g, '\n\n');
|
|
95
|
+
// retainLines drops the final newline; keep the file's own ending.
|
|
96
|
+
if (originalCode !== undefined && /\r?\n$/.test(originalCode) && !/\n$/.test(code)) {
|
|
97
|
+
code += originalCode.endsWith('\r\n') ? '\r\n' : '\n';
|
|
98
|
+
}
|
|
99
|
+
return code;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* With `retainLines`, statements the injector adds (which have no source
|
|
103
|
+
* location) are printed on the line of the preceding token, e.g.
|
|
104
|
+
* `function Page() {const t = useTranslations();`. Move each such statement
|
|
105
|
+
* that directly follows a `{` onto its own line, indented like the body.
|
|
106
|
+
*/
|
|
107
|
+
function placeStatementsOnOwnLines(code, statements) {
|
|
108
|
+
if (statements.length === 0)
|
|
109
|
+
return code;
|
|
110
|
+
const eol = code.includes('\r\n') ? '\r\n' : '\n';
|
|
111
|
+
const lines = code.split(eol);
|
|
112
|
+
// The generator may print the same statement compactly or across lines
|
|
113
|
+
// (`const { t } = …` vs `const {\n t\n} = …`): match on tokens, ignoring whitespace.
|
|
114
|
+
const escape = (x) => x.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
115
|
+
const matchers = statements.map((text) => {
|
|
116
|
+
const tokens = text.split(/\s+/).filter(Boolean).map(escape).join('\\s*');
|
|
117
|
+
return { re: new RegExp(`\\{\\s*(${tokens})`) };
|
|
118
|
+
});
|
|
119
|
+
const out = [];
|
|
120
|
+
for (let i = 0; i < lines.length; i++) {
|
|
121
|
+
const line = lines[i];
|
|
122
|
+
let hit = null;
|
|
123
|
+
for (const m of matchers) {
|
|
124
|
+
const found = m.re.exec(line);
|
|
125
|
+
if (found && (!hit || found.index < hit.at))
|
|
126
|
+
hit = { at: found.index, length: found[0].length - 1, text: found[1] };
|
|
127
|
+
}
|
|
128
|
+
if (!hit) {
|
|
129
|
+
out.push(line);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const lineIndent = line.match(/^\s*/)[0];
|
|
133
|
+
const next = lines.slice(i + 1).find((l) => l.trim().length > 0) ?? '';
|
|
134
|
+
const nextIndent = next.match(/^\s*/)[0];
|
|
135
|
+
const bodyIndent = nextIndent.length > lineIndent.length ? nextIndent : `${lineIndent} `;
|
|
136
|
+
const rest = line.slice(hit.at + 1 + hit.length);
|
|
137
|
+
out.push(line.slice(0, hit.at + 1));
|
|
138
|
+
out.push(`${bodyIndent}${hit.text}`);
|
|
139
|
+
if (rest.trim()) {
|
|
140
|
+
// Anything else that followed on the line (rare) gets re-checked too.
|
|
141
|
+
lines.splice(i + 1, 0, `${bodyIndent}${rest.trim()}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return splitClosingBraces(out.join(eol));
|
|
145
|
+
}
|
|
146
|
+
/** A block body added around a concise arrow: ` return <jsx/>;};` → closing brace on its own line. */
|
|
147
|
+
function splitClosingBraces(code) {
|
|
148
|
+
return code.replace(/^([ \t]+)(return\b[^\n]*;)(\};?)(\r?)$/gm, (_m, indent, stmt, close, cr) => `${indent}${stmt}${cr}\n${indent.slice(0, Math.max(0, indent.length - 2))}${close}${cr}`);
|
|
149
|
+
}
|
|
150
|
+
function isJSXText(node) {
|
|
151
|
+
return t.isJSXText(node);
|
|
152
|
+
}
|
|
153
|
+
function isAlreadyTranslated(node, path) {
|
|
154
|
+
if (path.parentPath?.isCallExpression()) {
|
|
155
|
+
const callee = path.parentPath.node.callee;
|
|
156
|
+
if (t.isIdentifier(callee) && callee.name === 't')
|
|
157
|
+
return true;
|
|
158
|
+
if (t.isMemberExpression(callee) &&
|
|
159
|
+
t.isIdentifier(callee.property) &&
|
|
160
|
+
callee.property.name === 't') {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
let current = path;
|
|
165
|
+
while (current) {
|
|
166
|
+
if (current.isJSXElement()) {
|
|
167
|
+
const openingElement = current.node.openingElement;
|
|
168
|
+
if ((t.isJSXIdentifier(openingElement.name) && openingElement.name.name === 'Trans') ||
|
|
169
|
+
(t.isJSXMemberExpression(openingElement.name) && openingElement.name.property.name === 'Trans')) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
current = current.parentPath;
|
|
174
|
+
}
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
function isNonTranslatableContext(path) {
|
|
178
|
+
let current = path;
|
|
179
|
+
let isInFunctionOrClass = false;
|
|
180
|
+
let hasFunctionOrClassBetween = false;
|
|
181
|
+
while (current) {
|
|
182
|
+
if (current.isFunction() || current.isClass()) {
|
|
183
|
+
isInFunctionOrClass = true;
|
|
184
|
+
hasFunctionOrClassBetween = true;
|
|
185
|
+
}
|
|
186
|
+
if (current.isCallExpression()) {
|
|
187
|
+
const callee = current.node.callee;
|
|
188
|
+
if (t.isMemberExpression(callee) &&
|
|
189
|
+
t.isIdentifier(callee.object) &&
|
|
190
|
+
callee.object.name === 'console') {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
if (t.isIdentifier(callee) && /^use[A-Z]/.test(callee.name)) {
|
|
194
|
+
if (!hasFunctionOrClassBetween) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (current.isThrowStatement())
|
|
200
|
+
return true;
|
|
201
|
+
if (current.isNewExpression()) {
|
|
202
|
+
const callee = current.node.callee;
|
|
203
|
+
if (t.isIdentifier(callee) && /Error$/.test(callee.name))
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
if (current.isObjectProperty()) {
|
|
207
|
+
const propKey = current.node.key;
|
|
208
|
+
if ((t.isIdentifier(propKey) && propKey.name === 'key') ||
|
|
209
|
+
(t.isStringLiteral(propKey) && propKey.value === 'key')) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
// Exclude string values of known browser API parameter keys
|
|
213
|
+
// (e.g. { behavior: "smooth" } in scrollIntoView). Without this
|
|
214
|
+
// guard, translating "smooth" causes a runtime browser error since
|
|
215
|
+
// the browser API expects the literal string "smooth".
|
|
216
|
+
const TECH_OBJ_KEYS = new Set([
|
|
217
|
+
'behavior',
|
|
218
|
+
'easing',
|
|
219
|
+
'fill',
|
|
220
|
+
'direction',
|
|
221
|
+
'inline',
|
|
222
|
+
'block',
|
|
223
|
+
'scroll',
|
|
224
|
+
]);
|
|
225
|
+
if ((t.isIdentifier(propKey) && TECH_OBJ_KEYS.has(propKey.name)) ||
|
|
226
|
+
(t.isStringLiteral(propKey) && TECH_OBJ_KEYS.has(propKey.value))) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (current.isMemberExpression() && current.node.computed && current.node.property === path.node) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
if (current.isSwitchCase() && current.node.test === path.node) {
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
if (current.isBinaryExpression() && ['===', '!==', '==', '!=', '>', '<', '>=', '<='].includes(current.node.operator)) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
if (current.isImportDeclaration())
|
|
240
|
+
return true;
|
|
241
|
+
if (current.isExportDeclaration() && !isInFunctionOrClass)
|
|
242
|
+
return true;
|
|
243
|
+
if (current.isTSTypeAnnotation() || current.isTSTypeLiteral() || current.isTypeAnnotation()) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
if (current.isJSXAttribute()) {
|
|
247
|
+
const nameNode = current.node.name;
|
|
248
|
+
if (t.isJSXIdentifier(nameNode)) {
|
|
249
|
+
const name = nameNode.name;
|
|
250
|
+
const NON_TRANSLATABLE_ATTRS = [
|
|
251
|
+
'className',
|
|
252
|
+
'class',
|
|
253
|
+
'style',
|
|
254
|
+
'key',
|
|
255
|
+
'id',
|
|
256
|
+
'ref',
|
|
257
|
+
'src',
|
|
258
|
+
'href',
|
|
259
|
+
'to',
|
|
260
|
+
'target',
|
|
261
|
+
'rel',
|
|
262
|
+
'type',
|
|
263
|
+
'width',
|
|
264
|
+
'height',
|
|
265
|
+
'rows',
|
|
266
|
+
'cols',
|
|
267
|
+
'data-testid',
|
|
268
|
+
'role',
|
|
269
|
+
'as',
|
|
270
|
+
];
|
|
271
|
+
if (NON_TRANSLATABLE_ATTRS.includes(name))
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
current = current.parentPath;
|
|
276
|
+
}
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
function getComponentName(path) {
|
|
280
|
+
if (path.isVariableDeclarator()) {
|
|
281
|
+
if (t.isIdentifier(path.node.id))
|
|
282
|
+
return path.node.id.name;
|
|
283
|
+
}
|
|
284
|
+
if (path.isFunctionDeclaration()) {
|
|
285
|
+
if (path.node.id && t.isIdentifier(path.node.id))
|
|
286
|
+
return path.node.id.name;
|
|
287
|
+
}
|
|
288
|
+
if (path.isClassDeclaration()) {
|
|
289
|
+
return path.node.id?.name || null;
|
|
290
|
+
}
|
|
291
|
+
if (path.isExportDefaultDeclaration()) {
|
|
292
|
+
const declaration = path.node.declaration;
|
|
293
|
+
if (t.isFunctionDeclaration(declaration) && declaration.id)
|
|
294
|
+
return declaration.id.name;
|
|
295
|
+
if (t.isIdentifier(declaration))
|
|
296
|
+
return declaration.name;
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
function isInsideComponent(path) {
|
|
301
|
+
let current = path;
|
|
302
|
+
while (current) {
|
|
303
|
+
if (current.isReturnStatement()) {
|
|
304
|
+
const argument = current.node.argument;
|
|
305
|
+
if (t.isJSXElement(argument) || t.isJSXFragment(argument))
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
if (current.isFunction()) {
|
|
309
|
+
let name = null;
|
|
310
|
+
if (current.isFunctionDeclaration()) {
|
|
311
|
+
name = current.node.id?.name;
|
|
312
|
+
}
|
|
313
|
+
else if (current.isArrowFunctionExpression() ||
|
|
314
|
+
current.isFunctionExpression()) {
|
|
315
|
+
if (current.parentPath?.isVariableDeclarator()) {
|
|
316
|
+
const id = current.parentPath.node.id;
|
|
317
|
+
if (t.isIdentifier(id)) {
|
|
318
|
+
name = id.name;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (name && /^[A-Z]/.test(name)) {
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
let hasJSX = false;
|
|
326
|
+
const checkJSX = (node) => {
|
|
327
|
+
if (!node || hasJSX)
|
|
328
|
+
return;
|
|
329
|
+
// Skip descending into nested function or class boundaries
|
|
330
|
+
if (t.isFunctionDeclaration(node) ||
|
|
331
|
+
t.isArrowFunctionExpression(node) ||
|
|
332
|
+
t.isFunctionExpression(node) ||
|
|
333
|
+
t.isClassDeclaration(node) ||
|
|
334
|
+
t.isClassExpression(node)) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (t.isJSXElement(node) || t.isJSXFragment(node)) {
|
|
338
|
+
hasJSX = true;
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const obj = node;
|
|
342
|
+
for (const key in obj) {
|
|
343
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
344
|
+
const child = obj[key];
|
|
345
|
+
if (Array.isArray(child)) {
|
|
346
|
+
child.forEach(checkJSX);
|
|
347
|
+
}
|
|
348
|
+
else if (child && typeof child === 'object' && child !== null && typeof child.type === 'string') {
|
|
349
|
+
checkJSX(child);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
checkJSX(current.node.body);
|
|
355
|
+
if (hasJSX)
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
current = current.parentPath;
|
|
359
|
+
}
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
/** `memo(…)`, `React.forwardRef(…)`: wrappers whose function argument is the component. */
|
|
363
|
+
function isComponentWrapperCall(call) {
|
|
364
|
+
if (!call.isCallExpression())
|
|
365
|
+
return false;
|
|
366
|
+
const callee = call.node.callee;
|
|
367
|
+
const name = t.isIdentifier(callee) ? callee.name : t.isMemberExpression(callee) && t.isIdentifier(callee.property) ? callee.property.name : '';
|
|
368
|
+
return /^(?:memo|forwardRef|observer)$/.test(name);
|
|
369
|
+
}
|
|
370
|
+
/** The function returns JSX from its own body (not from a nested function). */
|
|
371
|
+
function returnsJsx(fn) {
|
|
372
|
+
if (!t.isBlockStatement(fn.node.body))
|
|
373
|
+
return t.isJSXElement(fn.node.body) || t.isJSXFragment(fn.node.body);
|
|
374
|
+
let found = false;
|
|
375
|
+
const isJsxish = (n) => !!n && (t.isJSXElement(n) || t.isJSXFragment(n) ||
|
|
376
|
+
(t.isConditionalExpression(n) && (isJsxish(n.consequent) || isJsxish(n.alternate))) ||
|
|
377
|
+
(t.isLogicalExpression(n) && (isJsxish(n.left) || isJsxish(n.right))) ||
|
|
378
|
+
(t.isParenthesizedExpression(n) && isJsxish(n.expression)));
|
|
379
|
+
fn.get('body').traverse({
|
|
380
|
+
Function(p) {
|
|
381
|
+
p.skip();
|
|
382
|
+
},
|
|
383
|
+
ReturnStatement(p) {
|
|
384
|
+
if (isJsxish(p.node.argument)) {
|
|
385
|
+
found = true;
|
|
386
|
+
p.stop();
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
return found;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Whether `fn` is a component the hook can go in: not a callback passed to
|
|
394
|
+
* another call (`items.map((x) => …)`, except memo/forwardRef), and either
|
|
395
|
+
* PascalCase-named, the default export, or returning JSX itself.
|
|
396
|
+
*/
|
|
397
|
+
function isComponentFunction(fn) {
|
|
398
|
+
const parent = fn.parentPath;
|
|
399
|
+
if (parent?.isCallExpression() && parent.node.arguments.includes(fn.node) && !isComponentWrapperCall(parent))
|
|
400
|
+
return false;
|
|
401
|
+
let name;
|
|
402
|
+
if (fn.isFunctionDeclaration())
|
|
403
|
+
name = fn.node.id?.name;
|
|
404
|
+
else {
|
|
405
|
+
let p = parent;
|
|
406
|
+
while (p && isComponentWrapperCall(p))
|
|
407
|
+
p = p.parentPath;
|
|
408
|
+
if (p?.isVariableDeclarator() && t.isIdentifier(p.node.id))
|
|
409
|
+
name = p.node.id.name;
|
|
410
|
+
if (p?.isExportDefaultDeclaration())
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
if (parent?.isExportDefaultDeclaration())
|
|
414
|
+
return true;
|
|
415
|
+
if (name && /^[A-Z]/.test(name))
|
|
416
|
+
return true;
|
|
417
|
+
return returnsJsx(fn);
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* The block body of the component `path` is in — where the translation hook
|
|
421
|
+
* goes. Skips callbacks (a hook inside `.map(…)` breaks the rules of hooks);
|
|
422
|
+
* null when there's no component with a block body.
|
|
423
|
+
*/
|
|
424
|
+
function findComponentBody(path) {
|
|
425
|
+
let current = path;
|
|
426
|
+
while (current) {
|
|
427
|
+
if (current.isArrowFunctionExpression() ||
|
|
428
|
+
current.isFunctionExpression() ||
|
|
429
|
+
current.isFunctionDeclaration()) {
|
|
430
|
+
const body = current.get('body');
|
|
431
|
+
if (!Array.isArray(body) && body.isBlockStatement() && isComponentFunction(current))
|
|
432
|
+
return body;
|
|
433
|
+
}
|
|
434
|
+
current = current.parentPath;
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
function hasTranslationImport(ast) {
|
|
439
|
+
let found = false;
|
|
440
|
+
(0, traverse_1.default)(ast, {
|
|
441
|
+
ImportDeclaration(path) {
|
|
442
|
+
if (path.node.source.value === 'react-i18next') {
|
|
443
|
+
path.node.specifiers.forEach((spec) => {
|
|
444
|
+
if (t.isImportSpecifier(spec) &&
|
|
445
|
+
t.isIdentifier(spec.imported) &&
|
|
446
|
+
spec.imported.name === 'useTranslation') {
|
|
447
|
+
found = true;
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
return found;
|
|
454
|
+
}
|
|
455
|
+
function hasTranslationHook(functionPath) {
|
|
456
|
+
let found = false;
|
|
457
|
+
functionPath.traverse({
|
|
458
|
+
VariableDeclarator(path) {
|
|
459
|
+
const node = path.node;
|
|
460
|
+
if (node.init &&
|
|
461
|
+
t.isCallExpression(node.init) &&
|
|
462
|
+
t.isIdentifier(node.init.callee) &&
|
|
463
|
+
node.init.callee.name === 'useTranslation') {
|
|
464
|
+
found = true;
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
return found;
|
|
469
|
+
}
|
|
470
|
+
function createTranslationImport() {
|
|
471
|
+
return t.importDeclaration([t.importSpecifier(t.identifier('useTranslation'), t.identifier('useTranslation'))], t.stringLiteral('react-i18next'));
|
|
472
|
+
}
|
|
473
|
+
function createTranslationHook() {
|
|
474
|
+
return t.variableDeclaration('const', [
|
|
475
|
+
t.variableDeclarator(t.objectPattern([t.objectProperty(t.identifier('t'), t.identifier('t'), false, true)]), t.callExpression(t.identifier('useTranslation'), [])),
|
|
476
|
+
]);
|
|
477
|
+
}
|
|
478
|
+
function createTCall(key) {
|
|
479
|
+
return t.callExpression(t.identifier('t'), [t.stringLiteral(key)]);
|
|
480
|
+
}
|
|
481
|
+
function createJSXTCall(key) {
|
|
482
|
+
return t.jsxExpressionContainer(createTCall(key));
|
|
483
|
+
}
|
|
484
|
+
function extractJSXTextContent(node) {
|
|
485
|
+
const value = node.value;
|
|
486
|
+
return value.replace(/\s+/g, ' ').trim();
|
|
487
|
+
}
|
|
488
|
+
function getParentContext(path) {
|
|
489
|
+
let parent = path.parentPath;
|
|
490
|
+
while (parent && !parent.isJSXElement() && !parent.isJSXFragment()) {
|
|
491
|
+
parent = parent.parentPath;
|
|
492
|
+
}
|
|
493
|
+
if (!parent)
|
|
494
|
+
return null;
|
|
495
|
+
const children = parent.node.children;
|
|
496
|
+
if (!children || children.length < 2)
|
|
497
|
+
return null;
|
|
498
|
+
let textChildCount = 0;
|
|
499
|
+
let elementIndex = 0;
|
|
500
|
+
const parts = [];
|
|
501
|
+
for (const child of children) {
|
|
502
|
+
if (t.isJSXText(child)) {
|
|
503
|
+
const text = extractJSXTextContent(child);
|
|
504
|
+
if (text && text.length >= 2) {
|
|
505
|
+
textChildCount++;
|
|
506
|
+
parts.push(text);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
else if (t.isJSXElement(child)) {
|
|
510
|
+
parts.push(`{#${elementIndex}}`);
|
|
511
|
+
elementIndex++;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (textChildCount < 1 || (textChildCount < 2 && elementIndex < 1))
|
|
515
|
+
return null;
|
|
516
|
+
const parentContext = parts.join(' ').replace(/\s+/g, ' ').trim();
|
|
517
|
+
if (!parentContext)
|
|
518
|
+
return null;
|
|
519
|
+
let hash = 0;
|
|
520
|
+
for (let i = 0; i < parentContext.length; i++) {
|
|
521
|
+
const char = parentContext.charCodeAt(i);
|
|
522
|
+
hash = (hash << 5) - hash + char;
|
|
523
|
+
hash = hash & hash;
|
|
524
|
+
}
|
|
525
|
+
return {
|
|
526
|
+
parentContext,
|
|
527
|
+
siblingGroupId: Math.abs(hash).toString(36),
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function extractExpressionContent(node, variables = []) {
|
|
531
|
+
if (t.isStringLiteral(node))
|
|
532
|
+
return node.value;
|
|
533
|
+
if (t.isTemplateLiteral(node)) {
|
|
534
|
+
let result = '';
|
|
535
|
+
const quasis = node.quasis;
|
|
536
|
+
const expressions = node.expressions;
|
|
537
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
538
|
+
result += quasis[i].value.raw;
|
|
539
|
+
if (i < expressions.length) {
|
|
540
|
+
const expr = expressions[i];
|
|
541
|
+
let varName = `var${variables.length}`;
|
|
542
|
+
if (t.isIdentifier(expr)) {
|
|
543
|
+
varName = expr.name;
|
|
544
|
+
}
|
|
545
|
+
else if (t.isMemberExpression(expr) && t.isIdentifier(expr.property)) {
|
|
546
|
+
varName = expr.property.name;
|
|
547
|
+
}
|
|
548
|
+
variables.push(varName);
|
|
549
|
+
result += `{${varName}}`;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
554
|
+
if (t.isBinaryExpression(node) && node.operator === '+') {
|
|
555
|
+
const leftVars = [];
|
|
556
|
+
const rightVars = [];
|
|
557
|
+
const left = extractExpressionContent(node.left, leftVars);
|
|
558
|
+
const right = extractExpressionContent(node.right, rightVars);
|
|
559
|
+
if (left !== null && right !== null) {
|
|
560
|
+
variables.push(...leftVars, ...rightVars);
|
|
561
|
+
return left + right;
|
|
562
|
+
}
|
|
563
|
+
if (left !== null && t.isIdentifier(node.right)) {
|
|
564
|
+
const varName = node.right.name;
|
|
565
|
+
variables.push(...leftVars, varName);
|
|
566
|
+
return left + `{${varName}}`;
|
|
567
|
+
}
|
|
568
|
+
if (right !== null && t.isIdentifier(node.left)) {
|
|
569
|
+
const varName = node.left.name;
|
|
570
|
+
variables.push(varName, ...rightVars);
|
|
571
|
+
return `{${varName}}` + right;
|
|
572
|
+
}
|
|
573
|
+
if (left !== null && t.isMemberExpression(node.right) && t.isIdentifier(node.right.property)) {
|
|
574
|
+
const varName = node.right.property.name;
|
|
575
|
+
variables.push(...leftVars, varName);
|
|
576
|
+
return left + `{${varName}}`;
|
|
577
|
+
}
|
|
578
|
+
if (right !== null && t.isMemberExpression(node.left) && t.isIdentifier(node.left.property)) {
|
|
579
|
+
const varName = node.left.property.name;
|
|
580
|
+
variables.push(varName, ...rightVars);
|
|
581
|
+
return `{${varName}}` + right;
|
|
582
|
+
}
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
if (t.isJSXExpressionContainer(node)) {
|
|
586
|
+
return extractExpressionContent(node.expression, variables);
|
|
587
|
+
}
|
|
588
|
+
return null;
|
|
589
|
+
}
|
|
590
|
+
function extractConditionalContent(node) {
|
|
591
|
+
return {
|
|
592
|
+
consequent: extractExpressionContent(node.consequent),
|
|
593
|
+
alternate: extractExpressionContent(node.alternate),
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Check if the file has a 'use client' directive
|
|
598
|
+
*/
|
|
599
|
+
function hasUseClientDirective(ast) {
|
|
600
|
+
if (ast.program.directives) {
|
|
601
|
+
for (const directive of ast.program.directives) {
|
|
602
|
+
if (directive.value && directive.value.value === 'use client') {
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation cache key helpers. The key format must stay identical to the
|
|
3
|
+
* backend's (config/redis CacheKeys.translation), which re-exports these so
|
|
4
|
+
* both sides read and write the same entries.
|
|
5
|
+
*/
|
|
6
|
+
export declare function hashText(text: string): string;
|
|
7
|
+
export declare const TRANSLATION_CACHE_TTL_SECONDS: number;
|
|
8
|
+
export declare function translationCacheKey(sourceLang: string, targetLang: string, textHash: string): string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TRANSLATION_CACHE_TTL_SECONDS = void 0;
|
|
4
|
+
exports.hashText = hashText;
|
|
5
|
+
exports.translationCacheKey = translationCacheKey;
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
/**
|
|
8
|
+
* Translation cache key helpers. The key format must stay identical to the
|
|
9
|
+
* backend's (config/redis CacheKeys.translation), which re-exports these so
|
|
10
|
+
* both sides read and write the same entries.
|
|
11
|
+
*/
|
|
12
|
+
function hashText(text) {
|
|
13
|
+
return (0, crypto_1.createHash)('sha256').update(text, 'utf8').digest('hex').slice(0, 16);
|
|
14
|
+
}
|
|
15
|
+
exports.TRANSLATION_CACHE_TTL_SECONDS = 30 * 24 * 60 * 60; // 30 days
|
|
16
|
+
function translationCacheKey(sourceLang, targetLang, textHash) {
|
|
17
|
+
return `translation:${sourceLang}:${targetLang}:${textHash}`;
|
|
18
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Pattern
|
|
3
|
+
*
|
|
4
|
+
* Prevents cascading failures by stopping requests to failing services
|
|
5
|
+
*/
|
|
6
|
+
export interface CircuitBreakerOptions {
|
|
7
|
+
failureThreshold: number;
|
|
8
|
+
resetTimeout: number;
|
|
9
|
+
halfOpenMaxCalls: number;
|
|
10
|
+
}
|
|
11
|
+
export declare enum CircuitState {
|
|
12
|
+
CLOSED = "closed",// Normal operation
|
|
13
|
+
OPEN = "open",// Failing, reject requests
|
|
14
|
+
HALF_OPEN = "half-open"
|
|
15
|
+
}
|
|
16
|
+
export declare class CircuitBreaker {
|
|
17
|
+
private name;
|
|
18
|
+
private options;
|
|
19
|
+
private state;
|
|
20
|
+
private failureCount;
|
|
21
|
+
private lastFailureTime;
|
|
22
|
+
private halfOpenCalls;
|
|
23
|
+
private successCount;
|
|
24
|
+
constructor(name: string, options?: CircuitBreakerOptions);
|
|
25
|
+
/**
|
|
26
|
+
* Execute a function with circuit breaker protection
|
|
27
|
+
*/
|
|
28
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
29
|
+
private onSuccess;
|
|
30
|
+
private onFailure;
|
|
31
|
+
getState(): CircuitState;
|
|
32
|
+
getStats(): {
|
|
33
|
+
name: string;
|
|
34
|
+
state: CircuitState;
|
|
35
|
+
failureCount: number;
|
|
36
|
+
lastFailureTime: number;
|
|
37
|
+
};
|
|
38
|
+
reset(): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get or create a circuit breaker
|
|
42
|
+
*/
|
|
43
|
+
export declare function getCircuitBreaker(name: string, options?: CircuitBreakerOptions): CircuitBreaker;
|