Newer
Older
* This module extends multilingual support being the base module for the i18n package.
* - Multilingual variables
* - Extended languages for nodes
* - Extended language API
// All multilingual options disabled
define('I18N_LANGUAGE_DISABLED', 0);
// Language list will include all enabled languages
define('I18N_LANGUAGE_ENABLED', 1);
// Language list will include also disabled languages
define('I18N_LANGUAGE_EXTENDED', 4);
// Disabled languages will be hidden when possible
define('I18N_LANGUAGE_HIDDEN', 8);
// All defined languages will be allowed but hidden when possible
define('I18N_LANGUAGE_EXTENDED_NOT_DISPLAYED', I18N_LANGUAGE_EXTENDED | I18N_LANGUAGE_HIDDEN);
// No multilingual options
define('I18N_MODE_NONE', 0);
// Localizable object. Run through the localization system
define('I18N_MODE_LOCALIZE', 1);
// Predefined language for this object and all related ones.
define('I18N_MODE_LANGUAGE', 2);
// Multilingual objects, translatable but not localizable.
define('I18N_MODE_TRANSLATE', 4);
Jose Antonio Reyero del Prado
committed
// Objects are translatable (if they have language or localizable if not)
define('I18N_MODE_MULTIPLE', I18N_MODE_LOCALIZE | I18N_MODE_TRANSLATE);
Jose Antonio Reyero del Prado
committed
/**
* Implements hook_boot().
Jose Antonio Reyero del Prado
committed
*/
function i18n_boot() {
// Just make sure the module is loaded for boot and the API is available.
Jose Antonio Reyero del Prado
committed
}
Jose Antonio Reyero del Prado
committed
/**
* Implements hook_hook_info().
*/
function i18n_hook_info() {
$hooks['i18n_object_info'] = array(
'group' => 'i18n',
);
return $hooks;
}
* Get global language object, make sure it is initialized
* @param $language
* Language code or language object to convert to valid language object
function i18n_language($language = NULL) {
if ($language) {
if (is_object($language)) {
return $language;
}
else {
$list = language_list();
return isset($list[$language]) ? $list[$language] : i18n_language();
}
}
else {
if (empty($GLOBALS['language'])) {
// We don't have language yet, initialize the language system and retry
drupal_bootstrap(DRUPAL_BOOTSTRAP_LANGUAGE);
}
return $GLOBALS['language'];
Jose Antonio Reyero del Prado
committed
}
}
/**
* Get language selector form element
*/
function i18n_element_language_select($default = LANGUAGE_NONE) {
Jose Antonio Reyero del Prado
committed
if (is_object($default) || is_array($default)) {
$default = i18n_object_langcode($default, LANGUAGE_NONE);
}
return array(
'#type' => 'select',
'#title' => t('Language'),
'#default_value' => $default,
Jose Antonio Reyero del Prado
committed
'#options' => array(LANGUAGE_NONE => t('Language neutral')) + i18n_language_list(),
);
}
/**
* Get language field for hook_fields_extra_fields()
*/
function i18n_language_field_extra() {
return array(
'form' => array(
'language' => array(
'label' => t('Language'),
'description' => t('Language selection'),
'weight' => 0,
),
),
'display' => array(
'language' => array(
'label' => t('Language'),
'description' => t('Language'),
'weight' => 0,
),
),
);
}
Jose Antonio Reyero del Prado
committed
/**
* Get full language list
*
* @todo See about creating a permission for seeing disabled languages
Jose Antonio Reyero del Prado
committed
*/
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);
}
/**
* Get language name for any defined (enabled or not) language
*
* @see locale_language_list()
*/
function i18n_language_name($lang) {
$list = &drupal_static(__FUNCTION__);
if (!isset($list)) {
$list = locale_language_list('name', TRUE);
}
if (!$lang || $lang === LANGUAGE_NONE) {
return t('Undefined');
Jose Antonio Reyero del Prado
committed
}
elseif (isset($list[$lang])) {
return check_plain($list[$lang]);
}
else {
return t('Unknown');
}
}
/**
Jose Antonio Reyero del Prado
committed
* Get valid language code for current page or check whether the code is a defined language
*/
function i18n_langcode($langcode = NULL) {
return $langcode && $langcode !== LANGUAGE_NONE ? $langcode : i18n_language()->language;
}
* Implements hook_help().
Jose Antonio Reyero del Prado
committed
function i18n_help($path = 'admin/help#i18n', $arg) {
switch ($path) {
$output = '<p>' . t('This module improves support for multilingual content in Drupal sites:') . '</p>';
$output .= '<li>' . t('Shows content depending on page language.') . '</li>';
$output .= '<li>' . t('Handles multilingual variables.') . '</li>';
$output .= '<li>' . t('Extended language option for chosen content types. For these content types transations will be allowed for all defined languages, not only for enabled ones.') . '</li>';
$output .= '<li>' . t('Provides a block for language selection and two theme functions: <em>i18n_flags</em> and <em>i18n_links</em>.') . '</li>';
$output .= '<p>' . t('This is the base module for several others adding different features:') . '</p>';
$output .= '<li>' . t('Multilingual menu items.') . '</li>';
$output .= '<li>' . t('Multilingual taxonomy adds a language field for taxonomy vocabularies and terms.') . '</li>';
$output .= '<p>' . t('For more information, see the online handbook entry for <a href="@i18n">Internationalization module</a>.', array('@i18n' => 'http://drupal.org/node/133977')) . '</p>';
case 'admin/config/language/i18n':
$output .= '<li>' . t('To enable multilingual support for specific content types go to <a href="@configure_content_types">configure content types</a>.', array('@configure_content_types' => url('admin/structure/types'))) . '</li>';
* Implements hook_menu().
$items['admin/config/regional/i18n'] = array(
'title' => 'Multilingual settings',
'description' => 'Configure extended options for multilingual content and translations.',
'page callback' => 'drupal_get_form',
'page arguments' => array('variable_module_form', 'i18n'),
'access arguments' => array('administer site configuration'),
'weight' => 10,
$items['admin/config/regional/i18n/configure'] = array(
'title' => 'Multilingual system',
'description' => 'Configure extended options for multilingual content and translations.',
'type' => MENU_DEFAULT_LOCAL_TASK,
Jose Antonio Reyero del Prado
committed
module_load_include('pages.inc', 'i18n');
$items += i18n_page_menu_items();
* Simple i18n API
* Switch select Mode on off if enabled
*
Jose Antonio Reyero del Prado
committed
* Usage for disabling content selection for a while then return to previous state
*
Jose Antonio Reyero del Prado
committed
* // Disable selection, but store previous mode
* $previous = i18n_select(FALSE);
*
Jose Antonio Reyero del Prado
committed
* // Other code to be run without content selection here
* ..........................
*
Jose Antonio Reyero del Prado
committed
* // Return to previous mode
* i18n_select($previous);
*
Jose Antonio Reyero del Prado
committed
* @param $value
* Optional, enable/disable selection: TRUE/FALSE
* @return boolean
* Previous selection mode (TRUE/FALSE)
function i18n_select($value = NULL) {
Jose Antonio Reyero del Prado
committed
static $mode = FALSE;
if (isset($value)) {
Jose Antonio Reyero del Prado
committed
$previous = $mode;
$mode = $value;
Jose Antonio Reyero del Prado
committed
return $previous;
}
else {
return $mode;
* @param $property
* It may be 'name', 'native', 'ltr'...
*/
function i18n_language_property($code, $property) {
$languages = language_list();
Jose Antonio Reyero del Prado
committed
return isset($languages[$code]->$property) ? $languages[$code]->$property : NULL;
* Implements hook_preprocess_html().
function i18n_preprocess_html(&$variables) {
global $language;
$variables['classes_array'][] = 'i18n-' . $language->language;
* Translate or update user defined string. Entry point for i18n_string API if enabled.
*
* This function is from i18n_string sub module and is subject to be moved back.
*
* @param $name
* Textgroup and context glued with ':'.
* @param $default
* String in default language. Default language may or may not be English.
* @param $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.
Jose Antonio Reyero del Prado
committed
* - 'filter' Filtering callback to apply to the translated string only
* - 'format' Input format to apply to the translated string only
* - 'callback' Callback to apply to the result (both to translated or untranslated string
* - 'update' (defaults to FALSE) Whether to update source table
* - 'translate' (defaults to TRUE) Whether to return a translation
*
* @return $string
* Translated string, $string if not found
function i18n_string($name, $string, $options = array()) {
$options += array('translate' => TRUE, 'update' => FALSE);
if ($options['update']) {
$result = function_exists('i18n_string_update') ? i18n_string_update($name, $string, $options) : FALSE;
}
if ($options['translate']) {
$result = function_exists('i18n_string_translate') ? i18n_string_translate($name, $string, $options) : $string;
}
return $result;
Jose Antonio Reyero del Prado
committed
/**
*
* Depending on the page content we may need to use a different language for some operations.
Jose Antonio Reyero del Prado
committed
*/
function i18n_context_language() {
// Get language from the first module that provides it
foreach (module_implements('i18n_context_language') as $module) {
if ($language = module_invoke($module, 'i18n_context_language')) {
return $language;
Jose Antonio Reyero del Prado
committed
}
}
return i18n_language();
}
/**
* Get object language code
*
* @param $object
* Object or array having language field or plain language field
* @param $default
* What value to return if the object doesn't have a valid language
*/
function i18n_object_langcode($object, $default = FALSE, $field = 'language') {
$value = i18n_object_field($object, $field, $default);
return $value && $value != LANGUAGE_NONE ? $value : $default;
}
/**
* Get translation information for objects
*/
Jose Antonio Reyero del Prado
committed
function i18n_object_info($type = NULL, $property = NULL) {
$info = &drupal_static(__FUNCTION__);
if (!$info) {
$info = module_invoke_all('i18n_object_info');
drupal_alter('i18n_object_info', $info);
}
Jose Antonio Reyero del Prado
committed
if ($property) {
return isset($info[$type][$property]) ? $info[$type][$property] : NULL;
}
elseif ($type) {
return isset($info[$type]) ? $info[$type] : array();
}
else {
return $info;
}
}
/**
* Get field value from object/array
*/
function i18n_object_field($object, $field, $default = NULL) {
Jose Antonio Reyero del Prado
committed
if (is_array($field)) {
// We can handle a list of fields too. This is useful for multiple keys (like blocks)
foreach ($field as $key => $name) {
$values[$key] = i18n_object_field($object, $name);
}
return $values;
}
elseif (is_object($object)) {
return isset($object->$field) ? $object->$field : $default;
}
elseif (is_array($object)) {
return isset($object[$field]) ? $object[$field] : $default;
}
else {
return $default;
}
}
Jose Antonio Reyero del Prado
committed
/**
* Get key value from object/array
*/
function i18n_object_key($type, $object, $default = NULL) {
if ($field = i18n_object_info($type, 'key')) {
return i18n_object_field($object, $field, $default);
}
else {
return $default;
}
}
Jose Antonio Reyero del Prado
committed
/**
* Get edit path for object
*/
function i18n_object_edit_path($type, $object) {
if ($path = i18n_object_info($type, 'edit path')) {
return strtr($path, i18n_object_placeholders($type, $object));
}
else {
return NULL;
}
}
/**
* Get menu placehoders for object
*/
function i18n_object_placeholders($type, $object) {
$placeholders = i18n_object_info($type, 'placeholders', array());
foreach ($placeholders as $name => $field) {
$placeholders[$name] = i18n_object_field($object, $field);
}
return $placeholders;
}
Jose Antonio Reyero del Prado
committed
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
/**
* Menu access callback for mixed translation tab
*/
function i18n_object_translate_access($type, $object) {
switch (i18n_object_translate_mode($type, $object)) {
case I18N_MODE_TRANSLATE:
return i18n_translation_object_translate_access($type, $object);
case I18N_MODE_LOCALIZE:
return i18n_string_object_translate_access($type, $object);
default:
return FALSE;
}
}
/**
* Get primary translate or localize mode for object
*/
function i18n_object_translate_mode($type, $object) {
$mode = &drupal_static(__FUNCTION__);
$key = i18n_object_key($type, $object);
$key = is_array($key) ? implode(':', $key) : $key;
if (!isset($mode[$type][$key])) {
if (module_exists('i18n_translation') && i18n_translation_set_info($type)) {
$mode[$type][$key] = i18n_translation_object_translate_mode($type, $object);
}
elseif (module_exists('i18n_string') && i18n_string_object_info($type)) {
$mode[$type][$key] = i18n_string_object_translate_mode($type, $object);
}
}
return $mode[$type][$key];
}
/**
* Build translation link
*/
function i18n_translation_link($path, $langcode, $link = array()) {
$language = i18n_language($langcode);
$link += array(
'href' => $path,
'title' => $language->native,
'language' => $language,
'i18n_translation' => TRUE,
);
$link['attributes']['class'] = array('language-link');
// @todo Fix languageicons weight, but until that
if (function_exists('languageicons_link_add')) {
languageicons_link_add($link);
}
return $link;
Jose Antonio Reyero del Prado
committed
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function i18n_form_block_admin_display_form_alter(&$form, &$form_state) {
$form['#submit'][] = 'i18n_form_block_admin_display_form_submit';
}
/**
* Display a help message when enabling the language switcher block.
*/
function i18n_form_block_admin_display_form_submit($form, &$form_state) {
foreach ($form_state['values']['blocks'] as $key => $block) {
$previous = $form['blocks'][$key]['region']['#default_value'];
if (empty($previous) && $block['region'] != -1 && $block['module'] == 'locale') {
$message = t('The language switcher will appear only after configuring <a href="!url">language detection</a>. You need to enable at least one method that alters URLs like <em>URL</em> or <em>Session</em>.', array('!url' => url('admin/config/regional/language/configure')));
drupal_set_message($message, 'warning', FALSE);
break;
}
}
}
/**
* Normal path should be checked with menu item's language to avoid
* troubles when a node and it's translation has the same url alias.
*/
function i18n_prepare_normal_path($link_path, $language) {
$normal_path = drupal_get_normal_path($link_path, $language);
if ($link_path != $normal_path) {
drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $link_path, '%normal_path' => $normal_path)));
}
return $normal_path;
}