/** * Test update changes configuration translations if enabled after language. */ public function testConfigTranslationImport() { $admin_user = $this->drupalCreateUser(array('administer modules', 'administer site configuration', 'administer languages', 'access administration pages', 'administer permissions')); $this->drupalLogin($admin_user); // Add a language. The Afrikaans translation file of locale_test_translate // (test.af.po) has been prepared with a configuration translation. ConfigurableLanguage::createFromLangcode('af')->save(); // Enable locale module. $this->container->get('module_installer')->install(array('locale')); $this->resetAll(); // Enable import of translations. By default this is disabled for automated // tests. $this->config('locale.settings')->set('translation.import_enabled', TRUE)->save(); // Add translation permissions now that the locale module has been enabled. $edit = array('authenticated[translate interface]' => 'translate interface'); $this->drupalPostForm('admin/people/permissions', $edit, t('Save permissions')); // Check and update the translation status. This will import the Afrikaans // translations of locale_test_translate module. $this->drupalGet('admin/reports/translations/check'); // Override the Drupal core translation status to be up to date. // Drupal core should not be a subject in this test. $status = locale_translation_get_status(); $status['drupal']['af']->type = 'current'; \Drupal::state()->set('locale.translation_status', $status); $this->drupalPostForm('admin/reports/translations', array(), t('Update translations')); // Check if configuration translations have been imported. $override = \Drupal::languageManager()->getLanguageConfigOverride('af', 'system.maintenance'); $this->assertEqual($override->get('message'), 'Ons is tans besig met onderhoud op @site. Wees asseblief geduldig, ons sal binnekort weer terug wees.'); }
protected function execute(InputInterface $input, OutputInterface $output) { $io = new DrupalStyle($input, $output); $language = $input->getArgument('language'); $tableHeader = [$this->trans('commands.locale.translation.status.messages.project'), $this->trans('commands.locale.translation.status.messages.version'), $this->trans('commands.locale.translation.status.messages.local-age'), $this->trans('commands.locale.translation.status.messages.remote-age'), $this->trans('commands.locale.translation.status.messages.info')]; $languages = locale_translatable_language_list(); $status = locale_translation_get_status(); $this->getModuleHandler()->loadInclude('locale', 'compare.inc'); if (!$languages) { $io->info($this->trans('commands.locale.translation.status.messages.no-languages')); return; } elseif (empty($status)) { $io->info($this->trans('commands.locale.translation.status.messages.no-translations')); return; } if ($languages) { $projectsStatus = $this->projectsStatus(); foreach ($projectsStatus as $langcode => $rows) { $tableRows = []; if ($language != '' && !($language == $langcode || strtolower($language) == strtolower($languages[$langcode]->getName()))) { continue; } $io->info($languages[$langcode]->getName()); foreach ($rows as $row) { if ($row[0] == 'drupal') { $row[0] = $this->trans('commands.common.messages.drupal-core'); } $tableRows[] = $row; } $io->table($tableHeader, $tableRows, 'compact'); } } }
protected function displayUpdates($language_filter, $output, $table) { $table->setHeaders([$this->trans('commands.locale.translation.status.messages.project'), $this->trans('commands.locale.translation.status.messages.version'), $this->trans('commands.locale.translation.status.messages.local-age'), $this->trans('commands.locale.translation.status.messages.remote-age'), $this->trans('commands.locale.translation.status.messages.info')]); $languages = locale_translatable_language_list(); $status = locale_translation_get_status(); $this->getModuleHandler()->loadInclude('locale', 'compare.inc'); if (!$languages) { $output->writeln('[+] <info>' . $this->trans('commands.locale.translation.status.messages.no-languages') . '</info>'); return; } elseif (empty($status)) { $output->writeln('[+] <info>' . $this->trans('commands.locale.translation.status.messages.no-translations') . '</info>'); return; } if ($languages) { $table->setStyle('compact'); $projectsStatus = $this->projectsStatus(); foreach ($projectsStatus as $langcode => $rows) { $table->setRows(array()); if ($language_filter != '' && !($language_filter == $langcode || strtolower($language_filter) == strtolower($languages[$langcode]->getName()))) { continue; } $output->writeln('[+] <info>' . $languages[$langcode]->getName() . '</info>'); foreach ($rows as $row) { if ($row[0] == 'drupal') { $row[0] = $this->trans('commands.common.messages.drupal-core'); } $table->addRow($row); } $table->render(); } } }
/** * LOCALE_TRANSLATION_REMOTE * and LOCALE_TRANSLATION_LOCAL indicate available new translations, * LOCALE_TRANSLATION_CURRENT indicate that the current translation is them * most recent. */ protected function projectsStatus() { $status_report = []; $status = locale_translation_get_status(); foreach ($status as $project_id => $project) { foreach ($project as $langcode => $project_info) { $info = ''; if ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) { $local = isset($project_info->files[LOCALE_TRANSLATION_LOCAL]) ? $project_info->files[LOCALE_TRANSLATION_LOCAL] : null; $remote = isset($project_info->files[LOCALE_TRANSLATION_REMOTE]) ? $project_info->files[LOCALE_TRANSLATION_REMOTE] : null; $local_age = $local->timestamp ? format_date($local->timestamp, 'html_date') : ''; $remote_age = $remote->timestamp ? format_date($remote->timestamp, 'html_date') : ''; if ($local_age >= $remote_age) { $info = $this->trans('commands.locale.translation.status.messages.translation-project-updated'); } else { $info = $this->trans('commands.locale.translation.status.messages.translation-project-available'); } } elseif ($project_info->type == LOCALE_TRANSLATION_CURRENT) { $info = $this->trans('commands.locale.translation.status.messages.translation-project-updated'); } else { $local_age = ''; $remote_age = ''; $info = $this->createInfoString($project_info); } $status_report[$langcode][] = [$project_info->name, $project_info->version, $local_age, $remote_age, $info]; } } return $status_report; }
/** * Form builder for displaying the current translation status. * * @ingroup forms */ public function buildForm(array $form, FormStateInterface $form_state) { $languages = locale_translatable_language_list(); $status = locale_translation_get_status(); $options = array(); $languages_update = array(); $languages_not_found = array(); $projects_update = array(); // Prepare information about projects which have available translation // updates. if ($languages && $status) { $updates = $this->prepareUpdateData($status); // Build data options for the select table. foreach ($updates as $langcode => $update) { $title = String::checkPlain($languages[$langcode]->getName()); $locale_translation_update_info = array('#theme' => 'locale_translation_update_info'); foreach (array('updates', 'not_found') as $update_status) { if (isset($update[$update_status])) { $locale_translation_update_info['#' . $update_status] = $update[$update_status]; } } $options[$langcode] = array('title' => array('class' => array('label'), 'data' => array('#title' => $title, '#markup' => $title)), 'status' => array('class' => array('description', 'expand', 'priority-low'), 'data' => drupal_render($locale_translation_update_info))); if (!empty($update['not_found'])) { $languages_not_found[$langcode] = $langcode; } if (!empty($update['updates'])) { $languages_update[$langcode] = $langcode; } } // Sort the table data on language name. uasort($options, function ($a, $b) { return strcasecmp($a['title']['data']['#title'], $b['title']['data']['#title']); }); $languages_not_found = array_diff($languages_not_found, $languages_update); } $last_checked = $this->state->get('locale.translation_last_checked'); $form['last_checked'] = array('#theme' => 'locale_translation_last_check', '#last' => $last_checked); $header = array('title' => array('data' => $this->t('Language'), 'class' => array('title')), 'status' => array('data' => $this->t('Status'), 'class' => array('status', 'priority-low'))); if (!$languages) { $empty = $this->t('No translatable languages available. <a href="@add_language">Add a language</a> first.', array('@add_language' => $this->url('language.admin_overview'))); } elseif ($status) { $empty = $this->t('All translations up to date.'); } else { $empty = $this->t('No translation status available. <a href="@check">Check manually</a>.', array('@check' => $this->url('locale.check_translation'))); } // The projects which require an update. Used by the _submit callback. $form['projects_update'] = array('#type' => 'value', '#value' => $projects_update); $form['langcodes'] = array('#type' => 'tableselect', '#header' => $header, '#options' => $options, '#default_value' => $languages_update, '#empty' => $empty, '#js_select' => TRUE, '#multiple' => TRUE, '#required' => TRUE, '#not_found' => $languages_not_found, '#after_build' => array('locale_translation_language_table')); $form['#attached']['library'][] = 'locale/drupal.locale.admin'; $form['#attached']['css'] = array(drupal_get_path('module', 'locale') . '/css/locale.admin.css'); $form['actions'] = array('#type' => 'actions'); if ($languages_update) { $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Update translations')); } return $form; }
/** * Tests the user interfaces of the interface translation update system. * * Testing the Available updates summary on the side wide status page and the * Avaiable translation updates page. */ function testInterface() { // No language added. // Check status page and Available translation updates page. $this->drupalGet('admin/reports/status'); $this->assertNoText(t('Translation update status'), 'No status message'); $this->drupalGet('admin/reports/translations'); $this->assertRaw(t('No translatable languages available. <a href="@add_language">Add a language</a> first.', array('@add_language' => url('admin/config/regional/language'))), 'Language message'); // Add German language. $this->addLanguage('de'); // Drupal core is probably in 8.x, but tests may also be executed with // stable releases. As this is an uncontrolled factor in the test, we will // mark Drupal core as translated and continue with the prepared modules. $status = locale_translation_get_status(); $status['drupal']['de']->type = 'current'; \Drupal::state()->set('locale.translation_status', $status); // One language added, all translations up to date. $this->drupalGet('admin/reports/status'); $this->assertText(t('Translation update status'), 'Status message'); $this->assertText(t('Up to date'), 'Translations up to date'); $this->drupalGet('admin/reports/translations'); $this->assertText(t('All translations up to date.'), 'Translations up to date'); // Set locale_test_translate module to have a local translation available. $status = locale_translation_get_status(); $status['locale_test_translate']['de']->type = 'local'; \Drupal::state()->set('locale.translation_status', $status); // Check if updates are available for German. $this->drupalGet('admin/reports/status'); $this->assertText(t('Translation update status'), 'Status message'); $this->assertRaw(t('Updates available for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => t('German'), '@updates' => url('admin/reports/translations'))), 'Updates available message'); $this->drupalGet('admin/reports/translations'); $this->assertText(t('Updates for: @modules', array('@modules' => 'Locale test translate')), 'Translations avaiable'); // Set locale_test_translate module to have a dev release and no // translation found. $status = locale_translation_get_status(); $status['locale_test_translate']['de']->version = '1.3-dev'; $status['locale_test_translate']['de']->type = ''; \Drupal::state()->set('locale.translation_status', $status); // Check if no updates were found. $this->drupalGet('admin/reports/status'); $this->assertText(t('Translation update status'), 'Status message'); $this->assertRaw(t('Missing translations for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => t('German'), '@updates' => url('admin/reports/translations'))), 'Missing translations message'); $this->drupalGet('admin/reports/translations'); $this->assertText(t('Missing translations for one project'), 'No translations found'); $this->assertText(t('@module (@version).', array('@module' => 'Locale test translate', '@version' => '1.3-dev')), 'Release details'); $this->assertText(t('No translation files are provided for development releases.'), 'Release info'); }
protected function displayUpdates($language_filter, $output, $table) { $table->setHeaders([$this->trans('commands.locale.translation.status.messages.project'), $this->trans('commands.locale.translation.status.messages.version'), $this->trans('commands.locale.translation.status.messages.local-age'), $this->trans('commands.locale.translation.status.messages.remote-age'), $this->trans('commands.locale.translation.status.messages.info')]); $languages = locale_translatable_language_list(); $status = locale_translation_get_status(); $this->getModuleHandler()->loadInclude('locale', 'compare.inc'); $project_data = locale_translation_build_projects(); if (!$languages) { $output->writeln('[+] <info>' . $this->trans('commands.locale.translation.status.messages.no-languages') . '</info>'); return; } elseif (empty($status)) { $output->writeln('[+] <info>' . $this->trans('commands.locale.translation.status.messages.no-translations') . '</info>'); return; } if ($languages && $status) { $table->setlayout($table::LAYOUT_COMPACT); $status_report = []; foreach ($status as $project_id => $project) { foreach ($project as $langcode => $project_info) { $info = $this->createInfoString($project_info); if ($project_info->type == LOCALE_TRANSLATION_LOCAL || $project_info->type == LOCALE_TRANSLATION_REMOTE) { $local = isset($project_info->files[LOCALE_TRANSLATION_LOCAL]) ? $project_info->files[LOCALE_TRANSLATION_LOCAL] : null; $remote = isset($project_info->files[LOCALE_TRANSLATION_REMOTE]) ? $project_info->files[LOCALE_TRANSLATION_REMOTE] : null; // Remove info because type was found $info = ''; } $local_age = $local->timestamp ? \Drupal::service('date.formatter')->formatTimeDiffSince($local->timestamp) : ''; $remote_age = $remote->timestamp ? \Drupal::service('date.formatter')->formatTimeDiffSince($remote->timestamp) : ''; $project_name = $project_info->name == 'drupal' ? $this->trans('commands.common.messages.drupal-core') : $project_data[$project_info->name]->info['name']; $status_report[$langcode][] = [$project_name, $project_info->version, $local_age, $remote_age, $info]; } } print $language_filter; foreach ($status_report as $langcode => $rows) { if ($language_filter != '' and !($language_filter == $langcode || strtolower($language_filter) == strtolower($languages[$langcode]->getName()))) { continue; } $output->writeln('[+] <info>' . $languages[$langcode]->getName() . '</info>'); foreach ($rows as $row) { $table->addRow($row); } } } $table->render($output); }
/** * Tests translation import from local sources. * * Test conditions: * - Source: local files only * - Import overwrite: all existing translations */ public function testUpdateImportSourceLocal() { $config = \Drupal::config('locale.settings'); // Build the test environment. $this->setTranslationFiles(); $this->setCurrentTranslations(); $config->set('translation.default_filename', '%project-%version.%language._po'); // Set the update conditions for this test. $edit = array('use_source' => LOCALE_TRANSLATION_USE_SOURCE_LOCAL, 'overwrite' => LOCALE_TRANSLATION_OVERWRITE_ALL); $this->drupalPostForm('admin/config/regional/translate/settings', $edit, t('Save configuration')); // Execute the translation update. $this->drupalGet('admin/reports/translations/check'); $this->drupalPostForm('admin/reports/translations', array(), t('Update translations')); // Check if the translation has been updated, using the status cache. $status = locale_translation_get_status(); $this->assertEqual($status['contrib_module_one']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_one found'); $this->assertEqual($status['contrib_module_two']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_two found'); $this->assertEqual($status['contrib_module_three']['de']->type, LOCALE_TRANSLATION_CURRENT, 'Translation of contrib_module_three found'); // Check the new translation status. // The static cache needs to be flushed first to get the most recent data // from the database. The function was called earlier during this test. drupal_static_reset('locale_translation_get_file_history'); $history = locale_translation_get_file_history(); $this->assertTrue($history['contrib_module_one']['de']->timestamp >= $this->timestampMedium, 'Translation of contrib_module_one is imported'); $this->assertEqual($history['contrib_module_one']['de']->last_checked, $this->timestampMedium, 'Translation of contrib_module_one is updated'); $this->assertEqual($history['contrib_module_two']['de']->timestamp, $this->timestampNew, 'Translation of contrib_module_two is imported'); $this->assertTrue($history['contrib_module_two']['de']->last_checked >= $this->timestamp_now, 'Translation of contrib_module_two is updated'); $this->assertEqual($history['contrib_module_three']['de']->timestamp, $this->timestampMedium, 'Translation of contrib_module_three is not imported'); $this->assertEqual($history['contrib_module_three']['de']->last_checked, $this->timestampMedium, 'Translation of contrib_module_three is not updated'); // Check whether existing translations have (not) been overwritten. $this->assertEqual(t('January', array(), array('langcode' => 'de')), 'Januar_customized', 'Translation of January'); $this->assertEqual(t('February', array(), array('langcode' => 'de')), 'Februar_2', 'Translation of February'); $this->assertEqual(t('March', array(), array('langcode' => 'de')), 'Marz_2', 'Translation of March'); $this->assertEqual(t('April', array(), array('langcode' => 'de')), 'April_2', 'Translation of April'); $this->assertEqual(t('May', array(), array('langcode' => 'de')), 'Mai_customized', 'Translation of May'); $this->assertEqual(t('June', array(), array('langcode' => 'de')), 'Juni', 'Translation of June'); $this->assertEqual(t('Monday', array(), array('langcode' => 'de')), 'Montag', 'Translation of Monday'); }
/** * Tests the user interfaces of the interface translation update system. * * Testing the Available updates summary on the side wide status page and the * Avaiable translation updates page. */ public function testInterface() { // No language added. // Check status page and Available translation updates page. $this->drupalGet('admin/reports/status'); $this->assertNoText(t('Translation update status'), 'No status message'); $this->drupalGet('admin/reports/translations'); $this->assertRaw(t('No translatable languages available. <a href="@add_language">Add a language</a> first.', array('@add_language' => \Drupal::url('entity.configurable_language.collection'))), 'Language message'); // Add German language. $this->addLanguage('de'); // Override Drupal core translation status as 'up-to-date'. $status = locale_translation_get_status(); $status['drupal']['de']->type = 'current'; \Drupal::state()->set('locale.translation_status', $status); // One language added, all translations up to date. $this->drupalGet('admin/reports/status'); $this->assertText(t('Translation update status'), 'Status message'); $this->assertText(t('Up to date'), 'Translations up to date'); $this->drupalGet('admin/reports/translations'); $this->assertText(t('All translations up to date.'), 'Translations up to date'); // Set locale_test_translate module to have a local translation available. $status = locale_translation_get_status(); $status['locale_test_translate']['de']->type = 'local'; \Drupal::state()->set('locale.translation_status', $status); // Check if updates are available for German. $this->drupalGet('admin/reports/status'); $this->assertText(t('Translation update status'), 'Status message'); $this->assertRaw(t('Updates available for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => t('German'), '@updates' => \Drupal::url('locale.translate_status'))), 'Updates available message'); $this->drupalGet('admin/reports/translations'); $this->assertText(t('Updates for: @modules', array('@modules' => 'Locale test translate')), 'Translations avaiable'); // Set locale_test_translate module to have a dev release and no // translation found. $status = locale_translation_get_status(); $status['locale_test_translate']['de']->version = '1.3-dev'; $status['locale_test_translate']['de']->type = ''; \Drupal::state()->set('locale.translation_status', $status); // Check if no updates were found. $this->drupalGet('admin/reports/status'); $this->assertText(t('Translation update status'), 'Status message'); $this->assertRaw(t('Missing translations for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => t('German'), '@updates' => \Drupal::url('locale.translate_status'))), 'Missing translations message'); $this->drupalGet('admin/reports/translations'); $this->assertText(t('Missing translations for one project'), 'No translations found'); $this->assertText(String::format('@module (@version). !info', array('@module' => 'Locale test translate', '@version' => '1.3-dev', '!info' => t('No translation files are provided for development releases.'))), 'Release details'); $this->assertText(t('No translation files are provided for development releases.'), 'Release info'); // Override Drupal core translation status as 'no translations found'. $status = locale_translation_get_status(); $status['drupal']['de']->type = ''; $status['drupal']['de']->timestamp = 0; $status['drupal']['de']->version = '8.1.1'; \Drupal::state()->set('locale.translation_status', $status); // Check if Drupal core is not translated. $this->drupalGet('admin/reports/translations'); $this->assertText(t('Missing translations for 2 projects'), 'No translations found'); $this->assertText(t('@module (@version).', array('@module' => t('Drupal core'), '@version' => '8.1.1')), 'Release details'); // Override Drupal core translation status as 'translations available'. $status = locale_translation_get_status(); $status['drupal']['de']->type = 'local'; $status['drupal']['de']->files['local']->timestamp = REQUEST_TIME; $status['drupal']['de']->files['local']->info['version'] = '8.1.1'; \Drupal::state()->set('locale.translation_status', $status); // Check if translations are available for Drupal core. $this->drupalGet('admin/reports/translations'); $this->assertText(t('Updates for: !project', array('!project' => t('Drupal core'))), 'Translations found'); $this->assertText(String::format('@module (@date)', array('@module' => t('Drupal core'), '@date' => format_date(REQUEST_TIME, 'html_date'))), 'Core translation update'); $update_button = $this->xpath('//input[@type="submit"][@value="' . t('Update translations') . '"]'); $this->assertTrue($update_button, 'Update translations button'); }