12
12
namespace Symfony \Bundle \FrameworkBundle \Command ;
13
13
14
14
use Symfony \Component \Console \Command \Command ;
15
+ use Symfony \Component \Console \Completion \CompletionInput ;
16
+ use Symfony \Component \Console \Completion \CompletionSuggestions ;
15
17
use Symfony \Component \Console \Exception \InvalidArgumentException ;
16
18
use Symfony \Component \Console \Input \InputArgument ;
17
19
use Symfony \Component \Console \Input \InputInterface ;
@@ -41,6 +43,10 @@ class TranslationUpdateCommand extends Command
41
43
private const ASC = 'asc ' ;
42
44
private const DESC = 'desc ' ;
43
45
private const SORT_ORDERS = [self ::ASC , self ::DESC ];
46
+ private const FORMATS = [
47
+ 'xlf12 ' => ['xlf ' , '1.2 ' ],
48
+ 'xlf20 ' => ['xlf ' , '2.0 ' ],
49
+ ];
44
50
45
51
protected static $ defaultName = 'translation:extract|translation:update ' ;
46
52
protected static $ defaultDescription = 'Extract missing translations keys from code to translation files. ' ;
@@ -53,8 +59,9 @@ class TranslationUpdateCommand extends Command
53
59
private $ defaultViewsPath ;
54
60
private $ transPaths ;
55
61
private $ codePaths ;
62
+ private $ enabledLocales ;
56
63
57
- public function __construct (TranslationWriterInterface $ writer , TranslationReaderInterface $ reader , ExtractorInterface $ extractor , string $ defaultLocale , string $ defaultTransPath = null , string $ defaultViewsPath = null , array $ transPaths = [], array $ codePaths = [])
64
+ public function __construct (TranslationWriterInterface $ writer , TranslationReaderInterface $ reader , ExtractorInterface $ extractor , string $ defaultLocale , string $ defaultTransPath = null , string $ defaultViewsPath = null , array $ transPaths = [], array $ codePaths = [], array $ enabledLocales = [] )
58
65
{
59
66
parent ::__construct ();
60
67
@@ -66,6 +73,7 @@ public function __construct(TranslationWriterInterface $writer, TranslationReade
66
73
$ this ->defaultViewsPath = $ defaultViewsPath ;
67
74
$ this ->transPaths = $ transPaths ;
68
75
$ this ->codePaths = $ codePaths ;
76
+ $ this ->enabledLocales = $ enabledLocales ;
69
77
}
70
78
71
79
/**
@@ -155,10 +163,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
155
163
trigger_deprecation ('symfony/framework-bundle ' , '5.3 ' , 'The "--output-format" option is deprecated, use "--format=xlf%d" instead. ' , 10 * $ xliffVersion );
156
164
}
157
165
158
- switch ($ format ) {
159
- case 'xlf20 ' : $ xliffVersion = '2.0 ' ;
160
- // no break
161
- case 'xlf12 ' : $ format = 'xlf ' ;
166
+ if (\in_array ($ format , array_keys (self ::FORMATS ), true )) {
167
+ [$ format , $ xliffVersion ] = self ::FORMATS [$ format ];
162
168
}
163
169
164
170
// check format
@@ -173,15 +179,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
173
179
$ kernel = $ this ->getApplication ()->getKernel ();
174
180
175
181
// Define Root Paths
176
- $ transPaths = $ this ->transPaths ;
177
- if ($ this ->defaultTransPath ) {
178
- $ transPaths [] = $ this ->defaultTransPath ;
179
- }
180
- $ codePaths = $ this ->codePaths ;
181
- $ codePaths [] = $ kernel ->getProjectDir ().'/src ' ;
182
- if ($ this ->defaultViewsPath ) {
183
- $ codePaths [] = $ this ->defaultViewsPath ;
184
- }
182
+ $ transPaths = $ this ->getRootTransPaths ();
183
+ $ codePaths = $ this ->getRootCodePaths ($ kernel );
184
+
185
185
$ currentName = 'default directory ' ;
186
186
187
187
// Override with provided Bundle info
@@ -214,24 +214,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
214
214
$ io ->title ('Translation Messages Extractor and Dumper ' );
215
215
$ io ->comment (sprintf ('Generating "<info>%s</info>" translation files for "<info>%s</info>" ' , $ input ->getArgument ('locale ' ), $ currentName ));
216
216
217
- // load any messages from templates
218
- $ extractedCatalogue = new MessageCatalogue ($ input ->getArgument ('locale ' ));
219
217
$ io ->comment ('Parsing templates... ' );
220
- $ this ->extractor ->setPrefix ($ input ->getOption ('prefix ' ));
221
- foreach ($ codePaths as $ path ) {
222
- if (is_dir ($ path ) || is_file ($ path )) {
223
- $ this ->extractor ->extract ($ path , $ extractedCatalogue );
224
- }
225
- }
218
+ $ extractedCatalogue = $ this ->extractMessages ($ input ->getArgument ('locale ' ), $ codePaths , $ input ->getOption ('prefix ' ));
226
219
227
- // load any existing messages from the translation files
228
- $ currentCatalogue = new MessageCatalogue ($ input ->getArgument ('locale ' ));
229
220
$ io ->comment ('Loading translation files... ' );
230
- foreach ($ transPaths as $ path ) {
231
- if (is_dir ($ path )) {
232
- $ this ->reader ->read ($ path , $ currentCatalogue );
233
- }
234
- }
221
+ $ currentCatalogue = $ this ->loadCurrentMessages ($ input ->getArgument ('locale ' ), $ transPaths );
235
222
236
223
if (null !== $ domain = $ input ->getOption ('domain ' )) {
237
224
$ currentCatalogue = $ this ->filterCatalogue ($ currentCatalogue , $ domain );
@@ -329,6 +316,60 @@ protected function execute(InputInterface $input, OutputInterface $output): int
329
316
return 0 ;
330
317
}
331
318
319
+ public function complete (CompletionInput $ input , CompletionSuggestions $ suggestions ): void
320
+ {
321
+ if ($ input ->mustSuggestArgumentValuesFor ('locale ' )) {
322
+ $ suggestions ->suggestValues ($ this ->enabledLocales );
323
+
324
+ return ;
325
+ }
326
+
327
+ /** @var KernelInterface $kernel */
328
+ $ kernel = $ this ->getApplication ()->getKernel ();
329
+ if ($ input ->mustSuggestArgumentValuesFor ('bundle ' )) {
330
+ $ bundles = [];
331
+
332
+ foreach ($ kernel ->getBundles () as $ bundle ) {
333
+ $ bundles [] = $ bundle ->getName ();
334
+ if ($ bundle ->getContainerExtension ()) {
335
+ $ bundles [] = $ bundle ->getContainerExtension ()->getAlias ();
336
+ }
337
+ }
338
+
339
+ $ suggestions ->suggestValues ($ bundles );
340
+
341
+ return ;
342
+ }
343
+
344
+ if ($ input ->mustSuggestOptionValuesFor ('format ' )) {
345
+ $ suggestions ->suggestValues (array_merge (
346
+ $ this ->writer ->getFormats (),
347
+ array_keys (self ::FORMATS )
348
+ ));
349
+
350
+ return ;
351
+ }
352
+
353
+ if ($ input ->mustSuggestOptionValuesFor ('domain ' ) && $ locale = $ input ->getArgument ('locale ' )) {
354
+ $ extractedCatalogue = $ this ->extractMessages ($ locale , $ this ->getRootCodePaths ($ kernel ), $ input ->getOption ('prefix ' ));
355
+
356
+ $ currentCatalogue = $ this ->loadCurrentMessages ($ locale , $ this ->getRootTransPaths ());
357
+
358
+ // process catalogues
359
+ $ operation = $ input ->getOption ('clean ' )
360
+ ? new TargetOperation ($ currentCatalogue , $ extractedCatalogue )
361
+ : new MergeOperation ($ currentCatalogue , $ extractedCatalogue );
362
+
363
+ $ suggestions ->suggestValues ($ operation ->getDomains ());
364
+
365
+ return ;
366
+ }
367
+
368
+ if ($ input ->mustSuggestOptionValuesFor ('sort ' )) {
369
+ $ suggestions ->suggestValues (self ::SORT_ORDERS );
370
+ }
371
+ }
372
+
332
373
private function filterCatalogue (MessageCatalogue $ catalogue , string $ domain ): MessageCatalogue
333
374
{
334
375
$ filteredCatalogue = new MessageCatalogue ($ catalogue ->getLocale ());
@@ -361,4 +402,50 @@ private function filterCatalogue(MessageCatalogue $catalogue, string $domain): M
361
402
362
403
return $ filteredCatalogue ;
363
404
}
405
+
406
+ private function extractMessages (string $ locale , array $ transPaths , string $ prefix ): MessageCatalogue
407
+ {
408
+ $ extractedCatalogue = new MessageCatalogue ($ locale );
409
+ $ this ->extractor ->setPrefix ($ prefix );
410
+ foreach ($ transPaths as $ path ) {
411
+ if (is_dir ($ path ) || is_file ($ path )) {
412
+ $ this ->extractor ->extract ($ path , $ extractedCatalogue );
413
+ }
414
+ }
415
+
416
+ return $ extractedCatalogue ;
417
+ }
418
+
419
+ private function loadCurrentMessages (string $ locale , array $ transPaths ): MessageCatalogue
420
+ {
421
+ $ currentCatalogue = new MessageCatalogue ($ locale );
422
+ foreach ($ transPaths as $ path ) {
423
+ if (is_dir ($ path )) {
424
+ $ this ->reader ->read ($ path , $ currentCatalogue );
425
+ }
426
+ }
427
+
428
+ return $ currentCatalogue ;
429
+ }
430
+
431
+ private function getRootTransPaths (): array
432
+ {
433
+ $ transPaths = $ this ->transPaths ;
434
+ if ($ this ->defaultTransPath ) {
435
+ $ transPaths [] = $ this ->defaultTransPath ;
436
+ }
437
+
438
+ return $ transPaths ;
439
+ }
440
+
441
+ private function getRootCodePaths (KernelInterface $ kernel ): array
442
+ {
443
+ $ codePaths = $ this ->codePaths ;
444
+ $ codePaths [] = $ kernel ->getProjectDir ().'/src ' ;
445
+ if ($ this ->defaultViewsPath ) {
446
+ $ codePaths [] = $ this ->defaultViewsPath ;
447
+ }
448
+
449
+ return $ codePaths ;
450
+ }
364
451
}
0 commit comments