/** * */ public function createLocalizedViews() { // init $languages = Tool::getValidLanguages(); $defaultTable = 'object_query_' . $this->model->getClass()->getId(); $db = $this->db; /** * macro for creating ifnull statement * @param string $field * @param array $languages * * @return string */ $getFallbackValue = function ($field, array $languages) use(&$getFallbackValue, $db) { // init $lang = array_shift($languages); // get fallback for current language $fallback = count($languages) > 0 ? $getFallbackValue($field, $languages) : 'null'; // create query $sql = sprintf('ifnull(`%s`.`%s`, %s)', $lang, $field, $fallback); return $fallback !== 'null' ? $sql : $db->quoteIdentifier($lang) . '.' . $db->quoteIdentifier($field); }; foreach ($languages as $language) { try { $tablename = $this->getQueryTableName() . "_" . $language; // get available columns $viewColumns = array_merge($this->db->fetchAll('SHOW COLUMNS FROM `' . $defaultTable . '`'), $this->db->fetchAll('SHOW COLUMNS FROM `objects`')); $localizedColumns = $this->db->fetchAll('SHOW COLUMNS FROM `' . $tablename . '`'); // get view fields $viewFields = []; foreach ($viewColumns as $row) { $viewFields[] = $this->db->quoteIdentifier($row['Field']); } // create fallback select $localizedFields = []; $fallbackLanguages = array_unique(Tool::getFallbackLanguagesFor($language)); array_unshift($fallbackLanguages, $language); foreach ($localizedColumns as $row) { $localizedFields[] = $getFallbackValue($row['Field'], $fallbackLanguages) . sprintf(' as "%s"', $row['Field']); } // create view select fields $selectViewFields = implode(',', array_merge($viewFields, $localizedFields)); // create view $viewQuery = <<<QUERY CREATE OR REPLACE VIEW `object_localized_{$this->model->getClass()->getId()}_{$language}` AS SELECT {$selectViewFields} FROM `{$defaultTable}` JOIN `objects` ON (`objects`.`o_id` = `{$defaultTable}`.`oo_id`) QUERY; // join fallback languages foreach ($fallbackLanguages as $lang) { $viewQuery .= <<<QUERY LEFT JOIN {$this->getQueryTableName()}_{$lang} as {$lang} ON( 1 AND {$defaultTable}.oo_id = {$lang}.ooo_id ) QUERY; } // execute $this->db->query($viewQuery); } catch (\Exception $e) { Logger::error($e); } } }
/** * @param array|string $messageId * @param null $locale * @return array|string * @throws \Exception */ public function translate($messageId, $locale = null) { $messageIdOriginal = $messageId; $messageId = mb_strtolower($messageId); // the maximum length of message-id's is 255 if (strlen($messageId) > 255) { throw new \Exception("Pimcore_Translate: Message ID's longer than 255 characters are invalid!"); } if ($locale === null) { $locale = $this->_options['locale']; } // list isn't cacheable, just get a single item if (!$this->isCacheable) { $backend = self::getBackend(); $translation = $backend::getByKeyLocalized($messageIdOriginal, true, true, $locale); if ($translation == $messageIdOriginal) { foreach (Tool::getFallbackLanguagesFor($locale) as $fallbackLanguage) { $translation = $backend::getByKeyLocalized($messageIdOriginal, true, true, $fallbackLanguage); if ($translation != $messageIdOriginal) { break; } } } return $translation; } if (empty($this->_translate[$locale])) { $this->_loadTranslationData(null, $locale); } if (!empty($this->_translate[$locale][$messageId])) { // return original translation return $this->_translate[$locale][$messageId]; } else { // check if there is a translation in a lower step $keyParts = explode(".", $messageId); if (count($keyParts) > 1) { krsort($keyParts); $keysLoop = array(); foreach ($keyParts as $key) { array_unshift($keysLoop, $key); $tmpKey = implode(".", $keysLoop); if (!empty($this->_translate[$locale][$tmpKey])) { return $this->_translate[$locale][$tmpKey]; } } } // check if there is a translation in a lower step (without reverting the keys) $tmpKey = $messageId; if (strrpos($tmpKey, ':')) { while ($tmpKey = substr($tmpKey, 0, strrpos($tmpKey, ':'))) { if (!empty($this->_translate[$locale][$tmpKey])) { return $this->_translate[$locale][$tmpKey]; } } } } // do not create a new translation if it is only empty, but do not return empty values if (!array_key_exists($messageId, $this->_translate[$locale])) { $this->createEmptyTranslation($locale, $messageIdOriginal); } else { // look for a fallback translation foreach (Tool::getFallbackLanguagesFor($locale) as $fallbackLanguage) { // check if data for fallback language is loaded, if not force it if (empty($this->_translate[$fallbackLanguage])) { $this->_loadTranslationData(null, $fallbackLanguage); } if (!empty($this->_translate[$fallbackLanguage][$messageId])) { return $this->_translate[$fallbackLanguage][$messageId]; } } } // no translation found, return original return $messageIdOriginal; }
/** * @param $name * @param null $language * @return */ public function getLocalizedValue($name, $language = null, $ignoreFallbackLanguage = false) { $data = null; $language = $this->getLanguage($language); $fieldDefinition = $this->getObject()->getClass()->getFieldDefinition("localizedfields")->getFieldDefinition($name); if ($fieldDefinition instanceof Model\Object\ClassDefinition\Data\CalculatedValue) { $valueData = new Model\Object\Data\CalculatedValue($fieldDefinition->getName()); $valueData->setContextualData("localizedfield", "localizedfields", null, $language); $data = Service::getCalculatedFieldValue($this->getObject(), $valueData); return $data; } if ($this->languageExists($language)) { if (array_key_exists($name, $this->items[$language])) { $data = $this->items[$language][$name]; } } // check for inherited value $doGetInheritedValues = AbstractObject::doGetInheritedValues(); if ($fieldDefinition->isEmpty($data) && $doGetInheritedValues) { $object = $this->getObject(); $class = $object->getClass(); $allowInherit = $class->getAllowInherit(); if ($allowInherit) { if ($object->getParent() instanceof AbstractObject) { $parent = $object->getParent(); while ($parent && $parent->getType() == "folder") { $parent = $parent->getParent(); } if ($parent && ($parent->getType() == "object" || $parent->getType() == "variant")) { if ($parent->getClassId() == $object->getClassId()) { $method = "getLocalizedfields"; if (method_exists($parent, $method)) { $localizedFields = $parent->getLocalizedFields(); if ($localizedFields instanceof Localizedfield) { if ($localizedFields->object->getId() != $this->object->getId()) { $data = $localizedFields->getLocalizedValue($name, $language, true); } } } } } } } } // check for fallback value if ($fieldDefinition->isEmpty($data) && !$ignoreFallbackLanguage && self::doGetFallbackValues()) { foreach (Tool::getFallbackLanguagesFor($language) as $l) { if ($this->languageExists($l)) { if (array_key_exists($name, $this->items[$l])) { $data = $this->getLocalizedValue($name, $l); } } } } if ($fieldDefinition && method_exists($fieldDefinition, "preGetData")) { $data = $fieldDefinition->preGetData($this, array("data" => $data, "language" => $language, "name" => $name)); } return $data; }
protected function getFallbackValue($groupId, $keyId, $language, $fielddefinition) { $fallbackLanguages = Tool::getFallbackLanguagesFor($language); $data = null; foreach ($fallbackLanguages as $l) { if (array_key_exists($groupId, $this->items) && array_key_exists($keyId, $this->items[$groupId]) && array_key_exists($l, $this->items[$groupId][$keyId])) { $data = $this->items[$groupId][$keyId][$l]; if (!$fielddefinition->isEmpty($data)) { return $data; } } } foreach ($fallbackLanguages as $l) { $data = $this->getFallbackValue($groupId, $keyId, $l, $fielddefinition); } return $data; }