natureco-cli 5.58.0 → 5.60.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.
@@ -12,6 +12,8 @@
12
12
  */
13
13
 
14
14
  const chalk = require('chalk');
15
+ const { getLang: _gl } = require('../utils/i18n');
16
+ const L = (tr, en) => (_gl() === 'en' ? en : tr);
15
17
  const tui = require('../utils/tui');
16
18
  const https = require('https');
17
19
  const http = require('http');
@@ -111,28 +113,28 @@ function extractMeta(html) {
111
113
  async function cmdAudit(args) {
112
114
  const targetUrl = args[0];
113
115
  if (!targetUrl) {
114
- console.log(tui.C.red('\n Kullanım: natureco seo audit <url>\n'));
116
+ console.log(tui.C.red(L('\n Kullanım: natureco seo audit <url>\n', '\n Usage: natureco seo audit <url>\n')));
115
117
  return;
116
118
  }
117
119
 
118
- console.log('\n' + tui.styled(` 🔍 SEO Denetimi: ${targetUrl}`, { color: tui.PALETTE.primary, bold: true }));
120
+ console.log('\n' + tui.styled(` 🔍 ${L('SEO Denetimi', 'SEO Audit')}: ${targetUrl}`, { color: tui.PALETTE.primary, bold: true }));
119
121
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
120
122
 
121
123
  // Spinner göster
122
- const spinner = new tui.Spinner('Sayfa yükleniyor', { style: 'dots' }).start();
124
+ const spinner = new tui.Spinner(L('Sayfa yükleniyor', 'Loading page'), { style: 'dots' }).start();
123
125
  let response;
124
126
  try {
125
127
  response = await fetchUrl(targetUrl);
126
128
  } catch (e) {
127
- spinner.stop(tui.C.red('✗ Hata: ' + e.message));
129
+ spinner.stop(tui.C.red(L('✗ Hata: ', '✗ Error: ') + e.message));
128
130
  console.log('');
129
131
  return;
130
132
  }
131
133
 
132
134
  if (response.statusCode !== 200) {
133
- spinner.stop(tui.C.yellow(`⚠ HTTP ${response.statusCode} yanıtı alındı`));
135
+ spinner.stop(tui.C.yellow(`⚠ HTTP ${response.statusCode} ${L('yanıtı alındı', 'response received')}`));
134
136
  } else {
135
- spinner.stop(tui.C.green('✓ Sayfa yüklendi'));
137
+ spinner.stop(tui.C.green(L('✓ Sayfa yüklendi', '✓ Page loaded')));
136
138
  }
137
139
  console.log('');
138
140
 
@@ -142,80 +144,80 @@ async function cmdAudit(args) {
142
144
 
143
145
  // Title
144
146
  if (!meta.title) {
145
- issues.push({ severity: 'high', msg: 'Title tag eksik' });
147
+ issues.push({ severity: 'high', msg: L('Title tag eksik', 'Title tag missing') });
146
148
  } else if (meta.title.length < 30) {
147
- issues.push({ severity: 'medium', msg: `Title çok kısa (${meta.title.length} karakter, ideal: 50-60)` });
149
+ issues.push({ severity: 'medium', msg: `${L('Title çok kısa', 'Title too short')} (${meta.title.length} ${L('karakter', 'chars')}, ideal: 50-60)` });
148
150
  } else if (meta.title.length > 60) {
149
- issues.push({ severity: 'medium', msg: `Title çok uzun (${meta.title.length} karakter, ideal: 50-60)` });
151
+ issues.push({ severity: 'medium', msg: `${L('Title çok uzun', 'Title too long')} (${meta.title.length} ${L('karakter', 'chars')}, ideal: 50-60)` });
150
152
  } else {
151
- passes.push(`Title (${meta.title.length} karakter)`);
153
+ passes.push(`Title (${meta.title.length} ${L('karakter', 'chars')})`);
152
154
  }
153
155
 
154
156
  // Description
155
157
  if (!meta.description) {
156
- issues.push({ severity: 'high', msg: 'Meta description eksik' });
158
+ issues.push({ severity: 'high', msg: L('Meta description eksik', 'Meta description missing') });
157
159
  } else if (meta.description.length < 120) {
158
- issues.push({ severity: 'low', msg: `Description kısa (${meta.description.length} karakter, ideal: 150-160)` });
160
+ issues.push({ severity: 'low', msg: `${L('Description kısa', 'Description short')} (${meta.description.length} ${L('karakter', 'chars')}, ideal: 150-160)` });
159
161
  } else if (meta.description.length > 160) {
160
- issues.push({ severity: 'low', msg: `Description uzun (${meta.description.length} karakter, ideal: 150-160)` });
162
+ issues.push({ severity: 'low', msg: `${L('Description uzun', 'Description long')} (${meta.description.length} ${L('karakter', 'chars')}, ideal: 150-160)` });
161
163
  } else {
162
- passes.push(`Description (${meta.description.length} karakter)`);
164
+ passes.push(`Description (${meta.description.length} ${L('karakter', 'chars')})`);
163
165
  }
164
166
 
165
167
  // Canonical
166
- if (meta.canonical) passes.push('Canonical URL var');
167
- else issues.push({ severity: 'medium', msg: 'Canonical URL tanımlı değil' });
168
+ if (meta.canonical) passes.push(L('Canonical URL var', 'Canonical URL present'));
169
+ else issues.push({ severity: 'medium', msg: L('Canonical URL tanımlı değil', 'Canonical URL not set') });
168
170
 
169
171
  // OG
170
172
  if (Object.keys(meta.og).length > 0) passes.push(`Open Graph (${Object.keys(meta.og).length} tag)`);
171
- else issues.push({ severity: 'low', msg: 'Open Graph tag yok (sosyal medya paylaşımı için)' });
173
+ else issues.push({ severity: 'low', msg: L('Open Graph tag yok (sosyal medya paylaşımı için)', 'No Open Graph tags (for social sharing)') });
172
174
 
173
175
  // Twitter
174
176
  if (Object.keys(meta.twitter).length > 0) passes.push(`Twitter Card (${Object.keys(meta.twitter).length} tag)`);
175
- else issues.push({ severity: 'low', msg: 'Twitter Card tag yok' });
177
+ else issues.push({ severity: 'low', msg: L('Twitter Card tag yok', 'No Twitter Card tags') });
176
178
 
177
179
  // H1
178
- if (meta.headings.h1.length === 0) issues.push({ severity: 'high', msg: 'H1 tag eksik' });
179
- else if (meta.headings.h1.length > 1) issues.push({ severity: 'medium', msg: `Birden fazla H1 var (${meta.headings.h1.length}, ideal: 1)` });
180
- else passes.push(`H1 var: "${meta.headings.h1[0].slice(0, 50)}"`);
180
+ if (meta.headings.h1.length === 0) issues.push({ severity: 'high', msg: L('H1 tag eksik', 'H1 tag missing') });
181
+ else if (meta.headings.h1.length > 1) issues.push({ severity: 'medium', msg: `${L('Birden fazla H1 var', 'Multiple H1 tags')} (${meta.headings.h1.length}, ideal: 1)` });
182
+ else passes.push(`${L('H1 var', 'H1 present')}: "${meta.headings.h1[0].slice(0, 50)}"`);
181
183
 
182
184
  // Images
183
185
  if (meta.totalImages > 0) {
184
186
  if (meta.imagesWithoutAlt > 0) {
185
- issues.push({ severity: 'medium', msg: `${meta.imagesWithoutAlt}/${meta.totalImages} image alt tag eksik` });
187
+ issues.push({ severity: 'medium', msg: `${meta.imagesWithoutAlt}/${meta.totalImages} ${L('image alt tag eksik', 'images missing alt tags')}` });
186
188
  } else {
187
- passes.push(`Tüm image'larda alt var (${meta.totalImages})`);
189
+ passes.push(`${L("Tüm image'larda alt var", 'All images have alt')} (${meta.totalImages})`);
188
190
  }
189
191
  }
190
192
 
191
193
  // Schema
192
- if (meta.hasSchema) passes.push('Schema.org markup var');
193
- else issues.push({ severity: 'low', msg: 'Schema.org markup yok (rich snippets için)' });
194
+ if (meta.hasSchema) passes.push(L('Schema.org markup var', 'Schema.org markup present'));
195
+ else issues.push({ severity: 'low', msg: L('Schema.org markup yok (rich snippets için)', 'No Schema.org markup (for rich snippets)') });
194
196
 
195
197
  // Content
196
- if (meta.wordCount < 300) issues.push({ severity: 'medium', msg: `İçerik kısa (${meta.wordCount} kelime, ideal: 600+)` });
197
- else passes.push(`İçerik uzunluğu (${meta.wordCount} kelime)`);
198
+ if (meta.wordCount < 300) issues.push({ severity: 'medium', msg: `${L('İçerik kısa', 'Content short')} (${meta.wordCount} ${L('kelime', 'words')}, ideal: 600+)` });
199
+ else passes.push(`${L('İçerik uzunluğu', 'Content length')} (${meta.wordCount} ${L('kelime', 'words')})`);
198
200
 
199
201
  // Sonuçları tablo halinde göster
200
- console.log(tui.styled(' 📊 Sonuçlar', { color: tui.PALETTE.primary, bold: true }));
202
+ console.log(tui.styled(L(' 📊 Sonuçlar', ' 📊 Results'), { color: tui.PALETTE.primary, bold: true }));
201
203
  console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
202
204
 
203
205
  // Geçenler
204
206
  if (passes.length > 0) {
205
- console.log('\n' + tui.styled(' ✅ Geçenler', { color: tui.PALETTE.success, bold: true }));
207
+ console.log('\n' + tui.styled(L(' ✅ Geçenler', ' ✅ Passed'), { color: tui.PALETTE.success, bold: true }));
206
208
  const passRows = passes.map((p, i) => ({
207
209
  icon: tui.styled(' ✓ ', { bg: tui.PALETTE.success, color: '#000', bold: true }),
208
210
  msg: p,
209
211
  }));
210
212
  console.log(tui.table(passRows, [
211
213
  { key: 'icon', label: ' ', minWidth: 5 },
212
- { key: 'msg', label: 'Kontrol', minWidth: 40, render: r => tui.C.text(r.msg) },
214
+ { key: 'msg', label: L('Kontrol', 'Check'), minWidth: 40, render: r => tui.C.text(r.msg) },
213
215
  ], { borderStyle: 'round', zebra: true }));
214
216
  }
215
217
 
216
218
  // İyileştirme alanları
217
219
  if (issues.length > 0) {
218
- console.log('\n' + tui.styled(' ⚠️ İyileştirme Alanları', { color: tui.PALETTE.warning, bold: true }));
220
+ console.log('\n' + tui.styled(L(' ⚠️ İyileştirme Alanları', ' ⚠️ Improvement Areas'), { color: tui.PALETTE.warning, bold: true }));
219
221
  const issueRows = issues.map(i => ({
220
222
  icon: i.severity === 'high' ? tui.styled(' ✗ ', { bg: tui.PALETTE.danger, color: '#000', bold: true })
221
223
  : i.severity === 'medium' ? tui.styled(' ⚠ ', { bg: tui.PALETTE.warning, color: '#000', bold: true })
@@ -224,17 +226,17 @@ async function cmdAudit(args) {
224
226
  }));
225
227
  console.log(tui.table(issueRows, [
226
228
  { key: 'icon', label: ' ', minWidth: 5 },
227
- { key: 'msg', label: 'Sorun', minWidth: 40, render: r => tui.C.text(r.msg) },
229
+ { key: 'msg', label: L('Sorun', 'Issue'), minWidth: 40, render: r => tui.C.text(r.msg) },
228
230
  ], { borderStyle: 'round', zebra: true }));
229
231
  }
230
232
 
231
233
  // Skor (büyük, prominent)
232
234
  const score = Math.max(0, Math.min(100, 100 - (issues.filter(i => i.severity === 'high').length * 15 + issues.filter(i => i.severity === 'medium').length * 7 + issues.filter(i => i.severity === 'low').length * 3)));
233
235
  const scoreColor = score >= 80 ? tui.PALETTE.success : score >= 50 ? tui.PALETTE.warning : tui.PALETTE.danger;
234
- const scoreGrade = score >= 80 ? '🟢 Mükemmel' : score >= 50 ? '🟡 İyi' : '🔴 Geliştirilmeli';
236
+ const scoreGrade = score >= 80 ? L('🟢 Mükemmel', '🟢 Excellent') : score >= 50 ? L('🟡 İyi', '🟡 Good') : L('🔴 Geliştirilmeli', '🔴 Needs work');
235
237
 
236
238
  console.log('\n' + tui.styled(' ╭────────────────────────────────────────────────────╮', { color: tui.PALETTE.border }));
237
- console.log(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted('SEO Skoru:') + ' ' +
239
+ console.log(tui.styled(' │', { color: tui.PALETTE.border }) + ' ' + tui.C.muted(L('SEO Skoru:', 'SEO Score:')) + ' ' +
238
240
  tui.styled(String(score).padStart(3), { color: scoreColor, bold: true }) + tui.C.muted('/100 ') +
239
241
  tui.styled(scoreGrade, { color: scoreColor }) + ' ' + tui.styled('│', { color: tui.PALETTE.border }));
240
242
  console.log(tui.styled(' ╰────────────────────────────────────────────────────╯', { color: tui.PALETTE.border }));
@@ -246,23 +248,23 @@ async function cmdAudit(args) {
246
248
  async function seo(args) {
247
249
  const [action, ...params] = args || [];
248
250
  if (!action || action === 'help') {
249
- console.log(chalk.yellow('\n Kullanım:'));
250
- console.log(chalk.gray(' natureco seo audit <url> Tam SEO denetimi'));
251
- console.log(chalk.gray(' natureco seo meta <url> Meta tag analizi'));
252
- console.log(chalk.gray(' natureco seo speed <url> Hız ipuçları'));
251
+ console.log(chalk.yellow(L('\n Kullanım:', '\n Usage:')));
252
+ console.log(chalk.gray(L(' natureco seo audit <url> Tam SEO denetimi', ' natureco seo audit <url> Full SEO audit')));
253
+ console.log(chalk.gray(L(' natureco seo meta <url> Meta tag analizi', ' natureco seo meta <url> Meta tag analysis')));
254
+ console.log(chalk.gray(L(' natureco seo speed <url> Hız ipuçları', ' natureco seo speed <url> Speed tips')));
253
255
  console.log('');
254
256
  return;
255
257
  }
256
258
  if (action === 'audit') return cmdAudit(params);
257
259
  if (action === 'meta') {
258
- console.log(chalk.gray('\n Meta analizi audit\'in bir parçası olarak geliyor.\n'));
260
+ console.log(chalk.gray(L('\n Meta analizi audit\'in bir parçası olarak geliyor.\n', '\n Meta analysis comes as part of the audit.\n')));
259
261
  return cmdAudit(params);
260
262
  }
261
263
  if (action === 'speed') {
262
- console.log(chalk.gray('\n Hız analizi: PageSpeed Insights API entegrasyonu eklenecek (Phase 7).\n'));
264
+ console.log(chalk.gray(L('\n Hız analizi: PageSpeed Insights API entegrasyonu eklenecek (Phase 7).\n', '\n Speed analysis: PageSpeed Insights API integration coming (Phase 7).\n')));
263
265
  return;
264
266
  }
265
- console.log(chalk.red(`\n Bilinmeyen: ${action}\n`));
267
+ console.log(chalk.red(`\n ${L('Bilinmeyen', 'Unknown')}: ${action}\n`));
266
268
  }
267
269
 
268
270
  module.exports = seo;
@@ -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');
@@ -109,7 +111,7 @@ const PROVIDER_PRESETS = {
109
111
  default: 'gemini-2.0-flash',
110
112
  },
111
113
  groq: {
112
- name: 'Groq (hızlı + ücretsiz)',
114
+ name: L('Groq (hızlı + ücretsiz)', 'Groq (fast + free)'),
113
115
  url: 'https://api.groq.com/openai/v1',
114
116
  models: [
115
117
  { id: 'llama-3.3-70b-versatile', label: 'Llama 3.3 70B Versatile', tier: 'flagship', desc: 'En güçlü açık', cost: 'FREE' },
@@ -305,8 +307,8 @@ async function cmdWizard() {
305
307
  // Tam NatureCo logosu — brand kimliği
306
308
  for (const line of FULL_LOGO) console.log(COLORS.primary(line));
307
309
  console.log('');
308
- console.log(COLORS.secondary.bold(' ⚡ Setup Wizard — 60 saniyede hazır'));
309
- console.log(COLORS.muted(' Provider seç, API key gir, hemen başla.\n'));
310
+ console.log(COLORS.secondary.bold(L(' ⚡ Setup Wizard — 60 saniyede hazır', ' ⚡ Setup Wizard — ready in 60 seconds')));
311
+ console.log(COLORS.muted(L(' Provider seç, API key gir, hemen başla.\n', ' Pick a provider, enter an API key, start now.\n')));
310
312
 
311
313
  // Ensure directories
312
314
  if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
@@ -350,46 +352,46 @@ async function cmdWizard() {
350
352
  const { modelId } = await inquirer.prompt([{
351
353
  type: 'list',
352
354
  name: 'modelId',
353
- message: ` Model sec (${preset.models.length} secenek):`,
355
+ message: ` ${L('Model sec', 'Select model')} (${preset.models.length} ${L('secenek', 'options')}):`,
354
356
  choices: [
355
357
  { name: '─────────────────────', disabled: true },
356
- { name: '🟢 GÜÇLÜ / REASONING (en iyi)', disabled: true },
358
+ { name: L('🟢 GÜÇLÜ / REASONING (en iyi)', '🟢 POWERFUL / REASONING (best)'), disabled: true },
357
359
  ...preset.models.filter(m => m.tier === 'flagship' || m.tier === 'reasoning').map(m => ({
358
360
  name: ` ${m.label} (${m.cost})`,
359
361
  value: m.id,
360
362
  })),
361
363
  { name: '─────────────────────', disabled: true },
362
- { name: '🟡 ORTA (dengeli)', disabled: true },
364
+ { name: L('🟡 ORTA (dengeli)', '🟡 MID (balanced)'), disabled: true },
363
365
  ...preset.models.filter(m => m.tier === 'balanced').map(m => ({
364
366
  name: ` ${m.label} (${m.cost})`,
365
367
  value: m.id,
366
368
  })),
367
369
  { name: '─────────────────────', disabled: true },
368
- { name: '🔵 HIZLI / UCUZ', disabled: true },
370
+ { name: L('🔵 HIZLI / UCUZ', '🔵 FAST / CHEAP'), disabled: true },
369
371
  ...preset.models.filter(m => m.tier === 'fast').map(m => ({
370
372
  name: ` ${m.label} (${m.cost})`,
371
373
  value: m.id,
372
374
  })),
373
375
  { name: '─────────────────────', disabled: true },
374
- { name: '⚪ KLASİK (legacy)', disabled: true },
376
+ { name: L('⚪ KLASİK (legacy)', '⚪ CLASSIC (legacy)'), disabled: true },
375
377
  ...preset.models.filter(m => m.tier === 'classic').map(m => ({
376
378
  name: ` ${m.label} (${m.cost})`,
377
379
  value: m.id,
378
380
  })),
379
381
  { name: '─────────────────────', disabled: true },
380
- { name: '🔊 ÖZEL (audio/vision/embedding)', disabled: true },
382
+ { name: L('🔊 ÖZEL (audio/vision/embedding)', '🔊 SPECIAL (audio/vision/embedding)'), disabled: true },
381
383
  ...preset.models.filter(m => ['audio', 'vision', 'embedding', 'custom'].includes(m.tier)).map(m => ({
382
384
  name: ` ${m.label} (${m.cost})`,
383
385
  value: m.id,
384
386
  })),
385
387
  { name: '─────────────────────', disabled: true },
386
- { name: '✏️ Custom model adı (ileri düzey)', value: '__custom__' },
388
+ { name: L('✏️ Custom model adı (ileri düzey)', '✏️ Custom model name (advanced)'), value: '__custom__' },
387
389
  ],
388
390
  pageSize: 20,
389
391
  }]);
390
392
 
391
393
  if (modelId === '__custom__') {
392
- providerModel = await rlQuestion(` Model adı: `) || preset.default;
394
+ providerModel = await rlQuestion(` ${L('Model adı', 'Model name')}: `) || preset.default;
393
395
  } else {
394
396
  providerModel = modelId;
395
397
  }
@@ -407,11 +409,11 @@ async function cmdWizard() {
407
409
  const currentKey = cfg.providerApiKey || '';
408
410
  if (currentKey) {
409
411
  console.log('');
410
- console.log(chalk.yellow(' ⚠️ Mevcut API key tespit edildi (son 4 karakter: ' + currentKey.slice(-4) + ')'));
412
+ console.log(chalk.yellow(L(' ⚠️ Mevcut API key tespit edildi (son 4 karakter: ', ' ⚠️ Existing API key detected (last 4 chars: ') + currentKey.slice(-4) + ')'));
411
413
  const reset = await inquirer.prompt([{
412
414
  type: 'confirm',
413
415
  name: 'fresh',
414
- message: 'Sıfırdan yeni kurulum mu yapacaksın? (N = mevcut korunur)',
416
+ message: L('Sıfırdan yeni kurulum mu yapacaksın? (N = mevcut korunur)', 'Start a fresh setup? (N = keep existing)'),
415
417
  default: false,
416
418
  }]);
417
419
  if (reset.fresh) {
@@ -424,39 +426,39 @@ async function cmdWizard() {
424
426
  delete cfg.mattermostBot;
425
427
  delete cfg.smsTwilioSid;
426
428
  delete cfg.webhooks;
427
- console.log(chalk.green(' ✓ Eski ayarlar temizlendi'));
429
+ console.log(chalk.green(L(' ✓ Eski ayarlar temizlendi', ' ✓ Old settings cleared')));
428
430
  }
429
431
  }
430
432
  const apiKey = await rlQuestion(` API Key ${currentKey ? '(leave blank to keep current)' : ''}: `);
431
433
  if (apiKey) {
432
434
  cfg.providerApiKey = apiKey;
433
435
  // v5.6.0: API key dogrula
434
- console.log('\n Doğrulanıyor...');
436
+ console.log(L('\n Doğrulanıyor...', '\n Validating...'));
435
437
  const isValid = await validateApiKey(providerUrl, apiKey);
436
438
  if (!isValid) {
437
- console.log(' ❌ API key gecersiz! Lutfen kontrol edin.');
439
+ console.log(L(' ❌ API key gecersiz! Lutfen kontrol edin.', ' ❌ API key invalid! Please check.'));
438
440
  const retry = await inquirer.prompt([{
439
441
  type: 'confirm',
440
442
  name: 'continue',
441
- message: 'Yine de devam etmek istiyor musunuz? (key sonra duzeltilebilir)',
443
+ message: L('Yine de devam etmek istiyor musunuz? (key sonra duzeltilebilir)', 'Continue anyway? (you can fix the key later)'),
442
444
  default: false,
443
445
  }]);
444
446
  if (!retry.continue) {
445
- console.log(' Setup iptal edildi. Tekrar deneyin: natureco setup');
447
+ console.log(L(' Setup iptal edildi. Tekrar deneyin: natureco setup', ' Setup cancelled. Try again: natureco setup'));
446
448
  process.exit(1);
447
449
  }
448
450
  } else {
449
- console.log(' ✓ API key gecerli!');
451
+ console.log(L(' ✓ API key gecerli!', ' ✓ API key valid!'));
450
452
  }
451
453
  }
452
454
 
453
455
  // Step 3: Bot & User identity
454
456
  console.log('');
455
- console.log(chalk.white(' Step 3: Bot & Kullanıcı'));
457
+ console.log(chalk.white(L(' Step 3: Bot & Kullanıcı', ' Step 3: Bot & User')));
456
458
  console.log(chalk.gray(' ─────────────────────────────────────────────'));
457
- const userName = await rlQuestion(` Sizin adınız: `);
459
+ const userName = await rlQuestion(` ${L('Sizin adınız', 'Your name')}: `);
458
460
  if (userName) cfg.userName = userName;
459
- const botName = await rlQuestion(` Bot adı: `);
461
+ const botName = await rlQuestion(` ${L('Bot adı', 'Bot name')}: `);
460
462
  if (botName) cfg.botName = botName;
461
463
 
462
464
  // v5.6.7: Memory dosyasi yoksa olustur, varsa guncelle
@@ -475,43 +477,43 @@ async function cmdWizard() {
475
477
  if (!fs.existsSync(BASE_DIR)) fs.mkdirSync(BASE_DIR, { recursive: true });
476
478
  if (!fs.existsSync(path.dirname(memFile))) fs.mkdirSync(path.dirname(memFile), { recursive: true });
477
479
  fs.writeFileSync(memFile, JSON.stringify(mem, null, 2), 'utf8');
478
- console.log(chalk.gray(' ✓ Memory ' + (memExists ? 'guncellendi' : 'olusturuldu') + ': ' + memFile));
480
+ console.log(chalk.gray(' ✓ Memory ' + (memExists ? L('guncellendi', 'updated') : L('olusturuldu', 'created')) + ': ' + memFile));
479
481
  }
480
482
  } catch (e) {
481
- console.log(chalk.gray(' ! Memory yazilamadi: ' + e.message));
483
+ console.log(chalk.gray(L(' ! Memory yazilamadi: ', ' ! Could not write memory: ') + e.message));
482
484
  }
483
485
 
484
486
  // Step 4: Kanal Entegrasyonları (isteğe bağlı, isteyen atlayabilir)
485
487
  console.log('');
486
- console.log(chalk.white(' Step 4: Kanal Entegrasyonları (opsiyonel)'));
488
+ console.log(chalk.white(L(' Step 4: Kanal Entegrasyonları (opsiyonel)', ' Step 4: Channel Integrations (optional)')));
487
489
  console.log(chalk.gray(' ─────────────────────────────────────────────'));
488
- console.log(chalk.gray(' Telegram, WhatsApp, Discord, Slack bağlamak ister misiniz?'));
489
- console.log(chalk.gray(' Atlamak için hepsini boş bırakın, sonra: natureco <kanal> connect\n'));
490
+ console.log(chalk.gray(L(' Telegram, WhatsApp, Discord, Slack bağlamak ister misiniz?', ' Connect Telegram, WhatsApp, Discord, Slack?')));
491
+ console.log(chalk.gray(L(' Atlamak için hepsini boş bırakın, sonra: natureco <kanal> connect\n', ' To skip, leave all blank, then: natureco <channel> connect\n')));
490
492
 
491
493
  const integrations = [
492
- { key: 'telegramToken', name: 'Telegram', hint: 'BotFather\'dan al (@BotFather → /newbot → token)' },
493
- { key: 'whatsappPhone', name: 'WhatsApp', hint: 'Telefon numaranızı girin (örn: +905422842631)' },
494
+ { key: 'telegramToken', name: 'Telegram', hint: L('BotFather\'dan al (@BotFather → /newbot → token)', 'Get it from BotFather (@BotFather → /newbot → token)') },
495
+ { key: 'whatsappPhone', name: 'WhatsApp', hint: L('Telefon numaranızı girin (örn: +905422842631)', 'Enter your phone number (e.g. +905422842631)') },
494
496
  { key: 'discordToken', name: 'Discord', hint: 'Discord bot token (Discord Developer Portal)' },
495
497
  { key: 'slackToken', name: 'Slack', hint: 'Slack bot token (api.slack.com/apps)' },
496
- { key: 'signalBotId', name: 'Signal', hint: 'Signal bot numarası veya ID' },
497
- { key: 'ircBotId', name: 'IRC', hint: 'IRC bot kullanıcı adı (örn: NatureCoBot)' },
498
- { key: 'mattermostBotId', name: 'Mattermost', hint: 'Mattermost bot kullanıcı adı' },
499
- { key: 'imessageBotId', name: 'iMessage', hint: 'iMessage bridge endpoint veya ad' },
500
- { key: 'smsBotId', name: 'SMS (Twilio)', hint: 'Twilio hesap SID veya bot ID' },
501
- { key: 'webhooks', name: 'Webhooks', hint: 'Webhook URL (veya boş bırakın, sonra: natureco webhooks add)' },
498
+ { key: 'signalBotId', name: 'Signal', hint: L('Signal bot numarası veya ID', 'Signal bot number or ID') },
499
+ { key: 'ircBotId', name: 'IRC', hint: L('IRC bot kullanıcı adı (örn: NatureCoBot)', 'IRC bot username (e.g. NatureCoBot)') },
500
+ { key: 'mattermostBotId', name: 'Mattermost', hint: L('Mattermost bot kullanıcı adı', 'Mattermost bot username') },
501
+ { key: 'imessageBotId', name: 'iMessage', hint: L('iMessage bridge endpoint veya ad', 'iMessage bridge endpoint or name') },
502
+ { key: 'smsBotId', name: 'SMS (Twilio)', hint: L('Twilio hesap SID veya bot ID', 'Twilio account SID or bot ID') },
503
+ { key: 'webhooks', name: 'Webhooks', hint: L('Webhook URL (veya boş bırakın, sonra: natureco webhooks add)', 'Webhook URL (or leave blank, then: natureco webhooks add)') },
502
504
  ];
503
505
 
504
506
  for (const integ of integrations) {
505
507
  const current = cfg[integ.key] || '';
506
508
  if (current) {
507
- console.log(chalk.gray(` ${integ.name}: zaten ayarlı, boş bırakırsanız korunur`));
509
+ console.log(chalk.gray(` ${integ.name}: ${L('zaten ayarlı, boş bırakırsanız korunur', 'already set, leave blank to keep')}`));
508
510
  } else {
509
511
  console.log(chalk.gray(` ${integ.hint}`));
510
512
  }
511
- const val = await rlQuestion(` ${integ.name} ${current ? '(mevcut - boş bırakın)' : '(boş = atla)'}: `);
513
+ const val = await rlQuestion(` ${integ.name} ${current ? L('(mevcut - boş bırakın)', '(current - leave blank)') : L('(boş = atla)', '(blank = skip)')}: `);
512
514
  if (val) {
513
515
  cfg[integ.key] = val;
514
- console.log(chalk.green(` ✓ ${integ.name} ayarlandı`));
516
+ console.log(chalk.green(` ✓ ${integ.name} ${L('ayarlandı', 'set')}`));
515
517
  }
516
518
  }
517
519
 
@@ -533,8 +535,8 @@ async function cmdWizard() {
533
535
  console.log('');
534
536
  console.log(chalk.white(' Next steps:'));
535
537
  console.log(chalk.cyan(' natureco chat Start chatting'));
536
- console.log(chalk.cyan(' natureco repl İnteraktif REPL (persistent memory)'));
537
- console.log(chalk.cyan(' natureco telegram connect Telegram bot bağla (henüz yapılmadıysa)'));
538
+ console.log(chalk.cyan(L(' natureco repl İnteraktif REPL (persistent memory)', ' natureco repl Interactive REPL (persistent memory)')));
539
+ console.log(chalk.cyan(L(' natureco telegram connect Telegram bot bağla (henüz yapılmadıysa)', ' natureco telegram connect Connect Telegram bot (if not done yet)')));
538
540
  console.log(chalk.cyan(' natureco help View all commands'));
539
541
  console.log('');
540
542
  }
@@ -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 F = require('../utils/format');
3
5
  const tui = require('../utils/tui');
4
6
  const fs = require('fs');
@@ -40,8 +42,8 @@ function cmdRun() {
40
42
  const pidFile = path.join(os.homedir(), '.natureco', 'gateway.pid');
41
43
  const gatewayRunning = fs.existsSync(pidFile);
42
44
  const gatewayStatus = gatewayRunning
43
- ? tui.styled(' ✓ Çalışıyor ', { bg: tui.PALETTE.success, color: '#000', bold: true })
44
- : tui.styled(' ✗ Durmuş ', { bg: tui.PALETTE.muted, color: '#000', bold: true });
45
+ ? tui.styled(L(' ✓ Çalışıyor ', ' ✓ Running '), { bg: tui.PALETTE.success, color: '#000', bold: true })
46
+ : tui.styled(L(' ✗ Durmuş ', ' ✗ Stopped '), { bg: tui.PALETTE.muted, color: '#000', bold: true });
45
47
  lines.push(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Gateway ') + gatewayStatus + ' '.repeat(23) + tui.styled(' │', { color: tui.PALETTE.border }));
46
48
 
47
49
  if (cfg.providerUrl) {
@@ -70,7 +72,7 @@ function cmdRun() {
70
72
  const all = getSkills();
71
73
  const builtin = all.filter(s => s.source === 'builtin').length;
72
74
  const user = all.length - builtin;
73
- skillInfo = `${all.length} (${builtin} yerleşik` + (user > 0 ? ` + ${user} kullanıcı` : '') + ')';
75
+ skillInfo = `${all.length} (${builtin} ${L('yerleşik', 'built-in')}` + (user > 0 ? ` + ${user} ${L('kullanıcı', 'user')}` : '') + ')';
74
76
  }
75
77
  } catch {}
76
78
  lines.push(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Skills ') + tui.styled(skillInfo.padEnd(36), { color: tui.PALETTE.text }) + tui.styled(' │', { color: tui.PALETTE.border }));
@@ -83,7 +85,7 @@ function cmdRun() {
83
85
  lines.push(tui.styled(' │ ', { color: tui.PALETTE.border }) + tui.C.muted('Tools ') + tui.styled(String(toolCount).padEnd(36), { color: tui.PALETTE.text }) + tui.styled(' │', { color: tui.PALETTE.border }));
84
86
 
85
87
  lines.push(tui.styled(' ╰' + '─'.repeat(cardW) + '╯', { color: tui.PALETTE.border }));
86
- console.log('\n' + tui.styled(' 🩺 Sistem Durumu', { color: tui.PALETTE.primary, bold: true }));
88
+ console.log('\n' + tui.styled(L(' 🩺 Sistem Durumu', ' 🩺 System Status'), { color: tui.PALETTE.primary, bold: true }));
87
89
  console.log(lines.join('\n'));
88
90
  console.log('');
89
91
  }
@@ -113,7 +115,7 @@ function cmdUsage() {
113
115
  const cfg = config ? config.getConfig() : {};
114
116
 
115
117
  if (!cfg.providerUrl) {
116
- console.log('\n' + tui.C.muted(' Provider tanımlı değil.'));
118
+ console.log('\n' + tui.C.muted(L(' Provider tanımlı değil.', ' Provider not set.')));
117
119
  return;
118
120
  }
119
121
 
@@ -126,10 +128,10 @@ function cmdUsage() {
126
128
  { key: 'session', label: 'Session', value: String(usage.sessionTokens || '—') },
127
129
  ];
128
130
 
129
- console.log('\n' + tui.styled(' 📊 Provider Kullanımı', { color: tui.PALETTE.primary, bold: true }));
131
+ console.log('\n' + tui.styled(L(' 📊 Provider Kullanımı', ' 📊 Provider Usage'), { color: tui.PALETTE.primary, bold: true }));
130
132
  console.log('\n' + tui.table(rows, [
131
- { key: 'key', label: 'Anahtar', minWidth: 12, render: r => tui.C.muted(r.key) },
132
- { key: 'value', label: 'Değer', minWidth: 30, render: r => tui.C.text(r.value) },
133
+ { key: 'key', label: L('Anahtar', 'Key'), minWidth: 12, render: r => tui.C.muted(r.key) },
134
+ { key: 'value', label: L('Değer', 'Value'), minWidth: 30, render: r => tui.C.text(r.value) },
133
135
  ], { borderStyle: 'round', zebra: true }));
134
136
  console.log('');
135
137
  }