/** * @param Project $project * * @return LoadedProject|null */ public function load(Project $project, $preferedDomain, $preferedLocale) { $domain = $project->pickDomain($preferedDomain); if (null == $domain) { return null; } $locale = $project->pickLocale($domain, $preferedLocale); $catalogue = $this->loader->loadFile($project->getFilePathName($domain, $locale), $project->getFileFormat($domain, $locale), $locale, $domain); $alternativeMessages = []; foreach ($project->getLocales($domain) as $otherLocale) { if ($locale === $otherLocale) { continue; } $altCatalogue = $this->loader->loadFile($project->getFilePathName($domain, $otherLocale), $project->getFileFormat($domain, $otherLocale), $otherLocale, $domain); foreach ($altCatalogue->getDomain($domain)->all() as $id => $message) { $alternativeMessages[$id][$otherLocale] = $message; } } $newMessages = $existingMessages = array(); foreach ($catalogue->getDomain($domain)->all() as $id => $message) { if ($message->isNew()) { $newMessages[$id] = $message; continue; } $existingMessages[$id] = $message; } return new LoadedProject($project, $domain, $locale, $catalogue, $newMessages, $existingMessages, $alternativeMessages); }
/** * @param string $file * @param string $format * @param string $domain * @param string $locale * @param string $id */ public function createTranslation($file, $format, $domain, $locale, $id) { /* @var $catalogue MessageCatalogue */ $catalogue = $this->loader->loadFile($file, $format, $locale, $domain); $message = new Message($id, $domain); $catalogue->add($message); $this->writer->write($catalogue, $domain, $file, $format, []); }
/** * @Route("/", name="jms_translation_index", options = {"i18n" = false}) * @Template * @param Request $request * @return array */ public function indexAction(Request $request) { $configs = $this->configFactory->getNames(); $config = $request->query->get('config') ?: reset($configs); if (!$config) { throw new RuntimeException('You need to configure at least one config under "jms_translation.configs".'); } $translationsDir = $this->configFactory->getConfig($config, 'en')->getTranslationsDir(); $files = FileUtils::findTranslationFiles($translationsDir); if (empty($files)) { throw new RuntimeException('There are no translation files for this config, please run the translation:extract command first.'); } $domains = array_keys($files); if (!($domain = $request->query->get('domain')) || !isset($files[$domain])) { $domain = reset($domains); } $locales = array_keys($files[$domain]); natsort($locales); if (!($locale = $request->query->get('locale')) || !isset($files[$domain][$locale])) { $locale = reset($locales); } $catalogue = $this->loader->loadFile($files[$domain][$locale][1]->getPathName(), $files[$domain][$locale][0], $locale, $domain); // create alternative messages // TODO: We should probably also add these to the XLIFF file for external translators, // and the specification already supports it $alternativeMessages = array(); foreach ($locales as $otherLocale) { if ($locale === $otherLocale) { continue; } $altCatalogue = $this->loader->loadFile($files[$domain][$otherLocale][1]->getPathName(), $files[$domain][$otherLocale][0], $otherLocale, $domain); foreach ($altCatalogue->getDomain($domain)->all() as $id => $message) { $alternativeMessages[$id][$otherLocale] = $message; } } $newMessages = $existingMessages = array(); foreach ($catalogue->getDomain($domain)->all() as $id => $message) { if ($message->isNew()) { $newMessages[$id] = $message; continue; } $existingMessages[$id] = $message; } return array('selectedConfig' => $config, 'configs' => $configs, 'selectedDomain' => $domain, 'domains' => $domains, 'selectedLocale' => $locale, 'locales' => $locales, 'format' => $files[$domain][$locale][0], 'newMessages' => $newMessages, 'existingMessages' => $existingMessages, 'alternativeMessages' => $alternativeMessages, 'isWriteable' => is_writeable($files[$domain][$locale][1]), 'file' => (string) $files[$domain][$locale][1], 'sourceLanguage' => $this->sourceLanguage); }
/** * @param Config $config */ private function setConfig(Config $config) { $this->config = $config; $this->logger->info(sprintf("Loading catalogues from \"%s\"", $config->getTranslationsDir())); $this->existingCatalogue = new MessageCatalogue(); // load external resources, so current translations can be reused in the final translation foreach ($config->getLoadResources() as $resource) { $this->existingCatalogue->merge($this->loader->loadFromDirectory($resource, $config->getLocale())); } $this->existingCatalogue->merge($this->loader->loadFromDirectory($config->getTranslationsDir(), $config->getLocale())); $this->extractor->reset(); $this->extractor->setDirectories($config->getScanDirs()); $this->extractor->setExcludedDirs($config->getExcludedDirs()); $this->extractor->setExcludedNames($config->getExcludedNames()); $this->extractor->setEnabledExtractors($config->getEnabledExtractors()); $this->logger->info("Extracting translation keys"); $this->scannedCatalogue = $this->extractor->extract(); $this->scannedCatalogue->setLocale($config->getLocale()); // merge existing messages into scanned messages foreach ($this->scannedCatalogue->getDomains() as $domainCatalogue) { foreach ($domainCatalogue->all() as $message) { if (!$this->existingCatalogue->has($message)) { continue; } $existingMessage = clone $this->existingCatalogue->get($message->getId(), $message->getDomain()); $existingMessage->mergeScanned($message); $this->scannedCatalogue->set($existingMessage, true); } } if ($this->config->isKeepOldMessages()) { foreach ($this->existingCatalogue->getDomains() as $domainCatalogue) { foreach ($domainCatalogue->all() as $message) { if ($this->scannedCatalogue->has($message)) { continue; } $this->scannedCatalogue->add($message); } } } //keep old translations translated if ($this->config->isKeepOldTranslationMessages()) { $locale = $this->scannedCatalogue->getLocale(); /** @var MessageCatalogue $domainCatalogue */ foreach ($this->scannedCatalogue->getDomains() as $domainCatalogue) { /** @var Message $message */ foreach ($domainCatalogue->all() as $message) { $translated = $this->translator->trans($message->getId(), array(), $message->getDomain(), $locale); $message->setLocaleString($translated); $message->setNew(false); } } } }
/** * @param Account $account * @param Project $project * @param UploadedFile $file * @param bool $save * * @return Change */ private function addFile(Account $account, Project $project, UploadedFile $file, $save) { $result = new Change(); list($domain, $locale, $format) = $this->getDomainLocaleFormatFromFilename($file->getClientOriginalName()); /** @var MessageCatalogue $inputCatalogue */ $inputCatalogue = $this->loaderManager->loadFile($file->getPathname(), $format, $locale, $domain); $inputDomain = $inputCatalogue->getDomain($domain); $loadedProject = $this->projectLoader->load($project, $domain, $locale); if ($loadedProject->getDomain() == $domain && $loadedProject->getLocale() == $locale) { // existing file /** * 1) remove from local all keys that do not exist in input * 2) add to local all keys that exist in input and do not exist in local * 3) update all empty app keys with values from input * 4) report conflicts where app values are different then input */ $path = $project->getFilePathName($domain, $locale); $localCatalogue = $loadedProject->getCatalogue(); $localDomain = $localCatalogue->getDomain($domain); /** @var Message $localMessage */ /** @var Message $inputMessage */ // find deleted foreach ($localDomain->all() as $localMessage) { $id = $localMessage->getId(); if (false == $inputDomain->has($id)) { $result->addDeleted($id); } } // find added foreach ($inputDomain->all() as $inputMessage) { $id = $inputMessage->getId(); if (false == $localDomain->has($id)) { $result->addAdded($id); } } // find updated empty local values & find conflicts and set values to local values foreach ($inputDomain->all() as $inputMessage) { $id = $inputMessage->getId(); if ($localDomain->has($id)) { $localMessage = $localDomain->get($id); $valueLocal = $localMessage->getLocaleString(); $valueInput = $inputMessage->getLocaleString(); if ($valueInput == $valueLocal) { continue; } if ($valueLocal == '' && $valueInput != '') { $result->addModified($id); } elseif ($valueLocal != $valueInput && $valueInput != '') { $result->addConflict($id, $localMessage->getLocaleString(), $inputMessage->getLocaleString()); $inputMessage->setLocaleString($localMessage->getLocaleString()); } else { $inputMessage->setLocaleString($valueLocal); } } } if ($save) { $this->writer->write($inputCatalogue, $domain, $path, $format); } } else { // new file /** @var Message $message */ foreach ($inputDomain->all() as $message) { $result->addAdded($message->getId()); } if ($save) { $this->store->addFile($account, $project, $file); } } return $result; }
/** * @param $foreignFilePath * @param $domain * @param $format * @return MessageCatalogue */ private function loadEnglishCatalogue($foreignFilePath, $domain, $format) { return $this->loaderManager->loadFile($this->getEnglishFilePath($foreignFilePath), $format, 'en', $domain); }