1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Translation\Bundle\Command; |
6
|
|
|
|
7
|
|
|
use Symfony\Component\Console\Command\Command; |
8
|
|
|
use Symfony\Component\Console\Input\InputArgument; |
9
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
10
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
11
|
|
|
use Symfony\Component\Console\Style\SymfonyStyle; |
12
|
|
|
use Symfony\Component\Finder\Finder; |
13
|
|
|
use Symfony\Component\Translation\MessageCatalogueInterface; |
14
|
|
|
use Translation\Bundle\Catalogue\CatalogueCounter; |
15
|
|
|
use Translation\Bundle\Catalogue\CatalogueFetcher; |
16
|
|
|
use Translation\Bundle\Model\Configuration; |
17
|
|
|
use Translation\Bundle\Service\ConfigurationManager; |
18
|
|
|
use Translation\Bundle\Service\Importer; |
19
|
|
|
|
20
|
|
|
final class CheckMissingCommand extends Command |
21
|
|
|
{ |
22
|
|
|
protected static $defaultName = 'translation:check-missing'; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* @var ConfigurationManager |
26
|
|
|
*/ |
27
|
|
|
private $configurationManager; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var CatalogueFetcher |
31
|
|
|
*/ |
32
|
|
|
private $catalogueFetcher; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @var Importer |
36
|
|
|
*/ |
37
|
|
|
private $importer; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* @var CatalogueCounter |
41
|
|
|
*/ |
42
|
|
|
private $catalogueCounter; |
43
|
|
|
|
44
|
|
View Code Duplication |
public function __construct( |
|
|
|
|
45
|
|
|
ConfigurationManager $configurationManager, |
46
|
|
|
CatalogueFetcher $catalogueFetcher, |
47
|
|
|
Importer $importer, |
48
|
|
|
CatalogueCounter $catalogueCounter |
49
|
|
|
) { |
50
|
|
|
parent::__construct(); |
51
|
|
|
|
52
|
|
|
$this->configurationManager = $configurationManager; |
53
|
|
|
$this->catalogueFetcher = $catalogueFetcher; |
54
|
|
|
$this->importer = $importer; |
55
|
|
|
$this->catalogueCounter = $catalogueCounter; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
protected function configure(): void |
59
|
|
|
{ |
60
|
|
|
$this |
61
|
|
|
->setName(self::$defaultName) |
62
|
|
|
->setDescription('Check that all translations for a given locale are extracted.') |
63
|
|
|
->addArgument('locale', InputArgument::REQUIRED, 'The locale to check') |
64
|
|
|
->addArgument('configuration', InputArgument::OPTIONAL, 'The configuration to use', 'default'); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int |
68
|
|
|
{ |
69
|
|
|
$config = $this->configurationManager->getConfiguration($input->getArgument('configuration')); |
70
|
|
|
|
71
|
|
|
$locale = $input->getArgument('locale'); |
72
|
|
|
|
73
|
|
|
$catalogues = $this->catalogueFetcher->getCatalogues($config, [$locale]); |
74
|
|
|
$finder = $this->getConfiguredFinder($config); |
75
|
|
|
|
76
|
|
|
$result = $this->importer->extractToCatalogues( |
77
|
|
|
$finder, |
78
|
|
|
$catalogues, |
79
|
|
|
[ |
80
|
|
|
'blacklist_domains' => $config->getBlacklistDomains(), |
81
|
|
|
'whitelist_domains' => $config->getWhitelistDomains(), |
82
|
|
|
'project_root' => $config->getProjectRoot(), |
83
|
|
|
] |
84
|
|
|
); |
85
|
|
|
|
86
|
|
|
$definedBefore = $this->catalogueCounter->getNumberOfDefinedMessages($catalogues[0]); |
87
|
|
|
$definedAfter = $this->catalogueCounter->getNumberOfDefinedMessages($result->getMessageCatalogues()[0]); |
88
|
|
|
|
89
|
|
|
$newMessages = $definedAfter - $definedBefore; |
90
|
|
|
|
91
|
|
|
$io = new SymfonyStyle($input, $output); |
92
|
|
|
|
93
|
|
|
if ($newMessages > 0) { |
94
|
|
|
$io->error(\sprintf('%d new message(s) have been found, run bin/console translation:extract', $newMessages)); |
95
|
|
|
|
96
|
|
|
return 1; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
$emptyTranslations = $this->countEmptyTranslations($result->getMessageCatalogues()[0]); |
100
|
|
|
|
101
|
|
|
if ($emptyTranslations > 0) { |
102
|
|
|
$io->error( |
103
|
|
|
\sprintf('%d messages have empty translations, please provide translations for them', $emptyTranslations) |
104
|
|
|
); |
105
|
|
|
|
106
|
|
|
return 1; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$io->success('No new translation messages'); |
110
|
|
|
|
111
|
|
|
return 0; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
View Code Duplication |
private function getConfiguredFinder(Configuration $config): Finder |
|
|
|
|
115
|
|
|
{ |
116
|
|
|
$finder = new Finder(); |
117
|
|
|
$finder->in($config->getDirs()); |
118
|
|
|
|
119
|
|
|
foreach ($config->getExcludedDirs() as $exclude) { |
120
|
|
|
$finder->notPath($exclude); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
foreach ($config->getExcludedNames() as $exclude) { |
124
|
|
|
$finder->notName($exclude); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return $finder; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
private function countEmptyTranslations(MessageCatalogueInterface $catalogue): int |
131
|
|
|
{ |
132
|
|
|
$total = 0; |
133
|
|
|
|
134
|
|
|
foreach ($catalogue->getDomains() as $domain) { |
135
|
|
|
$emptyTranslations = \array_filter( |
136
|
|
|
$catalogue->all($domain), |
137
|
|
|
function (string $message): bool { |
138
|
|
|
return '' === $message; |
139
|
|
|
} |
140
|
|
|
); |
141
|
|
|
|
142
|
|
|
$total += \count($emptyTranslations); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
return $total; |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.