You are here

lang_dropdown.module in Language Switcher Dropdown 7

File

lang_dropdown.module
View source
<?php

define('CHOSEN_WEB_URL', 'http://harvesthq.github.com/chosen');

/**
 * Implements hook_help().
 */
function lang_dropdown_help($path, $arg) {
  switch ($path) {
    case 'admin/help#lang_dropdown':
      $output = '<p>' . t('The module will populate a new block named "Language switcher dropdown" under <a href="@block_admin">blocks admin page</a>.', array(
        '@block_admin' => check_plain(url('admin/structure/block')),
      )) . '</p>';
      $output .= '<p>' . t('For more information on blocks, please see <a href="@blocks_help">block help section</a>.', array(
        '@blocks_help' => check_plain(url('admin/help/block')),
      )) . '</p>';
      $output .= '<p>' . t('The module Provides same functionality as the core language switcher block but with a better look&feel.') . '</p>';
      $output .= '<p>' . t('For more information on multilingual sites, please see <a href="@locale_help">locale help section</a>.', array(
        '@locale_help' => check_plain(url('admin/help/locale')),
      )) . '</p>';
      return $output;
    case 'admin/structure/block/manage/%/%':
      if ($arg[4] == 'lang_dropdown') {
        return '<p>' . t('This block is only shown if <a href="@languages">at least two languages are enabled</a> and <a href="@configuration">language negotiation</a> is set to <em>URL</em> or <em>Session</em>.', array(
          '@languages' => url('admin/config/regional/language'),
          '@configuration' => url('admin/config/regional/language/configure'),
        )) . '</p>';
      }
      break;
  }
}

/**
 * Implements hook_block_info().
 */
function lang_dropdown_block_info() {
  include_once DRUPAL_ROOT . '/includes/language.inc';
  $block = array();
  $info = language_types_info();
  foreach (language_types_configurable(FALSE) as $type) {
    $block[$type] = array(
      'info' => t('Language switcher dropdown (@type)', array(
        '@type' => $info[$type]['name'],
      )),
      'cache' => DRUPAL_NO_CACHE,
    );
  }
  return $block;
}

/**
 * Implements hook_block_configure().
 */
function lang_dropdown_block_configure($delta = '') {
  $settings = _lang_dropdown_get_settings($delta);
  $form = array();
  $form['lang_dropdown'] = array(
    '#type' => 'fieldset',
    '#title' => t('Language switcher dropdown settings'),
    '#weight' => 0,
  );
  $form['lang_dropdown']['showall'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show all enabled languages'),
    '#description' => t('Show all languages in the switcher no matter if there is a translation for the node or not. For languages without translation the switcher will redirect to homepage.'),
    '#default_value' => $settings['showall'],
  );
  $form['lang_dropdown']['tohome'] = array(
    '#type' => 'checkbox',
    '#title' => t('Redirect to home on switch'),
    '#description' => t('When you change language the switcher will redirect to homepage.'),
    '#default_value' => $settings['tohome'],
  );
  $form['lang_dropdown']['width'] = array(
    '#type' => 'textfield',
    '#title' => t('Width of dropdown element'),
    '#size' => 5,
    '#maxlength' => 3,
    '#required' => TRUE,
    '#field_suffix' => 'px',
    '#default_value' => $settings['js_widget_settings']['width'],
  );
  $form['lang_dropdown']['js_widget'] = array(
    '#type' => 'select',
    '#title' => t('Output type'),
    '#options' => array(
      '0' => t('Simple HTML select'),
      '1' => t('Marghoob Suleman Dropdown jquery library'),
      '2' => t('Chosen jquery library'),
    ),
    '#description' => t('This looks better with <a href="!href">Language icons</a> module.', array(
      '!href' => 'http://drupal.org/project/languageicons',
    )),
    '#default_value' => $settings['js_widget'],
    '#element_validate' => array(
      '_lang_dropdown_validate_output_value',
    ),
  );
  $form['lang_dropdown']['mssettings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Marghoob Suleman Dropdown Settings'),
    '#weight' => 1,
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
      ),
    ),
  );
  $num_rows = array(
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
  );
  $form['lang_dropdown']['mssettings']['visible_rows'] = array(
    '#type' => 'select',
    '#title' => t('Maximum number of visible rows'),
    '#options' => array_combine($num_rows, $num_rows),
    '#default_value' => $settings['js_widget_settings']['visible_rows'],
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
      ),
    ),
  );
  $form['lang_dropdown']['mssettings']['rounded'] = array(
    '#type' => 'checkbox',
    '#title' => t('Rounded corners.'),
    '#default_value' => $settings['js_widget_settings']['rounded'],
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
      ),
    ),
  );
  $form['lang_dropdown']['mssettings']['animation'] = array(
    '#type' => 'select',
    '#title' => t('Animation style for dropdown'),
    '#options' => array(
      'slideDown' => t('Slide down'),
      'fadeIn' => t('Fade in'),
      'show' => t('Show'),
    ),
    '#default_value' => $settings['js_widget_settings']['animation'],
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
      ),
    ),
  );
  $form['lang_dropdown']['mssettings']['event'] = array(
    '#type' => 'select',
    '#title' => t('Event that opens the menu'),
    '#options' => array(
      'click' => t('Click'),
      'mouseover' => t('Mouse Over'),
    ),
    '#default_value' => $settings['js_widget_settings']['event'],
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
      ),
    ),
  );
  $skinOptions = array();
  foreach (_lang_dropdown_get_skins() as $key => $value) {
    $skinOptions[$key] = $value['text'];
  }
  $form['lang_dropdown']['mssettings']['skin'] = array(
    '#type' => 'select',
    '#title' => t('Skin'),
    '#options' => $skinOptions,
    '#default_value' => $settings['js_widget_settings']['skin'],
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
      ),
    ),
  );
  $form['lang_dropdown']['mssettings']['custom_skin'] = array(
    '#type' => 'textfield',
    '#title' => t('Custom skin'),
    '#size' => 80,
    '#maxlength' => 55,
    '#default_value' => $settings['js_widget_settings']['custom_skin'],
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 1,
        ),
        ':input[name="skin"]' => array(
          'value' => 'custom',
        ),
      ),
    ),
  );
  $form['lang_dropdown']['languageicons'] = array(
    '#type' => 'fieldset',
    '#title' => t('Language icons settings'),
    '#weight' => 1,
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 0,
        ),
      ),
    ),
  );
  if (module_exists('languageicons')) {
    $form['lang_dropdown']['languageicons']['flag_position'] = array(
      '#type' => 'select',
      '#title' => t('Position of the flag when the dropdown is show just as a select'),
      '#options' => array(
        0 => t('Before'),
        1 => t('After'),
      ),
      '#default_value' => $settings['languageicons']['flag_position'],
    );
  }
  else {
    $form['lang_dropdown']['languageicons']['#description'] = t('Enable <a href="!href">Language icons</a> to enhance the Language dropdown widget.', array(
      '!href' => 'http://drupal.org/project/languageicons',
    ));
  }
  $form['lang_dropdown']['chosen'] = array(
    '#type' => 'fieldset',
    '#title' => t('Chosen settings'),
    '#weight' => 1,
    '#states' => array(
      'visible' => array(
        ':input[name="js_widget"]' => array(
          'value' => 2,
        ),
      ),
    ),
  );
  if (module_exists('chosen')) {
    $form['lang_dropdown']['chosen']['#description'] = t('If you are already using the chosen module you must just choose to output language dropdown as a simple HTML select and allow chosen module to turn it into a chosen style select.');
  }
  else {
    if (_get_chosen_path()) {
      $form['lang_dropdown']['chosen']['disable_search'] = array(
        '#type' => 'checkbox',
        '#title' => t('Disable select box'),
        '#default_value' => $settings['chosen']['disable_search'],
      );
      $form['lang_dropdown']['chosen']['no_results_text'] = array(
        '#type' => 'textfield',
        '#title' => t('No Result Text'),
        '#description' => t('Text to show when no result is found on search.'),
        '#default_value' => $settings['chosen']['no_results_text'],
        '#states' => array(
          'visible' => array(
            ':input[name="disable_search"]' => array(
              'checked' => FALSE,
            ),
          ),
        ),
      );
    }
    else {
      $form['lang_dropdown']['chosen']['#description'] = t('You need to download the !chosen and extract the entire contents of the archive into the %path directory on your server.', array(
        '!chosen' => l(t('Chosen JavaScript file'), CHOSEN_WEB_URL),
        '%path' => 'sites/all/libraries',
      ));
    }
  }
  return $form;
}

/**
 * Validates output value
 */
function _lang_dropdown_validate_output_value($element, &$form_state, $form) {
  if ($element['#value'] == 2 && module_exists('chosen')) {
    form_error($element, t('You can\'t use chosen output directly on language dropdown switcher. You have chosen module installed. Use simple HTML select as output and chosen module will render it with the chosen library.'));
  }
  else {
    if ($element['#value'] == 2 && !_get_chosen_path()) {
      form_error($element, t('You can\'t use chosen output. You don\'t have chosen library installed.'));
    }
  }
}

/**
 * Implements hook_block_save().
 */
function lang_dropdown_block_save($delta = '', $edit = array()) {
  $lang_dropdown_settings = array(
    'showall' => $edit['showall'],
    'tohome' => $edit['tohome'],
    'js_widget' => $edit['js_widget'],
    'js_widget_settings' => array(
      'visible_rows' => $edit['visible_rows'],
      'width' => $edit['width'],
      'rounded' => $edit['rounded'],
      'animation' => $edit['animation'],
      'event' => $edit['event'],
      'skin' => $edit['skin'],
      'custom_skin' => $edit['custom_skin'],
    ),
    'chosen' => array(
      'disable_search' => $edit['disable_search'],
      'no_results_text' => $edit['no_results_text'],
    ),
    'languageicons' => array(
      'flag_position' => 1,
    ),
  );
  if (module_exists('languageicons')) {
    $lang_dropdown_settings['languageicons']['flag_position'] = $edit['flag_position'];
  }
  variable_set('lang_dropdown_' . $delta, $lang_dropdown_settings);
}

/**
 * Implements hook_block_view().
 */
function lang_dropdown_block_view($type = 'language') {
  if (drupal_multilingual()) {
    $path = drupal_is_front_page() ? '<front>' : $_GET['q'];
    $languages = language_negotiation_get_switch_links($type, $path);
    if (!empty($languages->links)) {
      $block['content'] = drupal_get_form('lang_dropdown_form', $languages, $type);
      $block['subject'] = t('Languages');
      return $block;
    }
  }
}

/**
 * Function to build the select widget form.
 */
function lang_dropdown_form($form, &$form_state, $languages, $type) {
  global $language_url;
  $settings = _lang_dropdown_get_settings($type);
  if ($settings['js_widget'] == 2 && !_get_chosen_path()) {
    return array();
  }
  $module_path = drupal_get_path('module', 'lang_dropdown');
  $options = $js_settings = $hidden_elements = array();
  $selected_option_language_icon = '';
  $hidden_elements['lang_dropdown_type'] = array(
    '#type' => 'hidden',
    '#default_value' => check_plain($type),
  );
  $language_names = locale_language_list('native');

  // Support Domain access
  if ($domain_locale_exists = module_exists('domain_locale')) {
    global $_domain;
    $domain_languages = domain_locale_lookup($_domain['domain_id']);
  }

  // Now we iterate on $languages to build the needed options for the select element.
  foreach ($languages->links as $lang_code => $lang_options) {

    // language icons module add language when negotiation is session so be careful
    // we need to get rid of that language icons bug by checking for native property
    $language_object = isset($lang_options['language']) && isset($lang_options['language']->native) ? $lang_options['language'] : NULL;

    // The language is not enabled on this domain
    if ($domain_locale_exists && !array_key_exists($lang_code, $domain_languages)) {
      continue;
    }

    // There is no translation for this language and not all languages are shown
    if (!isset($lang_options['href']) && !$settings['showall']) {
      continue;
    }

    // Build the options in an assosiative array, so it will be ready for #options in select form element.
    $options += array(
      $lang_code => $language_names[$lang_code],
    );

    // Set the selected option to be ready for #default_value in select form element.
    if (isset($lang_options['href']) && ($lang_options['href'] == $_GET['q'] || $lang_options['href'] == '<front>' && drupal_is_front_page()) && (empty($lang_options['language']) || $lang_options['language']->language == $language_url->language)) {
      $selected_option = $lang_code;

      // Icon for the selected language
      if (module_exists('languageicons') && !$settings['js_widget']) {
        $selected_option_language_icon = theme('languageicons_icon', array(
          'language' => (object) array(
            'language' => $lang_code,
          ),
          'title' => $language_names[$lang_code],
        ));
      }
    }

    // Now we build our hidden form inputs to handle the redirections.
    $href = isset($lang_options['href']) && $settings['tohome'] == 0 ? $lang_options['href'] : '<front>';
    $hidden_elements[$lang_code] = array(
      '#type' => 'hidden',
      '#default_value' => check_plain(url($href, array(
        'language' => $language_object,
        'query' => isset($lang_options['query']) ? $lang_options['query'] : '',
      ))),
    );

    // Handle flags with Language icons module using JS widget.
    if (module_exists('languageicons') && $settings['js_widget']) {
      $languageicons_path = variable_get('languageicons_path', drupal_get_path('module', 'languageicons') . '/flags/*.png');
      $js_settings['languageicons'][$lang_code] = file_create_url(str_replace('*', $lang_code, $languageicons_path));
    }
  }

  // Add required files and settings for JS widget.
  if ($settings['js_widget'] == 1) {
    drupal_add_js($module_path . '/msdropdown/js/msdropdown/jquery.dd.min.js');
    $js_settings += array(
      'widget' => 'msdropdown',
      'visibleRows' => $settings['js_widget_settings']['visible_rows'],
      'roundedCorner' => $settings['js_widget_settings']['rounded'],
      'animStyle' => $settings['js_widget_settings']['animation'],
      'event' => $settings['js_widget_settings']['event'],
    );
    drupal_add_css($module_path . '/msdropdown/css/msdropdown/dd.css');
    $selected_skin = $settings['js_widget_settings']['skin'];
    if ($selected_skin == 'custom') {
      $custom_skin = check_plain($settings['js_widget_settings']['custom_skin']);
      drupal_add_css($module_path . '/msdropdown/css/msdropdown/' . $custom_skin . '.css');
      $js_settings += array(
        'mainCSS' => $custom_skin,
      );
    }
    else {
      $skins = _lang_dropdown_get_skins();
      $skin_data = $skins[$selected_skin];
      drupal_add_css($skin_data['file']);
      $js_settings += array(
        'mainCSS' => $skin_data['mainCSS'],
      );
    }
    drupal_add_js(array(
      'lang_dropdown' => array(
        $type => array(
          'jsWidget' => $js_settings,
        ),
      ),
    ), 'setting');
  }
  else {
    if ($settings['js_widget'] == 2) {
      drupal_add_library('lang_dropdown', 'chosen');
      $js_settings += array(
        'widget' => 'chosen',
        'disable_search' => $settings['chosen']['disable_search'],
        'no_results_text' => $settings['chosen']['no_results_text'],
      );
      drupal_add_js(array(
        'lang_dropdown' => array(
          $type => array(
            'jsWidget' => $js_settings,
          ),
        ),
      ), 'setting');
    }
  }
  $settings['languageicons']['flag_position'] ? $flag_position = '#suffix' : ($flag_position = '#prefix');

  // Now we build the $form array.
  $form['lang_dropdown_select'] = array(
    '#type' => 'select',
    '#default_value' => isset($selected_option) ? $selected_option : key($options),
    '#options' => $options,
    '#attributes' => array(
      'style' => 'width:' . $settings['js_widget_settings']['width'] . 'px',
      'class' => array(
        'lang-dropdown-select-element',
      ),
      'id' => 'lang-dropdown-select-' . $type,
    ),
    '#attached' => array(
      'js' => array(
        $module_path . '/lang_dropdown.js',
      ),
      'css' => $settings['js_widget'] ? array() : array(
        $module_path . '/lang_dropdown.css',
      ),
    ),
  );
  if (empty($hidden_elements)) {
    return array();
  }
  $form += $hidden_elements;
  if (module_exists('languageicons')) {
    $form['lang_dropdown_select'][$flag_position] = $selected_option_language_icon;
  }
  $form['#attributes']['class'] = array(
    'lang_dropdown_form',
    $type,
  );
  $form['#attributes']['id'] = 'lang_dropdown_form_' . $type;
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Go'),
    // The below prefix & suffix for gracefull fallback if JavaScript was disabled
    '#prefix' => "<noscript><div>\n",
    '#suffix' => "\n</div></noscript>",
  );
  return $form;
}

/**
 * Handles graceful degrade when JS is disabled.
 */
function lang_dropdown_form_submit($form, &$form_state) {
  $language_code = check_plain($form_state['values']['lang_dropdown_select']);
  $type = check_plain($form_state['values']['lang_dropdown_type']);
  $language_codes = locale_language_list('language');
  if (!in_array($language_code, $language_codes)) {
    return;
  }
  $types = language_types_configurable(FALSE);
  if (!in_array($type, $types)) {
    $type = 'language';
  }
  $path = drupal_is_front_page() ? '<front>' : $_GET['q'];
  $languages = language_negotiation_get_switch_links($type, $path);
  $language = $languages->links[$language_code];
  $newpath = isset($language['href']) ? $language['href'] : '<front>';

  // language icons module add language when negotiation is session so be careful
  // we need to get rid of that language icons bug by checking for native property
  $language_object = isset($language['language']) && isset($language['language']->native) ? $language['language'] : NULL;
  drupal_goto($newpath, array(
    'language' => $language_object,
    'query' => isset($language['query']) ? $language['query'] : '',
  ));
}

/**
 * Helper function to get Language switcher dropdown settings
 */
function _lang_dropdown_get_settings($type, $settings = NULL) {
  $defaults = array(
    'showall' => 0,
    'tohome' => 0,
    'js_widget' => 1,
    'js_widget_settings' => array(
      'visible_rows' => 5,
      'width' => 165,
      'rounded' => 1,
      'animation' => 'slideDown',
      'event' => 'click',
      'skin' => 'ldsSkin',
      'custom_skin' => '',
    ),
    'chosen' => array(
      'disable_search' => 1,
      'no_results_text' => 'No language match',
    ),
    'languageicons' => array(
      'flag_position' => 1,
    ),
  );
  return array_replace_recursive(array_replace_recursive($defaults, variable_get('lang_dropdown', $defaults)), variable_get('lang_dropdown_' . $type, $defaults));
}

/**
 * Helper function to handle skins data
 */
function _lang_dropdown_get_skins() {
  $module_path = drupal_get_path('module', 'lang_dropdown');
  return array(
    'ldsSkin' => array(
      'text' => t('Default skin'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsSkin.css',
      'mainCSS' => 'ldsSkin',
    ),
    'ldsSkinAfter' => array(
      'text' => t('Default skin, icon right'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsSkin.css',
      'mainCSS' => 'ldsSkinAfter',
    ),
    'ldsSkinNoIcon' => array(
      'text' => t('Default skin, no icon'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsSkin.css',
      'mainCSS' => 'ldsSkinNoIcon',
    ),
    'ldsSkinNoLabel' => array(
      'text' => t('Default skin, no label'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsSkin.css',
      'mainCSS' => 'ldsSkinNoLabel',
    ),
    'ldsDark' => array(
      'text' => t('Dark skin'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsDark.css',
      'mainCSS' => 'ldsDark',
    ),
    'ldsDarkAfter' => array(
      'text' => t('Dark skin, icon right'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsDark.css',
      'mainCSS' => 'ldsDarkAfter',
    ),
    'ldsDarkNoIcon' => array(
      'text' => t('Dark skin, no icon'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsDark.css',
      'mainCSS' => 'ldsDarkNoIcon',
    ),
    'ldsDarkNoLabel' => array(
      'text' => t('Dark skin, no label'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsDark.css',
      'mainCSS' => 'ldsDarkNoLabel',
    ),
    'ldsBlue' => array(
      'text' => t('Blue skin'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsBlue.css',
      'mainCSS' => 'ldsBlue',
    ),
    'ldsBlueAfter' => array(
      'text' => t('Blue skin, icon right'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsBlue.css',
      'mainCSS' => 'ldsBlueAfter',
    ),
    'ldsBlueNoIcon' => array(
      'text' => t('Blue skin, no icon'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsBlue.css',
      'mainCSS' => 'ldsBlueNoIcon',
    ),
    'ldsBlueNoLabel' => array(
      'text' => t('Blue skin, no label'),
      'file' => $module_path . '/msdropdown/css/msdropdown/ldsBlue.css',
      'mainCSS' => 'ldsBlueNoLabel',
    ),
    'custom' => array(
      'text' => t('Custom skin'),
      'file' => '',
      'mainCSS' => '',
    ),
  );
}

/**
 * Get the location of the chosen library.
 *
 * @return
 *   The location of the library, or FALSE if the library isn't installed.
 */
function _get_chosen_path() {
  $path = FALSE;
  if (function_exists('libraries_get_path')) {
    $path = libraries_get_path('chosen');
    if (!file_exists($path)) {
      $path = FALSE;
    }
  }
  elseif (file_exists('sites/all/libraries/chosen/chosen.jquery.min.js')) {
    $path = 'sites/all/libraries/chosen';
  }
  return $path;
}

/**
 * Implements hook_library().
 */
function lang_dropdown_library() {
  $chosen_library_path = module_exists('libraries') ? libraries_get_path('chosen') : 'sites/all/libraries/chosen';
  $info['chosen'] = array(
    'title' => 'Chosen',
    'website' => CHOSEN_WEB_URL,
    'version' => '1.0.0',
    'js' => array(
      $chosen_library_path . '/chosen.jquery.min.js' => array(
        'group' => 'JS_LIBRARY',
      ),
    ),
  );
  $info['chosen']['css'] = array(
    $chosen_library_path . '/chosen.css' => array(),
  );
  return $info;
}

Functions

Namesort descending Description
lang_dropdown_block_configure Implements hook_block_configure().
lang_dropdown_block_info Implements hook_block_info().
lang_dropdown_block_save Implements hook_block_save().
lang_dropdown_block_view Implements hook_block_view().
lang_dropdown_form Function to build the select widget form.
lang_dropdown_form_submit Handles graceful degrade when JS is disabled.
lang_dropdown_help Implements hook_help().
lang_dropdown_library Implements hook_library().
_get_chosen_path Get the location of the chosen library.
_lang_dropdown_get_settings Helper function to get Language switcher dropdown settings
_lang_dropdown_get_skins Helper function to handle skins data
_lang_dropdown_validate_output_value Validates output value

Constants

Namesort descending Description
CHOSEN_WEB_URL