/** * Get elements * * @return array */ public function getItems() { $elements = parent::getItems(); $translations = array(); $groups = array(); foreach ($elements as $element) { if (!empty($element->group_id)) { $groups[] = $element->group_id; } $translation = new NenoContentElementTranslation($element, false); $translations[] = $translation->prepareDataForView(true); } if (!empty($groups)) { $this->setState('filter.parent_group_id', $groups); } return $translations; }
/** * Consolidate Translation * * @param int $translationId Translation id * * @return bool True on success */ public function consolidateTranslations($translationId) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId); $db = JFactory::getDbo(); $query = $db->getQuery(true); if (!empty($translation)) { $translationsToConsolidate = NenoContentElementTranslation::load(array('original_text' => $translation->getOriginalText(), 'language' => $translation->getLanguage(), 'id' => array('_field' => 'id', '_condition' => '<>', '_value' => $translation->getId()))); /* @var $translationToConsolidate NenoContentElementTranslation */ foreach ($translationsToConsolidate as $translationToConsolidate) { $translationToConsolidate->setString($translation->getString())->setState(NenoContentElementTranslation::TRANSLATED_STATE)->persist(); } } return true; }
/** * Consolidate Translation * * @param int $translationId Translation id * * @return bool True on success */ public function consolidateTranslations($translationId) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId, false, true); if (!empty($translation)) { $translationsToConsolidate = NenoContentElementTranslation::load(array('original_text' => $translation->getOriginalText(), 'language' => $translation->getLanguage(), 'id' => array('_field' => 'id', '_condition' => '<>', '_value' => $translation->getId())), false, true); // Making sure that is an array if (!is_array($translationsToConsolidate)) { $translationsToConsolidate = array($translationsToConsolidate); } /* @var $translationToConsolidate NenoContentElementTranslation */ foreach ($translationsToConsolidate as $translationToConsolidate) { $translationToConsolidate->setString($translation->getString())->setState(NenoContentElementTranslation::TRANSLATED_STATE)->persist(); } } return true; }
/** * Trash translations when the user click on the trash button * * @param NenoContentElementTable $table Table where the element was trashed * @param mixed $pk Primary key value * * @return void */ protected function trashTranslations(NenoContentElementTable $table, $pk) { $db = JFactory::getDbo(); $primaryKeys = $table->getPrimaryKeys(); $query = $db->getQuery(true); $query->select('tr.id')->from('#__neno_content_element_translations AS tr'); /* @var $primaryKey NenoContentElementField */ foreach ($primaryKeys as $key => $primaryKey) { $alias = 'ft' . $key; $query->where("exists(SELECT 1 FROM #__neno_content_element_fields_x_translations AS {$alias} WHERE {$alias}.translation_id = tr.id AND {$alias}.field_id = " . $primaryKey->getId() . " AND {$alias}.value = " . $db->quote($pk) . ")"); } $db->setQuery($query); $translationIds = $db->loadColumn(); foreach ($translationIds as $translationId) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId); $translation->remove(); } }
public function saveExternalTranslatorsComment() { $input = $this->input; $placement = $input->post->getString('placement'); $comment = $input->post->getHtml('comment', ''); $result = false; $db = JFactory::getDbo(); $query = $db->getQuery(true); switch ($placement) { case 'general': NenoSettings::set('external_translators_notes', $comment); $result = true; break; case 'language': $language = $input->post->getString('language'); $query->select('*')->from('#__neno_language_external_translators_comments')->where('language = ' . $db->quote($language)); $db->setQuery($query); $languageComment = $db->loadObject(); if (empty($languageComment)) { $languageComment = new stdClass(); $languageComment->language = $language; } $languageComment->comment = $comment; if (empty($languageComment->id)) { $db->insertObject('#__neno_language_external_translators_comments', $languageComment, 'id'); } else { $db->updateObject('#__neno_language_external_translators_comments', $languageComment, 'id'); } $result = true; break; case 'string': $translationId = $input->post->getInt('stringId'); /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId, false, true); $result = $translation->setComment($comment)->persist(); $allTranslations = $input->post->getBool('alltranslations', false); if ($allTranslations) { $contentId = $input->post->getInt('contentId'); if (!empty($contentId)) { $query->update('#__neno_content_element_translations')->set('comment = ' . $db->quote($comment))->where(array('content_id = ' . $db->quote($contentId), 'content_type = ' . $db->quote($translation->getContentType()), 'language = ' . $db->quote($translation->getLanguage()))); $db->setQuery($query); $db->execute(); $query->clear(); if ($translation->getContentType() == NenoContentElementTranslation::DB_STRING) { $query->update('#__neno_content_element_fields'); } else { $query->update('#__neno_content_element_language_strings'); } // Saving this comment for the future $query->set('comment = ' . $db->quote($comment))->where('id = ' . $db->quote($contentId)); $db->setQuery($query); $db->execute(); } } break; } echo $result ? 'ok' : 'err'; JFactory::getApplication()->close(); }
/** * Get an object with the amount of words per state * * @return stdClass */ public function getWordCount() { if ($this->wordCount === null) { $this->wordCount = new stdClass(); $this->wordCount->total = 0; $this->wordCount->untranslated = 0; $this->wordCount->translated = 0; $this->wordCount->queued = 0; $this->wordCount->changed = 0; $db = JFactory::getDbo(); $query = $db->getQuery(true); $workingLanguage = NenoHelper::getWorkingLanguage(); $query->select(array('SUM(word_counter) AS counter', 't.state'))->from($db->quoteName(NenoContentElementLanguageString::getDbTable()) . ' AS ls')->innerJoin($db->quoteName(NenoContentElementLanguageFile::getDbTable()) . ' AS lf ON ls.languagefile_id = lf.id')->innerJoin($db->quoteName(NenoContentElementTranslation::getDbTable()) . ' AS t ON t.content_id = ls.id AND t.content_type = ' . $db->quote('lang_string') . ' AND t.language LIKE ' . $db->quote($workingLanguage))->where('lf.group_id = ' . $this->getId())->group('t.state'); $db->setQuery($query); $statistics = $db->loadAssocList('state'); // Assign the statistics foreach ($statistics as $state => $data) { switch ($state) { case NenoContentElementTranslation::NOT_TRANSLATED_STATE: $this->wordCount->untranslated = (int) $data['counter']; break; case NenoContentElementTranslation::QUEUED_FOR_BEING_TRANSLATED_STATE: $this->wordCount->queued = (int) $data['counter']; break; case NenoContentElementTranslation::SOURCE_CHANGED_STATE: $this->wordCount->changed = (int) $data['counter']; break; case NenoContentElementTranslation::TRANSLATED_STATE: $this->wordCount->translated = (int) $data['counter']; break; } } $query->clear()->select(array('SUM(word_counter) AS counter', 'tr.state'))->from('#__neno_content_element_tables AS t')->innerJoin('#__neno_content_element_fields AS f ON f.table_id = t.id')->innerJoin('#__neno_content_element_translations AS tr ON tr.content_id = f.id AND tr.content_type = ' . $db->quote('db_string') . ' AND tr.language LIKE ' . $db->quote($workingLanguage))->where(array('t.group_id = ' . $this->getId(), 't.translate IN (1,2)', 'f.translate = 1'))->group('tr.state'); $db->setQuery($query); $statistics = $db->loadAssocList('state'); // Assign the statistics foreach ($statistics as $state => $data) { switch ($state) { case NenoContentElementTranslation::NOT_TRANSLATED_STATE: $this->wordCount->untranslated = (int) $data['counter'] + $this->wordCount->untranslated; break; case NenoContentElementTranslation::QUEUED_FOR_BEING_TRANSLATED_STATE: $this->wordCount->queued = (int) $data['counter'] + $this->wordCount->queued; break; case NenoContentElementTranslation::SOURCE_CHANGED_STATE: $this->wordCount->changed = (int) $data['counter'] + $this->wordCount->changed; break; case NenoContentElementTranslation::TRANSLATED_STATE: $this->wordCount->translated = (int) $data['counter'] + $this->wordCount->translated; break; } } $this->wordCount->total = $this->wordCount->untranslated + $this->wordCount->queued + $this->wordCount->changed + $this->wordCount->translated; } return $this->wordCount; }
public function refreshWordCount() { $input = $this->input; // Refresh content for groups $groups = $input->get('groups', array(), 'ARRAY'); $tables = $input->get('tables', array(), 'ARRAY'); $files = $input->get('files', array(), 'ARRAY'); $workingLanguage = NenoHelper::getWorkingLanguage(); /* @var $db NenoDatabaseDriverMysqlx */ $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('tr.id')->from('#__neno_content_element_translations AS tr')->innerJoin('#__neno_content_element_fields AS f ON tr.content_id = f.id')->innerJoin('#__neno_content_element_tables AS t ON t.id = f.table_id')->where(array('tr.state = ' . $db->quote(NenoContentElementTranslation::TRANSLATED_STATE), 'tr.language = ' . $db->quote($workingLanguage))); if (!empty($groups)) { $query->innerJoin('#__neno_content_element_groups AS g ON t.group_id = g.id')->where('g.id IN (' . implode(',', $db->quote($groups)) . ')'); } elseif (!empty($tables) || !empty($files)) { $where = array(); if (!empty($tables)) { $where[] = '(t.id IN (' . implode(',', $db->quote($tables)) . ') AND tr.content_type = ' . $db->quote(NenoContentElementTranslation::DB_STRING) . ')'; } if (!empty($files)) { $where[] = '(t.id IN (' . implode(',', $db->quote($tables)) . ') AND tr.content_type = ' . $db->quote(NenoContentElementTranslation::LANG_STRING) . ')'; } $query->where('(' . implode(' OR ', $where) . ')'); } $db->setQuery($query); $translationIds = $db->loadArray(); foreach ($translationIds as $translationId) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId, false, true); $translation->persist(); } JFactory::getApplication()->redirect('index.php?option=com_neno&view=groupselements'); }
/** * Process a file * * @return bool True on success, false otherwise */ public function processJobFinished() { $config = JFactory::getConfig(); $tmpPath = $config->get('tmp_path'); $filename = $this->getFileName(); $fileContents = json_decode(file_get_contents($tmpPath . '/' . $filename . '.json' . '/' . $filename . '.json'), true); if ($fileContents !== null) { foreach ($fileContents['strings'] as $translationId => $translationText) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId); $translation->setString($translationText); // Mark this translation method as completed $translation->markTranslationMethodAsCompleted($this->translationMethod->id); if ($translation->isBeingCompleted()) { $translation->setState(NenoContentElementTranslation::TRANSLATED_STATE); } $translation->persist(); } return true; } return false; }
/** * Persist all the translations * * @param array|null $recordId Record id to just load that row * @param string|null $language Language tag * * @return bool True on success */ public function persistTranslations($recordId = null, $language = null) { if ($this->translate) { $commonData = array('contentType' => NenoContentElementTranslation::DB_STRING, 'contentId' => $this->getId(), 'content' => $this, 'state' => NenoContentElementTranslation::NOT_TRANSLATED_STATE, 'timeAdded' => new DateTime(), 'comment' => $this->comment); if ($language !== null) { $languageData = new stdClass(); $languageData->lang_code = $language; $languages = array($languageData); } else { $languages = NenoHelper::getLanguages(false); } $defaultLanguage = NenoSettings::get('source_language'); $this->translations = array(); $strings = $this->getStrings($recordId); $primaryKeyData = $this->getTable()->getPrimaryKey(); $translationmethods = NenoHelper::getTranslationMethodsByTableId($this->table->getId()); if (!empty($strings)) { foreach ($strings as $string) { $progressCounters = $this->getProgressCounters(); if (!NenoSettings::get('installation_completed')) { NenoHelper::setSetupState(JText::sprintf('COM_NENO_INSTALLATION_MESSAGE_PARSING_GROUP_TABLE_FIELD_PROGRESS', $this->getTable()->getGroup()->getGroupName(), $this->getTable()->getTableName(), $this->getFieldName(), $progressCounters['processed'], $progressCounters['total']), 3); } if ($string['state'] == 1 || $string['state'] == 0 && NenoSettings::get('copy_unpublished', 1) || $string['state'] == -2 && NenoSettings::get('copy_trashed', 0)) { foreach ($languages as $language) { if ($defaultLanguage !== $language->lang_code) { $commonData['language'] = $language->lang_code; $commonData['string'] = $string['string']; // If the string is empty or is a number, let's mark as translated. if (empty($string['string']) || is_numeric($string['string'])) { $commonData['state'] = NenoContentElementTranslation::TRANSLATED_STATE; } else { $commonData['state'] = NenoContentElementTranslation::NOT_TRANSLATED_STATE; } $translation = new NenoContentElementTranslation($commonData); $sourceData = array(); $fieldBreakpoint = array(); foreach ($primaryKeyData as $primaryKey) { $field = self::getFieldByTableAndFieldName($this->getTable(), $primaryKey); $fieldData = array('field' => $field, 'value' => $string[$primaryKey]); $sourceData[] = $fieldData; $fieldBreakpoint[$primaryKey] = $string[$primaryKey]; } // Save breakpoint into the database NenoSettings::set('field_breakpoint', json_encode($fieldBreakpoint)); $translation->setSourceElementData($sourceData); // If the translation does not exists already, let's add it if ($translation->existsAlready()) { $translation = NenoContentElementTranslation::getTranslationBySourceElementData($sourceData, $language->lang_code, $this->getId()); $translation->setElement($this); if ($translation->refresh()) { $translation->persist(); } } $translationMethods = $translation->getTranslationMethods(); if (empty($translationMethods[$language->lang_code])) { if (!empty($translationmethods[$language->lang_code])) { $translationMethodsTr = $translationmethods[$language->lang_code]; foreach ($translationMethodsTr as $translationMethodTr) { $translation->addTranslationMethod($translationMethodTr->translation_method_id); } } } $translation->persist(); $this->translations[] = $translation; } } } } NenoSettings::set('field_breakpoint', null); } } else { for ($i = 0; $i < count($this->translations); $i++) { $translation = $this->translations[$i]; /* @var $translation NenoContentElementTranslation */ $translation->refresh(); $this->translations[$i] = $translation; } } return true; }
/** * Save translation as completed * * @return void */ public function saveAsCompleted() { $input = $this->input; $translationId = $input->getInt('id'); $translationText = $input->get('text', '', 'RAW'); if ($this->saveTranslation($translationId, $translationText, NenoContentElementTranslation::TRANSLATED_STATE)) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId, false); $data = array('translation' => $translation->prepareDataForView()); $original_text = $translation->getOriginalText(); $model = $this->getModel(); $counter = $model->getSimilarTranslationsCounter($translationId, $translation->getLanguage(), $original_text); if ($counter != 0) { $data['message'] = JText::sprintf('COM_NENO_EDITOR_CONSOLIDATE_MESSAGE', $counter, NenoHelper::html2text($original_text, 200), NenoHelper::html2text($translationText, 200)); $data['counter'] = $counter; } echo json_encode($data); } JFactory::getApplication()->close(); }
/** * Apply filter to existing translations * * @return void */ public function applyFiltersToExistingContent() { $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select('t.id')->from('#__neno_content_element_translations AS t')->where(array('t.content_type = ' . $db->quote('db_string'), 'EXISTS (SELECT 1 FROM #__neno_content_element_fields AS f ON t.content_id = f.id WHERE f.table_id = ' . (int) $this->id . ')')); $db->setQuery($query); $translationIds = $db->loadColumn(); $filters = $this->getTableFilters(); foreach ($translationIds as $translationId) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId, false, true); $sqlQuery = $translation->generateSQLStatement(); $sqlQuery->clear('select')->select('1'); foreach ($filters as $filter) { $query->where($db->quoteName($filter['field']) . ' ' . $filter['operator'] . ' ' . $db->quote($filter['value'])); } $db->setQuery($query); $result = $db->loadResult(); // If the translation does not meet this requirements, let's delete it if (empty($result)) { $translation->remove(); } } }
/** * Persist all the translations * * @param array|null $recordId Record id to just load that row * @param string|null $language Language tag * * @return bool True on success */ public function persistTranslations($recordId = null, $language = null) { if ($this->translate) { $commonData = array('contentType' => NenoContentElementTranslation::DB_STRING, 'contentId' => $this->getId(), 'content' => $this, 'state' => NenoContentElementTranslation::NOT_TRANSLATED_STATE, 'timeAdded' => new DateTime(), 'comment' => $this->comment); if ($language != null) { $languageData = new stdClass(); $languageData->lang_code = $language; $languages = array($languageData); } else { $languages = NenoHelper::getLanguages(); } $defaultLanguage = NenoSettings::get('source_language'); $this->translations = array(); $strings = $this->getStrings($recordId); $primaryKeyData = $this->getTable()->getPrimaryKey(); /* @var $db NenoDatabaseDriverMysqlx */ $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select(array('gtm.lang', 'gtm.translation_method_id'))->from('#__neno_content_element_tables AS t')->innerJoin('#__neno_content_element_groups AS g ON t.group_id = g.id')->innerJoin('#__neno_content_element_groups_x_translation_methods AS gtm ON gtm.group_id = g.id')->where('t.id = ' . $this->table->getId()); $db->setQuery($query); $translationmethods = $db->loadObjectListMultiIndex('lang'); if (!empty($strings)) { foreach ($languages as $language) { if ($defaultLanguage !== $language->lang_code) { $commonData['language'] = $language->lang_code; foreach ($strings as $string) { if ($string['state'] == 1 || $string['state'] == 0 && NenoSettings::get('copy_unpublished', 1) || $string['state'] == -2 && NenoSettings::get('copy_trashed', 0)) { $commonData['string'] = $string['string']; // If the string is empty or is a number, let's mark as translated. if (empty($string['string']) || is_numeric($string['string'])) { $commonData['state'] = NenoContentElementTranslation::TRANSLATED_STATE; } else { $commonData['state'] = NenoContentElementTranslation::NOT_TRANSLATED_STATE; } $translation = new NenoContentElementTranslation($commonData); $sourceData = array(); foreach ($primaryKeyData as $primaryKey) { $field = self::getFieldByTableAndFieldName($this->getTable(), $primaryKey); $fieldData = array('field' => $field, 'value' => $string[$primaryKey]); $sourceData[] = $fieldData; } $translation->setSourceElementData($sourceData); // If the translation does not exists already, let's add it if ($translation->existsAlready()) { $translation = NenoContentElementTranslation::getTranslationBySourceElementData($sourceData, $language->lang_code, $this->getId()); $translation->setElement($this); if ($translation->refresh()) { $translation->persist(); } } $translationMethods = $translation->getTranslationMethods(); if (empty($translationMethods[$language->lang_code])) { $translationMethodsTr = $translationmethods[$language->lang_code]; if (!empty($translationMethodsTr)) { foreach ($translationMethodsTr as $translationMethodTr) { $translation->addTranslationMethod($translationMethodTr->translation_method_id); } } } $translation->persist(); $this->translations[] = $translation; } } } } } } else { for ($i = 0; $i < count($this->translations); $i++) { $translation = $this->translations[$i]; /* @var $translation NenoContentElementTranslation */ $translation->setState(NenoContentElementTranslation::SOURCE_CHANGED_STATE); $this->translations[$i] = $translation; } } return true; }
/** * Persist translations * * @param string|null $language A language tag to persist only for language, null to persist on all the language known * * @return bool True on success */ public function persistTranslations($language = null) { // If it doesn't have translations if (empty($this->translations)) { $this->translations = NenoContentElementTranslation::getTranslations($this); } if (empty($this->translations)) { $commonData = array('contentType' => NenoContentElementTranslation::LANG_STRING, 'element' => $this, 'contentId' => $this->getId(), 'state' => NenoContentElementTranslation::NOT_TRANSLATED_STATE, 'string' => $this->getString(), 'timeAdded' => new DateTime(), 'comment' => $this->comment); if ($language != null) { $languageData = new stdClass(); $languageData->lang_code = $language; $languages = array($languageData); } else { $languages = NenoHelper::getLanguages(); } $defaultLanguage = NenoSettings::get('source_language'); $this->translations = array(); foreach ($languages as $language) { if ($defaultLanguage !== $language->lang_code) { // If the string is empty or is a number, let's mark as translated. $string = $this->getString(); // If the string is empty or is a number, let's mark as translated. if (empty($string['string']) || is_numeric($string['string'])) { $commonData['state'] = NenoContentElementTranslation::TRANSLATED_STATE; } else { $commonData['state'] = NenoContentElementTranslation::NOT_TRANSLATED_STATE; } $commonData['language'] = $language->lang_code; $translation = new NenoContentElementTranslation($commonData); // If the translation does not exists already, let's add it if (!$translation->existsAlready()) { $translation->persist(); $this->translations[] = $translation; } } } } elseif ($this->hasChanged) { for ($i = 0; $i < count($this->translations); $i++) { /* @var $translation NenoContentElementTranslation */ $translation = $this->translations[$i]; // If the state is queued or translate, let's mark it as out of sync if (in_array($translation->getState(), array(NenoContentElementTranslation::QUEUED_FOR_BEING_TRANSLATED_STATE, NenoContentElementTranslation::TRANSLATED_STATE))) { $translation->setState(NenoContentElementTranslation::SOURCE_CHANGED_STATE); } $this->translations[$i] = $translation; } } return true; }
/** * Save translation as completed * * @return void */ public function saveAllAsCompleted() { // Get input and turn it into an array with objects $input = $this->input; $stringsJson = $input->get('strings', '', 'RAW'); $strings = json_decode($stringsJson); // Create an array to hold info about the translations $messages = array(); if (!empty($strings) && count($strings) > 0) { $checkedStrings = array(); foreach ($strings as $string) { $string->text = NenoHelper::cleanXssString($string->text); // Save the translation if ($this->saveTranslation($string->translation_id, $string->text, NenoContentElementTranslation::TRANSLATED_STATE)) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($string->translation_id, false); // Check for number of same translations to offer consolidation // Only check for one string once $counter = 0; $originalText = $translation->getOriginalText(); if (in_array(strtolower(trim($originalText)), $checkedStrings) === false) { $checkedStrings[] = strtolower(trim($originalText)); $model = $this->getModel(); $counter = $model->getSimilarTranslationsCounter($string->translation_id, $translation->getLanguage(), $originalText); } // If we found matches prepare data to return $message = array(); if ($counter != 0) { $message['translation_id'] = $string->translation_id; $message['message'] = '<div><input type="checkbox" class="consolidate-checkbox" value="' . $string->translation_id . '" checked="checked"> ' . JText::sprintf('COM_NENO_EDITOR_CONSOLIDATE_MESSAGE', $counter, NenoHelper::html2text($originalText, 200), NenoHelper::html2text($string->text, 200)) . '</div>'; $message['counter'] = $counter; } if (!empty($message)) { $messages[] = $message; } } } } // Echo any messages if (count($messages) > 0) { echo json_encode($messages); } JFactory::getApplication()->close(); }
/** * Process a file * * @return bool True on success, false otherwise */ public function processJobFinished() { $config = JFactory::getConfig(); $tmpPath = $config->get('tmp_path'); $filename = $this->getFileName(); $fileContents = json_decode(file_get_contents($tmpPath . '/' . $filename . '.json' . '/' . $filename . '.json'), true); if ($fileContents !== null) { foreach ($fileContents['strings'] as $translationId => $translationText) { /* @var $translation NenoContentElementTranslation */ $translation = NenoContentElementTranslation::load($translationId, false, true); if (!empty($translation)) { $translation->setString(NenoHelper::replaceTranslationsInHtmlTag($translation->getOriginalText(), html_entity_decode($translationText, ENT_COMPAT | ENT_HTML401, $this->getCorrectEncodingCharset($this->getToLanguage())))); // Mark this translation method as completed $translation->markTranslationMethodAsCompleted($this->translationMethod->id); if ($translation->isBeingCompleted()) { $translation->setState(NenoContentElementTranslation::TRANSLATED_STATE); } // Saving translation if ($translation->persist()) { // Move translation to the target even if it's not completed. Machine => Professional || Professional => Manual $translation->moveTranslationToTarget(); } } } // Ensure the shadow tables of the target language have their language column (if there's any) properly set. $tables = NenoContentElementTable::load(array('translate' => 1)); /* @var $table NenoContentElementTable */ foreach ($tables as $table) { $table->checkIntegrity($this->getToLanguage()); } return true; } return false; }