languageManager; } /** * @return \Drupal\Core\Extension\ModuleHandlerInterface */ public function getModuleHandler() { return $this->moduleHandler; } public function __construct(LanguageManagerInterface $languageManager, ModuleHandlerInterface $moduleHandler) { $this->languageManager = $languageManager; $this->moduleHandler = $moduleHandler; } /** * Add a configurable language. * * @command language:add * @param $langcode A comma delimited list of language codes. * @option skip-translations Prevent translations to be downloaded and/or imported. * @usage drush language:add nl,fr * Add Dutch and French language and import their translations. * @usage drush language:add nl --skip-translations * Add Dutch language without importing translations. * @aliases language-add * @validate-module-enabled language * @hidden * @throws \Exception */ public function add($langcode, $options = ['skip-translations' => false]) { if ($langcodes = StringUtils::csvToArray($langcode)) { $langcodes = array_unique($langcodes); $langcodes = $this->filterValidLangcode($langcodes); $langcodes = $this->filterNewLangcode($langcodes); if (empty($langcodes)) { return; } foreach ($langcodes as $langcode) { $language = ConfigurableLanguage::createFromLangcode($langcode); $language->save(); $this->logger->success(dt('Added language @language', [ '@language' => $language->label(), ])); } if ($options['skip-translations']) { return; } if ($this->getModuleHandler()->moduleExists('locale')) { $this->setBatchLanguageImport($langcodes); drush_backend_batch_process(); } } } /** * Print the currently available languages. * * @command language:info * @aliases language-info * @hidden * @field-labels * language: Language * direction: Direction * default: Default * locked: Locked * @default-fields language,direction,default * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields */ public function info() { $rows = []; $languages = $this->getLanguageManager()->getLanguages(); foreach ($languages as $key => $language) { $row = [ 'language' => $language->getName() . ' (' . $language->getId() . ')', 'direction' => $language->getDirection(), 'default' => $language->isDefault() ? dt('yes') : '', 'locked' => $language->isLocked() ? dt('yes') : '', ]; $rows[$key] = $row; } return new RowsOfFields($rows); } /** * Filters valid language codes. * * @param $langcodes * @return array * @throws \Exception * Exception when a language code is not in the standard language list. */ private function filterValidLangcode($langcodes) { $standardLanguages = $this->getLanguageManager()->getStandardLanguageList(); foreach ($langcodes as $key => $langcode) { if (!isset($standardLanguages[$langcode])) { throw new \Exception(dt('Unknown language: !langcode', [ '!langcode' => $langcode ])); } } return $langcodes; } /** * Filters new language codes. * * @param $langcodes * @return array */ private function filterNewLangcode($langcodes) { $enabledLanguages = $this->getLanguageManager()->getLanguages(); foreach ($langcodes as $key => $langcode) { if (isset($enabledLanguages[$langcode])) { $this->logger->warning(dt('The language !langcode is already enabled.', [ '!langcode' => $langcode ])); unset($langcodes[$key]); } } return $langcodes; } /** * Sets a batch to download and import translations and update configurations. * * @param $langcodes */ private function setBatchLanguageImport($langcodes) { $moduleHandler = $this->getModuleHandler(); $moduleHandler->loadInclude('locale', 'inc', 'locale.translation'); $moduleHandler->loadInclude('locale', 'inc', 'locale.fetch'); $moduleHandler->loadInclude('locale', 'inc', 'locale.bulk'); $translationOptions = _locale_translation_default_update_options(); locale_translation_clear_status(); $batch = locale_translation_batch_update_build([], $langcodes, $translationOptions); batch_set($batch); if ($batch = locale_config_batch_update_components($translationOptions, $langcodes)) { batch_set($batch); } } }