diff --git a/core/modules/config_translation/src/ConfigEntityMapper.php b/core/modules/config_translation/src/ConfigEntityMapper.php index 269bfac..4a6d275 100644 --- a/core/modules/config_translation/src/ConfigEntityMapper.php +++ b/core/modules/config_translation/src/ConfigEntityMapper.php @@ -8,8 +8,8 @@ namespace Drupal\config_translation; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Config\TypedConfigManagerInterface; -use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Routing\RouteMatch; @@ -43,7 +43,7 @@ class ConfigEntityMapper extends ConfigNamesMapper { /** * Loaded entity instance to help produce the translation interface. * - * @var \Drupal\Core\Entity\EntityInterface + * @var \Drupal\Core\Config\Entity\ConfigEntityInterface */ protected $entity; @@ -125,13 +125,13 @@ public function populateFromRequest(Request $request) { * configuration names to use to check permissions or display a translation * screen. * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to set. + * @param \Drupal\Core\Config\Entity\ConfigEntityInterface $entity + * The configuration entity to set. * * @return bool * TRUE, if the entity was set successfully; FALSE otherwise. */ - public function setEntity(EntityInterface $entity) { + public function setEntity(ConfigEntityInterface $entity) { if (isset($this->entity)) { return FALSE; } @@ -143,6 +143,7 @@ public function setEntity(EntityInterface $entity) { // page with more names if form altering added more configuration to an // entity. This is not a Drupal 8 best practice (ideally the configuration // would have pluggable components), but this may happen as well. + /** @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type_info */ $entity_type_info = $this->entityManager->getDefinition($this->entityType); $this->addConfigName($entity_type_info->getConfigPrefix() . '.' . $entity->id()); diff --git a/core/modules/config_translation/src/ConfigFieldMapper.php b/core/modules/config_translation/src/ConfigFieldMapper.php index e9d48e4..a593fff 100644 --- a/core/modules/config_translation/src/ConfigFieldMapper.php +++ b/core/modules/config_translation/src/ConfigFieldMapper.php @@ -7,6 +7,8 @@ namespace Drupal\config_translation; +use Drupal\Core\Config\Entity\ConfigEntityInterface; + /** * Configuration mapper for fields. * @@ -49,4 +51,22 @@ public function getTypeLabel() { return $this->t('@label fields', array('@label' => $base_entity_info->getLabel())); } + /** + * {@inheritdoc} + */ + public function setEntity(ConfigEntityInterface $entity) { + if (parent::setEntity($entity)) { + + // Field storage config can also contain translatable values. Add the name + // of the config as well to the list of configs for this entity. + /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ + $field_storage = $this->entity->getFieldStorageDefinition(); + /** @var \Drupal\Core\Config\Entity\ConfigEntityTypeInterface $entity_type_info */ + $entity_type_info = $this->entityManager->getDefinition($field_storage->getEntityTypeId()); + $this->addConfigName($entity_type_info->getConfigPrefix() . '.' . $field_storage->id()); + return TRUE; + } + return FALSE; + } + } diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php index c7218df..18b5a21 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php @@ -13,6 +13,8 @@ use Drupal\Core\Config\FileStorage; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageInterface; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\simpletest\WebTestBase; @@ -28,7 +30,21 @@ class ConfigTranslationUiTest extends WebTestBase { * * @var array */ - public static $modules = array('node', 'contact', 'contact_test', 'config_translation', 'config_translation_test', 'views', 'views_ui', 'contextual', 'filter', 'filter_test'); + public static $modules = [ + 'config_translation', + 'config_translation_test', + 'contact', + 'contact_test', + 'contextual', + 'entity_test', + 'field_test', + 'field_ui', + 'filter', + 'filter_test', + 'node', + 'views', + 'views_ui', + ]; /** * Languages to enable. @@ -610,6 +626,46 @@ public function testViewsTranslationUI() { } /** + * Tests the translation of field and field storage configuration. + */ + public function testFieldConfigTranslation() { + // Add a test field which has a translatable field setting and a + // translatable field storage setting. + $field_name = strtolower($this->randomMachineName()); + $field_storage = FieldStorageConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'entity_test', + 'type' => 'test_field', + ]); + + $translatable_storage_setting = $this->randomString(); + $field_storage->setSetting('translatable_storage_setting', $translatable_storage_setting); + $field_storage->save(); + + $bundle = strtolower($this->randomMachineName()); + entity_test_create_bundle($bundle); + $field = FieldConfig::create([ + 'field_name' => $field_name, + 'entity_type' => 'entity_test', + 'bundle' => $bundle, + ]); + + $translatable_field_setting = $this->randomString(); + $field->setSetting('translatable_field_setting', $translatable_field_setting); + $field->save(); + + $this->drupalLogin($this->translatorUser); + + $this->drupalGet("/entity_test/structure/$bundle/fields/entity_test.$bundle.$field_name/translate"); + $this->clickLink('Add'); + + $this->assertText('Translatable field setting'); + $this->assertText(SafeMarkup::checkPlain($translatable_field_setting)); + $this->assertText('Translatable storage setting'); + $this->assertText(SafeMarkup::checkPlain($translatable_storage_setting)); + } + + /** * Test translation storage in locale storage. */ public function testLocaleDBStorage() { diff --git a/core/modules/config_translation/tests/src/Unit/ConfigEntityMapperTest.php b/core/modules/config_translation/tests/src/Unit/ConfigEntityMapperTest.php index 8a2fc59..8041931 100644 --- a/core/modules/config_translation/tests/src/Unit/ConfigEntityMapperTest.php +++ b/core/modules/config_translation/tests/src/Unit/ConfigEntityMapperTest.php @@ -57,7 +57,7 @@ class ConfigEntityMapperTest extends UnitTestCase { protected function setUp() { $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); - $this->entity = $this->getMock('Drupal\Core\Entity\EntityInterface'); + $this->entity = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityInterface'); $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface'); @@ -109,6 +109,10 @@ public function testSetEntity() { ->will($this->returnValue('entity_id')); $entity_type = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface'); + $entity_type + ->expects($this->any()) + ->method('getConfigPrefix') + ->will($this->returnValue('config_prefix')); $this->entityManager ->expects($this->once()) ->method('getDefinition') @@ -118,6 +122,10 @@ public function testSetEntity() { $result = $this->configEntityMapper->setEntity($this->entity); $this->assertTrue($result); + // Ensure that the configuration name was added to the mapper. + $plugin_definition = $this->configEntityMapper->getPluginDefinition(); + $this->assertTrue(in_array('config_prefix.entity_id', $plugin_definition['names'])); + // Make sure setEntity() returns FALSE when called a second time. $result = $this->configEntityMapper->setEntity($this->entity); $this->assertFalse($result); diff --git a/core/modules/config_translation/tests/src/Unit/ConfigFieldMapperTest.php b/core/modules/config_translation/tests/src/Unit/ConfigFieldMapperTest.php new file mode 100644 index 0000000..740b722 --- /dev/null +++ b/core/modules/config_translation/tests/src/Unit/ConfigFieldMapperTest.php @@ -0,0 +1,116 @@ +entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); + $this->entity = $this->getMock('Drupal\field\FieldConfigInterface'); + + $definition = array( + 'class' => '\Drupal\config_translation\ConfigFieldMapper', + 'base_route_name' => 'entity.field_config.node_field_edit_form', + 'title' => '!label field', + 'names' => array(), + 'entity_type' => 'field_config', + ); + + $locale_config_manager = $this->getMockBuilder('Drupal\locale\LocaleConfigManager') + ->disableOriginalConstructor() + ->getMock(); + + $this->configFieldMapper = new ConfigFieldMapper( + 'node_fields', + $definition, + $this->getConfigFactoryStub(), + $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface'), + $locale_config_manager, + $this->getMock('Drupal\config_translation\ConfigMapperManagerInterface'), + $this->getMock('Drupal\Core\Routing\RouteProviderInterface'), + $this->getStringTranslationStub(), + $this->entityManager, + $this->getMock('Drupal\Core\Language\LanguageManagerInterface') + ); + } + + /** + * Tests ConfigFieldMapper::setEntity(). + * + * @covers ::setEntity + */ + public function testSetEntity() { + $entity_type = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityTypeInterface'); + $entity_type + ->expects($this->any()) + ->method('getConfigPrefix') + ->will($this->returnValue('config_prefix')); + + $this->entityManager + ->expects($this->any()) + ->method('getDefinition') + ->will($this->returnValue($entity_type)); + + $field_storage = $this->getMock('Drupal\field\FieldStorageConfigInterface'); + $field_storage + ->expects($this->any()) + ->method('id') + ->will($this->returnValue('field_storage_id')); + + $this->entity + ->expects($this->any()) + ->method('getFieldStorageDefinition') + ->will($this->returnValue($field_storage)); + + $result = $this->configFieldMapper->setEntity($this->entity); + $this->assertTrue($result); + + // Ensure that the configuration name was added to the mapper. + $plugin_definition = $this->configFieldMapper->getPluginDefinition(); + $this->assertTrue(in_array('config_prefix.field_storage_id', $plugin_definition['names'])); + + // Make sure setEntity() returns FALSE when called a second time. + $result = $this->configFieldMapper->setEntity($this->entity); + $this->assertFalse($result); + } + +} diff --git a/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml b/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml index 48f5dcf..8e06db1 100644 --- a/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml +++ b/core/modules/field/tests/modules/field_test/config/schema/field_test.schema.yml @@ -65,6 +65,9 @@ field.storage_settings.test_field: config_data_from_storage_setting: type: boolean label: 'Test FieldItemInterface::storageSettingsToConfigData()' + translatable_storage_setting: + type: label + label: 'Translatable storage setting' field.storage_settings.test_field_with_dependencies: type: field.storage_settings.test_field @@ -88,6 +91,9 @@ field.field_settings.test_field: config_data_from_field_setting: type: boolean label: 'Test FieldItemInterface::fieldSettingsToConfigData()' + translatable_field_setting: + type: label + label: 'Translatable field setting' field.field_settings.test_field_with_dependencies: type: field.field_settings.test_field diff --git a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php index 9886b03..42eb11e 100644 --- a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php +++ b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php @@ -33,6 +33,7 @@ public static function defaultStorageSettings() { 'test_field_storage_setting' => 'dummy test string', 'changeable' => 'a changeable field storage setting', 'unchangeable' => 'an unchangeable field storage setting', + 'translatable_storage_setting' => 'a translatable field storage setting', ) + parent::defaultStorageSettings(); } @@ -42,6 +43,7 @@ public static function defaultStorageSettings() { public static function defaultFieldSettings() { return array( 'test_field_setting' => 'dummy test string', + 'translatable_field_setting' => 'a translatable field setting', ) + parent::defaultFieldSettings(); }