addonova 1.0.3 → 1.0.4

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.
@@ -1,299 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import * as readline from 'node:readline/promises';
3
- import { stdin as input, stdout as output } from 'node:process';
4
- import {readFile, writeFile, httpsRequest, timeout} from '../build/utils.js';
5
-
6
-
7
- const LOCALES_ROOT = 'src/_locales';
8
-
9
- function toMessageId(message) {
10
- if (typeof message !== 'string') return '';
11
-
12
- return message
13
- .trim()
14
- .split(/\s+/) // split by any whitespace
15
- .slice(0, 3) // only first 3 words
16
- .map(word =>
17
- word
18
- .replace(/[^\w]/g, '') // remove special characters
19
- .toLowerCase()
20
- )
21
- .filter(Boolean) // remove empty results
22
- .join('_');
23
- }
24
-
25
- async function getSupportedLocales() {
26
- const fileList = await fs.readdir(LOCALES_ROOT);
27
-
28
- const locales = [];
29
-
30
- for (const file of fileList) {
31
- if (file.endsWith('.i18n')) {
32
- const locale = file.substring(0, file.lastIndexOf('.i18n'));
33
- locales.push(locale);
34
- }
35
- }
36
-
37
- return locales;
38
- }
39
-
40
- function stringifyLocale(messages) {
41
- const lines = [];
42
- messages.forEach((message, id) => {
43
- lines.push(`@${id}`);
44
- const hasDoubleNewLines = /\n\n/.test(message);
45
- message.split('\n')
46
- .filter((line) => line.trim())
47
- .forEach((line, index, filtered) => {
48
- lines.push(line);
49
- if (hasDoubleNewLines && index < filtered.length - 1) {
50
- lines.push('');
51
- }
52
- });
53
- lines.push('');
54
- });
55
- return lines.join('\n');
56
- }
57
-
58
- function parseLocale(content) {
59
- const messages = new Map();
60
- const lines = content.split('\n');
61
- let id = '';
62
- for (let i = 0; i < lines.length; i++) {
63
- const line = lines[i];
64
- if (line.startsWith('@')) {
65
- id = line.substring(1);
66
- } else if (line.startsWith('#')) {
67
- // Ignore
68
- } else if (messages.has(id)) {
69
- const message = messages.get(id);
70
- messages.set(id, `${message}\n${line}`);
71
- } else {
72
- messages.set(id, line);
73
- }
74
- }
75
- messages.forEach((value, id) => {
76
- messages.set(id, value.trim());
77
- });
78
- return messages;
79
- }
80
-
81
- async function translate(text, lang) {
82
- const url = new URL('https://translate.googleapis.com/translate_a/single');
83
- url.search = (new URLSearchParams({
84
- client: 'gtx',
85
- sl: 'en-US',
86
- tl: lang,
87
- dt: 't',
88
- dj: '1',
89
- q: text,
90
- })).toString();
91
- const response = await httpsRequest(url.toString());
92
- const translation = JSON.parse(response.text());
93
- return translation.sentences.map((s) => s.trans).join('\n').replaceAll(/\n+/g, '\n');
94
- }
95
-
96
- async function deleteMessage(messageId, targetLocale = null) {
97
- const supportedLocales = await getSupportedLocales();
98
-
99
- if (!messageId || !messageId.trim()) {
100
- console.log('⚠ Message key cannot be empty.');
101
- return;
102
- }
103
-
104
- const id = messageId.trim();
105
- let foundAnywhere = false;
106
-
107
- // 🎯 Decide scope
108
- const localesToProcess = targetLocale
109
- ? [targetLocale]
110
- : supportedLocales;
111
-
112
- for (const locale of localesToProcess) {
113
- const locFile = `${LOCALES_ROOT}/${locale}.i18n`;
114
-
115
- try {
116
- const locContent = await readFile(locFile);
117
- const locMessages = parseLocale(locContent);
118
-
119
- if (!locMessages.has(id)) {
120
- continue;
121
- }
122
-
123
- locMessages.delete(id);
124
-
125
- const output = stringifyLocale(locMessages);
126
- await writeFile(locFile, output);
127
-
128
- console.log(`✔ Removed from ${locale}.i18n`);
129
- foundAnywhere = true;
130
-
131
- } catch (err) {
132
- console.log(`⚠ Failed to process ${locale}: ${err.message}`);
133
- }
134
- }
135
-
136
- // 🧾 Final status
137
- if (!foundAnywhere) {
138
- console.log(
139
- targetLocale
140
- ? `⚠ Message key not found in ${targetLocale}.`
141
- : '⚠ Message key not found in any locale.'
142
- );
143
- } else {
144
- console.log('🗑 Deletion completed.');
145
- }
146
- }
147
-
148
-
149
- async function translateEnMessage(message, customId) {
150
- console.log(`Translating message: ${message}`);
151
-
152
- const supportedLocales = await getSupportedLocales();
153
- const messageId = customId && customId.trim()
154
- ? customId.trim()
155
- : toMessageId(message);
156
-
157
- // 1️⃣ Update English first
158
- const enFile = `${LOCALES_ROOT}/en.i18n`;
159
- const enContent = await readFile(enFile);
160
- const enMessages = parseLocale(enContent);
161
-
162
- if (!enMessages.has(messageId)) {
163
- enMessages.set(messageId, message);
164
- const output = stringifyLocale(enMessages);
165
- await writeFile(enFile, output);
166
- console.log(`en: ${message}`);
167
- } else {
168
- console.log('Message already exists in en.i18n');
169
- }
170
-
171
- // 2️⃣ Translate other locales
172
- for (const locale of supportedLocales) {
173
- if (locale === 'en') continue;
174
-
175
- await timeout(1000);
176
-
177
- const locFile = `${LOCALES_ROOT}/${locale}.i18n`;
178
- const locContent = await readFile(locFile);
179
- const locMessages = parseLocale(locContent);
180
-
181
- if (locMessages.has(messageId)) {
182
- console.log(`Already exists in: ${locFile}`);
183
- continue;
184
- }
185
-
186
- const translatedDefault = await translate(message, locale);
187
-
188
- console.log(`✅ Output: ${locale}: ${translatedDefault}`);
189
-
190
- locMessages.set(messageId, translatedDefault);
191
-
192
- const outputs = stringifyLocale(locMessages);
193
- await writeFile(locFile, outputs);
194
- }
195
- }
196
-
197
- async function main() {
198
- const rl = readline.createInterface({ input, output });
199
-
200
- try {
201
- while (true) {
202
- console.log('\n=== Message Manager ===');
203
- console.log('[1] Add new message');
204
- console.log('[2] Delete message');
205
- console.log('[0] Exit');
206
-
207
- const choice = (await rl.question('Select option: '))
208
- .trim()
209
- .toLowerCase();
210
-
211
- switch (choice) {
212
- case '1': {
213
- const newMessage = (await rl.question('Enter new message: '))
214
- .trim();
215
-
216
- if (!newMessage) {
217
- console.log('⚠ Message cannot be empty.');
218
- break;
219
- }
220
-
221
- const newMessageId = (await rl.question(
222
- 'Enter new message key (leave empty for auto-generation): '
223
- )).trim();
224
-
225
- await translateEnMessage(
226
- newMessage,
227
- newMessageId || undefined
228
- );
229
-
230
- console.log('✔ Message processed successfully.');
231
- break;
232
- }
233
-
234
- case '2': {
235
- const messageId = (await rl.question(
236
- 'Enter message key to delete: '
237
- )).trim();
238
-
239
- if (!messageId) {
240
- console.log('⚠ Message key cannot be empty.');
241
- break;
242
- }
243
-
244
- // 🌍 Ask scope
245
- const scope = (await rl.question(
246
- 'Delete from (a)ll locales or specific locale? (a/s): '
247
- )).trim().toLowerCase();
248
-
249
- let targetLocale = null;
250
-
251
- if (scope === 's') {
252
- targetLocale = (await rl.question(
253
- 'Enter locale (e.g., en, fa, ru): '
254
- )).trim();
255
-
256
- if (!targetLocale) {
257
- console.log('⚠ Locale cannot be empty.');
258
- break;
259
- }
260
- }
261
-
262
- // ✅ Confirmation
263
- const confirm = (await rl.question(
264
- targetLocale
265
- ? `Are you sure you want to delete "${messageId}" from "${targetLocale}"? (y/n): `
266
- : `Are you sure you want to delete "${messageId}" from ALL locales? (y/n): `
267
- )).trim().toLowerCase();
268
-
269
- if (confirm !== 'y') {
270
- console.log('Deletion cancelled.');
271
- break;
272
- }
273
-
274
- // 🔥 Delete logic
275
- if (targetLocale) {
276
- await deleteMessage(messageId, targetLocale);
277
- } else {
278
- await deleteMessage(messageId);
279
- }
280
-
281
- console.log('Deleted ✅');
282
- break;
283
- }
284
-
285
- case '0':
286
- case 'exit': {
287
- console.log('Exiting...');
288
- return;
289
- }
290
-
291
- default: {
292
- console.log('Invalid selection. Please try again.');
293
- }
294
- }
295
- }
296
- } finally {
297
- rl.close();
298
- }
299
- }main();