@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,78 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.FinalizationWriter = void 0;
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const file_utils_1 = require("../../utils/file-utils");
|
|
39
|
+
/**
|
|
40
|
+
* The single path every finalization write goes through.
|
|
41
|
+
*
|
|
42
|
+
* Hosts ship `changes` with the run (the GitHub PR, the ZIP, the CLI report),
|
|
43
|
+
* so a write that bypasses this recorder is a file the PR silently leaves out:
|
|
44
|
+
* `t()` calls merged without the dependency or the init code that makes them
|
|
45
|
+
* work. Records new files as well as edits, and folds repeated writes to one
|
|
46
|
+
* file into a single change (first original, last content).
|
|
47
|
+
*/
|
|
48
|
+
class FinalizationWriter {
|
|
49
|
+
constructor(root, dryRun) {
|
|
50
|
+
this.root = root;
|
|
51
|
+
this.dryRun = dryRun;
|
|
52
|
+
this.byFile = new Map();
|
|
53
|
+
}
|
|
54
|
+
/** Write `content` to `absPath` (unless dry run) and record it. Returns false when the file already had that content. */
|
|
55
|
+
async write(absPath, content) {
|
|
56
|
+
const original = (await (0, file_utils_1.pathExists)(absPath)) ? await (0, file_utils_1.readFile)(absPath) : null;
|
|
57
|
+
if (original === content)
|
|
58
|
+
return false;
|
|
59
|
+
if (!this.dryRun)
|
|
60
|
+
await (0, file_utils_1.writeFile)(absPath, content);
|
|
61
|
+
this.record(absPath, original, content);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
/** Record a write made elsewhere (e.g. by a package manager). `original` null = file was created. */
|
|
65
|
+
record(absPath, original, content) {
|
|
66
|
+
const file = path.relative(this.root, path.resolve(absPath)).split(path.sep).join('/');
|
|
67
|
+
const prev = this.byFile.get(file);
|
|
68
|
+
if (prev) {
|
|
69
|
+
prev.modifiedContent = content;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.byFile.set(file, { file, originalContent: original ?? '', modifiedContent: content, created: original === null });
|
|
73
|
+
}
|
|
74
|
+
get changes() {
|
|
75
|
+
return [...this.byFile.values()];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.FinalizationWriter = FinalizationWriter;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExtractedString, FileInjection, SkippedFile, WorkspaceInfo } from '../../runtime/types';
|
|
2
|
+
import type { FormatLocaleConfig } from '@babelize/types';
|
|
3
|
+
export interface FormatInjectionResult {
|
|
4
|
+
modifiedFiles: FileInjection[];
|
|
5
|
+
skippedFiles: SkippedFile[];
|
|
6
|
+
totalInjections: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Run format injection for all format strings.
|
|
10
|
+
*
|
|
11
|
+
* Replaces hardcoded currency, date, and number values in source files
|
|
12
|
+
* with Intl.* API calls (e.g., Intl.NumberFormat, Intl.DateTimeFormat).
|
|
13
|
+
*/
|
|
14
|
+
export declare function injectFormats(workspace: WorkspaceInfo, formatStrings: ExtractedString[], formatConfig: FormatLocaleConfig, dryRun?: boolean): Promise<FormatInjectionResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Filter format strings out of an array of extracted strings.
|
|
17
|
+
* Returns [translatableStrings, formatStrings].
|
|
18
|
+
*/
|
|
19
|
+
export declare function partitionFormatStrings(strings: ExtractedString[]): [translatable: ExtractedString[], format: ExtractedString[]];
|
|
@@ -0,0 +1,273 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.injectFormats = injectFormats;
|
|
37
|
+
exports.partitionFormatStrings = partitionFormatStrings;
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const t = __importStar(require("@babel/types"));
|
|
40
|
+
const inject_formats_1 = require("./inject-formats");
|
|
41
|
+
const ast_helpers_1 = require("../../utils/ast-helpers");
|
|
42
|
+
const file_utils_1 = require("../../utils/file-utils");
|
|
43
|
+
const types_1 = require("../../runtime/types");
|
|
44
|
+
const generator_1 = require("@babel/generator");
|
|
45
|
+
/**
|
|
46
|
+
* Run format injection for all format strings.
|
|
47
|
+
*
|
|
48
|
+
* Replaces hardcoded currency, date, and number values in source files
|
|
49
|
+
* with Intl.* API calls (e.g., Intl.NumberFormat, Intl.DateTimeFormat).
|
|
50
|
+
*/
|
|
51
|
+
async function injectFormats(workspace, formatStrings, formatConfig, dryRun = false) {
|
|
52
|
+
const modifiedFiles = [];
|
|
53
|
+
const skippedFiles = [];
|
|
54
|
+
let totalInjections = 0;
|
|
55
|
+
if (!formatConfig.enabled || formatStrings.length === 0) {
|
|
56
|
+
return { modifiedFiles, skippedFiles, totalInjections: 0 };
|
|
57
|
+
}
|
|
58
|
+
// Group format strings by file
|
|
59
|
+
const stringsByFile = new Map();
|
|
60
|
+
for (const s of formatStrings) {
|
|
61
|
+
if (!s.detectedFormat)
|
|
62
|
+
continue;
|
|
63
|
+
const fileKey = s.file;
|
|
64
|
+
if (!stringsByFile.has(fileKey)) {
|
|
65
|
+
stringsByFile.set(fileKey, []);
|
|
66
|
+
}
|
|
67
|
+
stringsByFile.get(fileKey).push(s);
|
|
68
|
+
}
|
|
69
|
+
// Build locale expression based on framework
|
|
70
|
+
const localeExpr = (0, inject_formats_1.buildLocaleExpression)(workspace.framework || 'unknown');
|
|
71
|
+
// Find all source files
|
|
72
|
+
const sourceFiles = [];
|
|
73
|
+
for (const sourceDir of workspace.sourceDirs) {
|
|
74
|
+
const dirPath = path.join(workspace.path, sourceDir);
|
|
75
|
+
const files = await (0, file_utils_1.findFiles)(dirPath, types_1.SUPPORTED_EXTENSIONS, types_1.EXCLUDED_PATTERNS);
|
|
76
|
+
sourceFiles.push(...files);
|
|
77
|
+
}
|
|
78
|
+
// Build a lookup of format strings by (relative file path, line)
|
|
79
|
+
const formatStringLookup = new Map();
|
|
80
|
+
for (const [fileKey, strings] of stringsByFile) {
|
|
81
|
+
const lineMap = new Map();
|
|
82
|
+
for (const s of strings) {
|
|
83
|
+
lineMap.set(s.line, s);
|
|
84
|
+
}
|
|
85
|
+
formatStringLookup.set(fileKey, lineMap);
|
|
86
|
+
}
|
|
87
|
+
// Process each file
|
|
88
|
+
for (const filePath of sourceFiles) {
|
|
89
|
+
const relativePath = (0, file_utils_1.getRelativePath)(workspace.path, filePath);
|
|
90
|
+
const fileStrings = stringsByFile.get(relativePath);
|
|
91
|
+
if (!fileStrings || fileStrings.length === 0)
|
|
92
|
+
continue;
|
|
93
|
+
try {
|
|
94
|
+
const originalContent = await (0, file_utils_1.readFile)(filePath);
|
|
95
|
+
const isTypeScript = filePath.endsWith('.ts') || filePath.endsWith('.tsx');
|
|
96
|
+
const ast = (0, ast_helpers_1.parseCode)(originalContent, { isTypeScript });
|
|
97
|
+
const injections = [];
|
|
98
|
+
const lineLookup = formatStringLookup.get(relativePath);
|
|
99
|
+
if (!lineLookup)
|
|
100
|
+
continue;
|
|
101
|
+
// Walk AST and replace matching string literals with Intl.* expressions
|
|
102
|
+
(0, ast_helpers_1.traverse)(ast, {
|
|
103
|
+
StringLiteral(strPath) {
|
|
104
|
+
const node = strPath.node;
|
|
105
|
+
if (!node.loc)
|
|
106
|
+
return;
|
|
107
|
+
const line = node.loc.start.line;
|
|
108
|
+
const formatStr = lineLookup.get(line);
|
|
109
|
+
if (!formatStr || !formatStr.detectedFormat)
|
|
110
|
+
return;
|
|
111
|
+
// Verify the text matches exactly (avoid false positives from partial matches)
|
|
112
|
+
if (node.value !== formatStr.text)
|
|
113
|
+
return;
|
|
114
|
+
const astExpr = (0, inject_formats_1.buildFormatAstExpression)(formatStr.detectedFormat, formatConfig, localeExpr);
|
|
115
|
+
if (!astExpr) {
|
|
116
|
+
skippedFiles.push({
|
|
117
|
+
file: relativePath,
|
|
118
|
+
reason: 'format-ast-build-failed',
|
|
119
|
+
details: `Could not build AST for: "${formatStr.text}"`,
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
strPath.replaceWith(astExpr);
|
|
124
|
+
const replacementCode = (0, generator_1.generate)(astExpr).code;
|
|
125
|
+
injections.push({
|
|
126
|
+
file: relativePath,
|
|
127
|
+
line,
|
|
128
|
+
column: node.loc.start.column,
|
|
129
|
+
original: formatStr.text,
|
|
130
|
+
replacement: replacementCode,
|
|
131
|
+
key: '',
|
|
132
|
+
confidence: 100,
|
|
133
|
+
formatClass: formatStr.detectedFormat.class,
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
JSXText(jsxPath) {
|
|
137
|
+
const node = jsxPath.node;
|
|
138
|
+
if (!node.loc)
|
|
139
|
+
return;
|
|
140
|
+
const line = node.loc.start.line;
|
|
141
|
+
const formatStr = lineLookup.get(line);
|
|
142
|
+
if (!formatStr || !formatStr.detectedFormat)
|
|
143
|
+
return;
|
|
144
|
+
const text = node.value.trim();
|
|
145
|
+
if (!text)
|
|
146
|
+
return;
|
|
147
|
+
const astExpr = (0, inject_formats_1.buildFormatAstExpression)(formatStr.detectedFormat, formatConfig, localeExpr);
|
|
148
|
+
if (!astExpr) {
|
|
149
|
+
skippedFiles.push({
|
|
150
|
+
file: relativePath,
|
|
151
|
+
reason: 'format-ast-build-failed',
|
|
152
|
+
details: `Could not build AST for: "${formatStr.text}"`,
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const exprContainer = t.jsxExpressionContainer(astExpr);
|
|
157
|
+
jsxPath.replaceWith(exprContainer);
|
|
158
|
+
const replacementCode = (0, generator_1.generate)(astExpr).code;
|
|
159
|
+
injections.push({
|
|
160
|
+
file: relativePath,
|
|
161
|
+
line,
|
|
162
|
+
column: node.loc.start.column,
|
|
163
|
+
original: formatStr.text,
|
|
164
|
+
replacement: replacementCode,
|
|
165
|
+
key: '',
|
|
166
|
+
confidence: 100,
|
|
167
|
+
formatClass: formatStr.detectedFormat.class,
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
if (injections.length === 0)
|
|
172
|
+
continue;
|
|
173
|
+
const modifiedContent = (0, ast_helpers_1.generateCode)(ast, originalContent);
|
|
174
|
+
if (!dryRun) {
|
|
175
|
+
await (0, file_utils_1.writeFile)(filePath, modifiedContent);
|
|
176
|
+
}
|
|
177
|
+
modifiedFiles.push({
|
|
178
|
+
file: relativePath,
|
|
179
|
+
originalContent,
|
|
180
|
+
modifiedContent,
|
|
181
|
+
injections,
|
|
182
|
+
importAdded: false,
|
|
183
|
+
hookAdded: false,
|
|
184
|
+
});
|
|
185
|
+
totalInjections += injections.length;
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
skippedFiles.push({
|
|
189
|
+
file: relativePath,
|
|
190
|
+
reason: 'parse-error',
|
|
191
|
+
details: error instanceof Error ? error.message : String(error),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Process HTML files with regex-based format injection
|
|
196
|
+
const htmlExtensions = ['.html', '.htm'];
|
|
197
|
+
for (const sourceDir of workspace.sourceDirs) {
|
|
198
|
+
const dirPath = path.join(workspace.path, sourceDir);
|
|
199
|
+
const files = await (0, file_utils_1.findFiles)(dirPath, htmlExtensions, types_1.EXCLUDED_PATTERNS);
|
|
200
|
+
for (const filePath of files) {
|
|
201
|
+
const relativePath = (0, file_utils_1.getRelativePath)(workspace.path, filePath);
|
|
202
|
+
const fileStrings = stringsByFile.get(relativePath);
|
|
203
|
+
if (!fileStrings || fileStrings.length === 0)
|
|
204
|
+
continue;
|
|
205
|
+
try {
|
|
206
|
+
const originalContent = await (0, file_utils_1.readFile)(filePath);
|
|
207
|
+
let content = originalContent;
|
|
208
|
+
const injections = [];
|
|
209
|
+
for (const formatStr of fileStrings) {
|
|
210
|
+
if (!formatStr.detectedFormat)
|
|
211
|
+
continue;
|
|
212
|
+
const escaped = formatStr.text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
213
|
+
const regex = new RegExp(escaped, 'g');
|
|
214
|
+
if (!regex.test(content))
|
|
215
|
+
continue;
|
|
216
|
+
const astExpr = (0, inject_formats_1.buildFormatAstExpression)(formatStr.detectedFormat, formatConfig, localeExpr);
|
|
217
|
+
if (!astExpr)
|
|
218
|
+
continue;
|
|
219
|
+
const replacementCode = (0, generator_1.generate)(astExpr).code;
|
|
220
|
+
content = content.replace(regex, replacementCode);
|
|
221
|
+
injections.push({
|
|
222
|
+
file: relativePath,
|
|
223
|
+
line: formatStr.line,
|
|
224
|
+
column: 0,
|
|
225
|
+
original: formatStr.text,
|
|
226
|
+
replacement: replacementCode,
|
|
227
|
+
key: '',
|
|
228
|
+
confidence: 100,
|
|
229
|
+
formatClass: formatStr.detectedFormat.class,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (injections.length === 0)
|
|
233
|
+
continue;
|
|
234
|
+
if (!dryRun)
|
|
235
|
+
await (0, file_utils_1.writeFile)(filePath, content);
|
|
236
|
+
modifiedFiles.push({
|
|
237
|
+
file: relativePath,
|
|
238
|
+
originalContent,
|
|
239
|
+
modifiedContent: content,
|
|
240
|
+
injections,
|
|
241
|
+
importAdded: false,
|
|
242
|
+
hookAdded: false,
|
|
243
|
+
});
|
|
244
|
+
totalInjections += injections.length;
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
skippedFiles.push({
|
|
248
|
+
file: relativePath,
|
|
249
|
+
reason: 'parse-error',
|
|
250
|
+
details: error instanceof Error ? error.message : String(error),
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return { modifiedFiles, skippedFiles, totalInjections };
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Filter format strings out of an array of extracted strings.
|
|
259
|
+
* Returns [translatableStrings, formatStrings].
|
|
260
|
+
*/
|
|
261
|
+
function partitionFormatStrings(strings) {
|
|
262
|
+
const translatable = [];
|
|
263
|
+
const format = [];
|
|
264
|
+
for (const s of strings) {
|
|
265
|
+
if (s.context === 'format-string' && s.detectedFormat) {
|
|
266
|
+
format.push(s);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
translatable.push(s);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return [translatable, format];
|
|
273
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import type { FormatLocaleConfig } from '@babelize/types';
|
|
3
|
+
import type { DetectedFormat, ExtractedString } from '../../runtime/types';
|
|
4
|
+
/**
|
|
5
|
+
* Generate the Intl.* API call string that replaces a hardcoded format value.
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* "$1,234.56" → `new Intl.NumberFormat(locale, { style: 'currency', currency: 'USD' }).format(1234.56)`
|
|
9
|
+
* "01/15/2024" → `new Intl.DateTimeFormat(locale, { month: '2-digit', day: '2-digit', year: 'numeric' }).format(new Date(2024, 0, 15))`
|
|
10
|
+
* "1,234.56" → `new Intl.NumberFormat(locale).format(1234.56)`
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateFormatExpression(format: DetectedFormat, formatConfig: FormatLocaleConfig): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Given a locale and DetectedFormat, return both the Intl.* expression
|
|
15
|
+
* and a getTranslationKey-compatible fallback string.
|
|
16
|
+
*/
|
|
17
|
+
export interface FormatInjection {
|
|
18
|
+
expression: string;
|
|
19
|
+
fallback: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function buildFormatInjection(extracted: ExtractedString, formatConfig: FormatLocaleConfig): FormatInjection | null;
|
|
22
|
+
/**
|
|
23
|
+
* Build a Babel AST Expression node for the Intl.* call that replaces
|
|
24
|
+
* a hardcoded format value. The localeExpr parameter provides the runtime
|
|
25
|
+
* locale expression (e.g., i18n.language, navigator.language).
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildFormatAstExpression(format: DetectedFormat, formatConfig: FormatLocaleConfig, localeExpr: t.Expression): t.Expression | null;
|
|
28
|
+
/**
|
|
29
|
+
* Build a locale expression based on the detected framework.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildLocaleExpression(framework: string): t.Expression;
|
|
@@ -0,0 +1,208 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateFormatExpression = generateFormatExpression;
|
|
37
|
+
exports.buildFormatInjection = buildFormatInjection;
|
|
38
|
+
exports.buildFormatAstExpression = buildFormatAstExpression;
|
|
39
|
+
exports.buildLocaleExpression = buildLocaleExpression;
|
|
40
|
+
const t = __importStar(require("@babel/types"));
|
|
41
|
+
/**
|
|
42
|
+
* Generate the Intl.* API call string that replaces a hardcoded format value.
|
|
43
|
+
*
|
|
44
|
+
* Examples:
|
|
45
|
+
* "$1,234.56" → `new Intl.NumberFormat(locale, { style: 'currency', currency: 'USD' }).format(1234.56)`
|
|
46
|
+
* "01/15/2024" → `new Intl.DateTimeFormat(locale, { month: '2-digit', day: '2-digit', year: 'numeric' }).format(new Date(2024, 0, 15))`
|
|
47
|
+
* "1,234.56" → `new Intl.NumberFormat(locale).format(1234.56)`
|
|
48
|
+
*/
|
|
49
|
+
function generateFormatExpression(format, formatConfig) {
|
|
50
|
+
switch (format.class) {
|
|
51
|
+
case 'currency':
|
|
52
|
+
return generateCurrencyExpression(format, formatConfig);
|
|
53
|
+
case 'date':
|
|
54
|
+
return generateDateExpression(format, formatConfig);
|
|
55
|
+
case 'number':
|
|
56
|
+
return generateNumberExpression(format, formatConfig);
|
|
57
|
+
default:
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function generateCurrencyExpression(format, formatConfig) {
|
|
62
|
+
const currencyCode = format.detectedCurrency || formatConfig.currency?.code || 'USD';
|
|
63
|
+
const numericValue = parseNumericValue(format.rawValue);
|
|
64
|
+
if (isNaN(numericValue)) {
|
|
65
|
+
return JSON.stringify(format.originalString);
|
|
66
|
+
}
|
|
67
|
+
return `new Intl.NumberFormat(locale, { style: 'currency', currency: '${currencyCode}' }).format(${numericValue})`;
|
|
68
|
+
}
|
|
69
|
+
function generateDateExpression(format, _formatConfig) {
|
|
70
|
+
const date = parseDateValue(format.rawValue, format.dateSource);
|
|
71
|
+
if (!date) {
|
|
72
|
+
return JSON.stringify(format.originalString);
|
|
73
|
+
}
|
|
74
|
+
const dateOptions = format.dateOptions || { year: 'numeric', month: '2-digit', day: '2-digit' };
|
|
75
|
+
const dateOptionsStr = JSON.stringify(dateOptions);
|
|
76
|
+
return `new Intl.DateTimeFormat(locale, ${dateOptionsStr}).format(new Date(${date.getTime()}))`;
|
|
77
|
+
}
|
|
78
|
+
function generateNumberExpression(format, _formatConfig) {
|
|
79
|
+
const numericValue = parseNumericValue(format.rawValue);
|
|
80
|
+
if (isNaN(numericValue)) {
|
|
81
|
+
return JSON.stringify(format.originalString);
|
|
82
|
+
}
|
|
83
|
+
const options = { ...format.numberOptions };
|
|
84
|
+
return `new Intl.NumberFormat(locale, ${JSON.stringify(options)}).format(${numericValue})`;
|
|
85
|
+
}
|
|
86
|
+
function parseNumericValue(rawValue) {
|
|
87
|
+
const cleaned = rawValue.replace(/[^0-9.,-]/g, '');
|
|
88
|
+
const normalized = cleaned.replace(/,/g, '');
|
|
89
|
+
return parseFloat(normalized);
|
|
90
|
+
}
|
|
91
|
+
function parseDateValue(rawValue, source) {
|
|
92
|
+
// Remove ordinal suffixes like "th", "nd", "st", "rd"
|
|
93
|
+
const cleaned = rawValue.replace(/(\d+)(st|nd|rd|th)/, '$1');
|
|
94
|
+
switch (source) {
|
|
95
|
+
case 'MM/DD/YYYY': {
|
|
96
|
+
const parts = cleaned.split(/[/]/);
|
|
97
|
+
if (parts.length !== 3)
|
|
98
|
+
return null;
|
|
99
|
+
return new Date(parseInt(parts[2]), parseInt(parts[0]) - 1, parseInt(parts[1]));
|
|
100
|
+
}
|
|
101
|
+
case 'DD/MM/YYYY': {
|
|
102
|
+
const parts = cleaned.split(/[/]/);
|
|
103
|
+
if (parts.length !== 3)
|
|
104
|
+
return null;
|
|
105
|
+
return new Date(parseInt(parts[2]), parseInt(parts[1]) - 1, parseInt(parts[0]));
|
|
106
|
+
}
|
|
107
|
+
case 'YYYY-MM-DD': {
|
|
108
|
+
const parts = cleaned.split(/[-/]/);
|
|
109
|
+
if (parts.length !== 3)
|
|
110
|
+
return null;
|
|
111
|
+
return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]));
|
|
112
|
+
}
|
|
113
|
+
case 'DD.MM.YYYY': {
|
|
114
|
+
const parts = cleaned.split('.');
|
|
115
|
+
if (parts.length !== 3)
|
|
116
|
+
return null;
|
|
117
|
+
return new Date(parseInt(parts[2]), parseInt(parts[1]) - 1, parseInt(parts[0]));
|
|
118
|
+
}
|
|
119
|
+
case 'MMM DD, YYYY': {
|
|
120
|
+
return new Date(cleaned);
|
|
121
|
+
}
|
|
122
|
+
case 'DD MMM YYYY': {
|
|
123
|
+
return new Date(cleaned);
|
|
124
|
+
}
|
|
125
|
+
default: {
|
|
126
|
+
return new Date(cleaned);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function buildFormatInjection(extracted, formatConfig) {
|
|
131
|
+
if (!extracted.detectedFormat)
|
|
132
|
+
return null;
|
|
133
|
+
const expression = generateFormatExpression(extracted.detectedFormat, formatConfig);
|
|
134
|
+
if (!expression)
|
|
135
|
+
return null;
|
|
136
|
+
return {
|
|
137
|
+
expression,
|
|
138
|
+
fallback: extracted.text,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Build a Babel AST Expression node for the Intl.* call that replaces
|
|
143
|
+
* a hardcoded format value. The localeExpr parameter provides the runtime
|
|
144
|
+
* locale expression (e.g., i18n.language, navigator.language).
|
|
145
|
+
*/
|
|
146
|
+
function buildFormatAstExpression(format, formatConfig, localeExpr) {
|
|
147
|
+
switch (format.class) {
|
|
148
|
+
case 'currency':
|
|
149
|
+
return buildCurrencyAstExpression(format, formatConfig, localeExpr);
|
|
150
|
+
case 'date':
|
|
151
|
+
return buildDateAstExpression(format, localeExpr);
|
|
152
|
+
case 'number':
|
|
153
|
+
return buildNumberAstExpression(format, localeExpr);
|
|
154
|
+
default:
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function buildCurrencyAstExpression(format, formatConfig, localeExpr) {
|
|
159
|
+
const currencyCode = format.detectedCurrency || formatConfig.currency?.code || 'USD';
|
|
160
|
+
const numericValue = parseNumericValue(format.rawValue);
|
|
161
|
+
if (isNaN(numericValue))
|
|
162
|
+
return null;
|
|
163
|
+
const intlCallee = t.memberExpression(t.identifier('Intl'), t.identifier('NumberFormat'));
|
|
164
|
+
const options = t.objectExpression([
|
|
165
|
+
t.objectProperty(t.identifier('style'), t.stringLiteral('currency')),
|
|
166
|
+
t.objectProperty(t.identifier('currency'), t.stringLiteral(currencyCode)),
|
|
167
|
+
]);
|
|
168
|
+
const nfNew = t.newExpression(intlCallee, [localeExpr, options]);
|
|
169
|
+
return t.callExpression(t.memberExpression(nfNew, t.identifier('format')), [t.numericLiteral(numericValue)]);
|
|
170
|
+
}
|
|
171
|
+
function buildDateAstExpression(format, localeExpr) {
|
|
172
|
+
const date = parseDateValue(format.rawValue, format.dateSource);
|
|
173
|
+
if (!date)
|
|
174
|
+
return null;
|
|
175
|
+
const dateOptions = format.dateOptions || { year: 'numeric', month: '2-digit', day: '2-digit' };
|
|
176
|
+
const props = Object.entries(dateOptions).map(([key, val]) => t.objectProperty(t.identifier(key), t.stringLiteral(val)));
|
|
177
|
+
const intlCallee = t.memberExpression(t.identifier('Intl'), t.identifier('DateTimeFormat'));
|
|
178
|
+
const dtfNew = t.newExpression(intlCallee, [localeExpr, t.objectExpression(props)]);
|
|
179
|
+
const dateArg = t.newExpression(t.identifier('Date'), [t.numericLiteral(date.getTime())]);
|
|
180
|
+
return t.callExpression(t.memberExpression(dtfNew, t.identifier('format')), [dateArg]);
|
|
181
|
+
}
|
|
182
|
+
function buildNumberAstExpression(format, localeExpr) {
|
|
183
|
+
const numericValue = parseNumericValue(format.rawValue);
|
|
184
|
+
if (isNaN(numericValue))
|
|
185
|
+
return null;
|
|
186
|
+
const intlCallee = t.memberExpression(t.identifier('Intl'), t.identifier('NumberFormat'));
|
|
187
|
+
const args = [localeExpr];
|
|
188
|
+
const options = { ...format.numberOptions };
|
|
189
|
+
if (Object.keys(options).length > 0) {
|
|
190
|
+
const props = Object.entries(options).map(([key, val]) => t.objectProperty(t.identifier(key), t.numericLiteral(val)));
|
|
191
|
+
args.push(t.objectExpression(props));
|
|
192
|
+
}
|
|
193
|
+
const nfNew = t.newExpression(intlCallee, args);
|
|
194
|
+
return t.callExpression(t.memberExpression(nfNew, t.identifier('format')), [t.numericLiteral(numericValue)]);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Build a locale expression based on the detected framework.
|
|
198
|
+
*/
|
|
199
|
+
function buildLocaleExpression(framework) {
|
|
200
|
+
switch (framework) {
|
|
201
|
+
case 'react-i18next':
|
|
202
|
+
return t.memberExpression(t.identifier('i18n'), t.identifier('language'));
|
|
203
|
+
case 'next-intl':
|
|
204
|
+
return t.callExpression(t.identifier('useLocale'), []);
|
|
205
|
+
default:
|
|
206
|
+
return t.logicalExpression('||', t.memberExpression(t.identifier('navigator'), t.identifier('language')), t.stringLiteral('en-US'));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { canonicalLocale, canonicalizeLocaleKeys, conflictNotes, containsTerm, EMPTY_GLOSSARY, fixedTermsFor, glossaryFingerprint, hasFixedTerm, localeValue, normalizeGlossary, sourceHasTerm, termPattern, type GlossaryRuleInput, type GlossaryRules, } from './rules';
|
|
2
|
+
export type { GlossaryEntry, GlossaryEntryType, BrandVoice, AlwaysTranslateAsEntry } from './types';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.termPattern = exports.sourceHasTerm = exports.normalizeGlossary = exports.localeValue = exports.hasFixedTerm = exports.glossaryFingerprint = exports.fixedTermsFor = exports.EMPTY_GLOSSARY = exports.containsTerm = exports.conflictNotes = exports.canonicalizeLocaleKeys = exports.canonicalLocale = void 0;
|
|
4
|
+
var rules_1 = require("./rules");
|
|
5
|
+
Object.defineProperty(exports, "canonicalLocale", { enumerable: true, get: function () { return rules_1.canonicalLocale; } });
|
|
6
|
+
Object.defineProperty(exports, "canonicalizeLocaleKeys", { enumerable: true, get: function () { return rules_1.canonicalizeLocaleKeys; } });
|
|
7
|
+
Object.defineProperty(exports, "conflictNotes", { enumerable: true, get: function () { return rules_1.conflictNotes; } });
|
|
8
|
+
Object.defineProperty(exports, "containsTerm", { enumerable: true, get: function () { return rules_1.containsTerm; } });
|
|
9
|
+
Object.defineProperty(exports, "EMPTY_GLOSSARY", { enumerable: true, get: function () { return rules_1.EMPTY_GLOSSARY; } });
|
|
10
|
+
Object.defineProperty(exports, "fixedTermsFor", { enumerable: true, get: function () { return rules_1.fixedTermsFor; } });
|
|
11
|
+
Object.defineProperty(exports, "glossaryFingerprint", { enumerable: true, get: function () { return rules_1.glossaryFingerprint; } });
|
|
12
|
+
Object.defineProperty(exports, "hasFixedTerm", { enumerable: true, get: function () { return rules_1.hasFixedTerm; } });
|
|
13
|
+
Object.defineProperty(exports, "localeValue", { enumerable: true, get: function () { return rules_1.localeValue; } });
|
|
14
|
+
Object.defineProperty(exports, "normalizeGlossary", { enumerable: true, get: function () { return rules_1.normalizeGlossary; } });
|
|
15
|
+
Object.defineProperty(exports, "sourceHasTerm", { enumerable: true, get: function () { return rules_1.sourceHasTerm; } });
|
|
16
|
+
Object.defineProperty(exports, "termPattern", { enumerable: true, get: function () { return rules_1.termPattern; } });
|