diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ba76017e5b133131565cfad0e829d104bb8f9609..303a24f789baa48e5e38b0adab2f2ce0930f49dc 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,13 +1,5 @@ // $Id$ --6.x-1.6 to 6.x-1.7 -------------------- --- Fixed: Missing function i18n_taxonomy_translate_term_name(), by srobert72, #870366 --- Fixed: Parameter 1 to menu_nodeapi() expected to be a reference (php5.3), by setvik, #886700 --- Fixed: Multilingual variables cache being rebuilt every page load, by patrick2000, #905428 --- Improved variable api, added i18n_variable(), extended i18n_variable_del() --- Improved variable settings, variables for default language are now set to main table - 6.x-1.5 to 6.x-1.6 ----------------- - Fixed: issues with i18nvariables, do not check anymore i18n_variables on initialization, by Jose, #850708 @@ -15,9 +7,9 @@ - Fixed: PHP notices, by eMPee584, #769318 - Delete description on menu item delete, #844208 by plach - Fixed: Node type help not translated, by NaX, #685788 -- Some improvements to i18nmenu API, by plach, #386372 -- Renamed theme_taxonomy_term_page() to theme_i18ntaxonomy_term_page() to avoid namespace conflicts -- Added some taxonomy API functions: i18ntaxonomy_translate_term_name().... +- Some improvements to i18n_menu API, by plach, #386372 +- Renamed theme_taxonomy_term_page() to theme_i18n_taxonomy_term_page() to avoid namespace conflicts +- Added some taxonomy API functions: i18n_taxonomy_translate_term_name().... - Fixed: Access denied to database query (LOCK TABLES) on i18n_variable_set(), #769260 - Reworked variable initialization to fix multiple issues (front page, etc), #826774 - Some changes to variables API, added new function: i18n_variable_get() diff --git a/i18n.module b/i18n.module index 2b27d3a577dfe8bac19b2db2a95d4d48fe571ff2..9bbc38e9890717e580a929148fd8434deec8e694 100644 --- a/i18n.module +++ b/i18n.module @@ -13,32 +13,48 @@ * @author Jose A. Reyero, 2004 */ -// Some constants. Language support modes for content -define('LANGUAGE_SUPPORT_NONE', 0); -define('LANGUAGE_SUPPORT_NORMAL', 1); -define('LANGUAGE_SUPPORT_EXTENDED', 2); -define('LANGUAGE_SUPPORT_EXTENDED_NOT_DISPLAYED', 3); - +// All multilingual options disabled +define('I18N_LANGUAGE_DISABLED', 0); // Language list will include all enabled languages -define('I18N_LANGUAGE_ENABLED', 0); +define('I18N_LANGUAGE_ENABLED', 1); // Language list will include also disabled languages -define('I18N_LANGUAGE_EXTENDED', 1); +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); /** * Implements hook_boot() - * - * Initialize variables, that will be used to decide on site_frontpage */ function i18n_boot() { // Just make sure the module is loaded for boot and the API is available. } /** - * Get global language, make sure it is initialized + * 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) { - return $language; + if (is_object($language)) { + return $language; + } + else { + $list = language_list(); + return isset($list[$language]) ? $list[$language] : i18n_language(); + } } else { if (empty($GLOBALS['language'])) { @@ -54,8 +70,9 @@ function i18n_language($language = NULL) { * * @todo See about creating a permission for seeing disabled languages */ -function i18n_language_list($field = 'name') { - return locale_language_list($field, I18N_LANGUAGE_EXTENDED & variable_get('i18n_language_list', I18N_LANGUAGE_ENABLED)); +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); } /** @@ -86,48 +103,6 @@ function i18n_langcode($langcode = NULL) { return $langcode && $langcode !== LANGUAGE_NONE ? $langcode : i18n_language()->language; } -/** - * Implements hook_init(). - * - * Special fix for site_frontpage, that may have been used before the language variables are loaded. - */ -/* -function i18n_init() { - // If not in bootstrap, variable init. Otherwise we are serving a cached page so we don't need anything else. - if (!_i18n_is_bootstrap()) { - _i18n_init_mode(); - } -} -*/ - -/** - * Initialize selection mode - */ -function _i18n_init_mode() { - if (i18n_selection_mode() != 'off') { - // Node language when loading specific nodes or creating translations. - if (arg(0) == 'node' ) { - if (($node = menu_get_object('node')) && $node->language) { - i18n_selection_mode('node', $node->language); - } - elseif (arg(1) == 'add' && !empty($_GET['translation']) && !empty($_GET['language'])) { - i18n_selection_mode('translation', db_escape_string($_GET['language'])); - } - } - elseif (arg(0) == 'admin') { - // There are some exceptions for admin pages. - if (arg(1) == 'content' && user_access('administer all languages')) { - // No restrictions for administration pages. - i18n_selection_mode('off'); - } - elseif (arg(1) == 'build' && (arg(2) == 'menu-customize' || arg(2) == 'menu')) { - // All nodes available when editing custom menu items. - i18n_selection_mode('off'); - } - } - } -} - /** * Implements hook_help(). */ @@ -199,20 +174,19 @@ function i18n_modules_installed($modules) { } /** - * Implements hook_user_login(). - * - * Switch to user's language after login. + * Simple i18n API */ -function i18n_user_login(&$edit, &$account) { - if ($account->language) { - $_SESSION['language'] = $account->language; - i18n_get_lang($account->language); - } -} /** - * Simple i18n API + * Switch select Mode on off if enabled */ +function i18n_select($value = NULL) { + static $mode; + if (isset($value)) { + $mode = $value; + } + return $mode; +} /** * Get language properties. @@ -228,148 +202,11 @@ function i18n_language_property($code, $property) { } /** - * Selection mode for content. - * - * Warning: when used with params they need to be escaped, as some values are thrown directly in queries. - * - * Allows several modes for query rewriting and to change them programatically. - * off = No language conditions inserted. - * simple = Only current language and no language. - * mixed = Only current and default languages. - * strict = Only current language. - * default = Only default language. - * user = User defined, in the module's settings page. - * params = Gets the stored params. - * reset = Returns to previous. - * custom = add custom where clause, like "%alias.language = 'en'". - * - * @param $reset - * Whether to reset the internal cache for the selection mode. - */ -function i18n_selection_mode($mode = NULL, $params = NULL, $reset = FALSE) { - $current_mode = &drupal_static(__FUNCTION__ . '_mode', NULL, $reset); - $current_mode = &drupal_static(__FUNCTION__ . '_value', '', $reset); - $store = &drupal_static(__FUNCTION__ . '_store', '', $reset); - - // Initialization, first time this runs - if (!isset($current_mode)) { - $current_mode = variable_get('i18n_selection_mode', 'simple'); - } - - if (!$mode) { - return $current_mode; - } - elseif ($mode == 'params') { - return $current_value; - } - elseif ($mode == 'reset') { - list($current_mode, $current_value) = array_pop($store); - } - else { - array_push($store, array($current_mode, $current_value)); - $current_mode = $mode; - $current_value = $params; - } -} - -/** - * Rewrites queries depending on rewriting mode. - * - * @return DatabaseCondition + * Implements hook_preprocess_html(). */ -function i18n_db_rewrite_where($alias, $type, $mode = NULL) { - if (!$mode) { - // Some exceptions for query rewrites. - $mode = i18n_selection_mode(); - } - - // Get languages to simplify query building. - $current = i18n_language()->language; - $default = language_default('language'); - - if ($mode == 'strict' && $type != 'node') { - // Special case. Selection mode is 'strict' but this should be only for node queries. - $mode = 'simple'; - } - elseif ($mode == 'mixed' && $current == $default) { - // If mode is mixed but current = default, is the same as 'simple'. - $mode = 'simple'; - } - - switch ($mode) { - case 'off': - return ''; - - case 'simple': - return db_condition('OR') - ->condition($alias . '.language', $current) - ->condition($alias . '.language', '') - ->condition($alias . '.language', NULL); - - case 'mixed': - return db_condition('OR') - ->condition($alias . '.language', $current) - ->condition($alias . '.language', $default) - ->condition($alias . '.language', '') - ->condition($alias . '.language', NULL); - - case 'strict': - return db_condition('AND')->condition($alias . '.language', $current); - - case 'node': - case 'translation': - return db_condition('OR') - ->condition($alias . '.language', i18n_selection_mode('params')) - ->condition($alias . '.language', '') - ->condition($alias . '.language', NULL); - - case 'default': - return db_condition('OR') - ->condition($alias . '.language', $default) - ->condition($alias . '.language', '') - ->condition($alias . '.language', NULL); - - case 'custom': - return str_replace('%alias', $alias, i18n_selection_mode('params')); - } -} - -/** - * Implements hook_preprocess_page(). - * - * Add the language code to the classes for the tag. Unfortunately, some - * themes will not respect the variable we're modifying to achieve this - in - * particular, Garland and Minelli do not. - */ -function i18n_preprocess_page(&$variables) { - if (isset($variables['body_classes'])) { - global $language; - $variables['body_classes'] .= ' i18n-' . $language->language; - } -} - - -/** - * Implements hook_permission(). - * - * Permissions defined - * - administer all languages - * Disables language conditions for administration pages, so the user can view objects for all languages at the same time. - * This applies for: menu items, taxonomy - * - administer translations - * Will allow to add/remove existing nodes to/from translation sets. - */ -function i18n_permission() { - return array( - 'administer all languages' => array( - 'title' => t('Administer all languages'), - 'description' => t('Administer all languages.'), - ), - 'administer translations' => array( - 'title' => t('Administer translations'), - 'description' => t('Administer translations.'), - ), - ); +function i18n_preprocess_html(&$variables) { + global $language; + $variables['classes_array'][] = 'i18n-' . $language->language; } /** @@ -403,15 +240,15 @@ function i18n_string($name, $string, $options = array()) { /** * Get language from context. + * + * Depending on the page content we may need to use a different language for some operations. */ -function _i18n_get_context_lang() { - // Node language when loading specific nodes or creating translations. - if (arg(0) == 'node' ) { - if (($node = menu_get_object('node')) && $node->language) { - return $node->language; - } - elseif (arg(1) == 'add' && !empty($_GET['translation']) && !empty($_GET['language'])) { - return $_GET['language']; +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; } } -} + return i18n_language(); +} \ No newline at end of file diff --git a/i18n_block/i18n_block.js b/i18n_block/i18n_block.js new file mode 100644 index 0000000000000000000000000000000000000000..9fced100ded29e965065b6d0d2a0e9f48fba90c4 --- /dev/null +++ b/i18n_block/i18n_block.js @@ -0,0 +1,31 @@ +// $Id$ + +(function ($) { + +/** + * Provide the summary information for the block settings vertical tab. + */ +Drupal.behaviors.i18nSettingsSummary = { + attach: function (context) { + + $('fieldset#edit-languages', context).drupalSetSummary(function (context) { + var summary = ''; + if ($('.form-item-i18n-mode input[type=checkbox]:checked', context).val()) { + summary += Drupal.t('Translatable'); + } + else { + summary += Drupal.t('Not translatable'); + } + summary += ', '; + if ($('.form-item-languages input[type=checkbox]:checked', context).val()) { + summary += Drupal.t('Restricted to certain languages'); + } + else { + summary += Drupal.t('Not restricted'); + } + return summary; + }); + } +}; + +})(jQuery); diff --git a/i18n_block/i18n_block.module b/i18n_block/i18n_block.module index 368a988d9af72948eeff0f287b1e3daee2598e33..fd629ee61b812ed7ce7f2828841600d547fcbac7 100644 --- a/i18n_block/i18n_block.module +++ b/i18n_block/i18n_block.module @@ -10,13 +10,6 @@ * @ TODO Add strings on block update. */ -// Tag for localizable block, cannot be any language. -define('I18N_BLOCK_LOCALIZE', '__LOCALIZE__'); -// Block type: localizable -define('I18N_BLOCK_LOCALIZABLE', 1); -// Block type: block with language -define('I18N_BLOCK_LANGUAGE', 0); - /** * Implements hook_block_list_alter(). * @@ -172,10 +165,6 @@ function i18n_block_form_block_add_block_form_alter(&$form, &$form_state, $form_ * Remove block title for multilingual blocks. */ function i18n_block_form_block_admin_configure_alter(&$form, &$form_state, $form_id) { - $default_options = db_query("SELECT language FROM {i18n_block_language} WHERE module = :module AND delta = :delta", array( - ':module' => $form['module']['#value'], - ':delta' => $form['delta']['#value'], - ))->fetchCol(); $form['i18n_block']['languages'] = array( '#type' => 'fieldset', '#title' => t('Languages'), @@ -183,23 +172,31 @@ function i18n_block_form_block_admin_configure_alter(&$form, &$form_state, $form '#collapsed' => TRUE, '#group' => 'visibility', '#weight' => 5, + '#attached' => array( + 'js' => array(drupal_get_path('module', 'i18n_block') . '/i18n_block.js'), + ), + ); + + // Add translatable option, just title for module blocks, title and content for custom blocks. + $block = block_load($form['module']['#value'], $form['delta']['#value']); + $form['i18n_block']['languages']['i18n_mode'] = array( + '#type' => 'checkbox', + '#title' => $form['module']['#value'] == 'block' ? t("Make this block's title and content translatable.") : t("Make this block's title translatable."), + '#default_value' => (int) @$block->i18n_mode, + '#access' => module_exists('i18n_string'), ); + + // Add option to select which language pages to show on. + $default_options = db_query("SELECT language FROM {i18n_block_language} WHERE module = :module AND delta = :delta", array( + ':module' => $form['module']['#value'], + ':delta' => $form['delta']['#value'], + ))->fetchCol(); $form['i18n_block']['languages']['languages'] = array( '#type' => 'checkboxes', - '#title' => t('Show block for specific languages'), + '#title' => t('Only show this block for these languages'), '#default_value' => $default_options, '#options' => i18n_language_list(), - '#description' => t('Show this block only on pages for the given language(s). If you select no language, there will be no language-specific limitation.'), - ); - // Add translatable option, just title for module blocks, title and content for custom blocks. - $block = block_load($form['module']['#value'], $form['delta']['#value']); - $form['i18n_block']['languages']['i18n_mode'] = array( - '#type' => 'radios', - '#title' => t('Block translation'), - '#default_value' => $block->i18n_mode, - '#options' => array(t('Disabled'), t('Enabled')), - '#description' => $form['module']['#value'] == 'block' ? t('Make this block title and content translatable.') : t('Make this block title translatable.'), - '#disabled' => !module_exists('i18n_string'), + '#description' => t('If no language is selected, block will show regardless of language.'), ); $form['#submit'][] = 'i18n_block_form_block_admin_configure_submit'; } diff --git a/i18n_menu/i18n_menu.module b/i18n_menu/i18n_menu.module index 8f79c48a4e9ffac9bcb88eff689fd34dda83bbe2..9cb022ccb922161a5cf368a4a43eef0d2e3962cc 100644 --- a/i18n_menu/i18n_menu.module +++ b/i18n_menu/i18n_menu.module @@ -188,9 +188,9 @@ function i18n_menu_help($path, $arg) { */ function i18n_menu_translated_tree($menu_name, $reset = FALSE) { $menu_output = &drupal_static(__FUNCTION__); - if (!isset($menu_output[$menu_name]) || $reset) { + if (!isset($menu_output[$menu_name]) || $reset) { $tree = menu_tree_page_data($menu_name); - i18n_menu_localize_tree($tree); + $tree = i18n_menu_localize_tree($tree); $menu_output[$menu_name] = menu_tree_output($tree); } return $menu_output[$menu_name]; @@ -199,16 +199,15 @@ function i18n_menu_translated_tree($menu_name, $reset = FALSE) { /** * Localize menu tree. */ -function i18n_menu_localize_tree(&$tree) { - global $language; - - foreach ($tree as $index => $item) { +function i18n_menu_localize_tree($tree, $langcode = NULL) { + $langcode = i18n_langcode($langcode); + foreach ($tree as $index => &$item) { $link = $item['link']; if ($link['customized'] && !empty($link['access']) && empty($link['hidden']) && empty($link['i18n_menu'])) { // Remove links for other languages than current. // Links with language wont be localized. - if (!empty($link['options']['langcode'])) { - if ($link['options']['langcode'] != $language->language) { + if (!empty($link['language'])) { + if ($link['language'] != $langcode) { unset($tree[$index]); } } @@ -216,18 +215,19 @@ function i18n_menu_localize_tree(&$tree) { $router = i18n_menu_get_router($link['router_path']); // If the title is the same it will be localized by the menu system. if ($link['link_title'] != $router['title']) { - $tree[$index]['link']['title'] = _i18n_menu_link_title($link); + $item['link']['title'] = _i18n_menu_link_title($link, $langcode); } - if ($description = _i18n_menu_link_description($link)) { - $tree[$index]['link']['localized_options']['attributes']['title'] = $description; + if ($description = _i18n_menu_link_description($link, $langcode)) { + $item['link']['localized_options']['attributes']['title'] = $description; } // Localize subtree. if ($item['below'] !== FALSE) { - i18n_menu_localize_tree($tree[$index]['below'], $update); + $item['below'] = i18n_menu_localize_tree($item['below'], $langcode); } } } } + return $tree; } /** @@ -254,7 +254,7 @@ function i18n_menu_menu_navigation_links($menu_name, $level = 0) { // Get the menu hierarchy for the current page. $tree = menu_tree_page_data($menu_name); - i18n_menu_localize_tree($tree); + $tree = i18n_menu_localize_tree($tree); // Go down the active trail until the right level is reached. while ($level-- > 0 && $tree) { diff --git a/i18n_node/i18n_node.module b/i18n_node/i18n_node.module index 1059be7596788f002345ff263f98fba71fa9d3d7..d2eafa6a75f1a0a38049b081892db21f20c5841d 100644 --- a/i18n_node/i18n_node.module +++ b/i18n_node/i18n_node.module @@ -100,6 +100,21 @@ function i18n_node_help($path, $arg) { } } +/** + * Implements hook_i18n_context_language() + */ +function i18n_node_i18n_context_language() { + // Node language when loading specific nodes or creating translations. + if (arg(0) == 'node' ) { + if (($node = menu_get_object('node')) && !empty($node->language)) { + return i18n_language($node->language); + } + elseif (arg(1) == 'add' && !empty($_GET['translation']) && !empty($_GET['target'])) { + return i18n_language($_GET['target']); + } + } +} + /** * Implements hook_i18n_string_info() */ @@ -179,12 +194,7 @@ function i18n_node_language_list($node, $translate = FALSE) { $languages = node_invoke($node, 'language_list', $translate); if (!$languages) { - if (variable_get('i18n_node_'. $node->type, 0) >= LANGUAGE_SUPPORT_EXTENDED) { - $languages = locale_language_list('name', TRUE); // All defined languages - } - else { - $languages = locale_language_list(); // All enabled languages - } + $languages = i18n_language_list('name', i18n_node_language_mode($node)); if ($translate && isset($node->tnid) && $node->tnid && ($translations = translation_node_get_translations($node->tnid))) { unset($translations[$node->language]); foreach (array_keys($translations) as $langcode) { @@ -204,6 +214,13 @@ function i18n_node_language_list($node, $translate = FALSE) { return $languages; } +/** + * Get language mode for node or node type + */ +function i18n_node_language_mode($type) { + $type = is_object($type) ? $type->type : $type; + return variable_get('i18n_node_'. $type, I18N_LANGUAGE_ENABLED); +} /** * Implements hook_node_prepare(). @@ -217,6 +234,25 @@ function i18n_node_nodeapi($node) { } } +/** + * Implements hook_permission(). + * + * Permissions defined + * - administer all languages + * Disables language conditions for administration pages, so the user can view objects for all languages at the same time. + * This applies for: menu items, taxonomy + * - administer translations + * Will allow to add/remove existing nodes to/from translation sets. + */ +function i18n_node_permission() { + return array( + 'administer content translations' => array( + 'title' => t('Administer content translations'), + 'description' => t('Add or remove existing content to translation sets.'), + ), + ); +} + /** * Implements hook_alter_translation_link(). * @@ -229,9 +265,9 @@ function i18n_node_translation_link_alter(&$links, $path) { // Check for a node related path, and for its translations. if ((preg_match("!^node/([0-9]+)(/.+|)$!", $path, $matches)) && ($node = node_load((int)$matches[1])) && !empty($node->tnid)) { - // make sure language support is set to LANGUAGE_SUPPORT_EXTENDED, so links - // dont get added for LANGUAGE_SUPPORT_EXTENDED_NOT_DISPLAYED - if (variable_get('i18n_node_'. $node->type, LANGUAGE_SUPPORT_NORMAL) == LANGUAGE_SUPPORT_EXTENDED) { + // make sure language support is set to I18N_LANGUAGE_EXTENDED, so links + // dont get added for I18N_LANGUAGE_EXTENDED_NOT_DISPLAYED + if (!(i18n_node_languabe_mode($node->type) & I18N_LANGUAGE_HIDDEN)) { $languages = language_list(); $extended = array(); foreach (translation_node_get_translations($node->tnid) as $langcode => $translation_node) { @@ -265,7 +301,7 @@ function i18n_node_translation_link_alter(&$links, $path) { function i18n_node_link_alter(&$links, $node) { global $language; - $language_support = variable_get('i18n_node_'. $node->type, LANGUAGE_SUPPORT_NORMAL); + $language_support = i18n_node_language_mode($node); // Hide node translation links. if (variable_get('i18n_hide_translation_links', 0) == 1) { @@ -280,7 +316,7 @@ function i18n_node_link_alter(&$links, $node) { foreach (i18n_node_language_list($node) as $langcode) { $index = 'node_translation_'. $langcode; if (!empty($links[$index])) { - if ($language_support != LANGUAGE_SUPPORT_EXTENDED && $links[$index]['language']->enabled == 0) { + if (!($language_support & I18N_LANGUAGE_EXTENDED) && $links[$index]['language']->enabled == 0) { unset($links[$index]); } else { @@ -449,7 +485,7 @@ function i18n_node_form_node_type_form_alter(&$form, &$form_state) { $form['i18n']['i18n_node'] = array( '#type' => 'radios', '#title' => t('Extended language support'), - '#default_value' => variable_get('i18n_node_'. $form['#node_type']->type, LANGUAGE_SUPPORT_NORMAL), + '#default_value' => i18n_node_language_mode($form['#node_type']->type), '#options' => _i18n_node_language_options(), '#description' => t('If enabled, all defined languages will be allowed for this content type in addition to only enabled ones. This is useful to have more languages for content than for the interface.'), '#disabled' => $disabled, @@ -498,9 +534,9 @@ function i18n_node_theme() { */ function _i18n_node_language_options() { return array( - LANGUAGE_SUPPORT_NORMAL => t('Normal - All enabled languages will be allowed.'), - LANGUAGE_SUPPORT_EXTENDED => t('Extended - All defined languages will be allowed.'), - LANGUAGE_SUPPORT_EXTENDED_NOT_DISPLAYED => t('Extended, but not displayed - All defined languages will be allowed for input, but not displayed in links.'), + I18N_LANGUAGE_ENABLED => t('Normal - All enabled languages will be allowed.'), + I18N_LANGUAGE_EXTENDED => t('Extended - All defined languages will be allowed.'), + I18N_LANGUAGE_EXTENDED | I18N_LANGUAGE_HIDDEN => t('Extended, but not displayed - All defined languages will be allowed for input, but not displayed in links.'), ); } diff --git a/i18n_string/i18n_string.admin.inc b/i18n_string/i18n_string.admin.inc index ccb421d3c932f2bde6a46be7d200e00f65492217..ba4a128cf5a86f691b406b798793c9d7beb8828e 100644 --- a/i18n_string/i18n_string.admin.inc +++ b/i18n_string/i18n_string.admin.inc @@ -89,7 +89,7 @@ function i18n_string_admin_update($language, $groups) { $count = 0; foreach($result as $string) { - // Just update strings when no input format, otherwise it could be dangerous under some circumstances. + // Just update strings when no text format, otherwise it could be dangerous under some circumstances. if (empty($string->format) && !empty($string->translation)) { $count++; db_insert(locales_target) @@ -117,11 +117,11 @@ function i18n_string_admin_settings() { $format_list[$fid] = $format->name; } $form['i18n_string_allowed_formats'] = array( - '#title' => t('Translatable input formats'), + '#title' => t('Translatable text formats'), '#options' => $format_list, '#type' => 'checkboxes', '#default_value' => variable_get('i18n_string_allowed_formats', array(variable_get('filter_default_format', 1))), - '#description' => t('Only the strings that have the input formats selected will be allowed by the translation system. All the others will be deleted next time the strings are refreshed.'), + '#description' => t('Only the strings that have the text formats selected will be allowed by the translation system. All the others will be deleted next time the strings are refreshed.'), ); // Whitelist text groups without formatted strings for backwards compatibility $textgroups = module_invoke_all('locale', 'groups'); diff --git a/i18n_string/i18n_string.inc b/i18n_string/i18n_string.inc index e6cf38f06f1b641733e638be6cbddfd28fb64ae1..7bcfab53a119c31724d3677a49c0e13faa88e874 100644 --- a/i18n_string/i18n_string.inc +++ b/i18n_string/i18n_string.inc @@ -52,10 +52,10 @@ class i18n_string_default { return $string; } /** - * Check if input format is allowed for translation + * Check if text format is allowed for translation * * @param $format - * Input format key or NULL if not format (will be allowed) + * Text format key or NULL if not format (will be allowed) */ public static function allowed_format($format = NULL) { $allowed_formats = variable_get('i18n_string_allowed_formats', array(variable_get('filter_default_format', 1))); @@ -73,7 +73,7 @@ class i18n_string_default { * @param $i18nstring * String object * @param $format - * Input format, for strings that will go through some filter + * Text format, for strings that will go through some filter * @return * Update status. */ @@ -172,7 +172,7 @@ class i18n_string_default { if (!empty($i18nstring->format) && !self::allowed_format($i18nstring->format)) { // This format is not allowed, so we remove the string, in this case we produce a warning $params = self::string_params($i18nstring); - drupal_set_message(t('The string %location for textgroup %textgroup is not allowed for translation because of its input format.', $params), 'warning'); + drupal_set_message(t('The string %location for textgroup %textgroup is not allowed for translation because of its text format.', $params), 'warning'); return FALSE; } else { @@ -206,10 +206,10 @@ class i18n_string_default { } /** - * Get translation from the database. Full object with input format. + * Get translation from the database. Full object with text format. * * This one doesn't return anything if we don't have the full i18n strings data there - * to prevent missing data resulting in missing input formats + * to prevent missing data resulting in missing text formats */ protected function get_translation($i18nstring) { // First, populate available data from the cache @@ -478,7 +478,7 @@ class i18n_string_default { * Source string in default language. Default language may or may not be English. * @param $options * Array with additional options: - * - 'format', String format if the string has input format + * - 'format', String format if the string has text format * - 'messages', Whether to print out status messages */ public function update($context, $string, $options = array()) { @@ -514,7 +514,7 @@ class i18n_string_default { * @pram $string * New value of string for update/create. May be empty for removing. * @param $format - * Input format, that must have been checked against allowed formats for translation + * Text format, that must have been checked against allowed formats for translation * @return status * SAVED_UPDATED | SAVED_NEW | SAVED_DELETED */ diff --git a/i18n_string/i18n_string.module b/i18n_string/i18n_string.module index d43a5fa18789703211675506f311a9b924484fbf..d44e26dea4e418bffd4a3da726326e55162bca87 100644 --- a/i18n_string/i18n_string.module +++ b/i18n_string/i18n_string.module @@ -91,19 +91,19 @@ function i18n_string_help($path, $arg) { $output .= '
  • ' . t('Use the update option when some of the strings had been previously translated with the localization system, but the translations are not showing up for the configurable strings.') . '
  • '; $output .= ''; $output .= '

    ' . t('To search and translate strings, use the translation interface pages.', array('@translate-interface' => url('admin/config/regional/translate'))) . '

    '; - $output .= '

    ' . t('Important: To configure which Input formats are safe for translation, visit the configure strings page before refreshing your strings.', array('@configure-strings' => url('admin/config/regional/i18n/strings'))) . '

    '; + $output .= '

    ' . t('Important: To configure which text formats are safe for translation, visit the configure strings page before refreshing your strings.', array('@configure-strings' => url('admin/config/regional/i18n/strings'))) . '

    '; return $output; case 'admin/config/language': $output = '

    ' . t('Warning: Changing the default language may have unwanted effects on string translations. Read more about String translation', array('@i18n_string-help' => url('admin/help/i18n_string'))) . '

    '; return $output; case 'admin/config/regional/i18n/strings': - $output = '

    ' . t('When translating user defined strings that have an Input format associated, translators will be able to edit the text before it is filtered which may be a security risk for some filters. An obvious example is when using the PHP filter but other filters may also be dangerous.') . '

    '; - $output .= '

    ' . t('As a general rule do not allow any filtered text to be translated unless the translators already have access to that Input format. However if you are doing all your translations through this site\'s translation UI or the Localization client, and never importing translations for other textgroups than default, filter access will be checked for translators on every translation page.') . '

    '; - $output .= '

    ' . t('Important: After disallowing some Input format, use the refresh strings page so forbidden strings are deleted and not allowed anymore for translators.', array('@refresh-strings' => url('admin/build/translate/refresh'))) . '

    '; + $output = '

    ' . t('When translating user defined strings that have a text format associated, translators will be able to edit the text before it is filtered which may be a security risk for some filters. An obvious example is when using the PHP filter but other filters may also be dangerous.') . '

    '; + $output .= '

    ' . t('As a general rule do not allow any filtered text to be translated unless the translators already have access to that text format. However if you are doing all your translations through this site\'s translation UI or the Localization client, and never importing translations for other textgroups than default, filter access will be checked for translators on every translation page.') . '

    '; + $output .= '

    ' . t('Important: After disallowing some text format, use the refresh strings page so forbidden strings are deleted and not allowed anymore for translators.', array('@refresh-strings' => url('admin/build/translate/refresh'))) . '

    '; return $output; case 'admin/config/filters': - return '

    ' . t('After updating your Input formats do not forget to review the list of formats allowed for string translations on the configure translatable strings page.', array('@configure-strings' => url('admin/config/regional/i18n/strings'))) . '

    '; + return '

    ' . t('After updating your text formats do not forget to review the list of formats allowed for string translations on the configure translatable strings page.', array('@configure-strings' => url('admin/config/regional/i18n/strings'))) . '

    '; } } @@ -174,17 +174,18 @@ function i18n_string_form_alter(&$form, &$form_state, $form_id) { // Replace validate callback $form['#validate'] = array('i18n_string_translate_edit_form_validate'); if ($context->format) { - $format = filter_formats($context->format); - $disabled = !filter_access($context->format); + $formats = filter_formats(); + $format = $formats[$context->format]; + $disabled = !filter_access($format); if ($disabled) { - drupal_set_message(t('This string uses the %name input format. You are not allowed to translate or edit texts with this format.', array('%name' => $format->name)), 'warning'); + drupal_set_message(t('This string uses the %name text format. You are not allowed to translate or edit texts with this format.', array('%name' => $format->name)), 'warning'); } foreach (element_children($form['translations']) as $langcode) { $form['translations'][$langcode]['#disabled'] = $disabled; } $form['translations']['format_help'] = array( '#type' => 'item', - '#title' => t('Input format: @name', array('@name' => $format->name)), + '#title' => t('Text format: @name', array('@name' => $format->name)), '#value' => theme('filter_tips', _filter_tips($context->format, FALSE)) ); $form['submit']['#disabled'] = $disabled; @@ -207,13 +208,16 @@ function i18n_string_form_alter(&$form, &$form_state, $form_id) { function i18n_string_translate_edit_form_validate($form, &$form_state) { $context = $form_state['values']['i18n_string_context']; if (empty($context->format)) { - // If not input format use regular validation for all strings + // If not text format use regular validation for all strings $copy_state = $form_state; $copy_state['values']['textgroup'] = 'default'; locale_translate_edit_form_validate($form, $copy_state); } - elseif (!filter_access($context->format)) { - form_set_error('translations', t('You are not allowed to translate or edit texts with this input format.')); + else { + $formats = filter_formats(); + if (!filter_access($formats[$context->format])) { + form_set_error('translations', t('You are not allowed to translate or edit texts with this text format.')); + } } } @@ -313,7 +317,7 @@ function i18n_string_update_object($context, $object, $properties = array()) { * Array of key => string to update multiple strings at once * @param $options * Array with additional options: - * - 'format', String format if the string has input format + * - 'format', String format if the string has text format * - 'messages', Whether to print out status messages */ function i18n_string_update($name, $string, $options = array()) { @@ -449,7 +453,7 @@ function i18n_string_modules_enabled($modules) { /** * Get translation for user defined string. * - * This function is intended to return translations for plain strings that have NO input format + * This function is intended to return translations for plain strings that have NO text format * * @param $name * Textgroup and context glued with ':' @@ -522,7 +526,7 @@ function i18n_string_format($i18nstring, $options = array()) { /** * Get filtered translation. * - * This function is intended to return translations for strings that have an input format + * This function is intended to return translations for strings that have an text format * * @param $name * Full string id @@ -627,7 +631,7 @@ function i18n_string_l10n_client_add($context, $options) { l10_client_add_string_to_page(FALSE, $context->translation, $context->textgroup); } else { - // Additional checking for input format, if its a dangerous one we ignore the string + // Additional checking for text format, if its a dangerous one we ignore the string $source = i18n_string_get_source($context); if (!empty($source) && (i18n_string_allowed_format($source->format) || filter_access($source->format))) { l10_client_add_string_to_page($string, $translation, $context->textgroup); diff --git a/i18n_sync/i18n_sync.module b/i18n_sync/i18n_sync.module index cf5fdb1439982b6a3e39479dbc33fac876659ff2..4b837623a4129dd77e797e44382acb67c3db9543 100644 --- a/i18n_sync/i18n_sync.module +++ b/i18n_sync/i18n_sync.module @@ -16,6 +16,20 @@ * @ TODO Test with CCK when possible, api may have changed. */ +/** + * Global switch to enable / disable syncing and check whether we are synching at the moment + * + * @return boolean + * TRUE if we need to run sync operations. FALSE during syncing so we don't have recursion. + */ +function i18n_sync($status = NULL) { + static $current = TRUE; + if (isset($status)) { + $current = $status; + } + return $status; +} + /** * Implements hook_help(). */ @@ -49,54 +63,66 @@ function i18n_sync_theme() { } /** - * Implements hook_form_alter(). - * - Vocabulary options - * - Content type options + * Implements hook_form_FORM_ID_alter(). */ -function i18n_sync_form_alter(&$form, $form_state, $form_id) { - // Taxonomy vocabulary form. - switch ($form_id) { - case 'node_type_form': - $type = $form['#node_type']->type; - $current = i18n_sync_node_fields($type); - $disabled = $form['i18n']['#disabled']; - $form['i18n']['i18n_sync_nodeapi'] = array( - '#type' => 'fieldset', - '#tree' => TRUE, - '#title' => t('Synchronize translations'), - '#collapsible' => TRUE, - '#collapsed' => !count($current), - '#description' => t('Select which fields to synchronize for all translations of this content type.'), - '#disabled' => $disabled, - ); - // Each set provides title and options. We build a big checkboxes control for it to be - // saved as an array. Special themeing for group titles. - foreach (i18n_sync_node_available_fields($type) as $group => $data) { - $title = $data['#title']; - if (!empty($data['#options'])) { - foreach ($data['#options'] as $field => $name) { - $form['i18n']['i18n_sync_nodeapi'][$field] = array( - '#group_title' => $title, - '#title' => $name, - '#type' => 'checkbox', - '#default_value' => in_array($field, $current), - '#theme' => 'i18n_sync_workflow_checkbox', - '#disabled' => $disabled, - ); - $title = ''; - } +function i18n_sync_form_node_admin_content_alter(&$form, &$form_state) { + if (!empty($form['operation']) && $form['operation']['#value'] == 'delete') { + $form['#submit'] = array_merge(array('i18n_sync_node_delete_submit'), $form['#submit']); + } +} + +/** + * Implements hook_form_FORM_ID_alter(). + */ +function i18n_sync_form_node_delete_confirm_alter(&$form, &$form_state) { + // Intercept form submission so we can handle uploads, replace callback + $form['#submit'] = array_merge(array('i18n_sync_node_delete_submit'), $form['#submit']); +} + + + +/** + * Implements hook_form_FORM_ID_alter(). + */ +function i18n_sync_form_node_type_form_alter(&$form, &$form_state) { + if (isset($form['type'])) { + $type = $form['#node_type']->type; + $disabled = !translation_supported_type($type); + $form['i18n_sync'] = array( + '#type' => 'fieldset', + '#title' => t('Synchronize translations'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#group' => 'additional_settings', + '#attributes' => array( + 'class' => array('i18n-node-type-settings-form'), + ), + '#description' => t('Select which fields to synchronize for all translations of this content type.'), + '#disabled' => $disabled, + ); + $form['i18n_sync']['i18n_sync_node_type'] = array( + '#title' => t('Synchronize fields'), + '#type' => 'fieldset', + '#tree' => TRUE, + ); + // Each set provides title and options. We build a big checkboxes control for it to be + // saved as an array. Special themeing for group titles. + foreach (i18n_sync_node_available_fields($type) as $group => $data) { + $title = $data['#title']; + if (!empty($data['#options'])) { + foreach ($data['#options'] as $field => $name) { + $form['i18n_sync']['i18n_sync_nodeapi'][$field] = array( + '#group_title' => $title, + '#title' => $name, + '#type' => 'checkbox', + '#default_value' => in_array($field, $current), + '#theme' => 'i18n_sync_workflow_checkbox', + '#disabled' => $disabled, + ); + $title = ''; } } - break; - case 'node_delete_confirm': - // Intercept form submission so we can handle uploads, replace callback - $form['#submit'] = array_merge(array('i18n_sync_node_delete_submit'), $form['#submit']); - break; - case 'node_admin_content': - if (!empty($form['operation']) && $form['operation']['#value'] == 'delete') { - $form['#submit'] = array_merge(array('i18n_sync_node_delete_submit'), $form['#submit']); - } - break; + } } } @@ -146,97 +172,98 @@ function theme_i18n_sync_workflow_checkbox($element) { } /** - * Implements hook_nodeapi(). + * Check whether this node is to be synced */ -function i18n_sync_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { - global $i18n_sync; // This variable will be true when a sync operation is in progress. - - // Only for nodes that have language and belong to a translation set. - if (translation_supported_type($node->type) && !empty($node->language) && !$i18n_sync) { - switch ($op) { - case 'load': - // Add instance count for cck fields so we can use the information later, see hook_file_references() - if (!empty($node->tnid) && ($sync_fields = i18n_sync_node_fields($node->type)) && ($content_fields = _i18n_sync_cck_fields($node->type))) { - if ($translations = _i18n_sync_node_translations($node, TRUE)) { - $count = count($translations); - foreach ($sync_fields as $field) { - if (isset($content_fields[$field]) && !empty($node->$field) && is_array($node->$field)) { - // The node field should be an array with one or more fields - // Reminder: Use brackets for $node->{$field}[$key] as $node->$field[$key] won't work - foreach (array_keys($node->$field) as $key) { - if (is_array($node->{$field}[$key])) { - $node->{$field}[$key]['i18n_sync'] = $count; - } - } - } - } - } - } - break; +function i18n_sync_node_check($node) { + return translation_supported_type($node->type) && !empty($node->language) && i18n_sync(); +} - case 'prepare translation': - // We copy over all the fields to be synchronized. - if ($fields = i18n_sync_node_fields($node->type)) { - i18n_sync_prepare_translation($node, $node->translation_source, $fields); - } - break; - - case 'insert': - // When creating a translation, there are some aditional steps, different from update - if (!empty($node->translation_source)) { - // Set tnid that is not set by translation module - $node->tnid = $node->translation_source->tnid ? $node->translation_source->tnid : $node->translation_source->nid; - // If we have files, we need to save the files that have been inherited - if (!empty($node->files) && i18n_sync_node_fields($node->type, 'files')) { - foreach ($node->files as $fid => $file) { - $file = (object)$file; - if (empty($file->remove) && empty($file->new)) { - db_query("INSERT INTO {upload} (fid, nid, vid, list, description, weight) VALUES (%d, %d, %d, %d, '%s', %d)", $file->fid, $node->nid, $node->vid, $file->list, $file->description, $file->weight); - } +/** + * Implements hook_node_load(). + */ +function i18n_sync_node_load($node) { + // Add instance count for cck fields so we can use the information later, see hook_file_references() + if (i18n_sync_node_check($node) && !empty($node->tnid) && ($sync_fields = i18n_sync_node_fields($node->type)) && ($content_fields = _i18n_sync_cck_fields($node->type))) { + if ($translations = _i18n_sync_node_translations($node, TRUE)) { + $count = count($translations); + foreach ($sync_fields as $field) { + if (isset($content_fields[$field]) && !empty($node->$field) && is_array($node->$field)) { + // The node field should be an array with one or more fields + // Reminder: Use brackets for $node->{$field}[$key] as $node->$field[$key] won't work + foreach (array_keys($node->$field) as $key) { + if (is_array($node->{$field}[$key])) { + $node->{$field}[$key]['i18n_sync'] = $count; } } } - // Intentional no break. - case 'update': - // Let's go with field synchronization. - if (!empty($node->tnid) && ($fields = i18n_sync_node_fields($node->type)) && ($translations = _i18n_sync_node_translations($node, TRUE))) { - $i18n_sync = TRUE; - $count = 0; - // If we have fields we need to reload them so we have the full data (fid, etc...) - if (!empty($node->files) && in_array('files', $fields)) { - $node->files = upload_load($node); - } - // Disable language selection temporarily, enable it again later - i18n_selection_mode('off'); - foreach ($translations as $trnode) { - if ($node->nid != $trnode->nid) { - i18n_sync_node_translation($node, $trnode, $fields, $op); - $count++; - } - } - i18n_selection_mode('reset'); - $i18n_sync = FALSE; - drupal_set_message(format_plural($count, 'One node translation has been synchronized.', 'All @count node translations have been synchronized.')); + } + } + } +} + +/** + * Implements hook_node_insert(). + */ +function i18n_sync_node_insert($node) { + // When creating a translation, there are some aditional steps, different from update + if (i18n_sync_node_check($node) && !empty($node->translation_source)) { + // Set tnid that is not set by translation module + $node->tnid = $node->translation_source->tnid ? $node->translation_source->tnid : $node->translation_source->nid; + // If we have files, we need to save the files that have been inherited + if (!empty($node->files) && i18n_sync_node_fields($node->type, 'files')) { + foreach ($node->files as $fid => $file) { + $file = (object)$file; + if (empty($file->remove) && empty($file->new)) { + db_query("INSERT INTO {upload} (fid, nid, vid, list, description, weight) VALUES (%d, %d, %d, %d, '%s', %d)", $file->fid, $node->nid, $node->vid, $file->list, $file->description, $file->weight); } - break; + } } - } + i18n_sync_node_update($node); + } } /** - * Prepare node translation. Copy over sincronizable fields. + * Implements hook_node_update(). */ -function i18n_sync_prepare_translation(&$node, $source, $field_list) { - foreach ($field_list as $field) { - if (empty($source->$field)) continue; - switch ($field) { - case 'taxonomy': - // Do nothing, this is handled by the i18n_taxonomy module - break; - - default: - $node->$field = $source->$field; - break; +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_translations($node, TRUE))) { + i18n_sync(FALSE); + $count = 0; + // If we have fields we need to reload them so we have the full data (fid, etc...) + if (!empty($node->files) && in_array('files', $fields)) { + $node->files = upload_load($node); + } + // Disable language selection temporarily, enable it again later + i18n_select(FALSE); + foreach ($translations as $trnode) { + if ($node->nid != $trnode->nid) { + i18n_sync_node_translation($node, $trnode, $fields, $op); + $count++; + } + } + i18n_select(TRUE); + i18n_sync(TRUE); + drupal_set_message(format_plural($count, 'One node translation has been synchronized.', 'All @count node translations have been synchronized.')); + } +} + +/** + * Implements hook_node_prepare(). + */ +function i18n_sync_node_prepare($node) { + // If creating a translation, copy over all the fields to be synchronized. + if (empty($node->nid) && !empty($node->translation_source) && ($sync_fields = i18n_sync_node_fields($node->type))) { + foreach ($field_list as $field) { + if (empty($node->translation_source->$field)) continue; + switch ($field) { + case 'taxonomy': + // Do nothing, this is handled by the i18n_taxonomy module + break; + default: + $node->$field = $node->translation_source->$field; + break; + } } } } @@ -515,7 +542,7 @@ function i18n_sync_node_available_fields($type) { 'timezone' => t('Timezone') ); } - +/* // Get CCK fields. if (($contentfields = _i18n_sync_cck_fields($type))) { // Get context information. @@ -525,7 +552,7 @@ function i18n_sync_node_available_fields($type) { $fields['cck']['#options'][$data['field_name']] = $data['widget']['label']; } } - +*/ // Give a chance to modules to change/remove/add their own fields drupal_alter('i18n_sync_fields', $fields, $type); diff --git a/i18n_taxonomy/i18n_taxonomy.module b/i18n_taxonomy/i18n_taxonomy.module index 875eac15120c78a553c5908ccb5a642b46d6cd78..93f0525d97a441302762d9ae29a0bad70ba8f058 100644 --- a/i18n_taxonomy/i18n_taxonomy.module +++ b/i18n_taxonomy/i18n_taxonomy.module @@ -16,18 +16,6 @@ * @author Jose A. Reyero, 2004 */ -/** - * Modes for multilingual vocabularies. - */ -// No multilingual options -define('I18N_TAXONOMY_NONE', 0); -// Run through the localization system -define('I18N_TAXONOMY_LOCALIZE', 1); -// Predefined language for all terms -define('I18N_TAXONOMY_LANGUAGE', 2); -// Multilingual terms, translatable -define('I18N_TAXONOMY_TRANSLATE', 3); - /** * Implements hook_help(). */ @@ -53,13 +41,13 @@ function i18n_taxonomy_help($path, $arg) { case 'admin/content/taxonomy/%': $vocabulary = taxonomy_vocabulary_load($arg[3]); switch (i18n_taxonomy_vocabulary_mode($vocabulary->vid)) { - case I18N_TAXONOMY_LOCALIZE: + case I18N_MODE_LOCALIZE: return '

    '. t('%capital_name is a localizable vocabulary. You will be able to translate term names and descriptions using the translate interface pages.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name, '@translate-interface' => url('admin/build/translate'))) .'

    '; - case I18N_TAXONOMY_LANGUAGE: + case I18N_MODE_LANGUAGE: return '

    '. t('%capital_name is a vocabulary with a fixed language. All the terms in this vocabulary will have %language language.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name, '%language' => i18n_language_property($vocabulary->language, 'name'))) .'

    '; - case I18N_TAXONOMY_TRANSLATE: + case I18N_MODE_TRANSLATE: return '

    '. t('%capital_name is a full multilingual vocabulary. You will be able to set a language for each term and create translation relationships.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) .'

    '; } @@ -71,10 +59,10 @@ function i18n_taxonomy_help($path, $arg) { */ function _i18n_taxonomy_vocabulary_options() { return array( - I18N_TAXONOMY_NONE => t('None. No multilingual options for this vocabulary.'), - I18N_TAXONOMY_LOCALIZE => t('Localize terms. Terms are common for all languages, but their name and description may be localized.'), - I18N_TAXONOMY_TRANSLATE => t('Per language terms. Different terms will be allowed for each language and they can be translated.'), - I18N_TAXONOMY_LANGUAGE => t('Set language to vocabulary. The vocabulary will have a global language and it will only show up for pages in that language.'), + I18N_MODE_NONE => t('None. No multilingual options for this vocabulary.'), + I18N_MODE_LOCALIZE => t('Localize terms. Terms are common for all languages, but their name and description may be localized.'), + I18N_MODE_TRANSLATE => t('Per language terms. Different terms will be allowed for each language and they can be translated.'), + I18N_MODE_LANGUAGE => t('Set language to vocabulary. The vocabulary will have a global language and it will only show up for pages in that language.'), ); } @@ -119,7 +107,7 @@ function i18n_taxonomy_menu_alter(&$items) { * Menu access callback. Show tab only for full multilingual vocabularies. */ function _i18n_taxonomy_translation_tab($vocabulary) { - return i18n_taxonomy_vocabulary_mode($vocabulary->vid) == I18N_TAXONOMY_TRANSLATE; + return i18n_taxonomy_vocabulary_mode($vocabulary->vid) & I18N_MODE_TRANSLATE; } /** @@ -148,7 +136,7 @@ function i18n_taxonomy_i18n_string_refresh($group) { i18n_string_update("taxonomy:vocabulary:$vid:description", $vocabulary->help); } } - if (i18n_taxonomy_vocabulary_mode($vid) == I18N_TAXONOMY_LOCALIZE) { + if (i18n_taxonomy_vocabulary_mode($vid) & I18N_MODE_LOCALIZE) { foreach (taxonomy_get_tree($vid, 0) as $term) { i18n_string_update("taxonomy:term:$term->tid:name", $term->name); if ($term->description) { @@ -199,7 +187,7 @@ function i18n_taxonomy_theme() { function i18n_taxonomy_translate_term_name($tid, $name = '', $langcode = NULL) { // If it is a term object we check for vocabulary options if (is_object($tid)) { - return i18n_taxonomy_vocabulary_mode($tid->vid) == I18N_TAXONOMY_LOCALIZE ? i18n_string_plain("taxonomy:term:$tid->tid:name", $tid->name, $langcode, TRUE) : check_plain($tid->name); + return i18n_taxonomy_vocabulary_mode($tid->vid) & I18N_MODE_LOCALIZE ? i18n_string_plain("taxonomy:term:$tid->tid:name", $tid->name, $langcode, TRUE) : check_plain($tid->name); } else { return i18n_string("taxonomy:term:$tid:name", $name, $langcode); @@ -271,9 +259,12 @@ function i18n_taxonomy_taxonomy_term_insert($term) { * Implements hook_taxonomy_term_update() */ function i18n_taxonomy_taxonomy_term_update($term) { - if (i18n_taxonomy_vocabulary_mode($term->vid) == I18N_TAXONOMY_LOCALIZE) { + if (i18n_taxonomy_vocabulary_mode($term->vid) & I18N_MODE_LOCALIZE) { i18n_string_update(array('taxonomy', 'term', $term->tid, 'name'), $term->name); - i18n_string_update(array('taxonomy', 'term', $term->tid, 'description'), $term->description, array('format' => $term->format)); + // Sometimes, like when tagging content we have no description. + if (isset($term->description)) { + i18n_string_update(array('taxonomy', 'term', $term->tid, 'description'), $term->description, array('format' => $term->format)); + } } } @@ -297,10 +288,10 @@ function i18n_taxonomy_taxonomy_vocabulary_insert($vocabulary) { function i18n_taxonomy_taxonomy_vocabulary_udpate($vocabulary) { // Update language for related terms switch ($vocabulary->i18n_mode) { - case I18N_TAXONOMY_LANGUAGE: + case I18N_MODE_LANGUAGE: $update['language'] = $vocabulary->language; break; - case I18N_TAXONOMY_NONE: + case I18N_MODE_NONE: $update['language'] = ''; break; } @@ -332,10 +323,10 @@ function i18n_taxonomy_taxonomy_vocabulary_delete($vocabulary) { */ function i18n_taxonomy_taxonomy_term_presave($term) { switch (i18n_taxonomy_vocabulary_mode($term->vid)) { - case I18N_TAXONOMY_LANGUAGE; // Predefined language for all terms + case I18N_MODE_LANGUAGE; // Predefined language for all terms $term->language = taxonomy_vocabulary_load($term->vid)->language; break; - case I18N_TAXONOMY_TRANSLATE: // Multilingual terms, translatable + case I18N_MODE_TRANSLATE: // Multilingual terms, translatable if (!isset($term->language)) { // The term may come from a node tags field, just if this is not a taxonomy form $term->language = i18n_langcode(); @@ -354,7 +345,7 @@ function i18n_taxonomy_taxonomy_term_presave($term) { function i18n_taxonomy_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) { $vocabulary = $form_state['vocabulary']; drupal_add_js(drupal_get_path('module', 'i18n_taxonomy') . '/i18n_taxonomy.js'); - drupal_add_js(array('i18n_taxonomy_vocabulary_form' => array('I18N_TAXONOMY_LANGUAGE' => I18N_TAXONOMY_LANGUAGE)), 'setting'); + drupal_add_js(array('i18n_taxonomy_vocabulary_form' => array('I18N_MODE_LANGUAGE' => I18N_MODE_LANGUAGE)), 'setting'); $form['i18n'] = array( '#type' => 'fieldset', '#title' => t('Multilingual options'), @@ -374,7 +365,7 @@ function i18n_taxonomy_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) '#default_value' => $vocabulary && !empty($vocabulary->language) ? $vocabulary->language : '', '#options' => array('' => '') + i18n_language_list(), '#description' => t('Language for this vocabulary. If set, it will apply to all terms in this vocabulary.'), - '#disabled' => ($vocabulary && $vocabulary->i18n_mode != I18N_TAXONOMY_LANGUAGE), + '#disabled' => ($vocabulary && $vocabulary->i18n_mode != I18N_MODE_LANGUAGE), ); $form['#validate'][] = 'i18n_taxonomy_form_vocabulary_validate'; } @@ -394,7 +385,7 @@ 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_TAXONOMY_TRANSLATE: + case I18N_MODE_TRANSLATE: $form['language'] = array( '#type' => 'select', '#title' => t('Language'), @@ -404,7 +395,7 @@ function i18n_taxonomy_form_taxonomy_form_term_alter(&$form, &$form_state) { ); break; - case I18N_TAXONOMY_LANGUAGE: + case I18N_MODE_LANGUAGE: $form['language'] = array( '#type' => 'value', '#value' => $vocabulary->language @@ -412,7 +403,7 @@ function i18n_taxonomy_form_taxonomy_form_term_alter(&$form, &$form_state) { $form['identification']['language_info'] = array('#value' => t('All terms in this vocabulary have a fixed language: %language', array('%language' => i18n_language_property($vocabulary->language, 'name')))); break; - case I18N_TAXONOMY_LOCALIZE: + case I18N_MODE_LOCALIZE: $form['language'] = array( '#type' => 'value', '#value' => '' @@ -421,7 +412,7 @@ function i18n_taxonomy_form_taxonomy_form_term_alter(&$form, &$form_state) { i18n_string_element_mark($form['description']); break; - case I18N_TAXONOMY_NONE: + case I18N_MODE_NONE: default: $form['language'] = array( '#type' => 'value', @@ -450,7 +441,7 @@ function i18n_taxonomy_form_alter(&$form, $form_state, $form_id) { break; case 'taxonomy_overview_terms': - if (i18n_taxonomy_vocabulary_mode($form['#vocabulary']->vid) == I18N_TAXONOMY_TRANSLATE) { + if (i18n_taxonomy_vocabulary_mode($form['#vocabulary']->vid) & I18N_MODE_TRANSLATE) { foreach (element_children($form) as $key) { if (isset($form[$key]['#term']) && ($lang = $form[$key]['#term']->language)) { $form[$key]['view']['#value'] .= ' ('. i18n_language_name($lang) .')'; @@ -477,10 +468,10 @@ function i18n_taxonomy_form_alter(&$form, $form_state, $form_id) { function i18n_taxonomy_form_vocabulary_validate($form, &$form_state) { $language = !empty($form_state['values']['language']) ? $form_state['values']['language'] : ''; $mode = $form_state['values']['i18n_mode']; - if ($mode != I18N_TAXONOMY_LANGUAGE && $language) { + if ($mode != I18N_MODE_LANGUAGE && $language) { form_set_error('language', t('Setting a vocabulary language only makes sense in the "Set language to vocabulary" translation mode. Either change to this mode or do not select a language.')); } - elseif ($mode == I18N_TAXONOMY_LANGUAGE && !$language ) { + elseif ($mode == I18N_MODE_LANGUAGE && !$language ) { form_set_error('language', t('If selecting "Set language to vocabulary" you need to set a language to this vocabulary. Either change the translation mode or select a language.')); } } @@ -502,7 +493,7 @@ function i18n_taxonomy_form_all_localize(&$item) { $options[$vname] = $options[$vocabulary->name]; unset($options[$vocabulary->name]); } - if (i18n_taxonomy_vocabulary_mode($vid) == I18N_TAXONOMY_LOCALIZE) { + if (i18n_taxonomy_vocabulary_mode($vid) & I18N_MODE_LOCALIZE) { $tree = taxonomy_get_tree($vid); if ($tree && (count($tree) > 0)) { foreach ($tree as $term) { @@ -537,16 +528,16 @@ function i18n_taxonomy_node_form(&$form) { // Special treatment for tags, add some help texts foreach (element_children($form['taxonomy']['tags']) as $vid) { $type = i18n_taxonomy_vocabulary_mode($vid); - if ($type == I18N_TAXONOMY_LOCALIZE || $type == I18N_TAXONOMY_TRANSLATE) { + if ($type == I18N_MODE_LOCALIZE || $type == I18N_MODE_TRANSLATE) { $form['taxonomy']['tags'][$vid]['#title'] = i18n_taxonomy_translate_vocabulary_name($vid, $form['taxonomy']['tags'][$vid]['#title']); $form['taxonomy']['tags'][$vid]['#description'] = i18n_string("taxonomy:vocabulary:$vid:help", $form['taxonomy']['tags'][$vid]['#description']); } - if ($type == I18N_TAXONOMY_LOCALIZE) { + if ($type == I18N_MODE_LOCALIZE) { $form['taxonomy']['tags'][$vid]['#description'] .= ' '. t('This is a localizable vocabulary, so only terms in %language are allowed here.', array('%language' => language_default('name'))); } } } - elseif (is_numeric($vid) && i18n_taxonomy_vocabulary_mode($vid) == I18N_TAXONOMY_LOCALIZE) { + elseif (is_numeric($vid) && i18n_taxonomy_vocabulary_mode($vid) == I18N_MODE_LOCALIZE) { // Rebuild this vocabulary's form. $vocabulary = taxonomy_vocabulary_load($vid); // Extract terms belonging to the vocabulary in question. @@ -561,7 +552,7 @@ function i18n_taxonomy_node_form(&$form) { $form['taxonomy'][$vid]['#required'] = $vocabulary->required; $form['taxonomy'][$vid]['#description'] = i18n_string("taxonomy:vocabulary:$vid:help", $vocabulary->help); } - elseif (is_numeric($vid) && i18n_taxonomy_vocabulary_mode($vid) == I18N_TAXONOMY_TRANSLATE) { + elseif (is_numeric($vid) && i18n_taxonomy_vocabulary_mode($vid) == I18N_MODE_TRANSLATE) { // Rebuild this vocabulary's form. $vocabulary = taxonomy_vocabulary_load($vid); $form['taxonomy'][$vid]['#title'] = i18n_taxonomy_translate_vocabulary_name($vid, $vocabulary->name); @@ -764,7 +755,7 @@ function i18n_taxonomy_translate_terms($taxonomy, $langcode, $fullterms = TRUE) $mode = i18n_taxonomy_vocabulary_mode($index); // We translate just some vocabularies: translatable, fixed language // Fixed language ones may have terms translated, though the UI doesn't support it - if ($mode == I18N_TAXONOMY_LANGUAGE || $mode == I18N_TAXONOMY_TRANSLATE) { + if ($mode == I18N_MODE_LANGUAGE || $mode == I18N_MODE_TRANSLATE) { $translation[$index] = i18n_taxonomy_translate_terms($tdata, $langcode, $filter, $fullterms); } elseif ($fullterms) { @@ -817,7 +808,7 @@ function i18n_taxonomy_translate_terms($taxonomy, $langcode, $fullterms = TRUE) function i18n_taxonomy_localize_terms($terms, $fields = array('name')) { $terms = is_array($terms) ? $terms : array($terms); foreach ($terms as $index => $term) { - if (i18n_taxonomy_vocabulary_mode($term->vid) === I18N_TAXONOMY_LOCALIZE) { + if (i18n_taxonomy_vocabulary_mode($term->vid) === I18N_MODE_LOCALIZE) { foreach ($fields as $property) { $term->$property = i18n_string(array('taxonomy', 'term', $term->tid, $property), $term->$property); } diff --git a/i18n_taxonomy/i18n_taxonomy.pages.inc b/i18n_taxonomy/i18n_taxonomy.pages.inc index 7259720f31fa4790386a02c82c2367007afa40b1..6655928091a8b06a0bded5938e16127dd878e697 100644 --- a/i18n_taxonomy/i18n_taxonomy.pages.inc +++ b/i18n_taxonomy/i18n_taxonomy.pages.inc @@ -79,7 +79,7 @@ function theme_i18n_taxonomy_term_page($tids, $result) { // Only display the description if we have a single term, to avoid clutter and confusion. if (count($tids) == 1) { $term = taxonomy_get_term($tids[0]); - if (i18n_taxonomy_vocabulary($term->vid) == I18N_TAXONOMY_LOCALIZE) { + if (i18n_taxonomy_vocabulary($term->vid) & I18N_MODE_LOCALIZE) { $description = i18n_string("taxonomy:term:$term->tid:description", $term->description); } else { diff --git a/tests/i18n_blocks.test b/tests/i18n_blocks.test index 12265fd1d2f8a2cf7ef47c0ef94744d3b9b5ef82..c1de3042fb602f6b5dceae1ab8dc6cf42a44bad9 100644 --- a/tests/i18n_blocks.test +++ b/tests/i18n_blocks.test @@ -66,7 +66,7 @@ class i18n_Blocks_Test extends Drupali18nTestCase { $this->assertTrue(i18n_string_get_source("blocks:user:1:title"), "We have a string for the Navigation block title"); $this->assertTrue(i18n_string_get_source("blocks:block:$box2->bid:title", $box2->title), "The string for the second box title is still there."); $this->assertTrue(i18n_string_get_source("blocks:block:$box2->bid:body", $box2->body), "The string for the second box body is still there."); - // Test a block with filtering and input formats + // Test a block with filtering and text formats $box3 = $this->i18nCreateBox(array( 'title' => '
    Title', 'body' => "One line\nTwo lines", diff --git a/tests/i18n_test.info b/tests/i18n_test.info index e63aee1c47fb38227728fc68103586ea35f7500d..f1df76c26004a5fc65bcaa3a5b518f9f96e03379 100644 --- a/tests/i18n_test.info +++ b/tests/i18n_test.info @@ -6,3 +6,4 @@ dependencies[] = translation dependencies[] = i18n package = Testing core = 6.x +hidden = TRUE