Initial import from cvs.d.o HEAD as of 2010-01-23
[drupal_langcheck.git] / langcheck.module
blobd372922b2e72ee612a4cda3e5b1d60b821c80934
1 <?php
2 // $Id: langcheck.module,v 1.1 2009/02/10 06:43:42 boobaa Exp $
4 /**
5  * @file
6  * Language checker.
7  */
9 /**
10  * Implementation of hook_module().
11  */
12 function langcheck_menu() {
13   $items = array();
14   $items['admin/langcheck'] = array(
15     'title'            => 'Language checker',
16     'description'      => 'Check all installed modules for translation percentage.',
17     'page callback'    => 'langcheck_page',
18     'access arguments' => array('administer site configuration'),
19   );
21   $items['admin/langcheck-batch-start'] = array(
22     'title'            => 'Language checker Batch Start',
23     'description'      => 'Check all installed modules for translation percentage. BATCH',
24     'page callback'    => 'langcheck_check_batch_start',
25     'access arguments' => array('administer site configuration'),
26     'type'             => MENU_CALLBACK,
27   );
29   $items['admin/langcheck-batch-display'] = array(
30     'title'            => 'Language checker Batch Display',
31     'description'      => 'Display Batch result',
32     'page callback'    => 'langcheck_check_batch_result_page',
33     'access arguments' => array('administer site configuration'),
34   );
36   return $items;
39 function langcheck_page() {
40   module_load_include('inc', 'potx');
41   // Load the list of installed modules in alphabetical order.
42   $modules = module_list(FALSE, TRUE, TRUE);
43   // Fetch the installed languages.
44   $languages = locale_language_list();
45   // Omit English from the table, as it is the _source_ language.
46   unset($languages['en']);
47   $header = array(
48     t('Module'),
49   );
50   $header += $languages;
51   // module_iterate() cannot be used in any decent way as we need to build that
52   // table for output.
53   global $_potx_store;
54   potx_status('set', POTX_STATUS_SILENT);
55   foreach ($modules as $module) {
56     // This is loosely based on potx_select_form_submit().
57     $path = drupal_get_path('module', $module);
58     $files = _potx_explore_dir($path .'/');
59     $strip_prefix = 1 + strlen($path);
60     $row = array($module);
61     foreach ($languages as $langcode => $language) {
62       if ($langcode == 'en') {
63         // Omit English from the table, as it is the _source_ language.
64         continue;
65       }
66       foreach ($files as $file) {
67         _potx_process_file($file, $strip_prefix);
68       }
69       _potx_build_files(POTX_STRING_RUNTIME, POTX_BUILD_SINGLE, 'general', '_potx_save_string', '_potx_save_version', '_potx_get_header', $langcode, $langcode);
70       $lines = explode("\n", $_potx_store['general']['strings']);
71       $total = $untranslated = 0;
72       foreach ($lines as $lineno => $line) {
73         if (substr($line, 0, 7) == 'msgid "') {
74           $total++;
75         }
76         elseif ((substr($line, 0, 9) == 'msgstr ""') || (substr($line, 0, 12) == 'msgstr[1] ""')) {
77           if (isset($lines[$lineno + 1]) && ($lines[$lineno + 1] == '')) {
78             $untranslated++;
79           }
80         }
81       }
82       $row[] = array(
83         'data' => sprintf('%0.2f%%', ($total - $untranslated) / $total * 100),
84         'title' => t('Total: @total, untranslated: @untranslated', array('@total' => $total, '@untranslated' => $untranslated)),
85         'class' => ($untranslated == 0) ? 'langcheck-done' : 'langcheck-unfinished',
86       );
87       // If these don't get unset(), output will be cumulative.
88       unset( $GLOBALS['_potx_store']['general']['strings'], $GLOBALS['_potx_strings']);
89     }
90     $rows[] = $row;
91   }
92   drupal_add_css(drupal_get_path('module', 'langcheck') .'/langcheck.css');
93   return theme('table', $header, $rows);
96 function langcheck_check_batch_start() {
97   $langs = locale_language_list();
98   unset($langs['en']);
100   $modules = module_list(FALSE, TRUE, TRUE);
102   $title = t('Translation status check process');
104   $batch = array(
105     'operations'       => array(
106       array('langcheck_check_batch_process', array()),
107     ),
108     'finished'         => 'langcheck_check_batch_finished',
109     'title'            => $title,
110     'init_message'     => t('Translation status check is starting.'),
111     'progress_message' => t('Processed @current out of @total.'),
112     'error_message'    => t('Projects\' translations checks has encountered an error.'),
113   );
115   batch_set($batch);
116   batch_process('admin/langcheck-batch-display');
119 function langcheck_check_batch_process(&$context) {
120   if ( !array_key_exists('status', $context['sandbox']) ) {
121     $context['sandbox']['status'] = 'initialize';
123   }
125   switch ($context['sandbox']['status']) {
126     case 'initialize' :
127       $context['sandbox']['languages'] = locale_language_list();
128       unset($context['sandbox']['languages']['en']);
130       $context['sandbox']['languages'] = array_keys($context['sandbox']['languages']);
131       $context['sandbox']['modules']   = array_keys(module_list(FALSE, TRUE, TRUE));
132       rsort($context['sandbox']['modules']);
135       $default = array(
136         'total'        => 0,
137         'untranslated' => 0,
138         'state'        => 0,
139       );
140       $context['message'] = t('Initializing');
141       $context['sandbox']['status'] = 'check';
142       $context['sandbox']['results'] = array(
143         'time_start'      => time(),
144         'count_languages' => count($context['sandbox']['languages']),
145         'count_modules'   => count($context['sandbox']['modules']),
146         'data_module'     => array(),
147         'data_language'   => array(),
148         'sum_module'      => array_fill_keys($context['sandbox']['languages'], $default),
149         'sum_language'    => array_fill_keys($context['sandbox']['modules'], $default),
150       );
152       if ( $context['sandbox']['results']['count_languages'] == 0 ) {
153         $context['sandbox']['results']['time_end'] = time();
154         $context['results'] = $context['sandbox']['results'];
155         $context['finished'] = 1;
156         return;
157       }
158       break;
160     case 'check' :
161       module_load_include('inc', 'potx');
162       global $_potx_store;
163       potx_status('set', POTX_STATUS_SILENT);
165       $module = array_pop($context['sandbox']['modules']);
167       $path = drupal_get_path('module', $module);
168       $files = _potx_explore_dir($path .'/');
169       $strip_prefix = 1 + strlen($path);
170       $context['sandbox']['results']['module_data'][$module] = array();
171       foreach ($context['sandbox']['languages'] as $langcode) {
172         foreach ($files as $file) {
173           _potx_process_file($file, $strip_prefix);
174         }
175         _potx_build_files(POTX_STRING_RUNTIME, POTX_BUILD_SINGLE, 'general', '_potx_save_string', '_potx_save_version', '_potx_get_header', $langcode, $langcode);
176         $lines = explode("\n", $_potx_store['general']['strings']);
177         $total = $untranslated = 0;
178         foreach ($lines as $lineno => $line) {
179           if (substr($line, 0, 7) == 'msgid "') {
180             $total++;
181           }
182           elseif ((substr($line, 0, 9) == 'msgstr ""') || (substr($line, 0, 12) == 'msgstr[1] ""')) {
183             if (isset($lines[$lineno + 1]) && ($lines[$lineno + 1] == '')) {
184               $untranslated++;
185             }
186           }
187         }
188         //$result = ($total - $untranslated) / $total;
189         $context['sandbox']['results']['data_module'][$module][$langcode]['total'] = $total;
190         $context['sandbox']['results']['data_module'][$module][$langcode]['untranslated'] = $untranslated;
192         $context['sandbox']['results']['data_language'][$langcode][$module]['total'] = $total;
193         $context['sandbox']['results']['data_language'][$langcode][$module]['untranslated'] = $untranslated;
195         $context['sandbox']['results']['sum_language'][$module]['total'] += $total;
196         $context['sandbox']['results']['sum_language'][$module]['untranslated'] += $untranslated;
198         $context['sandbox']['results']['sum_module'][$langcode]['total'] += $total;
199         $context['sandbox']['results']['sum_module'][$langcode]['untranslated'] += $untranslated;
201         unset( $GLOBALS['_potx_store']['general']['strings'], $GLOBALS['_potx_strings']);
202       }
204       $context['message'] = t('Current module is %module', array('%module' => $module)) .'<br />';
205       $context['message'] .= t('Remaining @count', array('@count' => count($context['sandbox']['modules'])));
207   }
209   if (count($context['sandbox']['modules']) == 0) {
210     foreach ($context['sandbox']['results']['sum_language'] as $module => $detail) {
211       $context['sandbox']['results']['sum_language'][$module]['state'] = ($detail['total'] - $detail['untranslated']) / $detail['total'];
212     }
214     foreach ($context['sandbox']['results']['sum_module'] as $langcode => $detail) {
215       $context['sandbox']['results']['sum_module'][$langcode]['state'] = ($detail['total'] - $detail['untranslated']) / $detail['total'];
216     }
218     foreach ($context['sandbox']['results']['data_module'] as $module => $langs) {
219       foreach ($langs as $langcode => $detail) {
220         $state = ($detail['total'] - $detail['untranslated']) / $detail['total'];
221         $context['sandbox']['results']['data_module'][$module][$langcode]['state'] = $state;
222       }
223     }
225     foreach ($context['sandbox']['results']['data_language'] as $langcode => $modules) {
226       foreach ($modules as $module => $detail) {
227         $state = ($detail['total'] - $detail['untranslated']) / $detail['total'];
228         $context['sandbox']['results']['data_language'][$langcode][$module]['state'] = $state;
229       }
230     }
234     $context['sandbox']['results']['time_end'] = time();
235     $context['results'] = $context['sandbox']['results'];
236     $context['finished'] = 1;
237   }
238   else {
239     $context['finished'] = ($context['sandbox']['results']['count_modules'] - count($context['sandbox']['modules'])) / $context['sandbox']['results']['count_modules'];
240   }
243 function langcheck_check_batch_finished($success, $results, $operations) {
244   variable_set('langcheck_check_batch_result', $results);
247 function langcheck_check_batch_result_page() {
248   $results = variable_get('langcheck_check_batch_result', NULL);
249   if ($results === NULL) {
250     return t(
251       'Stored result not fund. To create a new one !link.',
252       array('!link' => l('click here', 'admin/langcheck-batch-start'))
253     );
254   }
256   if ( $results['count_languages'] == 0) {
257     return t('Only the English language is enabled. Check was not necessary.');
258   }
260   $output = t(
261     'The result created %created. To refresh !link.',
262     array(
263       '%created' => format_interval(time() - $results['time_start']),
264       '!link'    => l('click here', 'admin/langcheck-batch-start')
265     )
266   );
268   $output .= theme('langcheck_check_batch_result', $results);
270   drupal_add_css(drupal_get_path('module', 'langcheck') .'/langcheck.css');
272   return $output;
276  * Implementation of hook_theme().
277  */
278 function langcheck_theme() {
279   return array(
280     'langcheck_check_batch_result' => array(
281       'arguments' => array('result' => NULL),
282     ),
283   );
286 function theme_langcheck_check_batch_result($results) {
287   $output = '';
289   $languages = locale_language_list();
291   $header = array(
292     t('Module'),
293   );
294   foreach ($results['data_language'] as $langcode => $modules) {
295     $header[] = $languages[$langcode];
296   }
298   $header[] = t('Module state');
300   $rows = array();
301   foreach ($results['data_module'] as $module => $langs) {
302     //drupal_set_message('<pre>$module = '.check_plain(print_r($module, TRUE)).'</pre>');
303     //drupal_set_message('<pre>$langs = '.check_plain(print_r($langs, TRUE)).'</pre>');
304     $row = array();
305     $row[] = array(
306       'data'  => $module,
307       'class' => 'langcheck-state-'. floor($results['sum_language'][$module]['state'] / 0.1),
308     );
310     foreach ($langs as $langcode => $detail) {
311       $row[] = array(
312         'data' => sprintf('%0.2f%%', $detail['state'] * 100),
313         'class' => 'langcheck-state-'. floor($detail['state'] / 0.1),
314       );
315     }
317     $row[] = array(
318       'data' => sprintf('%0.2f%%',  $results['sum_language'][$module]['state'] * 100),
319       'class' => 'langcheck-state-'. floor($results['sum_language'][$module]['state'] / 0.1),
320     );
322     $rows[] = $row;
323   }
324   $overall = 0;
325   $row = array();
326   $row[] = t('Language state');
327   foreach ($results['sum_module'] as $langcode => $detail) {
328     $overall += $detail['state'];
329     $row[] = array(
330       'data' => sprintf('%0.2f%%',  $detail['state'] * 100),
331       'class' => 'langcheck-state-'. floor($detail['state'] / 0.1),
332     );
333   }
334   $state = $overall / $results['count_languages'];
335   $row[] = array(
336     'data' => sprintf('%0.2f%%',  $state * 100),
337     'class' => 'langcheck-state-'. floor($state / 0.1),
338   );
339   $rows[] = $row;
341   $attributes = array(
342     'class' => 'langcheck-result-table',
343   );
345   return '<div class="langcheck-result-table">'. theme('table', $header, $rows) . '</div>';
347   //return print_r($results, TRUE);
350 // vim: set ft=php syntax=php expandtab ts=2 sw=2 autoindent smartindent: