. * * For more information, contact Colosa Inc, 2566 Le Jeune Rd., * Coral Gables, FL, 33134, USA, or email info@colosa.com. * */ require_once 'classes/model/om/BaseLanguage.php'; require_once 'classes/model/Content.php'; require_once 'classes/model/IsoCountry.php'; require_once 'classes/model/Translation.php'; /** * Skeleton subclass for representing a row from the 'LANGUAGE' table. * * * * You should add additional methods to this class to meet the * application requirements. This class will only be generated as * long as it does not already exist in the output directory. * * @package workflow.engine.classes.model */ class Language extends BaseLanguage { function load($sLanUid) { try { $oRow = LanguagePeer::retrieveByPK($sLanUid); if (!is_null($oRow)) { $aFields = $oRow->toArray(BasePeer::TYPE_FIELDNAME); $this->fromArray($aFields, BasePeer::TYPE_FIELDNAME); $this->setNew(false); return $aFields; } else { throw(new Exception('This row doesn\'t exist!')); } } catch (Exception $oError) { throw($oError); } } function update($aFields) { $oConnection = Propel::getConnection(LanguagePeer::DATABASE_NAME); try { $oConnection->begin(); $this->load($aFields['LAN_ID']); $this->fromArray($aFields, BasePeer::TYPE_FIELDNAME); if ($this->validate()) { $iResult = $this->save(); $oConnection->commit(); return $iResult; } else { $oConnection->rollback(); throw(new Exception('Failed Validation in class ' . get_class($this) . '.')); } } catch(Exception $e) { $oConnection->rollback(); throw($e); } } //SELECT LAN_ID, LAN_NAME FROM LANGUAGE WHERE LAN_ENABLED = '1' ORDER BY LAN_WEIGHT DESC function getActiveLanguages() { $oCriteria = new Criteria('workflow'); $oCriteria->addSelectColumn(LanguagePeer::LAN_ID); $oCriteria->addSelectColumn(LanguagePeer::LAN_NAME); $oCriteria->add(LanguagePeer::LAN_ENABLED , '1'); $oCriteria->addDescendingOrderByColumn(LanguagePeer::LAN_WEIGHT); $oDataset = ContentPeer::doSelectRS($oCriteria); $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); $oContent = new Content(); $rows = Array(); while ($oDataset->next()) array_push($rows, $oDataset->getRow()); return $rows; } function findById($LAN_ID) { $oCriteria = new Criteria('workflow'); $oCriteria->addSelectColumn(LanguagePeer::LAN_NAME); $oCriteria->add(LanguagePeer::LAN_ID, $LAN_ID); $oDataset = LanguagePeer::doSelectRS($oCriteria); $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); $oDataset->next(); return $oDataset->getRow(); } function findByLanName($LAN_NAME) { $oCriteria = new Criteria('workflow'); $oCriteria->addSelectColumn(LanguagePeer::LAN_ID); $oCriteria->addSelectColumn(LanguagePeer::LAN_NAME); $oCriteria->add(LanguagePeer::LAN_NAME, $LAN_NAME, Criteria::LIKE); $oDataset = LanguagePeer::doSelectRS($oCriteria); $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); $oDataset->next(); return $oDataset->getRow(); } /* * Import a language file * * @author Erik Amaru Ortiz * @param string $sLanguageFile * @param string $bXml * @return void */ public function import($sLanguageFile, $updateXml = true, $updateDB = true) { try { G::LoadSystem('i18n_po'); $POFile = new i18n_PO($sLanguageFile); $POFile->readInit(); $POHeaders = $POFile->getHeaders(); /*getting the PO Language definition*/ $langName = $POHeaders['X-Poedit-Language']; //find the lang id $language = new Language(); $langRecord = $language->findByLanName($langName); if( ! isset($langRecord['LAN_ID']) ) //if the language doesn't exist abort throw new Exception('The .po file has a invalid X-Poedit-Language definition!'); $languageID = $langRecord['LAN_ID']; /*getting the PO Language definition*/ $countryName = $POHeaders['X-Poedit-Country']; if( $countryName != '.' ) { $isoCountry = new IsoCountry(); $countryRecord = $isoCountry->findByIcName($countryName); if( ! isset($countryRecord['IC_UID']) ) //if the language doesn't exist abort throw new Exception('The .po file has a invalid X-Poedit-Country definition!'); $countryID = $countryRecord['IC_UID']; //define locale $LOCALE = "$languageID-$countryID"; } else { $LOCALE = $languageID; } $oTranslation = new Translation(); $countItems = 0; $countItemsSuccess = 0; $errorMsg = ''; while( $rowTranslation = $POFile->getTranslation() ) { $countItems++; if ( ! isset($POFile->translatorComments[0]) || ! isset($POFile->translatorComments[1]) || ! isset($POFile->references[0]) ) { throw new Exception('The .po file doesn\'t have valid directives for Processmaker!'); } foreach($POFile->translatorComments as $a=>$aux){ $aux = trim($aux); if ( $aux == 'TRANSLATION') $identifier = $aux; else { $var = explode('/',$aux); if ($var[0]=='LABEL') $context = $aux; if ($var[0]=='JAVASCRIPT') $context = $aux; } if (preg_match('/^([\w-]+)\/([\w-]+\/*[\w-]*\.xml\?)/', $aux, $match)) $identifier = $aux; else{ if (preg_match('/^([\w-]+)\/([\w-]+\/*[\w-]*\.xml$)/', $aux, $match)) $context = $aux; } } $reference = $POFile->references[0]; // it is a Sql insert on TRANSLATIONS TAble if( $identifier == 'TRANSLATION') { if ($updateDB) { list($category, $id) = explode('/', $context); $result = $oTranslation->addTranslation( $category, $id, $LOCALE, trim(stripcslashes(str_replace(chr(10), '', $rowTranslation['msgstr']))) ); if( $result['codError'] == 0 ) { $countItemsSuccess++; } else { $errorMsg .= $id .': ' . $result['message'] . "\n"; } } } // is a Xml update else if( $updateXml ) { $xmlForm = $context; //erik: expresion to prevent and hable correctly dropdown values like -1, -2 etc. preg_match('/^([\w_]+)\s-\s([\w_]+)\s*-*\s*([\w\W]*)$/', $reference, $match); if( ! file_exists(PATH_XMLFORM . $xmlForm) ) { $errorMsg .= 'file doesn\'t exist: ' . PATH_XMLFORM . $xmlForm . "\n"; continue; } if (count($match) < 4) { $near = isset($rowTranslation['msgid']) ? $rowTranslation['msgid'] : (isset($rowTranslation['msgstr']) ? $rowTranslation['msgstr'] : ''); $errorMsg .= "Invalid Translation reference: \"$reference\", near -> ".$near."\n"; continue; } G::LoadSystem('dynaformhandler'); $dynaform = new dynaFormHandler(PATH_XMLFORM . $xmlForm); $fieldName = $match[2]; $codes = explode('-', $reference); if( sizeof($codes) == 2 ) { //is a normal node $dynaform->addChilds($fieldName, Array($LOCALE=>stripcslashes(str_replace(chr(10), '', $rowTranslation['msgstr'])))); } else if( sizeof($codes) > 2 ) { //is a node child for a language node $name = $match[3] == "''" ? '' : $match[3]; $childNode = Array( Array('name'=>'option', 'value'=>$rowTranslation['msgstr'], 'attributes'=>Array('name'=>$name)) ); $dynaform->addChilds($fieldName, Array($LOCALE=>NULL), $childNode); } $countItemsSuccess++; } } $oLanguage = new Language(); $oLanguage->update(array('LAN_ID' => $languageID, 'LAN_ENABLED' => '1')); $trn = new Translation(); $trn->generateFileTranslation($LOCALE); $trn->addTranslationEnvironment($LOCALE, $POHeaders, $countItemsSuccess); $content = new Content(); $content->regenerateContent($languageID); //fill the results $results = new stdClass(); $results->recordsCount = $countItems; $results->recordsCountSuccess = $countItemsSuccess; $results->lang = $languageID; $results->headers = $POHeaders; $results->errMsg = $errorMsg; return $results; } catch (Exception $oError) { throw($oError); } } //export function export() { //G::LoadThirdParty('pear', 'Benchmark/Timer'); G::LoadSystem('i18n_po'); G::LoadClass("system"); //echo G::getMemoryUsage(); //$timer = new Benchmark_Timer(); //$timer->start(); //creating the .po file $sPOFile = PATH_CORE . 'content' . PATH_SEP . 'translations' . PATH_SEP . MAIN_POFILE . '.' . $_GET['LOCALE'] . '.po'; $poFile = new i18n_PO($sPOFile); $poFile->buildInit(); $language = new Language(); $locale = $_GET['LOCALE']; $_TARGET_LANG = $_GET['LOCALE']; $_BASE_LANG = 'en'; if( strpos($locale, Translation::$localeSeparator) !== false ) { list($LAN_ID, $IC_UID) = explode(Translation::$localeSeparator, $_GET['LOCALE']); $iCountry = new IsoCountry(); $iCountryRecord = $iCountry->findById($IC_UID); if( ! isset($iCountryRecord['IC_UID']) ) throw new Exception("Country Target ID '{$_GET['LAN_ID']}' doesn't exist!"); $sCountry = $iCountryRecord['IC_NAME']; } else { $LAN_ID = $locale; $sCountry = $IC_UID = ''; } $langRecord = $language->findById($LAN_ID); if( ! isset($langRecord['LAN_NAME']) ) throw new Exception("Language Target ID \"{$LAN_ID}\" doesn't exist!"); $sLanguage = $langRecord['LAN_NAME']; //setting headers $poFile->addHeader('Project-Id-Version' , 'ProcessMaker ' . System::getVersion()); $poFile->addHeader('POT-Creation-Date' , ''); $poFile->addHeader('PO-Revision-Date' , date('Y-m-d H:i:s')); $poFile->addHeader('Last-Translator' , ''); $poFile->addHeader('Language-Team' , 'Colosa Developers Team '); $poFile->addHeader('MIME-Version' , '1.0'); $poFile->addHeader('Content-Type' , 'text/plain; charset=utf-8'); $poFile->addHeader('Content-Transfer_Encoding' , '8bit'); $poFile->addHeader('X-Poedit-Language' , ucwords($sLanguage)); $poFile->addHeader('X-Poedit-Country' , ucwords($sCountry)); $poFile->addHeader('X-Poedit-SourceCharset' , 'utf-8'); $poFile->addHeader('Content-Transfer-Encoding' , '8bit'); //$timer->setMarker('end making po headers'); //export translation $aLabels = array(); $aMsgids = array(); // selecting all translations records of base language 'en' on TRANSLATIONS table $oCriteria = new Criteria('workflow'); $oCriteria->addSelectColumn(TranslationPeer::TRN_CATEGORY); $oCriteria->addSelectColumn(TranslationPeer::TRN_ID); $oCriteria->addSelectColumn(TranslationPeer::TRN_VALUE); $oCriteria->add(TranslationPeer::TRN_LANG, 'en'); $oDataset = TranslationPeer::doSelectRS($oCriteria); $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); $targetLangRecords = array(); // retrieve the translation for the target language if( $LAN_ID != 'en' ) { // only if it is different language than base language 'en' $c = new Criteria('workflow'); $c->addSelectColumn(TranslationPeer::TRN_CATEGORY); $c->addSelectColumn(TranslationPeer::TRN_ID); $c->addSelectColumn(TranslationPeer::TRN_VALUE); $c->add(TranslationPeer::TRN_LANG, $_GET['LOCALE']); $ds = TranslationPeer::doSelectRS($c); $ds->setFetchmode(ResultSet::FETCHMODE_ASSOC); while ($ds->next()) { $row = $ds->getRow(); $targetLangRecords[$row['TRN_CATEGORY'].'/'.$row['TRN_ID']] = $row['TRN_VALUE']; } } // get the respective translation for each english label while ($oDataset->next()) { $aRow1 = $oDataset->getRow(); $trnCategory = trim($aRow1['TRN_CATEGORY']); # Validation, validate that the TRN_CATEGORY contains valid characteres preg_match("/^[0-9a-zA-Z_-]+/", $trnCategory, $sTestResult); // IF the translations id "TRN_ID" has invalid characteres or has not accepted categories if ($sTestResult[0] !== $trnCategory || ($trnCategory != 'LABEL' && $trnCategory != 'JAVASCRIPT')) { $oTranslation = new Translation; $oTranslation->remove($aRow1['TRN_CATEGORY'], $aRow1['TRN_ID'], 'en'); //remove not accepted translations continue; //jump to next iteration } // retrieve the translation for the target language if( $LAN_ID != 'en' ){ // only if it is different language than base language 'en' if (isset($targetLangRecords[$aRow1['TRN_CATEGORY'].'/'.$aRow1['TRN_ID']])) { $msgstr = $targetLangRecords[$aRow1['TRN_CATEGORY'].'/'.$aRow1['TRN_ID']] != '' ? $targetLangRecords[$aRow1['TRN_CATEGORY'].'/'.$aRow1['TRN_ID']]: $aRow1['TRN_VALUE']; } else { $msgstr = $aRow1['TRN_VALUE']; } } else { //if not just copy the same $msgstr = $aRow1['TRN_VALUE']; } $msgid = trim($aRow1['TRN_VALUE']); $msgstr = trim($msgstr); if ( isset($aMsgids[$msgid]) ) { $msgid = '[' . $aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID'] . '] ' . $msgid; } $poFile->addTranslatorComment('TRANSLATION'); $poFile->addTranslatorComment($aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID']); $poFile->addReference($aRow1['TRN_CATEGORY'] . '/' . $aRow1['TRN_ID']); $poFile->addTranslation(stripcslashes($msgid), stripcslashes($msgstr)); $aMsgids[$msgid] = true; } //$timer->setMarker('end making 1th .po from db'); //now find labels in xmlforms /************/ $aExceptionFields = array('', 'javascript', 'hidden', 'phpvariable', 'private', 'toolbar', 'xmlmenu', 'toolbutton', 'cellmark', 'grid'); //find all xml files into PATH_XMLFORM $aXMLForms = glob(PATH_XMLFORM . '*/*.xml'); //from a sublevel to $aXMLForms2 = glob(PATH_XMLFORM . '*/*/*.xml'); $aXMLForms = array_merge($aXMLForms, $aXMLForms2); $aEnglishLabel = array(); $aOptions = array(); $nodesNames = Array(); G::loadSystem('dynaformhandler'); foreach ($aXMLForms as $xmlFormPath) { $xmlFormFile = str_replace( chr(92), '/', $xmlFormPath); $xmlFormFile = str_replace( PATH_XMLFORM, '', $xmlFormPath); $dynaForm = new dynaFormHandler($xmlFormPath); $dynaNodes = $dynaForm->getFields(); //get all fields of each xmlform foreach ($dynaNodes as $oNode) { $sNodeName = $oNode->nodeName; //$arrayNode = $dynaForm->getArray($oNode, Array('type', $_BASE_LANG, $_BASE_LANG)); $arrayNode = $dynaForm->getArray($oNode); //if has not native language translation if( ! isset($arrayNode[$_BASE_LANG]) || ! isset($arrayNode['type']) || ( isset($arrayNode['type']) && in_array($arrayNode['type'], $aExceptionFields)) ){ continue; //just continue with the next node } // Getting the Base Origin Text if( ! is_array($arrayNode[$_BASE_LANG]) ) $originNodeText = trim($arrayNode[$_BASE_LANG]); else { $langNode = $arrayNode[$_BASE_LANG][0]; $originNodeText = $langNode['__nodeText__']; } // Getting the Base Target Text if( isset($arrayNode[$_TARGET_LANG]) ) { if( ! is_array($arrayNode[$_TARGET_LANG]) ) $targetNodeText = trim($arrayNode[$_TARGET_LANG]); else { $langNode = $arrayNode[$_TARGET_LANG][0]; $targetNodeText = $langNode['__nodeText__']; } } else { $targetNodeText = $originNodeText; } $nodeName = $arrayNode['__nodeName__']; $nodeType = $arrayNode['type']; $msgid = $originNodeText; // if the nodeName already exists in the po file, we need to create other msgid if( isset($aMsgids[$msgid]) ) $msgid = '[' . $xmlFormFile . '?' . $nodeName . '] ' . $originNodeText; $poFile->addTranslatorComment($xmlFormFile . '?' . $nodeName); $poFile->addTranslatorComment($xmlFormFile); $poFile->addReference($nodeType . ' - ' . $nodeName); $poFile->addTranslation(stripslashes($msgid), stripslashes($targetNodeText)); $aMsgids[$msgid] = true; //if this node has options child nodes if( isset($arrayNode[$_BASE_LANG]) && isset($arrayNode[$_BASE_LANG][0]) && isset($arrayNode[$_BASE_LANG][0]['option']) ){ $originOptionNode = $arrayNode[$_BASE_LANG][0]['option']; //get the options $targetOptionExists = false; if( isset($arrayNode[$_TARGET_LANG]) && isset($arrayNode[$_TARGET_LANG][0]) && isset($arrayNode[$_TARGET_LANG][0]['option']) ) { $targetOptionNode = $arrayNode[$_TARGET_LANG][0]['option']; $targetOptionExists = true; } if ( ! is_array($originOptionNode) ){ if( is_string($originOptionNode) ){ $poFile->addTranslatorComment($xmlFormFile . '?' . $nodeName . '-'. $originOptionNode); $poFile->addTranslatorComment($xmlFormFile); $poFile->addReference($nodeType . ' - ' . $nodeName . ' - ' . $originOptionNode); $poFile->addTranslation(stripslashes($msgid), stripslashes($originOptionNode)); } } else { foreach( $originOptionNode as $optionNode ) { $optionName = $optionNode['name']; $originOptionValue = $optionNode['__nodeText__']; if( $targetOptionExists ){ $targetOptionValue = getMatchDropdownOptionValue($optionName, $targetOptionNode); if( $targetOptionValue === false ){ $targetOptionValue = $originOptionValue; } } else { $targetOptionValue = $originOptionValue; } $msgid = '[' . $xmlFormFile . '?' . $nodeName . '-' . $optionName . ']'; $poFile->addTranslatorComment($xmlFormFile . '?' . $nodeName . '-'. $optionName); $poFile->addTranslatorComment($xmlFormFile); $poFile->addReference($nodeType . ' - ' . $nodeName . ' - ' . $optionName); $poFile->addTranslation($msgid, stripslashes($targetOptionValue)); } } } } //end foreach } // //$timer->setMarker('end xml files processed'); //$profiling = $timer->getProfiling(); //$timer->stop(); $timer->display(); //echo G::getMemoryUsage(); //die; //g::pr($profiling); G::streamFile($sPOFile, true); } } // Language function getMatchDropdownOptionValue($name, $options){ foreach($options as $option){ if($name == $option['name']){ return $option['__nodeText__']; } } return false; }