1111
1212namespace Symfony \Bundle \FrameworkBundle \Command ;
1313
14- use Symfony \Component \ Translation \Catalogue \ MergeOperation ;
14+ use Symfony \Bundle \ FrameworkBundle \ Translation \TranslationLoader ;
1515use Symfony \Component \Console \Helper \Table ;
1616use Symfony \Component \Console \Input \InputInterface ;
17- use Symfony \Component \Console \Output \OutputInterface ;
1817use Symfony \Component \Console \Input \InputArgument ;
1918use Symfony \Component \Console \Input \InputOption ;
19+ use Symfony \Component \Console \Output \OutputInterface ;
20+ use Symfony \Component \HttpKernel \Kernel ;
21+ use Symfony \Component \Translation \Catalogue \MergeOperation ;
2022use Symfony \Component \Translation \MessageCatalogue ;
2123use Symfony \Component \Translation \Translator ;
2224
@@ -48,6 +50,7 @@ protected function configure()
4850 new InputOption ('domain ' , null , InputOption::VALUE_OPTIONAL , 'The messages domain ' ),
4951 new InputOption ('only-missing ' , null , InputOption::VALUE_NONE , 'Displays only missing messages ' ),
5052 new InputOption ('only-unused ' , null , InputOption::VALUE_NONE , 'Displays only unused messages ' ),
53+ new InputOption ('all ' , null , InputOption::VALUE_NONE , 'Load messages from all registered bundles ' ),
5154 ))
5255 ->setDescription ('Displays translation messages information ' )
5356 ->setHelp (<<<EOF
@@ -75,6 +78,10 @@ protected function configure()
7578
7679 <info>php %command.full_name% en</info>
7780
81+ You can display information about translations in all registered bundles in a specific locale:
82+
83+ <info>php %command.full_name% --all en</info>
84+
7885EOF
7986 )
8087 ;
@@ -91,129 +98,123 @@ protected function execute(InputInterface $input, OutputInterface $output)
9198
9299 $ locale = $ input ->getArgument ('locale ' );
93100 $ domain = $ input ->getOption ('domain ' );
101+ /** @var TranslationLoader $loader */
94102 $ loader = $ this ->getContainer ()->get ('translation.loader ' );
103+ /** @var Kernel $kernel */
95104 $ kernel = $ this ->getContainer ()->get ('kernel ' );
96105
97106 // Define Root Path to App folder
98- $ rootPath = $ kernel ->getRootDir ();
107+ $ rootPaths = array ( $ kernel ->getRootDir () );
99108
100109 // Override with provided Bundle info
101110 if (null !== $ input ->getArgument ('bundle ' )) {
102111 try {
103- $ rootPath = $ kernel ->getBundle ($ input ->getArgument ('bundle ' ))->getPath ();
112+ $ rootPaths = array ( $ kernel ->getBundle ($ input ->getArgument ('bundle ' ))->getPath () );
104113 } catch (\InvalidArgumentException $ e ) {
105114 // such a bundle does not exist, so treat the argument as path
106- $ rootPath = $ input ->getArgument ('bundle ' );
115+ $ rootPaths = array ( $ input ->getArgument ('bundle ' ) );
107116
108- if (!is_dir ($ rootPath )) {
109- throw new \InvalidArgumentException (sprintf ('<error>"%s" is neither an enabled bundle nor a directory.</error> ' , $ rootPath ));
117+ if (!is_dir ($ rootPaths [0 ])) {
118+ throw new \InvalidArgumentException (
119+ sprintf ('<error>"%s" is neither an enabled bundle nor a directory.</error> ' , $ rootPaths [0 ])
120+ );
110121 }
111122 }
123+ } elseif ($ input ->getOption ('all ' )) {
124+ foreach ($ kernel ->getBundles () as $ bundle ) {
125+ $ rootPaths [] = $ bundle ->getPath ();
126+ }
112127 }
113128
114- // get bundle directory
115- $ translationsPath = $ rootPath .'/Resources/translations ' ;
129+ foreach ($ rootPaths as $ rootPath ) {
130+ // get bundle directory
131+ $ translationsPath = $ rootPath .'/Resources/translations ' ;
116132
117- // Extract used messages
118- $ extractedCatalogue = new MessageCatalogue ($ locale );
119- if (is_dir ($ rootPath .'/Resources/views ' )) {
120- $ this ->getContainer ()->get ('translation.extractor ' )->extract ($ rootPath .'/Resources/views ' , $ extractedCatalogue );
121- }
133+ $ output ->writeln (sprintf ('Translations in <info>%s</info> ' , $ translationsPath ));
122134
123- // Load defined messages
124- $ currentCatalogue = new MessageCatalogue ($ locale );
125- if (is_dir ($ translationsPath )) {
126- $ loader ->loadMessages ($ translationsPath , $ currentCatalogue );
127- }
128-
129- // Merge defined and extracted messages to get all message ids
130- $ mergeOperation = new MergeOperation ($ extractedCatalogue , $ currentCatalogue );
131- $ allMessages = $ mergeOperation ->getResult ()->all ($ domain );
132- if (null !== $ domain ) {
133- $ allMessages = array ($ domain => $ allMessages );
134- }
135+ // Extract used messages
136+ $ extractedCatalogue = $ this ->extractMessages ($ locale , $ rootPath );
135137
136- // No defined or extracted messages
137- if (empty ($ allMessages ) || null !== $ domain && empty ($ allMessages [$ domain ])) {
138- $ outputMessage = sprintf ('<info>No defined or extracted messages for locale "%s"</info> ' , $ locale );
138+ // Load defined messages
139+ $ currentCatalogue = $ this ->loadCurrentMessages ($ locale , $ translationsPath , $ loader );
139140
141+ // Merge defined and extracted messages to get all message ids
142+ $ mergeOperation = new MergeOperation ($ extractedCatalogue , $ currentCatalogue );
143+ $ allMessages = $ mergeOperation ->getResult ()->all ($ domain );
140144 if (null !== $ domain ) {
141- $ outputMessage .= sprintf ( ' <info>and domain "%s"</info> ' , $ domain );
145+ $ allMessages = array ( $ domain => $ allMessages );
142146 }
143147
144- $ output ->writeln ($ outputMessage );
145-
146- return ;
147- }
148+ // No defined or extracted messages
149+ if (empty ($ allMessages ) || null !== $ domain && empty ($ allMessages [$ domain ])) {
150+ $ outputMessage = sprintf ('<info>No defined or extracted messages for locale "%s"</info> ' , $ locale );
148151
149- // Load the fallback catalogues
150- $ fallbackCatalogues = array ();
151- $ translator = $ this ->getContainer ()->get ('translator ' );
152- if ($ translator instanceof Translator) {
153- foreach ($ translator ->getFallbackLocales () as $ fallbackLocale ) {
154- if ($ fallbackLocale === $ locale ) {
155- continue ;
152+ if (null !== $ domain ) {
153+ $ outputMessage .= sprintf (' <info>and domain "%s"</info> ' , $ domain );
156154 }
157155
158- $ fallbackCatalogue = new MessageCatalogue ($ fallbackLocale );
159- $ loader ->loadMessages ($ translationsPath , $ fallbackCatalogue );
160- $ fallbackCatalogues [] = $ fallbackCatalogue ;
161- }
162- }
156+ $ output ->writeln ($ outputMessage );
163157
164- if (class_exists ('Symfony\Component\Console\Helper\Table ' )) {
165- $ table = new Table ($ output );
166- } else {
167- $ table = $ this ->getHelperSet ()->get ('table ' );
168- }
158+ continue ;
159+ }
169160
170- // Display header line
171- $ headers = array ('State ' , 'Domain ' , 'Id ' , sprintf ('Message Preview (%s) ' , $ locale ));
172- foreach ($ fallbackCatalogues as $ fallbackCatalogue ) {
173- $ headers [] = sprintf ('Fallback Message Preview (%s) ' , $ fallbackCatalogue ->getLocale ());
174- }
175- $ table ->setHeaders ($ headers );
161+ // Load the fallback catalogues
162+ $ fallbackCatalogues = $ this ->loadFallbackCatalogues ($ locale , $ translationsPath , $ loader );
163+ if (class_exists ('Symfony\Component\Console\Helper\Table ' )) {
164+ $ table = new Table ($ output );
165+ } else {
166+ $ table = $ this ->getHelperSet ()->get ('table ' );
167+ }
176168
177- // Iterate all message ids and determine their state
178- foreach ($ allMessages as $ domain => $ messages ) {
179- foreach (array_keys ($ messages ) as $ messageId ) {
180- $ value = $ currentCatalogue ->get ($ messageId , $ domain );
181- $ states = array ();
169+ // Display header line
170+ $ headers = array ('State ' , 'Domain ' , 'Id ' , sprintf ('Message Preview (%s) ' , $ locale ));
171+ foreach ($ fallbackCatalogues as $ fallbackCatalogue ) {
172+ $ headers [] = sprintf ('Fallback Message Preview (%s) ' , $ fallbackCatalogue ->getLocale ());
173+ }
174+ $ table ->setHeaders ($ headers );
175+
176+ // Iterate all message ids and determine their state
177+ foreach ($ allMessages as $ domain => $ messages ) {
178+ foreach (array_keys ($ messages ) as $ messageId ) {
179+ $ value = $ currentCatalogue ->get ($ messageId , $ domain );
180+ $ states = array ();
181+
182+ if ($ extractedCatalogue ->defines ($ messageId , $ domain )) {
183+ if (!$ currentCatalogue ->defines ($ messageId , $ domain )) {
184+ $ states [] = self ::MESSAGE_MISSING ;
185+ }
186+ } elseif ($ currentCatalogue ->defines ($ messageId , $ domain )) {
187+ $ states [] = self ::MESSAGE_UNUSED ;
188+ }
182189
183- if ($ extractedCatalogue -> defines ( $ messageId , $ domain )) {
184- if (! $ currentCatalogue -> defines ( $ messageId , $ domain )) {
185- $ states [] = self :: MESSAGE_MISSING ;
190+ if (! in_array ( self :: MESSAGE_UNUSED , $ states ) && true === $ input -> getOption ( ' only-unused ' )
191+ || ! in_array ( self :: MESSAGE_MISSING , $ states ) && true === $ input -> getOption ( ' only-missing ' )) {
192+ continue ;
186193 }
187- } elseif ($ currentCatalogue ->defines ($ messageId , $ domain )) {
188- $ states [] = self ::MESSAGE_UNUSED ;
189- }
190194
191- if (!in_array (self ::MESSAGE_UNUSED , $ states ) && true === $ input ->getOption ('only-unused ' )
192- || !in_array (self ::MESSAGE_MISSING , $ states ) && true === $ input ->getOption ('only-missing ' )) {
193- continue ;
194- }
195+ foreach ($ fallbackCatalogues as $ fallbackCatalogue ) {
196+ if ($ fallbackCatalogue ->defines ($ messageId , $ domain ) && $ value === $ fallbackCatalogue ->get ($ messageId , $ domain )) {
197+ $ states [] = self ::MESSAGE_EQUALS_FALLBACK ;
195198
196- foreach ( $ fallbackCatalogues as $ fallbackCatalogue ) {
197- if ( $ fallbackCatalogue -> defines ( $ messageId , $ domain ) && $ value === $ fallbackCatalogue -> get ( $ messageId , $ domain )) {
198- $ states [] = self :: MESSAGE_EQUALS_FALLBACK ;
199+ break ;
200+ }
201+ }
199202
200- break ;
203+ $ row = array ($ this ->formatStates ($ states ), $ domain , $ this ->formatId ($ messageId ), $ this ->sanitizeString ($ value ));
204+ foreach ($ fallbackCatalogues as $ fallbackCatalogue ) {
205+ $ row [] = $ this ->sanitizeString ($ fallbackCatalogue ->get ($ messageId , $ domain ));
201206 }
202- }
203207
204- $ row = array ($ this ->formatStates ($ states ), $ domain , $ this ->formatId ($ messageId ), $ this ->sanitizeString ($ value ));
205- foreach ($ fallbackCatalogues as $ fallbackCatalogue ) {
206- $ row [] = $ this ->sanitizeString ($ fallbackCatalogue ->get ($ messageId , $ domain ));
208+ $ table ->addRow ($ row );
207209 }
208-
209- $ table ->addRow ($ row );
210210 }
211- }
212211
213- if (class_exists ('Symfony\Component\Console\Helper\Table ' )) {
214- $ table ->render ();
215- } else {
216- $ table ->render ($ output );
212+ if (class_exists ('Symfony\Component\Console\Helper\Table ' )) {
213+ $ table ->render ();
214+ } else {
215+ $ table ->render ($ output );
216+ }
217+ $ output ->writeln ('' );
217218 }
218219 }
219220
@@ -263,4 +264,63 @@ private function sanitizeString($string, $length = 40)
263264
264265 return $ string ;
265266 }
267+
268+ /**
269+ * @param string $locale
270+ * @param string $rootPath
271+ *
272+ * @return MessageCatalogue
273+ */
274+ private function extractMessages ($ locale , $ rootPath )
275+ {
276+ $ extractedCatalogue = new MessageCatalogue ($ locale );
277+ if (is_dir ($ rootPath .'/Resources/views ' )) {
278+ $ this ->getContainer ()->get ('translation.extractor ' )->extract ($ rootPath .'/Resources/views ' , $ extractedCatalogue );
279+ }
280+
281+ return $ extractedCatalogue ;
282+ }
283+
284+ /**
285+ * @param string $locale
286+ * @param string $translationsPath
287+ * @param TranslationLoader $loader
288+ *
289+ * @return MessageCatalogue
290+ */
291+ private function loadCurrentMessages ($ locale , $ translationsPath , TranslationLoader $ loader )
292+ {
293+ $ currentCatalogue = new MessageCatalogue ($ locale );
294+ if (is_dir ($ translationsPath )) {
295+ $ loader ->loadMessages ($ translationsPath , $ currentCatalogue );
296+ }
297+
298+ return $ currentCatalogue ;
299+ }
300+
301+ /**
302+ * @param string $locale
303+ * @param string $translationsPath
304+ * @param TranslationLoader $loader
305+ *
306+ * @return MessageCatalogue[]
307+ */
308+ private function loadFallbackCatalogues ($ locale , $ translationsPath , TranslationLoader $ loader )
309+ {
310+ $ fallbackCatalogues = array ();
311+ $ translator = $ this ->getContainer ()->get ('translator ' );
312+ if ($ translator instanceof Translator) {
313+ foreach ($ translator ->getFallbackLocales () as $ fallbackLocale ) {
314+ if ($ fallbackLocale === $ locale ) {
315+ continue ;
316+ }
317+
318+ $ fallbackCatalogue = new MessageCatalogue ($ fallbackLocale );
319+ $ loader ->loadMessages ($ translationsPath , $ fallbackCatalogue );
320+ $ fallbackCatalogues [] = $ fallbackCatalogue ;
321+ }
322+ }
323+
324+ return $ fallbackCatalogues ;
325+ }
266326}
0 commit comments