#565480 by plach and peximo: TF #2: Multilingual field handling. Integration between field API and locale module + translatable node bodies.
parent
5faaa376aa
commit
6061fa9781
|
@ -1627,7 +1627,7 @@ function drupal_language_initialize() {
|
||||||
|
|
||||||
// Ensure the language is correctly returned, even without multilanguage support.
|
// Ensure the language is correctly returned, even without multilanguage support.
|
||||||
// Useful for eg. XML/HTML 'lang' attributes.
|
// Useful for eg. XML/HTML 'lang' attributes.
|
||||||
if (variable_get('language_count', 1) == 1) {
|
if (!drupal_multilingual()) {
|
||||||
$default = language_default();
|
$default = language_default();
|
||||||
foreach ($types as $type) {
|
foreach ($types as $type) {
|
||||||
$GLOBALS[$type] = $default;
|
$GLOBALS[$type] = $default;
|
||||||
|
@ -1656,6 +1656,17 @@ function drupal_language_types() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if there is more than one language enabled.
|
||||||
|
*/
|
||||||
|
function drupal_multilingual() {
|
||||||
|
static $multilingual;
|
||||||
|
if (!isset($multilingual)) {
|
||||||
|
$multilingual = variable_get('language_count', 1) > 1;
|
||||||
|
}
|
||||||
|
return $multilingual;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of the available language types.
|
* Return an array of the available language types.
|
||||||
*/
|
*/
|
||||||
|
@ -1672,7 +1683,7 @@ function language_list($field = 'language') {
|
||||||
$languages = &drupal_static(__FUNCTION__);
|
$languages = &drupal_static(__FUNCTION__);
|
||||||
// Init language list
|
// Init language list
|
||||||
if (!isset($languages)) {
|
if (!isset($languages)) {
|
||||||
if (variable_get('language_count', 1) > 1 || module_exists('locale')) {
|
if (drupal_multilingual() || module_exists('locale')) {
|
||||||
$languages['language'] = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
|
$languages['language'] = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -396,3 +396,36 @@ function language_url_split_prefix($path, $languages) {
|
||||||
|
|
||||||
return array(FALSE, $path);
|
return array(FALSE, $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the possible fallback languages ordered by language weight.
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* The language type.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* An array of language codes.
|
||||||
|
*/
|
||||||
|
function language_fallback_get_candidates($type = LANGUAGE_TYPE_CONTENT) {
|
||||||
|
$fallback_candidates = &drupal_static(__FUNCTION__);
|
||||||
|
|
||||||
|
if (!isset($fallback_candidates)) {
|
||||||
|
$fallback_candidates = array();
|
||||||
|
|
||||||
|
// Get languages ordered by weight.
|
||||||
|
// Use array keys to avoid duplicated entries.
|
||||||
|
foreach (language_list('weight') as $languages) {
|
||||||
|
foreach ($languages as $language) {
|
||||||
|
$fallback_candidates[$language->language] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$fallback_candidates = array_keys($fallback_candidates);
|
||||||
|
$fallback_candidates[] = FIELD_LANGUAGE_NONE;
|
||||||
|
|
||||||
|
// Let other modules hook in and add/change candidates.
|
||||||
|
drupal_alter('language_get_fallback_candidates', $fallback_candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $fallback_candidates;
|
||||||
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ function locale_languages_overview_form_submit($form, &$form_state) {
|
||||||
|
|
||||||
// Changing the language settings impacts the interface.
|
// Changing the language settings impacts the interface.
|
||||||
cache_clear_all('*', 'cache_page', TRUE);
|
cache_clear_all('*', 'cache_page', TRUE);
|
||||||
|
module_invoke_all('multilingual_settings_changed');
|
||||||
|
|
||||||
$form_state['redirect'] = 'admin/config/regional/language';
|
$form_state['redirect'] = 'admin/config/regional/language';
|
||||||
return;
|
return;
|
||||||
|
@ -362,6 +363,8 @@ function locale_languages_predefined_form_submit($form, &$form_state) {
|
||||||
batch_set($batch);
|
batch_set($batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_invoke_all('multilingual_settings_changed');
|
||||||
|
|
||||||
$form_state['redirect'] = 'admin/config/regional/language';
|
$form_state['redirect'] = 'admin/config/regional/language';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -469,6 +472,7 @@ function locale_languages_delete_form_submit($form, &$form_state) {
|
||||||
->fields(array('language' => ''))
|
->fields(array('language' => ''))
|
||||||
->condition('language', $form_state['values']['langcode'])
|
->condition('language', $form_state['values']['langcode'])
|
||||||
->execute();
|
->execute();
|
||||||
|
module_invoke_all('multilingual_settings_changed');
|
||||||
$variables = array('%locale' => $languages[$form_state['values']['langcode']]->name);
|
$variables = array('%locale' => $languages[$form_state['values']['langcode']]->name);
|
||||||
drupal_set_message(t('The language %locale has been removed.', $variables));
|
drupal_set_message(t('The language %locale has been removed.', $variables));
|
||||||
watchdog('locale', 'The language %locale has been removed.', $variables);
|
watchdog('locale', 'The language %locale has been removed.', $variables);
|
||||||
|
|
|
@ -147,7 +147,7 @@ function _field_info_collate_types($reset = FALSE) {
|
||||||
// Provide defaults.
|
// Provide defaults.
|
||||||
$entity_info += array(
|
$entity_info += array(
|
||||||
'cacheable' => TRUE,
|
'cacheable' => TRUE,
|
||||||
'translation_handlers' => array(),
|
'translation' => array(),
|
||||||
'bundles' => array(),
|
'bundles' => array(),
|
||||||
);
|
);
|
||||||
$entity_info['object keys'] += array(
|
$entity_info['object keys'] += array(
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
* Multilingual field API helper functions.
|
* Multilingual field API helper functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement hook_multilingual_settings_changed().
|
||||||
|
*/
|
||||||
|
function field_multilingual_settings_changed() {
|
||||||
|
cache_clear_all('field_info_types', 'cache_field');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect the available languages for the given entity type and field.
|
* Collect the available languages for the given entity type and field.
|
||||||
*
|
*
|
||||||
|
@ -31,12 +38,14 @@ function field_multilingual_available_languages($obj_type, $field, $suggested_la
|
||||||
$field_name = $field['field_name'];
|
$field_name = $field['field_name'];
|
||||||
|
|
||||||
if (!isset($field_languages[$field_name]) || !empty($suggested_languages)) {
|
if (!isset($field_languages[$field_name]) || !empty($suggested_languages)) {
|
||||||
$obj_info = field_info_fieldable_types($obj_type);
|
$translation_handlers = field_multilingual_check_translation_handlers($obj_type);
|
||||||
if (!empty($obj_info['translation_handlers']) && $field['translatable']) {
|
|
||||||
$available_languages = field_multilingual_content_languages();
|
if ($translation_handlers && $field['translatable']) {
|
||||||
// The returned languages are a subset of the intersection of enabled ones
|
// The returned languages are a subset of the intersection of enabled ones
|
||||||
// and suggested ones.
|
// and suggested ones.
|
||||||
|
$available_languages = field_multilingual_content_languages();
|
||||||
$languages = !empty($suggested_languages) ? $available_languages = array_intersect($available_languages, $suggested_languages) : $available_languages;
|
$languages = !empty($suggested_languages) ? $available_languages = array_intersect($available_languages, $suggested_languages) : $available_languages;
|
||||||
|
|
||||||
foreach (module_implements('field_languages') as $module) {
|
foreach (module_implements('field_languages') as $module) {
|
||||||
$function = $module . '_field_languages';
|
$function = $module . '_field_languages';
|
||||||
$function($obj_type, $field, $languages);
|
$function($obj_type, $field, $languages);
|
||||||
|
@ -71,20 +80,36 @@ function field_multilingual_content_languages() {
|
||||||
return array_keys(language_list() + array(FIELD_LANGUAGE_NONE => NULL));
|
return array_keys(language_list() + array(FIELD_LANGUAGE_NONE => NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a module is registered as a translation handler for a given entity.
|
* Check if a module is registered as a translation handler for a given entity.
|
||||||
*
|
*
|
||||||
|
* If no handler is passed, simply check if there is any translation handler
|
||||||
|
* enabled for the given entity type.
|
||||||
|
*
|
||||||
* @param $obj_type
|
* @param $obj_type
|
||||||
* The type of the entity whose fields are to be translated.
|
* The type of the entity whose fields are to be translated.
|
||||||
* @param $handler
|
* @param $handler
|
||||||
* The name of the handler to be checked.
|
* The name of the handler to be checked.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* TRUE, if the handler is allowed to manage field translations.
|
* TRUE, if the handler is allowed to manage field translations.
|
||||||
*/
|
*/
|
||||||
function field_multilingual_check_translation_handler($obj_type, $handler) {
|
function field_multilingual_check_translation_handlers($obj_type, $handler = NULL) {
|
||||||
$obj_info = field_info_fieldable_types($obj_type);
|
$obj_info = field_info_fieldable_types($obj_type);
|
||||||
return isset($obj_info['translation_handlers'][$handler]);
|
|
||||||
|
if (isset($handler)) {
|
||||||
|
return isset($obj_info['translation'][$handler]) && !empty($obj_info['translation'][$handler]);
|
||||||
|
}
|
||||||
|
elseif (isset($obj_info['translation'])) {
|
||||||
|
foreach ($obj_info['translation'] as $handler_info) {
|
||||||
|
// The translation handler must use a non-empty data structure.
|
||||||
|
if (!empty($handler_info)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2272,11 +2272,12 @@ class FieldTranslationsTestCase extends FieldTestCase {
|
||||||
*/
|
*/
|
||||||
function testFieldAvailableLanguages() {
|
function testFieldAvailableLanguages() {
|
||||||
// Test 'translatable' fieldable info.
|
// Test 'translatable' fieldable info.
|
||||||
|
field_test_entity_info_translatable('test_entity', FALSE);
|
||||||
$field = $this->field;
|
$field = $this->field;
|
||||||
$field['field_name'] .= '_untranslatable';
|
$field['field_name'] .= '_untranslatable';
|
||||||
$langcode = language_default();
|
$langcode = language_default();
|
||||||
$suggested_languages = array($langcode->language);
|
$suggested_languages = array($langcode->language);
|
||||||
$available_languages = field_multilingual_available_languages($this->obj_type, $field);
|
$available_languages = field_multilingual_available_languages($this->obj_type, $field, $suggested_languages);
|
||||||
$this->assertTrue(count($available_languages) == 1 && $available_languages[0] === FIELD_LANGUAGE_NONE, t('Untranslatable entity: suggested language ignored.'));
|
$this->assertTrue(count($available_languages) == 1 && $available_languages[0] === FIELD_LANGUAGE_NONE, t('Untranslatable entity: suggested language ignored.'));
|
||||||
|
|
||||||
// Enable field translations for the entity.
|
// Enable field translations for the entity.
|
||||||
|
@ -2411,7 +2412,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
|
||||||
// Enable field translations for nodes.
|
// Enable field translations for nodes.
|
||||||
field_test_entity_info_translatable('node', TRUE);
|
field_test_entity_info_translatable('node', TRUE);
|
||||||
$obj_info = field_info_fieldable_types('node');
|
$obj_info = field_info_fieldable_types('node');
|
||||||
$this->assertTrue(count($obj_info['translation_handlers']), t('Nodes are translatable.'));
|
$this->assertTrue(count($obj_info['translation']), t('Nodes are translatable.'));
|
||||||
|
|
||||||
// Prepare the field translations.
|
// Prepare the field translations.
|
||||||
$eid = $evid = 1;
|
$eid = $evid = 1;
|
||||||
|
|
|
@ -136,6 +136,13 @@ function hook_language_negotiation_info_alter(array &$language_providers) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow modules to react to language settings changes.
|
||||||
|
*/
|
||||||
|
function hook_multilingual_settings_changed() {
|
||||||
|
cache_clear_all('field_info_types', 'cache_field');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @} End of "addtogroup hooks".
|
* @} End of "addtogroup hooks".
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
// $Id$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Field API multilingual handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form submit handler for node_form().
|
||||||
|
*
|
||||||
|
* Update the field language according to the node language, changing the
|
||||||
|
* previous language if necessary.
|
||||||
|
*/
|
||||||
|
function locale_field_node_form_update_field_language($form, &$form_state, $reset_previous = TRUE) {
|
||||||
|
$node = (object) $form_state['values'];
|
||||||
|
$available_languages = field_multilingual_content_languages();
|
||||||
|
// @todo: Unify language neutral language codes.
|
||||||
|
$selected_language = empty($node->language) ? FIELD_LANGUAGE_NONE : $node->language;
|
||||||
|
list(, , $bundle) = field_extract_ids('node', $node);
|
||||||
|
|
||||||
|
foreach (field_info_instances('node', $bundle) as $instance) {
|
||||||
|
$field_name = $instance['field_name'];
|
||||||
|
$field = field_info_field($field_name);
|
||||||
|
$previous_language = $form[$field_name]['#language'];
|
||||||
|
|
||||||
|
// Handle a possible language change: previous language values are deleted,
|
||||||
|
// new ones are inserted.
|
||||||
|
if ($field['translatable'] && $previous_language != $selected_language) {
|
||||||
|
$form_state['values'][$field_name][$selected_language] = $node->{$field_name}[$previous_language];
|
||||||
|
if ($reset_previous) {
|
||||||
|
$form_state['values'][$field_name][$previous_language] = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply fallback rules to the given object.
|
||||||
|
*
|
||||||
|
* Parameters are the same of hook_field_attach_view().
|
||||||
|
*/
|
||||||
|
function locale_field_fallback_view(&$output, $context) {
|
||||||
|
// Lazily init fallback values and candidates to avoid unnecessary calls.
|
||||||
|
$fallback_values = array();
|
||||||
|
$fallback_candidates = NULL;
|
||||||
|
list(, , $bundle) = field_extract_ids($context['obj_type'], $context['object']);
|
||||||
|
|
||||||
|
foreach (field_info_instances($context['obj_type'], $bundle) as $instance) {
|
||||||
|
$field_name = $instance['field_name'];
|
||||||
|
$field = field_info_field($field_name);
|
||||||
|
|
||||||
|
// If the items array is empty then we have a missing field translation.
|
||||||
|
// @todo: Verify this assumption.
|
||||||
|
if (empty($output[$field_name]['items'])) {
|
||||||
|
if (!isset($fallback_candidates)) {
|
||||||
|
require_once DRUPAL_ROOT . '/includes/language.inc';
|
||||||
|
$fallback_candidates = language_fallback_get_candidates();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($fallback_candidates as $langcode) {
|
||||||
|
// Again if we have a non-empty array we assume the field translation is
|
||||||
|
// valid.
|
||||||
|
if (!empty($context['object']->{$field_name}[$langcode])) {
|
||||||
|
// Cache fallback values per language as fields might have different
|
||||||
|
// fallback values.
|
||||||
|
if (!isset($fallback_values[$langcode])) {
|
||||||
|
$fallback_values[$langcode] = field_attach_view($context['obj_type'], $context['object'], $context['build_mode'], $langcode);
|
||||||
|
}
|
||||||
|
// We are done, skip to the next field.
|
||||||
|
$output[$field_name] = $fallback_values[$langcode][$field_name];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,4 +6,5 @@ version = VERSION
|
||||||
core = 7.x
|
core = 7.x
|
||||||
files[] = locale.module
|
files[] = locale.module
|
||||||
files[] = locale.install
|
files[] = locale.install
|
||||||
|
files[] = locale.field.inc
|
||||||
files[] = locale.test
|
files[] = locale.test
|
||||||
|
|
|
@ -385,6 +385,16 @@ function locale_form_node_type_form_alter(&$form, &$form_state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the given content type has multilingual support.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* True if multilingual support is enabled.
|
||||||
|
*/
|
||||||
|
function locale_multilingual_node_type($type_name) {
|
||||||
|
return (bool) variable_get('language_content_type_' . $type_name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement hook_form_alter().
|
* Implement hook_form_alter().
|
||||||
*
|
*
|
||||||
|
@ -392,7 +402,7 @@ function locale_form_node_type_form_alter(&$form, &$form_state) {
|
||||||
*/
|
*/
|
||||||
function locale_form_alter(&$form, &$form_state, $form_id) {
|
function locale_form_alter(&$form, &$form_state, $form_id) {
|
||||||
// Only alter user forms if there is more than one language.
|
// Only alter user forms if there is more than one language.
|
||||||
if (variable_get('language_count', 1) > 1) {
|
if (drupal_multilingual()) {
|
||||||
// Display language selector when either creating a user on the admin
|
// Display language selector when either creating a user on the admin
|
||||||
// interface or editing a user account.
|
// interface or editing a user account.
|
||||||
if (($form_id == 'user_register_form' && user_access('administer users')) || ($form_id == 'user_profile_form' && $form['#user_category'] == 'account')) {
|
if (($form_id == 'user_register_form' && user_access('administer users')) || ($form_id == 'user_profile_form' && $form['#user_category'] == 'account')) {
|
||||||
|
@ -400,7 +410,7 @@ function locale_form_alter(&$form, &$form_state, $form_id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($form['#id']) && $form['#id'] == 'node-form') {
|
if (isset($form['#id']) && $form['#id'] == 'node-form') {
|
||||||
if (isset($form['#node']->type) && variable_get('language_content_type_' . $form['#node']->type, 0)) {
|
if (isset($form['#node']->type) && locale_multilingual_node_type($form['#node']->type)) {
|
||||||
$form['language'] = array(
|
$form['language'] = array(
|
||||||
'#type' => 'select',
|
'#type' => 'select',
|
||||||
'#title' => t('Language'),
|
'#title' => t('Language'),
|
||||||
|
@ -416,6 +426,20 @@ function locale_form_alter(&$form, &$form_state, $form_id) {
|
||||||
'#value' => $default->language
|
'#value' => $default->language
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$form['#submit'][] = 'locale_field_node_form_submit';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form submit handler for node_form().
|
||||||
|
*
|
||||||
|
* Check if Locale is registered as a translation handler and handle possible
|
||||||
|
* node language changes.
|
||||||
|
*/
|
||||||
|
function locale_field_node_form_submit($form, &$form_state) {
|
||||||
|
if (field_multilingual_check_translation_handlers('node', 'locale')) {
|
||||||
|
module_load_include('inc', 'locale', 'locale.field');
|
||||||
|
locale_field_node_form_update_field_language($form, $form_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,6 +463,34 @@ function locale_theme() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement hook_field_attach_view_alter().
|
||||||
|
*/
|
||||||
|
function locale_field_attach_view_alter(&$output, $context) {
|
||||||
|
// In locale_field_fallback_view() we might call field_attach_view(). The
|
||||||
|
// static variable avoids unnecessary recursion.
|
||||||
|
static $recursion;
|
||||||
|
|
||||||
|
// Do not apply fallback rules if disabled or if Locale is not registered as a
|
||||||
|
// translation handler.
|
||||||
|
if (!$recursion && variable_get('locale_field_fallback_view', TRUE) && field_multilingual_check_translation_handlers($context['obj_type'], 'locale')) {
|
||||||
|
$recursion = TRUE;
|
||||||
|
module_load_include('inc', 'locale', 'locale.field');
|
||||||
|
locale_field_fallback_view($output, $context);
|
||||||
|
$recursion = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement hook_entity_info_alter().
|
||||||
|
*/
|
||||||
|
function locale_entity_info_alter(&$entity_info) {
|
||||||
|
$enabled = drupal_multilingual();
|
||||||
|
foreach ($entity_info as $type => $info) {
|
||||||
|
$entity_info[$type]['translation']['locale'] = $enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement hook_language_types_info().
|
* Implement hook_language_types_info().
|
||||||
*/
|
*/
|
||||||
|
@ -829,7 +881,7 @@ function locale_block_info() {
|
||||||
* Displays a language switcher. Only show if we have at least two languages.
|
* Displays a language switcher. Only show if we have at least two languages.
|
||||||
*/
|
*/
|
||||||
function locale_block_view($type) {
|
function locale_block_view($type) {
|
||||||
if (variable_get('language_count', 1) > 1) {
|
if (drupal_multilingual()) {
|
||||||
$path = drupal_is_front_page() ? '<front>' : $_GET['q'];
|
$path = drupal_is_front_page() ? '<front>' : $_GET['q'];
|
||||||
$links = language_negotiation_get_switch_links($type, $path);
|
$links = language_negotiation_get_switch_links($type, $path);
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* - a functional test for configuring a different path alias per language;
|
* - a functional test for configuring a different path alias per language;
|
||||||
* - a functional test for configuring a different path alias per language;
|
* - a functional test for configuring a different path alias per language;
|
||||||
* - a functional test for multilingual support by content type and on nodes.
|
* - a functional test for multilingual support by content type and on nodes.
|
||||||
|
* - a functional test for multilingual fields.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -986,6 +987,7 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
|
||||||
$this->assertEqual($language_count, 1, t('Language count: %count', array('%count' => $language_count)));
|
$this->assertEqual($language_count, 1, t('Language count: %count', array('%count' => $language_count)));
|
||||||
|
|
||||||
// Check language negotiation.
|
// Check language negotiation.
|
||||||
|
require_once DRUPAL_ROOT . '/includes/language.inc';
|
||||||
$this->assertTrue(count(language_types()) == count(drupal_language_types()), t('Language types reset'));
|
$this->assertTrue(count(language_types()) == count(drupal_language_types()), t('Language types reset'));
|
||||||
$language_negotiation = language_negotiation_get(LANGUAGE_TYPE_INTERFACE) == LANGUAGE_NEGOTIATION_DEFAULT;
|
$language_negotiation = language_negotiation_get(LANGUAGE_TYPE_INTERFACE) == LANGUAGE_NEGOTIATION_DEFAULT;
|
||||||
$this->assertTrue($language_negotiation, t('Interface language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
|
$this->assertTrue($language_negotiation, t('Interface language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
|
||||||
|
@ -1396,7 +1398,7 @@ class LocaleContentFunctionalTest extends DrupalWebTestCase {
|
||||||
$edit = array(
|
$edit = array(
|
||||||
'type' => 'page',
|
'type' => 'page',
|
||||||
'title' => array(FIELD_LANGUAGE_NONE => array(array('value' => $node_title))),
|
'title' => array(FIELD_LANGUAGE_NONE => array(array('value' => $node_title))),
|
||||||
'body' => array(FIELD_LANGUAGE_NONE => array(array('value' => $node_body))),
|
'body' => array($langcode => array(array('value' => $node_body))),
|
||||||
'language' => $langcode,
|
'language' => $langcode,
|
||||||
);
|
);
|
||||||
$node = $this->drupalCreateNode($edit);
|
$node = $this->drupalCreateNode($edit);
|
||||||
|
@ -1619,6 +1621,73 @@ class UILanguageNegotiationTest extends DrupalWebTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LocaleMultilingualFieldsFunctionalTest extends DrupalWebTestCase {
|
||||||
|
public static function getInfo() {
|
||||||
|
return array(
|
||||||
|
'name' => 'Multilingual fields',
|
||||||
|
'description' => 'Test multilingual support for fields.',
|
||||||
|
'group' => 'Locale',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp('locale');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMultilingualNodeForm() {
|
||||||
|
// Setup users.
|
||||||
|
$admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages', 'create page content', 'edit own page content'));
|
||||||
|
$this->drupalLogin($admin_user);
|
||||||
|
|
||||||
|
// Add a new language.
|
||||||
|
require_once DRUPAL_ROOT . '/includes/locale.inc';
|
||||||
|
locale_add_language('it', 'Italian', 'Italiano', LANGUAGE_LTR, '', '', TRUE, FALSE);
|
||||||
|
|
||||||
|
// Set page content type to use multilingual support.
|
||||||
|
$this->drupalGet('admin/structure/types/manage/page');
|
||||||
|
$this->assertText(t('Multilingual support'), t('Multilingual support fieldset present on content type configuration form.'));
|
||||||
|
$edit = array(
|
||||||
|
'language_content_type' => 1,
|
||||||
|
);
|
||||||
|
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||||
|
$this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Page')), t('Page content type has been updated.'));
|
||||||
|
|
||||||
|
// Create page content.
|
||||||
|
$langcode = FIELD_LANGUAGE_NONE;
|
||||||
|
$title_key = "title[$langcode][0][value]";
|
||||||
|
$title_value = $this->randomName(8);
|
||||||
|
$body_key = "body[$langcode][0][value]";
|
||||||
|
$body_value = $this->randomName(16);
|
||||||
|
|
||||||
|
// Create node to edit.
|
||||||
|
$edit = array();
|
||||||
|
$edit[$title_key] = $title_value;
|
||||||
|
$edit[$body_key] = $body_value;
|
||||||
|
$edit['language'] = 'en';
|
||||||
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||||
|
|
||||||
|
// Check that the node exists in the database.
|
||||||
|
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||||
|
$this->assertTrue($node, t('Node found in database.'));
|
||||||
|
|
||||||
|
$assert = isset($node->body['en']) && !isset($node->body[FIELD_LANGUAGE_NONE]) && $node->body['en'][0]['value'] == $body_value;
|
||||||
|
$this->assertTrue($assert, t('Field language correctly set.'));
|
||||||
|
|
||||||
|
// Change node language.
|
||||||
|
$this->drupalGet("node/$node->nid/edit");
|
||||||
|
$edit = array(
|
||||||
|
$title_key => $this->randomName(8),
|
||||||
|
'language' => 'it'
|
||||||
|
);
|
||||||
|
$this->drupalPost(NULL, $edit, t('Save'));
|
||||||
|
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||||
|
$this->assertTrue($node, t('Node found in database.'));
|
||||||
|
|
||||||
|
$assert = isset($node->body['it']) && !isset($node->body['en']) && $node->body['it'][0]['value'] == $body_value;
|
||||||
|
$this->assertTrue($assert, t('Field language correctly changed.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functional tests for localizing date formats.
|
* Functional tests for localizing date formats.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -534,6 +534,7 @@ function node_configure_fields($type) {
|
||||||
$field = array(
|
$field = array(
|
||||||
'field_name' => 'body',
|
'field_name' => 'body',
|
||||||
'type' => 'text_with_summary',
|
'type' => 'text_with_summary',
|
||||||
|
'translatable' => TRUE,
|
||||||
);
|
);
|
||||||
$field = field_create_field($field);
|
$field = field_create_field($field);
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,6 @@ class PathLanguageTestCase extends DrupalWebTestCase {
|
||||||
$edit['langcode'] = 'fr';
|
$edit['langcode'] = 'fr';
|
||||||
|
|
||||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||||
drupal_static_reset('language_list');
|
|
||||||
|
|
||||||
// Set language negotiation to "Path prefix with fallback".
|
// Set language negotiation to "Path prefix with fallback".
|
||||||
include_once DRUPAL_ROOT . '/includes/locale.inc';
|
include_once DRUPAL_ROOT . '/includes/locale.inc';
|
||||||
|
@ -215,9 +214,10 @@ class PathLanguageTestCase extends DrupalWebTestCase {
|
||||||
$this->drupalGet('node/' . $english_node->nid . '/translate');
|
$this->drupalGet('node/' . $english_node->nid . '/translate');
|
||||||
$this->clickLink(t('add translation'));
|
$this->clickLink(t('add translation'));
|
||||||
$edit = array();
|
$edit = array();
|
||||||
|
$langcode = 'fr';
|
||||||
|
$edit["body[$langcode][0][value]"] = $this->randomName();
|
||||||
$langcode = FIELD_LANGUAGE_NONE;
|
$langcode = FIELD_LANGUAGE_NONE;
|
||||||
$edit["title[$langcode][0][value]"] = $this->randomName();
|
$edit["title[$langcode][0][value]"] = $this->randomName();
|
||||||
$edit["body[$langcode][0][value]"] = $this->randomName();
|
|
||||||
$edit['path'] = $this->randomName();
|
$edit['path'] = $this->randomName();
|
||||||
$this->drupalPost(NULL, $edit, t('Save'));
|
$this->drupalPost(NULL, $edit, t('Save'));
|
||||||
|
|
||||||
|
@ -234,9 +234,9 @@ class PathLanguageTestCase extends DrupalWebTestCase {
|
||||||
$this->assertText($french_node->title[FIELD_LANGUAGE_NONE][0]['value'], 'Alias for French translation works.');
|
$this->assertText($french_node->title[FIELD_LANGUAGE_NONE][0]['value'], 'Alias for French translation works.');
|
||||||
|
|
||||||
// Confirm that the alias is returned by url().
|
// Confirm that the alias is returned by url().
|
||||||
|
drupal_static_reset('language_list');
|
||||||
$languages = language_list();
|
$languages = language_list();
|
||||||
$url = url('node/' . $french_node->nid, array('language' => $languages[$french_node->language]));
|
$url = url('node/' . $french_node->nid, array('language' => $languages[$french_node->language]));
|
||||||
$this->assertTrue(strpos($url, $edit['path']), t('URL contains the path alias.'));
|
$this->assertTrue(strpos($url, $edit['path']), t('URL contains the path alias.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -730,7 +730,8 @@ class DrupalWebTestCase extends DrupalTestCase {
|
||||||
'value' => $this->randomName(32),
|
'value' => $this->randomName(32),
|
||||||
'format' => filter_default_format(),
|
'format' => filter_default_format(),
|
||||||
);
|
);
|
||||||
$settings['body'][FIELD_LANGUAGE_NONE][0] += $body;
|
$langcode = isset($settings['language']) ? $settings['language'] : FIELD_LANGUAGE_NONE;
|
||||||
|
$settings['body'][$langcode][0] += $body;
|
||||||
|
|
||||||
$node = (object) $settings;
|
$node = (object) $settings;
|
||||||
node_save($node);
|
node_save($node);
|
||||||
|
|
|
@ -6,6 +6,17 @@
|
||||||
* Install, update and uninstall functions for the field_test module.
|
* Install, update and uninstall functions for the field_test module.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement hook_install().
|
||||||
|
*/
|
||||||
|
function field_test_install() {
|
||||||
|
// hook_entity_info_alter() needs to be executed as last.
|
||||||
|
db_update('system')
|
||||||
|
->fields(array('weight' => 1))
|
||||||
|
->condition('name', 'field_test')
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement hook_schema().
|
* Implement hook_schema().
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -93,8 +93,13 @@ function field_test_entity_info() {
|
||||||
* Implement hook_entity_info_alter().
|
* Implement hook_entity_info_alter().
|
||||||
*/
|
*/
|
||||||
function field_test_entity_info_alter(&$entity_info) {
|
function field_test_entity_info_alter(&$entity_info) {
|
||||||
|
// Enable/disable field_test as a translation handler.
|
||||||
foreach (field_test_entity_info_translatable() as $obj_type => $translatable) {
|
foreach (field_test_entity_info_translatable() as $obj_type => $translatable) {
|
||||||
$entity_info[$obj_type]['translation_handlers']['field_test'] = TRUE;
|
$entity_info[$obj_type]['translation']['field_test'] = $translatable;
|
||||||
|
}
|
||||||
|
// Disable locale as a translation handler.
|
||||||
|
foreach (field_info_fieldable_types() as $obj_type => $info) {
|
||||||
|
$entity_info[$obj_type]['translation']['locale'] = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +651,7 @@ function field_test_field_languages($obj_type, $field, &$languages) {
|
||||||
*/
|
*/
|
||||||
function field_test_entity_info_translatable($obj_type = NULL, $translatable = NULL) {
|
function field_test_entity_info_translatable($obj_type = NULL, $translatable = NULL) {
|
||||||
$stored_value = &drupal_static(__FUNCTION__, array());
|
$stored_value = &drupal_static(__FUNCTION__, array());
|
||||||
if (isset($obj_type) && isset($translatable)) {
|
if (isset($obj_type)) {
|
||||||
$stored_value[$obj_type] = $translatable;
|
$stored_value[$obj_type] = $translatable;
|
||||||
_field_info_collate_types(TRUE);
|
_field_info_collate_types(TRUE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ class TranslationTestCase extends DrupalWebTestCase {
|
||||||
|
|
||||||
// Update original and mark translation as outdated.
|
// Update original and mark translation as outdated.
|
||||||
$edit = array();
|
$edit = array();
|
||||||
$edit["body[$langcode][0][value]"] = $this->randomName();
|
$edit["body[$node->language][0][value]"] = $this->randomName();
|
||||||
$edit['translation[retranslate]'] = TRUE;
|
$edit['translation[retranslate]'] = TRUE;
|
||||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||||
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node_title)), t('Original node updated.'));
|
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node_title)), t('Original node updated.'));
|
||||||
|
@ -79,7 +79,7 @@ class TranslationTestCase extends DrupalWebTestCase {
|
||||||
|
|
||||||
// Update translation and mark as updated.
|
// Update translation and mark as updated.
|
||||||
$edit = array();
|
$edit = array();
|
||||||
$edit["body[$langcode][0][value]"] = $this->randomName();
|
$edit["body[$node_translation->language][0][value]"] = $this->randomName();
|
||||||
$edit['translation[status]'] = FALSE;
|
$edit['translation[status]'] = FALSE;
|
||||||
$this->drupalPost('node/' . $node_translation->nid . '/edit', $edit, t('Save'));
|
$this->drupalPost('node/' . $node_translation->nid . '/edit', $edit, t('Save'));
|
||||||
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node_translation_title)), t('Translated node updated.'));
|
$this->assertRaw(t('Page %title has been updated.', array('%title' => $node_translation_title)), t('Translated node updated.'));
|
||||||
|
@ -133,10 +133,10 @@ class TranslationTestCase extends DrupalWebTestCase {
|
||||||
$edit["body[$langcode][0][value]"] = $body;
|
$edit["body[$langcode][0][value]"] = $body;
|
||||||
$edit['language'] = $language;
|
$edit['language'] = $language;
|
||||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||||
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit["title[$langcode][0][value]"])), t('Page created.'));
|
$this->assertRaw(t('Page %title has been created.', array('%title' => $title)), t('Page created.'));
|
||||||
|
|
||||||
// Check to make sure the node was created.
|
// Check to make sure the node was created.
|
||||||
$node = $this->drupalGetNodeByTitle($edit["title[$langcode][0][value]"]);
|
$node = $this->drupalGetNodeByTitle($title);
|
||||||
$this->assertTrue($node, t('Node found in database.'));
|
$this->assertTrue($node, t('Node found in database.'));
|
||||||
|
|
||||||
return $node;
|
return $node;
|
||||||
|
@ -156,12 +156,12 @@ class TranslationTestCase extends DrupalWebTestCase {
|
||||||
$edit = array();
|
$edit = array();
|
||||||
$langcode = FIELD_LANGUAGE_NONE;
|
$langcode = FIELD_LANGUAGE_NONE;
|
||||||
$edit["title[$langcode][0][value]"] = $title;
|
$edit["title[$langcode][0][value]"] = $title;
|
||||||
$edit["body[$langcode][0][value]"] = $body;
|
$edit["body[$language][0][value]"] = $body;
|
||||||
$this->drupalPost(NULL, $edit, t('Save'));
|
$this->drupalPost(NULL, $edit, t('Save'));
|
||||||
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit["title[$langcode][0][value]"])), t('Translation created.'));
|
$this->assertRaw(t('Page %title has been created.', array('%title' => $title)), t('Translation created.'));
|
||||||
|
|
||||||
// Check to make sure that translation was successful.
|
// Check to make sure that translation was successful.
|
||||||
$node = $this->drupalGetNodeByTitle($edit["title[$langcode][0][value]"]);
|
$node = $this->drupalGetNodeByTitle($title);
|
||||||
$this->assertTrue($node, t('Node found in database.'));
|
$this->assertTrue($node, t('Node found in database.'));
|
||||||
|
|
||||||
return $node;
|
return $node;
|
||||||
|
|
Loading…
Reference in New Issue