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>