public function testRDFAnnotations() { try { // - Test parsing from source code. // 1. Defensive tests. $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations(""); $this->assertEquals($annotations, array()); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("sd@eipredicate%\nblu"); $this->assertEquals($annotations, array()); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@fake FUBAR"); $this->assertEquals($annotations, array()); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@predicate "); $this->assertEquals($annotations, array()); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@predicate\n@subject"); $this->assertEquals($annotations, array()); // 2. Other tests. $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@predicate http://www.tao.lu/Ontologies/tao.rdf#aFragment\n@fake FUBAR"); $this->assertEquals($annotations, array("predicate" => "http://www.tao.lu/Ontologies/tao.rdf#aFragment")); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source This is a source test."); $this->assertEquals($annotations, array("source" => "This is a source test.")); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source This is a source test.\n@sourceLanguage en-US"); $this->assertEquals($annotations, array("source" => "This is a source test.", "sourceLanguage" => "en-US")); $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source بعض النصوص في اللغة العربية"); $this->assertEquals($annotations, array("source" => "بعض النصوص في اللغة العربية")); // 3. Test escaping. $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations("@source lorem \\-\\- ipsum \\\\ dolomet.\n@sourceLanguage fr-CA"); $this->assertEquals($annotations, array("source" => "lorem -- ipsum \\ dolomet.", "sourceLanguage" => "fr-CA")); $annotations = tao_helpers_translation_RDFUtils::serializeAnnotations(array("source" => "lorem -- ipsum \\ \n dolomet.", "sourceLanguage" => "fr-CA")); $this->assertEquals($annotations, "@source lorem \\-\\- ipsum \\\\ \n dolomet.\n @sourceLanguage fr-CA"); // - Test serialization from array. $annotations = tao_helpers_translation_RDFUtils::serializeAnnotations(array("source" => "This is a source test.", "sourceLanguage" => "en-US", "targetLanguage" => "fr-CA", "predicate" => "http://www.tao.lu/Ontologies/tao.rdf#aFragment")); $this->assertEquals($annotations, "@source This is a source test.\n @sourceLanguage en-US\n @targetLanguage fr-CA\n @predicate http://www.tao.lu/Ontologies/tao.rdf#aFragment"); // - Test Annotations parsing while reading with RDFFileWriter. $reader = new tao_helpers_translation_RDFFileReader(dirname(__FILE__) . self::FAKE_RDF_TRANSLATION_MODEL_ANNOTATIONS); $reader->read(); $tf = $reader->getTranslationFile(); $this->assertEquals($tf->getAnnotations(), array('sourceLanguage' => 'EN', 'targetLanguage' => 'es')); $tus = $tf->getTranslationUnits(); $this->assertEquals($tus[0]->getSourceLanguage(), 'EN'); $this->assertEquals($tus[0]->getTargetLanguage(), 'es'); $this->assertEquals($tus[0]->getSource(), 'TAO Object'); $this->assertEquals($tus[0]->getTarget(), 'TAO objeto'); $this->assertEquals($tus[0]->getAnnotation('sourceLanguage'), array('name' => 'sourceLanguage', 'value' => 'EN')); $this->assertEquals($tus[0]->getAnnotation('targetLanguage'), array('name' => 'targetLanguage', 'value' => 'es')); $this->assertEquals($tus[10]->getTarget(), 'Función de usuario de flujo de trabajo: el papel asignado por defecto a todos los usuarios backend, no eliminable'); } catch (tao_helpers_translation_TranslationException $e) { $this->assertFalse(true, "No TranslationException should be thrown in testRDFAnnotations test."); } }
/** * Short description of method read * * @access public * @author Jerome Bogaerts, <*****@*****.**> * @return mixed */ public function read() { $translationUnits = array(); try { $translationFile = $this->getTranslationFile(); } catch (tao_helpers_translation_TranslationException $e) { $translationFile = new tao_helpers_translation_RDFTranslationFile(); } $this->setTranslationFile($translationFile); $inputFile = $this->getFilePath(); if (file_exists($inputFile)) { if (is_file($inputFile)) { if (is_readable($inputFile)) { try { $doc = new DOMDocument('1.0', 'UTF-8'); $doc->load($inputFile); $xpath = new DOMXPath($doc); $rdfNS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; $xmlNS = 'http://www.w3.org/XML/1998/namespace'; $xpath->registerNamespace('rdf', $rdfNS); $rootNodes = $xpath->query('//rdf:RDF'); if ($rootNodes->length == 1) { // Try to get annotations from the root node. $sibling = $rootNodes->item(0)->previousSibling; while ($sibling !== null) { if ($sibling instanceof DOMNode && $sibling->nodeType == XML_COMMENT_NODE) { $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations($sibling->data); $translationFile->setAnnotations($annotations); if (isset($annotations['sourceLanguage'])) { $translationFile->setSourceLanguage($annotations['sourceLanguage']); } if (isset($annotations['targetLanguage'])) { $translationFile->setTargetLanguage($annotations['targetLanguage']); } break; } $sibling = $sibling->previousSibling; } $descriptions = $xpath->query('//rdf:Description'); foreach ($descriptions as $description) { if ($description->hasAttributeNS($rdfNS, 'about')) { $subject = $description->getAttributeNS($rdfNS, 'about'); // Let's retrieve properties. foreach ($description->childNodes as $property) { if ($property->nodeType == XML_ELEMENT_NODE) { // Retrieve namespace uri of this node. if ($property->namespaceURI != null) { $predicate = $property->namespaceURI . $property->localName; // Retrieve an hypothetic target language. $lang = tao_helpers_translation_Utils::getDefaultLanguage(); if ($property->hasAttributeNS($xmlNS, 'lang')) { $lang = $property->getAttributeNS($xmlNS, 'lang'); } $object = $property->nodeValue; $tu = new tao_helpers_translation_RDFTranslationUnit(''); $tu->setTargetLanguage($lang); $tu->setTarget($object); $tu->setSubject($subject); $tu->setPredicate($predicate); // Try to get annotations. $sibling = $property->previousSibling; while ($sibling !== null) { if ($sibling instanceof DOMNode && $sibling->nodeType == XML_COMMENT_NODE) { // We should have the annotations we are looking for. $annotations = tao_helpers_translation_RDFUtils::unserializeAnnotations($sibling->data); $tu->setAnnotations($annotations); // Set the found sources and sourcelanguages if found. if (isset($annotations['source'])) { $tu->setSource($annotations['source']); } } $sibling = $sibling->previousSibling; } $translationUnits[] = $tu; } } } } } $this->getTranslationFile()->addTranslationUnits($translationUnits); } else { throw new tao_helpers_translation_TranslationException("'{$inputFile}' has no rdf:RDF root node or more than one rdf:RDF root node."); } } catch (DOMException $e) { throw new tao_helpers_translation_TranslationException("'{$inputFile}' cannot be parsed."); } } else { throw new tao_helpers_translation_TranslationException("'{$inputFile}' cannot be read. Check your system permissions."); } } else { throw new tao_helpers_translation_TranslationException("'{$inputFile}' is not a file."); } } else { throw new tao_helpers_translation_TranslationException("The file '{$inputFile}' does not exist."); } }
/** * Implementation of the 'create' action. * * @access public * @author Joel Bout, <*****@*****.**> * @return void */ public function actionCreate() { $extensionsToCreate = explode(',', $this->options['extension']); $extensionsToCreate = array_unique($extensionsToCreate); foreach ($extensionsToCreate as $etc) { $this->options['extension'] = $etc; $this->options['input'] = dirname(__FILE__) . '/../../' . $etc . '/' . self::DEF_INPUT_DIR; $this->options['output'] = dirname(__FILE__) . '/../../' . $etc . '/' . self::DEF_OUTPUT_DIR; $this->outVerbose("Creating language '" . $this->options['language'] . "' for extension '" . $this->options['extension'] . "' ..."); // We first create the directory where locale files will go. $dir = $this->buildLanguagePath($this->options['extension'], $this->options['language']); $dirExists = false; if (file_exists($dir) && is_dir($dir) && $this->options['force'] == true) { $dirExists = true; $this->outVerbose("Language '" . $this->options['language'] . "' exists for extension '" . $this->options['extension'] . "'. Creation will be forced."); // Clean it up. foreach (scandir($dir) as $d) { if ($d !== '.' && $d !== '..' && $d !== '.svn') { if (!tao_helpers_File::remove($dir . '/' . $d, true)) { $this->err("Unable to clean up 'language' directory '" . $dir . "'.", true); } } } } else { if (file_exists($dir) && is_dir($dir) && $this->options['force'] == false) { $this->err("The 'language' " . $this->options['language'] . " already exists in the file system. Use the 'force' parameter to overwrite it.", true); } } // If we are still here... it means that we have to create the language directory. if (!$dirExists && !@mkdir($dir)) { $this->err("Unable to create 'language' directory '" . $this->options['language'] . "'.", true); } else { if ($this->options['build'] == true) { $sortingMethod = tao_helpers_translation_TranslationFile::SORT_ASC_I; $this->outVerbose("Building language '" . $this->options['language'] . "' for extension '" . $this->options['extension'] . "' ..."); // Let's populate the language with raw PO files containing sources but no targets. // Source code extraction. $fileExtensions = array('php', 'tpl', 'js', 'ejs'); $filePaths = array(); foreach (self::$WHITE_LIST as $subFolder) { $filePaths[] = $this->options['input'] . DIRECTORY_SEPARATOR . $subFolder; } $sourceExtractor = new tao_helpers_translation_SourceCodeExtractor($filePaths, $fileExtensions); $sourceExtractor->extract(); $translationFile = new tao_helpers_translation_POFile(); $translationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage()); $translationFile->setTargetLanguage($this->options['language']); $translationFile->addTranslationUnits($sourceExtractor->getTranslationUnits()); $file = MenuService::getStructuresFilePath($this->options['extension']); if (!is_null($file)) { $structureExtractor = new tao_helpers_translation_StructureExtractor(array($file)); $structureExtractor->extract(); $translationFile->addTranslationUnits($structureExtractor->getTranslationUnits()); } $sortedTus = $translationFile->sortBySource($sortingMethod); $sortedTranslationFile = new tao_helpers_translation_POFile(); $sortedTranslationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage()); $sortedTranslationFile->setTargetLanguage($this->options['language']); $sortedTranslationFile->addTranslationUnits($sortedTus); $this->preparePOFile($sortedTranslationFile, true); $poPath = $dir . '/' . self::DEF_PO_FILENAME; $writer = new tao_helpers_translation_POFileWriter($poPath, $sortedTranslationFile); $writer->write(); $this->outVerbose("PO Translation file '" . basename($poPath) . "' in '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'."); $writer->write(); // Writing JS files $jsPath = $dir . '/' . self::DEF_JS_FILENAME; $writer = new tao_helpers_translation_JSFileWriter($jsPath, $sortedTranslationFile); $writer->write(false); $this->outVerbose("JavaScript Translation file '" . basename($jsPath) . "' in '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'."); $writer->write(); // Now that PO files & JS files are created, we can create the translation models // if we find RDF models to load for this extension. $translatableProperties = array(RDFS_LABEL, RDFS_COMMENT); foreach ($this->getOntologyFiles() as $f) { common_Logger::d('reading rdf ' . $f); $translationFile = $this->extractPoFileFromRDF($f, $translatableProperties); $writer = new tao_helpers_translation_POFileWriter($dir . '/' . $this->getOntologyPOFileName($f), $translationFile); $writer->write(); $this->outVerbose("PO Translation file '" . $this->getOntologyPOFileName($f) . "' in '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'."); } $this->outVerbose("Language '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'."); } else { // Only build virgin files. // (Like a virgin... woot !) $translationFile = new tao_helpers_translation_POFile(); $translationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage()); $translationFile->setTargetLanguage($this->options['language']); $this->preparePOFile($translationFile, true); foreach ($this->getOntologyFiles() as $f) { common_Logger::d('reading rdf ' . $f); $translationFile = new tao_helpers_translation_POFile(); $translationFile->setSourceLanguage(tao_helpers_translation_Utils::getDefaultLanguage()); $translationFile->setTargetLanguage($this->options['language']); $translationFile->setExtensionId($this->options['extension']); $writer = new tao_helpers_translation_POFileWriter($dir . '/' . $this->getOntologyPOFileName($f), $translationFile); $writer->write(); } $this->outVerbose("Language '" . $this->options['language'] . "' created for extension '" . $this->options['extension'] . "'."); } // Create the language manifest in RDF. if ($this->options['extension'] == 'tao') { $langDescription = tao_helpers_translation_RDFUtils::createLanguageDescription($this->options['language'], $this->options['languageLabel']); $langDescription->save($dir . '/' . self::DEF_LANG_FILENAME); } } } }
/** * Writes the RDF file on the file system. * * @access public * @author Jerome Bogaerts, <*****@*****.**> * @return mixed */ public function write() { $targetPath = $this->getFilePath(); $file = $this->getTranslationFile(); $semanticNamespaces = array('rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#'); $xmlNS = 'http://www.w3.org/XML/1998/namespace'; $xmlnsNS = 'http://www.w3.org/2000/xmlns/'; try { $targetFile = new DOMDocument('1.0', 'UTF-8'); $targetFile->formatOutput = true; // Create the RDF root node and annotate if possible. $rdfNode = $targetFile->createElementNS($semanticNamespaces['rdf'], 'rdf:RDF'); $targetFile->appendChild($rdfNode); $rootAnnotations = $this->getTranslationFile()->getAnnotations(); if (count($rootAnnotations)) { $annotationsString = tao_helpers_translation_RDFUtils::serializeAnnotations($rootAnnotations); $annotationsNode = $targetFile->createComment("\n " . $annotationsString . "\n"); $targetFile->insertBefore($annotationsNode, $rdfNode); } $rdfNode->setAttributeNS($xmlNS, 'xml:base', $file->getBase()); $rdfNode->setAttributeNS($xmlnsNS, 'xmlns:rdfs', $semanticNamespaces['rdfs']); $xPath = new DOMXPath($targetFile); $xPath->registerNamespace($semanticNamespaces['rdf'], 'rdf'); $xPath->registerNamespace($semanticNamespaces['rdfs'], 'rdfs'); foreach ($file->getTranslationUnits() as $tu) { // Look if the predicate is a semantic namespace. $uri = explode('#', $tu->getPredicate()); if (count($uri) == 2) { $namespace = $uri[0] . '#'; $qName = $uri[1]; if (($searchedNS = array_search($namespace, $semanticNamespaces)) !== false) { $tuNode = $targetFile->createElement("{$searchedNS}:{$qName}"); $tuNode->setAttributeNS($xmlNS, 'xml:lang', $tu->getTargetLanguage()); $cdataValue = $tu->getTarget() == '' ? $tu->getSource() : $tu->getTarget(); $tuNodeValue = $targetFile->createCDATASection($cdataValue); $tuNode->appendChild($tuNodeValue); // Check if an rdf:Description exists for // the target of the TranslationUnit. $subject = $tu->getSubject(); $result = $xPath->query("//rdf:Description[@rdf:about='{$subject}']"); if ($result->length > 0) { // Append to the existing rdf:Description. $existingDescription = $result->item(0); $existingDescription->appendChild($tuNode); } else { // Append to a new rdf:Description node. $descriptionNode = $targetFile->createElementNS($semanticNamespaces['rdf'], 'rdf:Description'); $descriptionNode->setAttributeNS($semanticNamespaces['rdf'], 'rdf:about', $subject); $descriptionNode->appendChild($tuNode); $rdfNode->appendChild($descriptionNode); } // Finally add annotations. $annotations = $tu->getAnnotations(); if (count($annotations) > 0) { $annotationString = "\n " . tao_helpers_translation_RDFUtils::serializeAnnotations($annotations) . "\n "; $annotationNode = $targetFile->createComment($annotationString); $tuNode->parentNode->insertBefore($annotationNode, $tuNode); } } } } $targetFile->save($targetPath); } catch (DOMException $e) { throw new tao_helpers_translation_TranslationException("An error occured while writing the RDF File at '{$targetPath}'."); } }