Skip to content

Instantly share code, notes, and snippets.

@gusrub
Created April 26, 2018 04:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gusrub/e3a380caa2034d084a022bbf2b53418b to your computer and use it in GitHub Desktop.
Save gusrub/e3a380caa2034d084a022bbf2b53418b to your computer and use it in GitHub Desktop.
i18n translation class
<?php
use \InvalidArgumentException as InvalidArgumentException;
/**
* This class contain helper methods to localize and translate the application.
*/
class I18n
{
/**
* @var The original text that is going to be translated
*/
private $originalText;
/**
* @var An array containing key-value pairs for any replacement needed to be
* done within the translation string
*/
private $translationArguments;
/**
* @var The translated text to the target language. Note that this does not
* have yet the interpolated values from $translationArguments
*/
private $translatedText;
/**
* Creates a new instance of a translator.
*
* @param string $str The string to be translated.
* @param Array $args A key value-pair array containing replacements to be
* done in the string.
* @param string $language If this is set, it will override the system
* language or the one configured globally in the application.
* @return I18n A translation object.
*/
private function __construct($str, Array $args = null, $language = null)
{
$this->setLanguage($language);
$this->originalText = $str;
$this->translationArguments = $args;
}
/**
* Sets the language to be used to translate.
*
* This method will, by default, try to get the LOCALE from argument given,
* if none is given, which is the default, it will try to get a default from
* the request if one was given or from the application configuration as a
* fallback.
*
* @param string $language The language to use for the translation. e.g.
* 'es_MX.utf8'
*/
private function setLanguage($language = null)
{
if (is_null($language)) {
$language = $this->getDefaultLanguage();
}
putenv("LC_ALL=$language");
putenv("LC_LANG=$language");
setlocale(LC_ALL, $language);
// // Set the text domain as 'messages'
$domain = 'messages';
bindtextdomain($domain, __DIR__.'/Locale');
textdomain($domain);
}
/**
* Gets the default LOCALE code from either the request or from the
* application configuration.
*
* @return string The LOCALE code, e.g. 'es_MX.utf8'
*/
private function getDefaultLanguage()
{
// let's see if client is requesting a specific language
if (array_key_exists('HTTP_X_LANGUAGE', $_SERVER)) {
$language = $_SERVER['HTTP_X_LANGUAGE'];
} else {
$language = getenv('APP_LANG');
}
return $language;
}
/**
* Checks that the given arguments to replace values in the translation
* match the actual amount of arguments in the translation string.
*/
private function validateArguments()
{
$matches = array();
preg_match_all('/{+(.*?)}/', $this->originalText, $matches);
$matches = $matches[1];
$matchCount = count($matches);
$wrongArgs = false;
if ($matchCount > 0 && is_null($this->translationArguments)) {
$wrongArgs = true;
} else if ($matchCount > 0 && isset($this->translationArguments)) {
$diff = array_diff($matches, array_keys($this->translationArguments));
if (count($diff) > 0) {
$wrongArgs = true;
}
}
if ($wrongArgs) {
throw new InvalidArgumentException("Wrong number of arguments for translation");
}
}
/**
* Extracts the argument values and replaces ocurrences in the translated
* string .
*
* @return string The translated string with the patterns replaced.
*/
private function extractArguments()
{
$patterns = array();
$replacements = array();
$counter = 0;
if (isset($this->translationArguments)) {
foreach ($this->translationArguments as $key => $value) {
$patterns[$counter] = '/'."{{$key}}".'/';
$replacements[$counter] = $value;
$counter++;
}
return preg_replace($patterns, $replacements, $this->translatedText);
}
return $this->translatedText;
}
/**
* Translates a given string of text by using gettext.
*
* This function will take a string of text and try to locale a translateion
* based either on the language given as argument or by searching on the
* reququest, if neither are present then it fallsback to the application
* default configuration.
*
* It can also receive an argument with an array of key-value pairs with
* strings that should be replaced with certain values.
*
* @param string $str The string to be translated.
* @param Array $args A key-value pair array of ocurrences to be replaced in
* the translated string. Defaults to null.
* @param string $language If given, it will override the request info or
* global application configuration and try to translate with this locale.
*
* @return string The translated string.
*/
public static function translate($str, Array $args = null, $language = null)
{
$translation = new self($str, $args, $language);
$translation->validateArguments();
$translation->translatedText = _($translation->originalText);
return $translation->extractArguments();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment