diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index 1411591..bfdf12a 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -602,10 +602,23 @@ function locale_translation_status_form($form, &$form_state) {
return $form;
}
+ // @todo It could be useful to consider refactoring theme_update_last_check().
+ $last = state()->get('locale.translation_last_checked');
+ $markup = '
';
+ $markup .= $last ? t('Last checked: @time ago', array('@time' => format_interval(REQUEST_TIME - $last))) : t('Last checked: never');
+ $markup .= ' (' . l(t('Check manually'), 'admin/reports/translations/check', array('query' => drupal_get_destination())) . ')';
+ $markup .= "
\n";
+ $form['last_checked'] = array(
+ '#markup' => $markup,
+ );
+
module_load_include('compare.inc', 'locale');
locale_translation_flush_projects();
$projects = locale_translation_get_projects();
$status = state()->get('locale.translation_status');
+ if (!$status) {
+ return $form;
+ }
// Prepare information about projects which have available translation
// updates.
@@ -616,6 +629,7 @@ function locale_translation_status_form($form, &$form_state) {
$projects_to_update[$langcode]['not_found'][] = array(
'name' => $project_info->name,
'version' => $project_info->version,
+ 'debug_info' => _locale_translation_status_debug_info($project_info->version, $project_info->files['remote']->uri, $project_info->files['local']->uri),
);
}
elseif ($project_info->type != 'current') {
@@ -627,60 +641,63 @@ function locale_translation_status_form($form, &$form_state) {
}
}
- // @todo It could be useful to consider refactoring theme_update_last_check().
- $last = state()->get('locale.translation_last_checked');
- $markup = '';
- $markup .= $last ? t('Last checked: @time ago', array('@time' => format_interval(REQUEST_TIME - $last))) : t('Last checked: never');
- $markup .= ' (' . l(t('Check manually'), 'admin/reports/translations/check', array('query' => drupal_get_destination())) . ')';
- $markup .= "
\n";
- $form['last_checked'] = array(
- '#markup' => $markup,
- );
-
- $form['langcodes_title'] = array(
- '#type' => 'item',
- '#title' => t('Languages'),
- );
- $header = array(
- 'title' => t('Title'),
- 'operations' => t('Operations'),
- );
$options = array();
foreach ($languages as $langcode => $language) {
if (isset($projects_to_update[$langcode])) {
+ $project_list = array(
+ 'updates' => isset($projects_to_update[$langcode]['updates']) ? $projects_to_update[$langcode]['updates'] : NULL,
+ 'not_found' => isset($projects_to_update[$langcode]['not_found']) ? $projects_to_update[$langcode]['not_found'] : NULL,
+ );
$options[$langcode] = array(
- 'title' => $language->name,
+ 'language' => $language->name,
+ 'description' => array(
+ 'class' => 'description',
+ 'data' => theme('locale_project_language_update_info', array(
+ 'projects' => $project_list,
+ 'type' => 'summary',
+ )),
+ ),
'operations' => array(
'class' => 'operations',
'data' => theme('locale_project_language_update_info', array(
- 'projects' => array(
- 'updates' => isset($projects_to_update[$langcode]['updates']) ? $projects_to_update[$langcode]['updates'] : NULL,
- 'not_found' => isset($projects_to_update[$langcode]['not_found']) ? $projects_to_update[$langcode]['not_found'] : NULL,
- ),
- 'langcode' => $langcode,
+ 'projects' => $project_list,
+ 'type' => 'detailed',
)),
),
);
}
}
- $form['langcodes'] = array(
- '#type' => 'tableselect',
- '#header' => $header,
- '#options' => $options,
- '#default_value' => drupal_map_assoc(array_keys($options)),
- );
- $form['actions'] = array(
- '#type' => 'actions',
- );
- $form['actions']['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Update'),
- );
- $form['#attached']['js'] = array(
- drupal_get_path('module', 'locale') . '/locale.toggle-interface-update-details.js' => array(
- 'type' => 'file',
- ),
- );
+ if (!empty($options)) {
+ $header = array(
+ 'language' => t('Language'),
+ 'description' => t('Description'),
+ 'operations' => t('Operations'),
+ );
+ $form['langcodes'] = array(
+ '#type' => 'tableselect',
+ '#header' => $header,
+ '#options' => $options,
+ '#default_value' => drupal_map_assoc(array_keys($options)),
+ );
+ // Disable language rows without available updates.
+ foreach ($form['langcodes']['#options'] as $langcode => $language_row) {
+ if (!isset($language_row['operations']['data']['updates_info'])) {
+ $form['langcodes'][$langcode]['#disable'] = TRUE;
+ }
+ }
+ $form['actions'] = array(
+ '#type' => 'actions',
+ );
+ $form['actions']['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Update translations'),
+ );
+ $form['#attached']['js'] = array(
+ drupal_get_path('module', 'locale') . '/locale.toggle-interface-update-details.js' => array(
+ 'type' => 'file',
+ ),
+ );
+ }
return $form;
}
@@ -711,6 +728,40 @@ function locale_translation_status_form_submit($form, &$form_state) {
}
/**
+ * Provides debug info when translation update were not found for a project.
+ *
+ * Translations files are being fetched either from Drupal translation server
+ * and local files or only from the local filesystem depending on the
+ * "Translation source" setting at admin/config/regional/translate/settings.
+ * This method will produce debug information including the respective path(s)
+ * based on this setting.
+ * Translations for development versions are never fetched, so the debug info
+ * for that is a fixed message.
+ *
+ * @param string $version
+ * Version of the project.
+ * @param string $remote_path
+ * Remote path where the translation file was tried to load from.
+ * @param string $local_path
+ * Local path where the translation file was tried to load from.
+ */
+function _locale_translation_status_debug_info($version, $remote_path, $local_path) {
+ if (strpos($version, 'dev') !== FALSE) {
+ return t('no translations provided for development releases');
+ }
+ $config = config('locale.settings');
+ if ($config->get('translation.use_source') == LOCALE_TRANSLATION_USE_SOURCE_REMOTE_AND_LOCAL) {
+ return t('File not found at %remote_path nor at %local_path', array(
+ '%remote_path' => $remote_path,
+ '%local_path' => $local_path,
+ ));
+ }
+ elseif ($config->get('translation.use_source') == LOCALE_TRANSLATION_USE_SOURCE_LOCAL) {
+ return t('File not found at %local_path', array('%local_path' => $local_path));
+ }
+}
+
+/**
* Default theme function for translation edit form.
*/
function theme_locale_translate_edit_form_strings($variables) {
@@ -746,11 +797,15 @@ function theme_locale_translate_edit_form_strings($variables) {
}
/**
- * Returns HTML for interface translation update status.
+ * Returns HTML to be displayed in the interface translation status overview.
*
- * Output contains the list of projects which language updates will be applied
- * to. A separated list is rendered which contains projects which language
- * updates were not found for.
+ * Output can be rendered in two modes. "Summary" displays a short sentence with
+ * a simple flat list of modules which updates are available for, possibly along
+ * with another sentence informing us about the number of modules which updates
+ * were not found for.
+ * The detailed view displays the aforementioned sentences following with a list
+ * of modules together with version numbers and possibly with debug information
+ * when updates were not found.
*
* @param $variables
* An associative array containing:
@@ -765,57 +820,81 @@ function theme_locale_translate_edit_form_strings($variables) {
* not found for. Each element of the array is an associative array with
* the following keys:
* - project: Human readable name of the project.
- * - version: Version of the project.
+ * - version: Optional. Version of the project.
+ * - debug_info: Optional. Reason of why update were not found for the
+ * project.
+ * - type: Optional. 'summary' or 'detailed'. Summary view will be returned if
+ * parameter is not provided.
*
* @ingroup themeable
*/
function theme_locale_project_language_update_info($variables) {
$output = array();
+ $type = (isset($variables['type'])) ? $variables['type'] : 'summary';
$project_list = array();
- if (isset($variables['projects']['updates'])) {
- foreach ($variables['projects']['updates'] as $project) {
- $project_list['flat'][] = $project['name'];
- $project_list['details'][] = format_string('!name (!version)', array(
- '!name' => $project['name'],
- '!version' => $project['version'],
+
+ foreach ($variables['projects'] as $update_status => $projects) {
+ if (is_array($projects)) {
+ foreach ($projects as $project) {
+ if ($type == 'detailed') {
+ $project_display = $project['name'];
+ if (!empty($project['version'])) {
+ $project_display .= format_string(' (!version)', array('!version' => $project['version']));
+ }
+ if (!empty($project['debug_info'])) {
+ $project_display .= format_string(': !info', array('!info' => $project['debug_info']));
+ }
+ $project_list[$update_status][] = $project_display;
+ }
+ else {
+ $project_list[$update_status][] = $project['name'];
+ }
+ }
+ }
+ }
+
+ if (!empty($project_list['updates'])) {
+ $output['updates_info'] = array();
+ if ($type == 'detailed') {
+ $summary = t('Translation updates available for:');
+ $output['updates_info']['#suffix'] = theme('item_list', array(
+ 'items' => $project_list['updates'],
+ 'attributes' => array(
+ 'class' => array('detailed-list'),
+ ),
));
}
- $output['updates_summary'] = array(
- '#type' => 'markup',
- '#markup' => '' . t('This applies language updates to %projects.', array(
- '%projects' => implode(', ', $project_list['flat']),
- )) . "
",
- );
- $output['updates_details'] = array(
- '#theme' => 'item_list',
- '#items' => $project_list['details'],
- '#attributes' => array(
- 'class' => array('details'),
- ),
- );
+ else {
+ $summary = t('Translation updates available for: %projects.', array(
+ '%projects' => implode(', ', $project_list['updates']),
+ ));
+ }
+ $output['updates_info']['#markup'] = '' . $summary . '
';
}
- $project_list = array('count' => 0);
- if (isset($variables['projects']['not_found'])) {
- foreach ($variables['projects']['not_found'] as $project) {
- $project_list['count']++;
- $project_list['details'][] = format_string('!name (!version)', array(
- '!name' => $project['name'],
- '!version' => $project['version'],
+
+ if (!empty($project_list['not_found'])) {
+ $output['not_found_info'] = array();
+ if ($type == 'detailed') {
+ $summary = t('No translations found for:');
+ $output['not_found_info']['#suffix'] = theme('item_list', array(
+ 'items' => $project_list['not_found'],
+ 'attributes' => array(
+ 'class' => array('detailed-list'),
+ ),
));
}
- $output['not_found_summary'] = array(
- '#type' => 'markup',
- '#markup' => '' . t('No updates were found for %count projects.', array(
- '%count' => $project_list['count'],
- )) . '
',
- );
- $output['not_found_details'] = array(
- '#theme' => 'item_list',
- '#items' => $project_list['details'],
- '#attributes' => array(
- 'class' => array('details'),
- ),
- );
+ else {
+ $summary = t('No translations found for %count projects.', array(
+ '%count' => count($project_list['not_found']),
+ ));
+ }
+ $output['not_found_info']['#markup'] = '' . $summary . '
';
+ }
+
+ if ($type == 'detailed') {
+ // Wrapping everything in a div helps adding toggle links with JS.
+ $output['#prefix'] = '';
+ $output['#suffix'] = '
';
}
return $output;
}
diff --git a/core/modules/locale/locale.toggle-interface-update-details.js b/core/modules/locale/locale.toggle-interface-update-details.js
index cf37891..fa2ff0c 100644
--- a/core/modules/locale/locale.toggle-interface-update-details.js
+++ b/core/modules/locale/locale.toggle-interface-update-details.js
@@ -7,12 +7,12 @@
*/
Drupal.behaviors.toggleInterfaceUpdateDetails = {
attach: function (context, settings) {
- $('' + Drupal.t('Details') + '').insertAfter('td.operations > .summary')
+ $('' + Drupal.t('Show details') + '').insertBefore('td.operations > .details')
.toggle(function() {
$(this).text(Drupal.t('Hide details'));
$(this).next().show();
}, function() {
- $(this).text(Drupal.t('Details'));
+ $(this).text(Drupal.t('Show details'));
$(this).next().hide();
}).next().hide()
}