Improvement options to processmaker

- Add plugins-translation-update
- Add plugins-translation-create
This commit is contained in:
Marco Antonio Nina
2013-03-12 16:44:17 -04:00
parent 1c5cb81f72
commit e321335790
3 changed files with 421 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
<?php
/**
* cliPlugins.php
*
* ProcessMaker Open Source Edition
* Copyright (C) 2011 Colosa Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
*
* @package workflow-engine-bin-tasks
*/
G::LoadClass("system");
G::LoadClass("wsTools");
//-------------------------------------------------------------------------------------------
CLI::taskName('plugins-translation-update');
CLI::taskDescription(<<<EOT
Upgrade workspaces.
This command should be run after ProcessMaker files are upgraded so that all
workspaces are upgraded to the current version.
EOT
);
CLI::taskArg('plugin', false);
CLI::taskArg('lang', false);
//CLI::taskOpt("buildACV", "If the option is enabled, performs the Build Cache View.", "ACV", "buildACV");
CLI::taskRun(run_update);
//-------------------------------------------------------------------------------------------
CLI::taskName('plugins-translation-create');
CLI::taskDescription(<<<EOT
Upgrade workspaces.
This command should be run after ProcessMaker files are upgraded so that all
workspaces are upgraded to the current version.
EOT
);
CLI::taskArg('plugin', true);
CLI::taskArg('lang', true);
//CLI::taskOpt("buildACV", "If the option is enabled, performs the Build Cache View.", "ACV", "buildACV");
CLI::taskRun(run_create);
/**
* A version of rm_dir which does not exits on error.
*
* @param string $filename directory or file to remove
* @param bool $filesOnly either to remove the containing directory as well or not
*/
function run_create($command, $args)
{
CLI::logging("Creating file .po ..\n");
$language = new Language();
$language->createLanguagePlugin($command[0], $command[1]);
CLI::logging("Creating successful\n");
}
function run_update($command, $args)
{
CLI::logging("Updating...\n");
$language = new Language();
$language->updateLanguagePlugin($command[0], $command[1]);
CLI::logging("Update successful\n");
}

View File

@@ -541,6 +541,267 @@ class Language extends BaseLanguage
}
G::streamFile( $sPOFile, true );
}
function updateLanguagePlugin ($plugin, $idLanguage)
{
if (!file_exists(PATH_PLUGINS . $plugin)) {
throw new Exception( 'The plugin ' . $plugin . ' not exist' );
die();
}
if (!file_exists(PATH_CORE . 'content' . PATH_SEP . 'translations' . PATH_SEP . $plugin . '.' . $idLanguage . '.po')) {
throw new Exception( 'The not exist the file ' . $plugin . '.' . $idLanguage . '.po' );
die();
}
$languageFile = PATH_CORE . 'content' . PATH_SEP . 'translations' . PATH_SEP . $plugin . '.' . $idLanguage . '.po' ;//PATH_LANGUAGECONT . $plugin . '.' . $idLanguage;
try {
G::LoadSystem( 'i18n_po' );
$POFile = new i18n_PO( $languageFile );
$POFile->readInit();
$POHeaders = $POFile->getHeaders();
$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) {
$identifier = '';
$context = '';
$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 ($identifier == '' && $context == '') {
$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];
if ($identifier != 'TRANSLATION') {
$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_PLUGINS . $plugin . PATH_SEP . $xmlForm )) {
$errorMsg .= 'file doesn\'t exist: ' . PATH_PLUGINS . $plugin . $xmlForm . "\n";
continue;
}
if (count( $match ) < 4) {
$near = isset( $rowTranslation['msgid'] ) ? $rowTranslation['msgid'] : (isset( $rowTranslation['msgstr'] ) ? $rowTranslation['msgstr'] : '');
$errorMsg .= "Invalid Translation reference: \"$reference\", near -> " . strip_tags($near) . "\n";
continue;
}
G::LoadSystem( 'dynaformhandler' );
$dynaform = new dynaFormHandler( PATH_PLUGINS . $plugin . PATH_SEP . $xmlForm );
$fieldName = $match[2];
$codes = explode( '-', $reference );
if (sizeof( $codes ) == 2) {
//is a normal node
$dynaform->addChilds( $fieldName, Array ($idLanguage => stripcslashes( str_replace( chr( 10 ), '', $rowTranslation['msgstr'] ) )
) );
} elseif (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 ($idLanguage => null
), $childNode );
}
$countItemsSuccess ++;
}
}
$trn = new Translation();
$trn->generateFileTranslationPlugin( $plugin, $idLanguage );
$trn->addTranslationEnvironmentPlugins( $plugin, $idLanguage, $POHeaders, $countItemsSuccess );
//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);
}
}
function createLanguagePlugin ($plugin, $idLanguage)
{
G::LoadSystem( 'i18n_po' );
G::LoadClass( "system" );
//creating the .po file
//$sPOFile = PATH_LANGUAGECONT . $plugin . '.' . $idLanguage . '.po';
$sPOFile = PATH_CORE . 'content' . PATH_SEP . 'translations' . PATH_SEP . $plugin . '.' . $idLanguage . '.po';
$poFile = new i18n_PO( $sPOFile );
$poFile->buildInit();
$language = new Language();
$locale = $language;
$_TARGET_LANG = $idLanguage;
$_BASE_LANG = 'en';
//setting headers
$poFile->addHeader( 'Project-Id-Version', $plugin );
$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 <developers@colosa.com>' );
$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( $idLanguage ) );
$poFile->addHeader( 'X-Poedit-SourceCharset', 'utf-8' );
$poFile->addHeader( 'Content-Transfer-Encoding', '8bit' );
$aLabels = array ();
$aMsgids = array ('' => true
);
//global $translations;
include PATH_PLUGINS . $plugin . PATH_SEP . 'translations'. PATH_SEP . 'translation.php';
foreach ($translations as $id => $translation) {
$msgid = trim( $translation);
$msgstr = trim( $translation );
$poFile->addTranslatorComment( 'TRANSLATION' );
$poFile->addTranslatorComment( 'LABEL/' . $id );
$poFile->addReference( 'LABEL/'. $id );
$poFile->addTranslation( stripcslashes( $msgid ), stripcslashes( $msgstr ) );
$aMsgids[$msgid] = true;
}
//now find labels in xmlforms
$aExceptionFields = array ('','javascript','hidden','phpvariable','private','toolbar','xmlmenu','toolbutton','cellmark','grid','CheckboxTable'
);
$aXMLForms = glob( PATH_PLUGINS . $plugin . PATH_SEP . '*.xml' );
$aXMLForms2 = glob( PATH_PLUGINS . $plugin . PATH_SEP . '*/*.xml' );
$aXMLForms = array_merge( $aXMLForms, $aXMLForms2 );
$aXMLForms3 = glob( PATH_PLUGINS . $plugin . PATH_SEP . '*/*/*.xml' );
$aXMLForms = array_merge( $aXMLForms, $aXMLForms3 );
$aEnglishLabel = array ();
$aOptions = array ();
$nodesNames = Array ();
G::loadSystem( 'dynaformhandler' );
foreach ($aXMLForms as $xmlFormPath) {
$xmlFormFile = str_replace( chr( 92 ), '/', $xmlFormPath );
$xmlFormFile = str_replace( PATH_PLUGINS . $plugin . PATH_SEP , '', $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 );
//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
}
//G::streamFile( $sPOFile, true );
}
}
// Language

View File

@@ -225,6 +225,81 @@ class Translation extends BaseTranslation
//to do: uniform coderror structures for all classes
}
/* Load strings from plugin translation.php .
* @parameter $languageId (es|en|...).
*/
public function generateFileTranslationPlugin ($plugin, $languageId = '')
{
$translation = Array ();
$translationJS = Array ();
if ($languageId === '') {
$languageId = defined( 'SYS_LANG' ) ? SYS_LANG : 'en';
}
global $translations;
include PATH_PLUGINS . $plugin . PATH_SEP . 'translations'. PATH_SEP . 'translation.php';
$cacheFile = PATH_LANGUAGECONT . $plugin . "." . $languageId;
$cacheFileJS = PATH_CORE . 'js' . PATH_SEP . 'labels' . PATH_SEP . $languageId . ".js";
foreach ($translations as $key => $row) {
$translation[$key] = $row;
}
try {
if (! is_dir( dirname( $cacheFile ) )) {
G::mk_dir( dirname( $cacheFile ) );
}
if (! is_dir( dirname( $cacheFileJS ) )) {
G::mk_dir( dirname( $cacheFileJS ) );
}
$f = fopen( $cacheFile, 'w+' );
fwrite( $f, "<?php\n" );
fwrite( $f, '$translation =' . 'unserialize(\'' . addcslashes( serialize( $translation ), '\\\'' ) . "');\n" );
fwrite( $f, "?>" );
fclose( $f );
$f = fopen( $cacheFileJS, 'w' );
fwrite( $f, "var G_STRINGS =" . Bootstrap::json_encode( $translationJS ) . ";\n" );
fclose( $f );
$res['cacheFile'] = $cacheFile;
$res['cacheFileJS'] = $cacheFileJS;
$res['rows'] = count( $translation );
$res['rowsJS'] = count( $translationJS );
return $res;
} catch (Exception $e) {
echo $e->getMessage();
}
}
public function addTranslationEnvironmentPlugins ($plugin, $locale, $headers, $numRecords)
{
$filePath = PATH_DATA . "META-INF" . PATH_SEP . $plugin . ".env";
$environments = Array ();
if (file_exists( $filePath )) {
$environments = unserialize( file_get_contents( $filePath ) );
}
$environment['LOCALE'] = $locale;
$environment['HEADERS'] = $headers;
$environment['DATE'] = date( 'Y-m-d H:i:s' );
$environment['NUM_RECORDS'] = $numRecords;
$environment['LANGUAGE'] = $headers['X-Poedit-Language'];
if (strpos( $locale, self::$localeSeparator ) !== false) {
list ($environment['LAN_ID'], $environment['IC_UID']) = explode( self::$localeSeparator, strtoupper( $locale ) );
$environments[$environment['LAN_ID']][$environment['IC_UID']] = $environment;
} else {
$environment['LAN_ID'] = strtoupper( $locale );
$environment['IC_UID'] = '';
$environments[$locale]['__INTERNATIONAL__'] = $environment;
}
file_put_contents( $filePath, serialize( $environments ) );
}
public function remove ($sCategory, $sId, $sLang)
{
$oTranslation = TranslationPeer::retrieveByPK( $sCategory, $sId, $sLang );