Created
April 26, 2018 04:23
-
-
Save gusrub/e3a380caa2034d084a022bbf2b53418b to your computer and use it in GitHub Desktop.
i18n translation class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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