diff --git a/entity_translation.install b/entity_translation.install
index 9108aca..d0b1442 100644
--- a/entity_translation.install
+++ b/entity_translation.install
@@ -96,14 +96,14 @@ function entity_translation_install() {
// Grant the 'edit original values' permission, so we don't break editing on
// existing sites.
- $msg = _entity_translation_grant_original_values_permissions();
+ $msg = _entity_translation_grant_edit_permissions();
drupal_set_message($msg);
}
/**
* Grant 'edit $type original values' permission to existing roles.
*/
-function _entity_translation_grant_original_values_permissions() {
+function _entity_translation_grant_edit_permissions() {
$permissions = array();
// Nodes.
@@ -129,8 +129,12 @@ function _entity_translation_grant_original_values_permissions() {
$assignments = array();
foreach ($permissions as $entity_type => $permissions_filter) {
- $permission = "edit $entity_type original values";
- $assignments[] = _entity_translation_grant_permission($permission, $permissions_filter);
+ if (entity_translation_enabled($entity_type)) {
+ $permission = "edit $entity_type original values";
+ $assignments[] = _entity_translation_grant_permission($permission, $permissions_filter);
+ $permission = "edit $entity_type translation shared fields";
+ $assignments[] = _entity_translation_grant_permission($permission, $permissions_filter);
+ }
}
$assignments = '
- ' . implode('
- ', $assignments) . '
';
@@ -230,10 +234,10 @@ function entity_translation_update_7001() {
}
/**
- * Grant 'edit original values' permission to roles which have entity editing permissions.
+ * Grant 'edit original values' and 'edit shared field' permissions to roles which have entity editing permissions.
*/
function entity_translation_update_7002() {
- return _entity_translation_grant_original_values_permissions();
+ return _entity_translation_grant_edit_permissions();
}
/**
diff --git a/entity_translation.module b/entity_translation.module
index 31d1ec8..7ce69bf 100644
--- a/entity_translation.module
+++ b/entity_translation.module
@@ -117,6 +117,7 @@ function entity_translation_entity_info() {
'entity_translation' => array(
'class' => 'EntityTranslationUserHandler',
'skip original values access' => TRUE,
+ 'skip shared fields access' => TRUE,
),
),
);
@@ -727,7 +728,7 @@ function entity_translation_permission() {
);
foreach (entity_get_info() as $entity_type => $info) {
- if ($info['fieldable']) {
+ if ($info['fieldable'] && entity_translation_enabled($entity_type)) {
$label = !empty($info['label']) ? t($info['label']) : $entity_type;
$permission["translate $entity_type entities"] = array(
'title' => t('Translate entities of type @type', array('@type' => $label)),
@@ -735,19 +736,20 @@ function entity_translation_permission() {
);
// Avoid access control for original values on the current entity.
- if (!empty($info['translation']['entity_translation']['skip original values access'])) {
- continue;
+ if (empty($info['translation']['entity_translation']['skip original values access'])) {
+ $permission["edit $entity_type original values"] = array(
+ 'title' => t('Edit original values on entities of type @type', array('@type' => $label)),
+ 'description' => t('Access the edit form in the original language for entities of type @type.', array('@type' => $label)),
+ );
}
- $permission["edit $entity_type original values"] = array(
- 'title' => t('Edit original values on entities of type @type', array('@type' => $label)),
- 'description' => t('Access the edit form in the original language for entities of type @type.', array('@type' => $label)),
- );
-
- $permission["edit $entity_type translation shared fields"] = array(
- 'title' => t('Edit @type shared fields.', array('@type' => $label)),
- 'description' => t('Edit fields shared between translations on the @type translation form.', array('@type' => $label)),
- );
+ // Avoid access control for shared fields on the current entity.
+ if (empty($info['translation']['entity_translation']['skip shared fields access'])) {
+ $permission["edit $entity_type translation shared fields"] = array(
+ 'title' => t('Edit @type shared fields.', array('@type' => $label)),
+ 'description' => t('Edit fields shared between translations on the @type translation form.', array('@type' => $label)),
+ );
+ }
}
}
@@ -1127,29 +1129,13 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f
// Handle fields shared between translations when there is at least one
// translation available or a new one is being created.
if (!$handler->isNewEntity() && ($new_translation || count($translations->data) > 1)) {
+ $access = user_access('edit translation shared fields') || user_access("edit $entity_type translation shared fields");
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
-
- // Shared fields are visible if we are either editing the source node, or
- // if the user has the respective permission.
- $is_source = $langcode == $handler->getLanguage();
- $shared_fields_visible = $is_source || user_access('edit translation shared fields');
-
foreach (field_info_instances($entity_type, $bundle) as $instance) {
$field_name = $instance['field_name'];
$field = field_info_field($field_name);
-
- if ($shared_fields_visible) {
- // Add visual clues about translatability.
- if (!isset($form[$field_name]['#process'])) {
- $form[$field_name]['#process'] = array();
- }
- $form[$field_name]['#field_name'] = $field_name;
- array_unshift($form[$field_name]['#process'], 'entity_translation_element_translatability_clue');
- }
- // Hide shared fields.
- elseif (!$field['translatable']) {
- $form[$field_name]['#access'] = FALSE;
- }
+ $form[$field_name]['#access'] = !empty($form[$field_name]['#access']) && ($field['translatable'] || $access) ;
+ $form[$field_name]['#multilingual'] = (boolean) $field['translatable'];
}
}
@@ -1236,14 +1222,10 @@ function entity_translation_form_element_language_replace(&$element, $source, $l
* shared between different translations. Moreover fields receive a CSS class to
* distinguish between translatable and shared fields.
*/
-function entity_translation_element_translatability_clue($element, &$form_state, $form) {
- $field_name = $element['#field_name'];
- $field = field_info_field($field_name);
-
+function entity_translation_element_translatability_clue($element) {
// Append language to element title.
- if (variable_get('entity_translation_shared_labels', TRUE)) {
- $suffix = $field['translatable'] ? '' : ' (' . t('shared field') . ')';
- _entity_translation_element_title_append($element, $suffix);
+ if (empty($element['#multilingual'])) {
+ _entity_translation_element_title_append($element, ' (' . t('all languages') . ')');
}
// Add CSS class names.
@@ -1253,12 +1235,43 @@ function entity_translation_element_translatability_clue($element, &$form_state,
if (!isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = array();
}
- $element['#attributes']['class'][] = 'entity-translation-' . ($field['translatable'] ? 'field-translatable' : 'field-shared');
+ $element['#attributes']['class'][] = 'entity-translation-' . ($element['#multilingual'] ? 'field-translatable' : 'field-shared');
return $element;
}
/**
+ * Adds a callback function to the given FAPI element.
+ *
+ * Drupal core only adds default element callbacks if the respective handler
+ * type is not defined yet. This function ensures that our callback is only
+ * prepended/appended to the default set of callbacks instead of replacing it.
+ *
+ * @param $element
+ * The FAPI element.
+ * @param $type
+ * The callback type, e.g. '#pre_render' or '#process'.
+ * @param $function
+ * The name of the callback to add.
+ * @param $prepend
+ * Set to TRUE to add the new callback to the beginning of the existing set of
+ * callbacks, and set it to FALSE to append it at the end.
+ */
+function _entity_translation_element_add_callback(&$element, $type, $function, $prepend = TRUE) {
+ // If handler type has not been set, add defaults from element_info().
+ if (!isset($element[$type])) {
+ $element_info = element_info($element['#type']);
+ $element[$type] = isset($element_info[$type]) ? $element_info[$type] : array();
+ }
+ if ($prepend) {
+ array_unshift($element[$type], $function);
+ }
+ else {
+ $element[$type][] = $function;
+ }
+}
+
+/**
* Appends the given $suffix string to the title of the given form element.
*
* If the given element does not have a #title attribute, the function is
@@ -1299,6 +1312,8 @@ function entity_translation_form_alter(&$form, &$form_state) {
if ($handler = entity_translation_entity_form_get_handler($form, $form_state)) {
if (!$handler->isNewEntity()) {
$handler->entityForm($form, $form_state);
+ // Hide shared form elements if the user is not allowed to edit them.
+ $handler->entityFormSharedElements($form);
}
else {
$handler->entityFormLanguageWidget($form, $form_state);
diff --git a/entity_translation_i18n_menu/entity_translation_i18n_menu.module b/entity_translation_i18n_menu/entity_translation_i18n_menu.module
index 88a9315..196f98f 100644
--- a/entity_translation_i18n_menu/entity_translation_i18n_menu.module
+++ b/entity_translation_i18n_menu/entity_translation_i18n_menu.module
@@ -165,6 +165,8 @@ function entity_translation_i18n_menu_form(&$form, &$form_state) {
$langcode = $handler->getFormLanguage();
$language_name = isset($languages[$langcode]) ? t($languages[$langcode]->name) : t('current');
+ $form['menu']['#multilingual'] = TRUE;
+
$form['menu']['link']['tset'] = array(
'#type' => 'checkbox',
'#title' => t('Menu link enabled only for the %language language', array('%language' => $language_name)),
diff --git a/includes/translation.handler.inc b/includes/translation.handler.inc
index b8b4325..d75d578 100644
--- a/includes/translation.handler.inc
+++ b/includes/translation.handler.inc
@@ -256,6 +256,11 @@ interface EntityTranslationHandlerInterface {
public function entityFormLanguageWidgetSubmit($form, &$form_state);
/**
+ * Handle shared form elements.
+ */
+ public function entityFormSharedElements(&$element);
+
+ /**
* Performs validation tasks on the submitted entity forms.
*/
public function entityFormValidate($form, &$form_state);
@@ -942,6 +947,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
'#tree' => TRUE,
'#weight' => -100,
'#access' => $access,
+ '#multilingual' => TRUE,
'language' => array(
'#type' => 'select',
'#default_value' => $this->getSourceLanguage(),
@@ -996,6 +1002,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
'#tree' => TRUE,
'#weight' => 10,
'#access' => $access,
+ '#multilingual' => TRUE,
);
$status = $new_translation || $translations->data[$form_langcode]['status'];
@@ -1074,20 +1081,43 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
if (!empty($form['actions']['delete']['#submit'])) {
$form['actions']['delete']['#submit'][] = 'entity_translation_entity_form_submit';
}
-
- // Hide shared fields if the user is not allowed to edit them.
- $this->entityFormAccess($form, user_access('edit translation shared fields') || user_access("edit $this->entityType translation shared fields"));
}
/**
- * Assign the given access to the form elements not defining one yet.
+ * @see EntityTranslationHandlerInterface::entityFormSharedElements()
+ *
+ * Either remove access or add a translatability clue depending on the current
+ * user's "edit translation shared fields" permissions.
*/
- protected function entityFormAccess(&$form, $access) {
- if (!$access) {
- $allowed_types = array_flip(array('actions', 'container', 'value', 'hidden', 'vertical_tabs'));
- foreach (element_children($form) as $key) {
- if (!isset($form[$key]['#access']) && !isset($allowed_types[$form[$key]['#type']])) {
- $form[$key]['#access'] = $access;
+ public function entityFormSharedElements(&$element) {
+ static $ignored_types;
+ if (!isset($ignored_types)) {
+ $ignored_types = array_flip(array('actions', 'value', 'hidden', 'vertical_tabs', 'token'));
+ }
+
+ $shared_labels = variable_get('entity_translation_shared_labels', TRUE);
+ $access = user_access('edit translation shared fields') || user_access("edit $this->entityType translation shared fields");
+
+ foreach (element_children($element) as $key) {
+ if (!isset($element[$key]['#type'])) {
+ $this->entityFormSharedElements($element[$key]);
+ }
+ else {
+ // Ignore non-widget form elements.
+ if (isset($ignored_types[$element[$key]['#type']])) {
+ continue;
+ }
+ // Elements are considered to be non multilingual by default.
+ if (!isset($element[$key]['#multilingual'])) {
+ $element[$key]['#multilingual'] = FALSE;
+ }
+ // Update #access only if it has not been set already.
+ if (!isset($element[$key]['#access'])) {
+ $element[$key]['#access'] = $access || $element[$key]['#multilingual'];
+ }
+ // Add translatability clue for visible elements.
+ if ($access && $shared_labels) {
+ _entity_translation_element_add_callback($element[$key], '#process', 'entity_translation_element_translatability_clue');
}
}
}
@@ -1123,6 +1153,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
'#options' => $options,
'#access' => empty($settings['hide_language_selector']),
'#disabled' => $is_translation || (!$is_new && !empty($settings['lock_language'])),
+ '#multilingual' => TRUE,
);
if (!empty($form['actions']['submit']['#submit'])) {
diff --git a/includes/translation.handler.node.inc b/includes/translation.handler.node.inc
index 6d82175..b91bf09 100644
--- a/includes/translation.handler.node.inc
+++ b/includes/translation.handler.node.inc
@@ -52,6 +52,11 @@ class EntityTranslationNodeHandler extends EntityTranslationDefaultHandler {
$form['translation']['created']['#access'] = FALSE;
}
}
+
+ // Path aliases natively support multilingual values.
+ if (isset($form['path'])) {
+ $form['path']['#multilingual'] = TRUE;
+ }
}
/**