@digitaldefiance/express-suite-starter 4.24.0 → 4.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/programmatic-generator.d.ts.map +1 -1
- package/dist/src/core/programmatic-generator.js +7 -4
- package/dist/src/core/programmatic-generator.js.map +1 -1
- package/dist/src/generate-monorepo.d.ts.map +1 -1
- package/dist/src/generate-monorepo.js +149 -53
- package/dist/src/generate-monorepo.js.map +1 -1
- package/dist/src/i18n/starter-string-key.d.ts +18 -1
- package/dist/src/i18n/starter-string-key.d.ts.map +1 -1
- package/dist/src/i18n/starter-string-key.js +18 -0
- package/dist/src/i18n/starter-string-key.js.map +1 -1
- package/dist/src/i18n/strings/de.d.ts.map +1 -1
- package/dist/src/i18n/strings/de.js +18 -0
- package/dist/src/i18n/strings/de.js.map +1 -1
- package/dist/src/i18n/strings/en-gb.d.ts +2 -184
- package/dist/src/i18n/strings/en-gb.d.ts.map +1 -1
- package/dist/src/i18n/strings/en-gb.js +22 -1
- package/dist/src/i18n/strings/en-gb.js.map +1 -1
- package/dist/src/i18n/strings/en-us.d.ts.map +1 -1
- package/dist/src/i18n/strings/en-us.js +18 -0
- package/dist/src/i18n/strings/en-us.js.map +1 -1
- package/dist/src/i18n/strings/es.d.ts.map +1 -1
- package/dist/src/i18n/strings/es.js +18 -0
- package/dist/src/i18n/strings/es.js.map +1 -1
- package/dist/src/i18n/strings/fr.d.ts.map +1 -1
- package/dist/src/i18n/strings/fr.js +18 -0
- package/dist/src/i18n/strings/fr.js.map +1 -1
- package/dist/src/i18n/strings/ja.d.ts.map +1 -1
- package/dist/src/i18n/strings/ja.js +18 -0
- package/dist/src/i18n/strings/ja.js.map +1 -1
- package/dist/src/i18n/strings/uk.d.ts.map +1 -1
- package/dist/src/i18n/strings/uk.js +18 -0
- package/dist/src/i18n/strings/uk.js.map +1 -1
- package/dist/src/i18n/strings/zh-cn.d.ts.map +1 -1
- package/dist/src/i18n/strings/zh-cn.js +18 -0
- package/dist/src/i18n/strings/zh-cn.js.map +1 -1
- package/dist/src/i18n/translations-all.d.ts +1 -184
- package/dist/src/i18n/translations-all.d.ts.map +1 -1
- package/dist/src/utils/translation-service.d.ts +99 -0
- package/dist/src/utils/translation-service.d.ts.map +1 -0
- package/dist/src/utils/translation-service.js +387 -0
- package/dist/src/utils/translation-service.js.map +1 -0
- package/package.json +2 -1
- package/scaffolding/lib/src/lib/strings-collection.ts.mustache +24 -24
|
@@ -8,190 +8,7 @@ import { jaTranslations } from './strings/ja';
|
|
|
8
8
|
import { ukTranslations } from './strings/uk';
|
|
9
9
|
export declare const allTranslations: {
|
|
10
10
|
'en-US': Record<import("./starter-string-key").StarterStringKey, string>;
|
|
11
|
-
'en-GB':
|
|
12
|
-
starter_title: string;
|
|
13
|
-
starter_subtitle: string;
|
|
14
|
-
starter_description: string;
|
|
15
|
-
cli_banner: string;
|
|
16
|
-
cli_fatalError: string;
|
|
17
|
-
cli_cancelled: string;
|
|
18
|
-
cli_installRequiredTools: string;
|
|
19
|
-
systemCheck_header: string;
|
|
20
|
-
systemCheck_passed: string;
|
|
21
|
-
systemCheck_continueAnyway: string;
|
|
22
|
-
systemCheck_missingTools: string;
|
|
23
|
-
systemCheck_optionalTools: string;
|
|
24
|
-
systemCheck_installInstructions: string;
|
|
25
|
-
systemCheck_ubuntuDebian: string;
|
|
26
|
-
systemCheck_fedoraRhel: string;
|
|
27
|
-
systemCheck_macos: string;
|
|
28
|
-
systemCheck_windows: string;
|
|
29
|
-
prompt_workspaceName: string;
|
|
30
|
-
prompt_projectPrefix: string;
|
|
31
|
-
prompt_npmNamespace: string;
|
|
32
|
-
prompt_parentDirectory: string;
|
|
33
|
-
prompt_gitRepo: string;
|
|
34
|
-
prompt_hostname: string;
|
|
35
|
-
prompt_dryRun: string;
|
|
36
|
-
prompt_includeE2e: string;
|
|
37
|
-
prompt_selectPackageGroups: string;
|
|
38
|
-
prompt_enableDocGeneration: string;
|
|
39
|
-
prompt_setupDevcontainer: string;
|
|
40
|
-
prompt_devcontainerConfig: string;
|
|
41
|
-
prompt_mongoPassword: string;
|
|
42
|
-
prompt_useInMemoryDb: string;
|
|
43
|
-
prompt_devDatabaseName: string;
|
|
44
|
-
prompt_generateSecret: string;
|
|
45
|
-
prompt_enterSecret: string;
|
|
46
|
-
prompt_createInitialCommit: string;
|
|
47
|
-
prompt_pushToRemote: string;
|
|
48
|
-
prompt_installPlaywright: string;
|
|
49
|
-
prompt_siteTitle: string;
|
|
50
|
-
prompt_siteDescription: string;
|
|
51
|
-
prompt_siteTagline: string;
|
|
52
|
-
validation_invalidWorkspaceName: string;
|
|
53
|
-
validation_invalidPrefix: string;
|
|
54
|
-
validation_invalidNamespace: string;
|
|
55
|
-
validation_invalidGitRepo: string;
|
|
56
|
-
validation_invalidHostname: string;
|
|
57
|
-
validation_passwordRequired: string;
|
|
58
|
-
validation_databaseNameRequired: string;
|
|
59
|
-
validation_mustBeHex64: string;
|
|
60
|
-
validation_packageJsonNotFound: string;
|
|
61
|
-
validation_packageJsonInvalid: string;
|
|
62
|
-
validation_packageJsonMissingName: string;
|
|
63
|
-
validation_packageJsonMissingVersion: string;
|
|
64
|
-
validation_packageJsonNoScripts: string;
|
|
65
|
-
validation_reactVersionMismatch: string;
|
|
66
|
-
validation_reactDomRequired: string;
|
|
67
|
-
validation_gitignoreNotFound: string;
|
|
68
|
-
validation_readmeNotFound: string;
|
|
69
|
-
validation_licenseNotFound: string;
|
|
70
|
-
validation_passed: string;
|
|
71
|
-
validation_passedWithWarnings: string;
|
|
72
|
-
validation_failed: string;
|
|
73
|
-
validation_reportHeader: string;
|
|
74
|
-
validation_errors: string;
|
|
75
|
-
validation_warnings: string;
|
|
76
|
-
validation_info: string;
|
|
77
|
-
validation_fix: string;
|
|
78
|
-
step_checkTargetDir: string;
|
|
79
|
-
step_createMonorepo: string;
|
|
80
|
-
step_updateTsConfigBase: string;
|
|
81
|
-
step_setupGitOrigin: string;
|
|
82
|
-
step_yarnBerrySetup: string;
|
|
83
|
-
step_addPackageResolutions: string;
|
|
84
|
-
step_addNxPlugins: string;
|
|
85
|
-
step_addYarnPackages: string;
|
|
86
|
-
step_generateProjects: string;
|
|
87
|
-
step_installReactComponents: string;
|
|
88
|
-
step_renderTemplates: string;
|
|
89
|
-
step_copyScaffolding: string;
|
|
90
|
-
step_generateLicense: string;
|
|
91
|
-
step_addScripts: string;
|
|
92
|
-
step_generateDocumentation: string;
|
|
93
|
-
step_setupEnvironment: string;
|
|
94
|
-
step_rebuildNativeModules: string;
|
|
95
|
-
step_validateGeneration: string;
|
|
96
|
-
step_initialCommit: string;
|
|
97
|
-
step_installPlaywright: string;
|
|
98
|
-
step_skipping: string;
|
|
99
|
-
step_completed: string;
|
|
100
|
-
step_failed: string;
|
|
101
|
-
generation_starting: string;
|
|
102
|
-
generation_complete: string;
|
|
103
|
-
generation_failed: string;
|
|
104
|
-
generation_dryRunMode: string;
|
|
105
|
-
generation_dryRunComplete: string;
|
|
106
|
-
generation_rollback: string;
|
|
107
|
-
generation_rollbackFailed: string;
|
|
108
|
-
project_generating: string;
|
|
109
|
-
project_addedTargets: string;
|
|
110
|
-
project_installingPackage: string;
|
|
111
|
-
project_copyingDevcontainer: string;
|
|
112
|
-
tsconfig_baseUpdated: string;
|
|
113
|
-
package_resolutionsAdded: string;
|
|
114
|
-
env_createdWithSecrets: string;
|
|
115
|
-
env_createdFromApi: string;
|
|
116
|
-
env_createdDevcontainer: string;
|
|
117
|
-
env_createdDevcontainerFromExample: string;
|
|
118
|
-
env_createdDevcontainerMinimal: string;
|
|
119
|
-
env_generatedSecret: string;
|
|
120
|
-
doc_generatedReadme: string;
|
|
121
|
-
doc_generatedArchitecture: string;
|
|
122
|
-
doc_generatedApi: string;
|
|
123
|
-
template_rendered: string;
|
|
124
|
-
template_copied: string;
|
|
125
|
-
package_installationFailed: string;
|
|
126
|
-
package_installBuildTools: string;
|
|
127
|
-
package_retryOrSkip: string;
|
|
128
|
-
package_resolvingVersion: string;
|
|
129
|
-
package_failedResolveLatest: string;
|
|
130
|
-
package_failedResolveStable: string;
|
|
131
|
-
plugin_registering: string;
|
|
132
|
-
plugin_hookFailed: string;
|
|
133
|
-
dryRun_header: string;
|
|
134
|
-
dryRun_summary: string;
|
|
135
|
-
dryRun_filesToCreate: string;
|
|
136
|
-
dryRun_filesToModify: string;
|
|
137
|
-
dryRun_filesToDelete: string;
|
|
138
|
-
dryRun_commandsToRun: string;
|
|
139
|
-
dryRun_encounteredError: string;
|
|
140
|
-
dryRun_actions: string;
|
|
141
|
-
diff_changesSummary: string;
|
|
142
|
-
diff_filesAdded: string;
|
|
143
|
-
diff_filesModified: string;
|
|
144
|
-
diff_filesDeleted: string;
|
|
145
|
-
diff_truncated: string;
|
|
146
|
-
diff_before: string;
|
|
147
|
-
diff_after: string;
|
|
148
|
-
command_failed: string;
|
|
149
|
-
command_rebuildingNative: string;
|
|
150
|
-
command_installingPlaywrightBrowsers: string;
|
|
151
|
-
command_skippedPlaywright: string;
|
|
152
|
-
success_generationComplete: string;
|
|
153
|
-
success_monorepoCreated: string;
|
|
154
|
-
success_validationNoIssues: string;
|
|
155
|
-
warning_directoryExists: string;
|
|
156
|
-
warning_updateEnvFile: string;
|
|
157
|
-
warning_updateDevcontainerEnv: string;
|
|
158
|
-
warning_validationErrors: string;
|
|
159
|
-
warning_dryRunRerun: string;
|
|
160
|
-
notice_siteTitleTaglineDescriptions: string;
|
|
161
|
-
error_directoryNotEmpty: string;
|
|
162
|
-
error_invalidStartStep: string;
|
|
163
|
-
error_fatal: string;
|
|
164
|
-
section_workspaceConfig: string;
|
|
165
|
-
section_optionalProjects: string;
|
|
166
|
-
section_packageGroups: string;
|
|
167
|
-
section_devcontainerConfig: string;
|
|
168
|
-
section_databaseConfig: string;
|
|
169
|
-
section_securityConfig: string;
|
|
170
|
-
section_expressSuitePackages: string;
|
|
171
|
-
section_nextSteps: string;
|
|
172
|
-
section_nextStepsUpdateEnv: string;
|
|
173
|
-
section_nextStepsInitDb: string;
|
|
174
|
-
section_nextStepsCopyCredentials: string;
|
|
175
|
-
section_nextStepsMemoryDbInfo: string;
|
|
176
|
-
section_generatedProjects: string;
|
|
177
|
-
section_issues: string;
|
|
178
|
-
section_runningValidation: string;
|
|
179
|
-
devcontainer_simple: string;
|
|
180
|
-
devcontainer_mongodb: string;
|
|
181
|
-
devcontainer_mongodbReplicaset: string;
|
|
182
|
-
prompt_stackType: string;
|
|
183
|
-
stack_mern: string;
|
|
184
|
-
stack_brightstack: string;
|
|
185
|
-
prompt_blockstorePath: string;
|
|
186
|
-
prompt_memberPoolName: string;
|
|
187
|
-
validation_invalidBlockstorePath: string;
|
|
188
|
-
section_stackSelection: string;
|
|
189
|
-
section_brightstackStorage: string;
|
|
190
|
-
devcontainer_simpleBrightstack: string;
|
|
191
|
-
validation_stackMismatch: string;
|
|
192
|
-
validation_missingBrightstackEnv: string;
|
|
193
|
-
validation_crossStackImport: string;
|
|
194
|
-
};
|
|
11
|
+
'en-GB': Record<import("./starter-string-key").StarterStringKey, string>;
|
|
195
12
|
es: Record<import("./starter-string-key").StarterStringKey, string>;
|
|
196
13
|
fr: Record<import("./starter-string-key").StarterStringKey, string>;
|
|
197
14
|
de: Record<import("./starter-string-key").StarterStringKey, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translations-all.d.ts","sourceRoot":"","sources":["../../../src/i18n/translations-all.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"translations-all.d.ts","sourceRoot":"","sources":["../../../src/i18n/translations-all.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,eAAe;;;;;;;;;CAS3B,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation service for auto-translating site strings during scaffolding.
|
|
3
|
+
*
|
|
4
|
+
* Provider chain (user always chooses):
|
|
5
|
+
* 1. Google Translate (free, no API key)
|
|
6
|
+
* 2. AWS Translate (auto-detect or prompt for credentials, may incur charges)
|
|
7
|
+
* 3. Skip: user's original input in all languages, with TODO comments in generated code
|
|
8
|
+
*
|
|
9
|
+
* The user is ALWAYS asked before using any paid service.
|
|
10
|
+
*/
|
|
11
|
+
/** Result of translating a single string */
|
|
12
|
+
export interface TranslationResult {
|
|
13
|
+
text: string;
|
|
14
|
+
wasTranslated: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Per-language site string translations */
|
|
17
|
+
export interface SiteStringsTranslations {
|
|
18
|
+
siteTitle: Record<string, TranslationResult>;
|
|
19
|
+
siteDescription: Record<string, TranslationResult>;
|
|
20
|
+
siteTagline: Record<string, TranslationResult>;
|
|
21
|
+
/** Languages where translation failed */
|
|
22
|
+
failedLanguages: string[];
|
|
23
|
+
/** Provider that succeeded, or 'none' */
|
|
24
|
+
providerUsed: string;
|
|
25
|
+
}
|
|
26
|
+
/** Provider interface for translation backends */
|
|
27
|
+
export interface TranslationProvider {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly displayName: string;
|
|
30
|
+
readonly isPaid: boolean;
|
|
31
|
+
/** Check if this provider is available (e.g. credentials exist) */
|
|
32
|
+
isAvailable(): Promise<boolean>;
|
|
33
|
+
translate(text: string, fromLang: string, toLang: string): Promise<TranslationResult>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the API language code for an i18n language code.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getApiLanguageCode(i18nCode: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Check if two i18n language codes are in the same language family
|
|
41
|
+
* (e.g. en-US and en-GB are both English).
|
|
42
|
+
*/
|
|
43
|
+
export declare function isSameFamily(langA: string, langB: string): boolean;
|
|
44
|
+
export declare const ALL_TARGET_LANGUAGES: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Uses the undocumented Google Translate web API.
|
|
47
|
+
* No API key required. Suitable for translating a handful of short strings.
|
|
48
|
+
* May break if Google changes their endpoint.
|
|
49
|
+
*/
|
|
50
|
+
export declare class GoogleTranslateProvider implements TranslationProvider {
|
|
51
|
+
readonly name = "google-free";
|
|
52
|
+
readonly displayName = "Google Translate (free, no API key)";
|
|
53
|
+
readonly isPaid = false;
|
|
54
|
+
isAvailable(): Promise<boolean>;
|
|
55
|
+
translate(text: string, fromLang: string, toLang: string): Promise<TranslationResult>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Uses AWS Translate via @aws-sdk/client-translate.
|
|
59
|
+
* Dynamically imports the SDK so it's not a hard dependency.
|
|
60
|
+
* Checks for existing AWS credentials before attempting.
|
|
61
|
+
*/
|
|
62
|
+
export declare class AwsTranslateProvider implements TranslationProvider {
|
|
63
|
+
readonly name = "aws-translate";
|
|
64
|
+
readonly displayName = "AWS Translate (may incur charges)";
|
|
65
|
+
readonly isPaid = true;
|
|
66
|
+
private region;
|
|
67
|
+
private accessKeyId?;
|
|
68
|
+
private secretAccessKey?;
|
|
69
|
+
constructor(options?: {
|
|
70
|
+
region?: string;
|
|
71
|
+
accessKeyId?: string;
|
|
72
|
+
secretAccessKey?: string;
|
|
73
|
+
});
|
|
74
|
+
isAvailable(): Promise<boolean>;
|
|
75
|
+
translate(text: string, fromLang: string, toLang: string): Promise<TranslationResult>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Translate site strings to all target languages using the given provider.
|
|
79
|
+
* For same-family languages (e.g. en-US → en-GB), copies verbatim.
|
|
80
|
+
* On per-language failure, marks that language as failed and uses fallback.
|
|
81
|
+
*/
|
|
82
|
+
export declare function translateSiteStrings(provider: TranslationProvider, sourceLang: string, siteTitle: string, siteDescription: string, siteTagline: string): Promise<SiteStringsTranslations>;
|
|
83
|
+
/**
|
|
84
|
+
* Build fallback translations (no translation attempted).
|
|
85
|
+
* Same-family languages get verbatim copy, others get the original text
|
|
86
|
+
* and are marked in failedLanguages for TODO comment generation.
|
|
87
|
+
*/
|
|
88
|
+
export declare function buildFallbackTranslations(sourceLang: string, siteTitle: string, siteDescription: string, siteTagline: string): SiteStringsTranslations;
|
|
89
|
+
/**
|
|
90
|
+
* Convert SiteStringsTranslations into a flat Record<string, string>
|
|
91
|
+
* suitable for mustache template variables.
|
|
92
|
+
*
|
|
93
|
+
* Produces keys like: siteTitleEnUs, siteDescriptionFr, siteTaglineJa, etc.
|
|
94
|
+
*
|
|
95
|
+
* @param translations - The translation results
|
|
96
|
+
* @param escapeForTs - Function to escape strings for TypeScript string literals
|
|
97
|
+
*/
|
|
98
|
+
export declare function translationsToMustacheVars(translations: SiteStringsTranslations, escapeForTs: (s: string) => string): Record<string, string | boolean>;
|
|
99
|
+
//# sourceMappingURL=translation-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-service.d.ts","sourceRoot":"","sources":["../../../src/utils/translation-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Translation service for auto-translating site strings during scaffolding.
|
|
4
|
+
*
|
|
5
|
+
* Provider chain (user always chooses):
|
|
6
|
+
* 1. Google Translate (free, no API key)
|
|
7
|
+
* 2. AWS Translate (auto-detect or prompt for credentials, may incur charges)
|
|
8
|
+
* 3. Skip: user's original input in all languages, with TODO comments in generated code
|
|
9
|
+
*
|
|
10
|
+
* The user is ALWAYS asked before using any paid service.
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.AwsTranslateProvider = exports.GoogleTranslateProvider = exports.ALL_TARGET_LANGUAGES = void 0;
|
|
47
|
+
exports.getApiLanguageCode = getApiLanguageCode;
|
|
48
|
+
exports.isSameFamily = isSameFamily;
|
|
49
|
+
exports.translateSiteStrings = translateSiteStrings;
|
|
50
|
+
exports.buildFallbackTranslations = buildFallbackTranslations;
|
|
51
|
+
exports.translationsToMustacheVars = translationsToMustacheVars;
|
|
52
|
+
const i18n_lib_1 = require("@digitaldefiance/i18n-lib");
|
|
53
|
+
const https = __importStar(require("https"));
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
// ─── Language mapping ────────────────────────────────────────────────
|
|
57
|
+
/** Map i18n-lib codes to BCP-47 codes used by translation APIs */
|
|
58
|
+
const LANGUAGE_API_MAP = {
|
|
59
|
+
[i18n_lib_1.LanguageCodes.EN_US]: 'en',
|
|
60
|
+
[i18n_lib_1.LanguageCodes.EN_GB]: 'en',
|
|
61
|
+
[i18n_lib_1.LanguageCodes.FR]: 'fr',
|
|
62
|
+
[i18n_lib_1.LanguageCodes.ES]: 'es',
|
|
63
|
+
[i18n_lib_1.LanguageCodes.DE]: 'de',
|
|
64
|
+
[i18n_lib_1.LanguageCodes.ZH_CN]: 'zh-CN',
|
|
65
|
+
[i18n_lib_1.LanguageCodes.JA]: 'ja',
|
|
66
|
+
[i18n_lib_1.LanguageCodes.UK]: 'uk',
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Get the API language code for an i18n language code.
|
|
70
|
+
*/
|
|
71
|
+
function getApiLanguageCode(i18nCode) {
|
|
72
|
+
return LANGUAGE_API_MAP[i18nCode] ?? i18nCode;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if two i18n language codes are in the same language family
|
|
76
|
+
* (e.g. en-US and en-GB are both English).
|
|
77
|
+
*/
|
|
78
|
+
function isSameFamily(langA, langB) {
|
|
79
|
+
const apiA = getApiLanguageCode(langA);
|
|
80
|
+
const apiB = getApiLanguageCode(langB);
|
|
81
|
+
return apiA === apiB;
|
|
82
|
+
}
|
|
83
|
+
// ─── All supported target languages ─────────────────────────────────
|
|
84
|
+
exports.ALL_TARGET_LANGUAGES = [
|
|
85
|
+
i18n_lib_1.LanguageCodes.EN_US,
|
|
86
|
+
i18n_lib_1.LanguageCodes.EN_GB,
|
|
87
|
+
i18n_lib_1.LanguageCodes.FR,
|
|
88
|
+
i18n_lib_1.LanguageCodes.ES,
|
|
89
|
+
i18n_lib_1.LanguageCodes.DE,
|
|
90
|
+
i18n_lib_1.LanguageCodes.ZH_CN,
|
|
91
|
+
i18n_lib_1.LanguageCodes.JA,
|
|
92
|
+
i18n_lib_1.LanguageCodes.UK,
|
|
93
|
+
];
|
|
94
|
+
// ─── Google Translate Provider (free, no API key) ────────────────────
|
|
95
|
+
/**
|
|
96
|
+
* Uses the undocumented Google Translate web API.
|
|
97
|
+
* No API key required. Suitable for translating a handful of short strings.
|
|
98
|
+
* May break if Google changes their endpoint.
|
|
99
|
+
*/
|
|
100
|
+
class GoogleTranslateProvider {
|
|
101
|
+
name = 'google-free';
|
|
102
|
+
displayName = 'Google Translate (free, no API key)';
|
|
103
|
+
isPaid = false;
|
|
104
|
+
async isAvailable() {
|
|
105
|
+
return true; // Always available to try
|
|
106
|
+
}
|
|
107
|
+
async translate(text, fromLang, toLang) {
|
|
108
|
+
if (!text.trim()) {
|
|
109
|
+
return { text, wasTranslated: false };
|
|
110
|
+
}
|
|
111
|
+
const encodedText = encodeURIComponent(text);
|
|
112
|
+
const url = `https://translate.googleapis.com/translate_a/single` +
|
|
113
|
+
`?client=gtx&sl=${fromLang}&tl=${toLang}&dt=t&q=${encodedText}`;
|
|
114
|
+
return new Promise((resolve, reject) => {
|
|
115
|
+
const req = https.get(url, { timeout: 10000 }, (res) => {
|
|
116
|
+
let data = '';
|
|
117
|
+
res.on('data', (chunk) => {
|
|
118
|
+
data += chunk.toString();
|
|
119
|
+
});
|
|
120
|
+
res.on('end', () => {
|
|
121
|
+
try {
|
|
122
|
+
if (res.statusCode !== 200) {
|
|
123
|
+
reject(new Error(`Google Translate returned status ${res.statusCode}`));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const parsed = JSON.parse(data);
|
|
127
|
+
// Response format: [[["translated text","original text",null,null,10]],null,"en",...]
|
|
128
|
+
const translated = parsed?.[0]
|
|
129
|
+
?.map((segment) => segment[0])
|
|
130
|
+
.join('');
|
|
131
|
+
if (translated) {
|
|
132
|
+
resolve({ text: translated, wasTranslated: true });
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
reject(new Error('Empty translation response'));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
reject(new Error(`Failed to parse Google Translate response: ${err instanceof Error ? err.message : String(err)}`));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
req.on('error', reject);
|
|
144
|
+
req.on('timeout', () => {
|
|
145
|
+
req.destroy();
|
|
146
|
+
reject(new Error('Google Translate request timed out'));
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.GoogleTranslateProvider = GoogleTranslateProvider;
|
|
152
|
+
// ─── AWS Translate Provider ──────────────────────────────────────────
|
|
153
|
+
/**
|
|
154
|
+
* Uses AWS Translate via @aws-sdk/client-translate.
|
|
155
|
+
* Dynamically imports the SDK so it's not a hard dependency.
|
|
156
|
+
* Checks for existing AWS credentials before attempting.
|
|
157
|
+
*/
|
|
158
|
+
class AwsTranslateProvider {
|
|
159
|
+
name = 'aws-translate';
|
|
160
|
+
displayName = 'AWS Translate (may incur charges)';
|
|
161
|
+
isPaid = true;
|
|
162
|
+
region;
|
|
163
|
+
accessKeyId;
|
|
164
|
+
secretAccessKey;
|
|
165
|
+
constructor(options) {
|
|
166
|
+
this.region = options?.region ?? process.env.AWS_REGION ?? 'us-east-1';
|
|
167
|
+
this.accessKeyId = options?.accessKeyId;
|
|
168
|
+
this.secretAccessKey = options?.secretAccessKey;
|
|
169
|
+
}
|
|
170
|
+
async isAvailable() {
|
|
171
|
+
// Check if credentials are available via env vars or explicit config
|
|
172
|
+
if (this.accessKeyId && this.secretAccessKey) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
// Check for ~/.aws/credentials file
|
|
179
|
+
const credPath = path.join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.aws', 'credentials');
|
|
180
|
+
try {
|
|
181
|
+
await fs.promises.access(credPath, fs.constants.R_OK);
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async translate(text, fromLang, toLang) {
|
|
189
|
+
if (!text.trim()) {
|
|
190
|
+
return { text, wasTranslated: false };
|
|
191
|
+
}
|
|
192
|
+
// Map some BCP-47 codes to AWS Translate codes
|
|
193
|
+
const awsLangMap = {
|
|
194
|
+
'zh-CN': 'zh',
|
|
195
|
+
};
|
|
196
|
+
const awsFrom = awsLangMap[fromLang] ?? fromLang;
|
|
197
|
+
const awsTo = awsLangMap[toLang] ?? toLang;
|
|
198
|
+
try {
|
|
199
|
+
// Dynamic require — not a hard dependency.
|
|
200
|
+
// Jest needs @aws-sdk in transformIgnorePatterns to avoid VM issues.
|
|
201
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
202
|
+
const { TranslateClient, TranslateTextCommand } = require('@aws-sdk/client-translate');
|
|
203
|
+
const clientConfig = { region: this.region };
|
|
204
|
+
if (this.accessKeyId && this.secretAccessKey) {
|
|
205
|
+
clientConfig.credentials = {
|
|
206
|
+
accessKeyId: this.accessKeyId,
|
|
207
|
+
secretAccessKey: this.secretAccessKey,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const client = new TranslateClient(clientConfig);
|
|
211
|
+
const command = new TranslateTextCommand({
|
|
212
|
+
Text: text,
|
|
213
|
+
SourceLanguageCode: awsFrom,
|
|
214
|
+
TargetLanguageCode: awsTo,
|
|
215
|
+
});
|
|
216
|
+
const response = await client.send(command);
|
|
217
|
+
if (response.TranslatedText) {
|
|
218
|
+
return { text: response.TranslatedText, wasTranslated: true };
|
|
219
|
+
}
|
|
220
|
+
return { text, wasTranslated: false };
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
throw new Error(`AWS Translate failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.AwsTranslateProvider = AwsTranslateProvider;
|
|
228
|
+
// ─── Translation orchestrator ────────────────────────────────────────
|
|
229
|
+
/**
|
|
230
|
+
* Translate site strings to all target languages using the given provider.
|
|
231
|
+
* For same-family languages (e.g. en-US → en-GB), copies verbatim.
|
|
232
|
+
* On per-language failure, marks that language as failed and uses fallback.
|
|
233
|
+
*/
|
|
234
|
+
async function translateSiteStrings(provider, sourceLang, siteTitle, siteDescription, siteTagline) {
|
|
235
|
+
const sourceApiLang = getApiLanguageCode(sourceLang);
|
|
236
|
+
const failedLanguages = [];
|
|
237
|
+
const result = {
|
|
238
|
+
siteTitle: {},
|
|
239
|
+
siteDescription: {},
|
|
240
|
+
siteTagline: {},
|
|
241
|
+
failedLanguages,
|
|
242
|
+
providerUsed: provider.name,
|
|
243
|
+
};
|
|
244
|
+
for (const targetLang of exports.ALL_TARGET_LANGUAGES) {
|
|
245
|
+
// Source language: use the user's input directly
|
|
246
|
+
if (targetLang === sourceLang) {
|
|
247
|
+
result.siteTitle[targetLang] = { text: siteTitle, wasTranslated: false };
|
|
248
|
+
result.siteDescription[targetLang] = {
|
|
249
|
+
text: siteDescription,
|
|
250
|
+
wasTranslated: false,
|
|
251
|
+
};
|
|
252
|
+
result.siteTagline[targetLang] = {
|
|
253
|
+
text: siteTagline,
|
|
254
|
+
wasTranslated: false,
|
|
255
|
+
};
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
// Same family (e.g. en-US and en-GB): copy verbatim
|
|
259
|
+
if (isSameFamily(sourceLang, targetLang)) {
|
|
260
|
+
result.siteTitle[targetLang] = { text: siteTitle, wasTranslated: false };
|
|
261
|
+
result.siteDescription[targetLang] = {
|
|
262
|
+
text: siteDescription,
|
|
263
|
+
wasTranslated: false,
|
|
264
|
+
};
|
|
265
|
+
result.siteTagline[targetLang] = {
|
|
266
|
+
text: siteTagline,
|
|
267
|
+
wasTranslated: false,
|
|
268
|
+
};
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
// Translate each string individually
|
|
272
|
+
const targetApiLang = getApiLanguageCode(targetLang);
|
|
273
|
+
try {
|
|
274
|
+
const [titleResult, descResult, taglineResult] = await Promise.all([
|
|
275
|
+
provider.translate(siteTitle, sourceApiLang, targetApiLang),
|
|
276
|
+
provider.translate(siteDescription, sourceApiLang, targetApiLang),
|
|
277
|
+
provider.translate(siteTagline, sourceApiLang, targetApiLang),
|
|
278
|
+
]);
|
|
279
|
+
result.siteTitle[targetLang] = titleResult;
|
|
280
|
+
result.siteDescription[targetLang] = descResult;
|
|
281
|
+
result.siteTagline[targetLang] = taglineResult;
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// Translation failed for this language — use original text as fallback
|
|
285
|
+
failedLanguages.push(targetLang);
|
|
286
|
+
result.siteTitle[targetLang] = {
|
|
287
|
+
text: siteTitle,
|
|
288
|
+
wasTranslated: false,
|
|
289
|
+
};
|
|
290
|
+
result.siteDescription[targetLang] = {
|
|
291
|
+
text: siteDescription,
|
|
292
|
+
wasTranslated: false,
|
|
293
|
+
};
|
|
294
|
+
result.siteTagline[targetLang] = {
|
|
295
|
+
text: siteTagline,
|
|
296
|
+
wasTranslated: false,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Build fallback translations (no translation attempted).
|
|
304
|
+
* Same-family languages get verbatim copy, others get the original text
|
|
305
|
+
* and are marked in failedLanguages for TODO comment generation.
|
|
306
|
+
*/
|
|
307
|
+
function buildFallbackTranslations(sourceLang, siteTitle, siteDescription, siteTagline) {
|
|
308
|
+
const result = {
|
|
309
|
+
siteTitle: {},
|
|
310
|
+
siteDescription: {},
|
|
311
|
+
siteTagline: {},
|
|
312
|
+
failedLanguages: [],
|
|
313
|
+
providerUsed: 'none',
|
|
314
|
+
};
|
|
315
|
+
for (const targetLang of exports.ALL_TARGET_LANGUAGES) {
|
|
316
|
+
if (targetLang === sourceLang || isSameFamily(sourceLang, targetLang)) {
|
|
317
|
+
result.siteTitle[targetLang] = { text: siteTitle, wasTranslated: false };
|
|
318
|
+
result.siteDescription[targetLang] = {
|
|
319
|
+
text: siteDescription,
|
|
320
|
+
wasTranslated: false,
|
|
321
|
+
};
|
|
322
|
+
result.siteTagline[targetLang] = {
|
|
323
|
+
text: siteTagline,
|
|
324
|
+
wasTranslated: false,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
result.failedLanguages.push(targetLang);
|
|
329
|
+
result.siteTitle[targetLang] = {
|
|
330
|
+
text: siteTitle,
|
|
331
|
+
wasTranslated: false,
|
|
332
|
+
};
|
|
333
|
+
result.siteDescription[targetLang] = {
|
|
334
|
+
text: siteDescription,
|
|
335
|
+
wasTranslated: false,
|
|
336
|
+
};
|
|
337
|
+
result.siteTagline[targetLang] = {
|
|
338
|
+
text: siteTagline,
|
|
339
|
+
wasTranslated: false,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return result;
|
|
344
|
+
}
|
|
345
|
+
// ─── Mustache variable helpers ───────────────────────────────────────
|
|
346
|
+
/**
|
|
347
|
+
* Map from i18n language code to the suffix used in mustache variable names.
|
|
348
|
+
* e.g. LanguageCodes.EN_US → 'EnUs', LanguageCodes.ZH_CN → 'ZhCn'
|
|
349
|
+
*/
|
|
350
|
+
const LANG_SUFFIX_MAP = {
|
|
351
|
+
[i18n_lib_1.LanguageCodes.EN_US]: 'EnUs',
|
|
352
|
+
[i18n_lib_1.LanguageCodes.EN_GB]: 'EnGb',
|
|
353
|
+
[i18n_lib_1.LanguageCodes.FR]: 'Fr',
|
|
354
|
+
[i18n_lib_1.LanguageCodes.ES]: 'Es',
|
|
355
|
+
[i18n_lib_1.LanguageCodes.DE]: 'De',
|
|
356
|
+
[i18n_lib_1.LanguageCodes.ZH_CN]: 'ZhCn',
|
|
357
|
+
[i18n_lib_1.LanguageCodes.JA]: 'Ja',
|
|
358
|
+
[i18n_lib_1.LanguageCodes.UK]: 'Uk',
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* Convert SiteStringsTranslations into a flat Record<string, string>
|
|
362
|
+
* suitable for mustache template variables.
|
|
363
|
+
*
|
|
364
|
+
* Produces keys like: siteTitleEnUs, siteDescriptionFr, siteTaglineJa, etc.
|
|
365
|
+
*
|
|
366
|
+
* @param translations - The translation results
|
|
367
|
+
* @param escapeForTs - Function to escape strings for TypeScript string literals
|
|
368
|
+
*/
|
|
369
|
+
function translationsToMustacheVars(translations, escapeForTs) {
|
|
370
|
+
const vars = {};
|
|
371
|
+
for (const lang of exports.ALL_TARGET_LANGUAGES) {
|
|
372
|
+
const suffix = LANG_SUFFIX_MAP[lang];
|
|
373
|
+
if (!suffix)
|
|
374
|
+
continue;
|
|
375
|
+
const titleResult = translations.siteTitle[lang];
|
|
376
|
+
const descResult = translations.siteDescription[lang];
|
|
377
|
+
const taglineResult = translations.siteTagline[lang];
|
|
378
|
+
vars[`siteTitle${suffix}`] = escapeForTs(titleResult?.text ?? '');
|
|
379
|
+
vars[`siteDescription${suffix}`] = escapeForTs(descResult?.text ?? '');
|
|
380
|
+
vars[`siteTagline${suffix}`] = escapeForTs(taglineResult?.text ?? '');
|
|
381
|
+
// True if this language needs manual translation (failed or skipped)
|
|
382
|
+
const needsIt = translations.failedLanguages.includes(lang);
|
|
383
|
+
vars[`needsTranslation${suffix}`] = needsIt;
|
|
384
|
+
}
|
|
385
|
+
return vars;
|
|
386
|
+
}
|
|
387
|
+
//# sourceMappingURL=translation-service.js.map
|