@verbaly/compiler 0.21.0 → 0.22.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/README.md +12 -1
- package/dist/cli.js +91 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +76 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -189,9 +189,12 @@ declare function doctor(cfg: ResolvedConfig): Promise<DoctorResult>;
|
|
|
189
189
|
//#endregion
|
|
190
190
|
//#region src/exchange.d.ts
|
|
191
191
|
type ExchangeFormat = 'xliff' | 'csv';
|
|
192
|
+
type MobileFormat = 'android-xml' | 'ios-strings';
|
|
193
|
+
type ExportFormat = ExchangeFormat | MobileFormat;
|
|
194
|
+
declare function isMobileFormat(format: ExportFormat): format is MobileFormat;
|
|
192
195
|
interface ExportOptions {
|
|
193
196
|
locales?: string[];
|
|
194
|
-
format?:
|
|
197
|
+
format?: ExportFormat;
|
|
195
198
|
out?: string;
|
|
196
199
|
missing?: boolean;
|
|
197
200
|
}
|
|
@@ -202,7 +205,7 @@ interface ExportedFile {
|
|
|
202
205
|
untranslated: number;
|
|
203
206
|
}
|
|
204
207
|
interface ExportResult {
|
|
205
|
-
format:
|
|
208
|
+
format: ExportFormat;
|
|
206
209
|
dir: string;
|
|
207
210
|
files: ExportedFile[];
|
|
208
211
|
}
|
|
@@ -309,5 +312,5 @@ interface RenderSiteResult {
|
|
|
309
312
|
}
|
|
310
313
|
declare function renderSite(cfg: ResolvedConfig, options?: RenderSiteOptions): Promise<RenderSiteResult>;
|
|
311
314
|
//#endregion
|
|
312
|
-
export { type Alternate, type Analysis, type AnalyzeOptions, type Catalog, type Catalogs, type CheckResult, type ClaudeProviderOptions, type DoctorEntry, type DoctorResult, type ExchangeFormat, type ExportOptions, type ExportResult, type ExportedFile, type ImportOptions, type ImportResult, type InitOptions, type InitResult, LOCALE_MODULE_PREFIX, MessageRegistry, type MissingEntry, PSEUDO_LOCALE, type ParamType, type PluginOptions, RESOLVED_VIRTUAL_ID, type RenderConfig, type RenderHtmlOptions, type RenderHtmlResult, type RenderSiteOptions, type RenderSiteResult, type ResolvedConfig, type RuntimeModuleOptions, SFC_FILE_RE, SOURCE_FILE_RE, type SyncResult, type TaggedMessage, type TaggedParam, type TransComponent, type TransformResult, type TranslateConfig, type TranslateOptions, type TranslateProvider, type TranslateRequest, type TranslateResult, type UnknownEntry, type UsedKey, VIRTUAL_ID, type VerbalyConfig, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, writeCatalog, writeDts };
|
|
315
|
+
export { type Alternate, type Analysis, type AnalyzeOptions, type Catalog, type Catalogs, type CheckResult, type ClaudeProviderOptions, type DoctorEntry, type DoctorResult, type ExchangeFormat, type ExportFormat, type ExportOptions, type ExportResult, type ExportedFile, type ImportOptions, type ImportResult, type InitOptions, type InitResult, LOCALE_MODULE_PREFIX, MessageRegistry, type MissingEntry, type MobileFormat, PSEUDO_LOCALE, type ParamType, type PluginOptions, RESOLVED_VIRTUAL_ID, type RenderConfig, type RenderHtmlOptions, type RenderHtmlResult, type RenderSiteOptions, type RenderSiteResult, type ResolvedConfig, type RuntimeModuleOptions, SFC_FILE_RE, SOURCE_FILE_RE, type SyncResult, type TaggedMessage, type TaggedParam, type TransComponent, type TransformResult, type TranslateConfig, type TranslateOptions, type TranslateProvider, type TranslateRequest, type TranslateResult, type UnknownEntry, type UsedKey, VIRTUAL_ID, type VerbalyConfig, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isMobileFormat, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, writeCatalog, writeDts };
|
|
313
316
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -382,11 +382,17 @@ function catalogPath(cfg, locale) {
|
|
|
382
382
|
return join(cfg.dir, `${locale}.json`);
|
|
383
383
|
}
|
|
384
384
|
function readCatalog(cfg, locale) {
|
|
385
|
+
let content;
|
|
385
386
|
try {
|
|
386
|
-
|
|
387
|
+
content = readFileSync(catalogPath(cfg, locale), "utf8");
|
|
387
388
|
} catch {
|
|
388
389
|
return {};
|
|
389
390
|
}
|
|
391
|
+
try {
|
|
392
|
+
return JSON.parse(content.replace(/^\uFEFF/, ""));
|
|
393
|
+
} catch (error) {
|
|
394
|
+
throw new Error(`[verbaly] ${catalogPath(cfg, locale)} is not valid JSON, fix or delete the file`, { cause: error });
|
|
395
|
+
}
|
|
390
396
|
}
|
|
391
397
|
function loadCatalogs(cfg) {
|
|
392
398
|
const catalogs = {};
|
|
@@ -1124,6 +1130,45 @@ function readDeps(root) {
|
|
|
1124
1130
|
}
|
|
1125
1131
|
}
|
|
1126
1132
|
//#endregion
|
|
1133
|
+
//#region src/mobile.ts
|
|
1134
|
+
function androidValuesDir(locale, sourceLocale) {
|
|
1135
|
+
if (locale === sourceLocale) return "values";
|
|
1136
|
+
const parts = locale.split("-");
|
|
1137
|
+
if (parts.length === 1) return `values-${locale}`;
|
|
1138
|
+
if (parts.length === 2 && /^[a-zA-Z]{2}$/.test(parts[1])) return `values-${parts[0]}-r${parts[1].toUpperCase()}`;
|
|
1139
|
+
return `values-b+${parts.join("+")}`;
|
|
1140
|
+
}
|
|
1141
|
+
function toAndroidXml(entries) {
|
|
1142
|
+
const names = /* @__PURE__ */ new Map();
|
|
1143
|
+
return [
|
|
1144
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
|
1145
|
+
"<resources>",
|
|
1146
|
+
...entries.map(({ key, text }) => {
|
|
1147
|
+
const name = androidName(key);
|
|
1148
|
+
const clash = names.get(name);
|
|
1149
|
+
if (clash !== void 0) throw new Error(`[verbaly] android-xml: keys "${clash}" and "${key}" both become resource name "${name}", rename one of them.`);
|
|
1150
|
+
names.set(name, key);
|
|
1151
|
+
return ` <string name="${name}">${androidText(text)}</string>`;
|
|
1152
|
+
}),
|
|
1153
|
+
"</resources>",
|
|
1154
|
+
""
|
|
1155
|
+
].join("\n");
|
|
1156
|
+
}
|
|
1157
|
+
function toIosStrings(entries) {
|
|
1158
|
+
return [...entries.map(({ key, text }) => `"${iosText(key)}" = "${iosText(text)}";`), ""].join("\n");
|
|
1159
|
+
}
|
|
1160
|
+
function androidName(key) {
|
|
1161
|
+
const name = key.replace(/[^A-Za-z0-9_]/g, "_");
|
|
1162
|
+
return /^[0-9]/.test(name) ? `_${name}` : name;
|
|
1163
|
+
}
|
|
1164
|
+
function androidText(text) {
|
|
1165
|
+
const escaped = text.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\t/g, "\\t").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1166
|
+
return /^[@?]/.test(escaped) ? `\\${escaped}` : escaped;
|
|
1167
|
+
}
|
|
1168
|
+
function iosText(text) {
|
|
1169
|
+
return text.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
1170
|
+
}
|
|
1171
|
+
//#endregion
|
|
1127
1172
|
//#region src/translate.ts
|
|
1128
1173
|
async function translateCatalogs(cfg, catalogs, provider, options = {}) {
|
|
1129
1174
|
const batchSize = options.batchSize ?? 20;
|
|
@@ -1182,11 +1227,15 @@ function sameMembers(a, b) {
|
|
|
1182
1227
|
}
|
|
1183
1228
|
//#endregion
|
|
1184
1229
|
//#region src/exchange.ts
|
|
1230
|
+
function isMobileFormat(format) {
|
|
1231
|
+
return format === "android-xml" || format === "ios-strings";
|
|
1232
|
+
}
|
|
1185
1233
|
function exportCatalogs(cfg, catalogs, options = {}) {
|
|
1186
1234
|
const format = options.format ?? "xliff";
|
|
1187
1235
|
const dir = resolve(cfg.root, options.out ?? "verbaly-export");
|
|
1188
1236
|
const source = catalogs[cfg.sourceLocale] ?? {};
|
|
1189
1237
|
const targets = targetLocales(cfg, options.locales);
|
|
1238
|
+
if (isMobileFormat(format)) return exportMobile(cfg, catalogs, format, dir, source, targets);
|
|
1190
1239
|
const files = [];
|
|
1191
1240
|
mkdirSync(dir, { recursive: true });
|
|
1192
1241
|
for (const locale of targets) {
|
|
@@ -1213,6 +1262,31 @@ function exportCatalogs(cfg, catalogs, options = {}) {
|
|
|
1213
1262
|
files
|
|
1214
1263
|
};
|
|
1215
1264
|
}
|
|
1265
|
+
function exportMobile(cfg, catalogs, format, dir, source, targets) {
|
|
1266
|
+
const keys = Object.keys(source).filter((key) => source[key]).sort();
|
|
1267
|
+
const files = [];
|
|
1268
|
+
for (const locale of [cfg.sourceLocale, ...targets]) {
|
|
1269
|
+
const catalog = locale === cfg.sourceLocale ? source : catalogs[locale] ?? {};
|
|
1270
|
+
const entries = keys.map((key) => ({
|
|
1271
|
+
key,
|
|
1272
|
+
text: catalog[key] ?? ""
|
|
1273
|
+
})).filter((entry) => entry.text);
|
|
1274
|
+
const path = join(dir, format === "android-xml" ? join(androidValuesDir(locale, cfg.sourceLocale), "strings.xml") : join(`${locale}.lproj`, "Localizable.strings"));
|
|
1275
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
1276
|
+
writeFileSync(path, format === "android-xml" ? toAndroidXml(entries) : toIosStrings(entries));
|
|
1277
|
+
files.push({
|
|
1278
|
+
locale,
|
|
1279
|
+
path,
|
|
1280
|
+
total: entries.length,
|
|
1281
|
+
untranslated: keys.length - entries.length
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
return {
|
|
1285
|
+
format,
|
|
1286
|
+
dir,
|
|
1287
|
+
files
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1216
1290
|
function importCatalogs(cfg, catalogs, files, options = {}) {
|
|
1217
1291
|
const source = catalogs[cfg.sourceLocale] ?? {};
|
|
1218
1292
|
const result = {
|
|
@@ -1683,6 +1757,6 @@ function decodeEntities(text) {
|
|
|
1683
1757
|
return text.replace(/"/g, "\"").replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
1684
1758
|
}
|
|
1685
1759
|
//#endregion
|
|
1686
|
-
export { LOCALE_MODULE_PREFIX, MessageRegistry, PSEUDO_LOCALE, RESOLVED_VIRTUAL_ID, SFC_FILE_RE, SOURCE_FILE_RE, VIRTUAL_ID, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, writeCatalog, writeDts };
|
|
1760
|
+
export { LOCALE_MODULE_PREFIX, MessageRegistry, PSEUDO_LOCALE, RESOLVED_VIRTUAL_ID, SFC_FILE_RE, SOURCE_FILE_RE, VIRTUAL_ID, analyze, analyzeFile, analyzeSfc, catalogPath, check, claudeProvider, collectParams, detectBundler, doctor, exportCatalogs, extractProject, findConfigFile, formatCheckResult, generateDts, generateLocaleModule, generateRuntimeModule, importCatalogs, init, isMobileFormat, isTransformTarget, loadCatalogs, loadConfig, loadConfigFile, loadVirtualModule, parseExchangeFile, pruneCatalogs, pseudoCatalogs, pseudoLocalize, readCatalog, renderHtml, renderParamType, renderSite, resolveConfig, resolveVirtualId, runBuildGate, serializeCatalog, stableKey, structureMatches, syncCatalogs, targetLocales, transformCode, transformSource, translateCatalogs, writeCatalog, writeDts };
|
|
1687
1761
|
|
|
1688
1762
|
//# sourceMappingURL=index.js.map
|