poly-lexis 0.4.1 → 0.4.3
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/cli/translations.js +136 -123
- package/dist/cli/translations.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +179 -163
- package/dist/index.js.map +1 -1
- package/dist/scripts/verify-translations.js +1 -1
- package/dist/scripts/verify-translations.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -741,7 +741,7 @@ var init_types = __esm({
|
|
|
741
741
|
languages: ["en"],
|
|
742
742
|
sourceLanguage: "en",
|
|
743
743
|
typesOutputPath: "src/types/i18nTypes.ts",
|
|
744
|
-
provider: "
|
|
744
|
+
provider: "deepl",
|
|
745
745
|
useFallbackLanguages: true
|
|
746
746
|
};
|
|
747
747
|
DEFAULT_LANGUAGES = ["en", "fr", "it", "pl", "es", "pt", "de", "nl", "sv", "hu", "cs", "ja"];
|
|
@@ -881,9 +881,9 @@ var init_init = __esm({
|
|
|
881
881
|
});
|
|
882
882
|
|
|
883
883
|
// src/translations/cli/add-key.ts
|
|
884
|
-
import * as
|
|
884
|
+
import * as path4 from "path";
|
|
885
885
|
|
|
886
|
-
// src/translations/utils/
|
|
886
|
+
// src/translations/utils/deepl-translate-provider.ts
|
|
887
887
|
init_language_fallback();
|
|
888
888
|
function preserveVariables(text) {
|
|
889
889
|
const variableMap = /* @__PURE__ */ new Map();
|
|
@@ -903,6 +903,99 @@ function restoreVariables(text, variableMap) {
|
|
|
903
903
|
}
|
|
904
904
|
return result;
|
|
905
905
|
}
|
|
906
|
+
function normalizeLanguageCode(langCode) {
|
|
907
|
+
return langCode.replace("_", "-").toUpperCase();
|
|
908
|
+
}
|
|
909
|
+
var DeepLTranslateProvider = class {
|
|
910
|
+
isFreeApi;
|
|
911
|
+
constructor(isFreeApi = false) {
|
|
912
|
+
this.isFreeApi = isFreeApi;
|
|
913
|
+
}
|
|
914
|
+
getApiEndpoint() {
|
|
915
|
+
return this.isFreeApi ? "https://api-free.deepl.com/v2/translate" : "https://api.deepl.com/v2/translate";
|
|
916
|
+
}
|
|
917
|
+
async translate(options) {
|
|
918
|
+
const { text, sourceLang, targetLang, apiKey, useFallbackLanguages = true } = options;
|
|
919
|
+
if (!apiKey) {
|
|
920
|
+
throw new Error(
|
|
921
|
+
"DeepL API key is required. Set DEEPL_API_KEY environment variable or provide apiKey in options."
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
const targetLangResult = resolveLanguageWithFallback(targetLang, "deepl", useFallbackLanguages);
|
|
925
|
+
logLanguageFallback(targetLangResult, "deepl");
|
|
926
|
+
let resolvedSourceLang;
|
|
927
|
+
if (sourceLang) {
|
|
928
|
+
const sourceLangResult = resolveLanguageWithFallback(sourceLang, "deepl", useFallbackLanguages);
|
|
929
|
+
logLanguageFallback(sourceLangResult, "deepl");
|
|
930
|
+
resolvedSourceLang = sourceLangResult.resolvedLanguage;
|
|
931
|
+
}
|
|
932
|
+
const { textWithPlaceholders, variableMap } = preserveVariables(text);
|
|
933
|
+
const body = {
|
|
934
|
+
text: [textWithPlaceholders],
|
|
935
|
+
target_lang: normalizeLanguageCode(targetLangResult.resolvedLanguage),
|
|
936
|
+
...resolvedSourceLang && { source_lang: normalizeLanguageCode(resolvedSourceLang) }
|
|
937
|
+
};
|
|
938
|
+
const response = await fetch(this.getApiEndpoint(), {
|
|
939
|
+
method: "POST",
|
|
940
|
+
headers: {
|
|
941
|
+
Authorization: `DeepL-Auth-Key ${apiKey}`,
|
|
942
|
+
"Content-Type": "application/json"
|
|
943
|
+
},
|
|
944
|
+
body: JSON.stringify(body)
|
|
945
|
+
});
|
|
946
|
+
if (!response.ok) {
|
|
947
|
+
const errorData = await response.json().catch(() => ({}));
|
|
948
|
+
throw new Error(`DeepL API error: ${errorData.message || response.statusText} (${response.status})`);
|
|
949
|
+
}
|
|
950
|
+
const data = await response.json();
|
|
951
|
+
if (!data.translations || data.translations.length === 0) {
|
|
952
|
+
throw new Error("DeepL API returned no translations");
|
|
953
|
+
}
|
|
954
|
+
const translatedText = data.translations[0].text;
|
|
955
|
+
return restoreVariables(translatedText, variableMap);
|
|
956
|
+
}
|
|
957
|
+
async translateBatch(texts, sourceLang, targetLang, apiKey, delayMs = 100) {
|
|
958
|
+
const results = [];
|
|
959
|
+
for (const text of texts) {
|
|
960
|
+
const translated = await this.translate({
|
|
961
|
+
text,
|
|
962
|
+
sourceLang,
|
|
963
|
+
targetLang,
|
|
964
|
+
apiKey
|
|
965
|
+
});
|
|
966
|
+
results.push(translated);
|
|
967
|
+
if (delayMs > 0) {
|
|
968
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return results;
|
|
972
|
+
}
|
|
973
|
+
async validateConfig() {
|
|
974
|
+
const apiKey = process.env.DEEPL_API_KEY;
|
|
975
|
+
return !!apiKey;
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
// src/translations/utils/google-translate-provider.ts
|
|
980
|
+
init_language_fallback();
|
|
981
|
+
function preserveVariables2(text) {
|
|
982
|
+
const variableMap = /* @__PURE__ */ new Map();
|
|
983
|
+
let placeholderIndex = 0;
|
|
984
|
+
const textWithPlaceholders = text.replace(/\{\{([^}]+)\}\}/g, (match) => {
|
|
985
|
+
const placeholder = `XXX_${placeholderIndex}_XXX`;
|
|
986
|
+
variableMap.set(placeholder, match);
|
|
987
|
+
placeholderIndex++;
|
|
988
|
+
return placeholder;
|
|
989
|
+
});
|
|
990
|
+
return { textWithPlaceholders, variableMap };
|
|
991
|
+
}
|
|
992
|
+
function restoreVariables2(text, variableMap) {
|
|
993
|
+
let result = text;
|
|
994
|
+
for (const [placeholder, original] of variableMap) {
|
|
995
|
+
result = result.replace(new RegExp(placeholder, "g"), original);
|
|
996
|
+
}
|
|
997
|
+
return result;
|
|
998
|
+
}
|
|
906
999
|
var GoogleTranslateProvider = class {
|
|
907
1000
|
async translate(options) {
|
|
908
1001
|
const { text, sourceLang, targetLang, apiKey, useFallbackLanguages = true } = options;
|
|
@@ -919,7 +1012,7 @@ var GoogleTranslateProvider = class {
|
|
|
919
1012
|
logLanguageFallback(sourceLangResult, "google");
|
|
920
1013
|
resolvedSourceLang = sourceLangResult.resolvedLanguage;
|
|
921
1014
|
}
|
|
922
|
-
const { textWithPlaceholders, variableMap } =
|
|
1015
|
+
const { textWithPlaceholders, variableMap } = preserveVariables2(text);
|
|
923
1016
|
const url = `https://translation.googleapis.com/language/translate/v2?key=${apiKey}`;
|
|
924
1017
|
const sourceForGoogle = resolvedSourceLang?.includes("_") ? resolvedSourceLang.split("_")[0] : resolvedSourceLang;
|
|
925
1018
|
const targetForGoogle = targetLangResult.resolvedLanguage.includes("_") ? targetLangResult.resolvedLanguage.split("_")[0] : targetLangResult.resolvedLanguage;
|
|
@@ -940,7 +1033,7 @@ var GoogleTranslateProvider = class {
|
|
|
940
1033
|
throw new Error(`Google Translate API error: ${data.error.message}`);
|
|
941
1034
|
}
|
|
942
1035
|
const translatedText = data.data.translations[0].translatedText;
|
|
943
|
-
return
|
|
1036
|
+
return restoreVariables2(translatedText, variableMap);
|
|
944
1037
|
}
|
|
945
1038
|
async translateBatch(texts, sourceLang, targetLang, apiKey, delayMs = 100) {
|
|
946
1039
|
const results = [];
|
|
@@ -993,11 +1086,79 @@ async function translateBatch(texts, targetLang, sourceLang = "en", apiKey, dela
|
|
|
993
1086
|
|
|
994
1087
|
// src/translations/cli/add-key.ts
|
|
995
1088
|
init_utils();
|
|
1089
|
+
|
|
1090
|
+
// src/translations/cli/generate-types.ts
|
|
1091
|
+
init_utils();
|
|
996
1092
|
init_init();
|
|
997
|
-
|
|
1093
|
+
import { execSync } from "child_process";
|
|
1094
|
+
import * as fs3 from "fs";
|
|
1095
|
+
import * as path3 from "path";
|
|
1096
|
+
var typeTemplate = (translationKeys, namespaceKeys) => `
|
|
1097
|
+
export const translationKeys = [${translationKeys.map((key) => `"${key}"`).join(", ")}] as const;
|
|
1098
|
+
export const namespaceKeys = [${namespaceKeys.map((key) => `"${key}"`).join(", ")}] as const;
|
|
1099
|
+
|
|
1100
|
+
export type TranslationKey = typeof translationKeys[number];
|
|
1101
|
+
export type TranslationNamespace = typeof namespaceKeys[number];
|
|
1102
|
+
`;
|
|
1103
|
+
function generateTranslationTypes(projectRoot = process.cwd()) {
|
|
1104
|
+
console.log("=====");
|
|
1105
|
+
console.time("i18n types generated");
|
|
1106
|
+
console.log("Generating i18n types");
|
|
1107
|
+
console.log("=====");
|
|
998
1108
|
const config = loadConfig(projectRoot);
|
|
999
1109
|
const translationsPath = path3.join(projectRoot, config.translationsPath);
|
|
1110
|
+
const sourceLanguage = config.sourceLanguage;
|
|
1111
|
+
const outputFilePath = path3.join(projectRoot, config.typesOutputPath);
|
|
1112
|
+
const dirPath = path3.join(translationsPath, sourceLanguage);
|
|
1113
|
+
if (!fs3.existsSync(dirPath)) {
|
|
1114
|
+
throw new Error(`Source language directory not found: ${dirPath}`);
|
|
1115
|
+
}
|
|
1116
|
+
const namespaces = getNamespaces(translationsPath, sourceLanguage);
|
|
1117
|
+
if (!namespaces.length) {
|
|
1118
|
+
throw new Error(`No translation files found in ${dirPath}`);
|
|
1119
|
+
}
|
|
1120
|
+
const translations = readTranslations(translationsPath, sourceLanguage);
|
|
1121
|
+
let allKeys = [];
|
|
1122
|
+
for (const namespace of namespaces) {
|
|
1123
|
+
const keys = Object.keys(translations[namespace] || {});
|
|
1124
|
+
allKeys = allKeys.concat(keys);
|
|
1125
|
+
}
|
|
1126
|
+
const outputDir = path3.dirname(outputFilePath);
|
|
1127
|
+
if (!fs3.existsSync(outputDir)) {
|
|
1128
|
+
fs3.mkdirSync(outputDir, { recursive: true });
|
|
1129
|
+
}
|
|
1130
|
+
const typeString = typeTemplate(allKeys, namespaces);
|
|
1131
|
+
fs3.writeFileSync(outputFilePath, typeString, "utf8");
|
|
1132
|
+
console.log(`Generated types with ${allKeys.length} keys and ${namespaces.length} namespaces`);
|
|
1133
|
+
console.log(`Output: ${outputFilePath}`);
|
|
1134
|
+
try {
|
|
1135
|
+
execSync(`pnpm biome format --write ${outputFilePath}`, {
|
|
1136
|
+
stdio: "inherit",
|
|
1137
|
+
cwd: projectRoot
|
|
1138
|
+
});
|
|
1139
|
+
} catch {
|
|
1140
|
+
console.warn("Failed to format with Biome, continuing without formatting...");
|
|
1141
|
+
}
|
|
1142
|
+
console.timeEnd("i18n types generated");
|
|
1143
|
+
console.log("=====");
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// src/translations/cli/add-key.ts
|
|
1147
|
+
init_init();
|
|
1148
|
+
async function addTranslationKey(projectRoot, options) {
|
|
1149
|
+
const config = loadConfig(projectRoot);
|
|
1150
|
+
const translationsPath = path4.join(projectRoot, config.translationsPath);
|
|
1000
1151
|
const { namespace, key, value, autoTranslate = false, apiKey } = options;
|
|
1152
|
+
const currentProvider = getTranslationProvider();
|
|
1153
|
+
const isDefaultGoogleProvider = currentProvider.constructor.name === "GoogleTranslateProvider";
|
|
1154
|
+
if (isDefaultGoogleProvider) {
|
|
1155
|
+
const provider = config.provider || "deepl";
|
|
1156
|
+
if (provider === "deepl") {
|
|
1157
|
+
setTranslationProvider(new DeepLTranslateProvider());
|
|
1158
|
+
} else {
|
|
1159
|
+
setTranslationProvider(new GoogleTranslateProvider());
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1001
1162
|
console.log("=====");
|
|
1002
1163
|
console.log("Adding translation key");
|
|
1003
1164
|
console.log("=====");
|
|
@@ -1027,7 +1188,7 @@ async function addTranslationKey(projectRoot, options) {
|
|
|
1027
1188
|
targetTranslations[namespace] = {};
|
|
1028
1189
|
}
|
|
1029
1190
|
if (!targetTranslations[namespace][key] || targetTranslations[namespace][key].trim() === "") {
|
|
1030
|
-
const translated = await translateText(value, lang, sourceLang, apiKey);
|
|
1191
|
+
const translated = await translateText(value, lang, sourceLang, apiKey, config.useFallbackLanguages ?? true);
|
|
1031
1192
|
targetTranslations[namespace][key] = translated;
|
|
1032
1193
|
const sorted = sortKeys(targetTranslations[namespace]);
|
|
1033
1194
|
writeTranslation(translationsPath, lang, namespace, sorted);
|
|
@@ -1063,6 +1224,12 @@ async function addTranslationKey(projectRoot, options) {
|
|
|
1063
1224
|
console.log("=====");
|
|
1064
1225
|
console.log("Translation key added successfully!");
|
|
1065
1226
|
console.log("=====");
|
|
1227
|
+
console.log("\nRegenerating TypeScript types...");
|
|
1228
|
+
try {
|
|
1229
|
+
generateTranslationTypes(projectRoot);
|
|
1230
|
+
} catch (error) {
|
|
1231
|
+
console.error("Failed to generate types:", error instanceof Error ? error.message : "Unknown error");
|
|
1232
|
+
}
|
|
1066
1233
|
}
|
|
1067
1234
|
async function addTranslationKeys(projectRoot, entries, autoTranslate = false, apiKey) {
|
|
1068
1235
|
console.log(`Adding ${entries.length} translation keys...`);
|
|
@@ -1078,112 +1245,17 @@ async function addTranslationKeys(projectRoot, entries, autoTranslate = false, a
|
|
|
1078
1245
|
}
|
|
1079
1246
|
|
|
1080
1247
|
// src/translations/cli/auto-fill.ts
|
|
1081
|
-
import * as
|
|
1082
|
-
|
|
1083
|
-
// src/translations/utils/deepl-translate-provider.ts
|
|
1084
|
-
init_language_fallback();
|
|
1085
|
-
function preserveVariables2(text) {
|
|
1086
|
-
const variableMap = /* @__PURE__ */ new Map();
|
|
1087
|
-
let placeholderIndex = 0;
|
|
1088
|
-
const textWithPlaceholders = text.replace(/\{\{([^}]+)\}\}/g, (match) => {
|
|
1089
|
-
const placeholder = `XXX_${placeholderIndex}_XXX`;
|
|
1090
|
-
variableMap.set(placeholder, match);
|
|
1091
|
-
placeholderIndex++;
|
|
1092
|
-
return placeholder;
|
|
1093
|
-
});
|
|
1094
|
-
return { textWithPlaceholders, variableMap };
|
|
1095
|
-
}
|
|
1096
|
-
function restoreVariables2(text, variableMap) {
|
|
1097
|
-
let result = text;
|
|
1098
|
-
for (const [placeholder, original] of variableMap) {
|
|
1099
|
-
result = result.replace(new RegExp(placeholder, "g"), original);
|
|
1100
|
-
}
|
|
1101
|
-
return result;
|
|
1102
|
-
}
|
|
1103
|
-
function normalizeLanguageCode(langCode) {
|
|
1104
|
-
return langCode.replace("_", "-").toUpperCase();
|
|
1105
|
-
}
|
|
1106
|
-
var DeepLTranslateProvider = class {
|
|
1107
|
-
isFreeApi;
|
|
1108
|
-
constructor(isFreeApi = false) {
|
|
1109
|
-
this.isFreeApi = isFreeApi;
|
|
1110
|
-
}
|
|
1111
|
-
getApiEndpoint() {
|
|
1112
|
-
return this.isFreeApi ? "https://api-free.deepl.com/v2/translate" : "https://api.deepl.com/v2/translate";
|
|
1113
|
-
}
|
|
1114
|
-
async translate(options) {
|
|
1115
|
-
const { text, sourceLang, targetLang, apiKey, useFallbackLanguages = true } = options;
|
|
1116
|
-
if (!apiKey) {
|
|
1117
|
-
throw new Error(
|
|
1118
|
-
"DeepL API key is required. Set DEEPL_API_KEY environment variable or provide apiKey in options."
|
|
1119
|
-
);
|
|
1120
|
-
}
|
|
1121
|
-
const targetLangResult = resolveLanguageWithFallback(targetLang, "deepl", useFallbackLanguages);
|
|
1122
|
-
logLanguageFallback(targetLangResult, "deepl");
|
|
1123
|
-
let resolvedSourceLang;
|
|
1124
|
-
if (sourceLang) {
|
|
1125
|
-
const sourceLangResult = resolveLanguageWithFallback(sourceLang, "deepl", useFallbackLanguages);
|
|
1126
|
-
logLanguageFallback(sourceLangResult, "deepl");
|
|
1127
|
-
resolvedSourceLang = sourceLangResult.resolvedLanguage;
|
|
1128
|
-
}
|
|
1129
|
-
const { textWithPlaceholders, variableMap } = preserveVariables2(text);
|
|
1130
|
-
const body = {
|
|
1131
|
-
text: [textWithPlaceholders],
|
|
1132
|
-
target_lang: normalizeLanguageCode(targetLangResult.resolvedLanguage),
|
|
1133
|
-
...resolvedSourceLang && { source_lang: normalizeLanguageCode(resolvedSourceLang) }
|
|
1134
|
-
};
|
|
1135
|
-
const response = await fetch(this.getApiEndpoint(), {
|
|
1136
|
-
method: "POST",
|
|
1137
|
-
headers: {
|
|
1138
|
-
Authorization: `DeepL-Auth-Key ${apiKey}`,
|
|
1139
|
-
"Content-Type": "application/json"
|
|
1140
|
-
},
|
|
1141
|
-
body: JSON.stringify(body)
|
|
1142
|
-
});
|
|
1143
|
-
if (!response.ok) {
|
|
1144
|
-
const errorData = await response.json().catch(() => ({}));
|
|
1145
|
-
throw new Error(`DeepL API error: ${errorData.message || response.statusText} (${response.status})`);
|
|
1146
|
-
}
|
|
1147
|
-
const data = await response.json();
|
|
1148
|
-
if (!data.translations || data.translations.length === 0) {
|
|
1149
|
-
throw new Error("DeepL API returned no translations");
|
|
1150
|
-
}
|
|
1151
|
-
const translatedText = data.translations[0].text;
|
|
1152
|
-
return restoreVariables2(translatedText, variableMap);
|
|
1153
|
-
}
|
|
1154
|
-
async translateBatch(texts, sourceLang, targetLang, apiKey, delayMs = 100) {
|
|
1155
|
-
const results = [];
|
|
1156
|
-
for (const text of texts) {
|
|
1157
|
-
const translated = await this.translate({
|
|
1158
|
-
text,
|
|
1159
|
-
sourceLang,
|
|
1160
|
-
targetLang,
|
|
1161
|
-
apiKey
|
|
1162
|
-
});
|
|
1163
|
-
results.push(translated);
|
|
1164
|
-
if (delayMs > 0) {
|
|
1165
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
return results;
|
|
1169
|
-
}
|
|
1170
|
-
async validateConfig() {
|
|
1171
|
-
const apiKey = process.env.DEEPL_API_KEY;
|
|
1172
|
-
return !!apiKey;
|
|
1173
|
-
}
|
|
1174
|
-
};
|
|
1175
|
-
|
|
1176
|
-
// src/translations/cli/auto-fill.ts
|
|
1248
|
+
import * as path6 from "path";
|
|
1177
1249
|
init_utils();
|
|
1178
1250
|
init_init();
|
|
1179
1251
|
|
|
1180
1252
|
// src/translations/cli/validate.ts
|
|
1181
1253
|
init_utils();
|
|
1182
1254
|
init_init();
|
|
1183
|
-
import * as
|
|
1255
|
+
import * as path5 from "path";
|
|
1184
1256
|
function validateTranslations(projectRoot = process.cwd()) {
|
|
1185
1257
|
const config = loadConfig(projectRoot);
|
|
1186
|
-
const translationsPath =
|
|
1258
|
+
const translationsPath = path5.join(projectRoot, config.translationsPath);
|
|
1187
1259
|
const sourceLanguage = config.sourceLanguage;
|
|
1188
1260
|
const missing = [];
|
|
1189
1261
|
const empty = [];
|
|
@@ -1266,7 +1338,7 @@ function getMissingForLanguage(projectRoot, language) {
|
|
|
1266
1338
|
// src/translations/cli/auto-fill.ts
|
|
1267
1339
|
async function autoFillTranslations(projectRoot = process.cwd(), options = {}) {
|
|
1268
1340
|
const config = loadConfig(projectRoot);
|
|
1269
|
-
const translationsPath =
|
|
1341
|
+
const translationsPath = path6.join(projectRoot, config.translationsPath);
|
|
1270
1342
|
const { apiKey, limit = 1e3, delayMs = 100, dryRun = false } = options;
|
|
1271
1343
|
const currentProvider = getTranslationProvider();
|
|
1272
1344
|
const isDefaultGoogleProvider = currentProvider.constructor.name === "GoogleTranslateProvider";
|
|
@@ -1359,7 +1431,7 @@ Processing language: ${language}`);
|
|
|
1359
1431
|
}
|
|
1360
1432
|
async function fillNamespace(projectRoot, language, namespace, apiKey) {
|
|
1361
1433
|
const config = loadConfig(projectRoot);
|
|
1362
|
-
const translationsPath =
|
|
1434
|
+
const translationsPath = path6.join(projectRoot, config.translationsPath);
|
|
1363
1435
|
const currentProvider = getTranslationProvider();
|
|
1364
1436
|
const isDefaultGoogleProvider = currentProvider.constructor.name === "GoogleTranslateProvider";
|
|
1365
1437
|
if (isDefaultGoogleProvider) {
|
|
@@ -1402,62 +1474,6 @@ async function fillNamespace(projectRoot, language, namespace, apiKey) {
|
|
|
1402
1474
|
}
|
|
1403
1475
|
}
|
|
1404
1476
|
|
|
1405
|
-
// src/translations/cli/generate-types.ts
|
|
1406
|
-
init_utils();
|
|
1407
|
-
init_init();
|
|
1408
|
-
import { execSync } from "child_process";
|
|
1409
|
-
import * as fs3 from "fs";
|
|
1410
|
-
import * as path6 from "path";
|
|
1411
|
-
var typeTemplate = (translationKeys, namespaceKeys) => `
|
|
1412
|
-
export const translationKeys = [${translationKeys.map((key) => `"${key}"`).join(", ")}] as const;
|
|
1413
|
-
export const namespaceKeys = [${namespaceKeys.map((key) => `"${key}"`).join(", ")}] as const;
|
|
1414
|
-
|
|
1415
|
-
export type TranslationKey = typeof translationKeys[number];
|
|
1416
|
-
export type TranslationNamespace = typeof namespaceKeys[number];
|
|
1417
|
-
`;
|
|
1418
|
-
function generateTranslationTypes(projectRoot = process.cwd()) {
|
|
1419
|
-
console.log("=====");
|
|
1420
|
-
console.time("i18n types generated");
|
|
1421
|
-
console.log("Generating i18n types");
|
|
1422
|
-
console.log("=====");
|
|
1423
|
-
const config = loadConfig(projectRoot);
|
|
1424
|
-
const translationsPath = path6.join(projectRoot, config.translationsPath);
|
|
1425
|
-
const sourceLanguage = config.sourceLanguage;
|
|
1426
|
-
const outputFilePath = path6.join(projectRoot, config.typesOutputPath);
|
|
1427
|
-
const dirPath = path6.join(translationsPath, sourceLanguage);
|
|
1428
|
-
if (!fs3.existsSync(dirPath)) {
|
|
1429
|
-
throw new Error(`Source language directory not found: ${dirPath}`);
|
|
1430
|
-
}
|
|
1431
|
-
const namespaces = getNamespaces(translationsPath, sourceLanguage);
|
|
1432
|
-
if (!namespaces.length) {
|
|
1433
|
-
throw new Error(`No translation files found in ${dirPath}`);
|
|
1434
|
-
}
|
|
1435
|
-
const translations = readTranslations(translationsPath, sourceLanguage);
|
|
1436
|
-
let allKeys = [];
|
|
1437
|
-
for (const namespace of namespaces) {
|
|
1438
|
-
const keys = Object.keys(translations[namespace] || {});
|
|
1439
|
-
allKeys = allKeys.concat(keys);
|
|
1440
|
-
}
|
|
1441
|
-
const outputDir = path6.dirname(outputFilePath);
|
|
1442
|
-
if (!fs3.existsSync(outputDir)) {
|
|
1443
|
-
fs3.mkdirSync(outputDir, { recursive: true });
|
|
1444
|
-
}
|
|
1445
|
-
const typeString = typeTemplate(allKeys, namespaces);
|
|
1446
|
-
fs3.writeFileSync(outputFilePath, typeString, "utf8");
|
|
1447
|
-
console.log(`Generated types with ${allKeys.length} keys and ${namespaces.length} namespaces`);
|
|
1448
|
-
console.log(`Output: ${outputFilePath}`);
|
|
1449
|
-
try {
|
|
1450
|
-
execSync(`pnpm biome format --write ${outputFilePath}`, {
|
|
1451
|
-
stdio: "inherit",
|
|
1452
|
-
cwd: projectRoot
|
|
1453
|
-
});
|
|
1454
|
-
} catch {
|
|
1455
|
-
console.warn("Failed to format with Biome, continuing without formatting...");
|
|
1456
|
-
}
|
|
1457
|
-
console.timeEnd("i18n types generated");
|
|
1458
|
-
console.log("=====");
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
1477
|
// src/translations/index.ts
|
|
1462
1478
|
init_init();
|
|
1463
1479
|
|