@lang-tag/cli 0.13.1 → 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/algorithms/collector/dictionary-collector.d.ts +17 -0
- package/algorithms/collector/index.d.ts +10 -0
- package/algorithms/collector/namespace-collector.d.ts +12 -0
- package/algorithms/collector/type.d.ts +12 -0
- package/algorithms/config-generation/index.d.ts +1 -0
- package/algorithms/config-generation/path-based-config-generator.d.ts +25 -0
- package/algorithms/config-generation/prepend-namespace-to-path.d.ts +28 -0
- package/algorithms/index.cjs +182 -5
- package/algorithms/index.d.ts +6 -3
- package/algorithms/index.js +194 -16
- package/config.d.ts +58 -47
- package/index.cjs +86 -122
- package/index.js +82 -118
- package/namespace-collector-DCruv_PK.js +95 -0
- package/namespace-collector-DRnZvkDR.cjs +94 -0
- package/package.json +1 -1
- package/template/base-app.mustache +11 -16
- package/template/base-library.mustache +24 -33
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TranslationsCollector } from './type.ts';
|
|
2
|
+
import { LangTagCLIProcessedTag } from '../../config.ts';
|
|
3
|
+
interface Options {
|
|
4
|
+
appendNamespaceToPath: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class DictionaryCollector extends TranslationsCollector {
|
|
7
|
+
private readonly options;
|
|
8
|
+
private clean;
|
|
9
|
+
constructor(options?: Options);
|
|
10
|
+
aggregateCollection(namespace: string): string;
|
|
11
|
+
transformTag(tag: LangTagCLIProcessedTag): LangTagCLIProcessedTag;
|
|
12
|
+
preWrite(clean: boolean): Promise<void>;
|
|
13
|
+
resolveCollectionFilePath(baseLanguageCode: string): Promise<any>;
|
|
14
|
+
onMissingCollection(baseLanguageCode: string): Promise<void>;
|
|
15
|
+
postWrite(changedCollections: string[]): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translation collectors for organizing translation tags into output files.
|
|
3
|
+
*
|
|
4
|
+
* These collectors define how translation tags are grouped and written to files
|
|
5
|
+
* during the collection process. Each collector implements a different strategy
|
|
6
|
+
* for organizing translations (e.g., single dictionary vs. namespace-based files).
|
|
7
|
+
*/
|
|
8
|
+
export { DictionaryCollector } from './dictionary-collector.ts';
|
|
9
|
+
export { NamespaceCollector } from './namespace-collector.ts';
|
|
10
|
+
export { type TranslationsCollector } from './type.ts';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TranslationsCollector } from './type.ts';
|
|
2
|
+
import { LangTagCLIProcessedTag } from '../../config.ts';
|
|
3
|
+
export declare class NamespaceCollector extends TranslationsCollector {
|
|
4
|
+
private clean;
|
|
5
|
+
private languageDirectory;
|
|
6
|
+
aggregateCollection(namespace: string): string;
|
|
7
|
+
transformTag(tag: LangTagCLIProcessedTag): LangTagCLIProcessedTag;
|
|
8
|
+
preWrite(clean: boolean): Promise<void>;
|
|
9
|
+
resolveCollectionFilePath(collectionName: string): Promise<any>;
|
|
10
|
+
onMissingCollection(collectionName: string): Promise<void>;
|
|
11
|
+
postWrite(changedCollections: string[]): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LangTagCLIConfig, LangTagCLIProcessedTag } from '../../config.ts';
|
|
2
|
+
import { LangTagCLILogger } from '../../logger.ts';
|
|
3
|
+
export declare abstract class TranslationsCollector {
|
|
4
|
+
config: LangTagCLIConfig;
|
|
5
|
+
logger: LangTagCLILogger;
|
|
6
|
+
abstract aggregateCollection(namespace: string): string;
|
|
7
|
+
abstract transformTag(tag: LangTagCLIProcessedTag): LangTagCLIProcessedTag;
|
|
8
|
+
abstract preWrite(clean?: boolean): Promise<void>;
|
|
9
|
+
abstract resolveCollectionFilePath(collectionName: string): Promise<string>;
|
|
10
|
+
abstract onMissingCollection(collectionName: string): Promise<void>;
|
|
11
|
+
abstract postWrite(changedCollections: string[]): Promise<void>;
|
|
12
|
+
}
|
|
@@ -6,3 +6,4 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { pathBasedConfigGenerator, type PathBasedConfigGeneratorOptions } from './path-based-config-generator.ts';
|
|
8
8
|
export { configKeeper, type ConfigKeeperOptions, type ConfigKeeperMode } from './config-keeper.ts';
|
|
9
|
+
export { prependNamespaceToPath, type PrependNamespaceToPathOptions } from './prepend-namespace-to-path.ts';
|
|
@@ -67,6 +67,12 @@ export interface PathBasedConfigGeneratorOptions {
|
|
|
67
67
|
* Supports ignoring and renaming segments with special keys:
|
|
68
68
|
* - `_`: when `false`, ignores the current segment but continues hierarchy
|
|
69
69
|
* - `>`: renames the current segment to the specified value
|
|
70
|
+
* - `>>`: namespace redirect - jumps to a different namespace and continues processing remaining path segments
|
|
71
|
+
* - String: `>>: 'namespace'` - redirects to specified namespace, remaining segments become path
|
|
72
|
+
* - Object: `>>: { namespace: 'name', pathPrefix: 'prefix.' }` - redirects with optional path prefix
|
|
73
|
+
* - Empty: `>>: ''` or `>>: null/undefined` - uses current segment as namespace
|
|
74
|
+
* - Missing namespace: `>>: { pathPrefix: 'prefix.' }` - uses current segment as namespace with prefix
|
|
75
|
+
* - Nested: deepest `>>` in hierarchy takes precedence
|
|
70
76
|
* - Regular keys: nested rules or boolean/string for child segments
|
|
71
77
|
*
|
|
72
78
|
* @example
|
|
@@ -79,6 +85,25 @@ export interface PathBasedConfigGeneratorOptions {
|
|
|
79
85
|
* admin: {
|
|
80
86
|
* '>': 'management', // rename "admin" to "management"
|
|
81
87
|
* users: true // keep "users" as is (does nothing)
|
|
88
|
+
* },
|
|
89
|
+
* layout: {
|
|
90
|
+
* '>>': 'dashboard' // redirect: everything below layout jumps to "dashboard" namespace
|
|
91
|
+
* },
|
|
92
|
+
* components: {
|
|
93
|
+
* '>>': { // redirect: jump to "ui" namespace with "components." path prefix
|
|
94
|
+
* namespace: 'ui',
|
|
95
|
+
* pathPrefix: 'components'
|
|
96
|
+
* }
|
|
97
|
+
* },
|
|
98
|
+
* features: {
|
|
99
|
+
* '>>': { // redirect: use current segment as namespace with "feature." prefix
|
|
100
|
+
* pathPrefix: 'feature.'
|
|
101
|
+
* }
|
|
102
|
+
* },
|
|
103
|
+
* auth: {
|
|
104
|
+
* '>>': '', // redirect: use current segment as namespace
|
|
105
|
+
* '>>': null, // same as empty string
|
|
106
|
+
* '>>': undefined // same as empty string
|
|
82
107
|
* }
|
|
83
108
|
* }
|
|
84
109
|
* }
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LangTagCLIConfigGenerationEvent } from '../../config.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the prependNamespaceToPath algorithm.
|
|
4
|
+
*/
|
|
5
|
+
export interface PrependNamespaceToPathOptions {
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Algorithm that prepends the namespace to the path in translation tag configurations.
|
|
9
|
+
*
|
|
10
|
+
* This is useful when you want to flatten the namespace structure by moving the namespace
|
|
11
|
+
* into the path, effectively removing the namespace separation.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Before: { namespace: 'common', path: 'hello.world' }
|
|
16
|
+
* // After: { path: 'common.hello.world' }
|
|
17
|
+
*
|
|
18
|
+
* // Before: { namespace: 'common' }
|
|
19
|
+
* // After: { path: 'common' }
|
|
20
|
+
*
|
|
21
|
+
* // Before: {}
|
|
22
|
+
* // After: { path: 'common' }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @param options Configuration options for the algorithm
|
|
26
|
+
* @returns A function compatible with LangTagCLIConfigGenerationEvent
|
|
27
|
+
*/
|
|
28
|
+
export declare function prependNamespaceToPath(options?: PrependNamespaceToPathOptions): (event: LangTagCLIConfigGenerationEvent) => Promise<void>;
|
package/algorithms/index.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const namespaceCollector = require("../namespace-collector-DRnZvkDR.cjs");
|
|
3
4
|
const path = require("pathe");
|
|
5
|
+
const process = require("node:process");
|
|
4
6
|
const caseLib = require("case");
|
|
5
7
|
function _interopNamespaceDefault(e) {
|
|
6
8
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -19,7 +21,74 @@ function _interopNamespaceDefault(e) {
|
|
|
19
21
|
return Object.freeze(n);
|
|
20
22
|
}
|
|
21
23
|
const caseLib__namespace = /* @__PURE__ */ _interopNamespaceDefault(caseLib);
|
|
22
|
-
|
|
24
|
+
class DictionaryCollector extends namespaceCollector.TranslationsCollector {
|
|
25
|
+
constructor(options = {
|
|
26
|
+
appendNamespaceToPath: false
|
|
27
|
+
}) {
|
|
28
|
+
super();
|
|
29
|
+
this.options = options;
|
|
30
|
+
}
|
|
31
|
+
clean;
|
|
32
|
+
aggregateCollection(namespace) {
|
|
33
|
+
return this.config.baseLanguageCode;
|
|
34
|
+
}
|
|
35
|
+
transformTag(tag) {
|
|
36
|
+
const originalPath = tag.parameterConfig.path;
|
|
37
|
+
let path2 = originalPath;
|
|
38
|
+
if (this.options.appendNamespaceToPath) {
|
|
39
|
+
path2 = tag.parameterConfig.namespace;
|
|
40
|
+
if (originalPath) {
|
|
41
|
+
path2 += ".";
|
|
42
|
+
path2 += originalPath;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
...tag,
|
|
46
|
+
parameterConfig: {
|
|
47
|
+
...tag.parameterConfig,
|
|
48
|
+
namespace: void 0,
|
|
49
|
+
path: path2
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return tag;
|
|
54
|
+
}
|
|
55
|
+
async preWrite(clean) {
|
|
56
|
+
this.clean = clean;
|
|
57
|
+
const baseDictionaryFile = path.join(this.config.localesDirectory, `${this.config.baseLanguageCode}.json`);
|
|
58
|
+
if (clean) {
|
|
59
|
+
this.logger.info("Removing {file}", { file: baseDictionaryFile });
|
|
60
|
+
await namespaceCollector.$LT_RemoveFile(baseDictionaryFile);
|
|
61
|
+
}
|
|
62
|
+
await namespaceCollector.$LT_EnsureDirectoryExists(this.config.localesDirectory);
|
|
63
|
+
}
|
|
64
|
+
async resolveCollectionFilePath(baseLanguageCode) {
|
|
65
|
+
return path.resolve(
|
|
66
|
+
process.cwd(),
|
|
67
|
+
this.config.localesDirectory,
|
|
68
|
+
baseLanguageCode + ".json"
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
async onMissingCollection(baseLanguageCode) {
|
|
72
|
+
if (!this.clean) {
|
|
73
|
+
this.logger.warn(`Original dictionary file "{namespace}.json" not found. A new one will be created.`, { namespace: baseLanguageCode });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async postWrite(changedCollections) {
|
|
77
|
+
if (!changedCollections?.length) {
|
|
78
|
+
this.logger.info("No changes were made based on the current configuration and files");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (changedCollections.length > 1) {
|
|
82
|
+
throw new Error("Should not write more than 1 collection! Only 1 base language dictionary expected!");
|
|
83
|
+
}
|
|
84
|
+
const dict = path.resolve(
|
|
85
|
+
this.config.localesDirectory,
|
|
86
|
+
this.config.baseLanguageCode + ".json"
|
|
87
|
+
);
|
|
88
|
+
this.logger.success("Updated dictionary {dict}", { dict });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const TRIGGER_NAME$2 = "path-based-config-generator";
|
|
23
92
|
function pathBasedConfigGenerator(options = {}) {
|
|
24
93
|
const {
|
|
25
94
|
includeFileName = false,
|
|
@@ -80,6 +149,8 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
80
149
|
namespace = pathSegments[0];
|
|
81
150
|
if (pathSegments.length > 1) {
|
|
82
151
|
path$1 = pathSegments.slice(1).join(".");
|
|
152
|
+
} else {
|
|
153
|
+
path$1 = "";
|
|
83
154
|
}
|
|
84
155
|
} else {
|
|
85
156
|
namespace = actualFallbackNamespace;
|
|
@@ -107,7 +178,7 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
107
178
|
(key) => key !== "namespace" && key !== "path"
|
|
108
179
|
);
|
|
109
180
|
if (!hasOtherProperties) {
|
|
110
|
-
event.save(null, TRIGGER_NAME$
|
|
181
|
+
event.save(null, TRIGGER_NAME$2);
|
|
111
182
|
return;
|
|
112
183
|
} else {
|
|
113
184
|
delete newConfig.namespace;
|
|
@@ -125,7 +196,7 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
125
196
|
}
|
|
126
197
|
}
|
|
127
198
|
if (Object.keys(newConfig).length > 0) {
|
|
128
|
-
event.save(newConfig, TRIGGER_NAME$
|
|
199
|
+
event.save(newConfig, TRIGGER_NAME$2);
|
|
129
200
|
}
|
|
130
201
|
};
|
|
131
202
|
}
|
|
@@ -163,11 +234,69 @@ function applyStructuredIgnore(segments, structure) {
|
|
|
163
234
|
}
|
|
164
235
|
return result;
|
|
165
236
|
}
|
|
237
|
+
function addPathPrefixAndSegments(result, pathPrefix, remainingSegments) {
|
|
238
|
+
if (pathPrefix && remainingSegments.length > 0) {
|
|
239
|
+
const cleanPrefix = pathPrefix.endsWith(".") ? pathPrefix.slice(0, -1) : pathPrefix;
|
|
240
|
+
result.push(cleanPrefix, ...remainingSegments);
|
|
241
|
+
} else if (pathPrefix && remainingSegments.length === 0) {
|
|
242
|
+
const cleanPrefix = pathPrefix.endsWith(".") ? pathPrefix.slice(0, -1) : pathPrefix;
|
|
243
|
+
result.push(cleanPrefix);
|
|
244
|
+
} else if (remainingSegments.length > 0) {
|
|
245
|
+
result.push(...remainingSegments);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function processNamespaceRedirect(redirectRule, remainingSegments, options) {
|
|
249
|
+
const result = [];
|
|
250
|
+
if (redirectRule === null || redirectRule === void 0) {
|
|
251
|
+
if (options?.currentSegment !== void 0) {
|
|
252
|
+
if (!options.ignoreSelf) {
|
|
253
|
+
result.push(options.renameTo || options.currentSegment);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
result.push(...remainingSegments);
|
|
257
|
+
} else if (typeof redirectRule === "string") {
|
|
258
|
+
if (redirectRule === "") {
|
|
259
|
+
if (options?.currentSegment !== void 0) {
|
|
260
|
+
if (!options.ignoreSelf) {
|
|
261
|
+
result.push(options.renameTo || options.currentSegment);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
result.push(...remainingSegments);
|
|
265
|
+
} else {
|
|
266
|
+
result.push(redirectRule);
|
|
267
|
+
result.push(...remainingSegments);
|
|
268
|
+
}
|
|
269
|
+
} else if (typeof redirectRule === "object" && redirectRule !== null) {
|
|
270
|
+
const namespace = redirectRule.namespace;
|
|
271
|
+
const pathPrefix = redirectRule.pathPrefix || "";
|
|
272
|
+
if (namespace === void 0 || namespace === null || namespace === "") {
|
|
273
|
+
if (options?.currentSegment !== void 0) {
|
|
274
|
+
if (!options.ignoreSelf) {
|
|
275
|
+
result.push(options.renameTo || options.currentSegment);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
addPathPrefixAndSegments(result, pathPrefix, remainingSegments);
|
|
279
|
+
} else {
|
|
280
|
+
result.push(namespace);
|
|
281
|
+
addPathPrefixAndSegments(result, pathPrefix, remainingSegments);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
166
286
|
function applyPathRules(segments, structure) {
|
|
167
287
|
const result = [];
|
|
168
288
|
let currentStructure = structure;
|
|
289
|
+
let deepestRedirect = null;
|
|
169
290
|
for (let i = 0; i < segments.length; i++) {
|
|
170
291
|
const segment = segments[i];
|
|
292
|
+
if (">>" in currentStructure && (!deepestRedirect || !deepestRedirect.context)) {
|
|
293
|
+
const redirectRule = currentStructure[">>"];
|
|
294
|
+
const remainingSegments = segments.slice(i);
|
|
295
|
+
deepestRedirect = {
|
|
296
|
+
rule: redirectRule,
|
|
297
|
+
remainingSegments
|
|
298
|
+
};
|
|
299
|
+
}
|
|
171
300
|
if (segment in currentStructure) {
|
|
172
301
|
const rule = currentStructure[segment];
|
|
173
302
|
if (rule === true) {
|
|
@@ -190,6 +319,22 @@ function applyPathRules(segments, structure) {
|
|
|
190
319
|
} else if (typeof rule === "object" && rule !== null) {
|
|
191
320
|
const ignoreSelf = rule["_"] === false;
|
|
192
321
|
const renameTo = rule[">"];
|
|
322
|
+
const redirectRule = rule[">>"];
|
|
323
|
+
if (">>" in rule) {
|
|
324
|
+
const remainingSegments = segments.slice(i + 1);
|
|
325
|
+
const ruleWithoutRedirect = { ...rule };
|
|
326
|
+
delete ruleWithoutRedirect[">>"];
|
|
327
|
+
const processedRemaining = applyPathRules(remainingSegments, ruleWithoutRedirect);
|
|
328
|
+
deepestRedirect = {
|
|
329
|
+
rule: redirectRule,
|
|
330
|
+
remainingSegments: processedRemaining,
|
|
331
|
+
context: {
|
|
332
|
+
currentSegment: segment,
|
|
333
|
+
renameTo,
|
|
334
|
+
ignoreSelf
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
193
338
|
if (!ignoreSelf) {
|
|
194
339
|
if (typeof renameTo === "string") {
|
|
195
340
|
result.push(renameTo);
|
|
@@ -204,6 +349,13 @@ function applyPathRules(segments, structure) {
|
|
|
204
349
|
result.push(segment);
|
|
205
350
|
currentStructure = structure;
|
|
206
351
|
}
|
|
352
|
+
if (deepestRedirect) {
|
|
353
|
+
return processNamespaceRedirect(
|
|
354
|
+
deepestRedirect.rule,
|
|
355
|
+
deepestRedirect.remainingSegments,
|
|
356
|
+
deepestRedirect.context
|
|
357
|
+
);
|
|
358
|
+
}
|
|
207
359
|
return result;
|
|
208
360
|
}
|
|
209
361
|
function applyCaseTransform(str, caseType) {
|
|
@@ -230,7 +382,7 @@ function extractRootDirectoriesFromIncludes(includes) {
|
|
|
230
382
|
}
|
|
231
383
|
return Array.from(directories);
|
|
232
384
|
}
|
|
233
|
-
const TRIGGER_NAME = "config-keeper";
|
|
385
|
+
const TRIGGER_NAME$1 = "config-keeper";
|
|
234
386
|
function configKeeper(options = {}) {
|
|
235
387
|
const propertyName = options.propertyName ?? "keep";
|
|
236
388
|
const keepPropertyAtEnd = options.keepPropertyAtEnd ?? true;
|
|
@@ -287,8 +439,33 @@ function configKeeper(options = {}) {
|
|
|
287
439
|
delete finalConfig[propertyName];
|
|
288
440
|
}
|
|
289
441
|
finalConfig[propertyName] = keepMode;
|
|
290
|
-
event.save(finalConfig, TRIGGER_NAME);
|
|
442
|
+
event.save(finalConfig, TRIGGER_NAME$1);
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
const TRIGGER_NAME = "prepend-namespace-to-path";
|
|
446
|
+
function prependNamespaceToPath(options = {}) {
|
|
447
|
+
return async (event) => {
|
|
448
|
+
const currentConfig = event.savedConfig;
|
|
449
|
+
const { namespace, path: path2 } = currentConfig || {};
|
|
450
|
+
const actualNamespace = namespace || event.langTagConfig.collect?.defaultNamespace;
|
|
451
|
+
if (!actualNamespace) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
let newPath;
|
|
455
|
+
if (path2) {
|
|
456
|
+
newPath = `${actualNamespace}.${path2}`;
|
|
457
|
+
} else {
|
|
458
|
+
newPath = actualNamespace;
|
|
459
|
+
}
|
|
460
|
+
event.save({
|
|
461
|
+
...currentConfig || {},
|
|
462
|
+
path: newPath,
|
|
463
|
+
namespace: void 0
|
|
464
|
+
}, TRIGGER_NAME);
|
|
291
465
|
};
|
|
292
466
|
}
|
|
467
|
+
exports.NamespaceCollector = namespaceCollector.NamespaceCollector;
|
|
468
|
+
exports.DictionaryCollector = DictionaryCollector;
|
|
293
469
|
exports.configKeeper = configKeeper;
|
|
294
470
|
exports.pathBasedConfigGenerator = pathBasedConfigGenerator;
|
|
471
|
+
exports.prependNamespaceToPath = prependNamespaceToPath;
|
package/algorithms/index.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Algorithm modules for lang-tag-cli.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* This module provides access to all available algorithms organized by category:
|
|
5
|
+
* - Collectors: Define how translation tags are organized into output files
|
|
6
|
+
* - Config Generation: Customize tag configuration generation
|
|
7
|
+
* - Import: Handle importing translation libraries (future)
|
|
6
8
|
*/
|
|
9
|
+
export * from './collector/index.ts';
|
|
7
10
|
export * from './config-generation/index.ts';
|