1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227:
<?php
namespace Nethgui\View;
class Translator implements \Nethgui\View\TranslatorInterface, \Nethgui\Utility\PhpConsumerInterface, \Nethgui\Log\LogConsumerInterface
{
private $phpWrapper;
private $catalogs = array();
private $catalogResolver;
public function __construct($languageCode, $catalogResolver, $notUsed = array())
{
if ( ! is_callable($catalogResolver)) {
throw new \InvalidArgumentException(sprintf('%s: $catalogResolver must be a valid callback function.', get_class($this)), 1322240722);
}
$this->log = new \Nethgui\Log\Nullog();
$this->phpWrapper = new \Nethgui\Utility\PhpWrapper();
$this->defaultLanguage = $languageCode;
$this->catalogResolver = $catalogResolver;
}
public function translate(\Nethgui\Module\ModuleInterface $module, $key, $args = array(), $languageCode = NULL)
{
if ( ! isset($languageCode)) {
$languageCode = $this->getLanguageCode();
}
if (empty($languageCode)) {
$translation = $key;
} else {
$catalogStack = $this->extractLanguageCatalogStack($module);
$translation = $this->lookupTranslation((string) $key, $languageCode, $catalogStack);
}
if (empty($args)) {
return $translation;
}
$placeholders = array();
foreach ($args as $argId => $argValue) {
$placeholders[sprintf('${%s}', $argId)] = $argValue;
}
return strtr($translation, $placeholders);
}
private function lookupTranslation($key, $languageCode, $catalogStack)
{
$languageCatalogs = $catalogStack;
$translation = NULL;
$attempts = array();
while (($catalog = array_shift($languageCatalogs)) !== NULL) {
if ( ! isset($this->catalogs[$languageCode][$catalog])) {
$this->loadLanguageCatalog($languageCode, $catalog);
}
if (isset($this->catalogs[$languageCode][$catalog][$key])) {
$translation = $this->catalogs[$languageCode][$catalog][$key];
break;
} else {
$attempts[] = $catalog;
}
}
if ($translation === NULL) {
if ($languageCode === 'en' || NETHGUI_DEBUG === TRUE) {
$translation = $key;
NETHGUI_DEBUG && $this->getLog()->notice(sprintf("%s: `%s` translation not found for `%s`. Catalogs: [%s]",
__CLASS__, $languageCode, $key,
implode(', ', $attempts)));
} else {
return $this->lookupTranslation($key, 'en', $catalogStack);
}
}
return $translation;
}
private function loadLanguageCatalog($languageCode, $languageCatalog)
{
if (preg_match('/^[a-z][a-z]([-_][A-Z][A-Z])?$/', $languageCode) == 0) {
throw new \InvalidArgumentException(sprintf('%s: Language code must be an IETF-like language tag', get_class($this)), 1458301359);
}
if (preg_match('/^[a-z_A-Z0-9]+$/', $languageCatalog) == 0) {
throw new \InvalidArgumentException(sprintf("%s: Language catalog name can contain only alphanumeric or `_` characters. It was `%s`.", get_class($this), $languageCatalog), 1322150265);
}
$filePath = call_user_func($this->catalogResolver, $languageCode, $languageCatalog);
$L = array();
$tmp = $this->getLog()->getLevel();
$this->getLog()->setLevel($tmp & ~E_WARNING);
$included = $this->phpWrapper->phpInclude($filePath, array('L' => &$L));
$this->getLog()->setLevel($tmp);
if ($included) {
NETHGUI_DEBUG && $this->getLog()->notice(sprintf('%s: Loaded language catalog `%s` [%s].', get_class($this), $languageCatalog, $languageCode));
} else {
NETHGUI_DEBUG && $this->getLog()->warning(sprintf('%s: Missing language catalog `%s` [%s].', get_class($this), $languageCatalog, $languageCode));
}
$this->catalogs[$languageCode][$languageCatalog] = &$L;
}
private function extractLanguageCatalogStack(\Nethgui\Module\ModuleInterface $module)
{
$languageCatalogList = array();
$moduleNamespace = \Nethgui\array_head(explode("\\", get_class($module)));
$defaultNamespace = \Nethgui\array_head(explode("\\", get_class($this)));
do {
$catalog = $module->getAttributesProvider()->getLanguageCatalog();
if (is_array($catalog)) {
$languageCatalogList = array_merge($languageCatalogList, $catalog);
} elseif (is_string($catalog)) {
$languageCatalogList[] = $catalog;
}
$module = $module->getParent();
} while ( ! is_null($module));
$languageCatalogList = array_unique(array_merge($languageCatalogList, array($moduleNamespace, $defaultNamespace)));
return $languageCatalogList;
}
public function setPhpWrapper(\Nethgui\Utility\PhpWrapper $object)
{
$this->phpWrapper = $object;
return $this;
}
public function getLog()
{
return $this->log;
}
public function setLog(\Nethgui\Log\LogInterface $log)
{
$this->log = $log;
$this->phpWrapper->setLog($log);
return $this;
}
public function getLanguageCode()
{
return $this->defaultLanguage;
}
}