View source
<?php
function language_hierarchy_language_init() {
global $conf;
foreach (language_list() as $langcode => $language) {
if (!empty($language->parent)) {
$conf["locale_custom_strings_{$langcode}"] = new LocaleHierarchy($langcode);
}
}
}
function language_hierarchy_permission() {
return array(
'always fallback to default' => array(
'title' => t('Always fallback to default language'),
'description' => t('Always include default language in fallback chain.'),
),
);
}
function language_hierarchy_menu_alter(&$items) {
$items['admin/config/regional/language']['page arguments'] = array(
'language_hierarchy_form',
);
$items['admin/config/regional/language']['file'] = 'language_hierarchy_form.inc';
$items['admin/config/regional/language']['file path'] = drupal_get_path('module', 'language_hierarchy');
}
function language_hierarchy_theme() {
return array(
'language_hierarchy_form' => array(
'render element' => 'form',
'file' => 'language_hierarchy_form.inc',
),
);
}
function language_hierarchy_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'language_hierarchy') . '/views',
);
}
function language_hierarchy_form_locale_languages_delete_form_alter(&$form, &$form_state) {
$language_code = isset($form['langcode']['#value']) ? $form['langcode']['#value'] : '';
$descendants = language_hierarchy_get_descendants($language_code);
if (isset($descendants->children) && sizeof($descendants->children) > 0) {
$message = t('The @languagename language has @childlanguages child languages. These must be moved or deleted before you can delete this language.', array(
'@languagename' => $descendants->name,
'@childlanguages' => sizeof($descendants->children),
));
drupal_set_message($message, 'warning');
drupal_goto('admin/config/regional/language');
}
else {
$form['#submit'][] = 'language_hierarchy_delete_form_submit_callback';
}
}
function language_hierarchy_delete_form_submit_callback($form, &$form_state) {
$language_code = $form['langcode']['#value'];
variable_del("locale_custom_strings_{$language_code}");
}
function language_hierarchy_form_locale_languages_predefined_form_alter(&$form, &$form_state) {
$form['language list']['parent_language_list'] = _language_hierarchy_add_language_parent_select_list();
$form['#submit'][] = 'language_hierarchy_language_add_form_submit_callback';
}
function language_hierarchy_form_locale_languages_custom_form_alter(&$form, &$form_state) {
$form['custom language']['parent_language_list'] = _language_hierarchy_add_language_parent_select_list();
$form['#submit'][] = 'language_hierarchy_language_add_form_submit_callback';
}
function _language_hierarchy_add_language_parent_select_list() {
$languages = language_hierarchy_language_list();
$options = array(
'none' => t('No parent language'),
);
foreach ($languages as $language_code => $language) {
$options[$language_code] = t('@language_name (@language_code)', array(
'@language_name' => $language->name,
'@language_code' => $language->language,
));
}
$select_list = array(
'#type' => 'select',
'#title' => t('Parent language'),
'#options' => $options,
'#default_value' => 'none',
'#description' => t('Select the parent language'),
);
return $select_list;
}
function language_hierarchy_language_add_form_submit_callback($form, &$form_state) {
$langcode = $form_state['values']['langcode'];
if (isset($form_state['values']['parent_language_list']) && $form_state['values']['parent_language_list'] != 'none') {
drupal_static_reset('language_hierarchy_language_list');
drupal_static_reset('language_hierarchy_get_children');
drupal_static_reset('language_hierarchy_get_root_languages');
db_update('languages')
->fields(array(
'parent' => $form_state['values']['parent_language_list'],
))
->condition('language', $form_state['values']['langcode'], '=')
->execute();
variable_set("locale_custom_strings_{$langcode}", new LocaleHierarchy($langcode));
_language_hierarchy_normalize_weight();
}
}
function language_hierarchy_form_alter(&$form, &$form_state, $form_id) {
if (in_array($form_id, array(
'locale_translate_edit_form',
'i18n_string_locale_translate_edit_form',
))) {
$lid = $form['lid']['#value'];
$source = db_query('SELECT source, context, textgroup, location FROM {locales_source} WHERE lid = :lid', array(
':lid' => $lid,
))
->fetchObject();
$languages = language_hierarchy_language_list();
if (!$source || count($languages) == 1) {
return;
}
$rows = min(ceil(str_word_count($source->source) / 12), 10);
foreach ($languages as $langcode => $language) {
if (isset($form['translations'][$langcode])) {
$form['translations'][$langcode]['#prefix'] = '<div style="margin-left: ' . $language->depth * 2 . 'em">';
$form['translations'][$langcode]['#suffix'] = '</div>';
}
else {
$form['translations'][$langcode] = array(
'#type' => 'textarea',
'#rows' => $rows,
'#title' => $language->name . ' (' . $form['original']['#title'] . ')',
'#disabled' => TRUE,
'#default_value' => $source->source,
);
}
$form['translations'][$langcode]['#weight'] = $language->weight;
}
}
}
function language_hierarchy_i18n_string_info_alter(&$object_info) {
foreach ($object_info as $type => &$info) {
if (!isset($info['class']) || $info['class'] == 'i18n_string_textgroup_default') {
$info['class'] = 'language_hierarchy_i18n_string_textgroup_default';
}
elseif ($info['class'] == 'i18n_string_textgroup_cached') {
$info['class'] = 'language_hierarchy_i18n_string_textgroup_cached';
}
}
}
function language_hierarchy_form_i18n_string_translate_page_overview_form_alter(&$form, &$form_state) {
$strings = $form_state['build_info']['args'][1];
$source_langcode = variable_get_value('i18n_string_source_language');
$languages = language_list();
foreach ($form['languages']['#rows'] as $langcode => &$row) {
if ($langcode != $source_langcode) {
foreach ($strings as $string_object) {
if ($string_object
->get_translation($langcode)) {
$fallback_langcode = _language_hierarchy_get_i18n_string_translation_fallback_langcode($string_object, $langcode);
if ($fallback_langcode !== NULL) {
$row['status'] = t('fallback from @language', array(
'@language' => $languages[$fallback_langcode]->name,
));
}
break;
}
}
}
}
unset($row);
}
function language_hierarchy_form_i18n_string_translate_page_form_alter(&$form, &$form_state) {
$languages = language_list();
foreach ($form['string_groups']['#value'] as $group_key => $strings) {
foreach ($strings as $string_object) {
$fallback_langcode = _language_hierarchy_get_i18n_string_translation_fallback_langcode($string_object, $form['langcode']['#value']);
if ($fallback_langcode !== NULL) {
$name = $string_object
->get_name();
$form['strings'][$group_key][$name]['#description'] .= t('The @language fallback is currently used for this string. If you save this string, a new one will be created and the fallback not used anymore.', array(
'@language' => $languages[$fallback_langcode]->name,
));
}
}
}
}
function _language_hierarchy_get_i18n_string_translation_fallback_langcode($string_object, $langcode) {
$class = i18n_string_group_info($string_object->textgroup, 'class', 'i18n_string_textgroup_default');
$group_object = new $class($string_object->textgroup);
if ($group_object instanceof language_hierarchy_i18n_string_textgroup_default) {
$show_language =& drupal_static('language_hierarchy_i18n_show_language');
$show_language = TRUE;
$translation = $group_object
->load_translation($string_object, $langcode);
drupal_static_reset('language_hierarchy_i18n_show_language');
if ($translation && isset($translation->language) && $translation->language != $langcode) {
return $translation->language;
}
}
return NULL;
}
function language_hierarchy_get_parent($langcode) {
$languages = language_list();
if (isset($languages[$langcode]) && !empty($languages[$langcode]->parent) && isset($languages[$languages[$langcode]->parent])) {
return $languages[$languages[$langcode]->parent];
}
else {
return NULL;
}
}
function language_hierarchy_get_children($langcode) {
$children =& drupal_static(__FUNCTION__);
if (!isset($children[$langcode])) {
$children[$langcode] = db_select('languages', 'l')
->fields('l')
->condition('parent', $langcode)
->orderBy('weight', 'ASC')
->orderBy('name', 'ASC')
->execute()
->fetchAllAssoc('language');
}
return $children[$langcode];
}
function language_hierarchy_get_root_languages() {
$top_level_languages =& drupal_static(__FUNCTION__);
if (!isset($top_level_languages)) {
$top_level_languages = db_select('languages', 'l')
->fields('l')
->condition('parent', '')
->orderBy('weight', 'ASC')
->orderBy('name', 'ASC')
->execute()
->fetchAllAssoc('language');
}
return $top_level_languages;
}
function language_hierarchy_get_ancestors($langcode, $enabled_languages_only = FALSE) {
$ancestors = array();
while ($ancestor = language_hierarchy_get_parent($langcode)) {
if ($enabled_languages_only == FALSE || $ancestor->enabled == TRUE) {
$ancestors[$ancestor->language] = $ancestor;
}
$langcode = $ancestor->language;
}
return $ancestors;
}
function language_hierarchy_get_descendants($langcode = NULL, &$language = NULL) {
$languages = language_list();
if (!empty($languages[$langcode])) {
$language = $languages[$langcode];
$children = language_hierarchy_get_children($langcode);
foreach ($children as $child_code => $child) {
$language->children[$child_code] = language_hierarchy_get_descendants($child_code, $child);
}
}
return $language;
}
function language_hierarchy_language_list() {
$languages =& drupal_static(__FUNCTION__);
if (empty($languages)) {
$root_languages = language_hierarchy_get_root_languages();
foreach ($root_languages as $langcode => $language) {
$language->depth = count(language_hierarchy_get_ancestors($langcode));
$languages[$langcode] = $language;
_language_hierarchy_language_list_descendants($langcode, $languages);
}
}
return $languages;
}
function language_hierarchy_set_parent($langcode, $parent_langcode) {
$languages = language_list();
if (empty($languages[$parent_langcode])) {
return FALSE;
}
if (!empty($languages[$langcode])) {
db_update('languages')
->fields(array(
'parent' => $parent_langcode,
))
->condition('language', $langcode)
->execute();
return TRUE;
}
else {
return FALSE;
}
}
function language_hierarchy_language_fallback_candidates_alter(array &$fallback_candidates) {
$fallback_languages = array_keys(language_hierarchy_get_ancestors($GLOBALS['language']->language, TRUE));
$default_language = language_default();
if (!in_array($default_language->language, $fallback_languages) && user_access('always fallback to default')) {
$fallback_languages[] = $default_language->language;
}
$fallback_languages[] = LANGUAGE_NONE;
$fallback_candidates = $fallback_languages;
}
function _language_hierarchy_language_list_descendants($langcode, &$languages = NULL) {
$children = language_hierarchy_get_children($langcode);
foreach ($children as $child_code => $child) {
$child->depth = count(language_hierarchy_get_ancestors($child_code));
$languages[$child_code] = $child;
_language_hierarchy_language_list_descendants($child_code, $languages);
}
}
function _language_hierarchy_normalize_weight() {
$languages = language_hierarchy_language_list();
$normalized_weight = -10;
foreach ($languages as $langcode => $language) {
db_update('languages')
->fields(array(
'weight' => $normalized_weight,
))
->condition('language', $langcode, '=')
->execute();
$normalized_weight++;
}
}
function language_hierarchy_attach_language_selector(&$element) {
$languages = language_hierarchy_get_root_languages();
foreach ($languages as $langcode => $language) {
$languages[$langcode] = language_hierarchy_get_descendants($langcode, $language);
}
$element['#attached']['js'][] = array(
'type' => 'setting',
'data' => array(
'languageHierarchy' => language_hierarchy_language_list(),
),
);
$path = drupal_get_path('module', 'language_hierarchy');
$element['#attached']['js'][] = $path . '/language_hierarchy.js';
$element['#attached']['css'][] = $path . '/language_hierarchy.css';
}
function language_hierarchy_preprocess_select(&$variables) {
if (language_hierarchy_is_language_selector($variables['element'])) {
language_hierarchy_indent_options_in_select($variables['element']);
}
}
function language_hierarchy_is_language_selector($element) {
$language_list = language_list();
$common = array_intersect(array_keys($language_list), array_keys($element['#options']));
return count($common) > 0;
}
function language_hierarchy_indent_options_in_select(&$element) {
$languages = language_hierarchy_language_list();
foreach ($languages as $langcode => $language) {
if (isset($element['#options'][$langcode])) {
$indent = str_repeat('--', $language->depth);
$indent = $indent ? $indent . ' ' : '';
$element['#options'][$langcode] = $indent . $element['#options'][$langcode];
}
}
}