@artilingo/artiframe-cli 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/artiframe.js CHANGED
@@ -3,55 +3,264 @@
3
3
  /**
4
4
  * ArtiFrame CLI — Node.js wrapper
5
5
  *
6
- * This file is the npm entry point. It checks that PHP is installed
7
- * on the system, then delegates execution to the PHP CLI bootstrap.
6
+ * Handles:
7
+ * 1. PHP 8.1+ availability check
8
+ * 2. --version / -v flag: shows current + latest version, optional self-update
9
+ * 3. Delegates all other args to the PHP bootstrap
8
10
  */
9
11
 
10
- const { execFileSync, spawnSync } = require('child_process');
11
- const path = require('path');
12
- const fs = require('fs');
12
+ const { spawnSync } = require('child_process');
13
+ const path = require('path');
14
+ const fs = require('fs');
15
+ const https = require('https');
16
+ const readline = require('readline');
13
17
 
14
- // ── 1. Verify PHP is available ──────────────────────────────────
15
- function findPhp() {
16
- const candidates = ['php', 'php8', 'php81', 'php82', 'php83', 'php84'];
17
- for (const bin of candidates) {
18
- const result = spawnSync(bin, ['--version'], { encoding: 'utf8', shell: true });
19
- if (result.status === 0) return bin;
18
+ const PACKAGE_NAME = '@artilingo/artiframe-cli';
19
+ const PKG = require(path.join(__dirname, '..', 'package.json'));
20
+ const CURRENT_VERSION = PKG.version;
21
+
22
+ // ── ANSI colour helpers ─────────────────────────────────────────
23
+ const G = '\x1b[38;2;0;157;108m'; // ArtiFrame green
24
+ const W = '\x1b[1;37m'; // white bold
25
+ const D = '\x1b[38;2;100;100;100m'; // dim gray
26
+ const Y = '\x1b[38;5;220m'; // yellow
27
+ const R = '\x1b[0m'; // reset
28
+
29
+ // ── Language detection (mirrors PHP App.php logic) ──────────────
30
+ function getLanguage() {
31
+ for (const arg of process.argv.slice(2)) {
32
+ if (arg.startsWith('--lang=')) {
33
+ const code = arg.slice(7, 9).toLowerCase();
34
+ if (['tr', 'en', 'de', 'fr', 'es'].includes(code)) return code;
35
+ }
20
36
  }
21
- return null;
37
+ const home = process.env.HOME || process.env.USERPROFILE;
38
+ const configFile = home ? path.join(home, '.artiframe_lang') : null;
39
+ if (configFile && fs.existsSync(configFile)) {
40
+ const lang = fs.readFileSync(configFile, 'utf8').trim();
41
+ if (['tr', 'en', 'de', 'fr', 'es'].includes(lang)) return lang;
42
+ }
43
+ return 'en';
22
44
  }
23
45
 
24
- const php = findPhp();
46
+ // ── Inline translations for the version/update screen ───────────
47
+ const MESSAGES = {
48
+ tr: {
49
+ currentVersion : 'Mevcut sürüm ',
50
+ latestVersion : 'Son sürüm ',
51
+ checking : 'Güncelleme kontrol ediliyor...',
52
+ upToDate : '✅ Güncel — Yeni sürüm bulunmuyor.',
53
+ updateAvail : '🔔 Güncelleme mevcut!',
54
+ updatePrompt : 'Şimdi güncellemek ister misiniz? [e/H]: ',
55
+ yesKeys : ['e', 'y'],
56
+ updating : '📦 Güncelleniyor...',
57
+ updateSuccess : '✅ Güncelleme tamamlandı! Terminali yeniden başlatın.',
58
+ updateCancelled: 'Güncelleme iptal edildi.',
59
+ updateFailed : '❌ Güncelleme başarısız oldu.',
60
+ networkError : '⚠️ Sürüm kontrolü yapılamadı (ağ hatası).',
61
+ },
62
+ en: {
63
+ currentVersion : 'Current version',
64
+ latestVersion : 'Latest version ',
65
+ checking : 'Checking for updates...',
66
+ upToDate : '✅ Up to date — No new version available.',
67
+ updateAvail : '🔔 Update available!',
68
+ updatePrompt : 'Would you like to update now? [y/N]: ',
69
+ yesKeys : ['y'],
70
+ updating : '📦 Updating...',
71
+ updateSuccess : '✅ Update complete! Please restart your terminal.',
72
+ updateCancelled: 'Update cancelled.',
73
+ updateFailed : '❌ Update failed.',
74
+ networkError : '⚠️ Could not check for updates (network error).',
75
+ },
76
+ de: {
77
+ currentVersion : 'Aktuelle Version',
78
+ latestVersion : 'Neueste Version ',
79
+ checking : 'Nach Updates suchen...',
80
+ upToDate : '✅ Aktuell — Keine neue Version verfügbar.',
81
+ updateAvail : '🔔 Update verfügbar!',
82
+ updatePrompt : 'Möchten Sie jetzt aktualisieren? [j/N]: ',
83
+ yesKeys : ['j', 'y'],
84
+ updating : '📦 Wird aktualisiert...',
85
+ updateSuccess : '✅ Update abgeschlossen! Bitte Terminal neu starten.',
86
+ updateCancelled: 'Update abgebrochen.',
87
+ updateFailed : '❌ Update fehlgeschlagen.',
88
+ networkError : '⚠️ Keine Verbindung zum Update-Server (Netzwerkfehler).',
89
+ },
90
+ fr: {
91
+ currentVersion : 'Version actuelle',
92
+ latestVersion : 'Dernière version',
93
+ checking : 'Vérification des mises à jour...',
94
+ upToDate : '✅ À jour — Aucune nouvelle version disponible.',
95
+ updateAvail : '🔔 Mise à jour disponible !',
96
+ updatePrompt : 'Mettre à jour maintenant ? [o/N] : ',
97
+ yesKeys : ['o', 'y'],
98
+ updating : '📦 Mise à jour en cours...',
99
+ updateSuccess : '✅ Mise à jour terminée ! Veuillez redémarrer votre terminal.',
100
+ updateCancelled: 'Mise à jour annulée.',
101
+ updateFailed : '❌ Échec de la mise à jour.',
102
+ networkError : '⚠️ Impossible de vérifier les mises à jour (erreur réseau).',
103
+ },
104
+ es: {
105
+ currentVersion : 'Versión actual ',
106
+ latestVersion : 'Última versión ',
107
+ checking : 'Verificando actualizaciones...',
108
+ upToDate : '✅ Al día — No hay nueva versión disponible.',
109
+ updateAvail : '🔔 ¡Actualización disponible!',
110
+ updatePrompt : '¿Actualizar ahora? [s/N]: ',
111
+ yesKeys : ['s', 'y'],
112
+ updating : '📦 Actualizando...',
113
+ updateSuccess : '✅ ¡Actualización completa! Por favor reinicie su terminal.',
114
+ updateCancelled: 'Actualización cancelada.',
115
+ updateFailed : '❌ Error en la actualización.',
116
+ networkError : '⚠️ No se pudo verificar las actualizaciones (error de red).',
117
+ },
118
+ };
25
119
 
26
- if (!php) {
27
- console.error('\n\x1b[1;31m[ArtiFrame] PHP Not Found!\x1b[0m');
28
- console.error('\x1b[33mArtiFrame CLI requires PHP 8.1 or higher.\x1b[0m\n');
29
- console.error('Install PHP:');
30
- console.error(' Windows : https://windows.php.net/download/');
31
- console.error(' macOS : brew install php');
32
- console.error(' Linux : sudo apt install php8.2-cli\n');
33
- process.exit(1);
120
+ // ── npm registry fetch ──────────────────────────────────────────
121
+ function fetchLatestVersion() {
122
+ return new Promise((resolve, reject) => {
123
+ const req = https.request({
124
+ hostname: 'registry.npmjs.org',
125
+ path : '/' + encodeURIComponent(PACKAGE_NAME) + '/latest',
126
+ method : 'GET',
127
+ headers : { Accept: 'application/json' },
128
+ timeout : 6000,
129
+ }, (res) => {
130
+ let raw = '';
131
+ res.on('data', c => raw += c);
132
+ res.on('end', () => {
133
+ try { resolve(JSON.parse(raw).version); }
134
+ catch { reject(new Error('parse')); }
135
+ });
136
+ });
137
+ req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
138
+ req.on('error', reject);
139
+ req.end();
140
+ });
34
141
  }
35
142
 
36
- // ── 2. Verify PHP version >= 8.1 ───────────────────────────────
37
- const versionResult = spawnSync(php, ['-r', 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;'], {
38
- encoding: 'utf8',
39
- shell: true
40
- });
41
-
42
- const [major, minor] = (versionResult.stdout || '0.0').split('.').map(Number);
43
- if (major < 8 || (major === 8 && minor < 1)) {
44
- console.error('\n\x1b[1;31m[ArtiFrame] PHP version too old!\x1b[0m');
45
- console.error(`\x1b[33mFound PHP ${major}.${minor} — ArtiFrame requires PHP 8.1+\x1b[0m\n`);
46
- process.exit(1);
143
+ function compareVersions(a, b) {
144
+ const pa = a.split('.').map(Number);
145
+ const pb = b.split('.').map(Number);
146
+ for (let i = 0; i < 3; i++) {
147
+ if (pa[i] > pb[i]) return 1;
148
+ if (pa[i] < pb[i]) return -1;
149
+ }
150
+ return 0;
47
151
  }
48
152
 
49
- // ── 3. Delegate to the PHP bootstrap ───────────────────────────
50
- const phpScript = path.join(__dirname, '..', 'bin', 'artiframe.php');
153
+ // ── --version handler ───────────────────────────────────────────
154
+ async function handleVersion() {
155
+ const lang = getLanguage();
156
+ const m = MESSAGES[lang] || MESSAGES.en;
157
+
158
+ console.log();
159
+ console.log(` ${W}${m.currentVersion}:${R} ${G}v${CURRENT_VERSION}${R}`);
160
+ process.stdout.write(` ${D}${m.checking}${R}`);
161
+
162
+ let latest;
163
+ try {
164
+ latest = await fetchLatestVersion();
165
+ } catch {
166
+ console.log();
167
+ console.log(` ${Y}${m.networkError}${R}`);
168
+ console.log();
169
+ process.exit(0);
170
+ }
171
+
172
+ // Clear the "checking..." line by overwriting with spaces then reprint
173
+ process.stdout.write('\r' + ' '.repeat(60) + '\r');
174
+ console.log(` ${W}${m.latestVersion}:${R} ${G}v${latest}${R}`);
175
+ console.log();
176
+
177
+ if (compareVersions(latest, CURRENT_VERSION) <= 0) {
178
+ console.log(` ${m.upToDate}`);
179
+ console.log();
180
+ process.exit(0);
181
+ }
182
+
183
+ // ── Update available ─────────────────────────────────────────
184
+ console.log(` ${Y}${m.updateAvail}${R} ${D}v${CURRENT_VERSION}${R} → ${G}v${latest}${R}`);
185
+ console.log();
186
+ process.stdout.write(` ${m.updatePrompt}`);
187
+
188
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
189
+
190
+ rl.once('line', (answer) => {
191
+ rl.close();
192
+ const yes = m.yesKeys.includes(answer.trim().toLowerCase());
193
+
194
+ if (!yes) {
195
+ console.log();
196
+ console.log(` ${D}${m.updateCancelled}${R}`);
197
+ console.log();
198
+ process.exit(0);
199
+ }
51
200
 
52
- const result = spawnSync(php, [phpScript, ...process.argv.slice(2)], {
53
- stdio: 'inherit',
54
- shell: false
55
- });
201
+ console.log();
202
+ console.log(` ${m.updating}`);
203
+ console.log();
56
204
 
57
- process.exit(result.status ?? 1);
205
+ const result = spawnSync('npm', ['install', '-g', PACKAGE_NAME], {
206
+ stdio: 'inherit',
207
+ shell: true,
208
+ });
209
+
210
+ console.log();
211
+ if (result.status === 0) {
212
+ console.log(` ${G}${m.updateSuccess}${R}`);
213
+ } else {
214
+ console.log(` ${m.updateFailed}`);
215
+ }
216
+ console.log();
217
+ process.exit(result.status ?? 1);
218
+ });
219
+ }
220
+
221
+ // ── PHP availability check ──────────────────────────────────────
222
+ function findPhp() {
223
+ for (const bin of ['php', 'php8', 'php81', 'php82', 'php83', 'php84']) {
224
+ const r = spawnSync(bin, ['--version'], { encoding: 'utf8', shell: true });
225
+ if (r.status === 0) return bin;
226
+ }
227
+ return null;
228
+ }
229
+
230
+ // ── Entry point ─────────────────────────────────────────────────
231
+ const args = process.argv.slice(2);
232
+
233
+ if (args.includes('--version') || args.includes('-v')) {
234
+ handleVersion().catch(() => process.exit(1));
235
+ } else {
236
+ // Normal PHP delegation
237
+ const php = findPhp();
238
+
239
+ if (!php) {
240
+ const lang = getLanguage();
241
+ console.error(`\n\x1b[1;31m[ArtiFrame] PHP Not Found!\x1b[0m`);
242
+ console.error(`\x1b[33mArtiFrame CLI requires PHP 8.1 or higher.\x1b[0m\n`);
243
+ console.error('Install PHP:');
244
+ console.error(' Windows : https://windows.php.net/download/');
245
+ console.error(' macOS : brew install php');
246
+ console.error(' Linux : sudo apt install php8.2-cli\n');
247
+ process.exit(1);
248
+ }
249
+
250
+ const vr = spawnSync(php, ['-r', 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;'], {
251
+ encoding: 'utf8', shell: true,
252
+ });
253
+ const [major, minor] = (vr.stdout || '0.0').split('.').map(Number);
254
+ if (major < 8 || (major === 8 && minor < 1)) {
255
+ console.error(`\n\x1b[1;31m[ArtiFrame] PHP version too old!\x1b[0m`);
256
+ console.error(`\x1b[33mFound PHP ${major}.${minor} — ArtiFrame requires PHP 8.1+\x1b[0m\n`);
257
+ process.exit(1);
258
+ }
259
+
260
+ const phpScript = path.join(__dirname, 'artiframe.php');
261
+ const result = spawnSync(php, [phpScript, ...args], {
262
+ stdio: 'inherit',
263
+ shell: false,
264
+ });
265
+ process.exit(result.status ?? 1);
266
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artilingo/artiframe-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.4",
4
4
  "description": "ArtiFrame — Zero-dependency native PHP framework with a powerful multilingual CLI. Scaffold projects, generate views, APIs and classes instantly.",
5
5
  "main": "bin/artiframe.js",
6
6
  "bin": {
package/src/App.php CHANGED
@@ -114,7 +114,7 @@ class App
114
114
  }
115
115
 
116
116
  if (in_array(strtolower($input), ['exit', 'quit'])) {
117
- echo PHP_EOL . "\033[38;5;240m Goodbye. Build something great.\033[0m" . PHP_EOL . PHP_EOL;
117
+ echo PHP_EOL . "\033[38;5;240m " . $this->translator->get('SHELL_GOODBYE') . "\033[0m" . PHP_EOL . PHP_EOL;
118
118
  break;
119
119
  }
120
120
 
@@ -127,7 +127,7 @@ class App
127
127
  try {
128
128
  $this->routeCommand($commandName, $parts);
129
129
  } catch (\Exception $e) {
130
- echo "\033[1;31m ✖ Error:\033[0m " . $e->getMessage() . PHP_EOL;
130
+ echo "\033[1;31m ✖ " . $this->translator->get('SHELL_ERROR') . "\033[0m " . $e->getMessage() . PHP_EOL;
131
131
  }
132
132
  echo PHP_EOL;
133
133
  }
@@ -157,7 +157,7 @@ class App
157
157
  echo $g . " │" . $r . PHP_EOL;
158
158
  echo $g . " └─────────────────────────────────────────────────────────────┘" . $r . PHP_EOL;
159
159
  echo PHP_EOL;
160
- echo " " . $d . "Type " . $r . $g . "help" . $r . $d . " for available commands, or " . $r . $g . "exit" . $r . $d . " to quit." . $r . PHP_EOL;
160
+ echo " " . $d . $this->translator->get('SHELL_TYPE_HELP') . $r . PHP_EOL;
161
161
  echo PHP_EOL;
162
162
  }
163
163
 
@@ -182,6 +182,10 @@ class App
182
182
  (new \ArtiFrame\Cli\Commands\MakeClassCommand($this->translator))->execute($commandArgs);
183
183
  break;
184
184
 
185
+ case 'lang':
186
+ (new \ArtiFrame\Cli\Commands\LangCommand($this->translator))->execute($commandArgs);
187
+ break;
188
+
185
189
  case 'version':
186
190
  (new \ArtiFrame\Cli\Commands\VersionCommand($this->translator))->execute($commandArgs);
187
191
  break;
@@ -203,64 +207,72 @@ class App
203
207
  $c = "\033[38;5;81m"; // cyan for sub-options
204
208
  $r = "\033[0m"; // reset
205
209
 
210
+ $t = $this->translator;
206
211
  echo PHP_EOL;
207
- echo " " . $w . "COMMANDS" . $r . PHP_EOL;
212
+ echo " " . $w . $t->get('HELP_COMMANDS') . $r . PHP_EOL;
208
213
  echo " " . $d . "─────────────────────────────────────────────────────────────" . $r . PHP_EOL;
209
214
  echo PHP_EOL;
210
215
 
211
216
  // new
212
217
  echo " " . $g . "new" . $r . " " . $y . "<project-path>" . $r . PHP_EOL;
213
- echo " " . $d . "│" . $r . " Create a new ArtiFrame project from scratch." . PHP_EOL;
218
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_NEW_DESC') . PHP_EOL;
214
219
  echo " " . $d . "└── " . $r . "Example: " . $lg . "new my-app" . $r . PHP_EOL;
215
220
  echo PHP_EOL;
216
221
 
217
222
  // make:view
218
223
  echo " " . $g . "make:view" . $r . " " . $y . "<path>" . $r . PHP_EOL;
219
- echo " " . $d . "│" . $r . " Generate a new view file with its paired CSS and JS assets." . PHP_EOL;
220
- echo " " . $d . "│" . $r . " The path can use subdirectories (auto-created)." . PHP_EOL;
224
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_MAKEVIEW_DESC1') . PHP_EOL;
225
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_MAKEVIEW_DESC2') . PHP_EOL;
221
226
  echo " " . $d . "└── " . $r . "Example: " . $lg . "make:view pages/about.php" . $r . PHP_EOL;
222
227
  echo PHP_EOL;
223
228
 
224
229
  // make:api
225
230
  echo " " . $g . "make:api" . $r . " " . $y . "<template>" . $r . " " . $y . "<path>" . $r . PHP_EOL;
226
- echo " " . $d . "│" . $r . " Generate a new API endpoint file." . PHP_EOL;
231
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_MAKEAPI_DESC') . PHP_EOL;
227
232
  echo " " . $d . "│" . $r . PHP_EOL;
228
- echo " " . $d . "├── " . $c . "standart" . $r . " Single-action endpoint (one request, one response)." . PHP_EOL;
233
+ echo " " . $d . "├── " . $c . "standart" . $r . " " . $t->get('HELP_MAKEAPI_STANDART') . PHP_EOL;
229
234
  echo " " . $d . "│ " . $r . "Example: " . $lg . "make:api standart api/user/get.php" . $r . PHP_EOL;
230
235
  echo " " . $d . "│" . $r . PHP_EOL;
231
- echo " " . $d . "└── " . $c . "switch-case" . $r . " Multi-action endpoint with action routing." . PHP_EOL;
236
+ echo " " . $d . "└── " . $c . "switch-case" . $r . " " . $t->get('HELP_MAKEAPI_SWITCH') . PHP_EOL;
232
237
  echo " " . $d . " " . $r . "Example: " . $lg . "make:api switch-case api/user/crud.php" . $r . PHP_EOL;
233
238
  echo PHP_EOL;
234
239
 
235
240
  // make:class
236
241
  echo " " . $g . "make:class" . $r . " " . $y . "<path>" . $r . PHP_EOL;
237
- echo " " . $d . "│" . $r . " Generate a new PHP class file with namespace boilerplate." . PHP_EOL;
242
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_MAKECLASS_DESC') . PHP_EOL;
238
243
  echo " " . $d . "└── " . $r . "Example: " . $lg . "make:class classes/UserManager.php" . $r . PHP_EOL;
239
244
  echo PHP_EOL;
240
245
 
241
246
  // version
242
247
  echo " " . $g . "version" . $r . " " . $y . "<action>" . $r . " " . $y . "<level>" . $r . PHP_EOL;
243
- echo " " . $d . "│" . $r . " Manage the semantic version number stored in your project config." . PHP_EOL;
244
- echo " " . $d . "│" . $r . " Version format: " . $w . "MAJOR.MINOR.PATCH" . $r . " (e.g. 2.4.1)" . PHP_EOL;
248
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_VERSION_DESC1') . PHP_EOL;
249
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_VERSION_FORMAT') . PHP_EOL;
245
250
  echo " " . $d . "│" . $r . PHP_EOL;
246
251
  echo " " . $d . "├── " . $c . "upgrade" . $r . PHP_EOL;
247
- echo " " . $d . "│ ├── " . $c . "patch" . $r . " Bug fixes, small tweaks. " . $d . "1.0.0 → 1.0.1" . $r . PHP_EOL;
248
- echo " " . $d . "│ ├── " . $c . "minor" . $r . " New backwards-compat feature. " . $d . "1.0.0 → 1.1.0" . $r . PHP_EOL;
249
- echo " " . $d . "│ └── " . $c . "major" . $r . " Breaking changes. " . $d . "1.0.0 → 2.0.0" . $r . PHP_EOL;
252
+ echo " " . $d . "│ ├── " . $c . "patch" . $r . " " . $t->get('HELP_PATCH_UP') . " " . $d . "1.0.0 → 1.0.1" . $r . PHP_EOL;
253
+ echo " " . $d . "│ ├── " . $c . "minor" . $r . " " . $t->get('HELP_MINOR_UP') . " " . $d . "1.0.0 → 1.1.0" . $r . PHP_EOL;
254
+ echo " " . $d . "│ └── " . $c . "major" . $r . " " . $t->get('HELP_MAJOR_UP') . " " . $d . "1.0.0 → 2.0.0" . $r . PHP_EOL;
250
255
  echo " " . $d . "│" . $r . PHP_EOL;
251
256
  echo " " . $d . "└── " . $c . "downgrade" . $r . PHP_EOL;
252
- echo " " . $d . " ├── " . $c . "patch" . $r . " Roll back last patch. " . $d . "1.0.3 → 1.0.2" . $r . PHP_EOL;
253
- echo " " . $d . " ├── " . $c . "minor" . $r . " Roll back last minor release. " . $d . "1.3.0 → 1.2.0" . $r . PHP_EOL;
254
- echo " " . $d . " └── " . $c . "major" . $r . " Roll back last major release. " . $d . "3.0.0 → 2.0.0" . $r . PHP_EOL;
257
+ echo " " . $d . " ├── " . $c . "patch" . $r . " " . $t->get('HELP_PATCH_DOWN') . " " . $d . "1.0.3 → 1.0.2" . $r . PHP_EOL;
258
+ echo " " . $d . " ├── " . $c . "minor" . $r . " " . $t->get('HELP_MINOR_DOWN') . " " . $d . "1.3.0 → 1.2.0" . $r . PHP_EOL;
259
+ echo " " . $d . " └── " . $c . "major" . $r . " " . $t->get('HELP_MAJOR_DOWN') . " " . $d . "3.0.0 → 2.0.0" . $r . PHP_EOL;
255
260
  echo PHP_EOL;
256
261
  echo " " . $d . " Example: " . $lg . "version upgrade minor" . $r . PHP_EOL;
257
262
  echo " " . $d . " Example: " . $lg . "version downgrade patch" . $r . PHP_EOL;
258
263
  echo PHP_EOL;
259
264
 
265
+ // lang
266
+ echo " " . $g . "lang" . $r . PHP_EOL;
267
+ echo " " . $d . "│" . $r . " " . $t->get('HELP_LANG_DESC') . PHP_EOL;
268
+ echo " " . $d . "├── " . $r . "Example: " . $lg . "lang" . $r . $d . " (interactive)" . $r . PHP_EOL;
269
+ echo " " . $d . "└── " . $r . "Example: " . $lg . "lang en" . $r . $d . " (direct)" . $r . PHP_EOL;
270
+ echo PHP_EOL;
271
+
260
272
  // help / exit
261
273
  echo " " . $d . "─────────────────────────────────────────────────────────────" . $r . PHP_EOL;
262
- echo " " . $g . "help" . $r . " Show this help message." . PHP_EOL;
263
- echo " " . $g . "exit" . $r . " / " . $g . "quit" . $r . " Exit the interactive shell." . PHP_EOL;
274
+ echo " " . $g . "help" . $r . " " . $t->get('HELP_HELP_DESC') . PHP_EOL;
275
+ echo " " . $g . "exit" . $r . " / " . $g . "quit" . $r . " " . $t->get('HELP_EXIT_DESC') . PHP_EOL;
264
276
  echo PHP_EOL;
265
277
  }
266
278
  }
@@ -0,0 +1,100 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class LangCommand
7
+ {
8
+ private Translator $translator;
9
+
10
+ private const SUPPORTED = [
11
+ '1' => ['code' => 'tr', 'label' => '🇹🇷 Türkçe (TR)'],
12
+ '2' => ['code' => 'en', 'label' => '🇬🇧 English (EN)'],
13
+ '3' => ['code' => 'de', 'label' => '🇩🇪 Deutsch (DE)'],
14
+ '4' => ['code' => 'fr', 'label' => '🇫🇷 Français (FR)'],
15
+ '5' => ['code' => 'es', 'label' => '🇪🇸 Español (ES)'],
16
+ ];
17
+
18
+ public function __construct(Translator $translator)
19
+ {
20
+ $this->translator = $translator;
21
+ }
22
+
23
+ public function execute(array $args): void
24
+ {
25
+ $current = $this->translator->getLang();
26
+
27
+ // If a language code is passed directly (e.g. `lang en`)
28
+ if (!empty($args[0])) {
29
+ $code = strtolower($args[0]);
30
+ $valid = array_column(self::SUPPORTED, 'code');
31
+ if (!in_array($code, $valid)) {
32
+ echo "❌ " . $this->translator->get('LANG_INVALID', ['code' => $code]) . PHP_EOL;
33
+ echo $this->translator->get('LANG_VALID_LIST') . ': tr, en, de, fr, es' . PHP_EOL;
34
+ return;
35
+ }
36
+ $this->saveAndConfirm($code, $current);
37
+ return;
38
+ }
39
+
40
+ // Interactive picker
41
+ $g = "\033[38;2;0;157;108m";
42
+ $d = "\033[38;2;100;100;100m";
43
+ $w = "\033[1;37m";
44
+ $r = "\033[0m";
45
+
46
+ echo PHP_EOL;
47
+ echo " " . $w . $this->translator->get('LANG_CURRENT') . $r . " " . $g . strtoupper($current) . $r . PHP_EOL;
48
+ echo " " . $d . $this->translator->get('LANG_SELECT') . $r . PHP_EOL;
49
+ echo PHP_EOL;
50
+
51
+ foreach (self::SUPPORTED as $num => $info) {
52
+ $marker = ($info['code'] === $current) ? $g . " ✔" . $r : " ";
53
+ echo " {$marker} [{$num}] " . $info['label'] . PHP_EOL;
54
+ }
55
+
56
+ echo PHP_EOL;
57
+
58
+ while (true) {
59
+ echo " " . $this->translator->get('LANG_PROMPT') . " ";
60
+ $choice = trim(fgets(STDIN));
61
+
62
+ if ($choice === '' || $choice === '0') {
63
+ echo " " . $d . $this->translator->get('LANG_UNCHANGED') . $r . PHP_EOL . PHP_EOL;
64
+ return;
65
+ }
66
+
67
+ if (isset(self::SUPPORTED[$choice])) {
68
+ $this->saveAndConfirm(self::SUPPORTED[$choice]['code'], $current);
69
+ return;
70
+ }
71
+
72
+ echo " ❌ " . $this->translator->get('LANG_INVALID_CHOICE') . PHP_EOL;
73
+ }
74
+ }
75
+
76
+ private function saveAndConfirm(string $newCode, string $oldCode): void
77
+ {
78
+ $home = getenv('HOME') ?: getenv('USERPROFILE');
79
+ $configFile = $home ? $home . DIRECTORY_SEPARATOR . '.artiframe_lang' : null;
80
+
81
+ if ($configFile) {
82
+ file_put_contents($configFile, $newCode);
83
+ }
84
+
85
+ $g = "\033[38;2;0;157;108m";
86
+ $r = "\033[0m";
87
+
88
+ if ($newCode === $oldCode) {
89
+ echo PHP_EOL . " " . $this->translator->get('LANG_ALREADY_SET', ['lang' => strtoupper($newCode)]) . PHP_EOL . PHP_EOL;
90
+ return;
91
+ }
92
+
93
+ echo PHP_EOL;
94
+ echo " ✅ " . $this->translator->get('LANG_CHANGED', [
95
+ 'old' => strtoupper($oldCode),
96
+ 'new' => $g . strtoupper($newCode) . $r,
97
+ ]) . PHP_EOL;
98
+ echo " " . $this->translator->get('LANG_RESTART_TIP') . PHP_EOL . PHP_EOL;
99
+ }
100
+ }
package/src/Lang/de.php CHANGED
@@ -50,4 +50,42 @@ return [
50
50
  'ERROR_VERSION_PARSE' => 'Fehler: APP_VERSION in app-version.php konnte nicht gelesen werden.',
51
51
  'WARN_VERSION_UNCHANGED' => '⚠️ Warnung: Version ist bereits am Minimum (:version) oder hat sich nicht geändert.',
52
52
  'SUCCESS_VERSION' => '✅ Version aktualisiert: :old → :new',
53
+
54
+ // Shell UI
55
+ 'SHELL_TYPE_HELP' => 'Geben Sie ' . "\033[38;2;0;157;108m" . 'help' . "\033[0m" . ' für Befehle ein, oder ' . "\033[38;2;0;157;108m" . 'exit' . "\033[0m" . ' zum Beenden.',
56
+ 'SHELL_GOODBYE' => 'Auf Wiedersehen. Bauen Sie etwas Großartiges.',
57
+ 'SHELL_ERROR' => 'Fehler:',
58
+
59
+ // Help screen
60
+ 'HELP_COMMANDS' => 'BEFEHLE',
61
+ 'HELP_NEW_DESC' => 'Erstellt ein neues ArtiFrame-Projekt von Grund auf.',
62
+ 'HELP_MAKEVIEW_DESC1' => 'Erstellt eine neue View-Datei mit CSS- und JS-Assets.',
63
+ 'HELP_MAKEVIEW_DESC2' => 'Der Pfad kann Unterverzeichnisse enthalten (automatisch erstellt).',
64
+ 'HELP_MAKEAPI_DESC' => 'Erstellt eine neue API-Endpunkt-Datei.',
65
+ 'HELP_MAKEAPI_STANDART' => 'Einzelner Endpunkt (eine Anfrage, eine Antwort).',
66
+ 'HELP_MAKEAPI_SWITCH' => 'Mehrfunktions-Endpunkt mit Aktionsrouting.',
67
+ 'HELP_MAKECLASS_DESC' => 'Erstellt eine neue PHP-Klassendatei mit Namespace-Vorlage.',
68
+ 'HELP_VERSION_DESC1' => 'Verwaltet die semantische Versionsnummer in der Projektkonfiguration.',
69
+ 'HELP_VERSION_FORMAT' => 'Versionsformat: MAJOR.MINOR.PATCH (z.B. 2.4.1)',
70
+ 'HELP_PATCH_UP' => 'Fehlerbehebungen, kleine Änderungen.',
71
+ 'HELP_MINOR_UP' => 'Rückwärtskompatibles neues Feature.',
72
+ 'HELP_MAJOR_UP' => 'Brechende Änderungen.',
73
+ 'HELP_PATCH_DOWN' => 'Letzten Patch zurücksetzen.',
74
+ 'HELP_MINOR_DOWN' => 'Letzte Minor-Version zurücksetzen.',
75
+ 'HELP_MAJOR_DOWN' => 'Letzte Major-Version zurücksetzen.',
76
+ 'HELP_HELP_DESC' => 'Diese Hilfemeldung anzeigen.',
77
+ 'HELP_EXIT_DESC' => 'Die interaktive Shell beenden.',
78
+
79
+ // LangCommand
80
+ 'LANG_CURRENT' => 'Aktuelle Sprache:',
81
+ 'LANG_SELECT' => 'Nummer eingeben zum Ändern (0 zum Abbrechen):',
82
+ 'LANG_PROMPT' => 'Ihre Wahl [1-5] oder 0:',
83
+ 'LANG_UNCHANGED' => 'Sprache unverändert.',
84
+ 'LANG_CHANGED' => 'Sprache geändert: :old → :new',
85
+ 'LANG_ALREADY_SET' => 'Sprache ist bereits auf :lang eingestellt.',
86
+ 'LANG_RESTART_TIP' => 'Die Änderung wird ab der nächsten Sitzung wirksam.',
87
+ 'LANG_INVALID' => 'Ungültiger Sprachcode: ":code".',
88
+ 'LANG_VALID_LIST' => 'Unterstützte Sprachen',
89
+ 'LANG_INVALID_CHOICE' => 'Ungültige Auswahl. Bitte eine Zahl zwischen 1 und 5 eingeben.',
90
+ 'HELP_LANG_DESC' => 'Spracheinstellung anzeigen und ändern.',
53
91
  ];
package/src/Lang/en.php CHANGED
@@ -50,4 +50,42 @@ return [
50
50
  'ERROR_VERSION_PARSE' => 'Error: Could not parse APP_VERSION in app-version.php.',
51
51
  'WARN_VERSION_UNCHANGED' => '⚠️ Warning: Version is already at minimum (:version) or did not change.',
52
52
  'SUCCESS_VERSION' => '✅ Version updated: :old → :new',
53
+
54
+ // Shell UI
55
+ 'SHELL_TYPE_HELP' => 'Type ' . "\033[38;2;0;157;108m" . 'help' . "\033[0m" . ' for available commands, or ' . "\033[38;2;0;157;108m" . 'exit' . "\033[0m" . ' to quit.',
56
+ 'SHELL_GOODBYE' => 'Goodbye. Build something great.',
57
+ 'SHELL_ERROR' => 'Error:',
58
+
59
+ // Help screen
60
+ 'HELP_COMMANDS' => 'COMMANDS',
61
+ 'HELP_NEW_DESC' => 'Create a new ArtiFrame project from scratch.',
62
+ 'HELP_MAKEVIEW_DESC1' => 'Generate a new view file with its paired CSS and JS assets.',
63
+ 'HELP_MAKEVIEW_DESC2' => 'The path can use subdirectories (auto-created).',
64
+ 'HELP_MAKEAPI_DESC' => 'Generate a new API endpoint file.',
65
+ 'HELP_MAKEAPI_STANDART' => 'Single-action endpoint (one request, one response).',
66
+ 'HELP_MAKEAPI_SWITCH' => 'Multi-action endpoint with action routing.',
67
+ 'HELP_MAKECLASS_DESC' => 'Generate a new PHP class file with namespace boilerplate.',
68
+ 'HELP_VERSION_DESC1' => 'Manage the semantic version number stored in your project config.',
69
+ 'HELP_VERSION_FORMAT' => 'Version format: MAJOR.MINOR.PATCH (e.g. 2.4.1)',
70
+ 'HELP_PATCH_UP' => 'Bug fixes, small tweaks.',
71
+ 'HELP_MINOR_UP' => 'New backwards-compat feature.',
72
+ 'HELP_MAJOR_UP' => 'Breaking changes.',
73
+ 'HELP_PATCH_DOWN' => 'Roll back last patch.',
74
+ 'HELP_MINOR_DOWN' => 'Roll back last minor release.',
75
+ 'HELP_MAJOR_DOWN' => 'Roll back last major release.',
76
+ 'HELP_HELP_DESC' => 'Show this help message.',
77
+ 'HELP_EXIT_DESC' => 'Exit the interactive shell.',
78
+
79
+ // LangCommand
80
+ 'LANG_CURRENT' => 'Current language:',
81
+ 'LANG_SELECT' => 'Enter a number to change (0 to cancel):',
82
+ 'LANG_PROMPT' => 'Your choice [1-5] or 0:',
83
+ 'LANG_UNCHANGED' => 'Language unchanged.',
84
+ 'LANG_CHANGED' => 'Language changed: :old → :new',
85
+ 'LANG_ALREADY_SET' => 'Language is already set to :lang.',
86
+ 'LANG_RESTART_TIP' => 'The change will take effect from the next session.',
87
+ 'LANG_INVALID' => 'Invalid language code: ":code".',
88
+ 'LANG_VALID_LIST' => 'Supported languages',
89
+ 'LANG_INVALID_CHOICE' => 'Invalid choice. Please enter a number between 1 and 5.',
90
+ 'HELP_LANG_DESC' => 'View and change the language preference.',
53
91
  ];
package/src/Lang/es.php CHANGED
@@ -50,4 +50,42 @@ return [
50
50
  'ERROR_VERSION_PARSE' => 'Error: No se pudo leer APP_VERSION en app-version.php.',
51
51
  'WARN_VERSION_UNCHANGED' => '⚠️ Advertencia: La versión ya está en el mínimo (:version) o no cambió.',
52
52
  'SUCCESS_VERSION' => '✅ Versión actualizada: :old → :new',
53
+
54
+ // Shell UI
55
+ 'SHELL_TYPE_HELP' => 'Escriba ' . "\033[38;2;0;157;108m" . 'help' . "\033[0m" . ' para ver los comandos, o ' . "\033[38;2;0;157;108m" . 'exit' . "\033[0m" . ' para salir.',
56
+ 'SHELL_GOODBYE' => 'Hasta luego. Construye algo grandioso.',
57
+ 'SHELL_ERROR' => 'Error:',
58
+
59
+ // Help screen
60
+ 'HELP_COMMANDS' => 'COMANDOS',
61
+ 'HELP_NEW_DESC' => 'Crea un nuevo proyecto ArtiFrame desde cero.',
62
+ 'HELP_MAKEVIEW_DESC1' => 'Genera un nuevo archivo de vista con sus recursos CSS y JS.',
63
+ 'HELP_MAKEVIEW_DESC2' => 'La ruta puede usar subdirectorios (creados automáticamente).',
64
+ 'HELP_MAKEAPI_DESC' => 'Genera un nuevo archivo de punto de conexión API.',
65
+ 'HELP_MAKEAPI_STANDART' => 'Endpoint único (una solicitud, una respuesta).',
66
+ 'HELP_MAKEAPI_SWITCH' => 'Endpoint multifunción con enrutamiento de acciones.',
67
+ 'HELP_MAKECLASS_DESC' => 'Genera un nuevo archivo de clase PHP con plantilla de namespace.',
68
+ 'HELP_VERSION_DESC1' => 'Gestiona el número de versión semántica en la configuración del proyecto.',
69
+ 'HELP_VERSION_FORMAT' => 'Formato de versión: MAJOR.MINOR.PATCH (ej. 2.4.1)',
70
+ 'HELP_PATCH_UP' => 'Correcciones de errores, pequeños ajustes.',
71
+ 'HELP_MINOR_UP' => 'Nueva funcionalidad retrocompatible.',
72
+ 'HELP_MAJOR_UP' => 'Cambios que rompen la compatibilidad.',
73
+ 'HELP_PATCH_DOWN' => 'Revertir el último parche.',
74
+ 'HELP_MINOR_DOWN' => 'Revertir la última versión menor.',
75
+ 'HELP_MAJOR_DOWN' => 'Revertir la última versión mayor.',
76
+ 'HELP_HELP_DESC' => 'Mostrar este mensaje de ayuda.',
77
+ 'HELP_EXIT_DESC' => 'Salir del shell interactivo.',
78
+
79
+ // LangCommand
80
+ 'LANG_CURRENT' => 'Idioma actual:',
81
+ 'LANG_SELECT' => 'Ingrese un número para cambiar (0 para cancelar):',
82
+ 'LANG_PROMPT' => 'Su elección [1-5] o 0:',
83
+ 'LANG_UNCHANGED' => 'Idioma sin cambios.',
84
+ 'LANG_CHANGED' => 'Idioma cambiado: :old → :new',
85
+ 'LANG_ALREADY_SET' => 'El idioma ya está configurado en :lang.',
86
+ 'LANG_RESTART_TIP' => 'El cambio tendrá efecto desde la próxima sesión.',
87
+ 'LANG_INVALID' => 'Código de idioma inválido: ":code".',
88
+ 'LANG_VALID_LIST' => 'Idiomas admitidos',
89
+ 'LANG_INVALID_CHOICE' => 'Elección inválida. Por favor ingrese un número entre 1 y 5.',
90
+ 'HELP_LANG_DESC' => 'Ver y cambiar la preferencia de idioma.',
53
91
  ];
package/src/Lang/fr.php CHANGED
@@ -50,4 +50,42 @@ return [
50
50
  'ERROR_VERSION_PARSE' => 'Erreur : Impossible de lire APP_VERSION dans app-version.php.',
51
51
  'WARN_VERSION_UNCHANGED' => '⚠️ Avertissement : La version est déjà au minimum (:version) ou n\'a pas changé.',
52
52
  'SUCCESS_VERSION' => '✅ Version mise à jour : :old → :new',
53
+
54
+ // Shell UI
55
+ 'SHELL_TYPE_HELP' => 'Tapez ' . "\033[38;2;0;157;108m" . 'help' . "\033[0m" . ' pour les commandes, ou ' . "\033[38;2;0;157;108m" . 'exit' . "\033[0m" . ' pour quitter.',
56
+ 'SHELL_GOODBYE' => 'Au revoir. Construisez quelque chose de grand.',
57
+ 'SHELL_ERROR' => 'Erreur :',
58
+
59
+ // Help screen
60
+ 'HELP_COMMANDS' => 'COMMANDES',
61
+ 'HELP_NEW_DESC' => 'Crée un nouveau projet ArtiFrame de zéro.',
62
+ 'HELP_MAKEVIEW_DESC1' => 'Génère un nouveau fichier vue avec ses assets CSS et JS.',
63
+ 'HELP_MAKEVIEW_DESC2' => 'Le chemin peut utiliser des sous-répertoires (créés automatiquement).',
64
+ 'HELP_MAKEAPI_DESC' => 'Génère un nouveau fichier de point de terminaison API.',
65
+ 'HELP_MAKEAPI_STANDART' => 'Point de terminaison unique (une requête, une réponse).',
66
+ 'HELP_MAKEAPI_SWITCH' => 'Point de terminaison multi-actions avec routage.',
67
+ 'HELP_MAKECLASS_DESC' => 'Génère un nouveau fichier de classe PHP avec un espace de noms.',
68
+ 'HELP_VERSION_DESC1' => 'Gère le numéro de version sémantique dans la configuration du projet.',
69
+ 'HELP_VERSION_FORMAT' => 'Format de version : MAJOR.MINOR.PATCH (ex. 2.4.1)',
70
+ 'HELP_PATCH_UP' => 'Corrections de bogues, petites modifications.',
71
+ 'HELP_MINOR_UP' => 'Nouvelle fonctionnalité rétrocompatible.',
72
+ 'HELP_MAJOR_UP' => 'Changements non rétrocompatibles.',
73
+ 'HELP_PATCH_DOWN' => 'Annuler le dernier correctif.',
74
+ 'HELP_MINOR_DOWN' => 'Annuler la dernière version mineure.',
75
+ 'HELP_MAJOR_DOWN' => 'Annuler la dernière version majeure.',
76
+ 'HELP_HELP_DESC' => 'Afficher ce message d\'aide.',
77
+ 'HELP_EXIT_DESC' => 'Quitter le shell interactif.',
78
+
79
+ // LangCommand
80
+ 'LANG_CURRENT' => 'Langue actuelle :',
81
+ 'LANG_SELECT' => 'Entrez un numéro pour changer (0 pour annuler) :',
82
+ 'LANG_PROMPT' => 'Votre choix [1-5] ou 0 :',
83
+ 'LANG_UNCHANGED' => 'Langue inchangée.',
84
+ 'LANG_CHANGED' => 'Langue modifiée : :old → :new',
85
+ 'LANG_ALREADY_SET' => 'La langue est déjà définie sur :lang.',
86
+ 'LANG_RESTART_TIP' => 'Le changement prendra effet dès la prochaine session.',
87
+ 'LANG_INVALID' => 'Code de langue invalide : ":code".',
88
+ 'LANG_VALID_LIST' => 'Langues prises en charge',
89
+ 'LANG_INVALID_CHOICE' => 'Choix invalide. Veuillez entrer un chiffre entre 1 et 5.',
90
+ 'HELP_LANG_DESC' => 'Afficher et modifier la préférence de langue.',
53
91
  ];
package/src/Lang/tr.php CHANGED
@@ -50,4 +50,42 @@ return [
50
50
  'ERROR_VERSION_PARSE' => 'Hata: app-version.php içindeki APP_VERSION okunamadı.',
51
51
  'WARN_VERSION_UNCHANGED' => '⚠️ Uyarı: Sürüm zaten minimum değerde (:version) veya değişmedi.',
52
52
  'SUCCESS_VERSION' => '✅ Sürüm güncellendi: :old → :new',
53
+
54
+ // Shell UI
55
+ 'SHELL_TYPE_HELP' => 'Kullanılabilir komutlar için ' . "\033[38;2;0;157;108m" . 'help' . "\033[0m" . ' yazın, çıkmak için ' . "\033[38;2;0;157;108m" . 'exit' . "\033[0m" . '.',
56
+ 'SHELL_GOODBYE' => 'Güle güle. Harika şeyler inşa et.',
57
+ 'SHELL_ERROR' => 'Hata:',
58
+
59
+ // Help screen
60
+ 'HELP_COMMANDS' => 'KOMUTLAR',
61
+ 'HELP_NEW_DESC' => 'Sıfırdan yeni bir ArtiFrame projesi oluşturur.',
62
+ 'HELP_MAKEVIEW_DESC1' => 'CSS ve JS varlıklarıyla birlikte yeni bir view dosyası oluşturur.',
63
+ 'HELP_MAKEVIEW_DESC2' => 'Yol alt dizinleri içerebilir (otomatik oluşturulur).',
64
+ 'HELP_MAKEAPI_DESC' => 'Yeni bir API endpoint dosyası oluşturur.',
65
+ 'HELP_MAKEAPI_STANDART' => 'Tekil endpoint (bir istek, bir yanıt).',
66
+ 'HELP_MAKEAPI_SWITCH' => 'Eylem yönlendirmeli çok işlevli endpoint.',
67
+ 'HELP_MAKECLASS_DESC' => 'Namespace şablonuyla yeni bir PHP sınıf dosyası oluşturur.',
68
+ 'HELP_VERSION_DESC1' => 'Proje yapılandırmasındaki semantik sürümü yönetir.',
69
+ 'HELP_VERSION_FORMAT' => 'Sürüm formatı: MAJOR.MINOR.PATCH (örn. 2.4.1)',
70
+ 'HELP_PATCH_UP' => 'Hata düzeltmeleri, küçük değişiklikler.',
71
+ 'HELP_MINOR_UP' => 'Geriye dönük uyumlu yeni özellik.',
72
+ 'HELP_MAJOR_UP' => 'Kırıcı değişiklikler.',
73
+ 'HELP_PATCH_DOWN' => 'Son yamanın geri alınması.',
74
+ 'HELP_MINOR_DOWN' => 'Son minör sürümün geri alınması.',
75
+ 'HELP_MAJOR_DOWN' => 'Son majör sürümün geri alınması.',
76
+ 'HELP_HELP_DESC' => 'Bu yardım mesajını gösterir.',
77
+ 'HELP_EXIT_DESC' => 'İnteraktif kabuğu kapatır.',
78
+
79
+ // LangCommand
80
+ 'LANG_CURRENT' => 'Mevcut dil:',
81
+ 'LANG_SELECT' => 'Değiştirmek için bir numara girin (çıkmak için 0):',
82
+ 'LANG_PROMPT' => 'Seçiminiz [1-5] veya 0:',
83
+ 'LANG_UNCHANGED' => 'Dil değiştirilmedi.',
84
+ 'LANG_CHANGED' => 'Dil değiştirildi: :old → :new',
85
+ 'LANG_ALREADY_SET' => 'Dil zaten :lang olarak ayarlı.',
86
+ 'LANG_RESTART_TIP' => 'Değişiklik bir sonraki oturumdan itibaren geçerli olacak.',
87
+ 'LANG_INVALID' => 'Geçersiz dil kodu: ":code".',
88
+ 'LANG_VALID_LIST' => 'Desteklenen diller',
89
+ 'LANG_INVALID_CHOICE' => 'Geçersiz seçim. Lütfen 1-5 arasında bir rakam girin.',
90
+ 'HELP_LANG_DESC' => 'Dil tercihini görüntüler ve değiştirir.',
53
91
  ];