@lang-tag/cli 0.14.0 → 0.15.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/index.cjs CHANGED
@@ -9,6 +9,7 @@ const path = require("path");
9
9
  const globby = require("globby");
10
10
  const path$1 = require("pathe");
11
11
  const url = require("url");
12
+ const namespaceCollector = require("./namespace-collector-DRnZvkDR.cjs");
12
13
  const process$1 = require("node:process");
13
14
  const acorn = require("acorn");
14
15
  const micromatch = require("micromatch");
@@ -501,10 +502,13 @@ const CONFIG_FILE_NAME = ".lang-tag.config.js";
501
502
  const EXPORTS_FILE_NAME = ".lang-tag.exports.json";
502
503
  const LANG_TAG_DEFAULT_CONFIG = {
503
504
  tagName: "lang",
505
+ isLibrary: false,
504
506
  includes: ["src/**/*.{js,ts,jsx,tsx}"],
505
507
  excludes: ["node_modules", "dist", "build"],
506
- outputDir: "locales/en",
508
+ localesDirectory: "locales",
509
+ baseLanguageCode: "en",
507
510
  collect: {
511
+ collector: new namespaceCollector.NamespaceCollector(),
508
512
  defaultNamespace: "common",
509
513
  ignoreConflictsWithMatchingValues: true,
510
514
  onCollectConfigFix: ({ config, langTagConfig }) => {
@@ -531,8 +535,6 @@ const LANG_TAG_DEFAULT_CONFIG = {
531
535
  actions.setExportName(`translations${exportIndex}`);
532
536
  }
533
537
  },
534
- isLibrary: false,
535
- language: "en",
536
538
  translationArgPosition: 1,
537
539
  onConfigGeneration: async (event) => {
538
540
  }
@@ -552,7 +554,7 @@ async function $LT_ReadConfig(projectPath) {
552
554
  if (tn === "langtag" || tn === "lang-tag") {
553
555
  throw new Error('Custom tagName cannot be "lang-tag" or "langtag"! (It is not recommended for use with libraries)\n');
554
556
  }
555
- return {
557
+ const config = {
556
558
  ...LANG_TAG_DEFAULT_CONFIG,
557
559
  ...userConfig,
558
560
  import: {
@@ -564,39 +566,14 @@ async function $LT_ReadConfig(projectPath) {
564
566
  ...userConfig.collect
565
567
  }
566
568
  };
569
+ if (!config.collect.collector) {
570
+ throw new Error("Collector not found! (config.collect.collector)");
571
+ }
572
+ return config;
567
573
  } catch (error) {
568
574
  throw error;
569
575
  }
570
576
  }
571
- async function $LT_EnsureDirectoryExists(filePath) {
572
- await promises.mkdir(filePath, { recursive: true });
573
- }
574
- async function $LT_RemoveDirectory(dirPath) {
575
- try {
576
- await promises.rm(dirPath, { recursive: true, force: true });
577
- } catch (error) {
578
- }
579
- }
580
- async function $LT_WriteJSON(filePath, data) {
581
- await promises.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
582
- }
583
- async function $LT_ReadJSON(filePath) {
584
- const content = await promises.readFile(filePath, "utf-8");
585
- return JSON.parse(content);
586
- }
587
- async function $LT_WriteFileWithDirs(filePath, content) {
588
- const dir = path.dirname(filePath);
589
- try {
590
- await promises.mkdir(dir, { recursive: true });
591
- } catch (error) {
592
- }
593
- await promises.writeFile(filePath, content, "utf-8");
594
- }
595
- async function $LT_ReadFileContent(relativeFilePath) {
596
- const cwd = process.cwd();
597
- const absolutePath = path.resolve(cwd, relativeFilePath);
598
- return await promises.readFile(absolutePath, "utf-8");
599
- }
600
577
  function parseObjectAST(code) {
601
578
  const nodes = [];
602
579
  try {
@@ -809,7 +786,7 @@ function printLines(lines, startLineNumber, errorLines = /* @__PURE__ */ new Set
809
786
  }
810
787
  async function getLangTagCodeSection(tagInfo) {
811
788
  const { tag, relativeFilePath } = tagInfo;
812
- const fileContent = await $LT_ReadFileContent(relativeFilePath);
789
+ const fileContent = await namespaceCollector.$LT_ReadFileContent(relativeFilePath);
813
790
  const fileLines = fileContent.split("\n");
814
791
  const startLine = tag.line;
815
792
  const endLine = tag.line + tag.fullMatch.split("\n").length - 1;
@@ -998,6 +975,8 @@ function $LT_CreateDefaultLogger(debugMode, translationArgPosition = 1) {
998
975
  async function $LT_GetCommandEssentials() {
999
976
  const config = await $LT_ReadConfig(process$1.cwd());
1000
977
  const logger = $LT_CreateDefaultLogger(config.debug, config.translationArgPosition);
978
+ config.collect.collector.config = config;
979
+ config.collect.collector.logger = logger;
1001
980
  return {
1002
981
  config,
1003
982
  logger
@@ -1060,36 +1039,26 @@ function deepMergeTranslations(target, source) {
1060
1039
  }
1061
1040
  return changed;
1062
1041
  }
1063
- async function $LT_WriteToNamespaces({ config, namespaces, logger, clean }) {
1064
- const changedNamespaces = [];
1065
- if (clean) {
1066
- logger.info("Cleaning output directory...");
1067
- await $LT_RemoveDirectory(config.outputDir);
1068
- }
1069
- await $LT_EnsureDirectoryExists(config.outputDir);
1070
- for (let namespace of Object.keys(namespaces)) {
1042
+ async function $LT_WriteToCollections({ config, collections, logger, clean }) {
1043
+ await config.collect.collector.preWrite(clean);
1044
+ const changedCollections = [];
1045
+ for (let namespace of Object.keys(collections)) {
1071
1046
  if (!namespace) {
1072
1047
  continue;
1073
1048
  }
1074
- const filePath = path$1.resolve(
1075
- process$1.cwd(),
1076
- config.outputDir,
1077
- namespace + ".json"
1078
- );
1049
+ const filePath = await config.collect.collector.resolveCollectionFilePath(namespace);
1079
1050
  let originalJSON = {};
1080
1051
  try {
1081
- originalJSON = await $LT_ReadJSON(filePath);
1052
+ originalJSON = await namespaceCollector.$LT_ReadJSON(filePath);
1082
1053
  } catch (e) {
1083
- if (!clean) {
1084
- logger.warn(`Original namespace file "{namespace}.json" not found. A new one will be created.`, { namespace });
1085
- }
1054
+ await config.collect.collector.onMissingCollection(namespace);
1086
1055
  }
1087
- if (deepMergeTranslations(originalJSON, namespaces[namespace])) {
1088
- changedNamespaces.push(namespace);
1089
- await $LT_WriteJSON(filePath, originalJSON);
1056
+ if (deepMergeTranslations(originalJSON, collections[namespace])) {
1057
+ changedCollections.push(namespace);
1058
+ await namespaceCollector.$LT_WriteJSON(filePath, originalJSON);
1090
1059
  }
1091
1060
  }
1092
- return changedNamespaces;
1061
+ await config.collect.collector.postWrite(changedCollections);
1093
1062
  }
1094
1063
  async function $LT_CollectCandidateFilesWithTags(props) {
1095
1064
  const { config, logger } = props;
@@ -1120,7 +1089,7 @@ async function $LT_CollectCandidateFilesWithTags(props) {
1120
1089
  return candidates;
1121
1090
  }
1122
1091
  async function $LT_WriteAsExportFile({ config, logger, files }) {
1123
- const packageJson = await $LT_ReadJSON(path.resolve(process.cwd(), "package.json"));
1092
+ const packageJson = await namespaceCollector.$LT_ReadJSON(path.resolve(process.cwd(), "package.json"));
1124
1093
  if (!packageJson) {
1125
1094
  throw new Error("package.json not found");
1126
1095
  }
@@ -1141,30 +1110,32 @@ async function $LT_WriteAsExportFile({ config, logger, files }) {
1141
1110
  };
1142
1111
  }
1143
1112
  const data = {
1144
- language: config.language,
1113
+ language: config.baseLanguageCode,
1145
1114
  packageName: packageJson.name || "",
1146
1115
  files: langTagFiles
1147
1116
  };
1148
- await $LT_WriteJSON(EXPORTS_FILE_NAME, data);
1117
+ await namespaceCollector.$LT_WriteJSON(EXPORTS_FILE_NAME, data);
1149
1118
  logger.success(`Written {file}`, { file: EXPORTS_FILE_NAME });
1150
1119
  }
1151
- async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1120
+ async function $LT_GroupTagsToCollections({ logger, files, config }) {
1152
1121
  let totalTags = 0;
1153
- const namespaces = {};
1154
- function getTranslations(namespace) {
1155
- const namespaceTranslations = namespaces[namespace] || {};
1156
- if (!(namespace in namespaces)) {
1157
- namespaces[namespace] = namespaceTranslations;
1122
+ const collections = {};
1123
+ function getTranslationsCollection(namespace) {
1124
+ const collectionName = config.collect.collector.aggregateCollection(namespace);
1125
+ const collection = collections[collectionName] || {};
1126
+ if (!(collectionName in collections)) {
1127
+ collections[collectionName] = collection;
1158
1128
  }
1159
- return namespaceTranslations;
1129
+ return collection;
1160
1130
  }
1161
1131
  const allConflicts = [];
1162
1132
  const existingValuesByNamespace = /* @__PURE__ */ new Map();
1163
1133
  for (const file of files) {
1164
1134
  totalTags += file.tags.length;
1165
- for (const tag of file.tags) {
1135
+ for (const _tag of file.tags) {
1136
+ const tag = config.collect.collector.transformTag(_tag);
1166
1137
  const tagConfig = tag.parameterConfig;
1167
- const namespaceTranslations = getTranslations(tagConfig.namespace);
1138
+ const collection = getTranslationsCollection(tagConfig.namespace);
1168
1139
  let existingValues = existingValuesByNamespace.get(tagConfig.namespace);
1169
1140
  if (!existingValues) {
1170
1141
  existingValues = /* @__PURE__ */ new Map();
@@ -1207,7 +1178,7 @@ async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1207
1178
  };
1208
1179
  const target = await ensureNestedObject(
1209
1180
  tagConfig.path,
1210
- namespaceTranslations,
1181
+ collection,
1211
1182
  valueTracker,
1212
1183
  addConflict
1213
1184
  );
@@ -1227,7 +1198,7 @@ async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1227
1198
  let shouldContinue = true;
1228
1199
  config.collect.onCollectFinish({
1229
1200
  totalTags,
1230
- namespaces,
1201
+ namespaces: collections,
1231
1202
  conflicts: allConflicts,
1232
1203
  logger,
1233
1204
  exit() {
@@ -1238,11 +1209,11 @@ async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1238
1209
  throw new Error(`LangTagConflictResolution:Processing stopped due to collect finish handler`);
1239
1210
  }
1240
1211
  }
1241
- return namespaces;
1212
+ return collections;
1242
1213
  }
1243
- async function ensureNestedObject(path2, root, valueTracker, addConflict) {
1244
- if (!path2 || !path2.trim()) return root;
1245
- let current = root;
1214
+ async function ensureNestedObject(path2, rootCollection, valueTracker, addConflict) {
1215
+ if (!path2 || !path2.trim()) return rootCollection;
1216
+ let current = rootCollection;
1246
1217
  let currentPath = "";
1247
1218
  for (const key of path2.split(".")) {
1248
1219
  currentPath = currentPath ? `${currentPath}.${key}` : key;
@@ -1342,19 +1313,10 @@ async function $LT_CMD_Collect(options) {
1342
1313
  return;
1343
1314
  }
1344
1315
  try {
1345
- const namespaces = await $LT_GroupTagsToNamespaces({ logger, files, config });
1316
+ const collections = await $LT_GroupTagsToCollections({ logger, files, config });
1346
1317
  const totalTags = files.reduce((sum, file) => sum + file.tags.length, 0);
1347
1318
  logger.debug("Found {totalTags} translation tags", { totalTags });
1348
- const changedNamespaces = await $LT_WriteToNamespaces({ config, namespaces, logger, clean: options?.clean });
1349
- if (!changedNamespaces?.length) {
1350
- logger.info("No changes were made based on the current configuration and files");
1351
- return;
1352
- }
1353
- const n = changedNamespaces.map((n2) => `"${n2}.json"`).join(", ");
1354
- logger.success("Updated namespaces {outputDir} ({namespaces})", {
1355
- outputDir: config.outputDir,
1356
- namespaces: n
1357
- });
1319
+ await $LT_WriteToCollections({ config, collections, logger, clean: options?.clean });
1358
1320
  } catch (e) {
1359
1321
  const prefix = "LangTagConflictResolution:";
1360
1322
  if (e.message.startsWith(prefix)) {
@@ -1420,15 +1382,8 @@ async function handleFile(config, logger, cwdRelativeFilePath, event) {
1420
1382
  const absoluteFilePath = path.join(cwd, cwdRelativeFilePath);
1421
1383
  await checkAndRegenerateFileLangTags(config, logger, absoluteFilePath, cwdRelativeFilePath);
1422
1384
  const files = await $LT_CollectCandidateFilesWithTags({ filesToScan: [cwdRelativeFilePath], config, logger });
1423
- const namespaces = await $LT_GroupTagsToNamespaces({ logger, files, config });
1424
- const changedNamespaces = await $LT_WriteToNamespaces({ config, namespaces, logger });
1425
- if (changedNamespaces.length > 0) {
1426
- const n = changedNamespaces.map((n2) => `"${n2}.json"`).join(", ");
1427
- logger.success("Updated namespaces {outputDir} ({namespaces})", {
1428
- outputDir: config.outputDir,
1429
- namespaces: n
1430
- });
1431
- }
1385
+ const namespaces = await $LT_GroupTagsToCollections({ logger, files, config });
1386
+ await $LT_WriteToCollections({ config, collections: namespaces, logger });
1432
1387
  }
1433
1388
  async function detectModuleSystem() {
1434
1389
  const packageJsonPath = path.join(process.cwd(), "package.json");
@@ -1468,7 +1423,13 @@ const generationAlgorithm = pathBasedConfigGenerator({
1468
1423
  // },
1469
1424
  // admin: {
1470
1425
  // '>': 'management', // rename "admin" to "management"
1471
- // users: false // ignore "users"
1426
+ // users: false // ignore "users",
1427
+ // ui: {
1428
+ // '>>': { // 'redirect' - ignore everything, jump to 'ui' namespace and prefix all paths with 'admin'
1429
+ // namespace: 'ui',
1430
+ // pathPrefix: 'admin'
1431
+ // }
1432
+ // }
1472
1433
  // }
1473
1434
  // }
1474
1435
  // }
@@ -1481,7 +1442,8 @@ const config = {
1481
1442
  isLibrary: false,
1482
1443
  includes: ['src/**/*.{js,ts,jsx,tsx}'],
1483
1444
  excludes: ['node_modules', 'dist', 'build', '**/*.test.ts'],
1484
- outputDir: 'public/locales/en',
1445
+ localesDirectory: 'public/locales',
1446
+ baseLanguageCode: 'en',
1485
1447
  onConfigGeneration: async event => {
1486
1448
  // We do not modify imported configurations
1487
1449
  if (event.isImportedLibrary) return;
@@ -1557,7 +1519,7 @@ async function $LT_ImportLibraries(config, logger) {
1557
1519
  const files = $LT_CollectNodeModulesExportFilePaths(logger);
1558
1520
  const generationFiles = {};
1559
1521
  for (const filePath of files) {
1560
- const exportData = await $LT_ReadJSON(filePath);
1522
+ const exportData = await namespaceCollector.$LT_ReadJSON(filePath);
1561
1523
  for (let langTagFilePath in exportData.files) {
1562
1524
  const fileGenerationData = {};
1563
1525
  const matches = exportData.files[langTagFilePath].matches;
@@ -1610,7 +1572,7 @@ async function $LT_ImportLibraries(config, logger) {
1610
1572
  const content = `${config.import.tagImportPath}
1611
1573
 
1612
1574
  ${exports2}`;
1613
- await $LT_EnsureDirectoryExists(path$1.dirname(filePath));
1575
+ await namespaceCollector.$LT_EnsureDirectoryExists(path$1.dirname(filePath));
1614
1576
  await promises.writeFile(filePath, content, "utf-8");
1615
1577
  logger.success('Imported node_modules file: "{fileName}"', { fileName });
1616
1578
  }
@@ -1618,7 +1580,7 @@ ${exports2}`;
1618
1580
  }
1619
1581
  async function $LT_ImportTranslations() {
1620
1582
  const { config, logger } = await $LT_GetCommandEssentials();
1621
- await $LT_EnsureDirectoryExists(config.import.dir);
1583
+ await namespaceCollector.$LT_EnsureDirectoryExists(config.import.dir);
1622
1584
  logger.info("Importing translations from libraries...");
1623
1585
  await $LT_ImportLibraries(config, logger);
1624
1586
  logger.success("Successfully imported translations from libraries.");
@@ -1719,7 +1681,7 @@ async function $LT_CMD_InitTagFile(options = {}) {
1719
1681
  return;
1720
1682
  }
1721
1683
  try {
1722
- await $LT_WriteFileWithDirs(outputPath, renderedContent);
1684
+ await namespaceCollector.$LT_WriteFileWithDirs(outputPath, renderedContent);
1723
1685
  logger.success("Lang-tag file created successfully: {outputPath}", { outputPath });
1724
1686
  logger.info("Next steps:");
1725
1687
  logger.info("1. Import the {tagName} function in your files:", { tagName: renderOptions.tagName });
package/index.js CHANGED
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from "commander";
3
3
  import fs, { readFileSync, existsSync } from "fs";
4
- import { writeFile, mkdir, readFile, rm } from "fs/promises";
4
+ import { writeFile, readFile } from "fs/promises";
5
5
  import JSON5 from "json5";
6
6
  import * as path from "path";
7
- import path__default, { sep, dirname, resolve as resolve$1, join } from "path";
7
+ import path__default, { sep, join, dirname as dirname$1 } from "path";
8
8
  import { globby } from "globby";
9
- import path$1, { resolve, dirname as dirname$1 } from "pathe";
9
+ import path$1, { resolve, dirname } from "pathe";
10
10
  import { pathToFileURL, fileURLToPath } from "url";
11
+ import { N as NamespaceCollector, $ as $LT_ReadFileContent, a as $LT_ReadJSON, b as $LT_WriteJSON, c as $LT_EnsureDirectoryExists, d as $LT_WriteFileWithDirs } from "./namespace-collector-DCruv_PK.js";
11
12
  import * as process$1 from "node:process";
12
13
  import process__default from "node:process";
13
14
  import * as acorn from "acorn";
@@ -481,10 +482,13 @@ const CONFIG_FILE_NAME = ".lang-tag.config.js";
481
482
  const EXPORTS_FILE_NAME = ".lang-tag.exports.json";
482
483
  const LANG_TAG_DEFAULT_CONFIG = {
483
484
  tagName: "lang",
485
+ isLibrary: false,
484
486
  includes: ["src/**/*.{js,ts,jsx,tsx}"],
485
487
  excludes: ["node_modules", "dist", "build"],
486
- outputDir: "locales/en",
488
+ localesDirectory: "locales",
489
+ baseLanguageCode: "en",
487
490
  collect: {
491
+ collector: new NamespaceCollector(),
488
492
  defaultNamespace: "common",
489
493
  ignoreConflictsWithMatchingValues: true,
490
494
  onCollectConfigFix: ({ config, langTagConfig }) => {
@@ -511,8 +515,6 @@ const LANG_TAG_DEFAULT_CONFIG = {
511
515
  actions.setExportName(`translations${exportIndex}`);
512
516
  }
513
517
  },
514
- isLibrary: false,
515
- language: "en",
516
518
  translationArgPosition: 1,
517
519
  onConfigGeneration: async (event) => {
518
520
  }
@@ -532,7 +534,7 @@ async function $LT_ReadConfig(projectPath) {
532
534
  if (tn === "langtag" || tn === "lang-tag") {
533
535
  throw new Error('Custom tagName cannot be "lang-tag" or "langtag"! (It is not recommended for use with libraries)\n');
534
536
  }
535
- return {
537
+ const config = {
536
538
  ...LANG_TAG_DEFAULT_CONFIG,
537
539
  ...userConfig,
538
540
  import: {
@@ -544,39 +546,14 @@ async function $LT_ReadConfig(projectPath) {
544
546
  ...userConfig.collect
545
547
  }
546
548
  };
549
+ if (!config.collect.collector) {
550
+ throw new Error("Collector not found! (config.collect.collector)");
551
+ }
552
+ return config;
547
553
  } catch (error) {
548
554
  throw error;
549
555
  }
550
556
  }
551
- async function $LT_EnsureDirectoryExists(filePath) {
552
- await mkdir(filePath, { recursive: true });
553
- }
554
- async function $LT_RemoveDirectory(dirPath) {
555
- try {
556
- await rm(dirPath, { recursive: true, force: true });
557
- } catch (error) {
558
- }
559
- }
560
- async function $LT_WriteJSON(filePath, data) {
561
- await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
562
- }
563
- async function $LT_ReadJSON(filePath) {
564
- const content = await readFile(filePath, "utf-8");
565
- return JSON.parse(content);
566
- }
567
- async function $LT_WriteFileWithDirs(filePath, content) {
568
- const dir = dirname(filePath);
569
- try {
570
- await mkdir(dir, { recursive: true });
571
- } catch (error) {
572
- }
573
- await writeFile(filePath, content, "utf-8");
574
- }
575
- async function $LT_ReadFileContent(relativeFilePath) {
576
- const cwd = process.cwd();
577
- const absolutePath = resolve$1(cwd, relativeFilePath);
578
- return await readFile(absolutePath, "utf-8");
579
- }
580
557
  function parseObjectAST(code) {
581
558
  const nodes = [];
582
559
  try {
@@ -978,6 +955,8 @@ function $LT_CreateDefaultLogger(debugMode, translationArgPosition = 1) {
978
955
  async function $LT_GetCommandEssentials() {
979
956
  const config = await $LT_ReadConfig(process__default.cwd());
980
957
  const logger = $LT_CreateDefaultLogger(config.debug, config.translationArgPosition);
958
+ config.collect.collector.config = config;
959
+ config.collect.collector.logger = logger;
981
960
  return {
982
961
  config,
983
962
  logger
@@ -1040,36 +1019,26 @@ function deepMergeTranslations(target, source) {
1040
1019
  }
1041
1020
  return changed;
1042
1021
  }
1043
- async function $LT_WriteToNamespaces({ config, namespaces, logger, clean }) {
1044
- const changedNamespaces = [];
1045
- if (clean) {
1046
- logger.info("Cleaning output directory...");
1047
- await $LT_RemoveDirectory(config.outputDir);
1048
- }
1049
- await $LT_EnsureDirectoryExists(config.outputDir);
1050
- for (let namespace of Object.keys(namespaces)) {
1022
+ async function $LT_WriteToCollections({ config, collections, logger, clean }) {
1023
+ await config.collect.collector.preWrite(clean);
1024
+ const changedCollections = [];
1025
+ for (let namespace of Object.keys(collections)) {
1051
1026
  if (!namespace) {
1052
1027
  continue;
1053
1028
  }
1054
- const filePath = resolve(
1055
- process__default.cwd(),
1056
- config.outputDir,
1057
- namespace + ".json"
1058
- );
1029
+ const filePath = await config.collect.collector.resolveCollectionFilePath(namespace);
1059
1030
  let originalJSON = {};
1060
1031
  try {
1061
1032
  originalJSON = await $LT_ReadJSON(filePath);
1062
1033
  } catch (e) {
1063
- if (!clean) {
1064
- logger.warn(`Original namespace file "{namespace}.json" not found. A new one will be created.`, { namespace });
1065
- }
1034
+ await config.collect.collector.onMissingCollection(namespace);
1066
1035
  }
1067
- if (deepMergeTranslations(originalJSON, namespaces[namespace])) {
1068
- changedNamespaces.push(namespace);
1036
+ if (deepMergeTranslations(originalJSON, collections[namespace])) {
1037
+ changedCollections.push(namespace);
1069
1038
  await $LT_WriteJSON(filePath, originalJSON);
1070
1039
  }
1071
1040
  }
1072
- return changedNamespaces;
1041
+ await config.collect.collector.postWrite(changedCollections);
1073
1042
  }
1074
1043
  async function $LT_CollectCandidateFilesWithTags(props) {
1075
1044
  const { config, logger } = props;
@@ -1121,30 +1090,32 @@ async function $LT_WriteAsExportFile({ config, logger, files }) {
1121
1090
  };
1122
1091
  }
1123
1092
  const data = {
1124
- language: config.language,
1093
+ language: config.baseLanguageCode,
1125
1094
  packageName: packageJson.name || "",
1126
1095
  files: langTagFiles
1127
1096
  };
1128
1097
  await $LT_WriteJSON(EXPORTS_FILE_NAME, data);
1129
1098
  logger.success(`Written {file}`, { file: EXPORTS_FILE_NAME });
1130
1099
  }
1131
- async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1100
+ async function $LT_GroupTagsToCollections({ logger, files, config }) {
1132
1101
  let totalTags = 0;
1133
- const namespaces = {};
1134
- function getTranslations(namespace) {
1135
- const namespaceTranslations = namespaces[namespace] || {};
1136
- if (!(namespace in namespaces)) {
1137
- namespaces[namespace] = namespaceTranslations;
1102
+ const collections = {};
1103
+ function getTranslationsCollection(namespace) {
1104
+ const collectionName = config.collect.collector.aggregateCollection(namespace);
1105
+ const collection = collections[collectionName] || {};
1106
+ if (!(collectionName in collections)) {
1107
+ collections[collectionName] = collection;
1138
1108
  }
1139
- return namespaceTranslations;
1109
+ return collection;
1140
1110
  }
1141
1111
  const allConflicts = [];
1142
1112
  const existingValuesByNamespace = /* @__PURE__ */ new Map();
1143
1113
  for (const file of files) {
1144
1114
  totalTags += file.tags.length;
1145
- for (const tag of file.tags) {
1115
+ for (const _tag of file.tags) {
1116
+ const tag = config.collect.collector.transformTag(_tag);
1146
1117
  const tagConfig = tag.parameterConfig;
1147
- const namespaceTranslations = getTranslations(tagConfig.namespace);
1118
+ const collection = getTranslationsCollection(tagConfig.namespace);
1148
1119
  let existingValues = existingValuesByNamespace.get(tagConfig.namespace);
1149
1120
  if (!existingValues) {
1150
1121
  existingValues = /* @__PURE__ */ new Map();
@@ -1187,7 +1158,7 @@ async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1187
1158
  };
1188
1159
  const target = await ensureNestedObject(
1189
1160
  tagConfig.path,
1190
- namespaceTranslations,
1161
+ collection,
1191
1162
  valueTracker,
1192
1163
  addConflict
1193
1164
  );
@@ -1207,7 +1178,7 @@ async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1207
1178
  let shouldContinue = true;
1208
1179
  config.collect.onCollectFinish({
1209
1180
  totalTags,
1210
- namespaces,
1181
+ namespaces: collections,
1211
1182
  conflicts: allConflicts,
1212
1183
  logger,
1213
1184
  exit() {
@@ -1218,11 +1189,11 @@ async function $LT_GroupTagsToNamespaces({ logger, files, config }) {
1218
1189
  throw new Error(`LangTagConflictResolution:Processing stopped due to collect finish handler`);
1219
1190
  }
1220
1191
  }
1221
- return namespaces;
1192
+ return collections;
1222
1193
  }
1223
- async function ensureNestedObject(path2, root, valueTracker, addConflict) {
1224
- if (!path2 || !path2.trim()) return root;
1225
- let current = root;
1194
+ async function ensureNestedObject(path2, rootCollection, valueTracker, addConflict) {
1195
+ if (!path2 || !path2.trim()) return rootCollection;
1196
+ let current = rootCollection;
1226
1197
  let currentPath = "";
1227
1198
  for (const key of path2.split(".")) {
1228
1199
  currentPath = currentPath ? `${currentPath}.${key}` : key;
@@ -1322,19 +1293,10 @@ async function $LT_CMD_Collect(options) {
1322
1293
  return;
1323
1294
  }
1324
1295
  try {
1325
- const namespaces = await $LT_GroupTagsToNamespaces({ logger, files, config });
1296
+ const collections = await $LT_GroupTagsToCollections({ logger, files, config });
1326
1297
  const totalTags = files.reduce((sum, file) => sum + file.tags.length, 0);
1327
1298
  logger.debug("Found {totalTags} translation tags", { totalTags });
1328
- const changedNamespaces = await $LT_WriteToNamespaces({ config, namespaces, logger, clean: options?.clean });
1329
- if (!changedNamespaces?.length) {
1330
- logger.info("No changes were made based on the current configuration and files");
1331
- return;
1332
- }
1333
- const n = changedNamespaces.map((n2) => `"${n2}.json"`).join(", ");
1334
- logger.success("Updated namespaces {outputDir} ({namespaces})", {
1335
- outputDir: config.outputDir,
1336
- namespaces: n
1337
- });
1299
+ await $LT_WriteToCollections({ config, collections, logger, clean: options?.clean });
1338
1300
  } catch (e) {
1339
1301
  const prefix = "LangTagConflictResolution:";
1340
1302
  if (e.message.startsWith(prefix)) {
@@ -1400,15 +1362,8 @@ async function handleFile(config, logger, cwdRelativeFilePath, event) {
1400
1362
  const absoluteFilePath = path__default.join(cwd, cwdRelativeFilePath);
1401
1363
  await checkAndRegenerateFileLangTags(config, logger, absoluteFilePath, cwdRelativeFilePath);
1402
1364
  const files = await $LT_CollectCandidateFilesWithTags({ filesToScan: [cwdRelativeFilePath], config, logger });
1403
- const namespaces = await $LT_GroupTagsToNamespaces({ logger, files, config });
1404
- const changedNamespaces = await $LT_WriteToNamespaces({ config, namespaces, logger });
1405
- if (changedNamespaces.length > 0) {
1406
- const n = changedNamespaces.map((n2) => `"${n2}.json"`).join(", ");
1407
- logger.success("Updated namespaces {outputDir} ({namespaces})", {
1408
- outputDir: config.outputDir,
1409
- namespaces: n
1410
- });
1411
- }
1365
+ const namespaces = await $LT_GroupTagsToCollections({ logger, files, config });
1366
+ await $LT_WriteToCollections({ config, collections: namespaces, logger });
1412
1367
  }
1413
1368
  async function detectModuleSystem() {
1414
1369
  const packageJsonPath = join(process.cwd(), "package.json");
@@ -1448,7 +1403,13 @@ const generationAlgorithm = pathBasedConfigGenerator({
1448
1403
  // },
1449
1404
  // admin: {
1450
1405
  // '>': 'management', // rename "admin" to "management"
1451
- // users: false // ignore "users"
1406
+ // users: false // ignore "users",
1407
+ // ui: {
1408
+ // '>>': { // 'redirect' - ignore everything, jump to 'ui' namespace and prefix all paths with 'admin'
1409
+ // namespace: 'ui',
1410
+ // pathPrefix: 'admin'
1411
+ // }
1412
+ // }
1452
1413
  // }
1453
1414
  // }
1454
1415
  // }
@@ -1461,7 +1422,8 @@ const config = {
1461
1422
  isLibrary: false,
1462
1423
  includes: ['src/**/*.{js,ts,jsx,tsx}'],
1463
1424
  excludes: ['node_modules', 'dist', 'build', '**/*.test.ts'],
1464
- outputDir: 'public/locales/en',
1425
+ localesDirectory: 'public/locales',
1426
+ baseLanguageCode: 'en',
1465
1427
  onConfigGeneration: async event => {
1466
1428
  // We do not modify imported configurations
1467
1429
  if (event.isImportedLibrary) return;
@@ -1590,7 +1552,7 @@ async function $LT_ImportLibraries(config, logger) {
1590
1552
  const content = `${config.import.tagImportPath}
1591
1553
 
1592
1554
  ${exports}`;
1593
- await $LT_EnsureDirectoryExists(dirname$1(filePath));
1555
+ await $LT_EnsureDirectoryExists(dirname(filePath));
1594
1556
  await writeFile(filePath, content, "utf-8");
1595
1557
  logger.success('Imported node_modules file: "{fileName}"', { fileName });
1596
1558
  }
@@ -1608,7 +1570,7 @@ function renderTemplate(template, data) {
1608
1570
  }
1609
1571
  function loadTemplate(templateName) {
1610
1572
  const __filename = fileURLToPath(import.meta.url);
1611
- const __dirname = dirname(__filename);
1573
+ const __dirname = dirname$1(__filename);
1612
1574
  const templatePath = join(__dirname, "template", `${templateName}.mustache`);
1613
1575
  try {
1614
1576
  return readFileSync(templatePath, "utf-8");