updated i18n, views, imagestyleflush, field_group
patch views_rss_media
This commit is contained in:
		| @@ -12,16 +12,16 @@ contentadminrelink | ||||
| entityreference | ||||
| feedback | ||||
| filter_path_alias | ||||
| termreferencetree | ||||
| ?? views | ||||
| wysiwyg | ||||
| views_rss_media (https://www.drupal.org/node/2472409) | ||||
| node_export : | ||||
|   - https://www.drupal.org/node/1869918 | ||||
|   - https://www.drupal.org/node/1911638 | ||||
| flag_lists | ||||
|   - https://www.drupal.org/project/flag_lists/issues/2114731 | ||||
| login_tobogan (pd with field permission et donc field collection) | ||||
|   - https://www.drupal.org/node/1365764#comment-10286257 | ||||
|   - logintoboggan-exempting_lt_preauth_role_from_user_permissions_js-1365764-52.patch | ||||
|   - interdiff-1365764-23-52-do-not-test.diff | ||||
| flag_lists | ||||
|   - https://www.drupal.org/project/flag_lists/issues/2114731 | ||||
| node_export : | ||||
|   - https://www.drupal.org/node/1869918 | ||||
|   - https://www.drupal.org/node/1911638 | ||||
| termreferencetree | ||||
| ?? views | ||||
| views_rss_media (https://www.drupal.org/node/2472409) | ||||
| wysiwyg | ||||
|   | ||||
| @@ -1,6 +1,37 @@ | ||||
| /* $Id*/ | ||||
| CHANGELOG for field_group for Drupal 7 | ||||
|  | ||||
| Field Group origin/7.x-1.x, 2017-11-04 | ||||
| -------------------------------------- | ||||
| - Tests fail after new 'administer fields' permission. | ||||
| - Update CHANGELOG.txt to 7.x-1.5 Release. | ||||
| - Revert "Issue #2646106 by jribeiro: Update CHANGELOG.txt to 7.x-1.5 Release". | ||||
| - Update CHANGELOG.txt to 7.x-1.5 Release. | ||||
| - Fix whitespace between "&" and parameters for some functions. | ||||
| - Avoid bad code pattern (that is picked up by security scanners) when getting hash. | ||||
| - Should #array_parents be updated in field_group_fields_nest()?. | ||||
| - "Show" appears in horizontal tab title if node form submitted through ajax. | ||||
| - CSS breaks i18n string translation interface. | ||||
| - "uncaught exception: Syntax error, unrecognized expression: #" after 7.x-1.4 update. | ||||
| - PHP7 - Uniform Variable Syntax updates are causing exported field_groups to not have names. | ||||
|  | ||||
| Field_group 7.x-1.5 | ||||
|     o Added extra formatting on html element attributes. | ||||
|     o Fixed bug on automatic ID generation in javascript. | ||||
|     o Issue #2511960 by rrfegade: spelling errors in D7. | ||||
|     o Issue #2194279 by Georgique: Export translatables (label and descriptions) in Features. | ||||
|     o Issue #2386335 by Dubs: Integer Group Array Keys can create empty node forms. | ||||
|     o Issue #2269133 by sammuell: Accordion is always closed when using jQuery update module. | ||||
|     o Issue #2258939 by Snipon: Fixed Change to preventDefault on multipage controls. | ||||
|     o Issue #2173937 by jantoine, omerida | Bernieman: Fixed Accordion Element has fixed height in HTML. | ||||
|     o Issue #2311789 by eelkeblok: Fixed Group is incorrectly determined to be empty with nested form elements. | ||||
|     o Issue #2272003 by karolrybak | Kwb: Fixed Fieldgroup no longer renders after using more than one 'HTML Element' on the same level. | ||||
|     o Issue #2309219 by czigor: Fixed Proper CTools exportable loading. | ||||
|     o Issue #2283245 by stefan.r | jrb: Fixed New id functionality breaks tests and CSS on existing field groups. | ||||
|     o Issue #2295133 by boyan.borisov, interX: Fixed field_group_update_7007 error. | ||||
|     o Remove field_group.css, the css is not needed anymore. | ||||
|     o Fix horiziontal tabs when used as standalone element. | ||||
|  | ||||
| Field_group 7.x-1.4 | ||||
|     o Issue #2129805 by RaF: Incorrect markup when open div & custom classes provided. | ||||
|     o Issue #2037731 by maximpodorov, Zach Harkey: Remove id attribute from HTML elements. | ||||
|   | ||||
| @@ -220,7 +220,7 @@ function hook_field_group_format_settings($group) { | ||||
|  * @param Array $elements by address. | ||||
|  * @param Object $group The Field group info. | ||||
|  */ | ||||
| function hook_field_group_pre_render(& $element, $group, & $form) { | ||||
| function hook_field_group_pre_render(&$element, $group, &$form) { | ||||
|  | ||||
|   // You can prepare some variables to use in the logic. | ||||
|   $view_mode = isset($form['#view_mode']) ? $form['#view_mode'] : 'form'; | ||||
| @@ -268,7 +268,7 @@ function hook_field_group_pre_render(& $element, $group, & $form) { | ||||
|  * | ||||
|  * Function that fungates as last resort to alter the pre_render build. | ||||
|  */ | ||||
| function hook_field_group_pre_render_alter(&$element, $group, & $form) { | ||||
| function hook_field_group_pre_render_alter(&$element, $group, &$form) { | ||||
|  | ||||
|   if ($group->format_type == 'htab') { | ||||
|     $element['#theme_wrappers'] = array('my_horizontal_tab'); | ||||
| @@ -285,7 +285,7 @@ function hook_field_group_pre_render_alter(&$element, $group, & $form) { | ||||
|  * | ||||
|  * @param Array $elements by address. | ||||
|  */ | ||||
| function hook_field_group_build_pre_render_alter(& $element) { | ||||
| function hook_field_group_build_pre_render_alter(&$element) { | ||||
|  | ||||
|   // Prepare variables. | ||||
|   $display = isset($element['#view_mode']); | ||||
|   | ||||
| @@ -99,10 +99,10 @@ function field_group_field_ui_overview_form_alter(&$form, &$form_state, $display | ||||
|     // Play around with form_state so we only need to hold things | ||||
|     // between requests, until the save button was hit. | ||||
|     if (isset($form_state['field_group'][$name])) { | ||||
|       $group = & $form_state['field_group'][$name]; | ||||
|       $group = &$form_state['field_group'][$name]; | ||||
|     } | ||||
|     else { | ||||
|       $group = & $params->groups[$name]; | ||||
|       $group = &$params->groups[$name]; | ||||
|     } | ||||
|  | ||||
|     // Check the currently selected formatter, and merge persisted values for | ||||
| @@ -456,7 +456,7 @@ function field_group_format_settings_label_validate($element, &$form_state) { | ||||
|  * @param Object $group | ||||
|  * @param array $settings | ||||
|  */ | ||||
| function field_group_formatter_row_update(& $group, $settings) { | ||||
| function field_group_formatter_row_update(&$group, $settings) { | ||||
|   // if the row has changed formatter type, update the group object | ||||
|   if (!empty($settings['format']['type']) && $settings['format']['type'] != $group->format_type) { | ||||
|     $group->format_type = $settings['format']['type']; | ||||
| @@ -469,7 +469,7 @@ function field_group_formatter_row_update(& $group, $settings) { | ||||
|  * @param Object $group The group object | ||||
|  * @param Array $settings Configuration settings | ||||
|  */ | ||||
| function field_group_formatter_settings_update(& $group, $settings) { | ||||
| function field_group_formatter_settings_update(&$group, $settings) { | ||||
|  | ||||
|   // for format changes we load the defaults. | ||||
|   if (empty($settings['format_settings']['settings'])) { | ||||
|   | ||||
| @@ -6,9 +6,9 @@ dependencies[] = ctools | ||||
| core = 7.x | ||||
| files[] = tests/field_group.ui.test | ||||
| files[] = tests/field_group.display.test | ||||
| ; Information added by Drupal.org packaging script on 2016-02-28 | ||||
| version = "7.x-1.5+2-dev" | ||||
| ; Information added by Drupal.org packaging script on 2017-11-03 | ||||
| version = "7.x-1.6" | ||||
| core = "7.x" | ||||
| project = "field_group" | ||||
| datestamp = "1456658044" | ||||
| datestamp = "1509751991" | ||||
|  | ||||
|   | ||||
| @@ -258,8 +258,6 @@ function field_group_field_attach_delete_bundle($entity_type, $bundle) { | ||||
|  * Implements hook_field_attach_form(). | ||||
|  */ | ||||
| function field_group_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) { | ||||
|  | ||||
|   $form['#attached']['css'][] = drupal_get_path('module', 'field_group') . '/field_group.field_ui.css'; | ||||
|   field_group_attach_groups($form, 'form', $form_state); | ||||
|   $form['#pre_render'][] = 'field_group_form_pre_render'; | ||||
| } | ||||
| @@ -1110,7 +1108,7 @@ function field_group_pre_render_tab(&$element, $group, &$form) { | ||||
|  * Implements hook_field_group_build_pre_render_alter(). | ||||
|  * @param Array $elements by address. | ||||
|  */ | ||||
| function field_group_field_group_build_pre_render_alter(& $element) { | ||||
| function field_group_field_group_build_pre_render_alter(&$element) { | ||||
|  | ||||
|   // Someone is doing a node view, in a node view. Reset content. | ||||
|   // TODO Check if this breaks something else. | ||||
| @@ -2027,6 +2025,19 @@ function field_group_fields_nest(&$element, &$vars = NULL) { | ||||
|       // Construct own weight, as some fields (for example preprocess fields) don't have weight set. | ||||
|       $element[$group_name] = array(); | ||||
|       $group_references[$group_name] = &$element[$group_name]; | ||||
|       // Get group parents | ||||
|       $parents = array(); | ||||
|       $current_group = $group; | ||||
|       while (!empty($current_group)) { | ||||
|         array_unshift($parents, $current_group->group_name); | ||||
|         $current_group = isset($element['#fieldgroups'][$current_group->parent_name]) ? | ||||
|           $element['#fieldgroups'][$current_group->parent_name] : NULL; | ||||
|       } | ||||
|       $group_references[$group_name]['#array_parents'] = $parents; | ||||
|       $element['#fieldgroups'][$group_name]->array_parents = $parents; | ||||
|       // Remove self from parents and set #field_parents | ||||
|       array_pop($parents); | ||||
|       $group_references[$group_name]['#field_parents'] = $parents; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -2077,6 +2088,19 @@ function field_group_fields_nest(&$element, &$vars = NULL) { | ||||
|         // list intact (but if it is a field we don't mind). | ||||
|         $group_references[$parent_name][$child_name] = &$element[$child_name]; | ||||
|         $group_references[$parent_name]['#weight'] = $element['#fieldgroups'][$parent_name]->weight; | ||||
|         // Prepend #array_parents & #field_parents of group child element & its element_children | ||||
|         // if those keys are set, and don't already include the group parents | ||||
|         $group_child = &$group_references[$parent_name][$child_name]; | ||||
|         $group_parents = $group_references[$parent_name]['#array_parents']; | ||||
|         $process_elements = array_merge(array(&$group_child), _field_group_element_children_recursive_ref($group_child)); | ||||
|         foreach ($process_elements as $key => $current_element) { | ||||
|           if (isset($current_element['#array_parents']) && !in_array($group_parents[0], $current_element['#array_parents'])) { | ||||
|             $process_elements[$key]['#array_parents'] = array_merge($group_parents, $current_element['#array_parents']); | ||||
|           } | ||||
|           if (isset($current_element['#field_parents']) && !in_array($group_parents[0], $current_element['#field_parents'])) { | ||||
|             $process_elements[$key]['#field_parents'] = array_merge($group_parents, $current_element['#field_parents']); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       // The child has been copied to its parent: remove it from the root element. | ||||
| @@ -2093,6 +2117,23 @@ function field_group_fields_nest(&$element, &$vars = NULL) { | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Recursive element_children, returns children by reference | ||||
|  */ | ||||
| function _field_group_element_children_recursive_ref(&$element) { | ||||
|   $results = array(); | ||||
|   $children = element_children($element); | ||||
|   foreach ($children as $key) { | ||||
|     $child = &$element[$key]; | ||||
|     if (is_array($child)) { | ||||
|       $results[] = &$child; | ||||
|       $results = array_merge($results, _field_group_element_children_recursive_ref($child)); | ||||
|     } | ||||
|     unset($child); | ||||
|   } | ||||
|   return $results; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Function to pre render the field group element. | ||||
|  * | ||||
|   | ||||
| @@ -29,8 +29,10 @@ Drupal.behaviors.horizontalTabs = { | ||||
|  | ||||
|       // Transform each fieldset into a tab. | ||||
|       $fieldsets.each(function (i) { | ||||
|         var $legend = $('> legend', this); | ||||
|         $('.element-invisible', $legend).remove(); | ||||
|         var horizontal_tab = new Drupal.horizontalTab({ | ||||
|           title: $('> legend', this).text(), | ||||
|           title: $legend.text(), | ||||
|           fieldset: $(this) | ||||
|         }); | ||||
|         horizontal_tab.item.addClass('horizontal-tab-button-' + i); | ||||
| @@ -52,7 +54,7 @@ Drupal.behaviors.horizontalTabs = { | ||||
|         // element that matches the URL fragment, activate that tab. | ||||
|         var hash = window.location.hash.replace(/[=%;,\/]/g, ""); | ||||
|         if (hash !== '#' && $(hash, this).length) { | ||||
|           tab_focus = $(window.location.hash, this).closest('.horizontal-tabs-pane'); | ||||
|           tab_focus = $(hash, this).closest('.horizontal-tabs-pane'); | ||||
|         } | ||||
|         else { | ||||
|           tab_focus = $('> .horizontal-tabs-pane:first', this); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ class GroupUITestCase extends DrupalWebTestCase { | ||||
|     parent::setUp('field_test', 'field_group', 'field_group_test'); | ||||
|  | ||||
|     // Create test user. | ||||
|     $admin_user = $this->drupalCreateUser(array('administer content types', 'administer nodes', 'access administration pages', 'bypass node access')); | ||||
|     $admin_user = $this->drupalCreateUser(array('administer content types', 'administer nodes', 'access administration pages', 'bypass node access', 'administer fields')); | ||||
|     $this->drupalLogin($admin_user); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -5,9 +5,9 @@ package = Fields | ||||
| hidden = TRUE | ||||
|  | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2016-02-28 | ||||
| version = "7.x-1.5+2-dev" | ||||
| ; Information added by Drupal.org packaging script on 2017-11-03 | ||||
| version = "7.x-1.6" | ||||
| core = "7.x" | ||||
| project = "field_group" | ||||
| datestamp = "1456658044" | ||||
| datestamp = "1509751991" | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,7 @@ Features | ||||
|  | ||||
|   - Flush all image styles | ||||
|   - Flush each individual image style | ||||
|   - Integrates with the admin_menu module | ||||
|  | ||||
|  | ||||
| Dependencies | ||||
| @@ -29,6 +30,8 @@ Install | ||||
| 2) In your Drupal site, enable the module under Administration -> Modules | ||||
|    (/admin/modules). | ||||
|  | ||||
| 3) Visit the Administration -> People -> Permissions page to give the | ||||
|    appropriate roles access to flush image styles. | ||||
|  | ||||
| Usage | ||||
| ----- | ||||
| @@ -36,6 +39,8 @@ Usage | ||||
| You can flush image styles under Administration -> Configuration -> Media | ||||
| -> Image styles | ||||
|  | ||||
| Note that this module only flushes images. It does not rebuild them. | ||||
|  | ||||
|  | ||||
| Known problems | ||||
| -------------- | ||||
|   | ||||
| @@ -4,9 +4,9 @@ package = Media | ||||
| core = 7.x | ||||
| configure = admin/config/media/image-styles | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-11-07 | ||||
| version = "7.x-1.3" | ||||
| ; Information added by Drupal.org packaging script on 2017-12-09 | ||||
| version = "7.x-1.5" | ||||
| core = "7.x" | ||||
| project = "imagestyleflush" | ||||
| datestamp = "1446884340" | ||||
| datestamp = "1512780486" | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * @file | ||||
|  * Contains install and update functions for imagestyleflush. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A new permission has been defined. Give it to all roles that currently | ||||
|  * have the 'administer image styles' permission. | ||||
|  */ | ||||
| function imagestyleflush_update_7000() { | ||||
|   // Since hook_update_N() can run on disabled modules, ensure the module | ||||
|   // file is loaded so we can get the list of permissions. | ||||
|   module_load_include('module', 'imagestyleflush', 'imagestyleflush'); | ||||
|   $permissions = array_keys(imagestyleflush_permission()); | ||||
|  | ||||
|   // Get existing role_permissions. | ||||
|   $rids = db_select('role_permission', 'rp') | ||||
|     ->fields('rp', array('rid')) | ||||
|     ->condition('permission', 'administer image styles') | ||||
|     ->execute() | ||||
|     ->fetchCol(); | ||||
|  | ||||
|   // Add the permissions for each role. | ||||
|   foreach ($rids as $rid) { | ||||
|     foreach ($permissions as $name) { | ||||
|       db_merge('role_permission') | ||||
|         ->key(array( | ||||
|           'rid' => $rid, | ||||
|           'permission' => $name, | ||||
|         )) | ||||
|         ->fields(array( | ||||
|           'module' => 'imagestyleflush', | ||||
|         )) | ||||
|         ->execute(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -14,7 +14,7 @@ function imagestyleflush_menu() { | ||||
|     'description' => 'Flush all image styles.', | ||||
|     'page callback' => 'drupal_get_form', | ||||
|     'page arguments' => array('imagestyleflush_form'), | ||||
|     'access arguments' => array('administer image styles'), | ||||
|     'access arguments' => array('flush image styles'), | ||||
|     'type' => MENU_LOCAL_ACTION, | ||||
|     'weight' => 3, | ||||
|   ); | ||||
| @@ -23,12 +23,24 @@ function imagestyleflush_menu() { | ||||
|     'description' => 'Flush an image style.', | ||||
|     'page callback' => 'drupal_get_form', | ||||
|     'page arguments' => array('imagestyleflush_form', 5), | ||||
|     'access arguments' => array('administer image styles'), | ||||
|     'access arguments' => array('flush image styles'), | ||||
|   ); | ||||
|  | ||||
|   return $items; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_permission(). | ||||
|  */ | ||||
| function imagestyleflush_permission() { | ||||
|   return array( | ||||
|     'flush image styles' => array( | ||||
|       'title' => t('Flush image styles'), | ||||
|       'description' => t('Allow users to flush image styles.'), | ||||
|     ), | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_theme_registry_alter(). | ||||
|  */ | ||||
| @@ -44,7 +56,10 @@ function imagestyleflush_theme_registry_alter(&$theme_registry) { | ||||
| function imagestyleflush_image_style_list($variables) { | ||||
|   $styles = $variables['styles']; | ||||
|  | ||||
|   $header = array(t('Style name'), t('Settings'), array('data' => t('Operations'), 'colspan' => 3)); | ||||
|   // Account for an extra column added by the image_styles_admin submodule of | ||||
|   // the imagecache_actions module. | ||||
|   $colspan = module_exists('image_styles_admin') ? 4 : 3; | ||||
|   $header = array(t('Style name'), t('Settings'), array('data' => t('Operations'), 'colspan' => $colspan)); | ||||
|   $rows = array(); | ||||
|   foreach ($styles as $style) { | ||||
|     $row = array(); | ||||
| @@ -77,7 +92,7 @@ function imagestyleflush_image_style_list($variables) { | ||||
|  | ||||
|   if (empty($rows)) { | ||||
|     $rows[] = array(array( | ||||
|       'colspan' => 4, | ||||
|       'colspan' => $colspan, | ||||
|       'data' => t('There are currently no styles. <a href="!url">Add a new one</a>.', array('!url' => url('admin/config/media/image-styles/add'))), | ||||
|     )); | ||||
|   } | ||||
| @@ -105,7 +120,8 @@ function imagestyleflush_form($form, &$form_state, $style = NULL) { | ||||
|       ), | ||||
|       t('Are you sure you want to flush the %style image style?', array('%style' => $style['label'])), | ||||
|       'admin/config/media/image-styles', | ||||
|        t('This action cannot be undone.'), | ||||
|       '<em>' . t('Note: this will only flush the images. It will not rebuild them.') | ||||
|         . '</em><br><br>' . t('This action cannot be undone.'), | ||||
|       t('Flush'), t('Cancel') | ||||
|     ); | ||||
|   } | ||||
| @@ -114,7 +130,8 @@ function imagestyleflush_form($form, &$form_state, $style = NULL) { | ||||
|       NULL, | ||||
|       t('Are you sure you want to flush all image styles?'), | ||||
|       'admin/config/media/image-styles', | ||||
|        t('This action cannot be undone.'), | ||||
|       '<em>' . t('Note: this will only flush the images. It will not rebuild them.') | ||||
|         . '</em><br><br>' . t('This action cannot be undone.'), | ||||
|       t('Flush'), t('Cancel') | ||||
|     ); | ||||
|   } | ||||
| @@ -138,6 +155,12 @@ function imagestyleflush_form_submit($form, &$form_state) { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Redirect to the destination URL. | ||||
|   $destination = drupal_get_destination(); | ||||
|   if ($destination['destination'] != current_path()) { | ||||
|     $operations[] = array('imagestyleflush_batch_destination_redirect', $destination); | ||||
|   } | ||||
|  | ||||
|   $batch = array( | ||||
|     'operations' => $operations, | ||||
|     'finished' => 'imagestyleflush_batch_finished', | ||||
| @@ -146,6 +169,15 @@ function imagestyleflush_form_submit($form, &$form_state) { | ||||
|   batch_set($batch); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Batch operation. Redirect the batch operation if it was called from the | ||||
|  * admin_menu item. | ||||
|  */ | ||||
| function imagestyleflush_batch_destination_redirect($destination, &$context) { | ||||
|   // Set the destination redirect. | ||||
|   $context['results']['redirect'] = $destination; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Batch message. | ||||
|  */ | ||||
| @@ -156,5 +188,51 @@ function imagestyleflush_batch_finished($success, $results, $operations) { | ||||
|   else { | ||||
|     drupal_set_message(t('An error occurred while flushing the image caches.'), 'error'); | ||||
|   } | ||||
|   drupal_goto('admin/config/media/image-styles'); | ||||
|  | ||||
|   if (!empty($results['redirect'])) { | ||||
|     drupal_goto($results['redirect']); | ||||
|   } | ||||
|   else { | ||||
|     // Send the user to the right place depending on their access. | ||||
|     if (user_access('administer image styles')) { | ||||
|       drupal_goto('admin/config/media/image-styles'); | ||||
|     } | ||||
|     else { | ||||
|       drupal_goto(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_admin_menu_output_build(). | ||||
|  */ | ||||
| function imagestyleflush_admin_menu_output_build(&$content) { | ||||
|   // Add link to the icon menu to flush image styles. | ||||
|   if (isset($content['icon'])) { | ||||
|     $styles = image_styles(); | ||||
|     $access = user_access('flush image styles'); | ||||
|     $destination = drupal_get_destination(); | ||||
|  | ||||
|     $style_links = array(); | ||||
|     foreach ($styles as $style) { | ||||
|       $style_links[$style['name']] = array( | ||||
|         '#title' => $style['label'], | ||||
|         '#href' => 'admin/config/media/image-styles/flush/' . $style['name'], | ||||
|         '#access' => $access, | ||||
|         '#options' => array( | ||||
|           'query' => $destination, | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     $content['icon']['icon']['flush-image-styles'] = array( | ||||
|       '#title' => t('Flush all image styles'), | ||||
|       '#access' => $access, | ||||
|       '#href' => 'admin/config/media/image-styles/flush', | ||||
|       '#options' => array( | ||||
|         'query' => $destination, | ||||
|       ), | ||||
|       '#weight' => 25, | ||||
|     ) + $style_links; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -20,7 +20,7 @@ For support, please create a support request for this module's project: | ||||
|  | ||||
| Support questions by email to the module maintainer will be simply ignored. Use the issue tracker. | ||||
|  | ||||
| Now if you want professional (paid) support the module maintainer may be available occassionally. | ||||
| Now if you want professional (paid) support the module maintainer may be available occasionally. | ||||
| Drop me a message to check availability and hourly rates, http://reyero.net/en/contact | ||||
|  | ||||
| ==================================================================== | ||||
|   | ||||
| @@ -8,9 +8,8 @@ files[] = i18n_object.inc | ||||
| files[] = i18n.test | ||||
| configure = admin/config/regional/i18n | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -198,7 +198,8 @@ function i18n_language_field_extra() { | ||||
|  */ | ||||
| function i18n_language_list($field = 'name', $mode = NULL) { | ||||
|   $mode = isset($mode) ? $mode : variable_get('i18n_language_list', I18N_LANGUAGE_ENABLED); | ||||
|   return locale_language_list($field, I18N_LANGUAGE_EXTENDED & $mode); | ||||
|   $all = I18N_LANGUAGE_EXTENDED & $mode; | ||||
|   return locale_language_list($field, $all); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -11,7 +11,7 @@ class Drupali18nTestCase extends DrupalWebTestCase { | ||||
|  | ||||
|   function setUpLanguages($admin_permissions = array()) { | ||||
|     // Setup admin user. | ||||
|     $this->admin_user = $this->drupalCreateUser(array_merge(array('bypass node access', 'administer nodes', 'administer languages', 'administer content types', 'administer blocks', 'access administration pages', 'translate interface'), $admin_permissions)); | ||||
|     $this->admin_user = $this->drupalCreateUser(array_merge(array('bypass node access', 'administer nodes', 'administer languages', 'administer content types', 'administer fields', 'administer blocks', 'access administration pages', 'translate interface'), $admin_permissions)); | ||||
|  | ||||
|     $this->drupalLogin($this->admin_user); | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,92 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Troubleshooting | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Block languages module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, allows the user to configure | ||||
| for which languages each block is visible. | ||||
|  | ||||
| * For a full description of the module, | ||||
|   visit https://www.drupal.org/node/1279698. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| The settings for visibility per language are provided under Visibility | ||||
| Settings via the Languages tab when configuring a block. | ||||
|  | ||||
| The Languages tab also provides a setting for whether the block is translatable. | ||||
| For custom blocks, the block title and the block content will be translatable. | ||||
| For blocks defined by modules, only the block title will be translatable. If | ||||
| "Make this block translatable" is selected, a Translate tab will appear for that | ||||
| block. This tab provides a UI for adding translations of the block in each | ||||
| available language. | ||||
|  | ||||
|  | ||||
| TROUBLESHOOTING | ||||
| --------------- | ||||
|  | ||||
| Conflicts with Context | ||||
|  | ||||
| The Block languages module conflicts with the Context module, which alters how | ||||
| blocks are rendered. This issue can be tracked in the Internationalization | ||||
| issue queue: http://drupal.org/node/1343044 | ||||
|  | ||||
| String Errors | ||||
|  | ||||
| The user must allow your used string format to be translated on | ||||
| admin/config/regional/i18n/strings or you are going to have an error message | ||||
| like "The string blocks:block:1:body for textgroup blocks is not allowed for | ||||
| translation because of its text format." | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -8,9 +8,8 @@ files[] = i18n_block.inc | ||||
| files[] = i18n_block.test | ||||
|  | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -37,6 +37,17 @@ function i18n_block_menu() { | ||||
|   return $items; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_permission(). | ||||
|  */ | ||||
| function i18n_block_permission() { | ||||
|   return array( | ||||
|     'translate blocks' => array( | ||||
|       'title' => t('Translate Blocks'), | ||||
|     ), | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implement hook_menu_alter(). | ||||
|  * | ||||
| @@ -59,7 +70,7 @@ function i18n_block_menu_alter(&$items) { | ||||
|  */ | ||||
| function i18n_block_translate_tab_access($module, $delta) { | ||||
|   $block = block_load($module, $delta); | ||||
|   return user_access('translate interface') && $block && isset($block->i18n_mode) && ($block->i18n_mode == I18N_MODE_LOCALIZE); | ||||
|   return (user_access('translate interface') || user_access('translate blocks')) && $block && isset($block->i18n_mode) && ($block->i18n_mode == I18N_MODE_LOCALIZE); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -226,7 +237,7 @@ function i18n_block_form_block_admin_configure_alter(&$form, &$form_state, $form | ||||
|     '#options' => i18n_language_list(), | ||||
|     '#description' => t('If no language is selected, block will show regardless of language.'), | ||||
|   ); | ||||
|   if (user_access('translate interface')) { | ||||
|   if (user_access('translate interface') || user_access('translate blocks')) { | ||||
|     $form['actions']['translate'] = array( | ||||
|       '#type' => 'submit', | ||||
|       '#name'   => 'save_translate', | ||||
|   | ||||
| @@ -72,15 +72,16 @@ class i18nBlocksTestCase extends Drupali18nTestCase { | ||||
|  | ||||
|     $this->clickLink(t('translate')); | ||||
|  | ||||
|     // Title is a textarea, body is a text_format. | ||||
|     $this->assertFieldByName('strings[blocks:block:' . $box2['delta'] . ':title]', $translations['title']['es']); | ||||
|     $this->assertFieldByName('strings[blocks:block:' . $box2['delta'] . ':body]', $translations['body']['es']); | ||||
|     $this->assertFieldByName('strings[blocks:block:' . $box2['delta'] . ':body][value]', $translations['body']['es']); | ||||
|  | ||||
|     // Update the translation. | ||||
|     $translations['title']['es'] = $this->randomName(10); | ||||
|     $translations['body']['es'] = $this->randomName(20); | ||||
|     $edit = array( | ||||
|       'strings[blocks:block:' . $box2['delta'] . ':title]' => $translations['title']['es'], | ||||
|       'strings[blocks:block:' . $box2['delta'] . ':body]' => $translations['body']['es'], | ||||
|       'strings[blocks:block:' . $box2['delta'] . ':body][value]' => $translations['body']['es'], | ||||
|     ); | ||||
|     $this->drupalPost(NULL, $edit, t('Save translation')); | ||||
|     $this->i18nAssertTranslations($translations['title'], '', 'Updated block title translation displayed.'); | ||||
|   | ||||
| @@ -0,0 +1,76 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Contact translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, helps with the multilingual | ||||
| configuration of the site contact forms. This module makes contact categories | ||||
| and replies available for translation. | ||||
|  | ||||
| * For a full description of the module, visit | ||||
|   https://www.drupal.org/node/1396984. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes, | ||||
|   visit https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| 1. Enable the Contact translation module included with the Internationalization | ||||
|    module. | ||||
| 2. Go to Administration > Structure > Contact form. | ||||
| 3. Select edit for the form to configure. | ||||
| 4. Select the Translate tab. | ||||
| 5. Select the translate link for a language. | ||||
| 6. Translate the Category and Auto-reply text. | ||||
| 7. Select Save translation. | ||||
| 8. Repeat steps 5 to 7 for each language. | ||||
| 9. Repeat steps 2 to 8 for all forms. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -5,9 +5,8 @@ dependencies[] = i18n_string | ||||
| package = Multilingual - Internationalization | ||||
| core = 7.x | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -0,0 +1,78 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Field translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, allows for translation of text | ||||
| associated with a field's settings including the label, help text, default | ||||
| value, and list options. | ||||
|  | ||||
| * For a full description of the module, visit this page | ||||
|   https://www.drupal.org/node/1279346. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| 1. Enable the Field translation module included with Internationalization. | ||||
| 2. Go to Administration > Configuration > Regional and language > Translate | ||||
|    interface. | ||||
| 3. Select the Filter Translatable Strings field set and limit search to fields. | ||||
| 4. Edit the desired field and Save. | ||||
|  | ||||
| For the translation to be displayed, the user needs to use some of the Field | ||||
| Formatters provided by this module whose name usually ends up in 'translated'. | ||||
| For most core fields it is Default translated. | ||||
|  | ||||
| Note: The Field Translation module does not provide content translation for | ||||
| fields. This functionality is provided by the Entity Translation (ET) module. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -72,7 +72,7 @@ function i18n_field_i18n_string_info() { | ||||
|     'description' => t('Configurable fields descriptions, defaults, options, etc.'), | ||||
|     'format' => FALSE, // This group doesn't have formatted strings | ||||
|     'list' => TRUE, // This group can list all strings | ||||
|     'class' => 'i18n_string_textgroup_cached', | ||||
|     'class' => variable_get('i18n_string_textgroup_class_field', 'i18n_string_textgroup_cached'), | ||||
|   ); | ||||
|   return $groups; | ||||
| } | ||||
|   | ||||
| @@ -6,9 +6,8 @@ package = Multilingual - Internationalization | ||||
| core = 7.x | ||||
| files[] = i18n_field.inc | ||||
| files[] = i18n_field.test | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -194,6 +194,9 @@ function i18n_field_field_widget_form_alter(&$element, &$form_state, $context) { | ||||
|     // Single-value file fields and image fields. | ||||
|     $alter_element = &$element[0]; | ||||
|   } | ||||
|   elseif ($field['type'] == 'url' && $field['module'] == 'url' && $field['cardinality'] == 1) { | ||||
|     $alter_element = &$element; | ||||
|   } | ||||
|   elseif (isset($element['value'])) { | ||||
|     // Number fields. Single-value text fields. | ||||
|     $alter_element = &$element['value']; | ||||
| @@ -202,6 +205,10 @@ function i18n_field_field_widget_form_alter(&$element, &$form_state, $context) { | ||||
|     // Entityreference fields using the entityreference_autocomplete widget. | ||||
|     $alter_element = &$element['target_id']; | ||||
|   } | ||||
|   elseif ($field['type'] == 'node_reference' && isset($element['nid'])) { | ||||
|     // The node_reference fields using the entityreference_autocomplete widget. | ||||
|     $alter_element = &$element['nid']; | ||||
|   } | ||||
|   else { | ||||
|     // All other fields. | ||||
|     $alter_element = &$element; | ||||
| @@ -446,3 +453,120 @@ function i18n_field_type_info($type = NULL, $property = NULL) { | ||||
|     return $info; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_field_info_alter(). | ||||
|  */ | ||||
| function i18n_field_field_info_alter(&$field_info) { | ||||
|   foreach(array_keys($field_info) as $type) { | ||||
|     $field_info[$type]['property_callbacks'][] = 'i18n_field_entity_property_callback'; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Prime the cache to avoid single db queries for entity fields / properties. | ||||
|  * | ||||
|  * This is mainly uses when large operations are occuring like a flush of the | ||||
|  * entity_property_infos(). | ||||
|  */ | ||||
| function i18n_field_prime_caches() { | ||||
|   global $language; | ||||
|   static $cache_primed; | ||||
|  | ||||
|   // Fill the cache. This should avoid single db queries when filling the | ||||
|   // properties. | ||||
|   if (empty($cache_primed)) { | ||||
|     $cache_primed = TRUE; | ||||
|     $text_group = i18n_string_textgroup('field'); | ||||
|     // Load all strings at once to avoid callbacks for each individual string. | ||||
|     $text_group->load_strings(); | ||||
|     $text_group->multiple_translation_search(array('type' => '*', 'objectid' => '*', 'property' => '*'), $language->language); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Callback to translate entity property info for a fields. | ||||
|  * | ||||
|  * @see entity_metadata_field_entity_property_info() | ||||
|  * @see entity_metadata_field_default_property_callback() | ||||
|  * @see i18n_field_i18n_object_info_alter() | ||||
|  * @see hook_module_implements_alter() | ||||
|  */ | ||||
| function i18n_field_entity_property_callback(&$info, $entity_type, $field, $instance, $field_type) { | ||||
|   global $language; | ||||
|  | ||||
|   // This could create a endless recursion if it's called during rebuilding the | ||||
|   // cache for i18n_object_info(). So if the cache of i18n_object_info isn't | ||||
|   // available yet we assume the worst case, leave the info alone but trigger a | ||||
|   // rebuild of the property when hook_i18n_object_info_alter is invoked. At | ||||
|   // that point the info is available and we can rely on it. | ||||
|   if (!$info = &drupal_static('i18n_object_info')) { | ||||
|     $i18n_field_entity_property_callback_fallback = &drupal_static(__FUNCTION__); | ||||
|     $i18n_field_entity_property_callback_fallback = TRUE; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   i18n_field_prime_caches(); | ||||
|   $name = $field['field_name']; | ||||
|   $property = &$info[$entity_type]['bundles'][$instance['bundle']]['properties'][$name]; | ||||
|   $property['label'] = i18n_field_translate_property($instance, 'label', $language->language); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_i18n_object_info_alter(). | ||||
|  */ | ||||
| function i18n_field_i18n_object_info_alter(&$info) { | ||||
|   if (drupal_static('i18n_field_entity_property_callback')) { | ||||
|     if ($info = drupal_static('i18n_object_info')) { | ||||
|       // Clean static and permanent cache of the data and then re-run the property | ||||
|       // building. | ||||
|       // Use a lock to avoid stampeding. | ||||
|       $lock_name = 'i18n_field_entity_property_callback_fallback:' . $GLOBALS['language']->language; | ||||
|       // See if another request is already doing this. If so we bail out here as | ||||
|       // we won't help with anything at the moment. | ||||
|       if (!lock_may_be_available($lock_name)) { | ||||
|         return; | ||||
|       } | ||||
|       if (lock_acquire($lock_name)) { | ||||
|         i18n_field_prime_caches(); | ||||
|         // Inject translated properties. | ||||
|         $entity_property_info = entity_get_property_info(); | ||||
|         foreach ($entity_property_info as $entity_type => $properties) { | ||||
|           if (isset($properties['bundles'])) { | ||||
|             foreach ($properties['bundles'] as $bundle => $bundle_properties) { | ||||
|               if ($bundle_properties['properties']) { | ||||
|                 foreach ($bundle_properties['properties'] as $bundle_property => $bundle_property_info) { | ||||
|                   if ($instance = field_info_instance($entity_type, $bundle_property, $bundle)) { | ||||
|                     $property = &$entity_property_info[$entity_type]['bundles'][$instance['bundle']]['properties'][$bundle_property]; | ||||
|                     $property['label'] = i18n_field_translate_property($instance, 'label', $GLOBALS['language']->language); | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         // Inject into static cache. | ||||
|         $entity_get_property_info = &drupal_static('entity_get_property_info', array()); | ||||
|         $entity_get_property_info = $entity_property_info; | ||||
|         // Write permanent cache. | ||||
|         cache_set('entity_property_info:' . $GLOBALS['language']->language, $entity_property_info); | ||||
|         lock_release($lock_name); | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       watchdog('i18n_field', 'Unable to run fall-back handling for entity property translation due missing "i18n_object_info" cache', array(), WATCHDOG_WARNING); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_module_implements_alter(). | ||||
|  */ | ||||
| function i18n_field_module_implements_alter(&$implementations, $hook) { | ||||
|   if ($hook == 'i18n_object_info_alter') { | ||||
|     // Move our hook implementation to the bottom. | ||||
|     $group = $implementations['i18n_field']; | ||||
|     unset($implementations['i18n_field']); | ||||
|     $implementations['i18n_field'] = $group; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,86 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Multilingual forum module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, helps with the multilingual | ||||
| configuration of the site’s forums. | ||||
|  | ||||
| * For a full description of the module visit | ||||
|   https://www.drupal.org/node/1396988. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| To configure forum vocabulary | ||||
|  | ||||
| 1. Enable the Multilingual forum module included with Internationalization. | ||||
| 2. Go to Administration > Structure > Taxonomy. | ||||
| 3. Select the "edit vocabulary" for the Forums vocabulary. | ||||
| 4. Choose the translation mode (Localize or Translate). | ||||
| 5. Select the "Save and translate" button. | ||||
| 6. Select the "translate" link for a language. | ||||
| 7. Translate the "Name" and "Description" for the forum. | ||||
| 8. Select the "Save translation" button. | ||||
| 9. Repeat steps 6 to 8 for each language. | ||||
|  | ||||
| To configure forum terms | ||||
|  | ||||
| 1. Go to Administration > Structure > Forums. | ||||
| 2. Select the "edit" link for a forum or container. | ||||
| 3. Select the "Translate" tab. | ||||
| 4. Select the "translate" link for a language. | ||||
| 5. Translate the "Name" and "Description" for the term. | ||||
| 6. Select the "Save translation" button. | ||||
| 7. Repeat steps 4 to 6 for each language. | ||||
| 8. Repeat all steps for all terms. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -7,9 +7,8 @@ package = Multilingual - Internationalization | ||||
| core = 7.x | ||||
| files[] = i18n_forum.test | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
							
								
								
									
										111
									
								
								sites/all/modules/contrib/localisation/i18n/i18n_menu/README.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								sites/all/modules/contrib/localisation/i18n/i18n_menu/README.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Troubleshooting | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Menu translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, allows users to select a | ||||
| translation mode for each menu. | ||||
|  | ||||
| * For a full description of the module, visit this page: | ||||
|   https://www.drupal.org/node/1113982. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes: | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
| To link menu item menus to nodes, it is useful to have the following modules: | ||||
|  | ||||
| * Entity translation i18n menu module, a submodule of Entity translation - | ||||
|   https://www.drupal.org/project/entity_translation | ||||
| * Menu translation node module - https://www.drupal.org/project/i18n_menu_node | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| Language-specific menus | ||||
| 1. To create or edit a menu, navigate to Structure > Menus > (menu to edit) > | ||||
|    Edit. | ||||
| 2. In the Translation mode section, choose Fixed Language and a Language field | ||||
|    will appear. | ||||
| 3. Select a language, select Save, and add or update the menu items as needed. | ||||
| The menu block will only appear when viewing content in the same language. | ||||
|  | ||||
| There are three modes available: Translate and Localize, Fixed Language, and No | ||||
| Multilingual Options. | ||||
|  | ||||
| Translate and Localize: | ||||
| The user can create one menu for all languages, and translate or localize each | ||||
| menu item. There are two ways that menu items will be translated. | ||||
| 1. The user can set a language when creating a custom menu item so that the menu | ||||
|    item will only show up for that language. Menu items that link to nodes in a | ||||
|    particular language will be treated this way. | ||||
| 2. The user can localize other custom menu items without a language | ||||
|    (for example, menu items linking to Views pages). Use the Translate tab to | ||||
|    translate the menu item title and description. Translators can also use the | ||||
|    "Translate interface" pages to translate these menu items. | ||||
|  | ||||
| Fixed Language: | ||||
| If the user chooses Fixed Language, they'll have to set up a separate menu in | ||||
| each language. This could become tedious if have a lot of languages enabled on | ||||
| the site, but is useful if the content or menu structure is different for each | ||||
| language. | ||||
|  | ||||
| No Multilingual Options: | ||||
| Only the menu will be translatable. | ||||
|  | ||||
| TROUBLESHOOTING | ||||
| --------------- | ||||
|  | ||||
| A menu item linked to a node will be displayed only when the node language | ||||
| matches the page language. This is due to how the menu system works and the | ||||
| "Language selection" feature in i18n. Therefore, to get translated menus items | ||||
| that link to nodes, you first need translated content. For more information | ||||
| visit https://www.drupal.org/docs/7/multilingual/translating-content. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -10,9 +10,8 @@ core = 7.x | ||||
| files[] = i18n_menu.inc | ||||
| files[] = i18n_menu.test | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -53,6 +53,24 @@ function i18n_menu_menu_alter(&$items) { | ||||
|   $items['admin/structure/menu/item/%menu_link'] = $items['admin/structure/menu/item/%menu_link/edit']; | ||||
|   $items['admin/structure/menu/item/%menu_link']['type'] = MENU_CALLBACK; | ||||
|   $items['admin/structure/menu/item/%menu_link/edit']['type'] = MENU_DEFAULT_LOCAL_TASK; | ||||
|   $items['admin/structure/menu/manage/%menu']['title callback'] = 'i18n_menu_menu_overview_title'; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Preprocess theme_menu_admin_overview to translate menu name and description | ||||
|  * | ||||
|  * @param $variables | ||||
|  */ | ||||
| function i18n_menu_preprocess_menu_admin_overview(&$variables) { | ||||
|   $variables['title'] = i18n_string(array('menu', 'menu', $variables['name'], 'title'), $variables['title'], array('sanitize' => FALSE)); | ||||
|   $variables['description'] = i18n_string(array('menu', 'menu', $variables['name'], 'description'), $variables['description'], array('sanitize' => FALSE)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Title callback for the menu overview page and links. | ||||
|  */ | ||||
| function i18n_menu_menu_overview_title($menu) { | ||||
|   return i18n_string(array('menu', 'menu', $menu['menu_name'], 'title'), $menu['title']); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -379,7 +397,7 @@ function i18n_menu_localize_tree($tree, $langcode = NULL) { | ||||
|     if (_i18n_menu_link_process($item['link'])) { | ||||
|       if (!_i18n_menu_link_is_visible($item['link'], $langcode)) { | ||||
|         // Remove links for other languages than current. | ||||
|         // Links with language wont be localized. | ||||
|         // Links with language won't be localized. | ||||
|         unset($tree[$index]); | ||||
|         // @todo Research whether the above has any advantage over: | ||||
|         // $item['hidden'] = TRUE; | ||||
| @@ -504,7 +522,7 @@ function _i18n_menu_link_localize(&$link, $langcode = NULL) { | ||||
| function _i18n_menu_link_description($link, $langcode = NULL) { | ||||
|   if (!empty($link['options']['attributes']['title'])) { | ||||
|     $key = i18n_object_info('menu_link', 'key'); | ||||
|     return i18n_string_translate(array('menu', 'item', $link[$key], 'description'), $link['options']['attributes']['title'], array('langcode' => $langcode)); | ||||
|     return i18n_string_translate(array('menu', 'item', $link[$key], 'description'), $link['options']['attributes']['title'], array('langcode' => $langcode, 'sanitize' => FALSE)); | ||||
|   } | ||||
|   else { | ||||
|     return NULL; | ||||
| @@ -515,9 +533,11 @@ function _i18n_menu_link_description($link, $langcode = NULL) { | ||||
|  * Check whether this link is to be processed by i18n_menu and start processing. | ||||
|  */ | ||||
| function _i18n_menu_link_process(&$link) { | ||||
|   // Only visible links that have a language property and haven't been processed | ||||
|   // before. We also check that they belong to a menu with language options. | ||||
|   if (empty($link['i18n_menu']) && !empty($link['language']) && !empty($link['access']) && empty($link['hidden']) && i18n_menu_mode($link['menu_name'])) { | ||||
|   // Only links that have a language property and haven't been processed before. | ||||
|   // We also translate links marked as hidden because core breadcrumbs ignore | ||||
|   // that flag and excluding them would basically interfere with core behaviour. | ||||
|   // We also check that they belong to a menu with language options. | ||||
|   if (empty($link['i18n_menu']) && !empty($link['language']) && !empty($link['access']) && i18n_menu_mode($link['menu_name'])) { | ||||
|     // Mark so it won't be processed twice. | ||||
|     $link['i18n_menu'] = TRUE; | ||||
|     // Skip if administering this menu or this menu item. | ||||
| @@ -579,7 +599,7 @@ function _i18n_menu_link_is_visible($link, $langcode = NULL) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get localizable properties for menu link checking agains the router item. | ||||
|  * Get localizable properties for menu link checking against the router item. | ||||
|  */ | ||||
| function _i18n_menu_link_localizable_properties($link) { | ||||
|   $props = array(); | ||||
| @@ -723,15 +743,19 @@ function i18n_menu_form_menu_edit_item_alter(&$form, &$form_state) { | ||||
|  * Add a "translate" link in operations column for each menu item. | ||||
|  */ | ||||
| function i18n_menu_form_menu_overview_form_alter(&$form, &$form_state) { | ||||
|   foreach (element_children($form) as $element) { | ||||
|     if (substr($element, 0, 5) == 'mlid:') { | ||||
|       $mlid = $form[$element]['#item']['mlid']; | ||||
|       if (i18n_get_object('menu', $mlid)->get_translate_access()) { | ||||
|         $form[$element]['operations']['translate'] = array( | ||||
|           '#type' => 'link', | ||||
|           '#title' => t('translate'), | ||||
|           '#href' => "admin/structure/menu/item/{$mlid}/translate", | ||||
|         ); | ||||
|   if (i18n_menu_mode($form['#menu']['menu_name'], I18N_MODE_MULTIPLE)) { | ||||
|     foreach (element_children($form) as $element) { | ||||
|       if (substr($element, 0, 5) == 'mlid:') { | ||||
|         $item = $form[$element]["#item"]; | ||||
|         $mlid = $form[$element]['#item']['mlid']; | ||||
|         if (i18n_get_object('menu', $mlid)->get_translate_access()) { | ||||
|           $form[$element]['operations']['translate'] = array( | ||||
|             '#type' => 'link', | ||||
|             '#title' => t('translate'), | ||||
|             '#href' => "admin/structure/menu/item/{$mlid}/translate", | ||||
|           ); | ||||
|           $form[$element]['title']['#markup'] = l(_i18n_menu_link_title($item), $item['href'], $item['localized_options']); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -898,93 +922,25 @@ function i18n_menu_query_features_menu_link_alter($query) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_init(). | ||||
|  * Implements hook_query_TAG_alter() | ||||
|  * | ||||
|  * Using tag 'preferred_menu_links' added in menu_link_get_preferred(). | ||||
|  * See http://drupal.org/node/1854134 | ||||
|  */ | ||||
| function i18n_menu_init() { | ||||
| function i18n_menu_query_preferred_menu_links_alter(QueryAlterableInterface $query) { | ||||
|   global $language; | ||||
|   // Get queried tables. | ||||
|   $tables = $query->getTables(); | ||||
|  | ||||
|   // The only way to override the default preferred menu link for a path is to | ||||
|   // inject it into the static cache of the function menu_link_get_preferred(). | ||||
|  | ||||
|   // The problem with the default implementation is that it does not take the | ||||
|   // language of a menu link into account. Whe having different menu trees for | ||||
|   // different menus, this means that the active trail will not work for all but | ||||
|   // one language. | ||||
|  | ||||
|   // The code below is identical to the mentioned function except the added | ||||
|   // language condition on the query. | ||||
|  | ||||
|   // TODO: Adding an alter tag to the query would allow to do this with a simple | ||||
|   // hook_query_alter() implementation. | ||||
|  | ||||
|   $preferred_links = &drupal_static('menu_link_get_preferred'); | ||||
|  | ||||
|   $path = $_GET['q']; | ||||
|  | ||||
|   // Look for the correct menu link by building a list of candidate paths, | ||||
|   // which are ordered by priority (translated hrefs are preferred over | ||||
|   // untranslated paths). Afterwards, the most relevant path is picked from | ||||
|   // the menus, ordered by menu preference. | ||||
|   $item = menu_get_item($path); | ||||
|   $path_candidates = array(); | ||||
|   // 1. The current item href. | ||||
|   $path_candidates[$item['href']] = $item['href']; | ||||
|   // 2. The tab root href of the current item (if any). | ||||
|   if ($item['tab_parent'] && ($tab_root = menu_get_item($item['tab_root_href']))) { | ||||
|     $path_candidates[$tab_root['href']] = $tab_root['href']; | ||||
|   } | ||||
|   // 3. The current item path (with wildcards). | ||||
|   $path_candidates[$item['path']] = $item['path']; | ||||
|   // 4. The tab root path of the current item (if any). | ||||
|   if (!empty($tab_root)) { | ||||
|     $path_candidates[$tab_root['path']] = $tab_root['path']; | ||||
|   } | ||||
|   // Retrieve a list of menu names, ordered by preference. | ||||
|   $menu_names = menu_get_active_menu_names(); | ||||
|   // Use an illegal menu name as the key for the preferred menu link. | ||||
|   $selected_menu = MENU_PREFERRED_LINK; | ||||
|   // Put the selected menu at the front of the list. | ||||
|   array_unshift($menu_names, $selected_menu); | ||||
|  | ||||
|   $query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC)); | ||||
|   $query->leftJoin('menu_router', 'm', 'm.path = ml.router_path'); | ||||
|   $query->fields('ml'); | ||||
|   // Weight must be taken from {menu_links}, not {menu_router}. | ||||
|   $query->addField('ml', 'weight', 'link_weight'); | ||||
|   $query->fields('m'); | ||||
|   $query->condition('ml.link_path', $path_candidates, 'IN'); | ||||
|  | ||||
|   // Only look menu links with none or the current language. | ||||
|   $query->condition('ml.language', array(LANGUAGE_NONE, i18n_language_interface()->language), 'IN'); | ||||
|  | ||||
|   // Sort candidates by link path and menu name. | ||||
|   $candidates = array(); | ||||
|   foreach ($query->execute() as $candidate) { | ||||
|     $candidate['weight'] = $candidate['link_weight']; | ||||
|     $candidates[$candidate['link_path']][$candidate['menu_name']] = $candidate; | ||||
|     // Add any menus not already in the menu name search list. | ||||
|     if (!in_array($candidate['menu_name'], $menu_names)) { | ||||
|       $menu_names[] = $candidate['menu_name']; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Store the most specific link for each menu. Also save the most specific | ||||
|   // link of the most preferred menu in $preferred_link. | ||||
|   foreach ($path_candidates as $link_path) { | ||||
|     if (isset($candidates[$link_path])) { | ||||
|       foreach ($menu_names as $menu_name) { | ||||
|         if (empty($preferred_links[$path][$menu_name]) && isset($candidates[$link_path][$menu_name])) { | ||||
|           $candidate_item = $candidates[$link_path][$menu_name]; | ||||
|           $map = explode('/', $path); | ||||
|           _menu_translate($candidate_item, $map); | ||||
|           if ($candidate_item['access']) { | ||||
|             $preferred_links[$path][$menu_name] = $candidate_item; | ||||
|             if (empty($preferred_links[$path][MENU_PREFERRED_LINK])) { | ||||
|               // Store the most specific link. | ||||
|               $preferred_links[$path][MENU_PREFERRED_LINK] = $candidate_item; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|   foreach ($tables as $alias => $table) { | ||||
|     if ($table['table'] == 'menu_links') { | ||||
|       // Add language filter, ensuring that we don't have any collision when | ||||
|       // determining the active menu trail when there are multiple menu items | ||||
|       // with same link path but different languages. | ||||
|       if ($language) { | ||||
|         $query->condition('language', array($language->language, LANGUAGE_NONE), 'IN'); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,96 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Multilingual content module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, provides extended multilingual | ||||
| options for nodes. These options help accommodate a variety of translation | ||||
| workflows by controlling how the language for nodes is set. | ||||
|  | ||||
| Note that the Multilingual content module lives in the i18n_node directory | ||||
| in the Internationalization package. Don't confuse this module with the core | ||||
| Content translation module. | ||||
|  | ||||
| * For a full description of the module visit: | ||||
|   https://www.drupal.org/node/1279644. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| For each content type, the following Extended language options are available | ||||
| under the Multilingual Settings tab. | ||||
| 1. "Set current language as default for new content" can be useful for content | ||||
|    that is community-generated. | ||||
| 2. "Require language" prevents users from creating 'Language neutral' nodes. | ||||
| 3. "Lock language" prevents users from changing the language of a node after | ||||
|    it's created. | ||||
|  | ||||
| Site-wide Settings for Node Translation | ||||
| 1. There are also site-wide settings provided to help streamline how | ||||
|    multilingual content is created. Navigate to Config > Regional and language > | ||||
|    Multilingual settings > Node Options. | ||||
| 2. "Switch interface for translating" switches the language of the user | ||||
|    interface to the chosen language when a user translates a node. This is | ||||
|    useful if users speak the language in which the translation is written. It | ||||
|    means that after the node translation is saved, the language of the UI will | ||||
|    match the language of the node. | ||||
| 3. "Hide content translation links" will prevent the language switcher links | ||||
|    from appearing in nodes and teasers. This is useful if a language switcher | ||||
|    block is enabled on the site. | ||||
| 4. The user can also select the default language for new nodes if the | ||||
|    corresponding content type doesn't have language support. By default, it is | ||||
|    set to be in the default language of the site, but this can be changed to be | ||||
|    language neutral. This is a useful option when thinking about forward | ||||
|    compatibility for adding multilingual support to these content types in the | ||||
|    future. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -9,9 +9,8 @@ configure = admin/config/regional/i18n/node | ||||
| files[]=i18n_node.test | ||||
| files[]=i18n_node.variable.inc | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -222,8 +222,16 @@ function i18n_node_language_mode($type) { | ||||
| function i18n_node_node_prepare($node) { | ||||
|   $options = variable_get('i18n_node_options_' . $node->type, array()); | ||||
|   if (i18n_node_type_enabled($node) && empty($node->nid) && !i18n_object_langcode($node) && in_array('current', $options)) { | ||||
|     $default = variable_get('i18n_node_default_language_for_' . $node->type, '-- current --'); | ||||
|  | ||||
|     // Set current language for new nodes if option enabled | ||||
|     $node->language = i18n_language_content()->language; | ||||
|     if ($default === '-- current --') { | ||||
|       $node->language = i18n_language_content()->language; | ||||
|     } | ||||
|     // If a custom language was specified, apply it. | ||||
|     else { | ||||
|       $node->language = $default; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -249,13 +257,16 @@ function i18n_node_permission() { | ||||
| /** | ||||
|  * Implements hook_node_view() | ||||
|  */ | ||||
| function i18n_node_node_view($node) { | ||||
| function i18n_node_node_view($node, $view_mode, $langcode) { | ||||
|   if (i18n_node_type_enabled($node)) { | ||||
|     $node->content['language'] = array( | ||||
|       '#type' => 'item', | ||||
|       '#title' => t('Language'), | ||||
|       '#markup' => i18n_language_name($node->language), | ||||
|     ); | ||||
|     $extra_fields_display_settings = field_extra_fields_get_display('node', $node->type, $view_mode); | ||||
|     if ($extra_fields_display_settings['language']['visible']) { | ||||
|       $node->content['language'] = array( | ||||
|         '#type' => 'item', | ||||
|         '#title' => t('Language'), | ||||
|         '#markup' => i18n_language_name($node->language), | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -265,7 +276,9 @@ function i18n_node_node_view($node) { | ||||
|  * Handles links for extended languages. Sets current interface language. | ||||
|  */ | ||||
| function i18n_node_node_view_alter(&$build) { | ||||
|   $node = $build['#node']; | ||||
|   if (isset($build['#node'])) { | ||||
|     $node = $build['#node']; | ||||
|   } | ||||
|   // Hide node translation links. | ||||
|   if (variable_get('i18n_hide_translation_links', 0)) { | ||||
|     if (isset($build['links']['translation'])) { | ||||
| @@ -417,7 +430,16 @@ function i18n_node_form_node_type_form_alter(&$form, &$form_state) { | ||||
|     // Some settings about node languages. Add variables for node type from variable definition | ||||
|     if ($form['#node_type']->type) { | ||||
|       variable_type_include('node_type'); | ||||
|       $form['i18n'] += node_variable_type_subform($form['#node_type']->type, array('i18n_node_options', 'i18n_node_extended')); | ||||
|       $form['i18n'] += node_variable_type_subform($form['#node_type']->type, array('i18n_node_options', 'i18n_node_default_language_for', 'i18n_node_extended')); | ||||
|       // Only show custom default language field if "current" is checked. | ||||
|       $form['i18n']['i18n_node_default_language_for']['#states'] = array( | ||||
|         'visible' => array( | ||||
|           ':input[name="i18n_node_options[current]"]' => array('checked' => TRUE), | ||||
|         ), | ||||
|         'required' => array( | ||||
|           ':input[name="i18n_node_options[current]"]' => array('checked' => TRUE), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|     // Add disabled message | ||||
|     if ($disabled) { | ||||
| @@ -506,8 +528,6 @@ function _i18n_node_form_node_form_alter($form, &$form_state) { | ||||
|     } | ||||
|   } | ||||
|   elseif (variable_get('i18n_node_default_language_none', 0) && !isset($form['#node']->nid)) { | ||||
|     // Override locale module setting default language to nodes. It is already in form_state. | ||||
|     // $form['language']['#value'] = $form_state['values']['language'] = LANGUAGE_NONE; | ||||
|     // Only do this if the language is really disabled | ||||
|     if (variable_get('language_content_type_' . $node->type, 0) == 0) { | ||||
|       // Override locale module setting default language to nodes. It is already in form_state. | ||||
|   | ||||
| @@ -45,13 +45,30 @@ function i18n_node_variable_info($options = array()) { | ||||
|     'repeat' => array( | ||||
|       'type' => 'options', | ||||
|       'options' => array( | ||||
|         'current' => t('Set current language as default for new content.', array(), $options), | ||||
|         // Note: this was previously used only to mark new, translatable nodes | ||||
|         // with the current language of the user. Now, this setting is extended | ||||
|         // to allow a specific language to be chosen (defaulting to the current | ||||
|         // language). This was done for backwards compatibility reasons. | ||||
|         'current' => t('Set custom language as default for new content.', array(), $options), | ||||
|         'required' => t('Require language (Do not allow Language Neutral).', array(), $options), | ||||
|         'lock' => t('Lock language (Cannot be changed).', array(), $options), | ||||
|       ), | ||||
|     ), | ||||
|     'group' => 'i18n', | ||||
|   ); | ||||
|   // This field will only be displayed if "current" is checked above. | ||||
|   $variables['i18n_node_default_language_for_[node_type]'] = array( | ||||
|     'type' => 'multiple', | ||||
|     'title' => t('Custom default language', array(), $options), | ||||
|     'repeat' => array( | ||||
|       'type' => 'select', | ||||
|       'options' => array_merge(array( | ||||
|         '-- current --' => t('Current language') | ||||
|       ), locale_language_list('name')), | ||||
|       'default' => '-- current --', | ||||
|     ), | ||||
|     'group' => 'i18n', | ||||
|   ); | ||||
|   $variables['i18n_node_extended_[node_type]'] = array( | ||||
|     'type' => 'multiple', | ||||
|     'title' => t('Extended language support'), | ||||
|   | ||||
| @@ -6,9 +6,8 @@ core = 7.x | ||||
|  | ||||
| files[] = i18n_path.inc | ||||
| files[] = i18n_path.test | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -0,0 +1,82 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|    | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Redirect translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, improves search engine | ||||
| optimization (SEO) for multilingual websites. | ||||
|  | ||||
| It redirects anonymous users (including web crawlers) to the translation of the | ||||
| page in the requested language, if it exists, using a 301 redirect code. | ||||
|  | ||||
| * For a full description of the module, visit this page: | ||||
|   https://www.drupal.org/node/1280468. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes: | ||||
|    https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
| The Translation redirect module requires the implementation of | ||||
| hook_i18n_translate_path by another module for the redirect page to be | ||||
| determined. Currently, the Multilingual content, Path translation, and Taxonomy | ||||
| translation modules implement this hook. | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| No configuration is necessary. | ||||
|  | ||||
| For node translation, enable the Multilingual content and the Translation | ||||
| redirect modules. For non-node pages, the redirection hook must be implemented | ||||
| by the relevant module. | ||||
| For example, for taxonomy pages, you should enable the Taxonomy translation | ||||
| module because the module provides the necessary hook code. If you are using the | ||||
| Path translation module to create translation sets for non-node pages, then it | ||||
| implements the hook code for determining the redirection page. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -4,9 +4,8 @@ dependencies[] = i18n | ||||
| package = Multilingual - Internationalization | ||||
| core = 7.x | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -0,0 +1,82 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Multilingual select module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, allows the user to define whether | ||||
| content is filtered by language on pages provided by Drupal core. | ||||
|  | ||||
| * For a full description of the module visit: | ||||
|   https://www.drupal.org/node/1279512. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
| * Variable - https://www.drupal.org/project/variable | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| The module allows the user to configure whether or not to filter pages by the | ||||
| current language. If the Taxonomy translation submodule is also enabled, an | ||||
| option will be available for how taxonomy term pages are filtered. It also | ||||
| allows the exclusion of the module’s language selection handling for some | ||||
| elements and certain paths. | ||||
|  | ||||
| 1. Enable the Multilingual select module included with Internationalization. | ||||
| 2. Navigate to Configuration > Regional and language > Multilingual settings > | ||||
|    Selection. | ||||
| 3. Select nodes and taxonomy can be filtered by language in the Content to | ||||
|    Filter by Language field set. | ||||
| 4. The "Content Selection Mode" allows content with specific tags to be skipped | ||||
|    by entering a list of tags. | ||||
| 5. The "Enable for Specific Pages" field set allows specific pages to be | ||||
|    included by path. | ||||
| 6. After making choices, Save configuration. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -6,9 +6,8 @@ core = 7.x | ||||
| configure = admin/config/regional/i18n/select | ||||
| files[] = i18n_select.test | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -82,11 +82,11 @@ function i18n_select_mode($type = NULL) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check current path to enable selection | ||||
|  * Check current path to enable selection. | ||||
|  * | ||||
|  * This works pretty much like block visibility | ||||
|  * This works pretty much like block visibility. | ||||
|  * | ||||
|  * @return boolean | ||||
|  * @return bool | ||||
|  *   TRUE if content selection should be enabled for this page. | ||||
|  */ | ||||
| function i18n_select_page() { | ||||
| @@ -100,8 +100,11 @@ function i18n_select_page() { | ||||
|       // with different case. Ex: /Page, /page, /PAGE. | ||||
|       $pages = drupal_strtolower($pages); | ||||
|       if ($visibility < I18N_SELECT_PAGE_PHP) { | ||||
|         // Convert the Drupal path to lowercase | ||||
|         $path = drupal_strtolower(drupal_get_path_alias($_GET['q'])); | ||||
|         // @see views_ajax() | ||||
|         // @see I18NSelectAdminViewsAjax::testViewsAjaxWithoutSkippingTags() | ||||
|         $path = isset($_REQUEST['view_path']) ? $_REQUEST['view_path'] : $_GET['q']; | ||||
|         // Convert the Drupal path to lowercase. | ||||
|         $path = drupal_strtolower(drupal_get_path_alias($path)); | ||||
|         // Compare the lowercase internal and lowercase path alias (if any). | ||||
|         $page_match = drupal_match_path($path, $pages); | ||||
|         if ($path != $_GET['q']) { | ||||
| @@ -109,8 +112,8 @@ function i18n_select_page() { | ||||
|         } | ||||
|         // When $visibility has a value of 0 (I18N_SELECT_PAGE_NOTLISTED), | ||||
|         // the block is displayed on all pages except those listed in $pages. | ||||
|         // When set to 1 (I18N_SELECT_PAGE_LISTED), it is displayed only on those | ||||
|         // pages listed in $pages. | ||||
|         // When set to 1 (I18N_SELECT_PAGE_LISTED), it is displayed only on | ||||
|         // those pages listed in $pages. | ||||
|         $mode = !($visibility xor $page_match); | ||||
|       } | ||||
|       elseif (module_exists('php')) { | ||||
| @@ -121,7 +124,7 @@ function i18n_select_page() { | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       // No pages defined, still respect the setting (unlike blocks) | ||||
|       // No pages defined, still respect the setting (unlike blocks). | ||||
|       $mode = $visibility == I18N_SELECT_PAGE_NOTLISTED; | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -84,3 +84,87 @@ class i18nSelectTestCase extends Drupali18nTestCase { | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Test case for AJAX queries on "views/ajax" when view on admin page. | ||||
|  */ | ||||
| class I18NSelectAdminViewsAjax extends Drupali18nTestCase { | ||||
|  | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static function getInfo() { | ||||
|     return array( | ||||
|       'name' => t('I18N select Admin Views (AJAX)'), | ||||
|       'group' => 'Internationalization', | ||||
|       'description' => t('Test AJAX requests to the "views/ajax" when view located on "admin/*" and list of skipping tags is empty.'), | ||||
|       // Skip this test when "admin_views" module does not exists. | ||||
|       'dependencies' => array('admin_views'), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function setUp() { | ||||
|     parent::setUp('translation', 'i18n_variable', 'i18n_select', 'admin_views'); | ||||
|     parent::setUpLanguages(array('access content overview')); | ||||
|     parent::setUpContentTranslation(); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Test AJAX of a view without skipping tags for selection. | ||||
|    * | ||||
|    * @see i18n_select_page() | ||||
|    */ | ||||
|   public function testViewsAjaxWithoutSkippingTags() { | ||||
|     // If this variable will have the "views" value then this test will not | ||||
|     // have sense. For instance, we want apply language selection filter | ||||
|     // for views and remove "views" from "i18n_select_skip_tags" variable. | ||||
|     // In this case all AJAX for views, on administration part of the site, | ||||
|     // will be broken because the "i18n_select_page()" function will work | ||||
|     // with "views/ajax" path instead of, for example, "admin/content". | ||||
|     variable_set('i18n_select_skip_tags', ''); | ||||
|  | ||||
|     // Create one hundred of nodes. | ||||
|     for ($i = 1; $i <= 100; $i++) { | ||||
|       // Create every second node on Spanish language and | ||||
|       // every first - on English. | ||||
|       $node = $this->createNode('page', "Node $i", '', $i % 2 ? $this->default_language : $this->secondary_language); | ||||
|  | ||||
|       // Update "changed" in order to sort the content by updating date. In | ||||
|       // other case all nodes will be with the same date and not arranged in | ||||
|       // order. | ||||
|       db_update('node') | ||||
|         ->fields(array('changed' => strtotime("+ $i minute"))) | ||||
|         ->condition('nid', $node->nid) | ||||
|         ->execute(); | ||||
|     } | ||||
|  | ||||
|     $this->drupalGet('admin/content'); | ||||
|  | ||||
|     // Check that latest node exists at the top. | ||||
|     $this->assertText('Node 100'); | ||||
|     // Check that our page contains fifty nodes (the latest must be 51). | ||||
|     $this->assertNoText('Node 50'); | ||||
|  | ||||
|     // Test $_REQUEST['view_path']. There's no form to submit to, so | ||||
|     // drupalPost() won't work here. This just tests a direct $_POST | ||||
|     // request instead. | ||||
|     $this->curlExec(array( | ||||
|       CURLOPT_URL => $this->getAbsoluteUrl('views/ajax'), | ||||
|       CURLOPT_POST => TRUE, | ||||
|       CURLOPT_POSTFIELDS => http_build_query(array( | ||||
|         'page' => 1, | ||||
|         'view_path' => 'admin/content', | ||||
|         'view_name' => 'admin_views_node', | ||||
|         'view_display_id' => 'system_1', | ||||
|       )), | ||||
|     )); | ||||
|  | ||||
|     // Check that we are successfully switched to a new page of content. | ||||
|     $this->assertText('Node 50'); | ||||
|     $this->assertNoText('Node 100'); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,94 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|    | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The String translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, provides support for other | ||||
| modules to translate user-defined strings. This is an API module that must be | ||||
| enabled only when required by other modules in the i18n package. | ||||
|  | ||||
|  | ||||
| * For a full description of the module, visit this page: | ||||
|   https://www.drupal.org/node/1279668 | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes: | ||||
|   https://www.drupal.org/project/issues/i18n | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| Strings will be translated from the source languages. By default the source | ||||
| language is the site's default language, so changing the default language could | ||||
| break these translations. | ||||
|  | ||||
| 1. The user can set which language is used as the source language via | ||||
|    Administration > Configuration > Regional and language > Multilingual | ||||
|    settings > Strings. By default, only plain strings are enabled, so regular | ||||
|    blocks are not fully translatable. | ||||
| 2. To allow Filtered HTML, Full HTML or Plain text select the appropriate radio | ||||
|    box(es) and Save configuration. | ||||
| 3. To select the strings to be translated navigate to Administration > | ||||
|    Configuration > Regional and language > Translate interface and select on | ||||
|    Stings vertical tab. From here the user can select which text groups to | ||||
|    translate and select the Refresh strings tab. | ||||
|  | ||||
|  | ||||
| FAQ | ||||
| --- | ||||
|  | ||||
| The String translation module allows you to configure which text formats are | ||||
| translatable. Formats like PHP Filter and Full HTML are translated before they | ||||
| are processed, so allowing a translator to edit these can be a security risk. | ||||
| This is particularly problematic when importing translations in bulk from a CSV | ||||
| file, since the translator's access to the import formats isn't verified by | ||||
| Drupal. After updating this setting, be sure to refresh the strings via | ||||
| Administration > Configuration > Regional and language > Translate interface > | ||||
| Strings so that strings in forbidden formats are deleted. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -703,9 +703,19 @@ class i18n_string_textgroup_default { | ||||
|       // Create source string so we get an lid | ||||
|       $this->save_source($string); | ||||
|     } | ||||
|  | ||||
|     // Convert objectid to objectkey if it's numeric. | ||||
|     if (!isset($string->objectkey)) { | ||||
|       $string->objectkey = (int)$string->objectid; | ||||
|       if (is_numeric($string->objectid)) { | ||||
|         $string->objectkey = (int)$string->objectid; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Make sure objectkey is numeric. | ||||
|     if (!is_numeric($string->objectkey)) { | ||||
|       $string->objectkey = 0; | ||||
|     } | ||||
|  | ||||
|     if (!isset($string->format)) { | ||||
|       $string->format = ''; | ||||
|     } | ||||
| @@ -1166,10 +1176,17 @@ class i18n_string_object_wrapper extends i18n_object_wrapper { | ||||
|       $info = is_array($info) ? $info : array('title' => $info); | ||||
|       $field_name = isset($info['field']) ? $info['field'] : $field; | ||||
|       $value = $this->get_field($field_name); | ||||
|       if (is_array($value) && isset($value['value'])) { | ||||
|         $format = isset($value['format']) ? $value['format'] : NULL; | ||||
|         $value = $value['value']; | ||||
|       } | ||||
|       else { | ||||
|         $format = isset($info['format']) ? $this->get_field($info['format']) : NULL; | ||||
|       } | ||||
|       $strings[$this->get_textgroup()][$string_type][$object_id][$field] = array( | ||||
|         'string' => is_array($value) || isset($info['empty']) && $value === $info['empty'] ? NULL : $value, | ||||
|         'title' => $info['title'], | ||||
|         'format' => isset($info['format']) ? $this->get_field($info['format']) : NULL, | ||||
|         'format' => $format, | ||||
|         'name' => array_merge($object_keys, array($field)), | ||||
|       ); | ||||
|     } | ||||
| @@ -1481,7 +1498,12 @@ class i18n_string_textgroup_cached extends i18n_string_textgroup_default { | ||||
|       foreach ($context as $key => $value) { | ||||
|         if ($value != '*') { | ||||
|           $try = array_merge($context, array($key => '*')); | ||||
|           return $this->multiple_cache_get($try); | ||||
|           $cached_results = $this->multiple_cache_get($try); | ||||
|           // Now filter the ones that actually match. | ||||
|           if (!empty($cached_results)) { | ||||
|             $cached_results = $this->string_filter($cached_results, $context); | ||||
|           } | ||||
|           return $cached_results; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -10,9 +10,8 @@ files[] = i18n_string.inc | ||||
| files[] = i18n_string.test | ||||
| configure = admin/config/regional/i18n/strings | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -94,6 +94,7 @@ function i18n_string_schema() { | ||||
|       ), | ||||
|       'objectindex' => array( | ||||
|         'type' => 'int', | ||||
|         'size' => 'big', | ||||
|         'not null' => TRUE, | ||||
|         'default' => 0, | ||||
|         'description' => 'Integer value of Object ID.', | ||||
| @@ -245,6 +246,24 @@ function i18n_string_update_7002() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Removed due to buggy upgrade for #2200647. | ||||
|  */ | ||||
| function i18n_string_update_7003() { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Change objectindex from int to bigint. | ||||
|  */ | ||||
| function i18n_string_update_7004() { | ||||
|   db_change_field('i18n_string', 'objectindex', 'objectindex', array( | ||||
|     'type' => 'int', | ||||
|     'size' => 'big', | ||||
|     'not null' => TRUE, | ||||
|     'default' => 0, | ||||
|     'description' => 'Integer value of Object ID.', | ||||
|   )); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Notes for update script | ||||
|   | ||||
| @@ -118,13 +118,14 @@ function i18n_string_menu() { | ||||
|     'file' => 'i18n_string.admin.inc', | ||||
|     'access arguments' => array('translate interface'), | ||||
|   ); | ||||
|  | ||||
|   $items['admin/config/regional/i18n/strings'] = array( | ||||
|     'title' => 'Strings', | ||||
|     'description' => 'Options for user defined strings.', | ||||
|     'weight' => 20, | ||||
|     'type' => MENU_LOCAL_TASK, | ||||
|     'page callback' => 'drupal_get_form', | ||||
|     'page arguments' => array('variable_edit_form', array('i18n_string_allowed_formats', 'i18n_string_source_language')), | ||||
|     'page arguments' => array('variable_edit_form', array('i18n_string_allowed_formats', 'i18n_string_source_language', 'i18n_string_textgroup_class_[textgroup]')), | ||||
|     'access arguments' => array('administer site configuration'), | ||||
|   ); | ||||
|   // AJAX callback path for strings. | ||||
| @@ -258,6 +259,34 @@ function i18n_string_locale_translate_import_form_submit($form, &$form_state) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_element_info_alter(). | ||||
|  * | ||||
|  * We need to do this on the element info level as wysiwyg also does so and form | ||||
|  * API (incorrectly) does not merge in the defaults for values that are arrays. | ||||
|  */ | ||||
| function i18n_string_element_info_alter(&$types) { | ||||
|   $types['text_format']['#pre_render'][] = 'i18n_string_pre_render_text_format'; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The '#pre_render' function to alter the text format element in a translation. | ||||
|  * The text format for a translation is taken form the original, so the text | ||||
|  * format drop down should be disabled. | ||||
|  * | ||||
|  * @param array $element | ||||
|  *   The text_format element which will be rendered. | ||||
|  * | ||||
|  * @return array | ||||
|  *   The altered text_format element with a disabled "Text format" select. | ||||
|  */ | ||||
| function i18n_string_pre_render_text_format($element) { | ||||
|   if (!empty($element['#i18n_string_is_translation'])) { | ||||
|       $element['format']['format']['#attributes']['disabled'] = TRUE; | ||||
|   } | ||||
|   return $element; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if translation is required for this language code. | ||||
|  * | ||||
| @@ -334,7 +363,10 @@ function i18n_string_update_context($oldname, $newname) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get textgroup handler | ||||
|  * Get textgroup handler. | ||||
|  * | ||||
|  * @return i18n_string_textgroup_default | ||||
|  * | ||||
|  */ | ||||
| function i18n_string_textgroup($textgroup) { | ||||
|   $groups = &drupal_static(__FUNCTION__); | ||||
| @@ -488,6 +520,19 @@ function i18n_string_group_info($group = NULL, $property = NULL, $default = NULL | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_i18n_string_info_alter(). | ||||
|  * | ||||
|  * Set determined classes to use for the text group. | ||||
|  */ | ||||
| function i18n_string_i18n_string_info_alter(&$info) { | ||||
|   foreach (array_keys($info) as $name) { | ||||
|     // If class is not defined. Classes from other modules, fixed classes and etc. | ||||
|     if (!isset($info[$name]['class'])) { | ||||
|       $info[$name]['class'] = variable_get('i18n_string_textgroup_class_' . $name, 'i18n_string_textgroup_default'); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Translate / update multiple strings | ||||
| @@ -519,11 +564,12 @@ function i18n_string_multiple($operation, $name, $strings, $options = array()) { | ||||
|  * | ||||
|  * This function is intended to return translations for plain strings that have NO text format | ||||
|  * | ||||
|  * @param $name | ||||
|  * @param array|string name | ||||
|  *   Array or string concatenated with ':' that contains textgroup and string context | ||||
|  * @param $string | ||||
|  *   String in default language or array of strings to be translated | ||||
|  * @param $options | ||||
|  * @param array|string $string | ||||
|  *   A string in the default language, a string wth format (array with keys | ||||
|  *   value and format),or an array of strings (without format) to be translated. | ||||
|  * @param array $options | ||||
|  *   An associative array of additional options, with the following keys: | ||||
|  *   - 'langcode' (defaults to the current language) The language code to translate to a language other than what is used to display the page. | ||||
|  *   - 'filter' Filtering callback to apply to the translated string only | ||||
| @@ -531,8 +577,13 @@ function i18n_string_multiple($operation, $name, $strings, $options = array()) { | ||||
|  *   - 'callback' Callback to apply to the result (both to translated or untranslated string | ||||
|  *   - 'sanitize' Whether to filter the translation applying the text format if any, default is TRUE | ||||
|  *   - 'sanitize default' Whether to filter the default value if no translation found, default is FALSE | ||||
|  * | ||||
|  * @return string | ||||
|  */ | ||||
| function i18n_string_translate($name, $string, $options = array()) { | ||||
|   if (is_array($string) && isset($string['value'])) { | ||||
|     $string = $string['value']; | ||||
|   } | ||||
|   if (is_array($string)) { | ||||
|     return i18n_string_translate_list($name, $string, $options); | ||||
|   } | ||||
| @@ -583,10 +634,17 @@ function i18n_string_translate_access($string_format, $account = NULL) { | ||||
|  *   Message if the user cannot translate that string. | ||||
|  */ | ||||
| function i18n_string_translate_check_string($i18nstring, $account = NULL) { | ||||
|   if (!user_access('translate interface', $account) || !user_access('translate user-defined strings', $account)) { | ||||
|   // Check block translation permissions. | ||||
|   if ($i18nstring->textgroup == 'blocks') { | ||||
|     if (!user_access('translate interface', $account) && !user_access('translate blocks', $account)) { | ||||
|       return t('This is a user-defined string within a block. You are not allowed to translate blocks.'); | ||||
|     } | ||||
|   } | ||||
|   elseif (!user_access('translate interface', $account) || !user_access('translate user-defined strings', $account)) { | ||||
|     return t('This is a user-defined string. You are not allowed to translate these strings.'); | ||||
|   } | ||||
|   elseif (!empty($i18nstring->format)) { | ||||
|  | ||||
|   if (!empty($i18nstring->format)) { | ||||
|     if (!i18n_string_allowed_format($i18nstring->format)) { | ||||
|       $format = filter_format_load($i18nstring->format); | ||||
|       return t('This string uses the %name text format. Strings with this format are not allowed for translation.', array('%name' => $format->name)); | ||||
|   | ||||
| @@ -170,14 +170,16 @@ function i18n_string_translate_page_form_base($form, $langcode, $redirect = NULL | ||||
|  | ||||
| /** | ||||
|  * Create field elements for strings | ||||
|  * | ||||
|  * @param i18n_string_object[] $strings | ||||
|  * @param string $langcode | ||||
|  * | ||||
|  * @return array | ||||
|  */ | ||||
| function i18n_string_translate_page_form_strings($strings, $langcode) { | ||||
|   $formats = filter_formats(); | ||||
|   global $user; | ||||
|   $form = array(); | ||||
|   foreach ($strings as $item) { | ||||
|     // We may have a source or not. Load it, our string may get the format from it. | ||||
|     $source = $item->get_source(); | ||||
|     $format_id = $source ? $source->format : $item->format; | ||||
|     $description = ''; | ||||
|     // Check permissions to translate this string, depends on format, etc.. | ||||
|     if ($message = $item->check_translate_access()) { | ||||
|       // We'll display a disabled element with the reason it cannot be translated. | ||||
| @@ -188,27 +190,31 @@ function i18n_string_translate_page_form_strings($strings, $langcode) { | ||||
|       $disabled = FALSE; | ||||
|       $description = ''; | ||||
|       // If we don't have a source and it can be translated, we create it. | ||||
|       if (!$source) { | ||||
|       if (!$item->get_source()) { | ||||
|         // Enable messages just as a reminder these strings are not being updated properly. | ||||
|         $status = $item->update(array('messages' => TRUE)); | ||||
|         if ($status === FALSE || $status === SAVED_DELETED) { | ||||
|           // We don't have a source string so nothing to translate here | ||||
|           $disabled = TRUE; | ||||
|         } | ||||
|         else { | ||||
|           $source = $item->get_source(); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     $default_value = $item->format_translation($langcode, array('langcode' => $langcode, 'sanitize' => FALSE, 'debug' => FALSE)); | ||||
|     $available_formats = array_keys(filter_formats($user)); | ||||
|     if (!in_array($item->format, $available_formats)) { | ||||
|       $item->format = NULL; | ||||
|     } | ||||
|     $form[$item->get_name()] = array( | ||||
|       '#title' => $item->get_title(), | ||||
|       '#type' => 'textarea', | ||||
|       '#type' => $item->format ? 'text_format' : 'textarea', | ||||
|       '#default_value' => $default_value, | ||||
|       '#format' => $item->format, | ||||
|       // This will trigger i18n_string_pre_render_text_format() to actually | ||||
|       // alter the element. | ||||
|       '#i18n_string_is_translation' => TRUE, | ||||
|       '#disabled' => $disabled, | ||||
|       '#description' => $description . _i18n_string_translate_format_help($format_id), | ||||
|       //'#i18n_string_format' => $source ? $source->format : 0, | ||||
|       '#description' => $description, | ||||
|       // If disabled, provide smaller textarea (that can be expanded anyway). | ||||
|       '#rows' => $disabled ? 1 : min(ceil(str_word_count($default_value) / 12), 10), | ||||
|       // Change the parent for disabled strings so we don't get empty values later | ||||
| @@ -226,6 +232,16 @@ function i18n_string_translate_page_form_submit($form, &$form_state) { | ||||
|   foreach ($form_state['values']['strings'] as $name => $value) { | ||||
|     $count++; | ||||
|     list($textgroup, $context) = i18n_string_context(explode(':', $name)); | ||||
|     if (is_array($value)) { | ||||
|       if (isset($value['value'])) { | ||||
|         $value = $value['value']; | ||||
|         $form_state['values']['strings'][$name] = $value; | ||||
|       } | ||||
|       else { | ||||
|         form_set_error("strings][$name", t('Unable to get the translated string value.')); | ||||
|         watchdog('locale', 'Unable to get the translated string value, string array is: %string', array('%string' => var_dump($value)), WATCHDOG_WARNING); | ||||
|       } | ||||
|     } | ||||
|     $result = i18n_string_textgroup($textgroup)->update_translation($context, $form_state['values']['langcode'], $value); | ||||
|     $success += ($result ? 1 : 0); | ||||
|   } | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class i18nStringTestCase extends Drupali18nTestCase { | ||||
|     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter')); | ||||
|     $this->clickLink(t('edit')); | ||||
|     // Just add a random translation. | ||||
|     $translation = $this->randomString(); | ||||
|     $translation = $this->randomName(); | ||||
|     $edit = array(); | ||||
|     foreach ($this->getOtherLanguages() as $language) { | ||||
|       $langcode = $language->language; | ||||
|   | ||||
| @@ -34,9 +34,32 @@ function i18n_string_variable_info($options = array()) { | ||||
|     'default' => 0, | ||||
|     'group' => 'debug', | ||||
|   ); | ||||
|   $variables['i18n_string_textgroup_class_[textgroup]'] = array( | ||||
|     'title' => t('Class to use for the text group'), | ||||
|     'description' => t('Determines which the class will be use for string translation in the text group.', array(), $options), | ||||
|     'repeat' => array( | ||||
|       'type' => 'select', | ||||
|       'default' => 'i18n_string_textgroup_default', | ||||
|       'options callback' => 'i18n_string_variable_textgroup_class_list', | ||||
|     ), | ||||
|     'submit callback' => 'i18n_string_variable_textgroup_class_submit_callback', | ||||
|     'group' => 'i18n', | ||||
|   ); | ||||
|   return $variables; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_variable_type_info(). | ||||
|  */ | ||||
| function i18n_string_variable_type_info() { | ||||
|   $type['textgroup'] = array( | ||||
|     'title' => t('Text group'), | ||||
|     'type' => 'select', | ||||
|     'options callback' => 'i18n_string_variable_textgroup_list', | ||||
|   ); | ||||
|   return $type; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Options callback, format list | ||||
|  */ | ||||
| @@ -54,4 +77,33 @@ function i18n_string_variable_format_list() { | ||||
|  */ | ||||
| function i18n_string_variable_format_default() { | ||||
|   return array(filter_fallback_format()); | ||||
| } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Options callback, text groups list. | ||||
|  */ | ||||
| function i18n_string_variable_textgroup_list() { | ||||
|   $groups = array(); | ||||
|   foreach (i18n_string_group_info() as $name => $info) { | ||||
|     $groups[$name] = $info['title']; | ||||
|   } | ||||
|   return $groups; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Options callback, text group classes list. | ||||
|  */ | ||||
| function i18n_string_variable_textgroup_class_list($variable, $options = array()) { | ||||
|   return array( | ||||
|     'i18n_string_textgroup_default' => t('Text group handler default.', array(), $options), | ||||
|     'i18n_string_textgroup_cached' => t('Text group handler which include persistent caching.', array(), $options), | ||||
|   ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Submit callback. Execute Reset the persistent caches after save the text group class variables. | ||||
|  */ | ||||
| function i18n_string_variable_textgroup_class_submit_callback($variable, $options, $form, $form_state) { | ||||
|   // Reset the persistent caches. | ||||
|   cache_clear_all('i18n:string:' , 'cache', TRUE); | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ README.txt | ||||
| ========== | ||||
| Drupal module: i18n_sync (Synchronization) | ||||
|  | ||||
| This module will handle content synchronization accross translations. | ||||
| This module will handle content synchronization across translations. | ||||
|  | ||||
| The available list of fields to synchronize will include standard node fields and cck fields. | ||||
| To have aditional fields, add the list in a variable in the settings.php file, like this: | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| name = Synchronize translations | ||||
| description = Synchronizes taxonomy and fields accross translations of the same content. | ||||
| description = Synchronizes taxonomy and fields across translations of the same content. | ||||
| dependencies[] = i18n | ||||
| dependencies[] = translation | ||||
| package = Multilingual - Internationalization | ||||
| @@ -10,9 +10,8 @@ files[] = i18n_sync.install | ||||
| files[] = i18n_sync.module.inc | ||||
| files[] = i18n_sync.node.inc | ||||
| files[] = i18n_sync.test | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -33,7 +33,7 @@ function i18n_sync($status = NULL) { | ||||
| function i18n_sync_help($path, $arg) { | ||||
|   switch ($path) { | ||||
|     case 'admin/help#i18n_sync' : | ||||
|       $output = '<p>' . t('This module synchronizes content taxonomy and fields accross translations:') . '</p>'; | ||||
|       $output = '<p>' . t('This module synchronizes content taxonomy and fields across translations:') . '</p>'; | ||||
|       $output .= '<p>' . t('First you need to select which fields should be synchronized. Then, after a node has been updated, all enabled vocabularies and fields will be synchronized as follows:') . '</p>'; | ||||
|       $output .= '<ul>'; | ||||
|       $output .= '<li>' . t('All the node fields selected for synchronization will be set to the same value for all translations.') . '</li>'; | ||||
| @@ -91,6 +91,7 @@ function i18n_sync_form_node_type_form_alter(&$form, &$form_state) { | ||||
|  | ||||
|     $form['i18n_sync']['i18n_sync_node_type'] = array( | ||||
|       '#tree' => TRUE, | ||||
|       '#weight' => 1, | ||||
|     ); | ||||
|  | ||||
|     // Each set provides title and options. We build a big checkboxes control for it to be | ||||
| @@ -121,6 +122,21 @@ function i18n_sync_form_node_type_form_alter(&$form, &$form_state) { | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Add option to restrict syncing only when editing the translation source. | ||||
|     $form['i18n_sync']['i18n_sync_source_description'] = array( | ||||
|       '#prefix' => '<div>', '#suffix' => '</div>', | ||||
|       '#markup' => t('Restrict synchronization to the translation source.'), | ||||
|       '#weight' => 2, | ||||
|     ); | ||||
|     $form['i18n_sync']['i18n_sync_source'] = array( | ||||
|       '#type' => 'checkbox', | ||||
|       '#title' => t('Synchronize translations only when saving the translation source'), | ||||
|       '#default_value' => variable_get('i18n_sync_source_' . $type, FALSE), | ||||
|       '#disabled' => $disabled, | ||||
|       '#weight' => 3, | ||||
|       '#description' => t('If not checked each node will trigger the synchronization, whether it\'s the source or not.'), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -167,9 +183,17 @@ function i18n_sync_node_insert($node) { | ||||
|  */ | ||||
| function i18n_sync_node_update($node) { | ||||
|   // Let's go with field synchronization. | ||||
|   if (i18n_sync_node_check($node) && !empty($node->tnid) && ($fields = i18n_sync_node_fields($node->type)) && ($translations = i18n_sync_node_get_translations($node, TRUE))) { | ||||
|     module_load_include('node.inc', 'i18n_sync'); | ||||
|     i18n_sync_node_translation($node, $translations, $fields, 'update'); | ||||
|   if (i18n_sync_node_check($node) && !empty($node->tnid) && (!variable_get('i18n_sync_source_' . $node->type, TRUE) || $node->tnid == $node->nid) && ($fields = i18n_sync_node_fields($node->type)) && ($translations = i18n_sync_node_get_translations($node, TRUE))) { | ||||
|     $do_sync = TRUE; | ||||
|     if (module_exists('entity_translation')) { | ||||
|       if (entity_translation_enabled_bundle('node', $node->type)) { | ||||
|         $do_sync = FALSE; | ||||
|       } | ||||
|     } | ||||
|     if ($do_sync) { | ||||
|       module_load_include('node.inc', 'i18n_sync'); | ||||
|       i18n_sync_node_translation($node, $translations, $fields, 'update'); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -98,7 +98,7 @@ function i18n_sync_node_translation_nodereference_field(&$node, &$translation, $ | ||||
|  * Example: | ||||
|  *   English A references English B and English C. | ||||
|  *   English A and B are translated to German A and B, but English C is not. | ||||
|  *   The syncronization from English A to German A would it German B and English C. | ||||
|  *   The synchronization from English A to German A would it German B and English C. | ||||
|  */ | ||||
| function i18n_sync_node_translation_reference_field(&$reference_node, $default_value, $langcode) { | ||||
|   if (isset($reference_node->tnid) && translation_supported_type($reference_node->type)) { | ||||
|   | ||||
| @@ -0,0 +1,103 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Taxonomy translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, provides multiple options to | ||||
| translate taxonomy vocabularies and terms. For each vocabulary, there are four | ||||
| types of behaviors to choose from: Language-independent terms, Language-specific | ||||
| terms, Localized terms, and Mixed-language vocabulary. | ||||
|  | ||||
| * For a full description of the module visit: | ||||
|   https://www.drupal.org/node/1114016 | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit: | ||||
|   https://www.drupal.org/project/issues/i18n | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| Language-independent terms - only vocabulary will be translatable. | ||||
| 1. Navigate to Structure > Taxonomy. | ||||
| 2. Select the "edit vocabulary" link. | ||||
| 3. Select the "No multilingual options for terms". | ||||
|  | ||||
| Language-specific terms - vocabulary is only used for content in that language. | ||||
| The terms will only be available if the term language matches the UI language. | ||||
| 1. Navigate to Structure > Taxonomy and select the "edit vocabulary link". | ||||
| 2. Choose "Fixed Language" and a Language drop-down field will be displayed. | ||||
| 3. Select the language. | ||||
| 4. Select "Fixed Language" and Save. | ||||
|  | ||||
| Localized terms - Terms are common for all languages, but their name and | ||||
| description may be localized. | ||||
| 1. Navigate to Structure > Taxonomy > vocabulary-to-edit > Edit. | ||||
| 2. Select "Localize" and select Save. | ||||
| 3. Edit a term and there will be a Translate tab. Select this tab. | ||||
| 4. Select Translate, translate the Name and Description, select | ||||
|    "Save translation", and repeat for all languages. | ||||
| 5. Repeat the process for all terms. | ||||
| 6. Navigate to Structure > Content types > term-to-edit > Manage display. | ||||
| 7. By default, the term reference is set to Link. Change this to "Link | ||||
|    (localized)" and Save. | ||||
| The vocabulary will be appropriate for the language. | ||||
|  | ||||
| Mixed-language vocabulary - Use for vocabularies with terms in multiple | ||||
| languages. | ||||
| 1. Navigate to Structure > Taxonomy > vocabulary-to-edit > Edit. | ||||
| 2. Select the Translate radio button and Save. | ||||
| 3. Edit a vocabulary term and there will be a new Language field. Choose a | ||||
|    language and then select Save and translate. | ||||
| 4. There are two options, the user can either select "Add translation link" or | ||||
|    the user can select an existing term in the Select translations form. | ||||
| 5. Create translations for the terms and add terms for specific languages only. | ||||
| Now if the user edits a node associated with this vocabulary, only the relevant | ||||
| terms will appear. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -11,9 +11,8 @@ files[] = i18n_taxonomy.pages.inc | ||||
| files[] = i18n_taxonomy.admin.inc | ||||
| files[] = i18n_taxonomy.test | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -213,7 +213,12 @@ function i18n_taxonomy_field_formatter_view($entity_type, $entity, $field, $inst | ||||
|           ); | ||||
|         } | ||||
|         else { | ||||
|           $term = $item['taxonomy_term']; | ||||
|           if (isset($item['taxonomy_term'])) { | ||||
|             $term = $item['taxonomy_term']; | ||||
|           } | ||||
|           else { | ||||
|             $term = taxonomy_term_load($item['tid']); | ||||
|           } | ||||
|           $uri = entity_uri('taxonomy_term', $term); | ||||
|           $element[$delta] = array( | ||||
|             '#type' => 'link', | ||||
| @@ -372,10 +377,19 @@ function i18n_taxonomy_field_prepare_translation($entity_type, $entity, $field, | ||||
|  *   The array of valid terms for this field, keyed by term id. | ||||
|  */ | ||||
| function i18n_taxonomy_allowed_values($field) { | ||||
|   global $language; | ||||
|   $options = array(); | ||||
|   foreach ($field['settings']['allowed_values'] as $tree) { | ||||
|     if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) { | ||||
|       if ($terms = taxonomy_get_tree($vocabulary->vid, $tree['parent'])) { | ||||
|       if (i18n_taxonomy_vocabulary_mode($vocabulary->vid) == I18N_MODE_TRANSLATE) { | ||||
|         $parent = i18n_taxonomy_translation_term_tid($tree['parent'], NULL, $tree['parent']); | ||||
|         $language = i18n_language_context(); | ||||
|         $terms = i18n_taxonomy_get_tree($vocabulary->vid, $language->language, $parent); | ||||
|       } | ||||
|       else { | ||||
|         $terms = taxonomy_get_tree($vocabulary->vid, $tree['parent']); | ||||
|       } | ||||
|       if ($terms) { | ||||
|         foreach ($terms as $term) { | ||||
|           $options[$term->tid] = str_repeat('-', $term->depth) . i18n_taxonomy_term_name($term); | ||||
|         } | ||||
| @@ -742,6 +756,28 @@ function i18n_taxonomy_form_taxonomy_form_term_alter(&$form, &$form_state) { | ||||
|   // Add language field or not depending on taxonomy mode. | ||||
|   switch (i18n_taxonomy_vocabulary_mode($vocabulary->vid)) { | ||||
|     case I18N_MODE_TRANSLATE: | ||||
|       // Set $form_state['storage'] default as empty array because we will add | ||||
|       // the translation and target from $_GET. So we still have it when the | ||||
|       // page partially reloads with ajax. | ||||
|       if(!isset($form_state['storage'])) { | ||||
|         $form_state['storage'] = array(); | ||||
|       } | ||||
|       // get translation from $_GET or $form_state['storage'] | ||||
|       $translation = null; | ||||
|       if(isset($_GET['translation'])) { | ||||
|         $translation = $_GET['translation']; | ||||
|         $form_state['storage']['translation'] = $translation; | ||||
|       } else if(isset($form_state['storage']) && isset($form_state['storage']['translation'])){ | ||||
|         $translation = $form_state['storage']['translation']; | ||||
|       } | ||||
|       // get target from $_GET or $form_state['storage'] | ||||
|       $target = null; | ||||
|       if(isset($_GET['target'])) { | ||||
|         $target = $_GET['target']; | ||||
|         $form_state['storage']['target'] = $target; | ||||
|       } else if(isset($form_state['storage']) && isset($form_state['storage']['target'])){ | ||||
|         $target = $form_state['storage']['target']; | ||||
|       } | ||||
|       $form['language'] = array( | ||||
|         '#description' => t('This term belongs to a multilingual vocabulary. You can set a language for it.'), | ||||
|       ) + i18n_element_language_select($term); | ||||
| @@ -749,7 +785,7 @@ function i18n_taxonomy_form_taxonomy_form_term_alter(&$form, &$form_state) { | ||||
|       // If the term to be added will be a translation of a source term, | ||||
|       // set the default value of the option list to the target language and | ||||
|       // create a form element for storing the translation set of the source term. | ||||
|       if (empty($term->tid) && isset($_GET['translation']) && isset($_GET['target']) && ($source_term = taxonomy_term_load($_GET['translation'])) && ($target_language = i18n_language_object($_GET['target']))) { | ||||
|       if (empty($term->tid) && isset($translation) && isset($target) && ($source_term = taxonomy_term_load($translation)) && ($target_language = i18n_language_object($target))) { | ||||
|         // Set context language to target language. | ||||
|         i18n_language_context($target_language); | ||||
|  | ||||
| @@ -991,7 +1027,7 @@ function i18n_taxonomy_translate_terms($taxonomy, $langcode, $fullterms = TRUE) | ||||
|       } | ||||
|       elseif ($term->language && $term->language != $langcode) { | ||||
|         $translation_set = i18n_translation_set_load($term->i18n_tsid); | ||||
|         $translations = $translation_set->get_translations(); | ||||
|         $translations = ($translation_set) ? $translation_set->get_translations() : NULL; | ||||
|  | ||||
|         if ($translations && !empty($translations[$langcode])) { | ||||
|           $newterm = $translations[$langcode]; | ||||
| @@ -1020,6 +1056,10 @@ function i18n_taxonomy_localize_terms($terms) { | ||||
|   if (!i18n_string_translate_langcode()) { | ||||
|     return $terms; | ||||
|   } | ||||
|   // $terms is not a valid array or term. | ||||
|   if (empty($terms)) { | ||||
|     return $terms; | ||||
|   } | ||||
|   $object_info = i18n_object_info('taxonomy_term'); | ||||
|   $list = is_array($terms) ? $terms : array($terms); | ||||
|   foreach ($list as $index => $term) { | ||||
| @@ -1087,7 +1127,7 @@ function i18n_taxonomy_get_tree($vid, $langcode, $parent = 0, $max_depth = NULL, | ||||
|     $query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid'); | ||||
|     $result = $query | ||||
|       ->addTag('translatable') | ||||
|       ->addTag('term_access') | ||||
|       ->addTag('taxonomy_term_access') | ||||
|       ->fields('t') | ||||
|       ->fields('h', array('parent')) | ||||
|       ->condition('t.vid', $vid) | ||||
| @@ -1216,6 +1256,11 @@ function i18n_taxonomy_field_uuid_presave($entity_type, $entity, $field, $instan | ||||
|  * Implements hook_entity_info_alter(). | ||||
|  */ | ||||
| function i18n_taxonomy_entity_info_alter(&$entity_info) { | ||||
|   if (isset($entity_info['taxonomy_vocabulary'])) { | ||||
|     // Add altered vocabulary schema fields. | ||||
|     $entity_info['taxonomy_vocabulary']['schema_fields_sql']['base table'][] = 'i18n_mode'; | ||||
|     $entity_info['taxonomy_vocabulary']['schema_fields_sql']['base table'][] = 'language'; | ||||
|   } | ||||
|   if (isset($entity_info['taxonomy_term'])) { | ||||
|     // Core doesn't provide a label callback for taxonomy terms. By setting one | ||||
|     // we can use it to return the correct localized term name. | ||||
| @@ -1261,3 +1306,22 @@ function i18n_taxonomy_modules_enabled($modules) { | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Implements hook_views_pre_render(). | ||||
|  */ | ||||
| function i18n_taxonomy_views_pre_render(&$view) { | ||||
|   if($view->base_table !== 'rules_scheduler') { | ||||
|     global $language; | ||||
|  | ||||
|     foreach ($view->result as $delta => $term){ | ||||
|       if (isset($term->tid)) { | ||||
|         i18n_string_translate_langcode($language->language); | ||||
|         $localized_term = i18n_taxonomy_localize_terms(taxonomy_term_load($term->tid)); | ||||
|         $term->tid = $localized_term->tid; | ||||
|         $term->taxonomy_term_data_name = $localized_term->name; | ||||
|         $term->taxonomy_term_data_description = $localized_term->description; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -100,7 +100,7 @@ function _i18n_taxonomy_autocomplete($langcode, $vids, $tags_typed = '') { | ||||
|     $query = db_select('taxonomy_term_data', 't') | ||||
|       ->fields('t', array('tid', 'name')); | ||||
|     $query->addTag('translatable'); | ||||
|     $query->addTag('term_access'); | ||||
|     $query->addTag('taxonomy_term_access'); | ||||
|     // Disable i18n_select for this query | ||||
|     $query->addTag('i18n_select'); | ||||
|     // Add language condition | ||||
|   | ||||
| @@ -15,6 +15,10 @@ function i18n_taxonomy_token_info() { | ||||
|     'name' => t("Name (localized)"), | ||||
|     'description' => t("The name of the taxonomy term."), | ||||
|   ); | ||||
|   $term['localized-name'] = array( | ||||
|     'name' => t("Name in current language"), | ||||
|     'description' => t("The name of the taxonomy term in current language."), | ||||
|   ); | ||||
|   $term['i18n-description'] = array( | ||||
|     'name' => t("Description (localized)"), | ||||
|     'description' => t("The optional description of the taxonomy term."), | ||||
| @@ -69,6 +73,12 @@ function i18n_taxonomy_tokens($type, $tokens, array $data = array(), array $opti | ||||
|           $replacements[$original] = $sanitize ? check_plain($name) : $name; | ||||
|           break; | ||||
|  | ||||
|         case 'localized-name': | ||||
|           $translated_term = i18n_taxonomy_term_get_translation($term, $langcode); | ||||
|           $name = i18n_taxonomy_term_name($translated_term, $langcode); | ||||
|           $replacements[$original] = $sanitize ? check_plain($name) : $name; | ||||
|           break; | ||||
|  | ||||
|         case 'i18n-description': | ||||
|           $replacements[$original] = i18n_string_text(array('taxonomy', 'term', $term->tid, 'description'), $term->description, array('langcode' => $langcode, 'format' => $term->format, 'sanitize' => $sanitize, 'cache' => TRUE)); | ||||
|           break; | ||||
|   | ||||
| @@ -6,9 +6,8 @@ core = 7.x | ||||
|  | ||||
| files[] = i18n_translation.inc | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -20,7 +20,7 @@ class I18nTranslationSetController extends DrupalDefaultEntityController { | ||||
|    * @param $queried_entities | ||||
|    *   Associative array of query results, keyed on the entity ID. | ||||
|    * @param $revision_id | ||||
|    *   ID of the revision that was loaded, or FALSE if teh most current revision | ||||
|    *   ID of the revision that was loaded, or FALSE if the most current revision | ||||
|    *   was loaded. | ||||
|    */ | ||||
|   protected function attachLoad(&$queried_entities, $revision_id = FALSE) { | ||||
|   | ||||
| @@ -0,0 +1,70 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The User mail translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, translates emails sent from the | ||||
| User module. | ||||
|  | ||||
| * For a full description of the module, visit this page: | ||||
|   https://www.drupal.org/node/133977. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes: | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following module: | ||||
|  | ||||
| * Internationalization - https://www.drupal.org/project/i18n | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| To configure email translations | ||||
| 1. Navigate to Administration > Configuration > Regional and language > | ||||
|    Multilingual settings and select the variables tab. | ||||
| 2. Select the "User emails" tab. Select the variables to be translated. Save | ||||
|    configuration. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -4,9 +4,8 @@ core = 7.x | ||||
| package = Multilingual - Internationalization | ||||
| dependencies[] = i18n_variable | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -9,7 +9,14 @@ | ||||
|  */ | ||||
| function i18n_user_mail_alter(&$message) { | ||||
|   if ($message['module'] == 'user') { | ||||
|     $language = $message['language']; | ||||
|     $message['language'] = language_default(); | ||||
|     if (isset($message['params']['account'])) { | ||||
|       $user_preferred = user_preferred_language($message['params']['account']); | ||||
|       if (isset($user_preferred)) { | ||||
|         $message['language'] = $user_preferred; | ||||
|       } | ||||
|     } | ||||
|     $language = (isset($message['language']) ? $message['language'] : language_default()); | ||||
|     $variables = array('user' => $message['params']['account']); | ||||
|     $key = $message['key']; | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,84 @@ | ||||
| CONTENTS OF THIS FILE | ||||
| --------------------- | ||||
|  | ||||
| * Introduction | ||||
| * Requirements | ||||
| * Recommended modules | ||||
| * Installation | ||||
| * Configuration | ||||
| * Maintainers | ||||
|  | ||||
|  | ||||
| INTRODUCTION | ||||
| ------------ | ||||
|  | ||||
| The Variable translation module, part of the Internationalization | ||||
| (https://www.drupal.org/project/i18n) package, allows the user to translate text | ||||
| and settings that are stored in Drupal as variables. These variables include | ||||
| text such as 'site name' and 'site slogan', as well as settings like 'Default | ||||
| front page' and 'Default 404 page'. | ||||
|  | ||||
| * For a full description of the module, visit: | ||||
|   https://www.drupal.org/node/1113374. | ||||
|  | ||||
| * To submit bug reports and feature suggestions, or to track changes visit: | ||||
|   https://www.drupal.org/project/issues/i18n. | ||||
|  | ||||
|  | ||||
| REQUIREMENTS | ||||
| ------------ | ||||
|  | ||||
| This module requires the following modules: | ||||
|  | ||||
| * Internationalization  - https://www.drupal.org/project/i18n | ||||
| * Variable - https://www.drupal.org/project/variable | ||||
|  | ||||
|  | ||||
| RECOMMENDED MODULES | ||||
| ------------------- | ||||
|  | ||||
| * Internationalization Views - https://www.drupal.org/project/i18nviews | ||||
| * Language Icons - https://www.drupal.org/project/languageicons | ||||
| * Translation Overview - https://www.drupal.org/project/translation_overview | ||||
| * Localization Client - https://www.drupal.org/project/l10n_client | ||||
| * Internationalization contributions - | ||||
|   https://www.drupal.org/project/i18n_contrib | ||||
|  | ||||
|  | ||||
| INSTALLATION | ||||
| ------------ | ||||
|  | ||||
| This is a submodule of the Internationalization module. Install the | ||||
| Internationalization module as you would normally install a contributed Drupal | ||||
| module. Visit https://www.drupal.org/node/895232 for further information. | ||||
|  | ||||
|  | ||||
| CONFIGURATION | ||||
| ------------- | ||||
|  | ||||
| To enable multilingual variables | ||||
|  | ||||
| 1. Enable the Variable translation module included with the Internationalization | ||||
|    package. | ||||
| 2. Go to Administration > Configuration > Regional and language > Multilingual | ||||
|    settings. | ||||
| 3. Select on the Variables tab. | ||||
| 4. Select the variables that will be multilingual. | ||||
| 5. Save configuration. | ||||
|  | ||||
| Once the user has the correct settings, they'll be marked with "This is a | ||||
| multilingual variable" when the user navigates to the corresponding | ||||
| administration pages. The user must switch the site language while in the | ||||
| administration pages to set the variables for each language. A language switcher | ||||
| link will appear at the top of each administrative page that has multilingual | ||||
| variables. | ||||
|  | ||||
|  | ||||
| MAINTAINERS | ||||
| ----------- | ||||
|  | ||||
| * Jose Reyero - https://www.drupal.org/u/jose-reyero | ||||
| * Florian Weber (webflo) - https://www.drupal.org/u/webflo | ||||
| * Peter Philipp - https://www.drupal.org/u/das-peter | ||||
| * Joseph Olstad - https://www.drupal.org/u/joseph.olstad | ||||
| * Nathaniel Catchpole - https://www.drupal.org/u/catch | ||||
| @@ -10,9 +10,8 @@ configure = admin/config/regional/i18n/variable | ||||
| files[] = i18n_variable.class.inc | ||||
| files[] = i18n_variable.test | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -7,9 +7,8 @@ package = Testing | ||||
| core = 6.x | ||||
| hidden = TRUE | ||||
|  | ||||
| ; Information added by Drupal.org packaging script on 2015-05-07 | ||||
| version = "7.x-1.13" | ||||
| ; Information added by Drupal.org packaging script on 2018-08-17 | ||||
| version = "7.x-1.26" | ||||
| core = "7.x" | ||||
| project = "i18n" | ||||
| datestamp = "1430999922" | ||||
|  | ||||
| datestamp = "1534531985" | ||||
|   | ||||
| @@ -40,7 +40,7 @@ function i18n_test_i18n_string_info() { | ||||
|     'title' => t('Test Cached Strings'), | ||||
|     'description' => t('Translatable items of a textgroup with caching enabled.'), | ||||
|     'format' => FALSE, // This group doesn't have strings with format | ||||
|     'class' => 'i18n_string_textgroup_cached_logged', | ||||
|     'class' => variable_get('i18n_string_textgroup_class_test_cached', 'i18n_string_textgroup_cached_logged'), | ||||
|   ); | ||||
|   return $groups; | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,22 @@ | ||||
| diff --git a/views_rss_media.install b/views_rss_media.install | ||||
| index cfee050..e7a0cc7 100644 | ||||
| --- a/views_rss_media.install | ||||
| +++ b/views_rss_media.install | ||||
| @@ -16,6 +16,8 @@ define('VIEWS_RSS_MEDIA_REQUIRED_BUILD', '7.x-2.x-dev-20120314'); | ||||
|  function views_rss_media_requirements($phase) { | ||||
|    $requirements = array(); | ||||
|    $t = get_t(); | ||||
| +  $vrb_array = explode('-', VIEWS_RSS_BUILD); | ||||
| +  $vrmrb_array = explode('-', VIEWS_RSS_MEDIA_REQUIRED_BUILD); | ||||
|    if (!defined('VIEWS_RSS_BUILD')) { | ||||
|      $requirements['views_rss_media'] = array( | ||||
|        'title' => $t('Views RSS: Media (MRSS) Elements'), | ||||
| @@ -26,7 +28,7 @@ function views_rss_media_requirements($phase) { | ||||
|        'value' => NULL, | ||||
|      ); | ||||
|    } | ||||
| -  elseif (array_pop(explode('-', VIEWS_RSS_BUILD)) < array_pop(explode('-', VIEWS_RSS_MEDIA_REQUIRED_BUILD))) { | ||||
| +  elseif (array_pop($vrb_array) < array_pop($vrmrb_array)) { | ||||
|      $requirements['views_rss_media'] = array( | ||||
|        'title' => $t('Views RSS: Media (MRSS) Elements'), | ||||
|        'description' => $t('Your current build of <a href="@views_rss_url">Views RSS</a> module (!views_rss_build) is too old for this version of <em>Views RSS: Media (MRSS) Elements</em> module to work properly. Minimum version required is <strong>!views_rss_required</strong>. Please upgrade.', array( | ||||
| @@ -16,6 +16,8 @@ define('VIEWS_RSS_MEDIA_REQUIRED_BUILD', '7.x-2.x-dev-20120314'); | ||||
| function views_rss_media_requirements($phase) { | ||||
|   $requirements = array(); | ||||
|   $t = get_t(); | ||||
|   $vrb_array = explode('-', VIEWS_RSS_BUILD); | ||||
|   $vrmrb_array = explode('-', VIEWS_RSS_MEDIA_REQUIRED_BUILD); | ||||
|   if (!defined('VIEWS_RSS_BUILD')) { | ||||
|     $requirements['views_rss_media'] = array( | ||||
|       'title' => $t('Views RSS: Media (MRSS) Elements'), | ||||
| @@ -26,7 +28,7 @@ function views_rss_media_requirements($phase) { | ||||
|       'value' => NULL, | ||||
|     ); | ||||
|   } | ||||
|   elseif (array_pop(explode('-', VIEWS_RSS_BUILD)) < array_pop(explode('-', VIEWS_RSS_MEDIA_REQUIRED_BUILD))) { | ||||
|   elseif (array_pop($vrb_array) < array_pop($vrmrb_array)) { | ||||
|     $requirements['views_rss_media'] = array( | ||||
|       'title' => $t('Views RSS: Media (MRSS) Elements'), | ||||
|       'description' => $t('Your current build of <a href="@views_rss_url">Views RSS</a> module (!views_rss_build) is too old for this version of <em>Views RSS: Media (MRSS) Elements</em> module to work properly. Minimum version required is <strong>!views_rss_required</strong>. Please upgrade.', array( | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  | ||||
| /** | ||||
|  * IE7 has no idea how large this container should be and it doesn't | ||||
|  * apply has-layout. Expand it's width to 100% and trigger has-layout. | ||||
|  * apply has-layout. Expand its width to 100% and trigger has-layout. | ||||
|  */ | ||||
| .views-edit-view .views-displays { | ||||
|   height: 1%; | ||||
|   | ||||
| @@ -312,9 +312,7 @@ div.form-item-options-value-all { | ||||
|  | ||||
| /* @end */ | ||||
|  | ||||
|  | ||||
|  | ||||
| /* @group Javascript dependent styling */ | ||||
| /* @group JavaScript dependent styling */ | ||||
|  | ||||
| .js-only { | ||||
|   display: none; | ||||
|   | ||||
| @@ -119,10 +119,11 @@ function views_drush_command() { | ||||
|  * Callback function for views-revert command. | ||||
|  */ | ||||
| function views_revert_views() { | ||||
|   $args = func_get_args(); | ||||
|   // The provided views names specified in the command. | ||||
|   $viewnames = _convert_csv_to_array($args); | ||||
|   $views = views_get_all_views(); | ||||
|   $i = 0; | ||||
|   // The provided views names specified in the command. | ||||
|   $viewnames = _convert_csv_to_array(func_get_args()); | ||||
|  | ||||
|   // Find all overridden views. | ||||
|   foreach ($views as $view) { | ||||
|   | ||||
| @@ -101,7 +101,7 @@ class views_handler_area_result extends views_handler_area { | ||||
|       $replacements["@$item"] = ${$item}; | ||||
|     } | ||||
|     // Send the output. | ||||
|     if (!empty($total)) { | ||||
|     if (!empty($total) || !empty($this->options['empty'])) { | ||||
|       $output .= filter_xss_admin(str_replace(array_keys($replacements), array_values($replacements), $format)); | ||||
|     } | ||||
|     return $output; | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
| /** | ||||
|  * Base class for arguments. | ||||
|  * | ||||
|  * The basic argument works for very simple arguments such as nid and uid | ||||
|  * The basic argument works for very simple arguments such as nid and uid. | ||||
|  * | ||||
|  * Definition terms for this handler: | ||||
|  * - name field: The field to use for the name to use in the summary, which is | ||||
| @@ -158,9 +158,10 @@ class views_handler_argument extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Determine if the argument can generate a breadcrumb | ||||
|    * Determine if the argument can generate a breadcrumb. | ||||
|    * | ||||
|    * @return bool | ||||
|    *   Indicates whether the argument can generate a breadcrumb. | ||||
|    */ | ||||
|   public function uses_breadcrumb() { | ||||
|     $info = $this->default_actions($this->options['default_action']); | ||||
| @@ -195,6 +196,7 @@ class views_handler_argument extends views_handler { | ||||
|    * Determine if the argument needs a style plugin. | ||||
|    * | ||||
|    * @return bool | ||||
|    *   the argument needs a plugin style. | ||||
|    */ | ||||
|   public function needs_style_plugin() { | ||||
|     $info = $this->default_actions($this->options['default_action']); | ||||
| @@ -527,8 +529,7 @@ class views_handler_argument extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Provide a list of default behaviors for this argument if the argument | ||||
|    * is not present. | ||||
|    * List of default behaviors for this argument if the argument is not present. | ||||
|    * | ||||
|    * Override this method to provide additional (or fewer) default behaviors. | ||||
|    */ | ||||
| @@ -657,8 +658,9 @@ class views_handler_argument extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Provide a form for selecting further summary options when the default | ||||
|    * action is set to display one. | ||||
|    * Form for selecting further summary options. | ||||
|    * | ||||
|    * Only used when the default action is set to display one. | ||||
|    */ | ||||
|   public function default_summary_form(&$form, &$form_state) { | ||||
|     $style_plugins = views_fetch_plugin_data('style'); | ||||
| @@ -795,10 +797,10 @@ class views_handler_argument extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Default action: empty | ||||
|    * Default action: empty. | ||||
|    * | ||||
|    * If an argument was expected and was not given, in this case, display the | ||||
|    * view's empty text | ||||
|    * view's empty text. | ||||
|    */ | ||||
|   public function default_empty() { | ||||
|     // We return with no query; this will force the empty text. | ||||
| @@ -967,6 +969,8 @@ class views_handler_argument extends views_handler { | ||||
|    * | ||||
|    * @param string $order | ||||
|    *   The order selected in the UI. | ||||
|    * @param string $by | ||||
|    *   Optional alias for this field. | ||||
|    */ | ||||
|   public function summary_sort($order, $by = NULL) { | ||||
|     $this->query->add_orderby(NULL, NULL, $order, (!empty($by) ? $by : $this->name_alias)); | ||||
| @@ -1116,7 +1120,7 @@ class views_handler_argument extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Set the input for this argument | ||||
|    * Set the input for this argument. | ||||
|    * | ||||
|    * @return bool | ||||
|    *   TRUE if it successfully validates; FALSE if it does not. | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  * Definitions terms: | ||||
|  * - many to one: If true, the "many to one" helper will be used. | ||||
|  * - invalid input: A string to give to the user for obviously invalid input. | ||||
|  *                  This is deprecated in favor of argument validators. | ||||
|  *   This is deprecated in favor of argument validators. | ||||
|  * | ||||
|  * @see views_many_to_one_helper() | ||||
|  * | ||||
| @@ -26,12 +26,12 @@ | ||||
| class views_handler_argument_date extends views_handler_argument_formula { | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * @var string | ||||
|    */ | ||||
|   public $option_name = 'default_argument_date'; | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * @var string | ||||
|    */ | ||||
|   public $arg_format = 'Y-m-d'; | ||||
|  | ||||
| @@ -46,9 +46,9 @@ class views_handler_argument_date extends views_handler_argument_formula { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Set the empty argument value to the current date, | ||||
|    * Set the empty argument value to the current date. | ||||
|    * | ||||
|    * formatted appropriately for this argument. | ||||
|    * Formatted appropriately for this argument. | ||||
|    * | ||||
|    * @return string | ||||
|    *   The default argument. | ||||
|   | ||||
| @@ -38,6 +38,7 @@ class views_handler_argument_string extends views_handler_argument { | ||||
|     $options['path_case'] = array('default' => 'none'); | ||||
|     $options['transform_dash'] = array('default' => FALSE, 'bool' => TRUE); | ||||
|     $options['break_phrase'] = array('default' => FALSE, 'bool' => TRUE); | ||||
|     $options['not'] = array('default' => FALSE, 'bool' => TRUE); | ||||
|  | ||||
|     if (!empty($this->definition['many to one'])) { | ||||
|       $options['add_table'] = array('default' => FALSE, 'bool' => TRUE); | ||||
| @@ -132,6 +133,13 @@ class views_handler_argument_string extends views_handler_argument { | ||||
|       '#default_value' => !empty($this->options['break_phrase']), | ||||
|       '#fieldset' => 'more', | ||||
|     ); | ||||
|     $form['not'] = array( | ||||
|       '#type' => 'checkbox', | ||||
|       '#title' => t('Exclude'), | ||||
|       '#description' => t('If selected, the numbers entered for the filter will be excluded rather than limiting the view.'), | ||||
|       '#default_value' => !empty($this->options['not']), | ||||
|       '#fieldset' => 'more', | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -207,21 +215,19 @@ class views_handler_argument_string extends views_handler_argument { | ||||
|     } | ||||
|  | ||||
|     if (count($this->value) > 1) { | ||||
|       $operator = 'IN'; | ||||
|       $operator = empty($this->options['not']) ? 'IN' : 'NOT IN'; | ||||
|       $argument = $this->value; | ||||
|     } | ||||
|     else { | ||||
|       $operator = '='; | ||||
|       $operator = empty($this->options['not']) ? '=' : '!='; | ||||
|     } | ||||
|  | ||||
|     if ($formula) { | ||||
|       $placeholder = $this->placeholder(); | ||||
|       if ($operator == 'IN') { | ||||
|         $field .= " IN($placeholder)"; | ||||
|       } | ||||
|       else { | ||||
|         $field .= ' = ' . $placeholder; | ||||
|       if (count($this->value) > 1) { | ||||
|         $placeholder = "($placeholder)"; | ||||
|       } | ||||
|       $field .= " $operator $placeholder"; | ||||
|       $placeholders = array( | ||||
|         $placeholder => $argument, | ||||
|       ); | ||||
|   | ||||
| @@ -68,7 +68,7 @@ class views_handler_field extends views_handler { | ||||
|  | ||||
|   /** | ||||
|    * @var array | ||||
|    * Stores additional fields which get's added to the query. | ||||
|    * Stores additional fields which get added to the query. | ||||
|    * The generated aliases are stored in $aliases. | ||||
|    */ | ||||
|   public $additional_fields = array(); | ||||
| @@ -424,6 +424,7 @@ class views_handler_field extends views_handler { | ||||
|         'absolute' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'external' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'replace_spaces' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'unwanted_characters' => array('default' => ''), | ||||
|         'path_case' => array('default' => 'none', 'translatable' => FALSE), | ||||
|         'trim_whitespace' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'alt' => array('default' => '', 'translatable' => TRUE), | ||||
| @@ -744,6 +745,16 @@ class views_handler_field extends views_handler { | ||||
|           'edit-options-alter-make-link' => array(1), | ||||
|         ), | ||||
|       ); | ||||
|       $form['alter']['unwanted_characters'] = array( | ||||
|         '#type' => 'textfield', | ||||
|         '#title' => t('Remove unwanted characters'), | ||||
|         '#description' => t('Space-separated list of characters to remove from the URL path'), | ||||
|         '#default_value' => $this->options['alter']['unwanted_characters'], | ||||
|         '#dependency' => array( | ||||
|           'edit-options-alter-make-link' => array(1) | ||||
|         ), | ||||
|         '#maxlength' => 255, | ||||
|       ); | ||||
|       $form['alter']['path_case'] = array( | ||||
|         '#type' => 'select', | ||||
|         '#title' => t('Transform the case'), | ||||
| @@ -782,7 +793,7 @@ class views_handler_field extends views_handler { | ||||
|         '#title' => t('Rel Text'), | ||||
|         '#type' => 'textfield', | ||||
|         '#default_value' => $this->options['alter']['rel'], | ||||
|         '#description' => t('Include Rel attribute for use in lightbox2 or other javascript utility.'), | ||||
|         '#description' => t('Include Rel attribute for use in lightbox2 or other JavaScript utility.'), | ||||
|         '#dependency' => array( | ||||
|           'edit-options-alter-make-link' => array(1), | ||||
|         ), | ||||
| @@ -1234,8 +1245,9 @@ If you would like to have the characters \'[\' and \']\' please use the html ent | ||||
|    * Render this field as altered text, from a fieldset set by the user. | ||||
|    */ | ||||
|   public function render_altered($alter, $tokens) { | ||||
|     // Filter this right away as our substitutions are already sanitized. | ||||
|     $value = filter_xss_admin($alter['text']); | ||||
|     // We trust admins so we allow any tag content. This is important for | ||||
|     // displays such as XML where we should not mess with tags. | ||||
|     $value = $alter['text']; | ||||
|     $value = strtr($value, $tokens); | ||||
|  | ||||
|     return $value; | ||||
| @@ -1287,6 +1299,12 @@ If you would like to have the characters \'[\' and \']\' please use the html ent | ||||
|       if (!empty($alter['replace_spaces'])) { | ||||
|         $path = str_replace(' ', '-', $path); | ||||
|       } | ||||
|  | ||||
|       if (!empty($alter['unwanted_characters'])) { | ||||
|         foreach (explode(' ', $alter['unwanted_characters']) as $unwanted) { | ||||
|           $path = str_replace($unwanted, '', $path); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Parse the URL and move any query and fragment parameters out of the path. | ||||
|   | ||||
| @@ -8,6 +8,9 @@ | ||||
| /** | ||||
|  * A handler to provide proper displays for dates. | ||||
|  * | ||||
|  * This may be used on table fields that hold either UNIX timestamps or SQL | ||||
|  * datetime strings. | ||||
|  * | ||||
|  * @ingroup views_field_handlers | ||||
|  */ | ||||
| class views_handler_field_date extends views_handler_field { | ||||
| @@ -138,6 +141,12 @@ class views_handler_field_date extends views_handler_field { | ||||
|    */ | ||||
|   public function render($values) { | ||||
|     $value = $this->get_value($values); | ||||
|  | ||||
|     if (!is_numeric($value)) { | ||||
|       // If the value isn't numeric, assume it's an SQL DATETIME. | ||||
|       $value = strtotime($value); | ||||
|     } | ||||
|  | ||||
|     $format = $this->options['date_format']; | ||||
|     if (in_array($format, $this->supported_date_types())) { | ||||
|       $custom_format = $this->options['custom_date_format']; | ||||
|   | ||||
| @@ -41,7 +41,9 @@ class views_handler_field_entity extends views_handler_field { | ||||
|  | ||||
|     // Initialize the entity-type used. | ||||
|     $table_data = views_fetch_data($this->table); | ||||
|     $this->entity_type = $table_data['table']['entity type']; | ||||
|     if (isset($table_data['table']['entity type'])) { | ||||
|       $this->entity_type = $table_data['table']['entity type']; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|   | ||||
| @@ -64,6 +64,7 @@ class views_handler_field_links extends views_handler_field { | ||||
|   public function options_submit(&$form, &$form_state) { | ||||
|     // Remove unselected options. | ||||
|     $form_state['values']['options']['fields'] = array_filter($form_state['values']['options']['fields']); | ||||
|     parent::options_submit($form, $form_state); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|   | ||||
| @@ -118,6 +118,11 @@ class views_handler_field_numeric extends views_handler_field { | ||||
|   public function render($values) { | ||||
|     $value = $this->get_value($values); | ||||
|  | ||||
|     // Output nothing if the value is null. | ||||
|     if (is_null($value)) { | ||||
|       return ''; | ||||
|     } | ||||
|  | ||||
|     // Hiding should happen before rounding or adding prefix/suffix. | ||||
|     if ($this->options['hide_empty'] && empty($value) && ($value !== 0 || $this->options['empty_zero'])) { | ||||
|       return ''; | ||||
| @@ -127,12 +132,13 @@ class views_handler_field_numeric extends views_handler_field { | ||||
|       $value = number_format($value, $this->options['precision'], $this->options['decimal'], $this->options['separator']); | ||||
|     } | ||||
|     else { | ||||
|       $remainder = abs($value) - intval(abs($value)); | ||||
|       $point_position = strpos($value, '.'); | ||||
|       $remainder = ($point_position === FALSE) ? '' : substr($value, $point_position + 1); | ||||
|       $value = $value > 0 ? floor($value) : ceil($value); | ||||
|       $value = number_format($value, 0, '', $this->options['separator']); | ||||
|       if ($remainder) { | ||||
|         // The substr may not be locale safe. | ||||
|         $value .= $this->options['decimal'] . substr($remainder, 2); | ||||
|         $value .= $this->options['decimal'] . $remainder; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -15,15 +15,14 @@ | ||||
|  *   available as standard operators. | ||||
|  * | ||||
|  * Object flags: | ||||
|  *  You can set some specific behavior by setting up the following flags on | ||||
|  *  your custom class. | ||||
|  * | ||||
|  * - always_multiple: | ||||
|  *    Disable the possibility to force a single value. | ||||
|  * - no_operator: | ||||
|  *    Disable the possibility to use operators. | ||||
|  * - always_required: | ||||
|  *    Disable the possibility to allow a exposed input to be optional. | ||||
|  *   It's possible to set specific behavior using the following flags on the | ||||
|  *   custom class: | ||||
|  *   - always_multiple: | ||||
|  *     Disable the possibility to force a single value. | ||||
|  *   - no_operator: | ||||
|  *     Disable the possibility to use operators. | ||||
|  *   - always_required: | ||||
|  *     Disable the possibility to allow a exposed input to be optional. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @@ -34,8 +33,10 @@ | ||||
| class views_handler_filter extends views_handler { | ||||
|  | ||||
|   /** | ||||
|    * Contains the actual value of the field,either configured in the views ui | ||||
|    * or entered in the exposed filters. | ||||
|    * Contains the actual value of the field. | ||||
|    * | ||||
|    * This will be either configured in the views UI or entered in the exposed | ||||
|    * filters. | ||||
|    * | ||||
|    * @var mixed | ||||
|    */ | ||||
| @@ -135,13 +136,17 @@ class views_handler_filter extends views_handler { | ||||
|         'use_operator' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'operator_label' => array('default' => '', 'translatable' => TRUE), | ||||
|         'operator' => array('default' => ''), | ||||
|         'limit_operators' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'available_operators' => array('default' => array()), | ||||
|         'identifier' => array('default' => ''), | ||||
|         'required' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'remember' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'multiple' => array('default' => FALSE, 'bool' => TRUE), | ||||
|         'remember_roles' => array('default' => array( | ||||
|           DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID, | ||||
|         )), | ||||
|         'remember_roles' => array( | ||||
|           'default' => array( | ||||
|             DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID, | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
| @@ -205,9 +210,8 @@ class views_handler_filter extends views_handler { | ||||
|   /** | ||||
|    * Provide the basic form which calls through to subforms. | ||||
|    * | ||||
|    * If overridden, it is best to call through to the parent, | ||||
|    * or to at least make sure all of the functions in this form | ||||
|    * are called. | ||||
|    * If overridden, it is best to call through to the parent, or to at least | ||||
|    * make sure all of the functions in this form are called. | ||||
|    */ | ||||
|   public function options_form(&$form, &$form_state) { | ||||
|     parent::options_form($form, $form_state); | ||||
| @@ -248,7 +252,7 @@ class views_handler_filter extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Simple validate handler | ||||
|    * Simple validate handler. | ||||
|    */ | ||||
|   public function options_validate(&$form, &$form_state) { | ||||
|     $this->operator_validate($form, $form_state); | ||||
| @@ -274,6 +278,8 @@ class views_handler_filter extends views_handler { | ||||
|       $this->value_submit($form, $form_state); | ||||
|     } | ||||
|     if (!empty($this->options['exposed'])) { | ||||
|       $options = &$form_state['values']['options']['expose']; | ||||
|       $options['available_operators'] = (!empty($options['use_operator']) && !empty($options['limit_operators'])) ? array_filter($options['available_operators']) : array(); | ||||
|       $this->expose_submit($form, $form_state); | ||||
|     } | ||||
|     if ($this->is_a_group()) { | ||||
| @@ -293,14 +299,29 @@ class views_handler_filter extends views_handler { | ||||
|   /** | ||||
|    * Options form subform for setting the operator. | ||||
|    * | ||||
|    * This may be overridden by child classes, and it must | ||||
|    * define $form['operator']; | ||||
|    * This may be overridden by child classes, and it must define | ||||
|    * $form['operator']. | ||||
|    * | ||||
|    * @see options_form() | ||||
|    */ | ||||
|   public function operator_form(&$form, &$form_state) { | ||||
|     $options = $this->operator_options(); | ||||
|     if (!empty($options)) { | ||||
|       $available = $this->options['expose']['available_operators']; | ||||
|       if ($this->options['expose']['limit_operators'] && count($available)) { | ||||
|         foreach ($options as $key => $value) { | ||||
|           if (!isset($available[$key])) { | ||||
|             unset($options[$key]); | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         // Make sure we have a valid default value if the current one is | ||||
|         // excluded. | ||||
|         if (!isset($options[$this->operator])) { | ||||
|           // Just choose the first. | ||||
|           $this->operator = key($options); | ||||
|         } | ||||
|       } | ||||
|       $form['operator'] = array( | ||||
|         '#type' => count($options) < 10 ? 'radios' : 'select', | ||||
|         '#title' => t('Operator'), | ||||
| @@ -313,7 +334,7 @@ class views_handler_filter extends views_handler { | ||||
|   /** | ||||
|    * Provide a list of options for the default operator form. | ||||
|    * | ||||
|    * Should be overridden by classes that don't override operator_form | ||||
|    * Should be overridden by classes that don't override operator_form. | ||||
|    */ | ||||
|   public function operator_options() { | ||||
|     return array(); | ||||
| @@ -511,6 +532,33 @@ class views_handler_filter extends views_handler { | ||||
|         '#title' => t('Required'), | ||||
|         '#default_value' => $this->options['expose']['required'], | ||||
|       ); | ||||
|  | ||||
|       $operator_options = $this->operator_options(); | ||||
|       if (count($operator_options)) { | ||||
|         $form['expose']['limit_operators'] = array( | ||||
|           '#type' => 'checkbox', | ||||
|           '#title' => t('Limit operators'), | ||||
|           '#description' => t('When checked, the operator will be exposed to the user'), | ||||
|           '#default_value' => !empty($this->options['expose']['limit_operators']), | ||||
|           '#dependency' => array( | ||||
|             'edit-options-expose-use-operator' => array(1), | ||||
|           ), | ||||
|           '#description' => t('Restrict which operators will be available to select in the exposed operator form.'), | ||||
|         ); | ||||
|  | ||||
|         $form['expose']['available_operators'] = array( | ||||
|           '#type' => 'checkboxes', | ||||
|           '#title' => t('Limit the exposed operators'), | ||||
|           '#default_value' => $this->options['expose']['available_operators'], | ||||
|           '#prefix' => '<div id="edit-options-expose-available-operators-wrapper"><div id="edit-options-expose-available-operators">', | ||||
|           '#suffix' => '</div></div>', | ||||
|           '#description' => t('Select which operators will be available to select in the exposed operator form. If none are selected, all the operators listed here will be used.'), | ||||
|           '#options' => $operator_options, | ||||
|           '#dependency' => array( | ||||
|             'edit-options-expose-limit-operators' => array(1), | ||||
|           ), | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|       $form['expose']['required'] = array( | ||||
| @@ -533,7 +581,7 @@ class views_handler_filter extends views_handler { | ||||
|     ); | ||||
|  | ||||
|     if (!empty($form['operator']['#type'])) { | ||||
|        // Increase the width of the left (operator) column. | ||||
|       // Increase the width of the left (operator) column. | ||||
|       $form['operator']['#prefix'] = '<div class="views-group-box views-left-40">'; | ||||
|       $form['operator']['#suffix'] = '</div>'; | ||||
|       $form['value']['#prefix'] = '<div class="views-group-box views-right-60">'; | ||||
| @@ -552,7 +600,7 @@ class views_handler_filter extends views_handler { | ||||
|         '#size' => 40, | ||||
|         '#description' => t('This will appear before your operator select field.'), | ||||
|         '#dependency' => array( | ||||
|           'edit-options-expose-use-operator' => array(1) | ||||
|           'edit-options-expose-use-operator' => array(1), | ||||
|         ), | ||||
|       ); | ||||
|       $form['expose']['operator_id'] = array( | ||||
| @@ -562,7 +610,7 @@ class views_handler_filter extends views_handler { | ||||
|         '#size' => 40, | ||||
|         '#description' => t('This will appear in the URL after the ? to identify this operator.'), | ||||
|         '#dependency' => array( | ||||
|           'edit-options-expose-use-operator' => array(1) | ||||
|           'edit-options-expose-use-operator' => array(1), | ||||
|         ), | ||||
|         '#fieldset' => 'more', | ||||
|       ); | ||||
| @@ -629,6 +677,12 @@ class views_handler_filter extends views_handler { | ||||
|     if (!$this->view->display_handler->is_identifier_unique($form_state['id'], $form_state['values']['options']['expose']['identifier'])) { | ||||
|       form_error($form['expose']['identifier'], t('This identifier is used by another handler.')); | ||||
|     } | ||||
|  | ||||
|     // Filter out roles which weren't selected, so that they aren't exported. | ||||
|     // This is purely cosmetic. | ||||
|     if (!empty($form_state['values']['options']['expose']['remember_roles'])) { | ||||
|       $form_state['values']['options']['expose']['remember_roles'] = array_filter($form_state['values']['options']['expose']['remember_roles']); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -657,10 +711,13 @@ class views_handler_filter extends views_handler { | ||||
|         if (empty($group['remove'])) { | ||||
|           // Check if the title is defined but value wasn't defined. | ||||
|           if (!empty($group['title'])) { | ||||
|             if ((!is_array($group['value']) && trim($group['value']) == "") || | ||||
|                 (is_array($group['value']) && count(array_filter($group['value'], '_views_array_filter_zero')) == 0)) { | ||||
|               form_error($form['group_info']['group_items'][$id]['value'], | ||||
|                 t('The value is required if title for this item is defined.')); | ||||
|             // No value is needed for 'empty' and 'not empty' operator. | ||||
|             if (!in_array($group['operator'], array('empty', 'not empty'))) { | ||||
|               if ((!is_array($group['value']) && trim($group['value']) == "") || | ||||
|                   (is_array($group['value']) && count(array_filter($group['value'], '_views_array_filter_zero')) == 0)) { | ||||
|                 form_error($form['group_info']['group_items'][$id]['value'], | ||||
|                   t('The value is required if title for this item is defined.')); | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|  | ||||
| @@ -786,9 +843,8 @@ class views_handler_filter extends views_handler { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * Render our chunk of the exposed filter form when selecting | ||||
|    * Render our chunk of the exposed filter form when selecting. | ||||
|    * | ||||
|    * You can override this if it doesn't do what you expect. | ||||
|    */ | ||||
| @@ -802,7 +858,7 @@ class views_handler_filter extends views_handler { | ||||
|       $operator = $this->options['expose']['operator_id']; | ||||
|       $this->operator_form($form, $form_state); | ||||
|       $form[$operator] = $form['operator']; | ||||
|       $form[$operator]['#title'] =  $this->options['expose']['operator_label']; | ||||
|       $form[$operator]['#title'] = $this->options['expose']['operator_label']; | ||||
|       $form[$operator]['#title_display'] = 'invisible'; | ||||
|  | ||||
|       $this->exposed_translate($form[$operator], 'operator'); | ||||
| @@ -813,7 +869,19 @@ class views_handler_filter extends views_handler { | ||||
|     // Build the form and set the value based on the identifier. | ||||
|     if (!empty($this->options['expose']['identifier'])) { | ||||
|       $value = $this->options['expose']['identifier']; | ||||
|       $this->value_form($form, $form_state); | ||||
|       if ($this->operator == 'empty' || $this->operator == 'not empty') { | ||||
|         $boolean = new views_handler_filter_boolean_operator(); | ||||
|         $boolean->value = $this->value = 'All'; | ||||
|         $boolean->value_value = $this->value_value = ''; | ||||
|         $boolean->value_options = $this->value_options = array( | ||||
|           1 => t('Yes'), | ||||
|           0 => t('No'), | ||||
|         ); | ||||
|         $boolean->value_form($form, $form_state); | ||||
|       } | ||||
|       else { | ||||
|         $this->value_form($form, $form_state); | ||||
|       } | ||||
|       $form[$value] = $form['value']; | ||||
|  | ||||
|       if (isset($form[$value]['#title']) && !empty($form[$value]['#type']) && $form[$value]['#type'] != 'checkbox') { | ||||
| @@ -955,7 +1023,7 @@ class views_handler_filter extends views_handler { | ||||
|  | ||||
|     // The string '- Any -' will not be rendered. | ||||
|     // @see theme_views_ui_build_group_filter_form() | ||||
|     $groups = array('All' => '- Any -');  | ||||
|     $groups = array('All' => '- Any -'); | ||||
|  | ||||
|     // Provide 3 options to start when we are in a new group. | ||||
|     if (count($this->options['group_info']['group_items']) == 0) { | ||||
| @@ -968,6 +1036,7 @@ class views_handler_filter extends views_handler { | ||||
|       if (!empty($form_state['values']['options']['group_info']['group_items'][$item_id]['remove'])) { | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       // Each rows contains three widgets: | ||||
|       // a) The title, where users define how they identify a pair of operator | ||||
|       //    | value. | ||||
| @@ -979,14 +1048,14 @@ class views_handler_filter extends views_handler { | ||||
|       $row = array(); | ||||
|       $groups[$item_id] = ''; | ||||
|       $this->operator_form($row, $form_state); | ||||
|       // Force the operator form to be a select box. Some handlers uses | ||||
|       // radios and they occupy a lot of space in a table row. | ||||
|       // Force the operator form to be a select box. Some handlers uses radios | ||||
|       // and they occupy a lot of space in a table row. | ||||
|       $row['operator']['#type'] = 'select'; | ||||
|       $row['operator']['#title'] = ''; | ||||
|       $this->value_form($row, $form_state); | ||||
|  | ||||
|       // Fix the dependencies to update value forms when operators changes. | ||||
|       // This is needed because forms are inside a new form and their ids | ||||
|       // This is needed because forms are inside a new form and their IDs | ||||
|       // changes. Dependencies are used when operator changes from to | ||||
|       // 'Between', 'Not Between', etc, and two or more widgets are displayed. | ||||
|       $without_children = TRUE; | ||||
| @@ -1041,6 +1110,7 @@ class views_handler_filter extends views_handler { | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     // From all groups, let chose which is the default. | ||||
|     $form['group_info']['default_group'] = array( | ||||
|       '#type' => 'radios', | ||||
| @@ -1049,8 +1119,9 @@ class views_handler_filter extends views_handler { | ||||
|       '#required' => TRUE, | ||||
|       '#attributes' => array( | ||||
|         'class' => array('default-radios'), | ||||
|       ) | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
|     // From all groups, let chose which is the default. | ||||
|     $form['group_info']['default_group_multiple'] = array( | ||||
|       '#type' => 'checkboxes', | ||||
| @@ -1058,7 +1129,7 @@ class views_handler_filter extends views_handler { | ||||
|       '#default_value' => $this->options['group_info']['default_group_multiple'], | ||||
|       '#attributes' => array( | ||||
|         'class' => array('default-checkboxes'), | ||||
|       ) | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
|     $form['group_info']['add_group'] = array( | ||||
| @@ -1086,7 +1157,6 @@ class views_handler_filter extends views_handler { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /** | ||||
|    * Make some translations to a form item to make it more suitable to exposing. | ||||
|    */ | ||||
| @@ -1190,13 +1260,13 @@ class views_handler_filter extends views_handler { | ||||
|   /** | ||||
|    * Transform the input from a grouped filter into a standard filter. | ||||
|    * | ||||
|    * When a filter is a group, find the set of operator and values | ||||
|    * that the choosed item represents, and inform views that a normal | ||||
|    * filter was submitted by telling the operator and the value selected. | ||||
|    * When a filter is a group, find the set of operator and values that the | ||||
|    * choosen item represents, and inform views that a normal filter was | ||||
|    * submitted by telling the operator and the value selected. | ||||
|    * | ||||
|    * The param $selected_group_id is only passed when the filter uses the | ||||
|    * checkboxes widget, and this function will be called for each item | ||||
|    * choosed in the checkboxes. | ||||
|    * checkboxes widget, and this function will be called for each item choosen | ||||
|    * in the checkboxes. | ||||
|    */ | ||||
|   public function convert_exposed_input(&$input, $selected_group_id = NULL) { | ||||
|     if ($this->is_a_group()) { | ||||
| @@ -1234,9 +1304,12 @@ class views_handler_filter extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Returns the options available for a grouped filter that users checkboxes | ||||
|    * as widget, and therefore has to be applied several times, one per | ||||
|    * item selected. | ||||
|    * Options available for a grouped filter which uses checkboxes. | ||||
|    * | ||||
|    * Note: has to be applied several times, one per item selected. | ||||
|    * | ||||
|    * @return array | ||||
|    *   The options available for a grouped filter. | ||||
|    */ | ||||
|   public function group_multiple_exposed_input(&$input) { | ||||
|     if (!empty($input[$this->options['group_info']['identifier']])) { | ||||
| @@ -1246,7 +1319,7 @@ class views_handler_filter extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * Indicate whether users can select multiple group items. | ||||
|    * | ||||
|    * @return bool | ||||
|    *   TRUE if users can select multiple groups items of a grouped exposed | ||||
| @@ -1258,8 +1331,9 @@ class views_handler_filter extends views_handler { | ||||
|  | ||||
|   /** | ||||
|    * If set to remember exposed input in the session, store it there. | ||||
|    * This function is similar to store_exposed_input but modified to | ||||
|    * work properly when the filter is a group. | ||||
|    * | ||||
|    * This function is similar to store_exposed_input but modified to work | ||||
|    * properly when the filter is a group. | ||||
|    */ | ||||
|   public function store_group_input($input, $status) { | ||||
|     if (!$this->is_a_group() || empty($this->options['group_info']['identifier'])) { | ||||
| @@ -1312,14 +1386,13 @@ class views_handler_filter extends views_handler { | ||||
|  | ||||
|       // Various ways to check for the absence of non-required input. | ||||
|       if (empty($this->options['expose']['required'])) { | ||||
|         if (($this->operator == 'empty' || $this->operator == 'not empty') && $value === '') { | ||||
|           $value = ' '; | ||||
|         if ($this->operator == 'empty' || $this->operator == 'not empty') { | ||||
|           $value = is_array($value) ? $value['value'] : $value; | ||||
|           $this->operator = ($this->operator == 'empty' && empty($value)) || ($this->operator == 'not empty' && !empty($value)) ? 'not empty' : 'empty'; | ||||
|         } | ||||
|  | ||||
|         if ($this->operator != 'empty' && $this->operator != 'not empty') { | ||||
|           if ($value == 'All' || $value === array()) { | ||||
|             return FALSE; | ||||
|           } | ||||
|         if ($value == 'All' || $value === array()) { | ||||
|           return FALSE; | ||||
|         } | ||||
|  | ||||
|         if (!empty($this->always_multiple) && $value === '') { | ||||
| @@ -1342,7 +1415,7 @@ class views_handler_filter extends views_handler { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * Store the exposed input for processing later. | ||||
|    */ | ||||
|   public function store_exposed_input($input, $status) { | ||||
|     if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) { | ||||
| @@ -1392,7 +1465,9 @@ class views_handler_filter extends views_handler { | ||||
|         $session[$this->options['expose']['operator_id']] = $input[$this->options['expose']['operator_id']]; | ||||
|       } | ||||
|  | ||||
|       $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']]; | ||||
|       if (isset($input[$this->options['expose']['identifier']])) { | ||||
|         $session[$this->options['expose']['identifier']] = $input[$this->options['expose']['identifier']]; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -1419,9 +1494,9 @@ class views_handler_filter extends views_handler { | ||||
|    * @return bool | ||||
|    *   Whether the filter can be used in OR groups. | ||||
|    */ | ||||
|    public function can_group() { | ||||
|      return TRUE; | ||||
|    } | ||||
|   public function can_group() { | ||||
|     return TRUE; | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -1476,14 +1551,15 @@ class views_handler_filter_broken extends views_handler_filter { | ||||
|  * Filter by no empty values, though allow to use "0". | ||||
|  * | ||||
|  * @param string $var | ||||
|  *   The string to check. | ||||
|  * | ||||
|  * @return bool | ||||
|  *   Indicates if the argument is an empty string. | ||||
|  */ | ||||
| function _views_array_filter_zero($var) { | ||||
|   return trim($var) != ""; | ||||
|   return trim($var) != ''; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @} | ||||
|  */ | ||||
|   | ||||
| @@ -73,7 +73,7 @@ class views_handler_filter_combine extends views_handler_filter_string { | ||||
|       // Always add the table of the selected fields to be sure a table alias | ||||
|       // exists. | ||||
|       $field->ensure_my_table(); | ||||
|       if (!empty($field->field_alias) && !empty($field->field_alias)) { | ||||
|       if (!empty($field->table_alias) && !empty($field->real_field)) { | ||||
|         $fields[] = "$field->table_alias.$field->real_field"; | ||||
|       } | ||||
|     } | ||||
| @@ -198,6 +198,14 @@ class views_handler_filter_combine extends views_handler_filter_string { | ||||
|     $this->query->add_where_expression($this->options['group'], "$field RLIKE $placeholder", array($placeholder => $this->value)); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    */ | ||||
|   public function op_not_regex($field) { | ||||
|     $placeholder = $this->placeholder(); | ||||
|     $this->query->add_where_expression($this->options['group'], "$field NOT RLIKE $placeholder", array($placeholder => $this->value)); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    */ | ||||
|   | ||||
| @@ -158,7 +158,7 @@ class views_handler_filter_date extends views_handler_filter_numeric { | ||||
|         return FALSE; | ||||
|       } | ||||
|     } | ||||
|     else { | ||||
|     elseif ($operators[$operator]['values'] == 2) { | ||||
|       if ($this->value['min'] == '' || $this->value['max'] == '') { | ||||
|         return FALSE; | ||||
|       } | ||||
|   | ||||
| @@ -116,6 +116,12 @@ class views_handler_filter_numeric extends views_handler_filter { | ||||
|           'method' => 'op_regex', | ||||
|           'values' => 1, | ||||
|         ), | ||||
|         'not_regular_expression' => array( | ||||
|           'title' => t('Not regular expression'), | ||||
|           'short' => t('not regex'), | ||||
|           'method' => 'op_not_regex', | ||||
|           'values' => 1, | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
| @@ -159,72 +165,108 @@ class views_handler_filter_numeric extends views_handler_filter { | ||||
|     // not rendered, we can't render dependencies; instead we only | ||||
|     // render the form items we need. | ||||
|     $which = 'all'; | ||||
|     $limit_operators = !empty($this->options['expose']['limit_operators']) && (count($this->options['expose']['available_operators']) > 0); | ||||
|     $use_value = FALSE; | ||||
|     $use_minmax = FALSE; | ||||
|  | ||||
|     if (!empty($form['operator'])) { | ||||
|       $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator'; | ||||
|     } | ||||
|  | ||||
|     if (!empty($form_state['exposed'])) { | ||||
|       $operator_values_with_1_values = $this->operator_values(1); | ||||
|       $operator_values_with_2_values = $this->operator_values(2); | ||||
|       if ($limit_operators) { | ||||
|         // If limit operators is enabled, check that at least one operator | ||||
|         // with two values is enabled to display the min max widgets | ||||
|         foreach ($operator_values_with_2_values as $operator) { | ||||
|           if (isset($this->options['expose']['available_operators'][$operator])) { | ||||
|             $use_minmax = TRUE; | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|         // the same for operators with one value | ||||
|         foreach ($operator_values_with_1_values as $operator) { | ||||
|           if (isset($this->options['expose']['available_operators'][$operator])) { | ||||
|             $use_value = TRUE; | ||||
|             break; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
|         $use_minmax = $use_value = TRUE; | ||||
|       } | ||||
|       $identifier = $this->options['expose']['identifier']; | ||||
|  | ||||
|       if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) { | ||||
|         // exposed and locked. | ||||
|         $which = in_array($this->operator, $this->operator_values(2)) ? 'minmax' : 'value'; | ||||
|         $which = in_array($this->operator, $operator_values_with_2_values) ? 'minmax' : 'value'; | ||||
|       } | ||||
|       else { | ||||
|         $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if ($which == 'all') { | ||||
|       $form['value']['value'] = array( | ||||
|         '#type' => 'textfield', | ||||
|         '#title' => empty($form_state['exposed']) ? t('Value') : '', | ||||
|         '#size' => 30, | ||||
|         '#default_value' => $this->value['value'], | ||||
|         '#dependency' => array($source => $this->operator_values(1)), | ||||
|       ); | ||||
|       if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['value'])) { | ||||
|         $form_state['input'][$identifier]['value'] = $this->value['value']; | ||||
|       } | ||||
|     else { | ||||
|       $use_minmax = $use_value = TRUE; | ||||
|     } | ||||
|     elseif ($which == 'value') { | ||||
|       // When exposed we drop the value-value and just do value if | ||||
|       // the operator is locked. | ||||
|       $form['value'] = array( | ||||
|         '#type' => 'textfield', | ||||
|         '#title' => empty($form_state['exposed']) ? t('Value') : '', | ||||
|         '#size' => 30, | ||||
|         '#default_value' => $this->value['value'], | ||||
|       ); | ||||
|       if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) { | ||||
|         $form_state['input'][$identifier] = $this->value['value']; | ||||
|  | ||||
|     if ($use_value) { | ||||
|       if ($which == 'all') { | ||||
|         $form['value']['value'] = array( | ||||
|           '#type' => 'textfield', | ||||
|           '#title' => empty($form_state['exposed']) ? t('Value') : '', | ||||
|           '#size' => 30, | ||||
|           '#default_value' => $this->value['value'], | ||||
|           '#dependency' => array($source => $this->operator_values(1)), | ||||
|         ); | ||||
|         if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['value'])) { | ||||
|           $form_state['input'][$identifier]['value'] = $this->value['value']; | ||||
|         } | ||||
|       } | ||||
|       elseif ($which == 'value') { | ||||
|         // When exposed we drop the value-value and just do value if | ||||
|         // the operator is locked. | ||||
|         $form['value'] = array( | ||||
|           '#type' => 'textfield', | ||||
|           '#title' => empty($form_state['exposed']) ? t('Value') : '', | ||||
|           '#size' => 30, | ||||
|           '#default_value' => $this->value['value'], | ||||
|         ); | ||||
|         if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) { | ||||
|           $form_state['input'][$identifier] = $this->value['value']; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if ($which == 'all' || $which == 'minmax') { | ||||
|       $form['value']['min'] = array( | ||||
|         '#type' => 'textfield', | ||||
|         '#title' => empty($form_state['exposed']) ? t('Min') : '', | ||||
|         '#size' => 30, | ||||
|         '#default_value' => $this->value['min'], | ||||
|       ); | ||||
|       $form['value']['max'] = array( | ||||
|         '#type' => 'textfield', | ||||
|         '#title' => empty($form_state['exposed']) ? t('And max') : t('And'), | ||||
|         '#size' => 30, | ||||
|         '#default_value' => $this->value['max'], | ||||
|       ); | ||||
|       if ($which == 'all') { | ||||
|         $dependency = array( | ||||
|           '#dependency' => array($source => $this->operator_values(2)), | ||||
|       if ($use_minmax) { | ||||
|         $form['value']['min'] = array( | ||||
|           '#type' => 'textfield', | ||||
|           '#title' => empty($form_state['exposed']) ? t('Min') : '', | ||||
|           '#size' => 30, | ||||
|           '#default_value' => $this->value['min'], | ||||
|         ); | ||||
|         $form['value']['min'] += $dependency; | ||||
|         $form['value']['max'] += $dependency; | ||||
|         $form['value']['max'] = array( | ||||
|           '#type' => 'textfield', | ||||
|           '#title' => empty($form_state['exposed']) ? t('And max') : t('And'), | ||||
|           '#size' => 30, | ||||
|           '#default_value' => $this->value['max'], | ||||
|         ); | ||||
|  | ||||
|         if ($which == 'all') { | ||||
|           $dependency = array( | ||||
|             '#dependency' => array($source => $this->operator_values(2)), | ||||
|           ); | ||||
|  | ||||
|           $form['value']['min'] += $dependency; | ||||
|           $form['value']['max'] += $dependency; | ||||
|         } | ||||
|       } | ||||
|       if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['min'])) { | ||||
|  | ||||
|       if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['min']) && $use_minmax) { | ||||
|         $form_state['input'][$identifier]['min'] = $this->value['min']; | ||||
|       } | ||||
|       if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['max'])) { | ||||
|       if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier]['max']) && $use_minmax) { | ||||
|         $form_state['input'][$identifier]['max'] = $this->value['max']; | ||||
|       } | ||||
|  | ||||
| @@ -291,6 +333,13 @@ class views_handler_filter_numeric extends views_handler_filter { | ||||
|     $this->query->add_where($this->options['group'], $field, $this->value['value'], 'RLIKE'); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function op_not_regex($field) { | ||||
|     $this->query->add_where($this->options['group'], $field, $this->value['value'], 'NOT RLIKE'); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   | ||||
| @@ -135,6 +135,12 @@ class views_handler_filter_string extends views_handler_filter { | ||||
|           'method' => 'op_regex', | ||||
|           'values' => 1, | ||||
|         ), | ||||
|         'not_regular_expression' => array( | ||||
|           'title' => t('Not regular expression'), | ||||
|           'short' => t('not regex'), | ||||
|           'method' => 'op_not_regex', | ||||
|           'values' => 1, | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
| @@ -274,7 +280,9 @@ class views_handler_filter_string extends views_handler_filter { | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function op_contains($field) { | ||||
|     $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value) . '%', 'LIKE'); | ||||
|     if (!empty($this->value)) { | ||||
|       $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value) . '%', 'LIKE'); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -371,6 +379,13 @@ class views_handler_filter_string extends views_handler_filter { | ||||
|     $this->query->add_where($this->options['group'], $field, $this->value, 'RLIKE'); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function op_not_regex($field) { | ||||
|     $this->query->add_where($this->options['group'], $field, $this->value, 'NOT RLIKE'); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   | ||||
| @@ -19,9 +19,9 @@ The "building block" design of the views system provides power and flexibility, | ||||
|  | ||||
| <li><a href="topic:views/header">Header</a>, which allow you to add by default one or more text area above the views output. </li> | ||||
|  | ||||
| 	<li><a href="topic:views/footer">Footer</a>, which allow you to add by default one or more text area beneath the views output. </li> | ||||
| <li><a href="topic:views/footer">Footer</a>, which allow you to add by default one or more text area beneath the views output. </li> | ||||
|  | ||||
| 	<li>The <a href="topic:views/footer">Emtpy Text</a> content will be displayed, when you choose in the Arguments Section "Action to take if argument is not present" the option "Display empty text".</li> | ||||
| <li>The <a href="topic:views/footer">Emtpy Text</a> content will be displayed, when you choose in the Arguments Section "Action to take if argument is not present" the option "Display empty text".</li> | ||||
|  | ||||
|  | ||||
| </ul> | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| <h2>Troubleshooting UI crashes</h2> | ||||
|  | ||||
| There are a number of reasons why the Views UI may crash; the most common state or result of a crash is either a white screen (everyone's favorite WSOD), or a screen of what looks like garbage text. This is generally a javascript crash of some fashion. | ||||
| There are a number of reasons why the Views UI may crash; the most common state or result of a crash is either a white screen (everyone's favorite WSOD), or a screen of what looks like garbage text. This is generally JavaScript crash of some fashion. | ||||
|  | ||||
| To get the most timely and accurate help in the issue queue, please try to gather this information: | ||||
|  | ||||
| Check your javascript console. In Firefox, you can hit ctrl-shift-j or use firebug. Copy this information into the issue, or attach it as a text file. Really - this is the single biggest thing you can do to help figure out where the crash is coming from. | ||||
| Check your JavaScript console. In Firefox, you can hit ctrl-shift-j or use firebug. Copy this information into the issue, or attach it as a text file. Really - this is the single biggest thing you can do to help figure out where the crash is coming from. | ||||
|  | ||||
|  | ||||
| <h3>JSON prepends data with jQuery, causing editing and preview problems.</h3> | ||||
|   | ||||
| @@ -691,7 +691,7 @@ function views_ui_ajax_update_form($form, $form_state) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Non-Javascript fallback for updating the add view form. | ||||
|  * Non-JavaScript fallback for updating the add view form. | ||||
|  */ | ||||
| function views_ui_nojs_submit($form, &$form_state) { | ||||
|   $form_state['rebuild'] = TRUE; | ||||
| @@ -1598,7 +1598,7 @@ function views_ui_get_display_tab_details($view, $display) { | ||||
|   $is_enabled = $display->handler->get_option('enabled'); | ||||
|  | ||||
|   if (!$is_display_deleted && $is_deletable && !$is_default) { | ||||
|     $prefix = '<div class="ctools-no-js ctools-button ctools-dropbutton"><div class="ctools-link"><a href="#" class="ctools-twisty ctools-text">open</a></div><div class="ctools-content"><ul class="horizontal right actions">'; | ||||
|     $prefix = '<div class="ctools-no-js ctools-button ctools-dropbutton"><div class="ctools-link"><a href="#" class="ctools-twisty ctools-text"><span class="element-invisible">open</span></a></div><div class="ctools-content"><ul class="horizontal right actions">'; | ||||
|     $suffix = '</ul></div></div>'; | ||||
|     $item_element = 'li'; | ||||
|   } | ||||
| @@ -2987,6 +2987,10 @@ function views_ui_add_form_to_stack($key, &$view, $display_id, $args, $top = FAL | ||||
|  * together. | ||||
|  */ | ||||
| function views_ui_ajax_form($js, $key, $view, $display_id = '') { | ||||
|   $args = func_get_args(); | ||||
|   // Remove the known args. | ||||
|   array_splice($args, 0, 4); | ||||
|  | ||||
|   // Reset the cache of IDs. Drupal rather aggressively prevents id duplication | ||||
|   // but this causes it to remember IDs that are no longer even being used. | ||||
|   if (isset($_POST['ajax_html_ids'])) { | ||||
| @@ -2999,9 +3003,6 @@ function views_ui_ajax_form($js, $key, $view, $display_id = '') { | ||||
|   } | ||||
|  | ||||
|   views_include('ajax'); | ||||
|   $args = func_get_args(); | ||||
|   // Remove the known args. | ||||
|   array_splice($args, 0, 4); | ||||
|  | ||||
|   $form_state = views_ui_build_form_state($js, $key, $view, $display_id, $args); | ||||
|   // check to see if this is the top form of the stack. If it is, pop | ||||
| @@ -3044,6 +3045,11 @@ function views_ui_ajax_form($js, $key, $view, $display_id = '') { | ||||
|       $stack = $view->stack; | ||||
|       $top = array_shift($stack); | ||||
|       $top[0] = $js; | ||||
|  | ||||
|       // Change view into a reference. | ||||
|       $stepview = $top[2]; | ||||
|       $top[2] = &$stepview; | ||||
|  | ||||
|       $form_state = call_user_func_array('views_ui_build_form_state', $top); | ||||
|       $form_state['input'] = array(); | ||||
|       $form_state['url'] = url(views_ui_build_form_url($form_state)); | ||||
| @@ -3165,7 +3171,7 @@ function views_ui_reorder_displays_form($form, &$form_state) { | ||||
|   $form['#title'] = t('Displays Reorder'); | ||||
|   $form['#section'] = 'reorder'; | ||||
|  | ||||
|   // Add javascript settings that will be added via $.extend for tabledragging. | ||||
|   // Add JavaScript settings that will be added via $.extend for tabledragging. | ||||
|   $form['#js']['tableDrag']['reorder-displays']['weight'][0] = array( | ||||
|     'target' => 'weight', | ||||
|     'source' => NULL, | ||||
| @@ -3548,7 +3554,7 @@ function views_ui_rearrange_form($form, &$form_state) { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   // Add javascript settings that will be added via $.extend for tabledragging. | ||||
|   // Add JavaScript settings that will be added via $.extend for tabledragging. | ||||
|   $form['#js']['tableDrag']['arrange']['weight'][0] = array( | ||||
|     'target' => 'weight', | ||||
|     'source' => NULL, | ||||
| @@ -5036,7 +5042,7 @@ function views_ui_admin_settings_advanced() { | ||||
|   $form['debug']['views_no_javascript'] = array( | ||||
|     '#type' => 'checkbox', | ||||
|     '#title' => t('Disable JavaScript with Views'), | ||||
|     '#description' => t("If you are having problems with the JavaScript, you can disable it here. The Views UI should degrade and still be usable without javascript; it's just not as good."), | ||||
|     '#description' => t("If you are having problems with the JavaScript, you can disable it here. The Views UI should degrade and still be usable without JavaScript; it's just not as good."), | ||||
|     '#default_value' => variable_get('views_no_javascript', FALSE), | ||||
|   ); | ||||
|  | ||||
|   | ||||
| @@ -18,8 +18,8 @@ function views_ajax() { | ||||
|   if (isset($_REQUEST['view_name']) && isset($_REQUEST['view_display_id'])) { | ||||
|     $name = $_REQUEST['view_name']; | ||||
|     $display_id = $_REQUEST['view_display_id']; | ||||
|     $args = isset($_REQUEST['view_args']) && $_REQUEST['view_args'] !== '' ? explode('/', $_REQUEST['view_args']) : array(); | ||||
|     $path = isset($_REQUEST['view_path']) ? rawurldecode($_REQUEST['view_path']) : NULL; | ||||
|     $args = isset($_REQUEST['view_args']) && $_REQUEST['view_args'] !== '' ? explode('/', htmlspecialchars_decode($_REQUEST['view_args'], ENT_QUOTES)) : array(); | ||||
|     $path = isset($_REQUEST['view_path']) ? htmlspecialchars_decode($_REQUEST['view_path'], ENT_QUOTES) : NULL; | ||||
|     $dom_id = isset($_REQUEST['view_dom_id']) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $_REQUEST['view_dom_id']) : NULL; | ||||
|     $pager_element = isset($_REQUEST['pager_element']) ? intval($_REQUEST['pager_element']) : NULL; | ||||
|  | ||||
| @@ -72,7 +72,8 @@ function views_ajax() { | ||||
|       // Reuse the same DOM id so it matches that in Drupal.settings. | ||||
|       $view->dom_id = $dom_id; | ||||
|  | ||||
|       $commands[] = ajax_command_replace('.view-dom-id-' . $dom_id, $view->preview($display_id, $args)); | ||||
|       // Always return HTML with the same DOM ID that was sent by the browser. | ||||
|       $commands[] = ajax_command_replace('.view-dom-id-' . $dom_id, preg_replace('/view-dom-id-[a-zA-Z0-9_-]+/', 'view-dom-id-' . $view->dom_id, $view->preview($display_id, $args), 1)); | ||||
|     } | ||||
|     drupal_alter('views_ajax_data', $commands, $view); | ||||
|     return array('#type' => 'ajax', '#commands' => $commands); | ||||
|   | ||||
| @@ -278,6 +278,9 @@ class views_handler extends views_object { | ||||
|       return $title; | ||||
|     } | ||||
|     $title = ($short && isset($this->definition['title short'])) ? $this->definition['title short'] : $this->definition['title']; | ||||
|     if (empty($this->definition['group'])) { | ||||
|       return $title; | ||||
|     } | ||||
|     return t('!group: !title', array('!group' => $this->definition['group'], '!title' => $title)); | ||||
|   } | ||||
|  | ||||
| @@ -418,8 +421,10 @@ class views_handler extends views_object { | ||||
|       '#collapsed' => TRUE, | ||||
|       '#weight' => 150, | ||||
|     ); | ||||
|  | ||||
|     // Allow to alter the default values brought into the form. | ||||
|     drupal_alter('views_handler_options', $this->options, $view); | ||||
|     // Triggers hook_views_handler_options_alter(). | ||||
|     drupal_alter('views_handler_options', $this->options, $this); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
| @@ -1001,7 +1006,8 @@ class views_many_to_one_helper { | ||||
|  | ||||
|       // Clone the join for each table: | ||||
|       $this->handler->table_aliases = array(); | ||||
|       foreach ($this->handler->value as $value) { | ||||
|       $values = $this->handler->operator === 'not' ? array($this->handler->value) : $this->handler->value; | ||||
|       foreach ($values as $value) { | ||||
|         $join = $this->get_join(); | ||||
|         if ($this->handler->operator == 'and') { | ||||
|           $join->type = 'INNER'; | ||||
| @@ -1014,6 +1020,9 @@ class views_many_to_one_helper { | ||||
|           'value' => $value, | ||||
|           'numeric' => !empty($this->handler->definition['numeric']), | ||||
|         ); | ||||
|         if (($this->handler->is_a_group() && is_array($value)) || $this->handler->operator === 'not') { | ||||
|           $value = serialize($value); | ||||
|         } | ||||
|         // The table alias needs to be unique to this value across the | ||||
|         // multiple times the filter or argument is called by the view. | ||||
|         if (!isset($this->handler->view->many_to_one_aliases[$field][$value])) { | ||||
| @@ -1028,6 +1037,9 @@ class views_many_to_one_helper { | ||||
|             $this->handler->table_alias = $alias; | ||||
|           } | ||||
|         } | ||||
|         else { | ||||
|           $this->handler->table_aliases[$value] = $this->handler->view->many_to_one_aliases[$field][$value]; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return $this->handler->table_alias; | ||||
| @@ -1068,7 +1080,12 @@ class views_many_to_one_helper { | ||||
|       } | ||||
|       else { | ||||
|         $value = is_array($value) ? array_pop($value) : $value; | ||||
|         $operator = '='; | ||||
|         if (is_array($value) && count($value) > 1) { | ||||
|           $operator = 'IN'; | ||||
|         } | ||||
|         else { | ||||
|           $operator = '='; | ||||
|         } | ||||
|       } | ||||
|       $add_condition = FALSE; | ||||
|     } | ||||
| @@ -1675,15 +1692,18 @@ class views_join { | ||||
|           } | ||||
|  | ||||
|           if (is_array($info['value'])) { | ||||
|             $value_placeholders = array(); | ||||
|  | ||||
|             // With an array of values, we need multiple placeholders and the | ||||
|             // 'IN' operator is implicit. | ||||
|             foreach ($info['value'] as $value) { | ||||
|               $placeholder_i = $view_query->placeholder('views_join_condition_'); | ||||
|               $value_placeholders[] = $placeholder_i; | ||||
|               $arguments[$placeholder_i] = $value; | ||||
|             } | ||||
|  | ||||
|             $operator = !empty($info['operator']) ? $info['operator'] : 'IN'; | ||||
|             $placeholder = '( ' . implode(', ', array_keys($arguments)) . ' )'; | ||||
|             $placeholder = '( ' . implode(', ', $value_placeholders) . ' )'; | ||||
|           } | ||||
|           else { | ||||
|             // With a single value, the '=' operator is implicit. | ||||
|   | ||||
| @@ -843,7 +843,11 @@ class view extends views_db_object { | ||||
|  | ||||
|       $argument->set_relationship(); | ||||
|  | ||||
|       $arg = isset($this->args[$position]) ? $this->args[$position] : NULL; | ||||
|       $arg = NULL; | ||||
|       if (isset($this->args[$position]) && $this->args[$position] !== '') { | ||||
|         $arg = $this->args[$position]; | ||||
|       } | ||||
|  | ||||
|       $argument->position = $position; | ||||
|  | ||||
|       if (isset($arg) || $argument->has_default_argument()) { | ||||
| @@ -1575,7 +1579,7 @@ class view extends views_db_object { | ||||
|   /** | ||||
|    * Override the view's current title. | ||||
|    * | ||||
|    * The tokens in the title get's replaced before rendering. | ||||
|    * The tokens in the title get replaced before rendering. | ||||
|    */ | ||||
|   public function set_title($title) { | ||||
|     $this->build_info['title'] = $title; | ||||
| @@ -2008,7 +2012,7 @@ class view extends views_db_object { | ||||
|   public function clone_view() { | ||||
|     $clone = clone $this; | ||||
|  | ||||
|     $keys = array('current_display', 'display_handler', 'build_info', 'built', 'executed', 'attachment_before', 'attachment_after', 'field', 'argument', 'filter', 'sort', 'relationship', 'header', 'footer', 'empty', 'query', 'inited', 'style_plugin', 'plugin_name', 'exposed_data', 'exposed_input', 'exposed_widgets', 'many_to_one_tables', 'feed_icon'); | ||||
|     $keys = array('current_display', 'display_handler', 'build_info', 'built', 'executed', 'attachment_before', 'attachment_after', 'field', 'argument', 'filter', 'sort', 'relationship', 'header', 'footer', 'empty', 'query', 'inited', 'style_plugin', 'plugin_name', 'exposed_data', 'exposed_input', 'exposed_widgets', 'many_to_one_aliases', 'many_to_one_tables', 'feed_icon'); | ||||
|     foreach ($keys as $key) { | ||||
|       if (isset($clone->{$key})) { | ||||
|         unset($clone->{$key}); | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|   Drupal.views.instances = {}; | ||||
|  | ||||
|   /** | ||||
|    * Javascript object for a certain view. | ||||
|    * JavaScript object for a certain view. | ||||
|    */ | ||||
|   Drupal.views.ajaxView = function(settings) { | ||||
|     var selector = '.view-dom-id-' + settings.view_dom_id; | ||||
| @@ -69,9 +69,6 @@ | ||||
|  | ||||
|     // Add the ajax to pagers. | ||||
|     this.$view | ||||
|     // Don't attach to nested views. Doing so would attach multiple behaviors | ||||
|     // to a given element. | ||||
|       .filter(jQuery.proxy(this.filterNestedViews, this)) | ||||
|       .once(jQuery.proxy(this.attachPagerAjax, this)); | ||||
|  | ||||
|     // Add a trigger to update this view specifically. In order to trigger a | ||||
| @@ -100,12 +97,6 @@ | ||||
|     this.exposedFormAjax = new Drupal.ajax($(button).attr('id'), button, this.element_settings); | ||||
|   }; | ||||
|  | ||||
|   Drupal.views.ajaxView.prototype.filterNestedViews = function() { | ||||
|     // If there is at least one parent with a view class, this view | ||||
|     // is nested (e.g., an attachment). Bail. | ||||
|     return !this.$view.parents('.view').length; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * Attach the ajax behavior to each link. | ||||
|    */ | ||||
| @@ -119,8 +110,20 @@ | ||||
|    */ | ||||
|   Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function(id, link) { | ||||
|     var $link = $(link); | ||||
|     // Don't attach to pagers inside nested views. | ||||
|     if ($link.closest('.view')[0] !== this.$view[0]) { | ||||
|       return; | ||||
|     } | ||||
|     var viewData = {}; | ||||
|     var href = $link.attr('href'); | ||||
|  | ||||
|     // Provide a default page if none has been set. This must be done | ||||
|     // prior to merging with settings to avoid accidentally using the | ||||
|     // page landed on instead of page 1. | ||||
|     if (typeof(viewData.page) === 'undefined') { | ||||
|       viewData.page = 0; | ||||
|     } | ||||
|  | ||||
|     // Construct an object using the settings defaults and then overriding | ||||
|     // with data specific to the link. | ||||
|     $.extend( | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
|  * @see views_ui.module | ||||
|  * @see js/jquery.ui.dialog.min.js | ||||
|  * | ||||
|  * This javascript patch overwrites the $.ui.dialog.overlay.events object to remove | ||||
|  * This JavaScript patch overwrites the $.ui.dialog.overlay.events object to remove | ||||
|  * the mousedown, mouseup and click events from the list of events that are bound | ||||
|  * in $.ui.dialog.overlay.create | ||||
|  * | ||||
|   | ||||
| @@ -981,11 +981,11 @@ Drupal.viewsUi.resizeModal = function (e, no_shrink) { | ||||
|   var difference = 0; | ||||
|   difference += parseInt($scroll.css('padding-top')); | ||||
|   difference += parseInt($scroll.css('padding-bottom')); | ||||
|   difference += $('.views-override').outerHeight(true); | ||||
|   difference += $('.views-messages').outerHeight(true); | ||||
|   difference += $('#views-ajax-title').outerHeight(true); | ||||
|   difference += $('.views-add-form-selected').outerHeight(true); | ||||
|   difference += $('.form-buttons', $modal).outerHeight(true); | ||||
|   difference += $('.views-override').outerHeight(true) || 0; | ||||
|   difference += $('.views-messages').outerHeight(true) || 0; | ||||
|   difference += $('#views-ajax-title').outerHeight(true) || 0; | ||||
|   difference += $('.views-add-form-selected').outerHeight(true) || 0; | ||||
|   difference += $('.form-buttons', $modal).outerHeight(true) || 0; | ||||
|  | ||||
|   height = scrollHeight + difference; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /** | ||||
|  * @file | ||||
|  * Javascript related to contextual links. | ||||
|  * JavaScript related to contextual links. | ||||
|  */ | ||||
| (function ($) { | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /** | ||||
|  * @file | ||||
|  * Javascript related to the main view list. | ||||
|  * JavaScript related to the main view list. | ||||
|  */ | ||||
| (function ($) { | ||||
|  | ||||
|   | ||||
| @@ -11,12 +11,12 @@ | ||||
| class views_plugin_row_aggregator_rss extends views_plugin_row { | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public $base_table = 'aggregator_item'; | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public $base_field = 'iid'; | ||||
|  | ||||
| @@ -52,8 +52,8 @@ class views_plugin_row_aggregator_rss extends views_plugin_row { | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function render($row) { | ||||
|     $iid =  $row->{$this->field_alias}; | ||||
|     $sql =  "SELECT ai.iid, ai.fid, ai.title, ai.link, ai.author, ai.description, "; | ||||
|     $iid = $row->{$this->field_alias}; | ||||
|     $sql = "SELECT ai.iid, ai.fid, ai.title, ai.link, ai.author, ai.description, "; | ||||
|     $sql .= "ai.timestamp, ai.guid, af.title AS feed_title, ai.link AS feed_LINK "; | ||||
|     $sql .= "FROM {aggregator_item} ai LEFT JOIN {aggregator_feed} af ON ai.fid = af.fid "; | ||||
|     $sql .= "WHERE ai.iid = :iid"; | ||||
| @@ -72,7 +72,7 @@ class views_plugin_row_aggregator_rss extends views_plugin_row { | ||||
|       array( | ||||
|         'key' => 'guid', | ||||
|         'value' => $item->guid, | ||||
|         'attributes' => array('isPermaLink' => 'false') | ||||
|         'attributes' => array('isPermaLink' => 'false'), | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
| @@ -85,7 +85,7 @@ class views_plugin_row_aggregator_rss extends views_plugin_row { | ||||
|     return theme($this->theme_functions(), array( | ||||
|       'view' => $this->view, | ||||
|       'options' => $this->options, | ||||
|       'row' => $item | ||||
|       'row' => $item, | ||||
|     )); | ||||
|   } | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user