@red-hat-developer-hub/translations-cli 0.0.1

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.
@@ -0,0 +1,93 @@
1
+ 'use strict';
2
+
3
+ require('node:path');
4
+ var fs = require('fs-extra');
5
+ var translationUtils = require('../utils/translationUtils.cjs.js');
6
+
7
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
8
+
9
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
10
+
11
+ function extractPoString(line, prefixLength) {
12
+ return translationUtils.unescapePoString(
13
+ line.substring(prefixLength).replaceAll(/(^["']|["']$)/g, "")
14
+ );
15
+ }
16
+ function extractPoContinuation(line) {
17
+ return translationUtils.unescapePoString(line.replaceAll(/(^["']|["']$)/g, ""));
18
+ }
19
+ function processMsgIdLine(line, currentKey, currentValue, data) {
20
+ if (currentKey && currentValue) {
21
+ data[currentKey] = currentValue;
22
+ }
23
+ return {
24
+ key: extractPoString(line, 6),
25
+ value: "",
26
+ inMsgId: true,
27
+ inMsgStr: false
28
+ };
29
+ }
30
+ function processMsgStrLine(line) {
31
+ return {
32
+ value: extractPoString(line, 7),
33
+ inMsgId: false,
34
+ inMsgStr: true
35
+ };
36
+ }
37
+ function processContinuationLine(line, currentKey, currentValue, inMsgId, inMsgStr) {
38
+ const value = extractPoContinuation(line);
39
+ return {
40
+ key: inMsgId ? currentKey + value : currentKey,
41
+ value: inMsgStr ? currentValue + value : currentValue
42
+ };
43
+ }
44
+ async function loadPoFile(filePath) {
45
+ try {
46
+ const content = await fs__default.default.readFile(filePath, "utf-8");
47
+ const data = {};
48
+ const lines = content.split("\n");
49
+ let currentKey = "";
50
+ let currentValue = "";
51
+ let inMsgId = false;
52
+ let inMsgStr = false;
53
+ for (const line of lines) {
54
+ const trimmed = line.trim();
55
+ if (trimmed.startsWith("msgid ")) {
56
+ const result = processMsgIdLine(
57
+ trimmed,
58
+ currentKey,
59
+ currentValue,
60
+ data
61
+ );
62
+ currentKey = result.key;
63
+ currentValue = result.value;
64
+ inMsgId = result.inMsgId;
65
+ inMsgStr = result.inMsgStr;
66
+ } else if (trimmed.startsWith("msgstr ")) {
67
+ const result = processMsgStrLine(trimmed);
68
+ currentValue = result.value;
69
+ inMsgId = result.inMsgId;
70
+ inMsgStr = result.inMsgStr;
71
+ } else if (trimmed.startsWith('"') && (inMsgId || inMsgStr)) {
72
+ const result = processContinuationLine(
73
+ trimmed,
74
+ currentKey,
75
+ currentValue,
76
+ inMsgId,
77
+ inMsgStr
78
+ );
79
+ currentKey = result.key;
80
+ currentValue = result.value;
81
+ }
82
+ }
83
+ if (currentKey && currentValue) {
84
+ data[currentKey] = currentValue;
85
+ }
86
+ return data;
87
+ } catch (error) {
88
+ throw new Error(`Failed to load PO file ${filePath}: ${error}`);
89
+ }
90
+ }
91
+
92
+ exports.loadPoFile = loadPoFile;
93
+ //# sourceMappingURL=loadFile.cjs.js.map
@@ -0,0 +1,126 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs-extra');
4
+ var translationUtils = require('../utils/translationUtils.cjs.js');
5
+ var loadFile = require('./loadFile.cjs.js');
6
+
7
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
8
+
9
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
10
+
11
+ function isNestedStructure(data) {
12
+ if (typeof data !== "object" || data === null) return false;
13
+ const firstKey = Object.keys(data)[0];
14
+ if (!firstKey) return false;
15
+ const firstValue = data[firstKey];
16
+ return typeof firstValue === "object" && firstValue !== null && "en" in firstValue;
17
+ }
18
+ async function loadExistingFile(existingPath, format) {
19
+ try {
20
+ switch (format.toLowerCase()) {
21
+ case "json":
22
+ return await loadJsonFile(existingPath);
23
+ case "po":
24
+ return await loadFile.loadPoFile(existingPath);
25
+ default:
26
+ throw new Error(`Unsupported format: ${format}`);
27
+ }
28
+ } catch (error) {
29
+ console.warn(
30
+ `Warning: Could not load existing file ${existingPath}: ${error}`
31
+ );
32
+ return {};
33
+ }
34
+ }
35
+ function mergeNestedStructures(newKeys, existingData) {
36
+ if (!isNestedStructure(existingData)) {
37
+ return newKeys;
38
+ }
39
+ const mergedData = { ...existingData };
40
+ for (const [pluginName, pluginData] of Object.entries(newKeys)) {
41
+ if (mergedData[pluginName]) {
42
+ mergedData[pluginName] = {
43
+ en: { ...mergedData[pluginName].en, ...pluginData.en }
44
+ };
45
+ } else {
46
+ mergedData[pluginName] = pluginData;
47
+ }
48
+ }
49
+ return mergedData;
50
+ }
51
+ function mergeFlatStructures(newKeys, existingData) {
52
+ const existingFlat = isNestedStructure(existingData) ? {} : existingData;
53
+ return { ...existingFlat, ...newKeys };
54
+ }
55
+ async function saveMergedFlatData(mergedData, existingPath, format) {
56
+ switch (format.toLowerCase()) {
57
+ case "json":
58
+ await saveJsonFile(mergedData, existingPath);
59
+ break;
60
+ case "po":
61
+ await savePoFile(mergedData, existingPath);
62
+ break;
63
+ default:
64
+ throw new Error(`Unsupported format: ${format}`);
65
+ }
66
+ }
67
+ async function mergeTranslationFiles(newKeys, existingPath, format) {
68
+ if (!await fs__default.default.pathExists(existingPath)) {
69
+ throw new Error(`Existing file not found: ${existingPath}`);
70
+ }
71
+ const existingData = await loadExistingFile(existingPath, format);
72
+ if (isNestedStructure(newKeys)) {
73
+ const mergedData = mergeNestedStructures(newKeys, existingData);
74
+ await saveNestedJsonFile(mergedData, existingPath);
75
+ } else {
76
+ const mergedData = mergeFlatStructures(newKeys, existingData);
77
+ await saveMergedFlatData(mergedData, existingPath, format);
78
+ }
79
+ }
80
+ async function loadJsonFile(filePath) {
81
+ const data = await fs__default.default.readJson(filePath);
82
+ if (isNestedStructure(data)) {
83
+ return data;
84
+ }
85
+ if (data.translations && typeof data.translations === "object") {
86
+ return data.translations;
87
+ }
88
+ if (typeof data === "object" && data !== null) {
89
+ return data;
90
+ }
91
+ return {};
92
+ }
93
+ async function saveJsonFile(data, filePath) {
94
+ const output = {
95
+ metadata: {
96
+ generated: (/* @__PURE__ */ new Date()).toISOString(),
97
+ version: "1.0",
98
+ totalKeys: Object.keys(data).length
99
+ },
100
+ translations: data
101
+ };
102
+ await fs__default.default.writeJson(filePath, output, { spaces: 2 });
103
+ }
104
+ async function saveNestedJsonFile(data, filePath) {
105
+ await fs__default.default.writeJson(filePath, data, { spaces: 2 });
106
+ }
107
+ async function savePoFile(data, filePath) {
108
+ const headerLines = [
109
+ 'msgid ""',
110
+ 'msgstr ""',
111
+ String.raw`"Content-Type: text/plain; charset=UTF-8\n"`,
112
+ String.raw`"Generated: ${(/* @__PURE__ */ new Date()).toISOString()}\n"`,
113
+ String.raw`"Total-Keys: ${Object.keys(data).length}\n"`,
114
+ ""
115
+ ];
116
+ const translationLines = Object.entries(data).flatMap(([key, value]) => [
117
+ `msgid "${translationUtils.escapePoString(key)}"`,
118
+ `msgstr "${translationUtils.escapePoString(value)}"`,
119
+ ""
120
+ ]);
121
+ const lines = [...headerLines, ...translationLines];
122
+ await fs__default.default.writeFile(filePath, lines.join("\n"), "utf-8");
123
+ }
124
+
125
+ exports.mergeTranslationFiles = mergeTranslationFiles;
126
+ //# sourceMappingURL=mergeFiles.cjs.js.map
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+
3
+ var node_crypto = require('node:crypto');
4
+ var path = require('node:path');
5
+ var fs = require('fs-extra');
6
+
7
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
8
+
9
+ var path__default = /*#__PURE__*/_interopDefaultCompat(path);
10
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
11
+
12
+ function getCacheDir() {
13
+ return path__default.default.join(process.cwd(), ".i18n-cache");
14
+ }
15
+ function getCacheFilePath(projectId, tmsUrl) {
16
+ const cacheDir = getCacheDir();
17
+ const safeProjectId = projectId.replaceAll(/[^a-zA-Z0-9]/g, "_");
18
+ const urlHash = node_crypto.createHash("sha256").update(tmsUrl).digest("hex").substring(0, 8);
19
+ return path__default.default.join(cacheDir, `upload_${safeProjectId}_${urlHash}.json`);
20
+ }
21
+ async function calculateFileHash(filePath) {
22
+ const content = await fs__default.default.readFile(filePath, "utf-8");
23
+ const data = JSON.parse(content);
24
+ if (data.metadata) {
25
+ delete data.metadata.generated;
26
+ }
27
+ const normalizedContent = JSON.stringify(data, null, 2);
28
+ return node_crypto.createHash("sha256").update(normalizedContent).digest("hex");
29
+ }
30
+ async function getCachedUpload(filePath, projectId, tmsUrl) {
31
+ try {
32
+ const cacheFilePath = getCacheFilePath(projectId, tmsUrl);
33
+ if (!await fs__default.default.pathExists(cacheFilePath)) {
34
+ return null;
35
+ }
36
+ const cacheData = await fs__default.default.readJson(cacheFilePath);
37
+ const entry = cacheData;
38
+ if (entry.filePath !== filePath) {
39
+ return null;
40
+ }
41
+ return entry;
42
+ } catch {
43
+ return null;
44
+ }
45
+ }
46
+ async function hasFileChanged(filePath, projectId, tmsUrl) {
47
+ const cachedEntry = await getCachedUpload(filePath, projectId, tmsUrl);
48
+ if (!cachedEntry) {
49
+ return true;
50
+ }
51
+ if (!await fs__default.default.pathExists(filePath)) {
52
+ return true;
53
+ }
54
+ const currentHash = await calculateFileHash(filePath);
55
+ return currentHash !== cachedEntry.fileHash;
56
+ }
57
+ async function saveUploadCache(filePath, projectId, tmsUrl, keyCount, uploadFileName) {
58
+ try {
59
+ const cacheDir = getCacheDir();
60
+ await fs__default.default.ensureDir(cacheDir);
61
+ const fileHash = await calculateFileHash(filePath);
62
+ const cacheEntry = {
63
+ filePath,
64
+ fileHash,
65
+ projectId,
66
+ tmsUrl,
67
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
68
+ keyCount,
69
+ uploadFileName
70
+ // Store the upload filename to track what was actually uploaded
71
+ };
72
+ const cacheFilePath = getCacheFilePath(projectId, tmsUrl);
73
+ await fs__default.default.writeJson(cacheFilePath, cacheEntry, { spaces: 2 });
74
+ } catch (error) {
75
+ console.warn(`Warning: Failed to save upload cache: ${error}`);
76
+ }
77
+ }
78
+
79
+ exports.calculateFileHash = calculateFileHash;
80
+ exports.getCachedUpload = getCachedUpload;
81
+ exports.hasFileChanged = hasFileChanged;
82
+ exports.saveUploadCache = saveUploadCache;
83
+ //# sourceMappingURL=uploadCache.cjs.js.map
@@ -0,0 +1,189 @@
1
+ 'use strict';
2
+
3
+ var path = require('node:path');
4
+ var fs = require('fs-extra');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
+
8
+ var path__default = /*#__PURE__*/_interopDefaultCompat(path);
9
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
10
+
11
+ async function validateTranslationFile(filePath) {
12
+ try {
13
+ const ext = path__default.default.extname(filePath).toLowerCase();
14
+ switch (ext) {
15
+ case ".json":
16
+ return await validateJsonFile(filePath);
17
+ case ".po":
18
+ return await validatePoFile(filePath);
19
+ default:
20
+ throw new Error(`Unsupported file format: ${ext}`);
21
+ }
22
+ } catch (error) {
23
+ console.error(`Validation error for ${filePath}:`, error);
24
+ return false;
25
+ }
26
+ }
27
+ function validateFileContent(content) {
28
+ if (!isValidUTF8(content)) {
29
+ throw new Error("File contains invalid UTF-8 sequences");
30
+ }
31
+ if (content.includes("\0")) {
32
+ throw new Error(
33
+ String.raw`File contains null bytes (\x00) which are not valid in JSON`
34
+ );
35
+ }
36
+ }
37
+ function parseJsonContent(content) {
38
+ let data;
39
+ try {
40
+ data = JSON.parse(content);
41
+ } catch (parseError) {
42
+ throw new Error(
43
+ `JSON parse error: ${parseError instanceof Error ? parseError.message : "Unknown error"}`
44
+ );
45
+ }
46
+ if (typeof data !== "object" || data === null) {
47
+ throw new TypeError("Root element must be a JSON object");
48
+ }
49
+ return data;
50
+ }
51
+ function isNestedStructure(obj) {
52
+ if (typeof obj !== "object" || obj === null) return false;
53
+ const firstKey = Object.keys(obj)[0];
54
+ if (!firstKey) return false;
55
+ const firstValue = obj[firstKey];
56
+ return typeof firstValue === "object" && firstValue !== null && "en" in firstValue;
57
+ }
58
+ function validateTranslationValue(value, keyPath) {
59
+ if (typeof value !== "string") {
60
+ throw new TypeError(
61
+ `Translation value for "${keyPath}" must be a string, got ${typeof value}`
62
+ );
63
+ }
64
+ if (value.includes("\0")) {
65
+ throw new Error(`Translation value for "${keyPath}" contains null byte`);
66
+ }
67
+ const curlyApostrophe = /[\u2018\u2019]/;
68
+ const curlyQuotes = /[\u201C\u201D]/;
69
+ if (curlyApostrophe.test(value) || curlyQuotes.test(value)) {
70
+ console.warn(
71
+ `Warning: Translation value for "${keyPath}" contains Unicode curly quotes/apostrophes.`
72
+ );
73
+ console.warn(` Consider normalizing to standard quotes: ' \u2192 ' and " \u2192 "`);
74
+ }
75
+ }
76
+ function validateNestedStructure(data) {
77
+ let totalKeys = 0;
78
+ for (const [pluginName, pluginData] of Object.entries(data)) {
79
+ if (typeof pluginData !== "object" || pluginData === null) {
80
+ throw new TypeError(`Plugin "${pluginName}" must be an object`);
81
+ }
82
+ if (!("en" in pluginData)) {
83
+ throw new Error(`Plugin "${pluginName}" must have an "en" property`);
84
+ }
85
+ const enData = pluginData.en;
86
+ if (typeof enData !== "object" || enData === null) {
87
+ throw new TypeError(`Plugin "${pluginName}".en must be an object`);
88
+ }
89
+ for (const [key, value] of Object.entries(enData)) {
90
+ validateTranslationValue(value, `${pluginName}.en.${key}`);
91
+ totalKeys++;
92
+ }
93
+ }
94
+ return totalKeys;
95
+ }
96
+ function validateFlatStructure(data) {
97
+ const translations = data.translations || data;
98
+ if (typeof translations !== "object" || translations === null) {
99
+ throw new TypeError("Translations must be an object");
100
+ }
101
+ let totalKeys = 0;
102
+ for (const [key, value] of Object.entries(translations)) {
103
+ validateTranslationValue(value, key);
104
+ totalKeys++;
105
+ }
106
+ return totalKeys;
107
+ }
108
+ function countNestedKeys(data) {
109
+ let count = 0;
110
+ for (const pluginData of Object.values(data)) {
111
+ if (pluginData.en && typeof pluginData.en === "object") {
112
+ count += Object.keys(pluginData.en).length;
113
+ }
114
+ }
115
+ return count;
116
+ }
117
+ function countFlatKeys(data) {
118
+ const translations = data.translations || data;
119
+ return Object.keys(translations).length;
120
+ }
121
+ function validateRoundTrip(data, originalKeyCount) {
122
+ const reStringified = JSON.stringify(data, null, 2);
123
+ const reparsed = JSON.parse(reStringified);
124
+ const reparsedKeys = isNestedStructure(reparsed) ? countNestedKeys(reparsed) : countFlatKeys(reparsed);
125
+ if (originalKeyCount !== reparsedKeys) {
126
+ throw new Error(
127
+ `Key count mismatch: original has ${originalKeyCount} keys, reparsed has ${reparsedKeys} keys`
128
+ );
129
+ }
130
+ }
131
+ async function validateJsonFile(filePath) {
132
+ try {
133
+ const content = await fs__default.default.readFile(filePath, "utf-8");
134
+ validateFileContent(content);
135
+ const data = parseJsonContent(content);
136
+ const totalKeys = isNestedStructure(data) ? validateNestedStructure(data) : validateFlatStructure(data);
137
+ validateRoundTrip(data, totalKeys);
138
+ return true;
139
+ } catch (error) {
140
+ console.error(
141
+ `JSON validation error for ${filePath}:`,
142
+ error instanceof Error ? error.message : error
143
+ );
144
+ return false;
145
+ }
146
+ }
147
+ function isValidUTF8(str) {
148
+ try {
149
+ const encoded = Buffer.from(str, "utf-8");
150
+ const decoded = encoded.toString("utf-8");
151
+ return decoded === str;
152
+ } catch {
153
+ return false;
154
+ }
155
+ }
156
+ async function validatePoFile(filePath) {
157
+ try {
158
+ const content = await fs__default.default.readFile(filePath, "utf-8");
159
+ const lines = content.split("\n");
160
+ let hasMsgId = false;
161
+ let hasMsgStr = false;
162
+ let inEntry = false;
163
+ for (const line of lines) {
164
+ const trimmed = line.trim();
165
+ if (trimmed.startsWith("msgid ")) {
166
+ hasMsgId = true;
167
+ inEntry = true;
168
+ } else if (trimmed.startsWith("msgstr ")) {
169
+ hasMsgStr = true;
170
+ } else if (trimmed === "" && inEntry) {
171
+ if (!hasMsgId || !hasMsgStr) {
172
+ return false;
173
+ }
174
+ hasMsgId = false;
175
+ hasMsgStr = false;
176
+ inEntry = false;
177
+ }
178
+ }
179
+ if (inEntry && (!hasMsgId || !hasMsgStr)) {
180
+ return false;
181
+ }
182
+ return true;
183
+ } catch {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ exports.validateTranslationFile = validateTranslationFile;
189
+ //# sourceMappingURL=validateFile.cjs.js.map
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ var path = require('node:path');
4
+ var fs = require('fs-extra');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
+
8
+ var path__default = /*#__PURE__*/_interopDefaultCompat(path);
9
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
10
+
11
+ function findProjectRoot() {
12
+ let currentDir = process.cwd();
13
+ const root = path__default.default.parse(currentDir).root;
14
+ let gitRoot = null;
15
+ while (currentDir !== root) {
16
+ const gitDir = path__default.default.join(currentDir, ".git");
17
+ if (fs__default.default.existsSync(gitDir)) {
18
+ gitRoot = currentDir;
19
+ break;
20
+ }
21
+ const parentDir = path__default.default.dirname(currentDir);
22
+ if (parentDir === currentDir) {
23
+ break;
24
+ }
25
+ currentDir = parentDir;
26
+ }
27
+ if (gitRoot) {
28
+ const gitRootConfig = path__default.default.join(gitRoot, ".i18n.config.json");
29
+ if (fs__default.default.existsSync(gitRootConfig)) {
30
+ return gitRoot;
31
+ }
32
+ }
33
+ currentDir = process.cwd();
34
+ while (currentDir !== root) {
35
+ const configFile = path__default.default.join(currentDir, ".i18n.config.json");
36
+ if (fs__default.default.existsSync(configFile)) {
37
+ return currentDir;
38
+ }
39
+ const parentDir = path__default.default.dirname(currentDir);
40
+ if (parentDir === currentDir) {
41
+ break;
42
+ }
43
+ currentDir = parentDir;
44
+ }
45
+ return gitRoot || process.cwd();
46
+ }
47
+ const paths = {
48
+ targetDir: findProjectRoot()};
49
+
50
+ exports.paths = paths;
51
+ //# sourceMappingURL=paths.cjs.js.map
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ var child_process = require('child_process');
4
+ var os = require('node:os');
5
+
6
+ function safeExecSync(command, args = [], options = {}) {
7
+ const defaultOptions = {
8
+ encoding: "utf-8",
9
+ stdio: "pipe",
10
+ ...options
11
+ };
12
+ const result = child_process.spawnSync(command, args, defaultOptions);
13
+ return {
14
+ stdout: (result.stdout?.toString() || "").trim(),
15
+ stderr: (result.stderr?.toString() || "").trim(),
16
+ status: result.status,
17
+ error: result.error
18
+ };
19
+ }
20
+ function commandExists(command) {
21
+ const isWindows = os.platform() === "win32";
22
+ const checkCommand = isWindows ? "where" : "which";
23
+ const result = safeExecSync(checkCommand, [command], { stdio: "pipe" });
24
+ return result.status === 0 && result.stdout.length > 0;
25
+ }
26
+ function safeExecSyncOrThrow(command, args = [], options = {}) {
27
+ const result = safeExecSync(command, args, options);
28
+ if (result.error) {
29
+ throw result.error;
30
+ }
31
+ if (result.status !== 0) {
32
+ const errorMessage = result.stderr || `Command failed with status ${result.status}`;
33
+ throw new Error(errorMessage);
34
+ }
35
+ return result.stdout;
36
+ }
37
+
38
+ exports.commandExists = commandExists;
39
+ exports.safeExecSync = safeExecSync;
40
+ exports.safeExecSyncOrThrow = safeExecSyncOrThrow;
41
+ //# sourceMappingURL=exec.cjs.js.map
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ function countTranslationKeys(data) {
4
+ if (!data || typeof data !== "object") {
5
+ return 0;
6
+ }
7
+ const isNested = Object.values(data).some(
8
+ (val) => typeof val === "object" && val !== null && "en" in val
9
+ );
10
+ if (isNested) {
11
+ let keyCount = 0;
12
+ for (const pluginData of Object.values(data)) {
13
+ const enData = pluginData?.en;
14
+ if (enData && typeof enData === "object") {
15
+ keyCount += Object.keys(enData).length;
16
+ }
17
+ }
18
+ return keyCount;
19
+ }
20
+ const translations = data.translations || data;
21
+ return Object.keys(translations).length;
22
+ }
23
+ function escapePoString(str) {
24
+ return str.replaceAll(/\\/g, "\\\\").replaceAll(/"/g, '\\"').replaceAll(/\n/g, "\\n").replaceAll(/\r/g, "\\r").replaceAll(/\t/g, "\\t");
25
+ }
26
+ function unescapePoString(str) {
27
+ return str.replaceAll(/\\n/g, "\n").replaceAll(/\\r/g, "\r").replaceAll(/\\t/g, " ").replaceAll(/\\"/g, '"').replaceAll(/\\\\/g, "\\");
28
+ }
29
+
30
+ exports.countTranslationKeys = countTranslationKeys;
31
+ exports.escapePoString = escapePoString;
32
+ exports.unescapePoString = unescapePoString;
33
+ //# sourceMappingURL=translationUtils.cjs.js.map
@@ -0,0 +1,38 @@
1
+ 'use strict';
2
+
3
+ var path = require('node:path');
4
+ var fs = require('fs-extra');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
+
8
+ var path__default = /*#__PURE__*/_interopDefaultCompat(path);
9
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
10
+
11
+ function findVersion() {
12
+ try {
13
+ const possiblePaths = [
14
+ // From package root (most common case)
15
+ path__default.default.resolve(process.cwd(), "package.json"),
16
+ // From workspace root if running from translations workspace
17
+ path__default.default.resolve(process.cwd(), "..", "..", "package.json"),
18
+ // From repo root if running from monorepo root
19
+ path__default.default.resolve(
20
+ process.cwd(),
21
+ "workspaces/translations/packages/cli/package.json"
22
+ )
23
+ ];
24
+ for (const pkgPath of possiblePaths) {
25
+ if (fs__default.default.existsSync(pkgPath)) {
26
+ const pkgContent = fs__default.default.readFileSync(pkgPath, "utf8");
27
+ return JSON.parse(pkgContent).version;
28
+ }
29
+ }
30
+ return "0.1.0";
31
+ } catch {
32
+ return "0.1.0";
33
+ }
34
+ }
35
+ const version = findVersion();
36
+
37
+ exports.version = version;
38
+ //# sourceMappingURL=version.cjs.js.map