/** * Execute the command. * * @return void * * @since 1.0 */ public function execute() { $this->getApplication()->outputTitle('Clear g11n cache dir'); $this->logOut(sprintf('Cleaning the cache dir in "%s"', ExtensionHelper::getCacheDir())); g11n::cleanCache(); $this->out()->out('The g11n cache directory has been cleared.'); }
/** * Execute the command. * * @return integer * * @since 1.0 * @throws \UnexpectedValueException */ public function execute() { $this->getApplication()->outputTitle('Check language files'); ExtensionHelper::addDomainPath('Core', JPATH_ROOT . '/src'); ExtensionHelper::addDomainPath('Template', JPATH_ROOT . '/templates'); ExtensionHelper::addDomainPath('App', JPATH_ROOT . '/src/App'); $scopes = array('Core' => array('JTracker', 'JTracker.js'), 'Template' => array('JTracker'), 'App' => (new Filesystem(new Local(JPATH_ROOT . '/src/App')))->listPaths()); $languages = $this->getApplication()->get('languages'); $languages[] = 'templates'; $errors = false; foreach ($scopes as $domain => $extensions) { foreach ($extensions as $extension) { $scopePath = ExtensionHelper::getDomainPath($domain); $extensionPath = ExtensionHelper::getExtensionLanguagePath($extension); foreach ($languages as $language) { $path = $scopePath . '/' . $extensionPath . '/' . $language; $path .= 'templates' == $language ? '/' . $extension . '.pot' : '/' . $language . '.' . $extension . '.po'; $this->debugOut(sprintf('Check: %s-%s %s in %s', $domain, $extension, $language, $path)); if (false == file_exists($path)) { $this->debugOut('not found'); continue; } // Check if the language file has UNIX style line endings. if ("\n" != PHP_CodeSniffer_File::detectLineEndings($path)) { $this->out($path)->out('<error> The file does not have UNIX style line endings ! </error>')->out(); continue; } // Check the language file for errors. $output = shell_exec('msgfmt -c ' . $path . ' 2>&1'); if ($output) { // If the command produces any output, that means errors. $errors = true; $this->out($output); } else { $this->debugOut('ok'); } } } } $this->out($errors ? '<error> There have been errors. </error>' : '<ok>Language file syntax OK</ok>'); if ($this->exit) { exit($errors ? 1 : 0); } return $errors ? 1 : 0; }
/** * Push translations. * * @return $this * * @throws \DomainException * @since 1.0 */ private function uploadTemplates() { $transifexProject = $this->getApplication()->get('transifex.project'); $create = $this->getApplication()->input->get('create'); defined('JDEBUG') || define('JDEBUG', 0); ExtensionHelper::addDomainPath('Core', JPATH_ROOT . '/src'); ExtensionHelper::addDomainPath('CoreJS', JPATH_ROOT . '/src'); ExtensionHelper::addDomainPath('Template', JPATH_ROOT . '/templates'); ExtensionHelper::addDomainPath('App', JPATH_ROOT . '/src/App'); ExtensionHelper::addDomainPath('CLI', JPATH_ROOT); $scopes = ['Core' => ['JTracker'], 'CoreJS' => ['JTracker.js'], 'Template' => ['JTracker'], 'CLI' => ['cli'], 'App' => (new Filesystem(new Local(JPATH_ROOT . '/src/App')))->listPaths()]; foreach ($scopes as $domain => $extensions) { foreach ($extensions as $extension) { $name = $extension . ' ' . $domain; $alias = OutputFilter::stringURLUnicodeSlug($name); $this->out('Processing: ' . $name . ' - ' . $alias); $templatePath = Storage::getTemplatePath($extension, $domain); if (false == file_exists($templatePath)) { throw new \DomainException(sprintf('Language template for %s not found.', $name)); } $this->out($templatePath); try { if ($create) { $this->transifex->resources->createResource($transifexProject, $name, $alias, 'PO', ['file' => $templatePath]); $this->out('<ok>Resource created successfully</ok>'); } else { $this->transifex->resources->updateResourceContent($transifexProject, $alias, $templatePath, 'file'); $this->out('<ok>Resource updated successfully</ok>'); } } catch (\Exception $e) { $this->out('<error>' . $e->getMessage() . '</error>'); } $this->out(); } } return $this; }
/** * Process language files for a domain. * * @param string $extension Extension name. * @param string $domain Extension domain. * @param boolean $templates If templates should be exported. * * @throws \DomainException * @return $this * * @since 1.0 */ protected function processDomain($extension, $domain, $templates) { $domainBase = trim(str_replace(JPATH_ROOT, '', g11nExtensionHelper::getDomainPath($domain)), '/'); $g11nPath = g11nExtensionHelper::$langDirName; $filesystem = new Filesystem(new Local($this->exportDir . '/' . $domainBase . '/' . $extension . '/' . $g11nPath)); $this->out(sprintf('Processing %s %s:... ', $domain, $extension), false); // Process language templates if ($templates) { $this->out('templates... ', false); $path = g11nStorage::getTemplatePath($extension, $domain); $contents = (new Filesystem(new Local(dirname($path))))->read(basename($path)); if (false == $filesystem->put('templates/' . basename($path), $contents)) { throw new \DomainException('Can not write the file at: ' . $path); } } // Process language files foreach ($this->languages as $lang) { if ('en-GB' == $lang) { continue; } $this->out($lang . '... ', false); $path = g11nExtensionHelper::findLanguageFile($lang, $extension, $domain); if (!$path) { $this->out('<error> ' . $lang . ' NOT FOUND </error>... ', false); continue; } $contents = (new Filesystem(new Local(dirname($path))))->read(basename($path)); if (false == $filesystem->put($lang . '/' . basename($path), $contents)) { throw new \DomainException('Can not write the file: ' . basename($path)); } } $this->out('ok'); return $this; }
/** * Extract information about the translators from the language files. * * @return array * * @since 1.0 */ private function checkLanguageFiles() { $list = array(); g11nExtensionHelper::addDomainPath('Core', JPATH_ROOT . '/src'); g11nExtensionHelper::addDomainPath('Template', JPATH_ROOT . '/templates'); g11nExtensionHelper::addDomainPath('App', JPATH_ROOT . '/src/App'); $scopes = array('Core' => array('JTracker'), 'Template' => array('JTracker'), 'App' => (new Filesystem(new Local(JPATH_ROOT . '/src/App')))->listPaths()); $langTags = $this->getApplication()->get('languages'); $noEmail = $this->getApplication()->input->get('noemail'); foreach ($langTags as $langTag) { if ('en-GB' == $langTag) { continue; } $langInfo = new \stdClass(); $langInfo->tag = $langTag; $langInfo->translators = array(); $translators = array(); foreach ($scopes as $domain => $extensions) { foreach ($extensions as $extension) { $path = g11nExtensionHelper::findLanguageFile($langTag, $extension, $domain); if (false == file_exists($path)) { $this->out(sprintf('Language file not found %s, %s, %s' . $langTag, $extension, $domain)); continue; } $f = fopen($path, 'r'); $line = '#'; $started = false; while ($line) { $line = fgets($f, 1000); if (0 !== strpos($line, '#')) { // Encountered the first line - We're done parsing. $line = ''; continue; } if (strpos($line, 'Translators:')) { // Start $started = true; continue; } if (!$started) { continue; } $line = trim($line, "# \n"); if ($noEmail) { // Strip off the e-mail address // Format: '<*****@*****.**>, ' $line = preg_replace('/<[a-z0-9\\.\\-+]+@[a-z\\.]+>,\\s/i', '', $line); } if (false == in_array($line, $translators)) { $translators[] = $line; } } fclose($f); } } foreach ($translators as $translator) { $t = new \stdClass(); $t->translator = $translator; $langInfo->translators[] = $t; } $list[] = $langInfo; } return $list; }
/** * Process language files for a domain. * * @param string $extension Extension name. * @param string $domain Extension domain. * @param string $lang Language tag e.g. en-GB or de-DE. * * @return $this * * @since 1.0 * @throws \Exception */ protected function processDomain($extension, $domain, $lang) { $this->out(sprintf('Processing: %1$s %2$s %3$s', $domain, $extension, $lang)); $languageFile = ExtensionHelper::findLanguageFile($lang, $extension, $domain); $templateFile = Storage::getTemplatePath($extension, $domain); // Check if the language file has UNIX style line endings. if ("\n" != PHP_CodeSniffer_File::detectLineEndings($templateFile)) { $this->out($templateFile)->out('<error> The file does not have UNIX style line endings ! </error>')->out(); return $this; } if (false == $languageFile) { $this->out('Creating language file...'); $scopePath = ExtensionHelper::getDomainPath($domain); $extensionPath = ExtensionHelper::getExtensionLanguagePath($extension); $path = $scopePath . '/' . $extensionPath . '/' . $lang; if (!is_dir($path)) { if (!mkdir($path, 0755, true)) { throw new \Exception('Can not create the language folder'); } } $fileName = $lang . '.' . $extension . '.po'; $options = array(); $options[] = 'input=' . $templateFile; $options[] = 'output=' . $path . '/' . $fileName; $options[] = 'no-wrap'; $options[] = 'locale=' . $lang; $cmd = 'msginit --' . implode(' --', $options) . ' 2>&1'; $this->debugOut($cmd); ob_start(); system($cmd); $msg = ob_get_clean(); if (!file_exists($templateFile)) { throw new \Exception('Can not create the language file'); } $this->out('The language file has been created')->out($msg); } else { $this->out('Updating language file...'); $options = array(); $options[] = 'update'; $options[] = 'backup=off'; $options[] = 'no-fuzzy-matching'; $options[] = 'verbose'; $options[] = 'no-wrap'; $paths = array(); $paths[] = $languageFile; $paths[] = $templateFile; $cmd = 'msgmerge --' . implode(' --', $options) . ' "' . implode('" "', $paths) . '"' . ' 2>&1'; $this->debugOut($cmd); ob_start(); system($cmd); $msg = ob_get_clean(); if ($msg) { $this->out($msg); } } return $this; }
/** * Receives language files from Transifex * * @param string $extension The extension to process * @param string $domain The domain of the extension * * @return void * * @since 1.0 * @throws \Exception */ private function receiveFiles($extension, $domain) { $this->out(sprintf('Processing: %s %s... ', $domain, $extension), false); $scopePath = ExtensionHelper::getDomainPath($domain); $extensionPath = ExtensionHelper::getExtensionLanguagePath($extension); // Fetch the file for each language and place it in the file tree foreach ($this->languages as $language) { if ('en-GB' == $language) { continue; } $this->out($language . '... ', false); // Call out to Transifex $translation = $this->transifex->translations->getTranslation($this->getApplication()->get('transifex.project'), strtolower(str_replace('.', '-', $extension)) . '-' . strtolower($domain), str_replace('-', '_', $language)); // Write the file $path = $scopePath . '/' . $extensionPath . '/' . $language . '/' . $language . '.' . $extension . '.po'; if (false == is_dir(dirname($path))) { if (false == mkdir(dirname($path))) { throw new \Exception('Could not create the directory at: ' . str_replace(JPATH_ROOT, '', dirname($path))); } } if (!file_put_contents($path, $translation->content)) { throw new \Exception('Could not store language file at: ' . str_replace(JPATH_ROOT, '', $path)); } } $this->out('ok'); }
/** * Generate templates for an extension. * * @param string $extension Extension name. * @param string $domain Extension domain. * @param string $type File extension. * @param array $paths Paths with source file. * @param string $templatePath The path to store the templates. * * @return $this * * @since 1.0 * @throws \Exception */ protected function processTemplates($extension, $domain, $type, array $paths, $templatePath) { $packageName = 'JTracker'; $headerData = ''; $headerData .= ' --copyright-holder="' . $packageName . '"'; $headerData .= ' --package-name="' . $packageName . '"'; $headerData .= ' --package-version="' . $this->product->version . '"'; // @$headerData .= ' --msgid-bugs-address="*****@*****.**"'; $comments = ' --add-comments=TRANSLATORS:'; $keywords = ' -k --keyword=g11n3t --keyword=g11n4t:1,2'; $noWrap = ' --no-wrap'; // Always write an output file even if no message is defined. $forcePo = ' --force-po'; // Sort output by file location. $sortByFile = ' --sort-by-file'; $extensionDir = ExtensionHelper::getExtensionPath($extension); $dirName = dirname($templatePath); $cleanFiles = array(); $excludes = array(); foreach ($paths as $base) { if (!is_dir($base . '/' . $extensionDir)) { throw new \Exception('Invalid extension'); } $cleanFiles = array_merge($cleanFiles, $this->getCleanFiles($base . '/' . $extensionDir, $type, $excludes)); } if (!is_dir($dirName)) { if (!mkdir($dirName, 0755, true)) { throw new \Exception('Can not create the language template folder'); } } $subType = ''; if (strpos($extension, '.')) { $subType = substr($extension, strpos($extension, '.') + 1); } $buildOpts = ''; switch ($type) { case 'js': $buildOpts .= ' -L python'; break; case 'config': $excludes[] = '/templates/'; $excludes[] = '/scripts/'; break; default: break; } $this->debugOut(sprintf('Found %d files', count($cleanFiles))); if ('config' == $subType) { $this->processConfigFiles($cleanFiles, $templatePath); } else { $fileList = implode("\n", $cleanFiles); $command = $keywords . $buildOpts . ' -o ' . $templatePath . $forcePo . $noWrap . $sortByFile . $comments . $headerData; $this->debugOut($command); ob_start(); system('echo "' . $fileList . '" | xgettext ' . $command . ' -f - 2>&1'); $result = ob_get_clean(); $this->out($result); } if (!file_exists($templatePath)) { throw new \Exception('Could not create the template'); } // Manually strip the JROOT path - ... $contents = file_get_contents($templatePath); $contents = str_replace(JPATH_ROOT, '', $contents); // Manually strip unwanted information - .... $contents = str_replace('#, fuzzy', '', $contents); $contents = str_replace('"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n"', '', $contents); // Set the character set $contents = str_replace('charset=CHARSET\\n', 'charset=utf-8\\n', $contents); // Some header data - that will hopefully remain.. $contents = str_replace('# SOME DESCRIPTIVE TITLE.', '# ' . $packageName . ' ' . $domain . ' ' . $extension . ' ' . $this->product->version, $contents); $contents = str_replace('# Copyright (C) YEAR', '# Copyright (C) 2012 - ' . date('Y'), $contents); $contents = str_replace('# This file is distributed under the same license as the PACKAGE package.', '# This file is distributed under the same license as the ' . $packageName . ' package.', $contents); file_put_contents($templatePath, $contents); $this->out('Your template has been created'); return $this; }