PHP / JavaScript Translations - Quick and Dirty
Sun, 30 October 2016
Translator.php
<?php
$translations = array(
'animals' => 'The :speed: :color: :animal: jumped over the lazy :otheranimal:',
'plural' => '{1,1}I like :color:||{2,5}I like :color:\\\\'s'
);
class Translator
{
/**
* @var array
*/
private $strings = array();
/**
* @param array $strings
*/
public function __construct(array $strings)
{
$this->strings = $strings;
}
/**
* Translate a single key, giving params and a plural number
* @param string $key
* @param array $params (optional) default array
* @param integer $pluralNumber
* @return string
*/
public function _($key, array $params = array(), $pluralNumber = 0)
{
if (!array_key_exists($key, $this->strings)) {
return $key;
}
// Identify language and fallback here.
$single = $this->strings[$key];
$single = $this->getPluralFromNumber($single, $pluralNumber);
$keys = array_keys($params);
$vals = array_values($params);
foreach ($keys as $position => $keyValue) {
$keys[$position] = ':' . $keyValue . ':';
}
$single = str_replace($keys, $vals, $single);
return $single;
}
/**
* Get the string if a plural is identified
* @param string $string
* @param integer $number
* @return string
*/
private function getPluralFromNumber($string, $number)
{
// Check if pluralised
if (preg_match('/^{[0-9]+,[0-9]+}/', $string)) {
$pluralPieces = explode('||', $string);
foreach ($pluralPieces as $pluralPiece) {
preg_match('/^{[0-9]+,[0-9]+}/', $pluralPiece, $matches);
if (!empty($matches)) {
$limits = explode(',', $matches[0]);
$lower = trim($limits[0]);
$upper = trim($limits[1]);
if ($lower <= $number && $upper >= $number) {
$final = strstr($pluralPiece, '}');
$final = trim($final, '}');
break;
}
}
unset($matches);
}
} else {
$final = $string;
}
return $final;
}
}
test_translator.php
<?php
include 'Translator.php';
$translator = new Translator($translations);
echo $translator->_(
'animals',
array(
'speed' => 'quick',
'color' => 'brown',
'animal' => 'fox',
'otheranimal' => 'dog'
)
);
echo '<br>' . PHP_EOL;
$quantity = 1;
echo $translator->_(
'plural',
array(
'color' => 'red',
),
$quantity
);
echo '<br>' . PHP_EOL;
echo $translator->_(
'nonexistentkey'
);
Translator.phtml
<?php
include 'Translator.php';
?>
<!DOCTYPE unspecified PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
</head>
<body>
<script type="text/javascript">
var translations = <?php echo json_encode($translations); ?>;
var Translator = function() {
var strings = translations;
this._ = function(key, params, number) {
// Handle undefined keys
if (typeof translations[key] == 'undefined') {
return key;
}
var string = translations[key];
string = getPluralFromNumber(string, number);
if (typeof params == 'object') {
for (var property in params) {
string = string.replace(':' + property + ':', params[property]);
}
}
return string;
};
var getPluralFromNumber = function(string, number) {
if (typeof number == 'undefined') {
return string;
}
number = parseInt(number);
var pattern = new RegExp(/^{[0-9]+,[0-9]+}/);
if (pattern.test(string)) {
var pluralPieces = string.split('||');
for (var i=0;i<pluralPieces.length;i++) {
var pluralPiece = pluralPieces[i];
var matches = pluralPiece.match(/^{[0-9]+,[0-9]+}/);
if (matches.length > 0) {
var regexLength = matches[0].length;
var limits = matches[0].split(',');
var lower = parseInt(limits[0].replace('{',''));
var upper = parseInt(limits[1].replace('}',''));
if (lower <= number && upper >= number) {
string = pluralPiece.substring(regexLength);
}
}
}
}
return string;
};
};
var a = new Translator();
console.log(a._('plural', {color:'red'}, 1));
console.log(a._('animals',{speed: 'quick', color: 'brown', animal:'fox', otheranimal:'dog'}));
console.log(a._('nonexistentkey'));
setTimeout(function(){
window.location = window.location.href;
},2000);
</script>
</body>
</html>