Skip to content

Instantly share code, notes, and snippets.

@marcalj
Created October 7, 2011 09:46
Show Gist options
  • Save marcalj/1269918 to your computer and use it in GitHub Desktop.
Save marcalj/1269918 to your computer and use it in GitHub Desktop.
Kohana: i18n strings generator
<?php defined('SYSPATH') or die('No direct script access.');
class Controller_Cron extends Controller {
public function before()
{
// Set default language
I18n::$lang = Kohana::$config->load('i18n.default');
}
public function action_i18n_generator()
{
if ( ! Kohana::$is_cli)
{
echo 'Usage: php index.php --uri=/cron/i18n_generator';
return;
}
$this->auto_render = FALSE;
$path = APPPATH;
$data = array();
$unique_phrases_helper = array();
$scan_files = $this->get_dir_files($path, array('php'));
foreach ($scan_files as $file)
{
$file_path_human = substr($file, strlen($path));
// echo Kohana::debug($file_path_human);
// Get each line of the file
$file_lines = file($file, FILE_IGNORE_NEW_LINES);
$data_file = array();
foreach ($file_lines as $num_line => $file_line)
{
$num_line++;
// echo Kohana::debug($num_line, $file_line, $file_path_human);
// if (preg_match_all('/(?P<key>\w+):(?P<name>[\p{L}+|\D+])/u', $file_line, $matches))
// if (preg_match('/^(?P<name>.*?[^(TO|COPYTO)]+)( TO (?P<assignedto>\w[^(COPYTO)]+))?( COPYTO (?P<copyto>\w[^(TO)]+))?$/u', trim($email['Subject']), $matches))
// if (preg_match_all('/__\(\'(?P<phrase>.+)\'(, ?array\(.+\))?\)/u', $file_line, $matches))
// if (preg_match_all('/__\(\'(?P<phrase>.*)(, ?array\(.+\))?\'\)/u', $file_line, $matches))
// if (preg_match_all("/__\('(?P<phrase>.*?[^;])'\)/u", $file_line, $matches))
// if (preg_match_all("/__\([^'.+'$]\)/u", $file_line, $matches))
// if (preg_match_all("/__\([^_]+\)/u", $file_line, $matches))
// if (preg_match_all("/__\([^\b__]+\)/u", $file_line, $matches))
// if (preg_match_all("/__\((?P<phrase>((?!__).)+)\)/u", $file_line, $matches)) /// NOTE IT WORKS!!!
// if (preg_match_all("/__\((?P<phrase>((?!__)|(?!array).)+)\)/u", $file_line, $matches))
// if (preg_match_all("/__\(('|\")(?P<phrase>((?!__)|(?! ?array ?\().)+)('|\")/u", $file_line, $matches)) /// NOTE IT WORKS!!!
if (preg_match_all("/__\(('|\")(?P<phrase>((?!__)|(?! ?array ?\().)+)('\)|',|\"\)|\",)/u", $file_line, $matches)) /// NOTE IT WORKS!!!
{
// echo Kohana::debug($file_path_human, $num_line, $file_line, $matches);
// echo Kohana::debug($file_path_human, $num_line, $file_line, $matches['phrase']);
// echo Kohana::debug($matches['phrase']);
$new_phrases = array_diff(array_unique($matches['phrase']), $unique_phrases_helper);
if ($new_phrases)
{
$data_file[] = array(
'line_number' => $num_line,
'line_string' => $file_line,
'phrases' => $new_phrases,
);
$unique_phrases_helper = array_merge($new_phrases, $unique_phrases_helper);
}
}
}
if ($data_file)
{
$data[] = array(
'filepath' => $file,
'filepath_human' => $file_path_human,
'lines' => $data_file,
);
}
}
// echo Kohana::debug($data);
$languages = Kohana::$config->load('i18n.languages');
$default_language = Kohana::$config->load('i18n.default');
$orphe_phrases = array();
// Fix phrases
foreach ($unique_phrases_helper as $key => $phrase)
{
$unique_phrases_helper[$key] = str_replace('\\\'', '\'', $unique_phrases_helper[$key]);
$unique_phrases_helper[$key] = str_replace('\\"', '"', $unique_phrases_helper[$key]);
}
// Add phrases present in current i18n language files but are not present in current code
foreach ($languages as $language_code => $language)
{
$i18n_messages = array_keys(I18n::load($language_code));
$orphe_phrases = array_merge($orphe_phrases, array_diff($i18n_messages, $unique_phrases_helper));
}
$orphe_phrases = array_unique($orphe_phrases);
// echo Kohana::debug($orphe_phrases);
// Generate new i18n files
foreach ($languages as $language_code => $language)
{
if ($default_language !== $language_code)
{
$filename = APPPATH.'i18n/'.$language_code.'.php';
if (file_exists($filename))
{
rename($filename, $filename.'.old');
}
$content = View::factory('i18n_generator')
->bind('data', $data)
->set('orphe_phrases', $orphe_phrases)
->set('language_code', $language_code);
if (FALSE === file_put_contents($filename, $content))
{
echo 'There\'s an error writing the file: '.$filename."\n";
}
else
{
echo 'File ok: '.$filename."\n";
}
}
}
// Fix permissions
// system('chown marcalj:marcalj '.APPPATH.'logs/i18n/*');
echo 'Finish';
}
/**
* Working tests:
*
* <?php echo __('tèst1'); ?>
* <?php echo __('tést2 :mico', array(':mico' => I18n::$lang)); ?>
* <?php echo __('tëst3 :mico', array(':mico' => I18n::$lang)); ?><?php echo __('test4'); ?>
* <?php echo __('test5 :mico', array(':mico' => I18n::$lang)).__('test6'); ?>
* <?php echo __('test7 :mico', array(':mico' => HTML::anchor(Route::get('website/new-tradu')->uri(array('language' => I18n::$lang)), __('test8')))); ?>
* <?php echo __('test9 :mico', array(':mico' => HTML::anchor(Route::get('website/new-tradu')->uri(array('language' => I18n::$lang)), __('test10 :moco', array(':moco' => I18n::$lang))))); ?>
* <?php echo __('tést11'); ?><?php echo __('tést12'); ?>
* <?php echo __('test13'); ?><?php echo __('tëst14 :mico', array(':mico' => I18n::$lang)); ?>
* <?php echo __('tést15'); ?><?php echo __('tést16'); ?><?php echo __('tést17'); ?>
* <?php echo __('tést18_jodete'); ?>
* <?php echo __('tést19;'); ?>
* <?php echo __("tést20;"); ?>
* <?php echo __('tést21 you\'re'); ?>
* <?php echo __('tést21 "enviar"'); ?>
*/
public function get_dir_files($dir, $types = NULL)
{
// Remove DIRECTORY_SEPARATOR at the end
$dir = rtrim($dir, DIRECTORY_SEPARATOR);
$path = '';
$stack[] = $dir;
while ($stack)
{
$thisdir = array_pop($stack);
if ($dircont = scandir($thisdir))
{
$i = 0;
while (isset($dircont[$i]))
{
if ($dircont[$i] !== '.' && $dircont[$i] !== '..')
{
$current_file = $thisdir.DIRECTORY_SEPARATOR.$dircont[$i];
if (is_file($current_file))
{
if (is_array($types))
{
if (in_array(strtolower(pathinfo($thisdir.$dircont[$i], PATHINFO_EXTENSION)), $types, TRUE))
{
$path[] = $thisdir.DIRECTORY_SEPARATOR.$dircont[$i];
}
}
}
elseif (is_dir($current_file))
{
$stack[] = $current_file;
}
}
$i++;
}
}
}
return $path;
}
/// FIXME use this function (alert!! it's recursive!)
/**
* Recursively finds all of the files in the specified directory at any
* location in the [Cascading Filesystem](kohana/files), and returns an
* array of all the files found, sorted alphabetically.
*
* // Find all view files.
* $views = Kohana::list_files('views');
*
* @param string directory name
* @param array list of paths to search
* @return array
*/
// public static function list_files($directory = NULL, array $paths = NULL)
} // End Cron
<?php defined('SYSPATH') or die('No direct access allowed.');
return array
(
'languages' => array(
'en' => 'English',
'ca' => 'Català',
'es' => 'Español',
'fr' => 'Français',
),
// The default language correspond to the language wrote in PHP code
'default' => 'en',
);
/// NOTE when adding more languages we need to check for the respective JS plugins' translations
<?php
print(Kohana::FILE_SECURITY."\n\n");
print("return array(\n");
foreach ($data as $file)
{
print("\t// ".$file['filepath_human']."\n");
foreach ($file['lines'] as $line)
{
$line['line_string'] = str_replace('<?php', '', $line['line_string']);
$line['line_string'] = str_replace('<?', '', $line['line_string']);
$line['line_string'] = str_replace('?>', '', $line['line_string']);
$line['line_string'] = trim($line['line_string']);
foreach ($line['phrases'] as $phrase)
{
$phrase_fixed = str_replace('\\\'', '\'', $phrase);
$phrase_fixed = str_replace('\\"', '"', $phrase_fixed);
$phrase_translated = I18n::get($phrase_fixed, $language_code);
$phrase_translated_fixed = str_replace('\'', '\\\'', $phrase_translated);
$not_translated = '';
if ($phrase_fixed === $phrase_translated)
{
$not_translated = '/// TODO';
$phrase_translated_fixed = '';
}
// print($not_translated."\t'$phrase' => '".$phrase_translated_fixed."', // ".$line['line_number'].": ".$line['line_string']."\n");
print($not_translated."\t'$phrase' => '".$phrase_translated_fixed."', // ".$line['line_number']."\n");
}
}
print("\n");
}
// Orphan phrases
print("\t// Orphan phrases\n");
foreach ($orphe_phrases as $phrase)
{
$phrase_translated = I18n::get($phrase, $language_code);
$not_translated = '';
if ($phrase === $phrase_translated)
{
$not_translated = '/// TODO';
$phrase_translated = '';
}
print($not_translated."\t'$phrase' => '".$phrase_translated."',\n");
}
print(");\n");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment