示例#1
0
 /**
  * Handle an array of translations and append to the Translations instance.
  *
  * @param array        $content
  * @param Translations $translations
  */
 public static function extract(array $content, Translations $translations)
 {
     $messages = current($content);
     $headers = isset($messages['']) ? $messages[''] : null;
     unset($messages['']);
     if (!empty($headers['domain'])) {
         $translations->setDomain($headers['domain']);
     }
     if (!empty($headers['lang'])) {
         $translations->setLanguage($headers['lang']);
     }
     if (!empty($headers['plural-forms'])) {
         $translations->setHeader(Translations::HEADER_PLURAL, $headers['plural-forms']);
     }
     $context_glue = '\\u0004';
     foreach ($messages as $key => $translation) {
         $key = explode($context_glue, $key);
         $context = isset($key[1]) ? array_shift($key) : '';
         $translations->insert($context, array_shift($key))->setTranslation(array_shift($translation))->setPluralTranslations($translation);
     }
 }
 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());
     }
 }
示例#3
0
 /**
  * Loads the translations of this multilingual section.
  *
  * @param bool $untranslatedFirst Set to true to have untranslated strings first
  *
  * @return \Gettext\Translations
  */
 public function getSectionInterfaceTranslations($untranslatedFirst = false)
 {
     $translations = new Translations();
     $translations->setLanguage($this->getLocale());
     $translations->setPluralForms($this->getNumberOfPluralForms(), $this->getPluralsRule());
     $db = \Database::get();
     $r = $db->query("select *\n            from MultilingualTranslations\n            where mtSectionID = ?\n            order by " . ($untranslatedFirst ? "if(ifnull(msgstr, '') = '', 0, 1), " : "") . "mtID", [$this->getCollectionID()]);
     while ($row = $r->fetch()) {
         $t = Translation::getByRow($row);
         if (isset($t)) {
             $translations[] = $t;
         }
     }
     return $translations;
 }
示例#4
0
 public static function load()
 {
     $locale = self::$locale;
     # IMPORTANT: locale must be installed in server!
     # sudo locale-gen es_ES.UTF-8
     # sudo update-locale
     // $_ENV["LANG"] = $locale;
     // $_ENV["LANGUAGE"] = $locale;
     // $_ENV["LC_MESSAGES"] = $locale;
     // $_ENV["LC_PAPER"] = $locale;
     // $_ENV["LC_TIME"] = $locale;
     // $_ENV["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 = base_path() . "/" . dirname(self::getFile(self::$locale));
     $file = $path . '/' . self::$config['domain'];
     if (is_file($file . '.mo')) {
         $translations = Translations::fromMoFile($file . '.mo');
     }
     if (is_file($file . '.po')) {
         $translationsPo = Translations::fromPoFile($file . '.po');
     }
     if ($translations) {
         $translations->mergeWith($translationsPo);
     } else {
         $translations = $translationsPo;
     }
     if (!$translations) {
         $translations = new Translations();
     }
     $translations->setLanguage($locale);
     $translations->setHeader('LANGUAGE', $locale);
     self::$currentTranslation = $translations;
     // $trans = new Translator();
     // $trans->loadTranslations($translations);
     // Translator::initGettextFunctions($trans);
 }
 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;
     }
 }
 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);
 }