natureco-cli 5.57.0 → 5.58.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "5.57.0",
3
+ "version": "5.58.0",
4
4
  "description": "OpenClaw'dan daha güvenli, daha hızlı, daha ucuz AI agent CLI. Multi-agent, self-evolving skills, audit log, maliyet optimizasyonu ve NatureCo platform-native.",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -1,4 +1,6 @@
1
- const chalk = require('chalk');
1
+ const chalk = require('chalk');
2
+ const { getLang: _gl } = require('../utils/i18n');
3
+ const L = (tr, en) => (_gl() === 'en' ? en : tr);
2
4
  const tui = require('../utils/tui');
3
5
  const F = require('../utils/format');
4
6
  const fs = require('fs');
@@ -40,8 +42,8 @@ function saveCrons(crons) {
40
42
 
41
43
  async function cron(action, options) {
42
44
  if (!action || !['add', 'list', 'remove', 'get', 'edit', 'enable', 'disable', 'runs', 'run'].includes(action)) {
43
- console.log(chalk.red('\n❌ Geçersiz aksiyon\n'));
44
- console.log(chalk.gray('Kullanım:'));
45
+ console.log(chalk.red(L('\n❌ Geçersiz aksiyon\n', '\n❌ Invalid action\n')));
46
+ console.log(chalk.gray(L('Kullanım:', 'Usage:')));
45
47
  console.log(chalk.cyan(' natureco cron add --name <name> --schedule <cron> --action <channel> --target <target> --prompt <prompt>'));
46
48
  console.log(chalk.cyan(' natureco cron list'));
47
49
  console.log(chalk.cyan(' natureco cron get <name>'));
@@ -51,8 +53,8 @@ async function cron(action, options) {
51
53
  console.log(chalk.cyan(' natureco cron disable <name>'));
52
54
  console.log(chalk.cyan(' natureco cron runs <name>'));
53
55
  console.log(chalk.cyan(' natureco cron run <name>'));
54
- console.log(chalk.gray('\nÖrnek:'));
55
- console.log(chalk.cyan(' natureco cron add --name "bitcoin-fiyat" --schedule "0 9 * * *" --action "whatsapp" --target "+905422842631" --prompt "Bugünkü Bitcoin fiyatını öğren ve kısaca bildir"\n'));
56
+ console.log(chalk.gray(L('\nÖrnek:', '\nExample:')));
57
+ console.log(chalk.cyan(L(' natureco cron add --name "bitcoin-fiyat" --schedule "0 9 * * *" --action "whatsapp" --target "+905422842631" --prompt "Bugünkü Bitcoin fiyatını öğren ve kısaca bildir"\n', ' natureco cron add --name "bitcoin-price" --schedule "0 9 * * *" --action "whatsapp" --target "+905422842631" --prompt "Get today\'s Bitcoin price and report briefly"\n')));
56
58
  process.exit(1);
57
59
  }
58
60
 
@@ -81,13 +83,13 @@ async function addCron(options) {
81
83
  const { name, schedule, action, target, prompt } = options;
82
84
 
83
85
  if (!name || !schedule || !action || !target || !prompt) {
84
- console.log(chalk.red('\n❌ Eksik parametre\n'));
85
- console.log(chalk.gray('Gerekli parametreler: --name, --schedule, --action, --target, --prompt\n'));
86
+ console.log(chalk.red(L('\n❌ Eksik parametre\n', '\n❌ Missing parameter\n')));
87
+ console.log(chalk.gray(L('Gerekli parametreler: --name, --schedule, --action, --target, --prompt\n', 'Required parameters: --name, --schedule, --action, --target, --prompt\n')));
86
88
  process.exit(1);
87
89
  }
88
90
 
89
91
  if (!['whatsapp', 'telegram'].includes(action)) {
90
- console.log(chalk.red('\n❌ Geçersiz action. Sadece "whatsapp" veya "telegram" kullanılabilir\n'));
92
+ console.log(chalk.red(L('\n❌ Geçersiz action. Sadece "whatsapp" veya "telegram" kullanılabilir\n', '\n❌ Invalid action. Only "whatsapp" or "telegram" can be used\n')));
91
93
  process.exit(1);
92
94
  }
93
95
 
@@ -95,13 +97,13 @@ async function addCron(options) {
95
97
  try {
96
98
  const nodeCron = require('node-cron');
97
99
  if (!nodeCron.validate(schedule)) {
98
- console.log(chalk.red('\n❌ Geçersiz cron ifadesi\n'));
99
- console.log(chalk.gray('Örnek: "0 9 * * *" (her gün saat 09:00)\n'));
100
+ console.log(chalk.red(L('\n❌ Geçersiz cron ifadesi\n', '\n❌ Invalid cron expression\n')));
101
+ console.log(chalk.gray(L('Örnek: "0 9 * * *" (her gün saat 09:00)\n', 'Example: "0 9 * * *" (every day at 09:00)\n')));
100
102
  process.exit(1);
101
103
  }
102
104
  } catch (err) {
103
- console.log(chalk.red('\n❌ node-cron yüklü değil\n'));
104
- console.log(chalk.yellow('Yüklemek için:'), chalk.cyan('npm install -g node-cron\n'));
105
+ console.log(chalk.red(L('\n❌ node-cron yüklü değil\n', '\n❌ node-cron not installed\n')));
106
+ console.log(chalk.yellow(L('Yüklemek için:', 'To install:')), chalk.cyan('npm install -g node-cron\n'));
105
107
  process.exit(1);
106
108
  }
107
109
 
@@ -109,8 +111,8 @@ async function addCron(options) {
109
111
 
110
112
  // Check if name already exists
111
113
  if (crons.find(c => c.name === name)) {
112
- console.log(chalk.red('\n❌ Bu isimde bir cron zaten var\n'));
113
- console.log(chalk.yellow('Önce silin:'), chalk.cyan(`natureco cron remove --name "${name}"\n`));
114
+ console.log(chalk.red(L('\n❌ Bu isimde bir cron zaten var\n', '\n❌ A cron with this name already exists\n')));
115
+ console.log(chalk.yellow(L('Önce silin:', 'Delete it first:')), chalk.cyan(`natureco cron remove --name "${name}"\n`));
114
116
  process.exit(1);
115
117
  }
116
118
 
@@ -127,24 +129,24 @@ async function addCron(options) {
127
129
  crons.push(newCron);
128
130
  saveCrons(crons);
129
131
 
130
- console.log(chalk.green('\n✅ Cron eklendi!\n'));
131
- console.log(chalk.cyan('İsim:'), chalk.white(name));
132
- console.log(chalk.cyan('Zamanlama:'), chalk.white(schedule));
133
- console.log(chalk.cyan('Kanal:'), chalk.white(action));
134
- console.log(chalk.cyan('Hedef:'), chalk.white(target));
132
+ console.log(chalk.green(L('\n✅ Cron eklendi!\n', '\n✅ Cron added!\n')));
133
+ console.log(chalk.cyan(L('İsim:', 'Name:')), chalk.white(name));
134
+ console.log(chalk.cyan(L('Zamanlama:', 'Schedule:')), chalk.white(schedule));
135
+ console.log(chalk.cyan(L('Kanal:', 'Channel:')), chalk.white(action));
136
+ console.log(chalk.cyan(L('Hedef:', 'Target:')), chalk.white(target));
135
137
  console.log(chalk.cyan('Prompt:'), chalk.white(prompt));
136
- console.log(chalk.gray('\nCron\'lar gateway başlatıldığında aktif olur.'));
137
- console.log(chalk.gray('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start\n'));
138
+ console.log(chalk.gray(L('\nCron\'lar gateway başlatıldığında aktif olur.', '\nCrons become active when the gateway starts.')));
139
+ console.log(chalk.gray(L('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start\n', 'If the gateway is running, restart it: natureco gateway stop && natureco gateway start\n')));
138
140
  }
139
141
 
140
142
  function listCrons() {
141
143
  const crons = loadCrons();
142
144
 
143
145
  if (crons.length === 0) {
144
- console.log('\n' + tui.styled(' ⏰ Zamanlanmış Görevler', { color: tui.PALETTE.primary, bold: true }));
146
+ console.log('\n' + tui.styled(L(' ⏰ Zamanlanmış Görevler', ' ⏰ Scheduled Tasks'), { color: tui.PALETTE.primary, bold: true }));
145
147
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
146
- console.log('\n ' + tui.C.muted('Henüz cron tanımlı değil. Eklemek için:'));
147
- console.log(' ' + tui.C.brand('natureco cron add --name "görev" --schedule "0 9 * * *" --action telegram --prompt "..."'));
148
+ console.log('\n ' + tui.C.muted(L('Henüz cron tanımlı değil. Eklemek için:', 'No crons defined yet. To add:')));
149
+ console.log(' ' + tui.C.brand(L('natureco cron add --name "görev" --schedule "0 9 * * *" --action telegram --prompt "..."', 'natureco cron add --name "task" --schedule "0 9 * * *" --action telegram --prompt "..."')));
148
150
  console.log('');
149
151
  return;
150
152
  }
@@ -177,16 +179,16 @@ function listCrons() {
177
179
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
178
180
 
179
181
  console.log('\n' + tui.table(rows, [
180
- { key: 'name', label: 'İsim', minWidth: 20, render: r => tui.styled(r.name, { color: tui.PALETTE.primary, bold: true }) },
181
- { key: 'schedule', label: 'Zamanlama', minWidth: 18, render: r => tui.C.muted(r.schedule) },
182
+ { key: 'name', label: L('İsim', 'Name'), minWidth: 20, render: r => tui.styled(r.name, { color: tui.PALETTE.primary, bold: true }) },
183
+ { key: 'schedule', label: L('Zamanlama', 'Schedule'), minWidth: 18, render: r => tui.C.muted(r.schedule) },
182
184
  {
183
- key: 'status', label: 'Durum', minWidth: 10,
185
+ key: 'status', label: L('Durum', 'Status'), minWidth: 10,
184
186
  render: r => r.status
185
- ? tui.styled(' ✓ Aktif ', { bg: tui.PALETTE.success, color: '#000', bold: true })
186
- : tui.styled(' ✗ Pasif ', { bg: tui.PALETTE.muted, color: '#000', bold: true }),
187
+ ? tui.styled(L(' ✓ Aktif ', ' ✓ Active '), { bg: tui.PALETTE.success, color: '#000', bold: true })
188
+ : tui.styled(L(' ✗ Pasif ', ' ✗ Inactive '), { bg: tui.PALETTE.muted, color: '#000', bold: true }),
187
189
  },
188
- { key: 'target', label: 'Hedef', minWidth: 18, render: r => tui.C.text(r.target) },
189
- { key: 'lastRun', label: 'Son Çalışma', minWidth: 18, render: r => tui.C.muted(r.lastRun) },
190
+ { key: 'target', label: L('Hedef', 'Target'), minWidth: 18, render: r => tui.C.text(r.target) },
191
+ { key: 'lastRun', label: L('Son Çalışma', 'Last Run'), minWidth: 18, render: r => tui.C.muted(r.lastRun) },
190
192
  ], { borderStyle: 'round', zebra: true }));
191
193
 
192
194
  console.log('');
@@ -196,7 +198,7 @@ function removeCron(options) {
196
198
  const { name } = options;
197
199
 
198
200
  if (!name) {
199
- F.error('--name parametresi gerekli');
201
+ F.error(L('--name parametresi gerekli', '--name parameter required'));
200
202
  process.exit(1);
201
203
  }
202
204
 
@@ -204,39 +206,39 @@ function removeCron(options) {
204
206
  const index = crons.findIndex(c => c.name === name);
205
207
 
206
208
  if (index === -1) {
207
- F.error('Bu isimde bir cron bulunamadı');
209
+ F.error(L('Bu isimde bir cron bulunamadı', 'No cron found with this name'));
208
210
  process.exit(1);
209
211
  }
210
212
 
211
213
  crons.splice(index, 1);
212
214
  saveCrons(crons);
213
215
 
214
- F.success('Cron silindi!');
215
- F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
216
+ F.success(L('Cron silindi!', 'Cron deleted!'));
217
+ F.meta(L('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start', 'If the gateway is running, restart it: natureco gateway stop && natureco gateway start'));
216
218
  }
217
219
 
218
220
  function getCron(options) {
219
221
  const { name } = options;
220
222
  if (!name) {
221
- F.error('Cron adı gerekli. Kullanım: natureco cron get <name>');
223
+ F.error(L('Cron adı gerekli. Kullanım: natureco cron get <name>', 'Cron name required. Usage: natureco cron get <name>'));
222
224
  process.exit(1);
223
225
  }
224
226
 
225
227
  const crons = loadCrons();
226
228
  const cron = crons.find(c => c.name === name);
227
229
  if (!cron) {
228
- F.error('"' + name + '" isminde bir cron bulunamadı');
230
+ F.error('"' + name + L('" isminde bir cron bulunamadı', '" — no cron found with this name'));
229
231
  process.exit(1);
230
232
  }
231
233
 
232
234
  F.header('Cron: ' + cron.name);
233
- F.kv('İsim', cron.name);
234
- F.kv('Zamanlama', cron.schedule);
235
- F.kv('Kanal', cron.action);
236
- F.kv('Hedef', cron.target);
235
+ F.kv(L('İsim', 'Name'), cron.name);
236
+ F.kv(L('Zamanlama', 'Schedule'), cron.schedule);
237
+ F.kv(L('Kanal', 'Channel'), cron.action);
238
+ F.kv(L('Hedef', 'Target'), cron.target);
237
239
  F.kv('Prompt', cron.prompt);
238
- F.kv('Oluşturulma', cron.createdAt);
239
- F.kv('Durum', cron.enabled ? 'Aktif' : 'Pasif');
240
+ F.kv(L('Oluşturulma', 'Created'), cron.createdAt);
241
+ F.kv(L('Durum', 'Status'), cron.enabled ? L('Aktif', 'Active') : L('Pasif', 'Inactive'));
240
242
  }
241
243
 
242
244
  function editCron(options) {
@@ -244,14 +246,14 @@ function editCron(options) {
244
246
  const newName = options['newName'];
245
247
 
246
248
  if (!name) {
247
- F.error('Cron adı gerekli. Kullanım: natureco cron edit <name> [--name <newName>] [--schedule <cron>] [--action <channel>] [--target <target>] [--prompt <prompt>]');
249
+ F.error(L('Cron adı gerekli. Kullanım: natureco cron edit <name> [--name <newName>] [--schedule <cron>] [--action <channel>] [--target <target>] [--prompt <prompt>]', 'Cron name required. Usage: natureco cron edit <name> [--name <newName>] [--schedule <cron>] [--action <channel>] [--target <target>] [--prompt <prompt>]'));
248
250
  process.exit(1);
249
251
  }
250
252
 
251
253
  const crons = loadCrons();
252
254
  const cron = crons.find(c => c.name === name);
253
255
  if (!cron) {
254
- F.error('"' + name + '" isminde bir cron bulunamadı');
256
+ F.error('"' + name + L('" isminde bir cron bulunamadı', '" — no cron found with this name'));
255
257
  process.exit(1);
256
258
  }
257
259
 
@@ -260,18 +262,18 @@ function editCron(options) {
260
262
  try {
261
263
  const nodeCron = require('node-cron');
262
264
  if (!nodeCron.validate(schedule)) {
263
- F.error('Geçersiz cron ifadesi');
265
+ F.error(L('Geçersiz cron ifadesi', 'Invalid cron expression'));
264
266
  process.exit(1);
265
267
  }
266
268
  } catch (err) {
267
- F.error('node-cron yüklü değil');
269
+ F.error(L('node-cron yüklü değil', 'node-cron not installed'));
268
270
  process.exit(1);
269
271
  }
270
272
  cron.schedule = schedule;
271
273
  }
272
274
  if (action) {
273
275
  if (!['whatsapp', 'telegram'].includes(action)) {
274
- F.error('Geçersiz action. Sadece "whatsapp" veya "telegram" kullanılabilir');
276
+ F.error(L('Geçersiz action. Sadece "whatsapp" veya "telegram" kullanılabilir', 'Invalid action. Only "whatsapp" or "telegram" can be used'));
275
277
  process.exit(1);
276
278
  }
277
279
  cron.action = action;
@@ -281,65 +283,65 @@ function editCron(options) {
281
283
 
282
284
  saveCrons(crons);
283
285
 
284
- F.success('Cron güncellendi!');
285
- F.kv('İsim', cron.name);
286
- F.kv('Zamanlama', cron.schedule);
287
- F.kv('Kanal', cron.action);
288
- F.kv('Hedef', cron.target);
286
+ F.success(L('Cron güncellendi!', 'Cron updated!'));
287
+ F.kv(L('İsim', 'Name'), cron.name);
288
+ F.kv(L('Zamanlama', 'Schedule'), cron.schedule);
289
+ F.kv(L('Kanal', 'Channel'), cron.action);
290
+ F.kv(L('Hedef', 'Target'), cron.target);
289
291
  F.kv('Prompt', cron.prompt);
290
- F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
292
+ F.meta(L('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start', 'If the gateway is running, restart it: natureco gateway stop && natureco gateway start'));
291
293
  }
292
294
 
293
295
  function enableCron(options) {
294
296
  const { name } = options;
295
297
  if (!name) {
296
- F.error('Cron adı gerekli. Kullanım: natureco cron enable <name>');
298
+ F.error(L('Cron adı gerekli. Kullanım: natureco cron enable <name>', 'Cron name required. Usage: natureco cron enable <name>'));
297
299
  process.exit(1);
298
300
  }
299
301
 
300
302
  const crons = loadCrons();
301
303
  const cron = crons.find(c => c.name === name);
302
304
  if (!cron) {
303
- F.error('"' + name + '" isminde bir cron bulunamadı');
305
+ F.error('"' + name + L('" isminde bir cron bulunamadı', '" — no cron found with this name'));
304
306
  process.exit(1);
305
307
  }
306
308
 
307
309
  if (cron.enabled) {
308
- F.warning('"' + name + '" cron zaten aktif');
310
+ F.warning('"' + name + L('" cron zaten aktif', '" cron already active'));
309
311
  return;
310
312
  }
311
313
 
312
314
  cron.enabled = true;
313
315
  saveCrons(crons);
314
316
  F.dot(true, name);
315
- F.success('"' + name + '" cron aktifleştirildi');
316
- F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
317
+ F.success('"' + name + L('" cron aktifleştirildi', '" cron enabled'));
318
+ F.meta(L('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start', 'If the gateway is running, restart it: natureco gateway stop && natureco gateway start'));
317
319
  }
318
320
 
319
321
  function disableCron(options) {
320
322
  const { name } = options;
321
323
  if (!name) {
322
- F.error('Cron adı gerekli. Kullanım: natureco cron disable <name>');
324
+ F.error(L('Cron adı gerekli. Kullanım: natureco cron disable <name>', 'Cron name required. Usage: natureco cron disable <name>'));
323
325
  process.exit(1);
324
326
  }
325
327
 
326
328
  const crons = loadCrons();
327
329
  const cron = crons.find(c => c.name === name);
328
330
  if (!cron) {
329
- F.error('"' + name + '" isminde bir cron bulunamadı');
331
+ F.error('"' + name + L('" isminde bir cron bulunamadı', '" — no cron found with this name'));
330
332
  process.exit(1);
331
333
  }
332
334
 
333
335
  if (!cron.enabled) {
334
- F.warning('"' + name + '" cron zaten pasif');
336
+ F.warning('"' + name + L('" cron zaten pasif', '" cron already inactive'));
335
337
  return;
336
338
  }
337
339
 
338
340
  cron.enabled = false;
339
341
  saveCrons(crons);
340
342
  F.dot(false, name);
341
- F.success('"' + name + '" cron pasifleştirildi');
342
- F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
343
+ F.success('"' + name + L('" cron pasifleştirildi', '" cron disabled'));
344
+ F.meta(L('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start', 'If the gateway is running, restart it: natureco gateway stop && natureco gateway start'));
343
345
  }
344
346
 
345
347
  function loadRuns() {
@@ -356,7 +358,7 @@ function loadRuns() {
356
358
  function showRuns(options) {
357
359
  const { name } = options;
358
360
  if (!name) {
359
- F.error('Cron adı gerekli. Kullanım: natureco cron runs <name>');
361
+ F.error(L('Cron adı gerekli. Kullanım: natureco cron runs <name>', 'Cron name required. Usage: natureco cron runs <name>'));
360
362
  process.exit(1);
361
363
  }
362
364
 
@@ -365,7 +367,7 @@ function showRuns(options) {
365
367
  F.header('Cron Runs: ' + name);
366
368
 
367
369
  if (runs.length === 0) {
368
- F.meta('"' + name + '" için kayıtlı çalışma geçmişi yok');
370
+ F.meta('"' + name + L('" için kayıtlı çalışma geçmişi yok', '" — no run history recorded'));
369
371
  return;
370
372
  }
371
373
 
@@ -380,25 +382,25 @@ function showRuns(options) {
380
382
  function runCron(options) {
381
383
  const { name } = options;
382
384
  if (!name) {
383
- F.error('Cron adı gerekli. Kullanım: natureco cron run <name>');
385
+ F.error(L('Cron adı gerekli. Kullanım: natureco cron run <name>', 'Cron name required. Usage: natureco cron run <name>'));
384
386
  process.exit(1);
385
387
  }
386
388
 
387
389
  const crons = loadCrons();
388
390
  const cron = crons.find(c => c.name === name);
389
391
  if (!cron) {
390
- F.error('"' + name + '" isminde bir cron bulunamadı');
392
+ F.error('"' + name + L('" isminde bir cron bulunamadı', '" — no cron found with this name'));
391
393
  process.exit(1);
392
394
  }
393
395
 
394
396
  const timestamp = new Date().toISOString();
395
397
 
396
- F.info('"' + name + '" cron manuel olarak çalıştırılıyor...');
397
- F.kv('Zamanlama', cron.schedule);
398
- F.kv('Kanal', cron.action);
399
- F.kv('Hedef', cron.target);
398
+ F.info('"' + name + L('" cron manuel olarak çalıştırılıyor...', '" cron running manually...'));
399
+ F.kv(L('Zamanlama', 'Schedule'), cron.schedule);
400
+ F.kv(L('Kanal', 'Channel'), cron.action);
401
+ F.kv(L('Hedef', 'Target'), cron.target);
400
402
  F.kv('Prompt', cron.prompt);
401
- F.success('Cron tetiklendi (mock)');
403
+ F.success(L('Cron tetiklendi (mock)', 'Cron triggered (mock)'));
402
404
 
403
405
  // Log the run
404
406
  const runs = loadRuns();
@@ -1,4 +1,6 @@
1
1
  const chalk = require('chalk');
2
+ const { getLang: _gl } = require('../utils/i18n');
3
+ const L = (tr, en) => (_gl() === 'en' ? en : tr);
2
4
  const tui = require('../utils/tui');
3
5
  const F = require('../utils/format');
4
6
  const fs = require('fs');
@@ -349,10 +351,10 @@ async function gateway(action, ...args) {
349
351
  }
350
352
 
351
353
  F.section('Quick Start');
352
- F.kv('natureco chat', 'Bot ile sohbet başlat');
353
- F.kv('natureco setup', 'Kurulumu yeniden çalıştır');
354
- F.kv('natureco gateway start', 'Gateway\'i arka planda başlat');
355
- F.kv('natureco help', 'Tüm komutları göster');
354
+ F.kv('natureco chat', L('Bot ile sohbet başlat', 'Start chatting with the bot'));
355
+ F.kv('natureco setup', L('Kurulumu yeniden çalıştır', 'Re-run setup'));
356
+ F.kv('natureco gateway start', L('Gateway\'i arka planda başlat', 'Start the gateway in the background'));
357
+ F.kv('natureco help', L('Tüm komutları göster', 'Show all commands'));
356
358
 
357
359
  F.meta('Docs: natureco.me/cli');
358
360
  }
@@ -371,9 +373,9 @@ async function startGateway() {
371
373
  const existingPid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
372
374
  try {
373
375
  process.kill(existingPid, 0); // Test et, canlı mı
374
- console.log('\n' + tui.styled(' ⚠️ Gateway zaten çalışıyor (PID: ' + existingPid + ')', { color: tui.PALETTE.warning, bold: true }) + '\n');
375
- console.log(' ' + tui.C.muted('Durdurmak için: ') + tui.C.brand('natureco gateway stop'));
376
- console.log(' ' + tui.C.muted('Durum için: ') + tui.C.brand('natureco gateway status'));
376
+ console.log('\n' + tui.styled(L(' ⚠️ Gateway zaten çalışıyor (PID: ', ' ⚠️ Gateway already running (PID: ') + existingPid + ')', { color: tui.PALETTE.warning, bold: true }) + '\n');
377
+ console.log(' ' + tui.C.muted(L('Durdurmak için: ', 'To stop: ')) + tui.C.brand('natureco gateway stop'));
378
+ console.log(' ' + tui.C.muted(L('Durum için: ', 'For status: ')) + tui.C.brand('natureco gateway status'));
377
379
  console.log('');
378
380
  return;
379
381
  } catch {
@@ -382,7 +384,7 @@ async function startGateway() {
382
384
  }
383
385
  }
384
386
 
385
- console.log('\n' + tui.styled(' 🚀 Gateway Başlatılıyor...', { color: tui.PALETTE.primary, bold: true }));
387
+ console.log('\n' + tui.styled(L(' 🚀 Gateway Başlatılıyor...', ' 🚀 Starting Gateway...'), { color: tui.PALETTE.primary, bold: true }));
386
388
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
387
389
 
388
390
  // Log dosyası
@@ -405,17 +407,17 @@ async function startGateway() {
405
407
  // Başarı kartı
406
408
  const cardW = 54;
407
409
  console.log(tui.styled(' ╭' + '─'.repeat(cardW) + '╮', { color: tui.PALETTE.border }));
408
- console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Durum ') + tui.styled(' ✓ Çalışıyor '.padEnd(36), { bg: tui.PALETTE.success, color: '#000', bold: true }) + tui.styled(' │', { color: tui.PALETTE.border }));
410
+ console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted(L('Durum ', 'Status ')) + tui.styled(L(' ✓ Çalışıyor ', ' ✓ Running ').padEnd(36), { bg: tui.PALETTE.success, color: '#000', bold: true }) + tui.styled(' │', { color: tui.PALETTE.border }));
409
411
  console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('PID ') + tui.styled(String(child.pid).padEnd(40), { color: tui.PALETTE.text, bold: true }) + tui.styled(' │', { color: tui.PALETTE.border }));
410
- console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Log dosyası ') + tui.styled(logFile.padEnd(40).slice(0, 40), { color: tui.PALETTE.text }) + tui.styled(' │', { color: tui.PALETTE.border }));
412
+ console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted(L('Log dosyası ', 'Log file ')) + tui.styled(logFile.padEnd(40).slice(0, 40), { color: tui.PALETTE.text }) + tui.styled(' │', { color: tui.PALETTE.border }));
411
413
  console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Provider ') + tui.styled((config.providerUrl || '—').replace('https://', '').padEnd(40).slice(0, 40), { color: tui.PALETTE.text }) + tui.styled(' │', { color: tui.PALETTE.border }));
412
- console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Telegram ') + tui.styled((config.telegramToken ? '✓ Token ayarlı' : '✗ Token yok').padEnd(40), { color: config.telegramToken ? tui.PALETTE.success : tui.PALETTE.warning, bold: true }) + tui.styled(' │', { color: tui.PALETTE.border }));
414
+ console.log(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Telegram ') + tui.styled((config.telegramToken ? L('✓ Token ayarlı', '✓ Token set') : L('✗ Token yok', '✗ No token')).padEnd(40), { color: config.telegramToken ? tui.PALETTE.success : tui.PALETTE.warning, bold: true }) + tui.styled(' │', { color: tui.PALETTE.border }));
413
415
  console.log(tui.styled(' ╰' + '─'.repeat(cardW) + '╯', { color: tui.PALETTE.border }));
414
416
 
415
- console.log('\n ' + tui.C.muted('Komutlar:'));
416
- console.log(' ' + tui.C.muted(' Durum: ') + tui.C.brand('natureco gateway status'));
417
- console.log(' ' + tui.C.muted(' Log: ') + tui.C.brand('natureco gateway logs') + ' ' + tui.C.muted('veya ') + tui.C.brand('tail -f ' + logFile));
418
- console.log(' ' + tui.C.muted(' Dur: ') + tui.C.brand('natureco gateway stop'));
417
+ console.log('\n ' + tui.C.muted(L('Komutlar:', 'Commands:')));
418
+ console.log(' ' + tui.C.muted(L(' Durum: ', ' Status: ')) + tui.C.brand('natureco gateway status'));
419
+ console.log(' ' + tui.C.muted(' Log: ') + tui.C.brand('natureco gateway logs') + ' ' + tui.C.muted(L('veya ', 'or ')) + tui.C.brand('tail -f ' + logFile));
420
+ console.log(' ' + tui.C.muted(L(' Dur: ', ' Stop: ')) + tui.C.brand('natureco gateway stop'));
419
421
  console.log('');
420
422
  }
421
423
 
@@ -485,30 +487,30 @@ async function startWhatsAppProvider(sessionDir, config) {
485
487
  if (trimmed.toLowerCase().startsWith('!code')) {
486
488
  const task = trimmed.replace(/^!code\s*/i, '').trim();
487
489
  if (!task) {
488
- await sock.sendMessage(msg.key.remoteJid, { text: '⚙️ Kullanım: !code <görev>\nÖrnek: !code login sayfasına forgot password ekle' });
490
+ await sock.sendMessage(msg.key.remoteJid, { text: L('⚙️ Kullanım: !code <görev>\nÖrnek: !code login sayfasına forgot password ekle', '⚙️ Usage: !code <task>\nExample: !code add forgot password to the login page') });
489
491
  continue;
490
492
  }
491
- console.log(chalk.cyan('[whatsapp]'), chalk.yellow(`!code komutu: ${task.slice(0, 60)}`));
493
+ console.log(chalk.cyan('[whatsapp]'), chalk.yellow(`!code ${L('komutu', 'command')}: ${task.slice(0, 60)}`));
492
494
 
493
495
  try {
494
496
  const { runCodeAgent } = require('../utils/headless');
495
- await sock.sendMessage(msg.key.remoteJid, { text: `⚙️ Çalışıyor: ${task.slice(0, 80)}...` });
497
+ await sock.sendMessage(msg.key.remoteJid, { text: `⚙️ ${L('Çalışıyor', 'Running')}: ${task.slice(0, 80)}...` });
496
498
 
497
499
  const result = await runCodeAgent(task, process.cwd(), (progress) => {
498
500
  console.log(chalk.cyan('[whatsapp/code]'), chalk.gray(progress));
499
501
  });
500
502
 
501
- let reply = `✅ Tamamlandı!\n\n${result.reply}`;
503
+ let reply = `✅ ${L('Tamamlandı!', 'Done!')}\n\n${result.reply}`;
502
504
  if (result.filesChanged?.length) {
503
- reply += `\n\n📝 Değiştirilen dosyalar:\n${result.filesChanged.map(f => `• ${f}`).join('\n')}`;
505
+ reply += `\n\n📝 ${L('Değiştirilen dosyalar', 'Changed files')}:\n${result.filesChanged.map(f => `• ${f}`).join('\n')}`;
504
506
  }
505
507
 
506
508
  await sock.sendMessage(msg.key.remoteJid, { text: reply.slice(0, 4000) });
507
- console.log(chalk.cyan('[whatsapp]'), chalk.green(`!code tamamlandı (${result.iterations} iterasyon)`));
509
+ console.log(chalk.cyan('[whatsapp]'), chalk.green(`!code ${L('tamamlandı', 'completed')} (${result.iterations} ${L('iterasyon', 'iterations')})`));
508
510
  } catch (err) {
509
511
  const msg = err instanceof NatureCoError ? err.message : err?.message ?? 'Unknown error';
510
- console.log(chalk.red('[whatsapp/code]'), chalk.gray(`hata: ${msg}`));
511
- await sock.sendMessage(msg.key.remoteJid, { text: `❌ Hata: ${msg}` });
512
+ console.log(chalk.red('[whatsapp/code]'), chalk.gray(`${L('hata', 'error')}: ${msg}`));
513
+ await sock.sendMessage(msg.key.remoteJid, { text: `❌ ${L('Hata', 'Error')}: ${msg}` });
512
514
  }
513
515
  continue;
514
516
  }
@@ -1,4 +1,6 @@
1
1
  const chalk = require('chalk');
2
+ const { getLang: _gl } = require('../utils/i18n');
3
+ const L = (tr, en) => (_gl() === 'en' ? en : tr);
2
4
  const fs = require('fs');
3
5
  const path = require('path');
4
6
  const os = require('os');
@@ -23,8 +25,8 @@ async function plugins(args) {
23
25
  if (action === 'registry') return registryHandler(opts);
24
26
  if (action === 'marketplace') return marketplaceHandler(opts);
25
27
 
26
- console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
27
- console.log(chalk.gray(' Kullanım: natureco plugins [list|install|uninstall|enable|disable|info|update|search|doctor|registry|marketplace]\n'));
28
+ console.log(chalk.red(`\n ❌ ${L('Bilinmeyen komut', 'Unknown command')}: ${action}\n`));
29
+ console.log(chalk.gray(L(' Kullanım: natureco plugins [list|install|uninstall|enable|disable|info|update|search|doctor|registry|marketplace]\n', ' Usage: natureco plugins [list|install|uninstall|enable|disable|info|update|search|doctor|registry|marketplace]\n')));
28
30
  process.exit(1);
29
31
  } catch (err) {
30
32
  handleError(err);
@@ -79,113 +81,113 @@ function listPlugins(opts) {
79
81
  console.log(chalk.cyan.bold('\n Plugins\n'));
80
82
 
81
83
  if (filtered.length === 0) {
82
- console.log(chalk.gray(' Yüklü plugin yok.\n'));
83
- console.log(chalk.gray(' Yüklemek için: ') + chalk.cyan('natureco plugins install <paket-adı|./path|git:url>'));
84
- console.log(chalk.gray(' Aramak için: ') + chalk.cyan('natureco plugins search <query>\n'));
84
+ console.log(chalk.gray(L(' Yüklü plugin yok.\n', ' No plugins installed.\n')));
85
+ console.log(chalk.gray(L(' Yüklemek için: ', ' To install: ')) + chalk.cyan('natureco plugins install <paket-adı|./path|git:url>'));
86
+ console.log(chalk.gray(L(' Aramak için: ', ' To search: ')) + chalk.cyan('natureco plugins search <query>\n'));
85
87
  return;
86
88
  }
87
89
 
88
90
  filtered.forEach(p => {
89
- const status = p.enabled ? chalk.green('✓ aktif') : chalk.gray('○ pasif');
91
+ const status = p.enabled ? chalk.green(L('✓ aktif', '✓ active')) : chalk.gray(L('○ pasif', '○ inactive'));
90
92
  const source = registry.plugins.find(r => r.id === p.slug)?.source || 'local';
91
93
  const sourceIcon = source === 'npm' ? '📦' : source === 'git' ? '🌐' : source === 'local' ? '📁' : '❓';
92
94
  console.log(` ${sourceIcon} ${chalk.white(p.name)} ${chalk.gray(`v${p.version}`)} ${status}`);
93
95
  if (p.description) console.log(chalk.gray(` ${p.description}`));
94
96
  if (opts.verbose) {
95
- console.log(chalk.gray(` Kaynak: ${source} | Yol: ${p.installPath}`));
96
- if (p.author) console.log(chalk.gray(` Yazar: ${p.author}`));
97
+ console.log(chalk.gray(` ${L('Kaynak', 'Source')}: ${source} | ${L('Yol', 'Path')}: ${p.installPath}`));
98
+ if (p.author) console.log(chalk.gray(` ${L('Yazar', 'Author')}: ${p.author}`));
97
99
  }
98
100
  console.log('');
99
101
  });
100
102
 
101
103
  console.log(chalk.gray(' ' + '─'.repeat(48)));
102
- console.log(chalk.gray(` Toplam: ${filtered.length} plugin (${allPlugins.length - filtered.length} pasif)`));
103
- console.log(chalk.gray(' Detay: ') + chalk.cyan('natureco plugins list --verbose'));
104
+ console.log(chalk.gray(` ${L('Toplam', 'Total')}: ${filtered.length} plugin (${allPlugins.length - filtered.length} ${L('pasif', 'inactive')})`));
105
+ console.log(chalk.gray(L(' Detay: ', ' Details: ')) + chalk.cyan('natureco plugins list --verbose'));
104
106
  console.log(chalk.gray(' JSON: ') + chalk.cyan('natureco plugins list --json\n'));
105
107
  }
106
108
 
107
109
  async function installHandler(spec, opts) {
108
110
  if (!spec) {
109
- console.log(chalk.red('\n ❌ Paket adı gerekli\n'));
110
- console.log(chalk.gray(' Kullanım: natureco plugins install <paket-adı|./path|git:url|clawhub:<id>>\n'));
111
- console.log(chalk.gray(' Örnekler:'));
111
+ console.log(chalk.red(L('\n ❌ Paket adı gerekli\n', '\n ❌ Package name required\n')));
112
+ console.log(chalk.gray(L(' Kullanım: natureco plugins install <paket-adı|./path|git:url|clawhub:<id>>\n', ' Usage: natureco plugins install <package-name|./path|git:url|clawhub:<id>>\n')));
113
+ console.log(chalk.gray(L(' Örnekler:', ' Examples:')));
112
114
  console.log(chalk.gray(' natureco plugins install my-plugin'));
113
115
  console.log(chalk.gray(' natureco plugins install npm:my-plugin'));
114
- console.log(chalk.gray(' natureco plugins install ./yerel-klasor'));
116
+ console.log(chalk.gray(L(' natureco plugins install ./yerel-klasor', ' natureco plugins install ./local-folder')));
115
117
  console.log(chalk.gray(' natureco plugins install git:github.com/user/repo'));
116
118
  console.log(chalk.gray(' natureco plugins install clawhub:plugin-id\n'));
117
119
  process.exit(1);
118
120
  }
119
121
 
120
122
  if (opts.dryRun) {
121
- console.log(chalk.gray(`\n 📋 Kuru çalışma: "${spec}" yüklenecek\n`));
123
+ console.log(chalk.gray(`\n 📋 ${L('Kuru çalışma', 'Dry run')}: "${spec}" ${L('yüklenecek', 'will be installed')}\n`));
122
124
  return;
123
125
  }
124
126
 
125
- console.log(chalk.gray(`\n "${spec}" yükleniyor...\n`));
127
+ console.log(chalk.gray(`\n "${spec}" ${L('yükleniyor...', 'installing...')}\n`));
126
128
 
127
129
  try {
128
130
  const result = await installPlugin(spec);
129
- console.log(chalk.green(` ✓ Plugin yüklendi: ${result.name} v${result.version}\n`));
130
- console.log(chalk.gray(` Kaynak: ${result.source}`));
131
+ console.log(chalk.green(` ✓ ${L('Plugin yüklendi', 'Plugin installed')}: ${result.name} v${result.version}\n`));
132
+ console.log(chalk.gray(` ${L('Kaynak', 'Source')}: ${result.source}`));
131
133
  console.log(chalk.gray(` Slug: ${result.slug}\n`));
132
134
  } catch (err) {
133
- console.log(chalk.red(`\n ❌ Yükleme başarısız: ${err.message}\n`));
135
+ console.log(chalk.red(`\n ❌ ${L('Yükleme başarısız', 'Installation failed')}: ${err.message}\n`));
134
136
  process.exit(1);
135
137
  }
136
138
  }
137
139
 
138
140
  async function uninstallHandler(slug, opts) {
139
141
  if (!slug) {
140
- console.log(chalk.red('\n ❌ Plugin adı gerekli\n'));
141
- console.log(chalk.gray(' Kullanım: natureco plugins uninstall <slug>\n'));
142
+ console.log(chalk.red(L('\n ❌ Plugin adı gerekli\n', '\n ❌ Plugin name required\n')));
143
+ console.log(chalk.gray(L(' Kullanım: natureco plugins uninstall <slug>\n', ' Usage: natureco plugins uninstall <slug>\n')));
142
144
  process.exit(1);
143
145
  }
144
146
 
145
147
  if (opts.dryRun) {
146
- console.log(chalk.gray(`\n 📋 Kuru çalışma: "${slug}" kaldırılacak\n`));
148
+ console.log(chalk.gray(`\n 📋 ${L('Kuru çalışma', 'Dry run')}: "${slug}" ${L('kaldırılacak', 'will be removed')}\n`));
147
149
  return;
148
150
  }
149
151
 
150
152
  try {
151
153
  const result = await uninstallPlugin(slug, { keepFiles: opts.keepFiles });
152
- console.log(chalk.green(`\n ✓ Plugin kaldırıldı: ${result.name}\n`));
154
+ console.log(chalk.green(`\n ✓ ${L('Plugin kaldırıldı', 'Plugin removed')}: ${result.name}\n`));
153
155
  } catch (err) {
154
- console.log(chalk.red(`\n ❌ Kaldırma başarısız: ${err.message}\n`));
156
+ console.log(chalk.red(`\n ❌ ${L('Kaldırma başarısız', 'Removal failed')}: ${err.message}\n`));
155
157
  process.exit(1);
156
158
  }
157
159
  }
158
160
 
159
161
  function toggleHandler(slug, enable) {
160
162
  if (!slug) {
161
- console.log(chalk.red(`\n ❌ Plugin adı gerekli\n`));
163
+ console.log(chalk.red(L('\n ❌ Plugin adı gerekli\n', '\n ❌ Plugin name required\n')));
162
164
  process.exit(1);
163
165
  }
164
166
  const pluginDir = path.join(PLUGINS_DIR, slug);
165
167
  if (!fs.existsSync(pluginDir)) {
166
- console.log(chalk.red(`\n ❌ Plugin bulunamadı: ${slug}\n`));
168
+ console.log(chalk.red(`\n ❌ ${L('Plugin bulunamadı', 'Plugin not found')}: ${slug}\n`));
167
169
  process.exit(1);
168
170
  }
169
171
  const disabledFile = path.join(pluginDir, '.disabled');
170
172
  if (enable) {
171
173
  if (fs.existsSync(disabledFile)) fs.unlinkSync(disabledFile);
172
- console.log(chalk.green(`\n ✓ Plugin aktif: ${slug}\n`));
174
+ console.log(chalk.green(`\n ✓ ${L('Plugin aktif', 'Plugin enabled')}: ${slug}\n`));
173
175
  } else {
174
176
  fs.writeFileSync(disabledFile, '');
175
- console.log(chalk.gray(`\n ○ Plugin pasif: ${slug}\n`));
177
+ console.log(chalk.gray(`\n ○ ${L('Plugin pasif', 'Plugin disabled')}: ${slug}\n`));
176
178
  }
177
179
  }
178
180
 
179
181
  function infoHandler(slug, opts) {
180
182
  if (!slug && !opts.all) {
181
- console.log(chalk.red('\n ❌ Plugin adı gerekli\n'));
182
- console.log(chalk.gray(' Kullanım: natureco plugins info <slug>\n'));
183
+ console.log(chalk.red(L('\n ❌ Plugin adı gerekli\n', '\n ❌ Plugin name required\n')));
184
+ console.log(chalk.gray(L(' Kullanım: natureco plugins info <slug>\n', ' Usage: natureco plugins info <slug>\n')));
183
185
  process.exit(1);
184
186
  }
185
187
 
186
188
  if (opts.all) {
187
189
  const all = scanInstalled();
188
- console.log(chalk.cyan.bold('\n Plugin Detayları\n'));
190
+ console.log(chalk.cyan.bold(L('\n Plugin Detayları\n', '\n Plugin Details\n')));
189
191
  all.forEach(p => {
190
192
  showPluginDetail(p);
191
193
  });
@@ -194,7 +196,7 @@ function infoHandler(slug, opts) {
194
196
 
195
197
  const p = getPlugin(slug);
196
198
  if (!p) {
197
- console.log(chalk.red(`\n ❌ Plugin bulunamadı: ${slug}\n`));
199
+ console.log(chalk.red(`\n ❌ ${L('Plugin bulunamadı', 'Plugin not found')}: ${slug}\n`));
198
200
  process.exit(1);
199
201
  }
200
202
 
@@ -216,16 +218,16 @@ function showPluginDetail(p) {
216
218
  console.log(chalk.gray(' ' + '─'.repeat(48)));
217
219
  console.log(chalk.cyan.bold(`\n ${p.name}\n`));
218
220
  console.log(chalk.gray(' Slug : ') + chalk.white(p.slug));
219
- console.log(chalk.gray(' Versiyon : ') + chalk.white(p.version));
220
- console.log(chalk.gray(' Durum : ') + (p.enabled ? chalk.green('aktif') : chalk.gray('pasif')));
221
- if (p.description) console.log(chalk.gray(' Açıklama : ') + chalk.white(p.description));
222
- if (p.author) console.log(chalk.gray(' Yazar : ') + chalk.white(p.author));
223
- if (p.license) console.log(chalk.gray(' Lisans : ') + chalk.white(p.license));
224
- if (p.keywords?.length) console.log(chalk.gray(' Etiketler : ') + chalk.white(p.keywords.join(', ')));
225
- console.log(chalk.gray(' Yol : ') + chalk.gray(p.installPath));
226
- if (p.entry) console.log(chalk.gray(' Giriş : ') + chalk.white(p.entry));
221
+ console.log(chalk.gray(L(' Versiyon : ', ' Version : ')) + chalk.white(p.version));
222
+ console.log(chalk.gray(L(' Durum : ', ' Status : ')) + (p.enabled ? chalk.green(L('aktif', 'active')) : chalk.gray(L('pasif', 'inactive'))));
223
+ if (p.description) console.log(chalk.gray(L(' Açıklama : ', ' Description: ')) + chalk.white(p.description));
224
+ if (p.author) console.log(chalk.gray(L(' Yazar : ', ' Author : ')) + chalk.white(p.author));
225
+ if (p.license) console.log(chalk.gray(L(' Lisans : ', ' License : ')) + chalk.white(p.license));
226
+ if (p.keywords?.length) console.log(chalk.gray(L(' Etiketler : ', ' Tags : ')) + chalk.white(p.keywords.join(', ')));
227
+ console.log(chalk.gray(L(' Yol : ', ' Path : ')) + chalk.gray(p.installPath));
228
+ if (p.entry) console.log(chalk.gray(L(' Giriş : ', ' Entry : ')) + chalk.white(p.entry));
227
229
  if (p.dependencies && Object.keys(p.dependencies).length > 0) {
228
- console.log(chalk.gray(' Bağımlılıklar:'));
230
+ console.log(chalk.gray(L(' Bağımlılıklar:', ' Dependencies:')));
229
231
  Object.entries(p.dependencies).forEach(([k, v]) => {
230
232
  const depPath = path.join(p.installPath, 'node_modules', k);
231
233
  const installed = fs.existsSync(depPath) ? chalk.green('✓') : chalk.yellow('✗');
@@ -240,15 +242,15 @@ function showPluginDetail(p) {
240
242
 
241
243
  async function updateHandler(slug, opts) {
242
244
  if (!slug && !opts.all) {
243
- console.log(chalk.red('\n ❌ Plugin adı gerekli\n'));
244
- console.log(chalk.gray(' Kullanım: natureco plugins update <slug>'));
245
- console.log(chalk.gray(' Tümü: natureco plugins update --all\n'));
245
+ console.log(chalk.red(L('\n ❌ Plugin adı gerekli\n', '\n ❌ Plugin name required\n')));
246
+ console.log(chalk.gray(L(' Kullanım: natureco plugins update <slug>', ' Usage: natureco plugins update <slug>')));
247
+ console.log(chalk.gray(L(' Tümü: natureco plugins update --all\n', ' All: natureco plugins update --all\n')));
246
248
  process.exit(1);
247
249
  }
248
250
 
249
251
  if (opts.all) {
250
252
  const all = scanInstalled();
251
- console.log(chalk.cyan('\n Tüm pluginler güncelleniyor...\n'));
253
+ console.log(chalk.cyan(L('\n Tüm pluginler güncelleniyor...\n', '\n Updating all plugins...\n')));
252
254
  for (const p of all) {
253
255
  try {
254
256
  const result = await updatePlugin(p.slug);
@@ -261,27 +263,27 @@ async function updateHandler(slug, opts) {
261
263
  }
262
264
 
263
265
  if (opts.dryRun) {
264
- console.log(chalk.gray(`\n 📋 Kuru çalışma: "${slug}" güncellenecek\n`));
266
+ console.log(chalk.gray(`\n 📋 ${L('Kuru çalışma', 'Dry run')}: "${slug}" ${L('güncellenecek', 'will be updated')}\n`));
265
267
  return;
266
268
  }
267
269
 
268
270
  try {
269
271
  const result = await updatePlugin(slug);
270
- console.log(chalk.green(`\n ✓ Plugin güncellendi: ${result.name} → v${result.version}\n`));
272
+ console.log(chalk.green(`\n ✓ ${L('Plugin güncellendi', 'Plugin updated')}: ${result.name} → v${result.version}\n`));
271
273
  } catch (err) {
272
- console.log(chalk.red(`\n ❌ Güncelleme başarısız: ${err.message}\n`));
274
+ console.log(chalk.red(`\n ❌ ${L('Güncelleme başarısız', 'Update failed')}: ${err.message}\n`));
273
275
  process.exit(1);
274
276
  }
275
277
  }
276
278
 
277
279
  async function searchHandler(query, opts) {
278
280
  if (!query) {
279
- console.log(chalk.red('\n ❌ Arama sorgusu gerekli\n'));
280
- console.log(chalk.gray(' Kullanım: natureco plugins search <query>\n'));
281
+ console.log(chalk.red(L('\n ❌ Arama sorgusu gerekli\n', '\n ❌ Search query required\n')));
282
+ console.log(chalk.gray(L(' Kullanım: natureco plugins search <query>\n', ' Usage: natureco plugins search <query>\n')));
281
283
  process.exit(1);
282
284
  }
283
285
 
284
- console.log(chalk.gray(`\n "${query}" aranıyor...\n`));
286
+ console.log(chalk.gray(`\n "${query}" ${L('aranıyor...', 'searching...')}\n`));
285
287
 
286
288
  const results = [];
287
289
 
@@ -325,17 +327,17 @@ async function searchHandler(query, opts) {
325
327
  }
326
328
 
327
329
  if (results.length === 0) {
328
- console.log(chalk.yellow(` "${query}" için sonuç bulunamadı.\n`));
330
+ console.log(chalk.yellow(` "${query}" ${L('için sonuç bulunamadı.', '— no results found.')}\n`));
329
331
  return;
330
332
  }
331
333
 
332
- console.log(chalk.cyan(` ${results.length} sonuç\n`));
334
+ console.log(chalk.cyan(` ${results.length} ${L('sonuç', 'results')}\n`));
333
335
  results.slice(0, opts.limit).forEach(p => {
334
336
  const sourceIcon = p.source === 'clawhub' ? '🦞' : p.source === 'naturehub' ? '🌿' : '📋';
335
337
  console.log(` ${sourceIcon} ${chalk.white(p.name)} ${chalk.gray(`v${p.version}`)}`);
336
338
  if (p.description) console.log(chalk.gray(` ${p.description.slice(0, 80)}`));
337
339
  const installHint = p.source === 'clawhub' ? `clawhub:${p.id}` : p.source === 'naturehub' ? p.id : p.id;
338
- console.log(chalk.gray(` Yüklemek: natureco plugins install ${installHint}\n`));
340
+ console.log(chalk.gray(` ${L('Yüklemek', 'Install')}: natureco plugins install ${installHint}\n`));
339
341
  });
340
342
  }
341
343
 
@@ -343,10 +345,10 @@ function doctorHandler() {
343
345
  const list = scanInstalled();
344
346
  const registry = loadRegistry();
345
347
 
346
- console.log(chalk.cyan.bold('\n Plugin Tanılama\n'));
348
+ console.log(chalk.cyan.bold(L('\n Plugin Tanılama\n', '\n Plugin Diagnostics\n')));
347
349
 
348
350
  if (list.length === 0 && registry.plugins.length === 0) {
349
- console.log(chalk.gray(' Yüklü plugin yok.\n'));
351
+ console.log(chalk.gray(L(' Yüklü plugin yok.\n', ' No plugins installed.\n')));
350
352
  return;
351
353
  }
352
354
 
@@ -358,11 +360,11 @@ function doctorHandler() {
358
360
  const manifestErrors = validateManifest(p);
359
361
 
360
362
  if (!hasPackage) {
361
- console.log(chalk.yellow(` ⚠ ${p.name}: package.json eksik`));
363
+ console.log(chalk.yellow(` ⚠ ${p.name}: package.json ${L('eksik', 'missing')}`));
362
364
  issues++;
363
365
  }
364
366
  if (!hasEntry) {
365
- console.log(chalk.yellow(` ⚠ ${p.name}: ${p.entry || 'index.js'} bulunamadı`));
367
+ console.log(chalk.yellow(` ⚠ ${p.name}: ${p.entry || 'index.js'} ${L('bulunamadı', 'not found')}`));
366
368
  issues++;
367
369
  }
368
370
  if (manifestErrors.length > 0) {
@@ -371,21 +373,21 @@ function doctorHandler() {
371
373
  }
372
374
 
373
375
  if (hasPackage && hasEntry && manifestErrors.length === 0) {
374
- console.log(` ${chalk.green('✓')} ${p.name} v${p.version} — sağlıklı`);
376
+ console.log(` ${chalk.green('✓')} ${p.name} v${p.version} — ${L('sağlıklı', 'healthy')}`);
375
377
  }
376
378
  });
377
379
 
378
380
  registry.plugins.forEach(r => {
379
381
  if (!list.some(p => p.slug === r.id)) {
380
- console.log(chalk.yellow(` ⚠ Kayıtlı ama diskte yok: ${r.id} (kayıttan temizlenecek)`));
382
+ console.log(chalk.yellow(` ⚠ ${L('Kayıtlı ama diskte yok', 'Registered but not on disk')}: ${r.id} (${L('kayıttan temizlenecek', 'will be pruned from registry')})`));
381
383
  issues++;
382
384
  }
383
385
  });
384
386
 
385
387
  if (issues === 0 && list.length > 0) {
386
- console.log(chalk.green(' ✓ Tüm pluginler sağlıklı.\n'));
388
+ console.log(chalk.green(L(' ✓ Tüm pluginler sağlıklı.\n', ' ✓ All plugins healthy.\n')));
387
389
  } else if (issues > 0) {
388
- console.log(chalk.yellow(`\n ⚠ ${issues} sorun bulundu.\n`));
390
+ console.log(chalk.yellow(`\n ⚠ ${issues} ${L('sorun bulundu.', 'issue(s) found.')}\n`));
389
391
  }
390
392
  console.log('');
391
393
  }
@@ -398,13 +400,13 @@ function registryHandler(opts) {
398
400
  return;
399
401
  }
400
402
 
401
- console.log(chalk.cyan.bold('\n Plugin Kayıt Defteri\n'));
402
- console.log(chalk.gray(' Versiyon : ') + chalk.white(`v${registry.version}`));
403
- console.log(chalk.gray(' Güncelleme: ') + chalk.white(registry.updatedAt || 'hiç'));
404
- console.log(chalk.gray(' Kayıtlı : ') + chalk.white(`${registry.plugins.length} plugin`));
403
+ console.log(chalk.cyan.bold(L('\n Plugin Kayıt Defteri\n', '\n Plugin Registry\n')));
404
+ console.log(chalk.gray(L(' Versiyon : ', ' Version : ')) + chalk.white(`v${registry.version}`));
405
+ console.log(chalk.gray(L(' Güncelleme: ', ' Updated : ')) + chalk.white(registry.updatedAt || L('hiç', 'never')));
406
+ console.log(chalk.gray(L(' Kayıtlı : ', ' Registered: ')) + chalk.white(`${registry.plugins.length} plugin`));
405
407
 
406
408
  if (registry.plugins.length > 0) {
407
- console.log(chalk.cyan('\n Kayıtlı Pluginler\n'));
409
+ console.log(chalk.cyan(L('\n Kayıtlı Pluginler\n', '\n Registered Plugins\n')));
408
410
  registry.plugins.forEach(p => {
409
411
  const installed = scanInstalled().some(s => s.slug === p.id) ? chalk.green('✓') : chalk.yellow('✗');
410
412
  console.log(` ${installed} ${chalk.white(p.name || p.id)} ${chalk.gray(`v${p.version} [${p.source}]`)}`);
@@ -1,4 +1,6 @@
1
1
  const chalk = require('chalk');
2
+ const { getLang: _gl } = require('../utils/i18n');
3
+ const L = (tr, en) => (_gl() === 'en' ? en : tr);
2
4
  const tui = require('../utils/tui');
3
5
  const path = require('path');
4
6
  const fs = require('fs');
@@ -20,7 +22,7 @@ async function skills(args) {
20
22
  if (action === 'install') {
21
23
  const slug = params[0];
22
24
  if (!slug) {
23
- console.log(chalk.red('\n❌ Kullanım: natureco skills install <slug>\n'));
25
+ console.log(chalk.red(L('\n❌ Kullanım: natureco skills install <slug>\n', '\n❌ Usage: natureco skills install <slug>\n')));
24
26
  process.exit(1);
25
27
  }
26
28
  await installSkillCommand(slug);
@@ -30,7 +32,7 @@ async function skills(args) {
30
32
  if (action === 'remove') {
31
33
  const slug = params[0];
32
34
  if (!slug) {
33
- console.log(chalk.red('\n❌ Kullanım: natureco skills remove <slug>\n'));
35
+ console.log(chalk.red(L('\n❌ Kullanım: natureco skills remove <slug>\n', '\n❌ Usage: natureco skills remove <slug>\n')));
34
36
  process.exit(1);
35
37
  }
36
38
  await removeSkillCommand(slug);
@@ -42,7 +44,7 @@ async function skills(args) {
42
44
  if (flag === '--all') {
43
45
  await updateAllSkillsCommand();
44
46
  } else {
45
- console.log(chalk.red('\n❌ Kullanım: natureco skills update --all\n'));
47
+ console.log(chalk.red(L('\n❌ Kullanım: natureco skills update --all\n', '\n❌ Usage: natureco skills update --all\n')));
46
48
  process.exit(1);
47
49
  }
48
50
  return;
@@ -51,7 +53,7 @@ async function skills(args) {
51
53
  if (action === 'create') {
52
54
  const name = params[0];
53
55
  if (!name) {
54
- console.log(chalk.red('\n❌ Kullanım: natureco skills create <ad>\n'));
56
+ console.log(chalk.red(L('\n❌ Kullanım: natureco skills create <ad>\n', '\n❌ Usage: natureco skills create <name>\n')));
55
57
  process.exit(1);
56
58
  }
57
59
  await createSkillCommand(name);
@@ -88,7 +90,7 @@ async function skills(args) {
88
90
  if (action === 'accept') {
89
91
  const proposalId = params[0];
90
92
  if (!proposalId) {
91
- console.log(chalk.red('\n❌ Kullanım: natureco skills accept <proposal-id>\n'));
93
+ console.log(chalk.red(L('\n❌ Kullanım: natureco skills accept <proposal-id>\n', '\n❌ Usage: natureco skills accept <proposal-id>\n')));
92
94
  process.exit(1);
93
95
  }
94
96
  await acceptProposalCommand(proposalId);
@@ -98,7 +100,7 @@ async function skills(args) {
98
100
  if (action === 'reject') {
99
101
  const proposalId = params[0];
100
102
  if (!proposalId) {
101
- console.log(chalk.red('\n❌ Kullanım: natureco skills reject <proposal-id>\n'));
103
+ console.log(chalk.red(L('\n❌ Kullanım: natureco skills reject <proposal-id>\n', '\n❌ Usage: natureco skills reject <proposal-id>\n')));
102
104
  process.exit(1);
103
105
  }
104
106
  detector.rejectProposal(proposalId);
@@ -108,7 +110,7 @@ async function skills(args) {
108
110
 
109
111
  if (action === 'forget') {
110
112
  detector.reset();
111
- console.log(chalk.yellow('\n🧹 Tüm pattern hafızası ve proposal\'lar silindi.\n'));
113
+ console.log(chalk.yellow(L('\n🧹 Tüm pattern hafızası ve proposal\'lar silindi.\n', '\n🧹 All pattern memory and proposals cleared.\n')));
112
114
  return;
113
115
  }
114
116
 
@@ -120,27 +122,27 @@ async function skills(args) {
120
122
 
121
123
  if (action === 'install-mp') {
122
124
  const skillName = params[0];
123
- if (!skillName) { console.log(chalk.red('\n❌ Kullanım: natureco skills install-mp <name>\n')); process.exit(1); }
125
+ if (!skillName) { console.log(chalk.red(L('\n❌ Kullanım: natureco skills install-mp <name>\n', '\n❌ Usage: natureco skills install-mp <name>\n'))); process.exit(1); }
124
126
  await installFromMarketplace(skillName);
125
127
  return;
126
128
  }
127
129
 
128
130
  if (action === 'search-mp') {
129
131
  const query = params[0];
130
- if (!query) { console.log(chalk.red('\n❌ Kullanım: natureco skills search-mp <query>\n')); process.exit(1); }
132
+ if (!query) { console.log(chalk.red(L('\n❌ Kullanım: natureco skills search-mp <query>\n', '\n❌ Usage: natureco skills search-mp <query>\n'))); process.exit(1); }
131
133
  await searchMarketplace(query);
132
134
  return;
133
135
  }
134
136
 
135
137
  if (action === 'remove-mp' || action === 'uninstall-mp') {
136
138
  const skillName = params[0];
137
- if (!skillName) { console.log(chalk.red('\n❌ Kullanım: natureco skills remove-mp <name>\n')); process.exit(1); }
139
+ if (!skillName) { console.log(chalk.red(L('\n❌ Kullanım: natureco skills remove-mp <name>\n', '\n❌ Usage: natureco skills remove-mp <name>\n'))); process.exit(1); }
138
140
  uninstallMarketplace(skillName);
139
141
  return;
140
142
  }
141
143
 
142
- console.log(chalk.red(`\n❌ Geçersiz action: ${action}\n`));
143
- console.log(chalk.gray('Kullanım: natureco skills [list|install|remove|update|create|search|browse|info|check|suggest|accept|reject|forget|marketplace|install-mp|search-mp|remove-mp]\n'));
144
+ console.log(chalk.red(`\n❌ ${L('Geçersiz action', 'Invalid action')}: ${action}\n`));
145
+ console.log(chalk.gray(L('Kullanım: natureco skills [list|install|remove|update|create|search|browse|info|check|suggest|accept|reject|forget|marketplace|install-mp|search-mp|remove-mp]\n', 'Usage: natureco skills [list|install|remove|update|create|search|browse|info|check|suggest|accept|reject|forget|marketplace|install-mp|search-mp|remove-mp]\n')));
144
146
  process.exit(1);
145
147
  }
146
148
 
@@ -157,7 +159,7 @@ async function listMarketplace() {
157
159
  for (const s of result.skills) {
158
160
  console.log(' ' + chalk.cyan(s.name.padEnd(22)) + chalk.gray((s.description || '').slice(0, 50)));
159
161
  }
160
- console.log('\n ' + chalk.gray('Kur: ') + chalk.cyan('natureco skills install-mp <name>'));
162
+ console.log('\n ' + chalk.gray(L('Kur: ', 'Install: ')) + chalk.cyan('natureco skills install-mp <name>'));
161
163
  console.log('');
162
164
  }
163
165
  }
@@ -169,7 +171,7 @@ async function installFromMarketplace(skillName) {
169
171
  if (!mp) return;
170
172
  const result = await mp.execute({ action: 'install', skillName });
171
173
  if (result.success) {
172
- console.log(chalk.green('\n ✓ ' + skillName + ' kuruldu: ' + result.path + '\n'));
174
+ console.log(chalk.green('\n ✓ ' + skillName + L(' kuruldu: ', ' installed: ') + result.path + '\n'));
173
175
  } else {
174
176
  console.log(chalk.red('\n ✗ ' + result.error + '\n'));
175
177
  }
@@ -182,7 +184,7 @@ async function searchMarketplace(query) {
182
184
  if (!mp) return;
183
185
  const result = await mp.execute({ action: 'search', query });
184
186
  if (result.success) {
185
- console.log(chalk.cyan.bold('\n 🔍 "' + query + '" icin sonuclar\n'));
187
+ console.log(chalk.cyan.bold('\n 🔍 "' + query + L('" icin sonuclar\n', '" results\n')));
186
188
  for (const s of result.results) {
187
189
  console.log(' ' + chalk.cyan(s.name.padEnd(22)) + chalk.gray((s.description || '').slice(0, 50)));
188
190
  }
@@ -194,9 +196,9 @@ function uninstallMarketplace(skillName) {
194
196
  const skillDir = path.join(os.homedir(), '.natureco', 'skills', skillName);
195
197
  if (fs.existsSync(skillDir)) {
196
198
  fs.rmSync(skillDir, { recursive: true });
197
- console.log(chalk.green('\n ✓ ' + skillName + ' kaldirildi\n'));
199
+ console.log(chalk.green('\n ✓ ' + skillName + L(' kaldirildi\n', ' removed\n')));
198
200
  } else {
199
- console.log(chalk.yellow('\n ' + skillName + ' zaten yok\n'));
201
+ console.log(chalk.yellow('\n ' + skillName + L(' zaten yok\n', ' already gone\n')));
200
202
  }
201
203
  }
202
204
 
@@ -206,41 +208,41 @@ async function listSkills() {
206
208
  const userCount = allSkills.filter(s => s.source === 'user').length;
207
209
 
208
210
  console.log(chalk.gray('\n ' + '─'.repeat(48)));
209
- console.log(chalk.cyan.bold('\n Yüklü Skill\'ler') + chalk.gray(` — toplam ${allSkills.length} (${builtinCount} yerleşik${userCount ? `, ${userCount} kişisel` : ''})`));
210
- console.log(chalk.gray(' Yerleşikler: ~/.natureco/skills-builtin · Kişiseller: ~/.natureco/skills · Araçlar: ~/.natureco/tools\n'));
211
+ console.log(chalk.cyan.bold(L('\n Yüklü Skill\'ler', '\n Installed Skills')) + chalk.gray(` — ${L('toplam', 'total')} ${allSkills.length} (${builtinCount} ${L('yerleşik', 'built-in')}${userCount ? `, ${userCount} ${L('kişisel', 'personal')}` : ''})`));
212
+ console.log(chalk.gray(L(' Yerleşikler: ~/.natureco/skills-builtin · Kişiseller: ~/.natureco/skills · Araçlar: ~/.natureco/tools\n', ' Built-in: ~/.natureco/skills-builtin · Personal: ~/.natureco/skills · Tools: ~/.natureco/tools\n')));
211
213
 
212
214
  if (allSkills.length === 0) {
213
215
  // Yerleşikler pakette gelir; bu duruma normalde ancak paket bozulursa düşülür
214
- console.log(chalk.red(' ⚠ Hiç skill bulunamadı — kurulum bozuk olabilir.'));
215
- console.log(chalk.gray(' Onarmak için: ') + chalk.cyan('npm install -g natureco-cli') + chalk.gray(' (yeniden kurar)\n'));
216
+ console.log(chalk.red(L(' ⚠ Hiç skill bulunamadı — kurulum bozuk olabilir.', ' ⚠ No skills found — installation may be broken.')));
217
+ console.log(chalk.gray(L(' Onarmak için: ', ' To repair: ')) + chalk.cyan('npm install -g natureco-cli') + chalk.gray(L(' (yeniden kurar)\n', ' (reinstalls)\n')));
216
218
  return;
217
219
  }
218
220
 
219
221
  allSkills.forEach((skill, index) => {
220
- const sourceLabel = skill.source === 'builtin' ? chalk.blue('[yerleşik]') :
221
- skill.source === 'user' ? chalk.cyan('[kişisel]') :
222
- chalk.magenta('[proje]');
222
+ const sourceLabel = skill.source === 'builtin' ? chalk.blue(L('[yerleşik]', '[built-in]')) :
223
+ skill.source === 'user' ? chalk.cyan(L('[kişisel]', '[personal]')) :
224
+ chalk.magenta(L('[proje]', '[project]'));
223
225
  console.log(chalk.white(` ${index + 1}. ${skill.name} `) + sourceLabel);
224
226
  console.log(chalk.gray(` ${skill.description}`));
225
227
  if (skill.metadata?.requires?.bins) {
226
- console.log(chalk.gray(` Gerekli: ${skill.metadata.requires.bins.join(', ')}`));
228
+ console.log(chalk.gray(` ${L('Gerekli', 'Required')}: ${skill.metadata.requires.bins.join(', ')}`));
227
229
  }
228
230
  console.log('');
229
231
  });
230
232
 
231
233
  console.log(chalk.gray(' ' + '─'.repeat(48)));
232
- console.log(chalk.gray(` Toplam: ${allSkills.length} skill`));
233
- console.log(chalk.gray(' Kaldırmak için: ') + chalk.cyan('natureco skills remove <slug>\n'));
234
+ console.log(chalk.gray(` ${L('Toplam', 'Total')}: ${allSkills.length} skill`));
235
+ console.log(chalk.gray(L(' Kaldırmak için: ', ' To remove: ')) + chalk.cyan('natureco skills remove <slug>\n'));
234
236
  }
235
237
 
236
238
  async function installSkillCommand(slug) {
237
- console.log(chalk.yellow(`\n⏳ "${slug}" skill'i yükleniyor...\n`));
239
+ console.log(chalk.yellow(`\n⏳ "${slug}" ${L("skill'i yükleniyor...", 'installing...')}\n`));
238
240
 
239
241
  try {
240
242
  await installSkill(slug);
241
- console.log(chalk.green(`✅ "${slug}" başarıyla yüklendi!\n`));
243
+ console.log(chalk.green(`✅ "${slug}" ${L('başarıyla yüklendi', 'installed successfully')}!\n`));
242
244
  } catch (err) {
243
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
245
+ console.log(chalk.red(`\n❌ ${L('Hata', 'Error')}: ${err.message}\n`));
244
246
  process.exit(1);
245
247
  }
246
248
  }
@@ -250,53 +252,53 @@ async function removeSkillCommand(slug) {
250
252
  {
251
253
  type: 'confirm',
252
254
  name: 'confirm',
253
- message: `"${slug}" skill'ini silmek istediğinizden emin misiniz?`,
255
+ message: `"${slug}" ${L("skill'ini silmek istediğinizden emin misiniz?", '— delete this skill?')}`,
254
256
  default: false,
255
257
  },
256
258
  ]);
257
259
 
258
260
  if (!confirm) {
259
- console.log(chalk.gray('\nİptal edildi.\n'));
261
+ console.log(chalk.gray(L('\nİptal edildi.\n', '\nCancelled.\n')));
260
262
  return;
261
263
  }
262
264
 
263
265
  try {
264
266
  removeSkill(slug);
265
- console.log(chalk.green(`\n✅ "${slug}" silindi.\n`));
267
+ console.log(chalk.green(`\n✅ "${slug}" ${L('silindi.', 'deleted.')}\n`));
266
268
  } catch (err) {
267
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
269
+ console.log(chalk.red(`\n❌ ${L('Hata', 'Error')}: ${err.message}\n`));
268
270
  process.exit(1);
269
271
  }
270
272
  }
271
273
 
272
274
  async function updateAllSkillsCommand() {
273
- console.log(chalk.yellow('\n⏳ Tüm skill\'ler güncelleniyor...\n'));
275
+ console.log(chalk.yellow(L('\n⏳ Tüm skill\'ler güncelleniyor...\n', '\n⏳ Updating all skills...\n')));
274
276
 
275
277
  try {
276
278
  const updated = await updateAllSkills();
277
279
  if (updated.length === 0) {
278
- console.log(chalk.gray('Güncellenecek skill bulunamadı.\n'));
280
+ console.log(chalk.gray(L('Güncellenecek skill bulunamadı.\n', 'No skills to update.\n')));
279
281
  } else {
280
- console.log(chalk.green(`✅ ${updated.length} skill güncellendi:\n`));
282
+ console.log(chalk.green(`✅ ${updated.length} skill ${L('güncellendi', 'updated')}:\n`));
281
283
  updated.forEach(s => console.log(chalk.cyan(` - ${s}`)));
282
284
  console.log('');
283
285
  }
284
286
  } catch (err) {
285
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
287
+ console.log(chalk.red(`\n❌ ${L('Hata', 'Error')}: ${err.message}\n`));
286
288
  process.exit(1);
287
289
  }
288
290
  }
289
291
 
290
292
  async function createSkillCommand(name) {
291
- console.log(chalk.yellow(`\n⏳ "${name}" skill şablonu oluşturuluyor...\n`));
293
+ console.log(chalk.yellow(`\n⏳ "${name}" skill ${L('şablonu oluşturuluyor...', 'template being created...')}\n`));
292
294
 
293
295
  try {
294
296
  const skillPath = createSkillTemplate(name);
295
- console.log(chalk.green(`✅ Skill şablonu oluşturuldu:\n`));
297
+ console.log(chalk.green(`✅ ${L('Skill şablonu oluşturuldu', 'Skill template created')}:\n`));
296
298
  console.log(chalk.cyan(` ${skillPath}\n`));
297
- console.log(chalk.gray('SKILL.md dosyasını düzenleyerek skill\'i özelleştirin.\n'));
299
+ console.log(chalk.gray(L('SKILL.md dosyasını düzenleyerek skill\'i özelleştirin.\n', 'Customize the skill by editing SKILL.md.\n')));
298
300
  } catch (err) {
299
- console.log(chalk.red(`\n❌ Hata: ${err.message}\n`));
301
+ console.log(chalk.red(`\n❌ ${L('Hata', 'Error')}: ${err.message}\n`));
300
302
  process.exit(1);
301
303
  }
302
304
  }
@@ -305,22 +307,22 @@ async function searchSkillsCommand(query) {
305
307
  if (!query || query.trim().length === 0) {
306
308
  try {
307
309
  const popularSkills = await getPopularSkills();
308
- console.log(chalk.yellow('\nPopüler Skill\'ler:\n'));
310
+ console.log(chalk.yellow(L('\nPopüler Skill\'ler:\n', '\nPopular Skills:\n')));
309
311
  popularSkills.forEach(skill => {
310
312
  console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description));
311
313
  });
312
314
  } catch (err) {
313
- console.log(chalk.red(`\n ❌ Popüler skill'ler alınamadı: ${err.message}\n`));
315
+ console.log(chalk.red(`\n ❌ ${L("Popüler skill'ler alınamadı", 'Could not fetch popular skills')}: ${err.message}\n`));
314
316
  }
315
317
  console.log('');
316
- console.log(chalk.gray('Kurmak için: '), chalk.cyan('natureco skills install <slug>'));
317
- console.log(chalk.gray('Örnek: '), chalk.cyan('natureco skills install github'));
318
+ console.log(chalk.gray(L('Kurmak için: ', 'To install: ')), chalk.cyan('natureco skills install <slug>'));
319
+ console.log(chalk.gray(L('Örnek: ', 'Example: ')), chalk.cyan('natureco skills install github'));
318
320
  console.log(chalk.gray('ClawHub: '), chalk.cyan('natureco skills install clawhub:github'));
319
321
  console.log('');
320
322
  return;
321
323
  }
322
324
 
323
- console.log(chalk.yellow(`\n⏳ "${query}" aranıyor...\n`));
325
+ console.log(chalk.yellow(`\n⏳ "${query}" ${L('aranıyor...', 'searching...')}\n`));
324
326
 
325
327
  try {
326
328
  // ClawHub search API
@@ -328,30 +330,30 @@ async function searchSkillsCommand(query) {
328
330
  const response = await fetch(searchUrl);
329
331
 
330
332
  if (!response.ok) {
331
- throw new SkillError('ClawHub API\'ye erişilemedi', 'fetch', `https://clawhub.ai/api/skills?q=${encodeURIComponent(query)}`);
333
+ throw new SkillError(L('ClawHub API\'ye erişilemedi', 'Could not reach the ClawHub API'), 'fetch', `https://clawhub.ai/api/skills?q=${encodeURIComponent(query)}`);
332
334
  }
333
335
 
334
336
  let data;
335
337
  try {
336
338
  data = await response.json();
337
339
  } catch {
338
- throw new SkillError('ClawHub geçersiz yanıt döndü (JSON bekleniyordu)', 'parse', searchUrl);
340
+ throw new SkillError(L('ClawHub geçersiz yanıt döndü (JSON bekleniyordu)', 'ClawHub returned an invalid response (JSON expected)'), 'parse', searchUrl);
339
341
  }
340
342
  const results = data.skills || [];
341
343
 
342
344
  if (results.length === 0) {
343
- console.log(chalk.yellow(`"${query}" için sonuç bulunamadı.\n`));
345
+ console.log(chalk.yellow(`"${query}" ${L('için sonuç bulunamadı.', '— no results found.')}\n`));
344
346
  return;
345
347
  }
346
348
 
347
- console.log(chalk.yellow(`"${query}" için ${results.length} sonuç:\n`));
349
+ console.log(chalk.yellow(`"${query}" ${L('için', 'for')} ${results.length} ${L('sonuç', 'results')}:\n`));
348
350
  results.forEach(skill => {
349
- console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description || 'Açıklama yok'));
350
- console.log(chalk.gray(` Kurmak için: natureco skills install clawhub:${skill.slug}`));
351
+ console.log(chalk.cyan(` ${skill.name.padEnd(15)}`), chalk.gray(skill.description || L('Açıklama yok', 'No description')));
352
+ console.log(chalk.gray(` ${L('Kurmak için', 'To install')}: natureco skills install clawhub:${skill.slug}`));
351
353
  });
352
354
  console.log('');
353
355
  } catch (err) {
354
- console.log(chalk.red(`\n ❌ Arama başarısız: ${err.message}\n`));
356
+ console.log(chalk.red(`\n ❌ ${L('Arama başarısız', 'Search failed')}: ${err.message}\n`));
355
357
  }
356
358
  }
357
359
 
@@ -360,18 +362,18 @@ async function browseSkillsCommand() {
360
362
  try {
361
363
  popularSkills = await getPopularSkills();
362
364
  } catch (err) {
363
- console.log(chalk.red(`\n ❌ Popüler skill'ler alınamadı: ${err.message}\n`));
365
+ console.log(chalk.red(`\n ❌ ${L("Popüler skill'ler alınamadı", 'Could not fetch popular skills')}: ${err.message}\n`));
364
366
  return;
365
367
  }
366
368
 
367
- console.log(chalk.green.bold('\n╭─ Popüler Skill\'ler ─╮\n'));
369
+ console.log(chalk.green.bold(L('\n╭─ Popüler Skill\'ler ─╮\n', '\n╭─ Popular Skills ─╮\n')));
368
370
 
369
371
  process.stdin.resume();
370
372
  const { selectedSkills } = await inquirer.prompt([
371
373
  {
372
374
  type: 'checkbox',
373
375
  name: 'selectedSkills',
374
- message: 'Kurmak istediğiniz skill\'leri seçin:',
376
+ message: L('Kurmak istediğiniz skill\'leri seçin:', 'Select the skills you want to install:'),
375
377
  choices: popularSkills.map(skill => ({
376
378
  name: `${skill.name} - ${skill.description}`,
377
379
  value: skill.source === 'clawhub' ? `clawhub:${skill.slug}` : skill.slug,
@@ -381,22 +383,22 @@ async function browseSkillsCommand() {
381
383
  process.stdin.pause();
382
384
 
383
385
  if (selectedSkills.length === 0) {
384
- console.log(chalk.gray('\nHiçbir skill seçilmedi.\n'));
386
+ console.log(chalk.gray(L('\nHiçbir skill seçilmedi.\n', '\nNo skills selected.\n')));
385
387
  return;
386
388
  }
387
389
 
388
- console.log(chalk.yellow(`\n⏳ ${selectedSkills.length} skill kuruluyor...\n`));
390
+ console.log(chalk.yellow(`\n⏳ ${selectedSkills.length} skill ${L('kuruluyor...', 'installing...')}\n`));
389
391
 
390
392
  for (const slug of selectedSkills) {
391
393
  try {
392
394
  await installSkill(slug);
393
- console.log(chalk.green(`✅ ${slug} kuruldu`));
395
+ console.log(chalk.green(`✅ ${slug} ${L('kuruldu', 'installed')}`));
394
396
  } catch (err) {
395
- console.log(chalk.red(`❌ ${slug} kurulamadı: ${err.message}`));
397
+ console.log(chalk.red(`❌ ${slug} ${L('kurulamadı', 'could not be installed')}: ${err.message}`));
396
398
  }
397
399
  }
398
400
 
399
- console.log(chalk.green('\n✅ Kurulum tamamlandı!\n'));
401
+ console.log(chalk.green(L('\n✅ Kurulum tamamlandı!\n', '\n✅ Installation complete!\n')));
400
402
  }
401
403
 
402
404
  async function infoSkill(slug) {
@@ -457,11 +459,11 @@ async function listProposals() {
457
459
 
458
460
  console.log('\n' + tui.styled(' 🧠 Self-Evolving Skill Proposals', { color: tui.PALETTE.primary, bold: true }));
459
461
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
460
- console.log(' ' + tui.C.muted('Kullanımın tekrar eden pattern\'lerinden otomatik skill önerileri.\n'));
462
+ console.log(' ' + tui.C.muted(L('Kullanımın tekrar eden pattern\'lerinden otomatik skill önerileri.\n', 'Automatic skill suggestions from your recurring usage patterns.\n')));
461
463
 
462
464
  if (pending.length === 0) {
463
- console.log(' ' + tui.C.muted('Şu an öneri yok. Daha fazla tool çağrısı yap, sistem öğrensin.'));
464
- console.log(' ' + tui.C.muted('Pattern\'leri sıfırla: ') + tui.C.brand('natureco skills forget\n'));
465
+ console.log(' ' + tui.C.muted(L('Şu an öneri yok. Daha fazla tool çağrısı yap, sistem öğrensin.', 'No suggestions right now. Make more tool calls so the system can learn.')));
466
+ console.log(' ' + tui.C.muted(L('Pattern\'leri sıfırla: ', 'Reset patterns: ')) + tui.C.brand('natureco skills forget\n'));
465
467
  return;
466
468
  }
467
469
 
@@ -474,26 +476,26 @@ async function listProposals() {
474
476
  }));
475
477
 
476
478
  console.log(tui.table(rows, [
477
- { key: 'name', label: 'Öneri', minWidth: 25, render: r => tui.styled(r.name, { color: tui.PALETTE.primary, bold: true }) },
478
- { key: 'count', label: 'Tekrar', minWidth: 7, render: r => tui.styled(r.count, { color: tui.PALETTE.accent, bold: true }) },
479
+ { key: 'name', label: L('Öneri', 'Suggestion'), minWidth: 25, render: r => tui.styled(r.name, { color: tui.PALETTE.primary, bold: true }) },
480
+ { key: 'count', label: L('Tekrar', 'Repeats'), minWidth: 7, render: r => tui.styled(r.count, { color: tui.PALETTE.accent, bold: true }) },
479
481
  { key: 'pattern', label: 'Pattern', minWidth: 30, render: r => tui.C.muted(r.pattern) },
480
- { key: 'first', label: 'İlk', minWidth: 18, render: r => tui.C.muted(r.first) },
482
+ { key: 'first', label: L('İlk', 'First'), minWidth: 18, render: r => tui.C.muted(r.first) },
481
483
  ], { borderStyle: 'round', zebra: true }));
482
484
 
483
- console.log('\n ' + tui.C.muted('Kabul et: ') + tui.C.brand('natureco skills accept <id>'));
484
- console.log(' ' + tui.C.muted('Reddet: ') + tui.C.brand('natureco skills reject <id>\n'));
485
+ console.log('\n ' + tui.C.muted(L('Kabul et: ', 'Accept: ')) + tui.C.brand('natureco skills accept <id>'));
486
+ console.log(' ' + tui.C.muted(L('Reddet: ', 'Reject: ')) + tui.C.brand('natureco skills reject <id>\n'));
485
487
  }
486
488
 
487
489
  async function acceptProposalCommand(proposalId) {
488
- console.log(chalk.yellow('\n⏳ Skill oluşturuluyor...\n'));
490
+ console.log(chalk.yellow(L('\n⏳ Skill oluşturuluyor...\n', '\n⏳ Creating skill...\n')));
489
491
  const result = detector.acceptProposal(proposalId);
490
492
  if (!result.success) {
491
493
  console.log(chalk.red(`\n❌ ${result.reason}\n`));
492
494
  process.exit(1);
493
495
  }
494
- console.log(chalk.green(`✅ Yeni skill oluşturuldu: ${result.skillName}\n`));
495
- console.log(chalk.gray(` Yol: ${result.path}\n`));
496
- console.log(chalk.gray(' SKILL.md dosyasını düzenleyerek özelleştirebilirsin.\n'));
496
+ console.log(chalk.green(`✅ ${L('Yeni skill oluşturuldu', 'New skill created')}: ${result.skillName}\n`));
497
+ console.log(chalk.gray(` ${L('Yol', 'Path')}: ${result.path}\n`));
498
+ console.log(chalk.gray(L(' SKILL.md dosyasını düzenleyerek özelleştirebilirsin.\n', ' You can customize it by editing SKILL.md.\n')));
497
499
  audit.log(audit.ACTIONS.SKILL_AUTO, { proposalId, skillName: result.skillName });
498
500
  }
499
501