示例#1
3
 public function register(Fol $app)
 {
     $app['middleware'] = function ($app) {
         $middleware = [];
         if ($app->has('users')) {
             $middleware[] = new Middlewares\DigestAuthentication($app['users']);
         }
         $middleware[] = new Middlewares\Expires();
         $middleware[] = (new Middlewares\ErrorHandler())->catchExceptions()->statusCode(function ($code) {
             return $code > 400 && $code < 600;
         })->arguments($app);
         $middleware[] = new Middlewares\BasePath($app->getUrlPath());
         $middleware[] = new Middlewares\TrailingSlash();
         $middleware[] = new Middlewares\ContentType();
         $middleware[] = new Middlewares\ContentLanguage(['en', 'gl', 'es']);
         $middleware[] = function ($request, $next) use($app) {
             $language = $request->getHeaderLine('Accept-Language');
             $translator = new Translator();
             $translator->loadTranslations(Translations::fromPoFile(dirname(dirname(__DIR__)) . '/locales/' . $language . '.po'));
             $prev = $translator->register();
             $app['templates']->addData(['language' => $language]);
             $response = $next($request);
             if ($prev) {
                 $prev->register();
             }
             return $response;
         };
         $middleware[] = (new Middlewares\MethodOverride())->parsedBodyParameter('method-override');
         $middleware[] = (new Middlewares\Reader(dirname(dirname(__DIR__)) . '/assets'))->continueOnError();
         $middleware[] = (new Middlewares\AuraRouter($app['router']))->arguments($app);
         return new Dispatcher($middleware);
     };
 }
示例#2
1
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->writeSection($output, 'Po to Csv converter');
     $this->cwd = getcwd() . DIRECTORY_SEPARATOR;
     $output->writeln('<info>Using CWD</info> ' . $this->cwd);
     $poFiles = $this->getInputPoFiles($input, $output);
     $outputFolder = $this->getOutputFolder($input, $output);
     $useDefaults = $input->getOption('use-defaults');
     if ($useDefaults) {
         $output->writeln('<info>Po files</info>:');
         $this->writeList($output, $poFiles);
         $output->writeln(['', '<info>Output folder</info>: ' . $outputFolder]);
     }
     $poHandles = [];
     foreach ($poFiles as $poFile) {
         $key = basename($poFile, '.po');
         $output->writeln('<info>loading ' . $key . '</info>...');
         $poHandles[$key] = Translations::fromPoFile($poFile);
     }
     $output->writeln('<info>merging po files</info>...');
     $csvArray = [];
     foreach ($poHandles as $language => $poHandle) {
         foreach ($poHandle as $translation) {
             $original = trim($translation->original);
             $translation = trim($translation->translation);
             if (!isset($csvArray[$original])) {
                 $csvArray[$original] = [$language => $translation];
             } elseif (!isset($csvArray[$original][$language])) {
                 $csvArray[$original][$language] = $translation;
             } elseif ($csvArray[$original][$language] != $translation) {
                 $csvArray[$original][$language] = $this->handleConflict($input, $output, $original, $csvArray[$original][$language], $translation);
             }
         }
     }
     $output->writeln('<info>writing csv</info>...');
     $writer = Writer::createFromFileObject(new SplTempFileObject());
     $writer->setDelimiter(';');
     $header = ['original'];
     $header = array_merge($header, array_keys($poHandles));
     $writer->insertOne($header);
     foreach ($csvArray as $original => $item) {
         $row = [];
         foreach ($header as $column) {
             if ($column === 'original') {
                 $row[] = $original;
             } else {
                 $row[] = isset($item[$column]) ? $item[$column] : null;
             }
         }
         $writer->insertOne($row);
     }
     $outputFile = $outputFolder . DIRECTORY_SEPARATOR . 'translations.csv';
     file_put_contents($outputFile, $writer->__toString());
     $output->writeln('<info>done. output file is</info> ' . $outputFile);
 }
示例#3
0
文件: MergeTask.php 项目: k1low/exec
 /**
  * main
  *
  */
 public function main()
 {
     $default = APP . 'Locale' . DS . 'default.pot';
     $response = $this->in("What is the full path you would like to merge file (created pot file)?\nExample:" . $default . "\n[Q]uit", null, $default);
     if (strtoupper($response) === 'Q') {
         $this->out('Merge Aborted');
         $this->_stop();
     }
     $created = new File($response, false, 0755);
     if (!$created->exists()) {
         $this->err('The file path you supplied was not found. Please try again.');
         $this->_stop();
     }
     $default = APP . 'Locale' . DS . 'ja' . DS . 'default.po';
     $response = $this->in("What is the full path you would like to merge file (current po file)?\nExample: " . $default . "\n[Q]uit", null, $default);
     if (strtoupper($response) === 'Q') {
         $this->out('Merge Aborted');
         $this->_stop();
     }
     $current = new File($response, false, 0755);
     if (!$current->exists()) {
         $this->err('The file path you supplied was not found. Please try again.');
         $this->_stop();
     }
     $createdTranslations = Translations::fromPoFile($created->path);
     $createdTranslations->addFromPoFile($current->path);
     $merged = $createdTranslations->toPoString();
     $this->createFile($current->path, $merged);
 }
示例#4
0
 /**
  * Load the i12n translation file.
  */
 public function load_translation()
 {
     $translator = new \Gettext\Translator();
     $i18n_path = realpath(__DIR__ . '/../../i18n/' . Config::$locale . '.po');
     if (file_exists($i18n_path)) {
         $translations = \Gettext\Translations::fromPoFile($i18n_path);
         $translator->loadTranslations($translations);
     }
     Translator::initGettextFunctions($translator);
 }
 protected function loadTranslations()
 {
     if (!file_exists($this->arguments['src-po'])) {
         $this->error('src-po file not found');
         exit;
     }
     $this->translations = Translations::fromPoFile($this->arguments['src-po']);
     list($code) = explode('_', $this->translations->getLanguage());
     $this->translateDirection = ($this->arguments['src-lang'] ?: 'en') . '-' . $code;
 }
示例#6
0
 /**
  * Updates the catalog file from the given po file
  *
  * @return void
  */
 public function updateFromCatalog()
 {
     $domain = $this->params['domain'];
     #$localePaths = App::path('Locale');
     $localePath = ROOT . '/src/Locale/';
     $catalogFile = $localePath . $domain . '.pot';
     if (!file_exists($catalogFile)) {
         return $this->abort(sprintf('Catalog File %s not found.', $catalogFile));
     }
     $poFiles = [];
     $folder = new Folder($localePath);
     $tree = $folder->tree();
     foreach ($tree[1] as $file) {
         $basename = basename($file);
         if ($domain . '.po' === $basename) {
             $poFiles[] = $file;
         }
     }
     if (empty($poFiles)) {
         return $this->abort('I could not find any matching po files in the given locale path (%s) for the domain (%s)', $localePath, $domain);
     }
     if (!$this->params['overwrite']) {
         $this->out('I will update the following .po files and their corresponding .mo file with the keys from catalog: ' . $catalogFile);
         foreach ($poFiles as $poFile) {
             $this->out('    - ' . $poFile);
         }
         $response = $this->in('Would you like to continue?', ['y', 'n'], 'n');
         if ($response !== 'y') {
             return $this->abort('Aborted');
         }
     }
     foreach ($poFiles as $poFile) {
         $catalogEntries = Translations::fromPoFile($catalogFile);
         $moFile = str_replace('.po', '.mo', $poFile);
         $translationEntries = Translations::fromPoFile($poFile);
         $newTranslationEntries = $catalogEntries->mergeWith($translationEntries, Merge::REFERENCES_THEIRS);
         $newTranslationEntries->deleteHeaders();
         foreach ($translationEntries->getHeaders() as $key => $value) {
             $newTranslationEntries->setHeader($key, $value);
         }
         if ($this->params['strip-references']) {
             foreach ($newTranslationEntries as $translation) {
                 $translation->deleteReferences();
             }
         }
         $newTranslationEntries->toPoFile($poFile);
         $newTranslationEntries->toMoFile($moFile);
         $this->out('Updated ' . $poFile);
         $this->out('Updated ' . $moFile);
     }
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $container = $this->getContainer();
     $filesystem = new Filesystem();
     $locator = $container->get("agit.common.filecollector");
     $bundles = $container->getParameter("kernel.bundles");
     $catalogPath = $container->getParameter("kernel.root_dir") . "/{$this->catalogSubdir}";
     $this->getContainer()->get("event_dispatcher")->dispatch("agit.intl.global.translations", new TranslationsEvent($this));
     foreach ($container->getParameter("agit.intl.locales") as $locale) {
         $catalog = new Translations();
         $messagesPath = "{$catalogPath}/{$locale}/LC_MESSAGES";
         $catalogFile = "{$messagesPath}/agit.po";
         $oldCatalog = $filesystem->exists($catalogFile) ? Translations::fromPoFile($catalogFile) : new Translations();
         foreach ($oldCatalog as $translation) {
             $translation->deleteReferences();
         }
         $catalog->mergeWith($oldCatalog, 0);
         foreach ($bundles as $alias => $namespace) {
             $bundlePath = $locator->resolve($alias);
             $bundleCatalogFile = "{$bundlePath}/{$this->catalogSubdir}/bundle.{$locale}.po";
             $bundleCatalog = $filesystem->exists($bundleCatalogFile) ? Translations::fromPoFile($bundleCatalogFile) : new Translations();
             $catalog->mergeWith($bundleCatalog, Merge::ADD);
         }
         if (isset($this->extraTranslations[$locale])) {
             foreach ($this->extraTranslations[$locale] as $translation) {
                 $catalog[] = $translation;
             }
         }
         // NOTE: we delete all headers and only set language in order to avoid garbage commits
         $catalog->deleteHeaders();
         $catalog->setLanguage($locale);
         $catalog->setHeader("Content-Type", "text/plain; charset=UTF-8");
         $filesystem->dumpFile($catalogFile, $catalog->toPoString());
         $filesystem->dumpFile("{$messagesPath}/agit.mo", $catalog->toMoString());
     }
 }
示例#8
0
 public function generateTranslationFiles(Locale $locale, $activeTranslations = null)
 {
     $envPoFile = $locale->getPoFilePath(WP_ENV);
     $poFile = $locale->getPoFilePath();
     $moFile = $locale->getMoFilePath();
     if (is_null($activeTranslations)) {
         $activeTranslations = $locale->hasPoFile() ? Translations::fromPoFile($locale->getPoFilePath()) : new Translations();
     }
     // Add local modifications to the default set should there
     // be any.
     if ($locale->hasPoFile(WP_ENV)) {
         $this->hardTranslationSetMerge($locale, Translations::fromPoFile($envPoFile), $activeTranslations);
     }
     $textDomain = Strata::i18n()->getTextdomain();
     $activeTranslations->setDomain($textDomain);
     $activeTranslations->setHeader('Language', $locale->getCode());
     $activeTranslations->setHeader('Text Domain', $textDomain);
     $activeTranslations->setHeader('X-Domain', $textDomain);
     @unlink($poFile);
     @unlink($moFile);
     $activeTranslations->toPoFile($poFile);
     $activeTranslations->toMoFile($moFile);
 }
示例#9
0
文件: Gettext.php 项目: jankal/mvc
 /**
  * @param string $path
  */
 public static function addTranslation($path)
 {
     $file = new File($path);
     if ($file->exists()) {
         $parts = explode('.', $path);
         $extension = $parts[count($parts) - 1];
         switch ($extension) {
             case 'po':
                 $translations = Translations::fromPoFile($path);
                 break;
             case 'mo':
                 $translations = Translations::fromMoFile($path);
                 break;
             case 'php':
                 $translations = Translations::fromPhpArrayFile($path);
                 break;
         }
         self::$activeTranslation->mergeWith($translations);
         self::$t->loadTranslations(self::$activeTranslation);
     }
 }
示例#10
0
 public static function updateMO()
 {
     $path = base_path() . "/" . dirname(self::getFile(self::$locale));
     $file = $path . '/' . self::$config['domain'];
     $translations = Translations::fromPoFile($file . '.po');
     $translations->toMoFile($file . '.mo');
 }
示例#11
0
 /**
  * Load translation domain from Gettext/Gettext using .po
  *
  * Note: Since Twig I18N does not support domains, all loaded files are
  * merged. Use contexts if identical strings need to be disambiguated.
  *
  * @param string $domain Name of domain
  * @param boolean $catchException Whether to catch an exception on error or return early
  *
  * @throws \Exception If something is wrong with the locale file for the domain and activated language
  */
 private function loadGettextGettextFromPO($domain = self::DEFAULT_DOMAIN, $catchException = true)
 {
     try {
         $langPath = $this->getLangPath($domain);
     } catch (\Exception $e) {
         $error = "Something went wrong when trying to get path to language file, cannot load domain '{$domain}'.";
         \SimpleSAML\Logger::error($_SERVER['PHP_SELF'] . ' - ' . $error);
         if ($catchException) {
             // bail out!
             return;
         } else {
             throw $e;
         }
     }
     $poFile = $domain . '.po';
     $poPath = $langPath . $poFile;
     if (file_exists($poPath) && is_readable($poPath)) {
         $translations = Translations::fromPoFile($poPath);
         $this->translator->loadTranslations($translations);
     } else {
         $error = "Localization file '{$poFile}' not found in '{$langPath}', falling back to default";
         \SimpleSAML\Logger::error($_SERVER['PHP_SELF'] . ' - ' . $error);
     }
 }
示例#12
0
 public static function load()
 {
     $locale = self::$locale . '.UTF-8';
     # IMPORTANT: locale must be installed in server!
     # sudo locale-gen es_ES.UTF-8
     # sudo update-locale
     putenv('LANG=' . $locale);
     putenv('LANGUAGE=' . $locale);
     putenv('LC_MESSAGES=' . $locale);
     putenv('LC_PAPER=' . $locale);
     putenv('LC_TIME=' . $locale);
     putenv('LC_MONETARY=' . $locale);
     setlocale(LC_MESSAGES, $locale);
     setlocale(LC_COLLATE, $locale);
     setlocale(LC_TIME, $locale);
     setlocale(LC_MONETARY, $locale);
     bindtextdomain(self::$config['domain'], self::$config['storage']);
     bind_textdomain_codeset(self::$config['domain'], 'UTF-8');
     textdomain(self::$config['domain']);
     # Also, we will work with gettext/gettext library
     # because PHP gones crazy when mo files are updated
     $path = dirname(self::getFile(self::$locale));
     $file = $path . '/' . self::$config['domain'];
     if (is_file($file . '.php')) {
         $translations = $file . '.php';
     } elseif (is_file($file . '.mo')) {
         $translations = Translations::fromMoFile($file . '.mo');
     } elseif (is_file($file . '.po')) {
         $translations = Translations::fromPoFile($file . '.po');
     } else {
         $translations = new Translations();
     }
     Translator::initGettextFunctions((new Translator())->loadTranslations($translations));
 }
示例#13
0
<?php

require '../vendor/autoload.php';
use Gettext\Translations;
use Gettext\Translator;
$locales = array('en', 'es', 'nb');
$text = "Hello, untranslated world!";
echo "<p>Original string: {$text}</p>";
foreach ($locales as $locale) {
    // START setup
    echo '<p>';
    echo "Trying to set locale: {$locale}";
    echo '<br>';
    $translations = Translations::fromPoFile("../locale/{$locale}/LC_MESSAGES/test1.po");
    echo '<br>';
    $t = new Translator();
    $t->loadTranslations($translations);
    Translator::initGettextFunctions($t);
    // END setup
    echo __($text);
    echo '<br>';
    echo '</p>';
}
示例#14
0
 private static function loadFormatPo($file)
 {
     return is_file($file . '.po') ? Translations::fromPoFile($file . '.po') : null;
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $container = $this->getContainer();
     $filesystem = new Filesystem();
     $bundleAlias = $input->getArgument("bundle");
     $bundlePath = $container->get("agit.common.filecollector")->resolve($bundleAlias);
     $defaultLocale = $container->get("agit.intl.locale")->getDefaultLocale();
     $locales = $input->getArgument("locales") ? array_map("trim", explode(",", $input->getArgument("locales"))) : $container->getParameter("agit.intl.locales");
     $globalCatalogPath = $container->getParameter("kernel.root_dir") . "/{$this->catalogSubdir}";
     $this->cacheBasePath = sprintf("%s/agit.intl.temp/%s", sys_get_temp_dir(), $bundleAlias);
     $filesystem->mkdir($this->cacheBasePath);
     $finder = (new Finder())->in("{$bundlePath}")->name("*\\.php")->name("*\\.js")->notPath("/test.*/i")->notPath("public/js/ext");
     $files = [];
     foreach ($finder as $file) {
         $filePath = $file->getRealpath();
         $alias = str_replace($bundlePath, "@{$bundleAlias}/", $filePath);
         $files[$filePath] = $alias;
     }
     $this->getContainer()->get("event_dispatcher")->dispatch("agit.intl.bundle.files", new BundleTranslationFilesEvent($this, $bundleAlias, $this->cacheBasePath));
     $this->extraTranslations = new Translations();
     $this->getContainer()->get("event_dispatcher")->dispatch("agit.intl.bundle.translations", new BundleTranslationsEvent($this, $bundleAlias));
     $files += $this->extraSourceFiles;
     $frontendFiles = array_filter(array_keys($files), function ($file) {
         return preg_match("|\\.js\$|", $file);
     });
     $backendFiles = array_filter(array_keys($files), function ($file) {
         return !preg_match("|\\.js\$|", $file);
     });
     $frontendCatalogs = "";
     foreach ($locales as $locale) {
         if (!preg_match("|^[a-z]{2}_[A-Z]{2}|", $locale)) {
             throw new Exception("Invalid locale: {$locale}");
         }
         // we use the global catalog as source for already translated strings
         $globalCatalogFile = "{$globalCatalogPath}/{$locale}/LC_MESSAGES/agit.po";
         $globalCatalog = $filesystem->exists($globalCatalogFile) ? $this->deleteReferences(Translations::fromPoFile($globalCatalogFile)) : new Translations();
         $bundleCatalogFile = "{$bundlePath}/{$this->catalogSubdir}/bundle.{$locale}.po";
         $oldBundleCatalog = $filesystem->exists($bundleCatalogFile) ? $this->deleteReferences(Translations::fromPoFile($bundleCatalogFile)) : new Translations();
         // NOTE: we delete all headers and only set language, in order to avoid garbage commits
         $bundleCatalog = new Translations();
         $bundleCatalog->deleteHeaders();
         $bundleCatalog->setLanguage($locale);
         // first: only JS messages
         foreach ($frontendFiles as $file) {
             $bundleCatalog->addFromJsCodeFile($file, $this->extractorOptions);
         }
         $bundleCatalog->mergeWith($oldBundleCatalog, 0);
         $bundleCatalog->mergeWith($globalCatalog, 0);
         if ($bundleCatalog->count() && $locale !== $defaultLocale) {
             $transMap = [];
             foreach ($bundleCatalog as $entry) {
                 $msgid = ltrim($entry->getId(), "");
                 $msgstr = $entry->getTranslation();
                 $transMap[$msgid] = $entry->hasPlural() ? array_merge([$msgstr], $entry->getPluralTranslations()) : $msgstr;
             }
             $frontendCatalogs .= sprintf("ag.intl.register(\"%s\", %s);\n\n", $locale, json_encode($transMap, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
         }
         // now the same with all messages
         foreach ($backendFiles as $file) {
             $bundleCatalog->addFromPhpCodeFile($file, $this->extractorOptions);
         }
         $bundleCatalog->mergeWith($this->extraTranslations, Merge::ADD);
         $bundleCatalog->mergeWith($oldBundleCatalog, 0);
         $bundleCatalog->mergeWith($globalCatalog, 0);
         $catalog = $bundleCatalog->toPoString();
         $catalog = str_replace(array_keys($files), array_values($files), $catalog);
         if ($bundleCatalog->count()) {
             $filesystem->dumpFile("{$bundlePath}/{$this->catalogSubdir}/bundle.{$locale}.po", $catalog);
         }
     }
     if ($frontendCatalogs) {
         $filesystem->dumpFile("{$bundlePath}/{$this->frontendSubdir}/translations.js", $frontendCatalogs);
     }
     $filesystem->remove($this->cacheBasePath);
 }
示例#16
0
 /**
  * Saves the list of $translation to the $locale.
  * @param  Locale       $locale
  * @param  Translations $translation
  */
 private function addGettextEntriesToLocale(Locale $locale, Translations $translations)
 {
     $defaultTranslations = $locale->hasPoFile() ? Translations::fromPoFile($locale->getPoFilePath()) : new Translations();
     $i18n = Strata::i18n();
     // it looks reversed to merge defaults into the found strings, but it's the
     // most efficient way of keeping existing translations
     $i18n->hardTranslationSetMerge($locale, $defaultTranslations, $translations);
     $i18n->generateTranslationFiles($locale, $translations);
 }
示例#17
0
 /**
  * Extracts translatable strings from PHP files with xgettext.
  *
  * @param string        $rootDirectory The base root directory
  * @param array[string] $phpFiles      The relative paths to the PHP files to be parsed
  *
  * @throws \Exception Throws an \Exception in case of problems
  *
  * @return \Gettext\Translations
  */
 protected static function parseDirectoryDo_xgettext($rootDirectory, $phpFiles)
 {
     $initialDirectory = @getcwd();
     if ($initialDirectory === false) {
         throw new \Exception('Unable to determine the current working directory');
     }
     if (@chdir($rootDirectory) === false) {
         throw new \Exception('Unable to switch to directory ' . $rootDirectory);
     }
     try {
         $tempDirectory = \C5TL\Options::getTemporaryDirectory();
         $tempFileList = @tempnam($tempDirectory, 'cil');
         if ($tempFileList === false) {
             throw new \Exception(t('Unable to create a temporary file'));
         }
         if (@file_put_contents($tempFileList, implode("\n", $phpFiles)) === false) {
             global $php_errormsg;
             if (isset($php_errormsg) && $php_errormsg) {
                 throw new \Exception("Error writing a temporary file: {$php_errormsg}");
             } else {
                 throw new \Exception('Error writing a temporary file');
             }
         }
         $tempFilePot = @tempnam($tempDirectory, 'cil');
         if ($tempFilePot === false) {
             throw new \Exception(t('Unable to create a temporary file'));
         }
         $line = 'xgettext';
         $line .= ' --default-domain=messages';
         // Domain
         $line .= ' --output=' . escapeshellarg(basename($tempFilePot));
         // Output .pot file name
         $line .= ' --output-dir=' . escapeshellarg(dirname($tempFilePot));
         // Output .pot folder name
         $line .= ' --language=PHP';
         // Source files are in php
         $line .= ' --from-code=UTF-8';
         // Source files are in utf-8
         $line .= ' --add-comments=i18n';
         // Place comment blocks preceding keyword lines in output file if they start with '// i18n: '
         $line .= ' --keyword';
         // Don't use default keywords
         $line .= ' --keyword=t:1';
         // Look for the first argument of the "t" function for extracting translatable text in singular form
         $line .= ' --keyword=t2:1,2';
         // Look for the first and second arguments of the "t2" function for extracting both the singular and plural forms
         $line .= ' --keyword=tc:1c,2';
         // Look for the first argument of the "tc" function for extracting translation context, and the second argument is the translatable text in singular form.
         $line .= ' --no-escape';
         // Do not use C escapes in output
         $line .= ' --add-location';
         // Generate '#: filename:line' lines
         $line .= ' --files-from=' . escapeshellarg($tempFileList);
         // Get list of input files from file
         $line .= ' 2>&1';
         $output = array();
         $rc = null;
         @exec($line, $output, $rc);
         @unlink($tempFileList);
         unset($tempFileList);
         if (!is_int($rc)) {
             $rc = -1;
         }
         if (!is_array($output)) {
             $output = array();
         }
         if ($rc !== 0) {
             throw new \Exception('xgettext failed: ' . implode("\n", $output));
         }
         $newTranslations = \Gettext\Translations::fromPoFile($tempFilePot);
         @unlink($tempFilePot);
         unset($tempFilePot);
     } catch (\Exception $x) {
         @chdir($initialDirectory);
         if (isset($tempFilePot) && @is_file($tempFilePot)) {
             @unlink($tempFilePot);
         }
         if (isset($tempFileList) && @is_file($tempFileList)) {
             @unlink($tempFileList);
         }
         throw $x;
     }
     return $newTranslations;
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     try {
         $vsh = Core::make('helper/validation/strings');
         /* @var \Concrete\Core\Utility\Service\Validation\Strings $vsh */
         $fh = Core::make('helper/file');
         /* @var \Concrete\Core\File\Service\File $fh */
         // Let's determine the package handle, directory and version
         $packageHandle = null;
         $packageDirectory = null;
         $packageVersion = null;
         $p = $input->getArgument('package');
         if (is_dir($p) || !$vsh->handle($p)) {
             $packageDirectory = @realpath($p);
             if ($packageDirectory === false) {
                 throw new Exception("Unable to find the directory '{$p}'");
             }
             $controllerFile = $packageDirectory . '/' . FILENAME_CONTROLLER;
             if (!is_file($controllerFile)) {
                 throw new Exception("The directory '{$packageDirectory}' does not seems to contain a valid concrete5 package");
             }
             $controllerContents = $fh->getContents($controllerFile);
             if ($controllerContents) {
                 $allTokens = @token_get_all($controllerContents);
                 if ($allTokens) {
                     $tokens = array_values(array_filter($allTokens, function ($token) {
                         $keep = true;
                         if (is_array($token)) {
                             switch ($token[0]) {
                                 case T_DOC_COMMENT:
                                 case T_WHITESPACE:
                                 case T_COMMENT:
                                     $keep = false;
                                     break;
                             }
                         }
                         return $keep;
                     }));
                     // Look for package version
                     for ($i = 0; $i < count($tokens) - 2; ++$i) {
                         if ($packageHandle === null && is_array($tokens[$i + 0]) && $tokens[$i + 0][0] === T_VARIABLE && $tokens[$i + 0][1] === '$pkgHandle' && is_string($tokens[$i + 1]) && $tokens[$i + 1] === '=' && is_array($tokens[$i + 2]) && $tokens[$i + 2][0] === T_CONSTANT_ENCAPSED_STRING) {
                             $packageHandle = @eval('return ' . $tokens[$i + 2][1] . ';');
                         }
                         if ($packageVersion === null && is_array($tokens[$i + 0]) && $tokens[$i + 0][0] === T_VARIABLE && $tokens[$i + 0][1] === '$pkgVersion' && is_string($tokens[$i + 1]) && $tokens[$i + 1] === '=' && is_array($tokens[$i + 2]) && $tokens[$i + 2][0] === T_CONSTANT_ENCAPSED_STRING) {
                             $packageVersion = @eval('return ' . $tokens[$i + 2][1] . ';');
                         }
                     }
                 }
             }
             if ($packageHandle === null) {
                 $packageHandle = basename($packageDirectory);
             }
         } else {
             foreach (Package::getAvailablePackages(false) as $pkg) {
                 if (strcasecmp($p, $pkg->getPackageHandle()) === 0) {
                     $packageHandle = $pkg->getPackageHandle();
                     $packageDirectory = $pkg->getPackagePath();
                     $packageVersion = $pkg->getPackageVersion();
                     break;
                 }
             }
             if ($packageHandle === null) {
                 throw new Exception("Unable to find a package with handle '{$p}'");
             }
         }
         $packageLanguagesDirectory = $packageDirectory . '/' . DIRNAME_LANGUAGES;
         // Determine the locales to translate
         $locales = array();
         $localeOption = $input->getOption('locale');
         if (in_array('-', $localeOption, true)) {
             // We don't want any locale
         } elseif (empty($localeOption)) {
             // List the currently package locales
             foreach ($fh->getDirectoryContents($packageLanguagesDirectory) as $item) {
                 if (is_file("{$packageLanguagesDirectory}/{$item}/LC_MESSAGES/messages.mo") || is_file("{$baseDir}/{$item}/LC_MESSAGES/messages.po")) {
                     $locales[] = $item;
                 }
             }
             if (empty($locales)) {
                 // Let's use the core locales
                 $locales = Localization::getAvailableInterfaceLanguages();
             }
         } else {
             // Normalize the locales (eg from it-it to it_IT)
             foreach ($localeOption as $lo) {
                 $chunks = array();
                 foreach (explode('_', str_replace('-', '_', $lo)) as $index => $chunk) {
                     if ($index === 0) {
                         // Language (eg zh)
                         $chunks[] = strtolower($chunk);
                     } elseif (strlen($chunk) === 4) {
                         // Script (eg Hans)
                         $chunks[] = ucfirst(strtolower($chunk));
                     } else {
                         // Territory (eg CN)
                         $chunks[] = strtoupper($chunk);
                     }
                 }
                 $locales[] = implode('_', $chunks);
             }
         }
         // Initialize the master translations file (.pot)
         $pot = new Translations();
         $pot->setHeader('Project-Id-Version', "{$packageHandle} {$packageVersion}");
         $pot->setLanguage('en_US');
         $pot->setHeader('Report-Msgid-Bugs-To', $input->getOption('contact'));
         $pot->setHeader('Last-Translator', $input->getOption('translator'));
         // Parse the package directory
         $output->writeln('Parsing package contents');
         foreach (\C5TL\Parser::getAllParsers() as $parser) {
             if ($parser->canParseDirectory()) {
                 $output->write('- running parser "' . $parser->getParserName() . '"... ');
                 $parser->parseDirectory($packageDirectory, "packages/{$packageHandle}", $pot, false, $input->getOption('exclude-3rdparty'));
                 $output->writeln('done.');
             }
         }
         // Save the pot file
         $output->write('Saving .pot file... ');
         if (!is_dir($packageLanguagesDirectory)) {
             @mkdir($packageLanguagesDirectory, 0775, true);
             if (!is_dir($packageLanguagesDirectory)) {
                 throw new Exception("Unable to create the directory {$packageLanguagesDirectory}");
             }
         }
         $potFilename = "{$packageLanguagesDirectory}/messages.pot";
         if ($pot->toPoFile($potFilename) === false) {
             throw new Exception("Unable to save the .pot file to {$potFilename}");
         }
         $output->writeln('done.');
         // Creating/updating the locale files
         foreach ($locales as $locale) {
             $output->writeln("Working on locale {$locale}");
             $poDirectory = "{$packageLanguagesDirectory}/{$locale}/LC_MESSAGES";
             $po = clone $pot;
             $po->setLanguage($locale);
             $poFile = "{$poDirectory}/messages.po";
             $moFile = "{$poDirectory}/messages.mo";
             if (is_file($poFile)) {
                 $output->write("- reading current .po file... ");
                 $oldPo = Translations::fromPoFile($poFile);
                 $output->writeln('done.');
             } elseif (is_file($moFile)) {
                 $output->write("- decompiling current .mo file... ");
                 $oldPo = Translations::fromMoFile($poFile);
                 $output->writeln('done.');
             } else {
                 $oldPo = null;
             }
             if ($oldPo !== null) {
                 $output->write("- merging translations... ");
                 $po->mergeWith($oldPo, 0);
                 $output->writeln('done.');
             }
             $output->write("- saving .po file... ");
             if (!is_dir($poDirectory)) {
                 @mkdir($poDirectory, 0775, true);
                 if (!is_dir($poDirectory)) {
                     throw new Exception("Unable to create the directory {$poDirectory}");
                 }
             }
             $po->toPoFile($poFile);
             $output->writeln('done.');
             $output->write("- saving .mo file... ");
             $po->toMoFile($moFile);
             $output->writeln('done.');
         }
     } catch (Exception $x) {
         $output->writeln($x->getMessage());
         return 1;
     }
 }
 private static function processDirectory($state, OutputInterface $output, $dirAbs, $dirRel)
 {
     $hDir = @opendir($dirAbs);
     if ($hDir === false) {
         throw new Exception("Failed to open directory {$dirAbs}");
     }
     try {
         $storePrefix = $state->packageHandle;
         if ($dirRel !== '') {
             $storePrefix .= "/{$dirRel}";
         }
         if ($state->zip !== null) {
             if (@$state->zip->addEmptyDir($storePrefix) === false) {
                 $err = "Failed to create directory entry {$storePrefix} in zip file";
                 $reason = $state->zip->getStatusString();
                 if ($reason) {
                     $err .= ": {$reason}";
                 }
                 throw new Exception($err);
             }
         }
         $store = array();
         $subDirs = array();
         while (($item = readdir($hDir)) !== false) {
             if ($item === '.' || $item === '..') {
                 continue;
             }
             if ($item[0] === '.' && !in_array(static::KEEP_DOT, $state->keep)) {
                 continue;
             }
             $itemAbs = $dirAbs . DIRECTORY_SEPARATOR . $item;
             if (is_dir($itemAbs)) {
                 $subDirs[] = $item;
                 continue;
             }
             if (isset($store[$item])) {
                 continue;
             }
             $store[$item] = array('kind' => 'file', 'file' => $itemAbs);
             $p = strrpos($item, '.');
             $ext = $p === false || $p === 0 ? '' : strtolower(substr($item, $p + 1));
             switch ($ext) {
                 case 'php':
                     if ($state->shortTags !== static::SHORTTAGS_NO) {
                         $newContents = static::expandShortTags($itemAbs, $state->shortTags !== static::SHORTTAGS_KEEPECHO);
                         if ($newContents !== null) {
                             if ($state->updateSourceDirectory) {
                                 if (@file_put_contents($itemAbs, $newContents) === false) {
                                     throw new Exception("Failed to update PHP file {$itemAbs}");
                                 }
                             } elseif ($state->zip !== null) {
                                 $store[$item] = array('kind' => 'contents', 'contents' => $newContents);
                             }
                             $output->writeln("Expanded short tags in: {$dirRel}/{$item}");
                         }
                     }
                     break;
                 case 'pot':
                     if ($dirRel === 'languages') {
                         if ($state->zip !== null && !in_array(static::KEEP_SOURCES, $state->keep)) {
                             $output->writeln("Skipped source file: {$dirRel}/{$item}");
                             unset($store[$item]);
                         }
                     }
                     break;
                 case 'po':
                     if (preg_match('%^languages/[^/]+/LC_MESSAGES$%', $dirRel)) {
                         if ($state->zip !== null && !in_array(static::KEEP_SOURCES, $state->keep)) {
                             $output->writeln("Skipped source file: {$dirRel}/{$item}");
                             unset($store[$item]);
                         }
                         $compile = false;
                         $compiledAbs = substr($itemAbs, 0, -2) . 'mo';
                         switch ($state->compileTranslations) {
                             case static::YNA_YES:
                                 $compile = true;
                                 break;
                             case static::YNA_AUTO:
                                 if (is_file($compiledAbs)) {
                                     $sourceTime = @filemtime($itemAbs);
                                     $compiledTime = @filemtime($compiledAbs);
                                     if ($sourceTime && $compiledTime && $sourceTime > $compiledTime) {
                                         $compile = true;
                                     }
                                 } else {
                                     $compile = true;
                                 }
                                 break;
                         }
                         if ($compile) {
                             $compiledItem = substr($item, 0, -2) . 'mo';
                             $output->writeln("Compiling language : {$dirRel}/{$item} => {$dirRel}/{$compiledItem}");
                             $translations = Translations::fromPoFile($itemAbs);
                             if ($state->updateSourceDirectory) {
                                 if ($translations->toMoFile($compiledAbs) === false) {
                                     throw new Exception("Failed to write compiled translations file to {$compiledAbs}");
                                 }
                                 $store[$compiledItem] = array('kind' => 'file', 'file' => $compiledAbs);
                             } elseif ($state->zip !== null) {
                                 $store[$compiledItem] = array('kind' => 'contents', 'contents' => $translations->toMoString());
                             }
                         }
                     }
                     break;
                 case 'svg':
                     if ($item === 'icon.svg') {
                         $iconSize = null;
                         if ($dirRel === '') {
                             // Package icon
                             $iconSize = $state->packageFormat === static::PACKAGEFORMAT_CURRENT ? array('width' => 200, 'height' => 200) : array('width' => 97, 'height' => 97);
                         } elseif (preg_match('%^blocks/[^/]+$%', $dirRel)) {
                             $iconSize = $state->packageFormat === static::PACKAGEFORMAT_CURRENT ? array('width' => 50, 'height' => 50) : array('width' => 16, 'height' => 16);
                         }
                         if ($iconSize !== null) {
                             if ($state->zip !== null && !in_array(static::KEEP_SOURCES, $state->keep)) {
                                 $output->writeln("Skipped source file: {$dirRel}/{$item}");
                                 unset($store[$item]);
                             }
                             $compile = false;
                             $compiledAbs = substr($itemAbs, 0, -3) . 'png';
                             switch ($state->compileIcons) {
                                 case static::YNA_YES:
                                     $compile = true;
                                     break;
                                 case static::YNA_AUTO:
                                     if (is_file($compiledAbs)) {
                                         $sourceTime = @filemtime($itemAbs);
                                         $compiledTime = @filemtime($compiledAbs);
                                         if ($sourceTime && $compiledTime && $sourceTime > $compiledTime) {
                                             $compile = true;
                                         }
                                     } else {
                                         $compile = true;
                                     }
                                     break;
                             }
                             if ($compile) {
                                 $compiledItem = substr($item, 0, -3) . 'png';
                                 $output->writeln("Generating png icon: {$dirRel}/{$item} => {$dirRel}/{$compiledItem}");
                                 $tmpDir = Core::make('helper/file')->getTemporaryDirectory();
                                 if (!is_dir($tmpDir)) {
                                     throw new Exception('Failed to retrieve the temporary directory');
                                 }
                                 $tmpFile = @tempnam($tmpDir, 'c5p');
                                 if ($tmpFile === false) {
                                     throw new Exception('Failed to create a temporary file in directory ' . $tmpDir);
                                 }
                                 try {
                                     $cmd = 'inkscape';
                                     $cmd .= ' --file=' . escapeshellarg($itemAbs);
                                     $cmd .= ' --export-png=' . escapeshellarg($tmpFile);
                                     $cmd .= ' --export-area-page';
                                     $cmd .= ' --export-width=' . $iconSize['width'];
                                     $cmd .= ' --export-height=' . $iconSize['height'];
                                     $cmd .= ' 2>&1';
                                     $execOutput = array();
                                     @exec($cmd, $execOutput, $rc);
                                     if (!is_int($rc)) {
                                         $rc = -1;
                                     }
                                     if ($rc !== 0) {
                                         throw new Exception(implode("\n", $execOutput));
                                     }
                                     $pngData = @file_get_contents($tmpFile);
                                     if ($pngData === false) {
                                         throw new Exception('Failed to read the generated PNG file');
                                     }
                                 } catch (Exception $x) {
                                     @unlink($tmpFile);
                                     throw $x;
                                 }
                                 @unlink($tmpFile);
                                 if ($pngData === '') {
                                     throw new Exception("Inkscape failed to generate the PNG file:\n" . implode("\n", $execOutput));
                                 }
                                 if ($state->updateSourceDirectory) {
                                     if (@file_put_contents($compiledAbs, $pngData) === false) {
                                         throw new Exception("Failed to write rendered SVN icon to {$compiledAbs}");
                                     }
                                     $store[$compiledItem] = array('kind' => 'file', 'file' => $compiledAbs);
                                 } elseif ($state->zip !== null) {
                                     $store[$compiledItem] = array('kind' => 'contents', 'contents' => $pngData);
                                 }
                             }
                         }
                     }
                     break;
             }
         }
         @closedir($hDir);
         if ($state->zip !== null) {
             foreach ($store as $storeItem => $storeWhat) {
                 $storeName = $storePrefix . '/' . $storeItem;
                 switch ($storeWhat['kind']) {
                     case 'file':
                         if ($state->zip->addFile($storeWhat['file'], $storeName) === false) {
                             $err = "Failed to store file {$storeName} to zip file";
                             $reason = $state->zip->getStatusString();
                             if ($reason) {
                                 $err .= ": {$reason}";
                             }
                             throw new Exception($err);
                         }
                         break;
                     case 'contents':
                         if ($state->zip->addFromString($storeName, $storeWhat['contents']) === false) {
                             $err = "Failed to store file {$storeName} to zip file";
                             $reason = $state->zip->getStatusString();
                             if ($reason) {
                                 $err .= ": {$reason}";
                             }
                             throw new Exception($err);
                         }
                         break;
                     default:
                         throw new Exception('?');
                 }
             }
         }
         unset($store);
         foreach ($subDirs as $subDir) {
             static::processDirectory($state, $output, $dirAbs . DIRECTORY_SEPARATOR . $subDir, $dirRel === '' ? $subDir : "{$dirRel}/{$subDir}");
         }
     } catch (Exception $x) {
         @closedir($hDir);
         throw $x;
     }
 }
    public function testGeneratedPO()
    {
        $translationsFolder = DIR_APPLICATION . '/' . DIRNAME_LANGUAGES;
        if (!is_dir($translationsFolder)) {
            mkdir($translationsFolder);
        }
        // Extract the translatable strings and create the template .pot file
        $potFile = $translationsFolder . '/messages.pot';
        $translations = new \Gettext\Translations();
        $cifParser = new \C5TL\Parser\Cif();
        $phpParser = new \C5TL\Parser\Php();
        $blockTemplatesParser = new \C5TL\Parser\BlockTemplates();
        $themesPresetsParser = new \C5TL\Parser\ThemePresets();
        $parsersForDir = array('' => array($phpParser), DIRNAME_BLOCKS => array($blockTemplatesParser), DIRNAME_THEMES => array($phpParser, $themesPresetsParser, $blockTemplatesParser), 'config/install' => array($cifParser));
        foreach ($parsersForDir as $parsersDir => $parsers) {
            $dir = DIR_BASE_CORE;
            $relDir = DIRNAME_CORE;
            if ($parsersDir !== '') {
                $dir .= '/' . $parsersDir;
                $relDir .= '/' . $parsersDir;
            }
            foreach ($parsers as $parser) {
                try {
                    $parser->parseDirectory($dir, $relDir, $translations);
                } catch (Exception $x) {
                    $reason = $x->getMessage();
                    $stack = $x->getTraceAsString();
                    $this->markTestSkipped(<<<EOT
Extraction of translatable strings has been skipped.
Reason: {$reason}
Stack trace:
{$stack}
EOT
);
                    return;
                }
            }
        }
        $translatableStrings = count($translations);
        $this->assertGreaterThan(2000, $translatableStrings);
        $translations->toPoFile($potFile);
        $this->assertFileExists($potFile);
        // Create a .po file with translations set to source strings
        $poFile = $translationsFolder . '/messages.po';
        $cmd = 'msgen --lang=en-US --output-file=' . escapeshellarg($poFile) . ' ' . escapeshellarg($potFile) . ' 2>&1';
        $output = array();
        @exec($cmd, $output, $rc);
        $this->assertSame(0, $rc, "msgen output:\n" . implode("\n", $output));
        $this->assertFileExists($poFile);
        // Set the plural rules
        $translations = \Gettext\Translations::fromPoFile($poFile);
        $translations->setLanguage('en_US');
        $translations->toPoFile($poFile);
        $this->assertSame($translatableStrings, count($translations));
        // Compile the .po file checking the strings
        $moFile = $translationsFolder . '/messages.mo';
        $cmd = 'msgfmt';
        $cmd .= ' --check-format';
        // check language dependent format strings
        $cmd .= ' --check-header';
        // verify presence and contents of the header entry
        $cmd .= ' --check-domain';
        // check for conflicts between domain directives and the --output-file option
        $cmd .= ' --verbose';
        // increase verbosity level
        $cmd .= ' --output-file=' . escapeshellarg($moFile);
        $cmd .= ' ' . escapeshellarg($poFile);
        $cmd .= ' 2>&1';
        $output = array();
        @exec($cmd, $output, $rc);
        $this->assertSame(0, $rc, "msgfmt output:\n" . implode("\n", $output));
        $this->assertFileExists($moFile);
    }
示例#21
-1
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->writeSection($output, 'Csv to Po converter');
     $this->cwd = getcwd() . DIRECTORY_SEPARATOR;
     $output->writeln('<info>Using CWD</info> ' . $this->cwd);
     $csvFile = $this->getInputCsvFile($input, $output);
     $poFiles = $this->getInputPoFiles($input, $output);
     $outputFolder = $this->getOutputFolder($input, $output);
     $useDefaults = $input->getOption('use-defaults');
     if ($useDefaults) {
         $output->writeln('<info>Csv file</info>:' . "\n" . $csvFile . "\n");
         $output->writeln('<info>Po files</info>:');
         $this->writeList($output, $poFiles);
         $output->writeln("\n" . '<info>Output folder</info>: ' . "\n" . $outputFolder . "\n");
     }
     $writeHandles = [];
     foreach ($poFiles as $poFile) {
         $key = basename($poFile, '.po');
         $output->writeln('<info>loading ' . $key . '</info>...');
         $writeHandles[$key] = Translations::fromPoFile($poFile);
     }
     $header = null;
     $output->writeln('<info>reading from csv</info>...');
     $reader = Reader::createFromPath($csvFile);
     foreach ($reader as $i => $row) {
         if ($header == null) {
             $header = $row;
             continue;
         }
         $original = null;
         foreach ($row as $j => $string) {
             if ($original == null) {
                 $original = $string;
                 continue;
             }
             if (empty($string)) {
                 continue;
             }
             $writeHandle = $writeHandles[$header[$j]];
             $translation = $writeHandle->find(null, $original);
             if ($translation != false && $translation->translation != $string) {
                 if (!empty($translation->translation)) {
                     $this->handleConflict($input, $output, $original, $translation->translation, $string);
                 } else {
                     $translation->setTranslation($string);
                 }
             } else {
                 $translation = new Translation(null, $original);
                 $translation->setTranslation($string);
                 $writeHandle[] = $translation;
             }
         }
     }
     foreach ($writeHandles as $key => $writeHandle) {
         $output->writeln('<info>writing ' . $key . '</info>...');
         $content = Po::toString($writeHandle);
         file_put_contents($this->outputDir . DIRECTORY_SEPARATOR . $key . '.po', $content);
     }
     $output->writeln('<info>done</info>');
 }