@babelize/engine 0.0.0-stage → 0.1.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/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/index.d.ts +54 -0
- package/dist/index.js +126 -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/django/django-template-injector.d.ts +29 -0
- package/dist/injection/django/django-template-injector.js +216 -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 +207 -0
- package/dist/local/report.d.ts +177 -0
- package/dist/local/report.js +186 -0
- package/dist/local/translate-core.d.ts +215 -0
- package/dist/local/translate-core.js +461 -0
- package/dist/local/translate-messages.d.ts +49 -0
- package/dist/local/translate-messages.js +91 -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 +701 -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 +13 -0
- package/dist/modules/finalization/django-finalize.js +275 -0
- package/dist/modules/finalization/finalize.d.ts +36 -0
- package/dist/modules/finalization/finalize.js +717 -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 +37 -0
- package/dist/modules/finalization/nextjs-finalize.js +329 -0
- package/dist/modules/finalization/static-runtime.d.ts +9 -0
- package/dist/modules/finalization/static-runtime.js +261 -0
- package/dist/modules/format-injection/index.d.ts +19 -0
- package/dist/modules/format-injection/index.js +272 -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/glossary.d.ts +9 -0
- package/dist/modules/glossary/glossary.js +27 -0
- package/dist/modules/glossary/index.d.ts +3 -0
- package/dist/modules/glossary/index.js +8 -0
- package/dist/modules/glossary/masker.d.ts +23 -0
- package/dist/modules/glossary/masker.js +56 -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 +1066 -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 +116 -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 +107 -0
- package/dist/modules/locale-builder/po.d.ts +33 -0
- package/dist/modules/locale-builder/po.js +131 -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 +21 -0
- package/dist/modules/lockfile/lockfile-manager.d.ts +90 -0
- package/dist/modules/lockfile/lockfile-manager.js +482 -0
- package/dist/modules/lockfile/schema.d.ts +154 -0
- package/dist/modules/lockfile/schema.js +45 -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/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 +38 -0
- package/dist/modules/translator/translate.js +932 -0
- package/dist/modules/translator/translator.d.ts +5 -0
- package/dist/modules/translator/translator.js +46 -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 +298 -0
- package/dist/orchestrator.d.ts +8 -0
- package/dist/orchestrator.js +616 -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 +145 -0
- package/dist/providers/types.js +2 -0
- package/dist/qa/check-project.d.ts +49 -0
- package/dist/qa/check-project.js +150 -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 +325 -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 +36 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/types.d.ts +363 -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/dtl-mask.d.ts +25 -0
- package/dist/utils/dtl-mask.js +58 -0
- package/dist/utils/extraction-options.d.ts +23 -0
- package/dist/utils/extraction-options.js +23 -0
- package/dist/utils/file-utils.d.ts +33 -0
- package/dist/utils/file-utils.js +262 -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 +621 -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 +80 -0
- package/dist/utils/metadata.js +255 -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 +36 -0
- package/dist/utils/placeholder-protection.d.ts +57 -0
- package/dist/utils/placeholder-protection.js +136 -0
- package/dist/utils/pseudo-markers.d.ts +9 -0
- package/dist/utils/pseudo-markers.js +16 -0
- package/dist/utils/py-extractor.d.ts +14 -0
- package/dist/utils/py-extractor.js +285 -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 +10 -0
- package/dist/utils/translation-sanitizer.js +57 -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 +293 -0
- package/dist/utils/ui-copy.d.ts +32 -0
- package/dist/utils/ui-copy.js +126 -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,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Translator Load Balancer
|
|
4
|
+
*
|
|
5
|
+
* Manages multiple translator endpoints with:
|
|
6
|
+
* - Health checking
|
|
7
|
+
* - Round-robin load balancing
|
|
8
|
+
* - Automatic failover on errors
|
|
9
|
+
* - Circuit breaker per endpoint
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.translatorLoadBalancer = void 0;
|
|
13
|
+
exports.getTranslatorLoadBalancer = getTranslatorLoadBalancer;
|
|
14
|
+
const circuit_breaker_1 = require("./circuit-breaker");
|
|
15
|
+
const logger_1 = require("./logger");
|
|
16
|
+
const DEFAULT_CONFIG = {
|
|
17
|
+
endpoints: [],
|
|
18
|
+
healthCheckInterval: 60000, // 1 minute
|
|
19
|
+
healthCheckTimeout: 10000, // 10 seconds
|
|
20
|
+
maxConsecutiveFailures: 3,
|
|
21
|
+
};
|
|
22
|
+
class TranslatorLoadBalancer {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.circuitBreakers = new Map();
|
|
25
|
+
this.healthCheckInterval = null;
|
|
26
|
+
this.currentEndpointIndex = 0;
|
|
27
|
+
this.config = { ...DEFAULT_CONFIG };
|
|
28
|
+
this.initializeEndpoints();
|
|
29
|
+
if (this.config.endpoints.length > 0) {
|
|
30
|
+
setTimeout(() => this.startHealthChecks(), 0);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Initialize endpoints from environment variable
|
|
35
|
+
* Format: url1|name1,url2|name2 or just url1,url2
|
|
36
|
+
*/
|
|
37
|
+
initializeEndpoints() {
|
|
38
|
+
const translatorUrl = process.env.TRANSLATOR_URL;
|
|
39
|
+
const backupUrl = process.env.TRANSLATOR_BACKUP_URL;
|
|
40
|
+
const endpoints = [];
|
|
41
|
+
// Primary endpoint
|
|
42
|
+
if (translatorUrl) {
|
|
43
|
+
endpoints.push({
|
|
44
|
+
url: translatorUrl,
|
|
45
|
+
name: 'primary',
|
|
46
|
+
priority: 1,
|
|
47
|
+
isHealthy: true,
|
|
48
|
+
lastHealthCheck: null,
|
|
49
|
+
consecutiveFailures: 0,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Backup endpoint
|
|
53
|
+
if (backupUrl) {
|
|
54
|
+
endpoints.push({
|
|
55
|
+
url: backupUrl,
|
|
56
|
+
name: 'backup',
|
|
57
|
+
priority: 2,
|
|
58
|
+
isHealthy: true,
|
|
59
|
+
lastHealthCheck: null,
|
|
60
|
+
consecutiveFailures: 0,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Parse additional endpoints from TRANSLATOR_ENDPOINTS env var
|
|
64
|
+
// Format: url1|name1,url2|name2
|
|
65
|
+
const additionalEndpoints = process.env.TRANSLATOR_ENDPOINTS;
|
|
66
|
+
if (additionalEndpoints) {
|
|
67
|
+
additionalEndpoints.split(',').forEach((entry, index) => {
|
|
68
|
+
const [url, name] = entry.trim().split('|');
|
|
69
|
+
if (url) {
|
|
70
|
+
endpoints.push({
|
|
71
|
+
url: url.trim(),
|
|
72
|
+
name: name?.trim() || `endpoint-${index + 3}`,
|
|
73
|
+
priority: index + 3,
|
|
74
|
+
isHealthy: true,
|
|
75
|
+
lastHealthCheck: null,
|
|
76
|
+
consecutiveFailures: 0,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
this.config.endpoints = endpoints;
|
|
82
|
+
// Create circuit breaker for each endpoint
|
|
83
|
+
endpoints.forEach(endpoint => {
|
|
84
|
+
this.circuitBreakers.set(endpoint.name, (0, circuit_breaker_1.getCircuitBreaker)(`translator-${endpoint.name}`, {
|
|
85
|
+
failureThreshold: 5,
|
|
86
|
+
resetTimeout: 30000,
|
|
87
|
+
halfOpenMaxCalls: 3,
|
|
88
|
+
}));
|
|
89
|
+
});
|
|
90
|
+
logger_1.engineLogger.info('Translator load balancer initialized', {
|
|
91
|
+
endpointCount: endpoints.length,
|
|
92
|
+
endpoints: endpoints.map(e => ({ name: e.name, url: e.url.substring(0, 50) })),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the next healthy endpoint using weighted round-robin
|
|
97
|
+
*/
|
|
98
|
+
getNextEndpoint() {
|
|
99
|
+
const healthyEndpoints = this.config.endpoints
|
|
100
|
+
.filter(e => e.isHealthy)
|
|
101
|
+
.sort((a, b) => a.priority - b.priority);
|
|
102
|
+
if (healthyEndpoints.length === 0) {
|
|
103
|
+
// All endpoints unhealthy, try primary anyway
|
|
104
|
+
if (this.config.endpoints.length > 0) {
|
|
105
|
+
logger_1.engineLogger.warn('All translator endpoints unhealthy, attempting primary');
|
|
106
|
+
return this.config.endpoints[0];
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
// Round-robin among healthy endpoints
|
|
111
|
+
const endpoint = healthyEndpoints[this.currentEndpointIndex % healthyEndpoints.length];
|
|
112
|
+
this.currentEndpointIndex++;
|
|
113
|
+
return endpoint;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Mark an endpoint as failed
|
|
117
|
+
*/
|
|
118
|
+
markEndpointFailed(endpoint) {
|
|
119
|
+
endpoint.consecutiveFailures++;
|
|
120
|
+
if (endpoint.consecutiveFailures >= this.config.maxConsecutiveFailures) {
|
|
121
|
+
endpoint.isHealthy = false;
|
|
122
|
+
logger_1.engineLogger.warn('Translator endpoint marked unhealthy', {
|
|
123
|
+
name: endpoint.name,
|
|
124
|
+
failures: endpoint.consecutiveFailures,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Mark an endpoint as successful
|
|
130
|
+
*/
|
|
131
|
+
markEndpointSuccess(endpoint) {
|
|
132
|
+
if (!endpoint.isHealthy || endpoint.consecutiveFailures > 0) {
|
|
133
|
+
logger_1.engineLogger.info('Translator endpoint recovered', { name: endpoint.name });
|
|
134
|
+
}
|
|
135
|
+
endpoint.consecutiveFailures = 0;
|
|
136
|
+
endpoint.isHealthy = true;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Execute a translation request with automatic failover and exponential backoff
|
|
140
|
+
*/
|
|
141
|
+
async executeWithFailover(requestFn) {
|
|
142
|
+
const maxAttempts = parseInt(process.env.TRANSLATOR_RETRY_ATTEMPTS || '2');
|
|
143
|
+
const triedEndpoints = [];
|
|
144
|
+
let lastError = null;
|
|
145
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
146
|
+
const endpoint = this.getNextEndpoint();
|
|
147
|
+
if (!endpoint) {
|
|
148
|
+
// No endpoints available
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
if (triedEndpoints.includes(endpoint.name)) {
|
|
152
|
+
// If we've already tried this endpoint, allow retry only when
|
|
153
|
+
// it's the only endpoint available (otherwise cycle to next)
|
|
154
|
+
const healthyEndpoints = this.config.endpoints.filter(e => e.isHealthy);
|
|
155
|
+
if (healthyEndpoints.length > 1) {
|
|
156
|
+
continue; // Skip to next round-robin pick
|
|
157
|
+
}
|
|
158
|
+
// Single endpoint — retrying it is our only option
|
|
159
|
+
}
|
|
160
|
+
if (!triedEndpoints.includes(endpoint.name)) {
|
|
161
|
+
triedEndpoints.push(endpoint.name);
|
|
162
|
+
}
|
|
163
|
+
const circuitBreaker = this.circuitBreakers.get(endpoint.name);
|
|
164
|
+
try {
|
|
165
|
+
const result = await (circuitBreaker
|
|
166
|
+
? circuitBreaker.execute(() => requestFn(endpoint.url))
|
|
167
|
+
: requestFn(endpoint.url));
|
|
168
|
+
this.markEndpointSuccess(endpoint);
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
173
|
+
this.markEndpointFailed(endpoint);
|
|
174
|
+
logger_1.engineLogger.warn('Translator endpoint failed, trying fallback', {
|
|
175
|
+
endpoint: endpoint.name,
|
|
176
|
+
error: lastError.message,
|
|
177
|
+
attempt: attempt + 1,
|
|
178
|
+
maxAttempts,
|
|
179
|
+
});
|
|
180
|
+
// Exponential backoff with jitter before next attempt
|
|
181
|
+
// Only delay if we have more attempts remaining
|
|
182
|
+
if (attempt < maxAttempts - 1) {
|
|
183
|
+
const baseDelay = Math.min(200 * Math.pow(2, attempt), 3000); // Max 3s
|
|
184
|
+
const jitter = Math.random() * 200; // 0-200ms jitter
|
|
185
|
+
const delay = baseDelay + jitter;
|
|
186
|
+
logger_1.engineLogger.info('Waiting before retry', {
|
|
187
|
+
delayMs: Math.round(delay),
|
|
188
|
+
nextAttempt: attempt + 2
|
|
189
|
+
});
|
|
190
|
+
await this.sleep(delay);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const endpointsTried = triedEndpoints.length > 0
|
|
195
|
+
? `tried endpoints: [${triedEndpoints.join(', ')}]`
|
|
196
|
+
: 'no endpoints available';
|
|
197
|
+
throw lastError
|
|
198
|
+
? new Error(`Translator request failed after ${maxAttempts} attempts (${endpointsTried}): ${lastError.message}`)
|
|
199
|
+
: new Error(`All translator endpoints failed (${endpointsTried})`);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Sleep utility
|
|
203
|
+
*/
|
|
204
|
+
sleep(ms) {
|
|
205
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Perform health check on all endpoints
|
|
209
|
+
*/
|
|
210
|
+
async healthCheck() {
|
|
211
|
+
const results = {};
|
|
212
|
+
for (const endpoint of this.config.endpoints) {
|
|
213
|
+
let timeout;
|
|
214
|
+
try {
|
|
215
|
+
const controller = new AbortController();
|
|
216
|
+
timeout = setTimeout(() => controller.abort(), this.config.healthCheckTimeout);
|
|
217
|
+
const response = await fetch(`${endpoint.url}/health`, {
|
|
218
|
+
method: 'GET',
|
|
219
|
+
signal: controller.signal,
|
|
220
|
+
});
|
|
221
|
+
const isHealthy = response.ok;
|
|
222
|
+
endpoint.isHealthy = isHealthy;
|
|
223
|
+
endpoint.lastHealthCheck = new Date();
|
|
224
|
+
if (isHealthy) {
|
|
225
|
+
endpoint.consecutiveFailures = 0;
|
|
226
|
+
// Reset the circuit breaker so subsequent calls don't fail immediately
|
|
227
|
+
const cb = this.circuitBreakers.get(endpoint.name);
|
|
228
|
+
if (cb) {
|
|
229
|
+
cb.reset();
|
|
230
|
+
logger_1.engineLogger.info('Circuit breaker reset after healthy health check', { endpoint: endpoint.name });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
results[endpoint.name] = isHealthy;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
endpoint.isHealthy = false;
|
|
237
|
+
endpoint.lastHealthCheck = new Date();
|
|
238
|
+
results[endpoint.name] = false;
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
clearTimeout(timeout);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Start periodic health checks
|
|
248
|
+
*/
|
|
249
|
+
startHealthChecks() {
|
|
250
|
+
if (this.healthCheckInterval)
|
|
251
|
+
return;
|
|
252
|
+
this.healthCheckInterval = setInterval(() => this.healthCheck(), this.config.healthCheckInterval);
|
|
253
|
+
// Initial health check
|
|
254
|
+
this.healthCheck();
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Stop periodic health checks
|
|
258
|
+
*/
|
|
259
|
+
stopHealthChecks() {
|
|
260
|
+
if (this.healthCheckInterval) {
|
|
261
|
+
clearInterval(this.healthCheckInterval);
|
|
262
|
+
this.healthCheckInterval = null;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Get current status of all endpoints
|
|
267
|
+
*/
|
|
268
|
+
getStatus() {
|
|
269
|
+
return this.config.endpoints.map(e => ({
|
|
270
|
+
name: e.name,
|
|
271
|
+
url: e.url.substring(0, 50) + (e.url.length > 50 ? '...' : ''),
|
|
272
|
+
isHealthy: e.isHealthy,
|
|
273
|
+
failures: e.consecutiveFailures,
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Singleton instance
|
|
278
|
+
// Created on first use, not at import: the constructor reads TRANSLATOR_*
|
|
279
|
+
// env vars and starts health checks, and importing @babelize/engine must not
|
|
280
|
+
// do either — a host may load its env (dotenv, test setup) after the import.
|
|
281
|
+
let instance = null;
|
|
282
|
+
function getTranslatorLoadBalancer() {
|
|
283
|
+
if (!instance)
|
|
284
|
+
instance = new TranslatorLoadBalancer();
|
|
285
|
+
return instance;
|
|
286
|
+
}
|
|
287
|
+
exports.translatorLoadBalancer = new Proxy({}, {
|
|
288
|
+
get(_target, prop) {
|
|
289
|
+
const lb = getTranslatorLoadBalancer();
|
|
290
|
+
const value = Reflect.get(lb, prop, lb);
|
|
291
|
+
return typeof value === 'function' ? value.bind(lb) : value;
|
|
292
|
+
},
|
|
293
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
/**
|
|
3
|
+
* UI copy vs program data in object / array / variable initializers.
|
|
4
|
+
*
|
|
5
|
+
* `const user = { name: "Ada" }` is data: translating it rewrites a user's
|
|
6
|
+
* name (`{ name: t("page.ada") }`). `[{ label: "Home", href: "/" }]` holds UI
|
|
7
|
+
* copy under `label` and data under `href`. A string in an initializer is
|
|
8
|
+
* only extracted when its key says it's copy, or (without a telling key) when
|
|
9
|
+
* it looks like copy: a sentence, a Title Case phrase or a capitalized word.
|
|
10
|
+
* Both lists match the key's last camelCase word (`buttonLabel` → label,
|
|
11
|
+
* `firstName` → name) or the whole key, case-insensitively, and can be
|
|
12
|
+
* extended by callers.
|
|
13
|
+
*/
|
|
14
|
+
export declare const UI_COPY_KEYS: Set<string>;
|
|
15
|
+
export declare const DATA_KEYS: Set<string>;
|
|
16
|
+
/** Two or more words with letters: reads like copy, not an identifier. */
|
|
17
|
+
export declare function isMultiWordCopy(text: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Copy without a key to say so: a sentence or Title Case phrase, or a single
|
|
20
|
+
* capitalized word ("Overview", "Settings"). Data looks different: lowercase
|
|
21
|
+
* tokens ("active"), kebab/snake/camelCase, ALLCAPS, or anything with digits,
|
|
22
|
+
* underscores, slashes or dots in a single token.
|
|
23
|
+
*/
|
|
24
|
+
export declare function looksLikeCopy(text: string): boolean;
|
|
25
|
+
/** Whether a string stored under `name` (a key or a variable) is UI copy. */
|
|
26
|
+
export declare function isUiCopyForName(name: string | null, text: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* For a string literal in an object property value, array element or
|
|
29
|
+
* variable/assignment initializer: is it UI copy? Other positions (JSX,
|
|
30
|
+
* returns, conditionals, …) aren't initializers and are left as they are.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isUiCopyLiteral(node: t.Node, parent: t.Node | null | undefined, text: string): boolean;
|
|
@@ -0,0 +1,126 @@
|
|
|
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.DATA_KEYS = exports.UI_COPY_KEYS = void 0;
|
|
37
|
+
exports.isMultiWordCopy = isMultiWordCopy;
|
|
38
|
+
exports.looksLikeCopy = looksLikeCopy;
|
|
39
|
+
exports.isUiCopyForName = isUiCopyForName;
|
|
40
|
+
exports.isUiCopyLiteral = isUiCopyLiteral;
|
|
41
|
+
const t = __importStar(require("@babel/types"));
|
|
42
|
+
/**
|
|
43
|
+
* UI copy vs program data in object / array / variable initializers.
|
|
44
|
+
*
|
|
45
|
+
* `const user = { name: "Ada" }` is data: translating it rewrites a user's
|
|
46
|
+
* name (`{ name: t("page.ada") }`). `[{ label: "Home", href: "/" }]` holds UI
|
|
47
|
+
* copy under `label` and data under `href`. A string in an initializer is
|
|
48
|
+
* only extracted when its key says it's copy, or (without a telling key) when
|
|
49
|
+
* it looks like copy: a sentence, a Title Case phrase or a capitalized word.
|
|
50
|
+
* Both lists match the key's last camelCase word (`buttonLabel` → label,
|
|
51
|
+
* `firstName` → name) or the whole key, case-insensitively, and can be
|
|
52
|
+
* extended by callers.
|
|
53
|
+
*/
|
|
54
|
+
exports.UI_COPY_KEYS = new Set([
|
|
55
|
+
'label', 'title', 'description', 'placeholder', 'text', 'message', 'heading', 'subheading', 'headline', 'subtitle',
|
|
56
|
+
'tooltip', 'cta', 'alt', 'arialabel', 'caption', 'hint', 'help', 'helptext', 'summary', 'body', 'question',
|
|
57
|
+
'answer', 'notice', 'error', 'success', 'warning', 'confirm', 'prompt', 'greeting', 'tagline', 'blurb', 'excerpt',
|
|
58
|
+
]);
|
|
59
|
+
exports.DATA_KEYS = new Set([
|
|
60
|
+
'name', 'id', 'key', 'email', 'username', 'slug', 'url', 'href', 'src', 'path', 'type', 'value', 'code', 'locale',
|
|
61
|
+
'lang', 'language', 'classname', 'class', 'variant', 'color', 'colour', 'icon', 'date', 'currency', 'size', 'status',
|
|
62
|
+
'role', 'method', 'format', 'mode', 'theme', 'target', 'rel', 'route', 'to', 'link', 'ref', 'uuid', 'token',
|
|
63
|
+
'phone', 'address', 'image', 'avatar', 'file', 'filename', 'extension', 'mime', 'kind', 'timezone', 'country',
|
|
64
|
+
'handle', 'domain', 'host', 'endpoint', 'version', 'sku', 'hash', 'secret', 'password', 'field', 'event', 'action',
|
|
65
|
+
'user', 'author', 'owner', 'customer', 'company', 'brand', 'city', 'state', 'zip', 'region',
|
|
66
|
+
]);
|
|
67
|
+
function words(name) {
|
|
68
|
+
return name.split(/(?=[A-Z])|[-_\s]/).filter(Boolean).map((w) => w.toLowerCase());
|
|
69
|
+
}
|
|
70
|
+
/** Two or more words with letters: reads like copy, not an identifier. */
|
|
71
|
+
function isMultiWordCopy(text) {
|
|
72
|
+
return text.trim().split(/\s+/).filter((w) => /\p{L}/u.test(w)).length >= 2;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Copy without a key to say so: a sentence or Title Case phrase, or a single
|
|
76
|
+
* capitalized word ("Overview", "Settings"). Data looks different: lowercase
|
|
77
|
+
* tokens ("active"), kebab/snake/camelCase, ALLCAPS, or anything with digits,
|
|
78
|
+
* underscores, slashes or dots in a single token.
|
|
79
|
+
*/
|
|
80
|
+
function looksLikeCopy(text) {
|
|
81
|
+
const trimmed = text.trim();
|
|
82
|
+
if (isMultiWordCopy(trimmed))
|
|
83
|
+
return true;
|
|
84
|
+
return /^\p{Lu}\p{Ll}+[!?.:…]?$/u.test(trimmed);
|
|
85
|
+
}
|
|
86
|
+
/** Whether a string stored under `name` (a key or a variable) is UI copy. */
|
|
87
|
+
function isUiCopyForName(name, text) {
|
|
88
|
+
if (name) {
|
|
89
|
+
const parts = words(name);
|
|
90
|
+
const last = parts[parts.length - 1] ?? '';
|
|
91
|
+
const full = name.toLowerCase().replace(/[-_]/g, '');
|
|
92
|
+
if (exports.UI_COPY_KEYS.has(last) || exports.UI_COPY_KEYS.has(full))
|
|
93
|
+
return true;
|
|
94
|
+
if (exports.DATA_KEYS.has(last) || exports.DATA_KEYS.has(full))
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return looksLikeCopy(text);
|
|
98
|
+
}
|
|
99
|
+
function keyName(key) {
|
|
100
|
+
if (t.isIdentifier(key))
|
|
101
|
+
return key.name;
|
|
102
|
+
if (t.isStringLiteral(key))
|
|
103
|
+
return key.value;
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* For a string literal in an object property value, array element or
|
|
108
|
+
* variable/assignment initializer: is it UI copy? Other positions (JSX,
|
|
109
|
+
* returns, conditionals, …) aren't initializers and are left as they are.
|
|
110
|
+
*/
|
|
111
|
+
function isUiCopyLiteral(node, parent, text) {
|
|
112
|
+
if (!parent)
|
|
113
|
+
return true;
|
|
114
|
+
if (t.isObjectProperty(parent) && parent.value === node)
|
|
115
|
+
return isUiCopyForName(parent.computed ? null : keyName(parent.key), text);
|
|
116
|
+
if (t.isVariableDeclarator(parent) && parent.init === node)
|
|
117
|
+
return isUiCopyForName(t.isIdentifier(parent.id) ? parent.id.name : null, text);
|
|
118
|
+
if (t.isAssignmentExpression(parent) && parent.right === node) {
|
|
119
|
+
const left = parent.left;
|
|
120
|
+
const name = t.isIdentifier(left) ? left.name : t.isMemberExpression(left) && !left.computed && t.isIdentifier(left.property) ? left.property.name : null;
|
|
121
|
+
return isUiCopyForName(name, text);
|
|
122
|
+
}
|
|
123
|
+
if (t.isArrayExpression(parent))
|
|
124
|
+
return looksLikeCopy(text);
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove stale locale files from the workspace that are NOT in the target locale list.
|
|
3
|
+
*
|
|
4
|
+
* When a project is re-run with changed languages, old locale files from previous
|
|
5
|
+
* runs persist because `git reset --hard` only resets tracked files and generated
|
|
6
|
+
* locale files are untracked. This function cleans them up.
|
|
7
|
+
*
|
|
8
|
+
* @param workspacePath - Path to the workspace directory
|
|
9
|
+
* @param targetLocales - Current list of target locale codes (e.g., ['fr', 'de'])
|
|
10
|
+
* @param sourceLocale - Source locale code (e.g., 'en') — always preserved
|
|
11
|
+
* @param localeFormat - Output format ('json' | 'po' | 'arb')
|
|
12
|
+
* @param publicDir - Public directory relative to workspace (e.g., 'public')
|
|
13
|
+
*/
|
|
14
|
+
export declare function removeStaleLocales(workspacePath: string, targetLocales: string[], sourceLocale: string, localeFormat?: string, publicDir?: string): Promise<void>;
|
|
@@ -0,0 +1,89 @@
|
|
|
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.removeStaleLocales = removeStaleLocales;
|
|
37
|
+
const fs = __importStar(require("fs-extra"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const file_utils_1 = require("./file-utils");
|
|
40
|
+
const logger_1 = require("./logger");
|
|
41
|
+
/**
|
|
42
|
+
* Remove stale locale files from the workspace that are NOT in the target locale list.
|
|
43
|
+
*
|
|
44
|
+
* When a project is re-run with changed languages, old locale files from previous
|
|
45
|
+
* runs persist because `git reset --hard` only resets tracked files and generated
|
|
46
|
+
* locale files are untracked. This function cleans them up.
|
|
47
|
+
*
|
|
48
|
+
* @param workspacePath - Path to the workspace directory
|
|
49
|
+
* @param targetLocales - Current list of target locale codes (e.g., ['fr', 'de'])
|
|
50
|
+
* @param sourceLocale - Source locale code (e.g., 'en') — always preserved
|
|
51
|
+
* @param localeFormat - Output format ('json' | 'po' | 'arb')
|
|
52
|
+
* @param publicDir - Public directory relative to workspace (e.g., 'public')
|
|
53
|
+
*/
|
|
54
|
+
async function removeStaleLocales(workspacePath, targetLocales, sourceLocale, localeFormat = 'json', publicDir = 'public') {
|
|
55
|
+
// Django uses locale/<lang>/LC_MESSAGES/ — skip stale locale removal for PO format
|
|
56
|
+
if (localeFormat === 'po')
|
|
57
|
+
return;
|
|
58
|
+
const localesDir = path.join(workspacePath, publicDir, 'locales');
|
|
59
|
+
if (!(await fs.pathExists(localesDir))) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const ext = (0, file_utils_1.localeExtension)(localeFormat);
|
|
63
|
+
const allowedLocales = new Set([sourceLocale, ...targetLocales]);
|
|
64
|
+
try {
|
|
65
|
+
const entries = await fs.readdir(localesDir);
|
|
66
|
+
let removedCount = 0;
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
if (!entry.endsWith(ext))
|
|
69
|
+
continue;
|
|
70
|
+
const localeCode = entry.replace(ext, '');
|
|
71
|
+
if (!allowedLocales.has(localeCode)) {
|
|
72
|
+
const filePath = path.join(localesDir, entry);
|
|
73
|
+
await fs.remove(filePath);
|
|
74
|
+
removedCount++;
|
|
75
|
+
logger_1.engineLogger.debug('Removed stale locale file', { file: entry, localeCode });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (removedCount > 0) {
|
|
79
|
+
logger_1.engineLogger.info('Cleaned up stale locale files', {
|
|
80
|
+
removedCount,
|
|
81
|
+
keptLocales: [...allowedLocales],
|
|
82
|
+
workspacePath,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
logger_1.engineLogger.warn('Failed to clean up stale locale files', { error: err, workspacePath });
|
|
88
|
+
}
|
|
89
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,66 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@babelize/engine",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Babelize translation pipeline (extract, keygen, translate, inject). Infrastructure is injected through provider/store interfaces.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"babelize",
|
|
7
|
+
"i18n",
|
|
8
|
+
"localization",
|
|
9
|
+
"translation",
|
|
10
|
+
"ast"
|
|
11
|
+
],
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"homepage": "https://babelize.co",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/babelize/babelize-dashboard.git"
|
|
17
|
+
},
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"schemas"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "eslint src",
|
|
31
|
+
"test": "jest",
|
|
32
|
+
"prepublishOnly": "npm run build && npm test && npm run typecheck"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@babel/generator": "^7.28.5",
|
|
36
|
+
"@babel/parser": "^7.28.5",
|
|
37
|
+
"@babel/traverse": "^7.28.5",
|
|
38
|
+
"@babel/types": "^7.29.8",
|
|
39
|
+
"@babelize/types": "^0.1.1",
|
|
40
|
+
"@vue/compiler-dom": "^3.5",
|
|
41
|
+
"@vue/compiler-sfc": "^3.5",
|
|
42
|
+
"diff": "^8.0.4",
|
|
43
|
+
"fast-glob": "^3.3.3",
|
|
44
|
+
"fs-extra": "^11.3.3",
|
|
45
|
+
"gettext-parser": "^9.1.1",
|
|
46
|
+
"magic-string": "^0.30",
|
|
47
|
+
"node-html-parser": "^8.0.4",
|
|
48
|
+
"zod": "^3.22.4"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@eslint/js": "^9.39.2",
|
|
52
|
+
"@jest/globals": "^30.3.0",
|
|
53
|
+
"@types/babel__generator": "^7.27.0",
|
|
54
|
+
"@types/babel__traverse": "^7.28.0",
|
|
55
|
+
"@types/fs-extra": "^11.0.4",
|
|
56
|
+
"@types/jest": "^30.0.0",
|
|
57
|
+
"@types/node": "^25.0.3",
|
|
58
|
+
"ajv": "^8.17.1",
|
|
59
|
+
"eslint": "^9.39.2",
|
|
60
|
+
"intl-messageformat": "^10.7.16",
|
|
61
|
+
"jest": "^30.2.0",
|
|
62
|
+
"ts-jest": "^29.4.6",
|
|
63
|
+
"typescript": "^5.9.3",
|
|
64
|
+
"typescript-eslint": "^8.53.1"
|
|
65
|
+
}
|
|
66
|
+
}
|