summaryrefslogtreecommitdiff
path: root/modules/locale
diff options
context:
space:
mode:
Diffstat (limited to 'modules/locale')
-rw-r--r--modules/locale/locale.api.php7
-rw-r--r--modules/locale/locale.field.inc77
-rw-r--r--modules/locale/locale.info1
-rw-r--r--modules/locale/locale.module58
-rw-r--r--modules/locale/locale.test71
5 files changed, 210 insertions, 4 deletions
diff --git a/modules/locale/locale.api.php b/modules/locale/locale.api.php
index b1805e2e0..461f459a4 100644
--- a/modules/locale/locale.api.php
+++ b/modules/locale/locale.api.php
@@ -137,5 +137,12 @@ 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".
*/
diff --git a/modules/locale/locale.field.inc b/modules/locale/locale.field.inc
new file mode 100644
index 000000000..bfb102edf
--- /dev/null
+++ b/modules/locale/locale.field.inc
@@ -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;
+ }
+ }
+ }
+ }
+}
diff --git a/modules/locale/locale.info b/modules/locale/locale.info
index 02b86521d..642b69330 100644
--- a/modules/locale/locale.info
+++ b/modules/locale/locale.info
@@ -6,4 +6,5 @@ version = VERSION
core = 7.x
files[] = locale.module
files[] = locale.install
+files[] = locale.field.inc
files[] = locale.test
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index a24198182..0d90233e9 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -386,13 +386,23 @@ 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().
*
* Adds language fields to forms.
*/
function locale_form_alter(&$form, &$form_state, $form_id) {
// 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
// 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')) {
@@ -400,7 +410,7 @@ function locale_form_alter(&$form, &$form_state, $form_id) {
}
}
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(
'#type' => 'select',
'#title' => t('Language'),
@@ -416,6 +426,20 @@ function locale_form_alter(&$form, &$form_state, $form_id) {
'#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);
}
}
@@ -440,6 +464,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().
*/
function locale_language_types_info() {
@@ -829,7 +881,7 @@ function locale_block_info() {
* Displays a language switcher. Only show if we have at least two languages.
*/
function locale_block_view($type) {
- if (variable_get('language_count', 1) > 1) {
+ if (drupal_multilingual()) {
$path = drupal_is_front_page() ? '<front>' : $_GET['q'];
$links = language_negotiation_get_switch_links($type, $path);
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index 7932bada1..57413ec33 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -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 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)));
// Check language negotiation.
+ require_once DRUPAL_ROOT . '/includes/language.inc';
$this->assertTrue(count(language_types()) == count(drupal_language_types()), t('Language types reset'));
$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'))));
@@ -1396,7 +1398,7 @@ class LocaleContentFunctionalTest extends DrupalWebTestCase {
$edit = array(
'type' => 'page',
'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,
);
$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.
*/