<?php
class I18nBuilder
{
function build($lng='tr')
{
$arr = array();
self::_readDir(CORE_ROOT.'/../', $arr);
//print_r($arr);
$cat = self::getCatalog($lng, 'message,bank');
self::mergeMessageTable($arr, $cat);
ksort($arr);
echo '<p>Generated from php files and existing lng files.</p>';
self::displayBuildTable('build', $arr);
echo '<p>Checking current tr table as base table for given language. First update base tr language file with build values. then check if every word has translation.</p>';
self::check($lng, 'message,bank');
// print new message array
echo '<p>This is new lng file to use. It is populated from frech build to use as base language table.</p>';
echo "<pre>return array (\n";
foreach ($arr as $k => $v)
{
$k_ = '';
$v_ = '';
switch ($v['type'])
{
case '':
case 'not':
// on not or correct key end fixing mode
$fixing = false;
// print
$k_ = $k;
$v_ = $v['trans'];
break;
case 'er':
// start fixing mode
$fixing = true;
break;
case 'rem':
// if fixing then print this
if ($fixing)
{
// print
$k_ = $k;
$v_ = $v['trans'];
}
break;
default:
break;
}
if (strlen($k_))
{
echo "'" . self::viewEscapeQuote($k_) . "'=>'" . self::viewEscapeQuote($v_) . "',\n";
}
}
echo ");\n</pre>";
// print new bank array
echo '<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js" type="text/javascript"></script>';
echo '<script type="text/javascript" src="' . URL_ASSETS . '/js/jquery.tablesorter.min.js"></script> ';
echo '<script>
$(document).ready(function() {
$("#myTable").tablesorter();
});
</script>';
return true;
}
static function viewEscapeQuote($str)
{
return str_replace("'", "\'", View::escape($str));
}
function mergeMessageTable(& $arr, $cat)
{
// find if text in message then do nothing add trans
// if message in blank then add bl as type
// if message not found then add not as type
// if message not found on scan then add rem as type
foreach ($arr as $k => $v)
{
// strings that are broken because of ' stored here. list them seperately for manuel insertion
$trans = $cat['message'][$k];
$type = '';
if (!strlen($trans))
{
$trans = $cat['bank'][$k];
$type = 'new';
}
if (!strlen($trans))
{
$type = 'not';
}
if (!isset($arr[$k]['type']))
{
$arr[$k]['type'] = $type;
}
$arr[$k]['trans'] = $trans;
}
// add records from message cat to arr
$i = 1;
foreach ($cat['message'] as $k => $v)
{
if (!isset($arr[$k]))
{
$arr[$k]['type'] = 'rem';
$arr[$k]['trans'] = $v;
}
$arr[$k]['pos'] = $i;
$i++;
}
}
function displayBuildTable($title, $arr)
{
foreach ($arr as $k => $v)
{
// strings that are broken because of ' stored here. list them seperately for manuel insertion
$trans = $v['trans'];
switch ($v['type'])
{
case 'not':
$style = 'style="background-color:#f00;"';
break;
case 'new':
$style = 'style="background-color:#7DA8C4;"';
break;
case 'rem':
$style = 'style="background-color:#E2E074;"';
break;
default:
$style = '';
break;
}
if ($v['location'])
{
$t = implode(" \n", $v['location']);
}
else
{
$t = '';
}
$echo .= '<tr>
<td ' . $style . '>' . ($v['type'] ? $v['type'] : ' ') . '</td>
<td ' . $style . '>' . ($v['pos'] ? $v['pos'] : 0) . '</td>
<td title="' . $t . '">' . View::escape($k) . '</td>
<td>' . ($trans ? View::escape($trans) : '<div style="background-color:#f00;">-</div>') . '</td></tr>';
}
echo '<h1>' . $title . '</h1>';
echo '<table border="1" cellspacing="0" width="100%" style="font-family:courier;" id="myTable">
<thead><tr><th>type</th><th>pos</th><th>key</th><th>trans</th></tr></thead>
' . $echo . '</table>';
}
function _readDir($dir, & $arr)
{
//echo "_readDir($dir)\n";
$dh = opendir($dir);
while (false !== ($filename = readdir($dh)))
{
if ($filename != '.' && $filename != '..')
{
$file = $dir . DIRECTORY_SEPARATOR . $filename;
if (is_file($file))
{
if (strpos($filename, '.php'))
{
self::_readFile($file, $arr);
}
}
else
{
self::_readDir($file, $arr);
}
}
}
closedir($dh);
}
/**
* find lines with __() function
* @param $file
* @return unknown_type
*/
function _readFile($file, & $arr)
{
//echo "_readFile($file)\n";
$line_num = 1;
$handle = @fopen($file, "r");
if ($handle)
{
while (!feof($handle))
{
$buffer = fgets($handle);
$location = '#' . $file . ' line ' . $line_num . "\n";
if (self::_findString($buffer, $matches))
{
//echo $buffer."\n";
//print_r($matches);
foreach ($matches[1] as $m)
{
$arr[$m]['location'][] = $location;
//echo $m."\n";
}
}
if (self::_findStringError($buffer, $matches))
{
foreach ($matches[1] as $m)
{
$arr[$m]['location'][] = $location;
$arr[$m]['type'] = 'er';
//echo $m."\n";
}
}
$line_num++;
}
fclose($handle);
}
}
function _findString($str, & $matches)
{
//echo "_findString($str,& $matches)";
$matches = false;
$pattern = '/__\(\'([^\']*)[(\'\))|\',]/';
return preg_match_all($pattern, $str, $matches);
}
function _findStringError($str, & $matches)
{
//echo "_findString($str,& $matches)";
$matches = false;
$pattern = '/__\(\'([^\\\\\']*)(\\\\\')/';
return preg_match_all($pattern, $str, $matches);
}
function getCatalog($lng, $catalogs='message')
{
$files = explode(',', $catalogs);
I18n::saveLocale();
I18n::setLocale($lng);
foreach ($files as $f)
{
I18n::loadCatalog($f);
}
$cat = I18n::getCatalogs();
I18n::restoreLocale();
return $cat;
}
function check($lng, $catalog='message')
{
$cat_tr = I18nBuilder::getCatalog('tr', $catalog);
$cat = I18nBuilder::getCatalog($lng, $catalog);
self::displayCatTable($cat_tr, $cat);
}
function displayCatTable($cat_tr, $cat)
{
echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>
<body>
';
foreach ($cat_tr as $key => $c)
{
echo '<h1>' . $key . '</h1>';
echo '<table border="1" cellspacing="0" width="100%" style="font-family:courier;">';
foreach ($c as $k => $v)
{
$trans = $cat[$key][$k];
echo '<tr><td>' . View::escape($k) . '</td><td>' . ($trans ? View::escape($trans) : '<div style="background-color:#f00;">-</div>') . '</td></tr>';
}
echo '</table>';
}
echo '</body>';
//print_r($r);
}
function page($type, $lng='tr')
{
switch ($type)
{
case 'build':
self::build($lng);
break;
case 'translate':
$cat_tr = self::getCatalog('tr');
$cat = self::getCatalog($lng);
self::displayTranslatePage(array(
'cat' => $cat,
'cat_tr' => $cat_tr,
'lng' => $lng
));
break;
case 'check':
self::check($lng);
break;
default:
exit('invalid action type: build,translate,check');
}
}
function displayTranslatePage($vars)
{
extract($vars);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
var lng = '<?php echo $lng ?>';
google.load("language", "1");
var _translate_row_all = false;
var _translate_row_empty = false;
$(function(){
//$('.translate_all').click(translate_all);
//$('.translate_empty').click(translate_empty);
$('.translate_all').click(translate_row_all);
$('.translate_empty').click(translate_row_empty);
$('.print_array').click(populateLanguageVar);
$('.print_array_new').click(populateLanguageVarNew);
});
function translate_row_all()
{
_translate_row_all = true;
var $tr = $('tr[rel!="x"]:first');
if($tr)
{
translateRow($tr);
}
return false;
}
function translate_row_empty()
{
_translate_row_empty = true;
var $tr = $('tr[rel!="x"]:first');
if($tr)
{
var val = $('.v',$tr).text();
if(!val.length){
translateRow($tr);
}
else
{
$tr.attr('rel','x');
translate_row_empty();
}
}
return false;
}
function translate_all()
{
$('tr').each(function(i){
if(1 || i<20){
translateRow($(this));
}
});
return false;
}
function translate_empty()
{
$('tr').each(function(i){
if(1 || i<20){
var $tr = $(this);
var val = $('.v',$tr).text();
if(!val.length){
translateRow($tr);
}
}
});
return false;
}
function translateRow($me)
{
var text = $('.k input',$me).val();
var $dest = $('.g',$me);
$me.attr('rel','x');
text = prepateTextToTranslate(text);
if(text.length){
google.language.translate(text, "en", lng, function(result) {
if (!result.error) {
var t = result.translation;
t = prepateTextToTranslateReverse(t);
//alert(text + "\n\n"+t);
$dest.append('<code></code>');
$('code',$dest).text(t);
$dest.append('<input type="hidden"/>');
$('input',$dest).val(t);
if(_translate_row_empty)
{
translate_row_empty();
}
else if(_translate_row_all)
{
translate_row_all();
}
}
});
}
}
function prepateTextToTranslate(text)
{
text = text.replace(/\"\{blog\}\"/g,'<hr class="blog"/>');
text = text.replace(/\"\{tag\}\"/g,'<hr class="tag"/>');
text = text.replace(/\"\{title\}\"/g,'<hr class="title"/>');
text = text.replace(/\"\{/g,'"[');
text = text.replace(/\}\"/g,']"');
text = text.replace(/{/g,'<br class="');
text = text.replace(/}/g,'"/>');
text = text.replace(/\]\"/g,'}"');
text = text.replace(/\"\[/g,'"{');
return text;
}
function prepateTextToTranslateReverse(t)
{
t = t.replace(/\<hr class=\"blog\"\/\>/g,'"{blog}"');
t = t.replace(/\<hr class=\"tag\"\/\>/g,'"{tag}"');
t = t.replace(/\<hr class=\"title\"\/\>/g,'"{title}"');
t = t.replace(/\<br class=\"/g,'{');
t = t.replace(/\"\/\>/g,'}');
t = t.replace(/\"\;/g,'"');
return t;
}
function populateLanguageVar(){
var str = '';
$('table').each(function(i){
var $table = $(this);
str += "$table_" + i + " = array(\n";
$('tr',$table).each(function(j){
var $me = $(this);
var text = $('.k input',$me).val();
var t = $('.g input',$me).val();
if(t==undefined)
{
t = $('.v',$me).text();
}
else
{
t = t.replace(/'/g,'\\\'');
}
text = text.replace(/'/g,'\\\'');
str += "'"+text+"' => '"+t+"',\n";
});
str += ");\n\n";
});
$('.array').text(str);
return false;
}
function populateLanguageVarNew(){
var str = '';
$('table').each(function(i){
var $table = $(this);
str += "$table_" + i + " = array(\n";
$('tr',$table).each(function(j){
var $me = $(this);
var text = $('.k input',$me).val();
var t = $('.g input',$me).val();
if(t==undefined)
{
t = '';
}
else
{
t = t.replace(/'/g,'\\\'');
}
text = text.replace(/'/g,'\\\'');
if(t)
{
str += "'"+text+"' => '"+t+"',\n";
}
});
str += ");\n\n";
});
$('.array').text(str);
return false;
}
</script>
</head>
<body>
<p>
<a href="#" class="translate_all">translate all</a> |
<a href="#" class="translate_empty">translate empty ones</a> |
<a href="#" class="print_array">print array</a> |
<a href="#" class="print_array_new">print array new entries</a> |
</p>
<pre class="array"></pre>
<?php
foreach ($cat_tr as $key => $c)
{
echo '<h1>' . $key . '</h1>';
echo '<table border="1" cellspacing="0" width="100%">';
foreach ($c as $k => $v)
{
echo '<tr><td class="k">' . View::escape($k) . '<input type="hidden" value="' . View::escape($k) . '" /></td>
<td class="v">' . View::escape($cat[$key][$k]) . '</td>
<td class="g"> </td></tr>';
}
echo '</table>';
}
?>
</body>
</html>
<?php
}
}
// end I18n class