Commit c195d872 authored by webchick's avatar webchick

Issue #1630264 by vasi1186, fubhy, Gábor Hojtsy: Move field language fallback...

Issue #1630264 by vasi1186, fubhy, Gábor Hojtsy: Move field language fallback code from Locale to Field and field language handling for nodes to Node.
parent 18040223
......@@ -1473,8 +1473,8 @@ function hook_field_attach_prepare_translation_alter(&$entity, $context) {
function hook_field_language_alter(&$display_langcode, $context) {
// Do not apply core language fallback rules if they are disabled or if Locale
// is not registered as a translation handler.
if (variable_get('locale_field_language_fallback', TRUE) && field_has_translation_handler($context['entity_type'], 'locale')) {
locale_field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
if (variable_get('field_language_fallback', TRUE) && field_has_translation_handler($context['entity_type'])) {
field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
}
}
......
......@@ -368,6 +368,49 @@ function field_system_info_alter(&$info, $file, $type) {
}
}
/**
* Applies language fallback rules to the fields attached to the given entity.
*
* Core language fallback rules simply check if fields have a field translation
* for the requested language code. If so, the requested language is returned,
* otherwise all the fallback candidates are inspected to see if there is a
* field translation available in another language.
* By default this is called by field_field_language_alter(), but this
* behavior can be disabled by setting the 'field_language_fallback'
* variable to FALSE.
*
* @param $field_langcodes
* A reference to an array of language codes keyed by field name.
* @param $entity
* The entity to be displayed.
* @param $langcode
* The language code $entity has to be displayed in.
*/
function field_language_fallback(&$field_langcodes, $entity, $langcode) {
// Lazily init fallback candidates to avoid unnecessary calls.
$fallback_candidates = NULL;
foreach ($field_langcodes as $field_name => $field_langcode) {
// If the requested language is defined for the current field use it,
// otherwise search for a fallback value among the fallback candidates.
if (isset($entity->{$field_name}[$langcode])) {
$field_langcodes[$field_name] = $langcode;
}
elseif (!empty($entity->{$field_name})) {
if (!isset($fallback_candidates)) {
require_once DRUPAL_ROOT . '/core/includes/language.inc';
$fallback_candidates = language_fallback_get_candidates();
}
foreach ($fallback_candidates as $fallback_langcode) {
if (isset($entity->{$field_name}[$fallback_langcode])) {
$field_langcodes[$field_name] = $fallback_langcode;
break;
}
}
}
}
}
/**
* Implements hook_cache_flush().
*/
......
......@@ -46,7 +46,7 @@
* language, the translation handler is responsible for performing one of the
* following actions:
* - Ignore missing translations, i.e. do not show any field values for the
* requested language. For example, see locale_field_language_alter().
* requested language. For example, see field_field_language_alter().
* - Provide a value in a different language as fallback. By default, the
* fallback logic is applied separately to each field to ensure that there
* is a value for each field to display.
......@@ -68,6 +68,13 @@
*/
function field_language_insert() {
field_info_cache_clear();
// If the number of languages is bigger than 1, enable the core language
// fallback rules.
// Because the language_count is updated only after the hook is invoked, we
// check if the language_count is bigger or equal with 1 at the current time.
if (variable_get('language_count', 1) >= 1) {
variable_set('field_language_fallback', TRUE);
}
}
/**
......@@ -82,6 +89,13 @@ function field_language_update() {
*/
function field_language_delete() {
field_info_cache_clear();
// If the number of languages is less than 2, disable the core language
// fallback rules.
// Because the language_count is updated after the hook is invoked, we check
// if the language_count is less or equal with 2 at the current time.
if (variable_get('language_count', 1) <= 2) {
variable_set('field_language_fallback', FALSE);
}
}
/**
......@@ -260,8 +274,8 @@ function field_valid_language($langcode, $default = TRUE) {
*
* If translation handlers are found, we let modules provide alternative display
* language codes for fields not having the requested language code available.
* Core language fallback rules are provided by locale_field_language_fallback()
* which is called by locale_field_language_alter().
* Core language fallback rules are provided by field_language_fallback()
* which is called by field_field_language_alter().
*
* @param $entity_type
* The type of $entity.
......@@ -314,6 +328,11 @@ function field_language($entity_type, $entity, $field_name = NULL, $langcode = N
'entity' => $entity,
'langcode' => $langcode,
);
// Do not apply core language fallback rules if they are disabled or if
// the entity does not have a translation handler registered.
if (variable_get('field_language_fallback', FALSE) && field_has_translation_handler($context['entity_type'])) {
field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
}
drupal_alter('field_language', $display_langcode, $context);
}
......
......@@ -23,7 +23,7 @@ public static function getInfo() {
}
function setUp() {
parent::setUp('locale', 'field_test');
parent::setUp('language', 'field_test');
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
......
......@@ -131,9 +131,9 @@ function field_test_entity_info_alter(&$entity_info) {
foreach (field_test_entity_info_translatable() as $entity_type => $translatable) {
$entity_info[$entity_type]['translation']['field_test'] = $translatable;
}
// Disable locale as a translation handler.
// Disable the entity type translation handler.
foreach ($entity_info as $entity_type => $info) {
$entity_info[$entity_type]['translation']['locale'] = FALSE;
$entity_info[$entity_type]['translation'][$entity_type] = FALSE;
}
}
......
......@@ -117,7 +117,7 @@ function field_test_field_available_languages_alter(&$langcodes, $context) {
*/
function field_test_field_language_alter(&$display_langcode, $context) {
if (variable_get('field_test_language_fallback', TRUE)) {
locale_field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
}
}
......
......@@ -29,7 +29,6 @@ function locale_uninstall() {
variable_del('locale_cache_strings');
variable_del('locale_js_directory');
variable_del('javascript_parsed');
variable_del('locale_field_language_fallback');
variable_del('locale_cache_length');
variable_del('locale_translation_plurals');
variable_del('locale_translation_javascript');
......
......@@ -208,43 +208,6 @@ function locale_permission() {
);
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function locale_form_node_form_alter(&$form, &$form_state) {
$form['#submit'][] = 'locale_field_node_form_submit';
}
/**
* Form submit handler for node_form().
*
* Checks if Locale is registered as a translation handler and handle possible
* node language changes.
*
* This submit handler needs to run before entity_form_submit_build_entity()
* is invoked by node_form_submit_build_node(), because it alters the values of
* attached fields. Therefore, it cannot be a hook_node_submit() implementation.
*/
function locale_field_node_form_submit($form, &$form_state) {
if (field_has_translation_handler('node', 'locale')) {
$bundle = $form_state['values']['type'];
$node_language = $form_state['values']['langcode'];
foreach (field_info_instances('node', $bundle) as $instance) {
$field_name = $instance['field_name'];
$field = field_info_field($field_name);
$previous_langcode = $form[$field_name]['#language'];
// Handle a possible language change: new language values are inserted,
// previous ones are deleted.
if ($field['translatable'] && $previous_langcode != $node_language) {
$form_state['values'][$field_name][$node_language] = $form_state['values'][$field_name][$previous_langcode];
$form_state['values'][$field_name][$previous_langcode] = array();
}
}
}
}
/**
* Implements hook_theme().
*/
......@@ -260,68 +223,6 @@ function locale_theme() {
);
}
/**
* Implements hook_field_language_alter().
*/
function locale_field_language_alter(&$display_langcode, $context) {
// Do not apply core language fallback rules if they are disabled or if Locale
// is not registered as a translation handler.
if (variable_get('locale_field_language_fallback', TRUE) && field_has_translation_handler($context['entity_type'], 'locale')) {
locale_field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
}
}
/**
* Applies language fallback rules to the fields attached to the given entity.
*
* Core language fallback rules simply check if fields have a field translation
* for the requested language code. If so the requested language is returned,
* otherwise all the fallback candidates are inspected to see if there is a
* field translation available in another language.
* By default this is called by locale_field_language_alter(), but this
* behavior can be disabled by setting the 'locale_field_language_fallback'
* variable to FALSE.
*
* @param $field_langcodes
* A reference to an array of language codes keyed by field name.
* @param $entity
* The entity to be displayed.
* @param $langcode
* The language code $entity has to be displayed in.
*/
function locale_field_language_fallback(&$field_langcodes, $entity, $langcode) {
// Lazily init fallback candidates to avoid unnecessary calls.
$fallback_candidates = NULL;
$field_languages = array();
foreach ($field_langcodes as $field_name => $field_langcode) {
// If the requested language is defined for the current field use it,
// otherwise search for a fallback value among the fallback candidates.
if (isset($entity->{$field_name}[$langcode])) {
$field_langcodes[$field_name] = $langcode;
}
elseif (!empty($entity->{$field_name})) {
if (!isset($fallback_candidates)) {
require_once DRUPAL_ROOT . '/core/includes/language.inc';
$fallback_candidates = language_fallback_get_candidates();
}
foreach ($fallback_candidates as $fallback_langcode) {
if (isset($entity->{$field_name}[$fallback_langcode])) {
$field_langcodes[$field_name] = $fallback_langcode;
break;
}
}
}
}
}
/**
* Implements hook_entity_info_alter().
*/
function locale_entity_info_alter(&$entity_info) {
$entity_info['node']['translation']['locale'] = TRUE;
}
/**
* Implements hook_language_insert().
*/
......
......@@ -2,27 +2,27 @@
/**
* @file
* Definition of Drupal\locale\Tests\LocaleMultilingualFieldsTest.
* Definition of Drupal\node\Tests\NodeFieldMultilingualTestCase.
*/
namespace Drupal\locale\Tests;
namespace Drupal\node\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Functional test for multilingual fields.
*/
class LocaleMultilingualFieldsTest extends WebTestBase {
class NodeFieldMultilingualTestCase extends WebTestBase {
public static function getInfo() {
return array(
'name' => 'Multilingual fields',
'description' => 'Test multilingual support for fields.',
'group' => 'Locale',
'group' => 'Field API',
);
}
function setUp() {
parent::setUp(array('node', 'locale'));
parent::setUp(array('node', 'language'));
// Create Basic page node type.
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
......
......@@ -226,6 +226,11 @@ function node_entity_info() {
),
);
// Add a translation handler for fields if the language module is enabled.
if (module_exists('language')) {
$return['node']['translation']['node'] = TRUE;
}
// Search integration is provided by node.module, so search-related
// view modes for nodes are defined here and not in search.module.
if (module_exists('search')) {
......
......@@ -493,6 +493,9 @@ function theme_node_preview($variables) {
* @see node_form_submit_build_node()
*/
function node_form_submit($form, &$form_state) {
// Handle possible field translations first and then build the node from the
// submitted values.
node_field_language_form_submit($form, $form_state);
$node = node_form_submit_build_node($form, $form_state);
$insert = empty($node->nid);
$node->save();
......@@ -523,6 +526,30 @@ function node_form_submit($form, &$form_state) {
cache_invalidate(array('content' => TRUE));
}
/**
* Handles possible node language changes.
*
*/
function node_field_language_form_submit($form, &$form_state) {
if (field_has_translation_handler('node', 'node')) {
$bundle = $form_state['values']['type'];
$node_language = $form_state['values']['langcode'];
foreach (field_info_instances('node', $bundle) as $instance) {
$field_name = $instance['field_name'];
$field = field_info_field($field_name);
$previous_langcode = $form[$field_name]['#language'];
// Handle a possible language change: New language values are inserted,
// previous ones are deleted.
if ($field['translatable'] && $previous_langcode != $node_language) {
$form_state['values'][$field_name][$node_language] = $form_state['values'][$field_name][$previous_langcode];
$form_state['values'][$field_name][$previous_langcode] = array();
}
}
}
}
/**
* Updates the form state's node entity by processing this submission's values.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment