Issue #1446382 by plach: Need a reliable way to determine if a specific bundle for an entity type is translatable.
parent
dd927b0008
commit
1bec76308f
|
@ -107,6 +107,8 @@ function hook_entity_view_mode_info_alter(&$view_modes) {
|
|||
* - access callback: As in hook_menu(). 'user_access' will be assumed if
|
||||
* no value is provided.
|
||||
* - access arguments: As in hook_menu().
|
||||
* - translatable: (optional) A boolean value specifying whether this bundle
|
||||
* has translation support enabled. Defaults to FALSE.
|
||||
*
|
||||
* @see entity_get_bundles()
|
||||
* @see hook_entity_bundle_info_alter()
|
||||
|
|
|
@ -440,4 +440,14 @@ class Entity implements IteratorAggregate, EntityInterface {
|
|||
// As entities are always the root of the tree of typed data, we do not need
|
||||
// to set any parent or name.
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Entity\EntityInterface::isTranslatable().
|
||||
*/
|
||||
public function isTranslatable() {
|
||||
// @todo Inject the entity manager and retrieve bundle info from it.
|
||||
$bundles = entity_get_bundles($this->entityType);
|
||||
return !empty($bundles[$this->bundle()]['translatable']);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -460,4 +460,12 @@ class EntityBCDecorator implements IteratorAggregate, EntityInterface {
|
|||
public function getExportProperties() {
|
||||
$this->decorated->getExportProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards the call to the decorated entity.
|
||||
*/
|
||||
public function isTranslatable() {
|
||||
return $this->decorated->isTranslatable();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -219,4 +219,13 @@ interface EntityInterface extends ContextAwareInterface, ComplexDataInterface, A
|
|||
* @see \Drupal\Core\Entity\EntityInterface::getBCEntity()
|
||||
*/
|
||||
public function getOriginalEntity();
|
||||
|
||||
/**
|
||||
* Returns the translation support status.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the entity bundle has translation support enabled.
|
||||
*/
|
||||
public function isTranslatable();
|
||||
|
||||
}
|
||||
|
|
|
@ -75,11 +75,8 @@ use Drupal\Core\Cache\CacheBackendInterface;
|
|||
* - static_cache: (optional) Boolean indicating whether entities should be
|
||||
* statically cached during a page request. Used by
|
||||
* Drupal\Core\Entity\DatabaseStorageController. Defaults to TRUE.
|
||||
* - translation: (optional) An associative array of modules registered as
|
||||
* field translation handlers. Array keys are the module names, and array
|
||||
* values can be any data structure the module uses to provide field
|
||||
* translation. If the value is empty, the module will not be used as a
|
||||
* translation handler.
|
||||
* - translatable: (optional) Boolean indicating whether entities of this type
|
||||
* have mutlilingual support. Defaults to FALSE.
|
||||
* - entity_keys: An array describing how the Field API can extract certain
|
||||
* information from objects of this entity type. Elements:
|
||||
* - id: The name of the property that contains the primary ID of the
|
||||
|
|
|
@ -52,4 +52,5 @@ interface TranslatableInterface {
|
|||
* A typed data object for the translated data.
|
||||
*/
|
||||
public function getTranslation($langcode, $strict = TRUE);
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* revision_table = "custom_block_revision",
|
||||
* menu_base_path = "block/%custom_block",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "revision" = "revision_id",
|
||||
|
|
|
@ -29,6 +29,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* base_table = "comment",
|
||||
* uri_callback = "comment_uri",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* static_cache = FALSE,
|
||||
* entity_keys = {
|
||||
* "id" = "cid",
|
||||
|
|
|
@ -184,3 +184,13 @@ function config_test_entity_disable(ConfigTest $config_test) {
|
|||
$config_test->disable()->save();
|
||||
return new RedirectResponse(url('admin/structure/config_test', array('absolute' => TRUE)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info_alter().
|
||||
*/
|
||||
function config_test_entity_info_alter(&$entity_info) {
|
||||
// The 'translatable' entity key is not supposed to change over time. In this
|
||||
// case we can safely do it because we set it once and we do not change it for
|
||||
// all the duration of the test session.
|
||||
$entity_info['config_test']['translatable'] = Drupal::service('state')->get('config_test.translatable');
|
||||
}
|
||||
|
|
|
@ -29,17 +29,9 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
* The available language codes for a particular field are returned by
|
||||
* field_available_languages(). Whether a field is translatable is determined by
|
||||
* calling field_is_translatable(), which checks the $field['translatable']
|
||||
* property returned by field_info_field(), and whether there is at least one
|
||||
* translation handler available for the field. A translation handler is a
|
||||
* module registering itself via hook_entity_info_alter() to handle field
|
||||
* translations.
|
||||
* property returned by field_info_field() and whether the entity type the field
|
||||
* is attached to supports translation.
|
||||
*
|
||||
|
||||
* By default, _field_invoke() and _field_invoke_multiple() are processing a
|
||||
* field in all available languages, unless they are given a language code
|
||||
* suggestion. Based on that suggestion, _field_language_suggestion() determines
|
||||
* the languages to act on.
|
||||
|
||||
* By default, _field_invoke() and _field_invoke_multiple() process a field in
|
||||
* all available languages, unless they are given a language code suggestion.
|
||||
* Based on that suggestion, _field_language_suggestion() determines the
|
||||
|
@ -226,23 +218,12 @@ function field_is_translatable($entity_type, $field) {
|
|||
* TRUE, if the given handler is allowed to manage field translations. If no
|
||||
* handler is passed, TRUE means there is at least one registered translation
|
||||
* handler.
|
||||
*
|
||||
* @todo Remove this once the migration to the Entity Field API is complete.
|
||||
*/
|
||||
function field_has_translation_handler($entity_type, $handler = NULL) {
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
|
||||
if (isset($handler)) {
|
||||
return !empty($entity_info['translation'][$handler]);
|
||||
}
|
||||
elseif (isset($entity_info['translation'])) {
|
||||
foreach ($entity_info['translation'] as $handler_info) {
|
||||
// The translation handler must use a non-empty data structure.
|
||||
if (!empty($handler_info)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
$info = entity_get_info($entity_type);
|
||||
return !empty($info['translatable']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,13 +12,8 @@ use Drupal\field_test\Plugin\Core\Entity\TestEntity;
|
|||
* Implements hook_entity_info_alter().
|
||||
*/
|
||||
function field_test_entity_info_alter(&$entity_info) {
|
||||
// Enable/disable field_test as a translation handler.
|
||||
foreach (field_test_entity_info_translatable() as $entity_type => $translatable) {
|
||||
$entity_info[$entity_type]['translation']['field_test'] = $translatable;
|
||||
}
|
||||
// Disable the entity type translation handler.
|
||||
foreach ($entity_info as $entity_type => $info) {
|
||||
$entity_info[$entity_type]['translation'][$entity_type] = FALSE;
|
||||
$entity_info[$entity_type]['translatable'] = $translatable;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -210,11 +210,7 @@ function language_theme() {
|
|||
function language_entity_supported() {
|
||||
$supported = array();
|
||||
foreach (entity_get_info() as $entity_type => $info) {
|
||||
// @todo Revisit this once all core entities are migrated to the Entity
|
||||
// Field API and language support for configuration entities has been
|
||||
// sorted out.
|
||||
$entity_class = new ReflectionClass($info['class']);
|
||||
if ($info['fieldable'] && !$entity_class->implementsInterface('Drupal\Core\Config\Entity\ConfigEntityInterface')) {
|
||||
if (!empty($info['fieldable']) && !empty($info['translatable'])) {
|
||||
$supported[$entity_type] = $entity_type;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* revision_table = "node_revision",
|
||||
* uri_callback = "node_uri",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "nid",
|
||||
* "revision" = "vid",
|
||||
|
|
|
@ -27,6 +27,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* base_table = "entity_test_mul",
|
||||
* data_table = "entity_test_mul_property_data",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
|
|
|
@ -28,6 +28,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* data_table = "entity_test_mulrev_property_data",
|
||||
* revision_table = "entity_test_mulrev_property_revision",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "id",
|
||||
* "uuid" = "uuid",
|
||||
|
|
|
@ -30,6 +30,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* base_table = "taxonomy_term_data",
|
||||
* uri_callback = "taxonomy_term_uri",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "tid",
|
||||
* "bundle" = "vid",
|
||||
|
|
|
@ -50,9 +50,7 @@ use Drupal\Core\Entity\EntityInterface;
|
|||
* Additionally some more entity info keys can be defined to further customize
|
||||
* the translation UI. The entity translation info is an associative array that
|
||||
* has to match the following structure. Two nested arrays keyed respectively
|
||||
* by the 'translation' key and the 'entity_translation' key: the first one is
|
||||
* the key defined by the core entity system, while the second one registers
|
||||
* Entity Tanslation as a field translation handler. Elements:
|
||||
* by the 'translation' key and the 'translation_entity' key. Elements:
|
||||
* - access callback: The access callback for the translation pages. Defaults to
|
||||
* 'entity_translation_translate_access'.
|
||||
* - access arguments: The access arguments for the translation pages. By
|
||||
|
|
|
@ -34,6 +34,14 @@ class ConfigTestTranslationUITest extends EntityTranslationUITest {
|
|||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\translation_entity\Tests\EntityTranslationUITest::enableTranslation().
|
||||
*/
|
||||
protected function enableTranslation() {
|
||||
$this->container->get('state')->set('config_test.translatable', TRUE);
|
||||
parent::enableTranslation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides \Drupal\translation_entity\Tests\EntityTranslationUITest::getNewEntityValues().
|
||||
*/
|
||||
|
|
|
@ -72,11 +72,12 @@ function translation_entity_language_types_info_alter(array &$language_types) {
|
|||
* Implements hook_entity_info_alter().
|
||||
*/
|
||||
function translation_entity_entity_info_alter(array &$entity_info) {
|
||||
$edit_form_info = array();
|
||||
|
||||
$bundles_info = entity_get_bundles();
|
||||
// Provide defaults for translation info.
|
||||
foreach ($entity_info as $entity_type => &$info) {
|
||||
if (empty($info['translatable'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($info['translation']['translation_entity'])) {
|
||||
$info['translation']['translation_entity'] = array();
|
||||
}
|
||||
|
@ -87,39 +88,37 @@ function translation_entity_entity_info_alter(array &$entity_info) {
|
|||
// shared accross different entities.
|
||||
$info += array('translation_controller_class' => 'Drupal\translation_entity\EntityTranslationController');
|
||||
|
||||
// Check whether translation is enabled at least for one bundle. We cannot
|
||||
// use translation_entity_enabled() here since it would cause infinite
|
||||
// recursion, as it relies on entity info.
|
||||
$enabled = FALSE;
|
||||
$bundles = isset($bundles_info[$entity_type]) ? array_keys($bundles_info[$entity_type]) : array($entity_type);
|
||||
foreach ($bundles as $bundle) {
|
||||
if (translation_entity_get_config($entity_type, $bundle, 'enabled')) {
|
||||
$enabled = TRUE;
|
||||
break;
|
||||
}
|
||||
// If no menu base path is provided we default to the usual
|
||||
// "entity_type/%entity_type" pattern.
|
||||
if (!isset($info['menu_base_path'])) {
|
||||
$path = "$entity_type/%$entity_type";
|
||||
$info['menu_base_path'] = $path;
|
||||
}
|
||||
|
||||
if ($enabled) {
|
||||
// If no menu base path is provided we default to the usual
|
||||
// "entity_type/%entity_type" pattern.
|
||||
if (!isset($info['menu_base_path'])) {
|
||||
$path = "$entity_type/%$entity_type";
|
||||
$info['menu_base_path'] = $path;
|
||||
}
|
||||
$path = $info['menu_base_path'];
|
||||
|
||||
$path = $info['menu_base_path'];
|
||||
$info += array(
|
||||
'menu_view_path' => $path,
|
||||
'menu_edit_path' => "$path/edit",
|
||||
'menu_path_wildcard' => "%$entity_type",
|
||||
);
|
||||
|
||||
$info += array(
|
||||
'menu_view_path' => $path,
|
||||
'menu_edit_path' => "$path/edit",
|
||||
'menu_path_wildcard' => "%$entity_type",
|
||||
);
|
||||
$entity_position = count(explode('/', $path)) - 1;
|
||||
$info['translation']['translation_entity'] += array(
|
||||
'access_callback' => 'translation_entity_translate_access',
|
||||
'access_arguments' => array($entity_position),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$entity_position = count(explode('/', $path)) - 1;
|
||||
$info['translation']['translation_entity'] += array(
|
||||
'access_callback' => 'translation_entity_translate_access',
|
||||
'access_arguments' => array($entity_position),
|
||||
);
|
||||
/**
|
||||
* Implements hook_entity_bundle_info_alter().
|
||||
*/
|
||||
function translation_entity_entity_bundle_info_alter(&$bundles) {
|
||||
foreach ($bundles as $entity_type => &$info) {
|
||||
foreach ($info as $bundle => &$bundle_info) {
|
||||
$enabled = translation_entity_get_config($entity_type, $bundle, 'enabled');
|
||||
$bundle_info['translatable'] = !empty($enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,9 +278,7 @@ function _translation_entity_menu_strip_loaders($path) {
|
|||
*/
|
||||
function translation_entity_translate_access(EntityInterface $entity) {
|
||||
$entity_type = $entity->entityType();
|
||||
return empty($entity->language()->locked) &&
|
||||
language_multilingual() &&
|
||||
translation_entity_enabled($entity_type, $entity->bundle()) &&
|
||||
return empty($entity->language()->locked) && language_multilingual() && $entity->isTranslatable() &&
|
||||
(user_access('create entity translations') || user_access('update entity translations') || user_access('delete entity translations'));
|
||||
}
|
||||
|
||||
|
@ -445,26 +442,26 @@ function translation_entity_set_config($entity_type, $bundle, $setting, $value)
|
|||
* @param string $bundle
|
||||
* (optional) The bundle of the entity. If no bundle is provided, all the
|
||||
* available bundles are checked.
|
||||
* @param boolean $skip_handler
|
||||
* (optional) Specifies whether the availablity of a field translation handler
|
||||
* should affect the returned value. By default the check is performed.
|
||||
*
|
||||
* @returns
|
||||
* TRUE if the specified bundle is translatable. If no bundle is provided
|
||||
* returns TRUE if at least one of the entity bundles is translatable.
|
||||
*/
|
||||
function translation_entity_enabled($entity_type, $bundle = NULL, $skip_handler = FALSE) {
|
||||
function translation_entity_enabled($entity_type, $bundle = NULL) {
|
||||
$enabled = FALSE;
|
||||
$bundles = !empty($bundle) ? array($bundle) : array_keys(entity_get_bundles($entity_type));
|
||||
$info = entity_get_info($entity_type);
|
||||
|
||||
foreach ($bundles as $bundle) {
|
||||
if (translation_entity_get_config($entity_type, $bundle, 'enabled')) {
|
||||
$enabled = TRUE;
|
||||
break;
|
||||
if (!empty($info['translatable'])) {
|
||||
$bundles = !empty($bundle) ? array($bundle) : array_keys(entity_get_bundles($entity_type));
|
||||
foreach ($bundles as $bundle) {
|
||||
if (translation_entity_get_config($entity_type, $bundle, 'enabled')) {
|
||||
$enabled = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $enabled && ($skip_handler || field_has_translation_handler($entity_type, 'translation_entity'));
|
||||
return $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -602,7 +599,7 @@ function translation_entity_permission() {
|
|||
* Implements hook_form_alter().
|
||||
*/
|
||||
function translation_entity_form_alter(array &$form, array &$form_state) {
|
||||
if (($form_controller = translation_entity_form_controller($form_state)) && ($entity = $form_controller->getEntity($form_state)) && !$entity->isNew() && translation_entity_enabled($entity->entityType(), $entity->bundle())) {
|
||||
if (($form_controller = translation_entity_form_controller($form_state)) && ($entity = $form_controller->getEntity($form_state)) && !$entity->isNew() && $entity->isTranslatable()) {
|
||||
$controller = translation_entity_controller($entity->entityType());
|
||||
$controller->entityFormAlter($form, $form_state, $entity);
|
||||
|
||||
|
@ -643,7 +640,7 @@ function translation_entity_field_language_alter(&$display_language, $context) {
|
|||
$entity = $context['entity'];
|
||||
$entity_type = $entity->entityType();
|
||||
|
||||
if (isset($entity->translation[$context['langcode']]) && translation_entity_enabled($entity_type, $entity->bundle()) && !translation_entity_view_access($entity, $context['langcode'])) {
|
||||
if (isset($entity->translation[$context['langcode']]) && $entity->isTranslatable() && !translation_entity_view_access($entity, $context['langcode'])) {
|
||||
$instances = field_info_instances($entity_type, $entity->bundle());
|
||||
// Avoid altering the real entity.
|
||||
$entity = clone($entity);
|
||||
|
@ -679,7 +676,7 @@ function translation_entity_entity_load(array $entities, $entity_type) {
|
|||
|
||||
if (translation_entity_enabled($entity_type)) {
|
||||
foreach ($entities as $entity) {
|
||||
if (translation_entity_enabled($entity_type, $entity->bundle())) {
|
||||
if ($entity->isTranslatable()) {
|
||||
$enabled_entities[$entity->id()] = $entity;
|
||||
}
|
||||
}
|
||||
|
@ -718,7 +715,7 @@ function translation_entity_load_translation_metadata(array $entities, $entity_t
|
|||
*/
|
||||
function translation_entity_entity_insert(EntityInterface $entity) {
|
||||
// Only do something if translation support for the given entity is enabled.
|
||||
if (!translation_entity_enabled($entity->entityType(), $entity->bundle())) {
|
||||
if (!$entity->isTranslatable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -758,7 +755,7 @@ function translation_entity_entity_insert(EntityInterface $entity) {
|
|||
*/
|
||||
function translation_entity_entity_delete(EntityInterface $entity) {
|
||||
// Only do something if translation support for the given entity is enabled.
|
||||
if (!translation_entity_enabled($entity->entityType(), $entity->bundle())) {
|
||||
if (!$entity->isTranslatable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -773,7 +770,7 @@ function translation_entity_entity_delete(EntityInterface $entity) {
|
|||
*/
|
||||
function translation_entity_entity_update(EntityInterface $entity) {
|
||||
// Only do something if translation support for the given entity is enabled.
|
||||
if (!translation_entity_enabled($entity->entityType(), $entity->bundle())) {
|
||||
if (!$entity->isTranslatable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -867,7 +864,7 @@ function translation_entity_field_info_alter(&$info) {
|
|||
* Implements hook_field_attach_presave().
|
||||
*/
|
||||
function translation_entity_field_attach_presave(EntityInterface $entity) {
|
||||
if (translation_entity_enabled($entity->entityType(), $entity->bundle())) {
|
||||
if ($entity->isTranslatable()) {
|
||||
$attributes = drupal_container()->get('request')->attributes;
|
||||
Drupal::service('translation_entity.synchronizer')->synchronizeFields($entity, $attributes->get('working_langcode'), $attributes->get('source_langcode'));
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ use Drupal\Core\Annotation\Translation;
|
|||
* uri_callback = "user_uri",
|
||||
* label_callback = "user_label",
|
||||
* fieldable = TRUE,
|
||||
* translatable = TRUE,
|
||||
* entity_keys = {
|
||||
* "id" = "uid",
|
||||
* "uuid" = "uuid"
|
||||
|
|
|
@ -984,6 +984,13 @@ class ViewUI implements ViewStorageInterface {
|
|||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\Entity\EntityInterface::isTranslatable().
|
||||
*/
|
||||
public function isTranslatable() {
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements \Drupal\Core\TypedData\ContextAwareInterface::getName().
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue