diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php
index 575daf9..9951673 100644
--- a/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -425,7 +425,6 @@ public function flagErrors(FieldItemListInterface $items, ConstraintViolationLis
           $property_path = explode('.', $violation->getPropertyPath());
           $delta = array_shift($property_path);
           $violations_by_delta[$delta][] = $violation;
-          $violation->arrayPropertyPath = $property_path;
         }
 
         /** @var \Symfony\Component\Validator\ConstraintViolationInterface[] $delta_violations */
@@ -442,7 +441,6 @@ public function flagErrors(FieldItemListInterface $items, ConstraintViolationLis
             $delta_element = $element[$original_delta];
           }
           foreach ($delta_violations as $violation) {
-            // @todo: Pass $violation->arrayPropertyPath as property path.
             $error_element = $this->errorElement($delta_element, $violation, $form, $form_state);
             if ($error_element !== FALSE) {
               $form_state->setError($error_element, $violation->getMessage());
@@ -500,10 +498,25 @@ public function settingsSummary() {
   }
 
   /**
+   * Returns an array containing the path to the flagged sub-element.
+   *
+   * @param \Symfony\Component\Validator\ConstraintViolationInterface $violation
+   *   A constraint violation reported during the validation phase.
+   *
+   * @return array
+   *   The array containing the path.
+   */
+  protected function getLocalErrorPath(ConstraintViolationInterface $violation) {
+    return array_filter(explode('.', $violation->getPropertyPath()));
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) {
-    return $element;
+    $error_path = $this->getLocalErrorPath($error);
+    $nested_element =  NestedArray::getValue($element, $error_path);
+    return is_array($nested_element) ? $nested_element : FALSE;
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php b/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php
new file mode 100644
index 0000000..3ddd933
--- /dev/null
+++ b/core/modules/system/src/Tests/Validation/WidgetBaseErrorElementTest.php
@@ -0,0 +1,227 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Validation\WidgetBaseErrorElementTest.
+ */
+
+namespace Drupal\system\Tests\Validation;
+
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\Core\Entity\Entity\EntityFormDisplay;
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests the validation violation property paths.
+ *
+ * @group Validation
+ */
+class WidgetBaseErrorElementTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'system',
+    'language',
+    'user',
+    'node',
+    'widgetbase_error_element_test',
+  ];
+
+  /**
+   * User with permission to administer entites.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $adminUser;
+
+  /**
+   * Entity form display.
+   *
+   * @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface
+   */
+  protected $formDisplay;
+
+  /**
+   * URL to add new content.
+   *
+   * @var string
+   */
+  protected $formContentAddUrl;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->drupalCreateContentType(['type' => 'article']);
+    $this->adminUser = $this->drupalCreateUser([
+      'create article content',
+      'edit own article content',
+      'administer content types',
+    ]);
+    $this->drupalLogin($this->adminUser);
+
+    // Set article's form display.
+    $this->formDisplay = EntityFormDisplay::load('node.article.default');
+    if (!$this->formDisplay) {
+      $this->formDisplay = EntityFormDisplay::create([
+        'targetEntityType' => 'node',
+        'bundle' => 'article',
+        'mode' => 'default',
+        'status' => TRUE,
+      ])->save();
+    }
+
+    $this->formContentAddUrl = 'node/add/article';
+
+    $this->drupalGet($this->formContentAddUrl);
+    $this->assertResponse(200, 'Article add form can be accessed at ' . $this->formContentAddUrl);
+  }
+
+  /**
+   * Test validation violation of multiple form elements widget.
+   */
+  public function testMultipleFormElementsWidget() {
+    $edit = [];
+    // Add an text area with summary and email field to the article content
+    // type.
+    $fieldStorage = FieldStorageConfig::create([
+      'field_name' => 'field_test_multiple',
+      'entity_type' => 'node',
+      'type' => 'text_with_summary_and_email',
+    ]);
+    $fieldStorage->save();
+
+    $fieldInstance = FieldConfig::create([
+      'field_storage' => $fieldStorage,
+      'bundle' => 'article',
+      'label' => 'Text with summary',
+      'settings' => [
+        'display_summary' => TRUE,
+      ],
+    ]);
+    $fieldInstance->save();
+
+    $this->formDisplay
+      ->setComponent($fieldInstance->getName(), [
+        'type' => 'text_textarea_with_summary_and_email',
+      ])->save();
+
+    $email = 'invalid#invalid.com';
+    $edit['title[0][value]'] = $this->randomMachineName(8);
+    $edit['field_test_multiple[0][summary]'] = 'Some summary';
+    $edit['field_test_multiple[0][value]'] = 'Some text';
+    $edit['field_test_multiple[0][email]'] = $email;
+    $this->drupalPostForm($this->formContentAddUrl, $edit, t('Save'));
+    $this->assertResponse(200);
+    $this->assertPattern('/(?ms)<div role="alert">.*1 error has been found.*<div class="item-list">.*<a href="\#edit\-field\-test\-multiple\-0\-email">Email<\/a>.*<\/div>.*<\/div>/', 'Error message for the invalid email "'. $email .'" found on '. $this->formContentAddUrl .' form.');
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_test_multiple[0][email]" and boolean(@aria-invalid)]'), 'Email test field is marked invalid on form '. $this->formContentAddUrl);
+    $this->assertTrue((bool) $this->xpath('//textarea[@name="field_test_multiple[0][summary]" and not(boolean(@aria-invalid))]'), 'Summary test field is not marked invalid on form '. $this->formContentAddUrl);
+    $this->assertTrue((bool) $this->xpath('//textarea[@name="field_test_multiple[0][value]" and not(boolean(@aria-invalid))]'), 'Value test field is not marked invalid on form '. $this->formContentAddUrl);
+  }
+
+  /**
+   * Test validation violation of email single cardinality widget.
+   */
+  public function testSingleCardinalityWidget() {
+    $edit = [];
+    // Add an email field to the article content type.
+    $fieldStorage = FieldStorageConfig::create([
+      'field_name' => 'field_email',
+      'entity_type' => 'node',
+      'type' => 'email',
+    ]);
+    $fieldStorage->save();
+
+    $fieldInstance = FieldConfig::create([
+      'field_storage' => $fieldStorage,
+      'bundle' => 'article',
+      'label' => 'Email',
+    ]);
+    $fieldInstance->save();
+
+    $this->formDisplay
+      ->setComponent($fieldInstance->getName(), [
+        'type' => 'email_default',
+        'settings' => [
+          'placeholder' => 'example@example.com',
+        ],
+      ])->save();
+
+    // Post erroneous email address and check form errors.
+    $fieldName = 'field_email[0][value]';
+    $email = 'invalid#invalid.com';
+    $edit['title[0][value]'] = $this->randomMachineName(8);;
+    $edit[$fieldName] = $email;
+    $this->drupalPostForm($this->formContentAddUrl, $edit, t('Save'));
+    $this->assertResponse(200);
+    $this->assertPattern('/(?ms)<div role="alert">.*1 error has been found.*<div class="item-list">.*<a href="\#edit\-field\-email\-0\-value">Email<\/a>.*<\/div>.*<\/div>/', 'Error message for the invalid email "'. $email .'" found on '. $this->formContentAddUrl .' form.');
+    $this->assertTrue((bool) $this->xpath('//input[@name="'. $fieldName .'" and boolean(@aria-invalid)]'), 'Email field is marked invalid on form '. $this->formContentAddUrl);
+  }
+
+  /**
+   * Test validation violation of email multiple cardinality widget.
+   */
+  public function testMultipleCardinalityWidget() {
+    $validEmail1 = 'test1@example.com';
+    $validEmail2 = 'test1@example.com';
+    $invalidEmail1 = 'invalid1#invalid.com';
+    $invalidEmail2 = 'invalid1#invalid.com';
+    $edit = [];
+    // Add an email field to the article content type.
+    $fieldStorage = FieldStorageConfig::create([
+      'field_name' => 'field_email',
+      'entity_type' => 'node',
+      'type' => 'email',
+      'cardinality' => 3,
+    ]);
+    $fieldStorage->save();
+
+    $fieldInstance = FieldConfig::create([
+      'field_storage' => $fieldStorage,
+      'bundle' => 'article',
+      'label' => 'Email',
+    ]);
+    $fieldInstance->save();
+
+    $this->formDisplay
+      ->setComponent($fieldInstance->getName(), [
+        'type' => 'email_default',
+        'settings' => [
+          'placeholder' => 'example@example.com',
+        ],
+      ])->save();
+
+    // Post 3 email addresses, set erroneous email address in second field and
+    // check form errors.
+    $edit['title[0][value]'] = $this->randomMachineName(8);
+    $edit['field_email[0][value]'] = $validEmail1;
+    $edit['field_email[1][value]'] = $invalidEmail1;
+    $edit['field_email[2][value]'] = $validEmail2;
+    $this->drupalPostForm($this->formContentAddUrl, $edit, t('Save'));
+    $this->assertResponse(200);
+    $this->assertPattern('/(?ms)<div role="alert">.*1 error has been found.*<div class="item-list">.*<a href="\#edit\-field\-email\-1\-value">Email \(value 2\)<\/a>.*<\/div>.*<\/div>/', 'Error message for the invalid email "'. $invalidEmail1 .'" found on '. $this->formContentAddUrl .' form.');
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_email[0][value]" and not(boolean(@aria-invalid))]'), 'First email field is not marked invalid on form '. $this->formContentAddUrl);
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_email[1][value]" and boolean(@aria-invalid)]'), 'Second email field is marked invalid on form '. $this->formContentAddUrl);
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_email[2][value]" and not(boolean(@aria-invalid))]'), 'Third email field is not marked invalid on form '. $this->formContentAddUrl);
+
+    // Now set erroneous email address in first and third fields and check form
+    // errors.
+    $edit['title[0][value]'] = $this->randomMachineName(8);
+    $edit['field_email[0][value]'] = $invalidEmail1;
+    $edit['field_email[1][value]'] = $validEmail1;
+    $edit['field_email[2][value]'] = $invalidEmail2;
+    $this->drupalPostForm($this->formContentAddUrl, $edit, t('Save'));
+    $this->assertResponse(200);
+    $this->assertPattern('/(?ms)<div role="alert">.*2 errors have been found.*<div class="item-list">.*<a href="\#edit\-field\-email\-0\-value">Email \(value 1\)<\/a>.*<a href="\#edit\-field\-email\-2\-value">Email \(value 3\)<\/a>.*<\/div>.*<\/div>/', 'Error message for the invalid email "'. $invalidEmail1 .', '. $invalidEmail2 .'" found on '. $this->formContentAddUrl .' form.');
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_email[0][value]" and boolean(@aria-invalid)]'), 'First email field is marked invalid on form '. $this->formContentAddUrl);
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_email[1][value]" and not(boolean(@aria-invalid))]'), 'Second email field is not marked invalid on form '. $this->formContentAddUrl);
+    $this->assertTrue((bool) $this->xpath('//input[@name="field_email[2][value]" and boolean(@aria-invalid)]'), 'Third email field is marked invalid on form '. $this->formContentAddUrl);
+  }
+}
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/config/install/widgetbase_error_element_test.settings.yml b/core/modules/system/tests/modules/widgetbase_error_element_test/config/install/widgetbase_error_element_test.settings.yml
new file mode 100644
index 0000000..1ff3cbc
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/config/install/widgetbase_error_element_test.settings.yml
@@ -0,0 +1 @@
+default_summary_length: 600
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/config/schema/widgetbase_error_element_test.schema.yml b/core/modules/system/tests/modules/widgetbase_error_element_test/config/schema/widgetbase_error_element_test.schema.yml
new file mode 100644
index 0000000..fca9110
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/config/schema/widgetbase_error_element_test.schema.yml
@@ -0,0 +1,57 @@
+# Schema for the configuration files of the text module.
+
+widgetbase_error_element_test.settings:
+  type: config_object
+  label: 'Text settings'
+  mapping:
+    default_summary_length:
+      type: integer
+      label: 'Default summary length'
+
+field.storage_settings.text_with_summary_and_email:
+  label: 'Text (formatted, long, with summary and email) settings'
+  type: mapping
+
+field.field_settings.text_with_summary_and_email:
+  type: mapping
+  label: 'Text (formatted, long, with summary and email) settings'
+  mapping:
+    display_summary:
+      type: boolean
+      label: 'Summary input'
+
+field.value.text_with_summary_and_email:
+  type: mapping
+  label: 'Default value'
+  mapping:
+    value:
+      type: text
+      label: 'Body'
+    summary:
+      type: string
+      label: 'Summary'
+    email:
+      type: string
+      label: 'Email'
+    format:
+      type: string
+      label: 'Text format'
+
+field.formatter.settings.text_with_summary_and_email_default:
+  type: mapping
+  label: 'Formatted text default display format settings'
+
+field.widget.settings.text_textarea_with_summary_and_email:
+  type: mapping
+  label: 'Text area with a summary and email display format settings'
+  mapping:
+    rows:
+      type: integer
+      label: 'Rows'
+    summary_rows:
+      type: integer
+      label: 'Number of summary rows'
+    placeholder:
+      type: label
+      label: 'Placeholder'
+
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldFormatter/TextWithSummaryAndEmailDefaultFormatter.php b/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldFormatter/TextWithSummaryAndEmailDefaultFormatter.php
new file mode 100644
index 0000000..7aef2d8
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldFormatter/TextWithSummaryAndEmailDefaultFormatter.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\widgetbase_error_element_test\Plugin\Field\FieldFormatter\TextWithSummaryAndEmailDefaultFormatter.
+ */
+
+namespace Drupal\widgetbase_error_element_test\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Field\FieldItemListInterface;
+
+/**
+ * Plugin implementation of the 'test_text_default' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "text_with_summary_and_email_default",
+ *   label = @Translation("Default"),
+ *   field_types = {
+ *     "text_with_summary_and_email",
+ *   },
+ *   quickedit = {
+ *     "editor" = "plain_text"
+ *   }
+ * )
+ */
+class TextWithSummaryAndEmailDefaultFormatter extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $elements = array();
+
+    // The ProcessedText element already handles cache context & tag bubbling.
+    // @see \Drupal\filter\Element\ProcessedText::preRenderText()
+    foreach ($items as $delta => $item) {
+      $elements[$delta] = array(
+        '#type' => 'processed_text',
+        '#text' => $item->value,
+        '#format' => $item->format,
+        '#langcode' => $item->getLangcode(),
+      );
+    }
+
+    return $elements;
+  }
+
+}
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldType/TextWithSummaryAndEmailItem.php b/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldType/TextWithSummaryAndEmailItem.php
new file mode 100644
index 0000000..beafeec
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldType/TextWithSummaryAndEmailItem.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\widgetbase_error_element_test\Plugin\Field\FieldType\TextWithSummaryAndEmailItem.
+ */
+
+namespace Drupal\widgetbase_error_element_test\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\text\Plugin\Field\FieldType\TextWithSummaryItem;
+
+/**
+ * Plugin implementation of the 'test_text_with_summary' field type.
+ *
+ * @FieldType(
+ *   id = "text_with_summary_and_email",
+ *   label = @Translation("Text (formatted, long, with summary and email)"),
+ *   description = @Translation("This field stores long text with a format and an optional summary and email."),
+ *   category = @Translation("Text"),
+ *   default_widget = "text_textarea_with_summary_and_email",
+ *   default_formatter = "text_with_summary_and_email_default"
+ * )
+ */
+class TextWithSummaryAndEmailItem extends TextWithSummaryItem {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
+    $properties = parent::propertyDefinitions($field_definition);
+
+    $properties['email'] = DataDefinition::create('string')
+      ->setLabel(t('Email'))
+      ->addConstraint('Email', []);
+
+    return $properties;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    $schema = parent::schema($field_definition);
+    $schema['columns']['email'] = ['type' => 'varchar', 'length' => 255];
+    return $schema;
+  }
+
+}
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldWidget/TextareaWithSummaryAndEmailWidget.php b/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldWidget/TextareaWithSummaryAndEmailWidget.php
new file mode 100644
index 0000000..1b7fff8
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/src/Plugin/Field/FieldWidget/TextareaWithSummaryAndEmailWidget.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\widgetbase_error_element_test\Plugin\Field\FieldWidget\TextareaWithSummaryAndEmailWidget.
+ */
+
+namespace Drupal\widgetbase_error_element_test\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\text\Plugin\Field\FieldWidget\TextareaWithSummaryWidget;
+use Symfony\Component\Validator\ConstraintViolationInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+
+/**
+ * Plugin implementation of the 'text_textarea_with_summary_and_email' widget.
+ *
+ * @FieldWidget(
+ *   id = "text_textarea_with_summary_and_email",
+ *   label = @Translation("Text area with a summary and email"),
+ *   field_types = {
+ *     "text_with_summary_and_email"
+ *   }
+ * )
+ */
+class TextareaWithSummaryAndEmailWidget extends TextareaWithSummaryWidget {
+
+  /**
+   * {@inheritdoc}
+   */
+  function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $element = parent::formElement($items, $delta, $element, $form, $form_state);
+
+    $element['email'] = array(
+      '#type' => 'textfield',
+      '#default_value' => '',
+      '#title' => t('Email'),
+      '#weight' => -50,
+    );
+
+    return $element;
+  }
+
+}
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/widgetbase_error_element_test.info.yml b/core/modules/system/tests/modules/widgetbase_error_element_test/widgetbase_error_element_test.info.yml
new file mode 100644
index 0000000..516da0b
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/widgetbase_error_element_test.info.yml
@@ -0,0 +1,5 @@
+name: WidgetBase error element test module
+type: module
+description: 'Helper module for testing WidgetBase error elements.'
+package: Testing
+core: 8.x
diff --git a/core/modules/system/tests/modules/widgetbase_error_element_test/widgetbase_error_element_test.module b/core/modules/system/tests/modules/widgetbase_error_element_test/widgetbase_error_element_test.module
new file mode 100644
index 0000000..a66642f
--- /dev/null
+++ b/core/modules/system/tests/modules/widgetbase_error_element_test/widgetbase_error_element_test.module
@@ -0,0 +1,25 @@
+<?php
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\field\FieldStorageConfigInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * @file
+ * Helper module for testing WidgetBase error elements.
+ *
+ * The module adds validation constraint to summary test field.
+ */
+
+/**
+ * Implements hook_entity_bundle_field_info_alter().
+ */
+/*
+function widgetbase_error_element_test_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
+    file_put_contents('/tmp/tralala','<pre>'.print_r($fields,true).'</pre>');
+  if (($field_name = \Drupal::state()->get('field_text_with_summary', FALSE)) && $entity_type->id() == 'node' && $bundle == 'article' && !empty($fields[$field_name])) {
+    $fields[$field_name]->setPropertyConstraints('summary', ['NotNull' => []]);
+  }
+}
+*/
+
diff --git a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
index 0ac3151..48a4966 100644
--- a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
+++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
@@ -42,7 +42,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
-    if ($violation->arrayPropertyPath == array('format') && isset($element['format']['#access']) && !$element['format']['#access']) {
+    $error_path = $this->getLocalErrorPath($violation);
+    if ($error_path == ['format'] && isset($element['format']['#access']) && !$element['format']['#access']) {
       // Ignore validation errors for formats if formats may not be changed,
       // i.e. when existing formats become invalid. See filter_process_format().
       return FALSE;
diff --git a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php
index 8349f7a..219e501 100644
--- a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php
+++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWithSummaryWidget.php
@@ -11,6 +11,7 @@
 use Drupal\text\Plugin\Field\FieldWidget\TextareaWidget;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Component\Utility\NestedArray;
 
 /**
  * Plugin implementation of the 'text_textarea_with_summary' widget.
@@ -91,8 +92,12 @@ function formElement(FieldItemListInterface $items, $delta, array $element, arra
    * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
-    $element = parent::errorElement($element, $violation, $form, $form_state);
-    return ($element === FALSE) ? FALSE : $element[$violation->arrayPropertyPath[0]];
+    if ($element = parent::errorElement($element, $violation, $form, $form_state)) {
+      $error_path = $this->getLocalErrorPath($violation);
+      $nested_element =  NestedArray::getValue($element, $error_path);
+      return is_array($nested_element) ? $nested_element : FALSE;
+    }
+    return FALSE;
   }
 
 }
diff --git a/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php b/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php
index ab2f19a..95f5225 100644
--- a/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php
+++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php
@@ -42,7 +42,8 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    * {@inheritdoc}
    */
   public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
-    if ($violation->arrayPropertyPath == array('format') && isset($element['format']['#access']) && !$element['format']['#access']) {
+    $error_path = $this->getLocalErrorPath($violation);
+    if ($error_path == ['format'] && isset($element['format']['#access']) && !$element['format']['#access']) {
       // Ignore validation errors for formats if formats may not be changed,
       // i.e. when existing formats become invalid. See filter_process_format().
       return FALSE;
diff --git a/core/modules/views/src/Plugin/views/HandlerBase.php b/core/modules/views/src/Plugin/views/HandlerBase.php
index c6ae4b7..7b5fe3a 100644
--- a/core/modules/views/src/Plugin/views/HandlerBase.php
+++ b/core/modules/views/src/Plugin/views/HandlerBase.php
@@ -185,7 +185,7 @@ public function adminLabel($short = FALSE) {
       return $this->options['admin_label'];
     }
     $title = ($short && isset($this->definition['title short'])) ? $this->definition['title short'] : $this->definition['title'];
-    return $this->t('@group: @title', array('@group' => $this->definition['group'], '@title' => $title));
+    return $this->t('!group: !title', array('!group' => $this->definition['group'], '!title' => $title));
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php
index 449cc23..ecb6a62 100644
--- a/core/modules/views/src/Plugin/views/PluginBase.php
+++ b/core/modules/views/src/Plugin/views/PluginBase.php
@@ -585,7 +585,7 @@ protected function listLanguages($flags = LanguageInterface::STATE_ALL, array $c
           $name = $types_info[$id]['name'];
           // Surround IDs by '***LANGUAGE_...***', to avoid query collisions.
           $id = '***LANGUAGE_' . $id . '***';
-          $list[$id] = $this->t('@type language selected for page', array('@type' => $name));
+          $list[$id] = $this->t('!type language selected for page', array('!type' => $name));
         }
       }
       if (!empty($current_values)) {
@@ -595,7 +595,7 @@ protected function listLanguages($flags = LanguageInterface::STATE_ALL, array $c
           // add that option too, so it is not lost. If not among the current
           // values, skip displaying it to avoid user confusion.
           if (isset($type['name']) && !isset($list[$id]) && in_array($id, $current_values)) {
-            $list[$id] = $this->t('@type language selected for page', array('@type' => $type['name']));
+            $list[$id] = $this->t('!type language selected for page', array('!type' => $type['name']));
           }
         }
       }
diff --git a/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php b/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php
index cadb796..036e369 100644
--- a/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php
+++ b/core/modules/views/src/Plugin/views/area/HTTPStatusCode.php
@@ -48,7 +48,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
 
     // Add the HTTP status code, so it's easier for people to find it.
     array_walk($options, function($title, $code) use(&$options) {
-      $options[$code] = $this->t('@code (@title)', array('@code' => $code, '@title' => $title));
+      $options[$code] = $this->t('@code (!title)', array('@code' => $code, '!title' => $title));
     });
 
     $form['status_code'] = array(
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 980da73..76ae608 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -1544,7 +1544,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         if ($access_plugin->usesOptions()) {
           $form['markup'] = array(
             '#prefix' => '<div class="js-form-item form-item description">',
-            '#markup' => $this->t('You may also adjust the @settings for the currently selected access restriction.', array('@settings' => $this->optionLink($this->t('settings'), 'access_options'))),
+            '#markup' => $this->t('You may also adjust the !settings for the currently selected access restriction.', array('!settings' => $this->optionLink(t('settings'), 'access_options'))),
             '#suffix' => '</div>',
           );
         }
@@ -1582,7 +1582,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
           $form['markup'] = array(
             '#prefix' => '<div class="js-form-item form-item description">',
             '#suffix' => '</div>',
-            '#markup' => $this->t('You may also adjust the @settings for the currently selected cache mechanism.', array('@settings' => $this->optionLink($this->t('settings'), 'cache_options'))),
+            '#markup' => $this->t('You may also adjust the !settings for the currently selected cache mechanism.', array('!settings' => $this->optionLink(t('settings'), 'cache_options'))),
           );
         }
         break;
@@ -1654,7 +1654,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
           $form['markup'] = array(
             '#prefix' => '<div class="js-form-item form-item description">',
             '#suffix' => '</div>',
-            '#markup' => $this->t('You may also adjust the @settings for the currently selected style.', array('@settings' => $this->optionLink($this->t('settings'), 'style_options'))),
+            '#markup' => $this->t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->optionLink(t('settings'), 'style_options'))),
           );
         }
 
@@ -1702,7 +1702,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
           $form['markup'] = array(
             '#prefix' => '<div class="js-form-item form-item description">',
             '#suffix' => '</div>',
-            '#markup' => $this->t('You may also adjust the @settings for the currently selected row style.', array('@settings' => $this->optionLink($this->t('settings'), 'row_options'))),
+            '#markup' => $this->t('You may also adjust the !settings for the currently selected row style.', array('!settings' => $this->optionLink(t('settings'), 'row_options'))),
           );
         }
 
@@ -1803,7 +1803,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
           $form['markup'] = array(
             '#prefix' => '<div class="js-form-item form-item description">',
             '#suffix' => '</div>',
-            '#markup' => $this->t('You may also adjust the @settings for the currently selected style.', array('@settings' => $this->optionLink($this->t('settings'), 'exposed_form_options'))),
+            '#markup' => $this->t('You may also adjust the !settings for the currently selected style.', array('!settings' => $this->optionLink(t('settings'), 'exposed_form_options'))),
           );
         }
         break;
@@ -1839,7 +1839,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
           $form['markup'] = array(
             '#prefix' => '<div class="js-form-item form-item description">',
             '#suffix' => '</div>',
-            '#markup' => $this->t('You may also adjust the @settings for the currently selected pager.', array('@settings' => $this->optionLink($this->t('settings'), 'pager_options'))),
+            '#markup' => $this->t('You may also adjust the !settings for the currently selected pager.', array('!settings' => $this->optionLink(t('settings'), 'pager_options'))),
           );
         }
 
diff --git a/core/modules/views/src/Plugin/views/filter/Date.php b/core/modules/views/src/Plugin/views/filter/Date.php
index 52dabbe..60dd605 100644
--- a/core/modules/views/src/Plugin/views/filter/Date.php
+++ b/core/modules/views/src/Plugin/views/filter/Date.php
@@ -37,7 +37,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
         '#title' => $this->t('Value type'),
         '#options' => array(
           'date' => $this->t('A date in any machine readable format. CCYY-MM-DD HH:MM:SS is preferred.'),
-          'offset' => $this->t('An offset from the current time such as "@example1" or "@example2"', array('@example1' => '+1 day', '@example2' => '-2 hours -30 minutes')),
+          'offset' => $this->t('An offset from the current time such as "!example1" or "!example2"', array('!example1' => '+1 day', '!example2' => '-2 hours -30 minutes')),
         ),
         '#default_value' => !empty($this->value['type']) ? $this->value['type'] : 'date',
       );
diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php
index 50f470e..e88fbc7 100644
--- a/core/modules/views/views.api.php
+++ b/core/modules/views/views.api.php
@@ -487,7 +487,7 @@ function hook_field_views_data(\Drupal\field\FieldStorageConfigInterface $field_
       'id' => 'standard',
       'base' => 'file_managed',
       'base field' => 'target_id',
-      'label' => t('image from @field_name', array('@field_name' => $field_storage->getName())),
+      'label' => t('image from !field_name', array('!field_name' => $field_storage->getName())),
     );
   }
 
@@ -531,7 +531,7 @@ function hook_field_views_data_alter(array &$data, \Drupal\field\FieldStorageCon
     'field field' => $field_name . '_target_id',
     'base' => $entity_type->getBaseTable(),
     'base field' => $entity_type->getKey('id'),
-    'label' => $field_name,
+    'label' => t('!field_name', array('!field_name' => $field_name)),
     'join_extra' => array(
       0 => array(
         'field' => 'deleted',
@@ -588,7 +588,7 @@ function hook_field_views_data_views_data_alter(array &$data, \Drupal\field\Fiel
     'field field' => $field_name . '_target_id',
     'base' => $entity_type->getBaseTable(),
     'base field' => $entity_type->getKey('id'),
-    'label' => $field_name,
+    'label' => t('!field_name', array('!field_name' => $field_name)),
     'join_extra' => array(
       0 => array(
         'field' => 'deleted',
diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc
index 9948880..4f28122 100644
--- a/core/modules/views/views.views.inc
+++ b/core/modules/views/views.views.inc
@@ -497,12 +497,12 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
     }
 
     if (count($field_columns) == 1 || $column == 'value') {
-      $title = t('@label (@name)', array('@label' => $label, '@name' => $field_name));
+      $title = t('@label (!name)', array('@label' => $label, '!name' => $field_name));
       $title_short = $label;
     }
     else {
-      $title = t('@label (@name:@column)', array('@label' => $label, '@name' => $field_name, '@column' => $column));
-      $title_short = t('@label:@column', array('@label' => $label, '@column' => $column));
+      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field_name, '!column' => $column));
+      $title_short = t('@label:!column', array('@label' => $label, '!column' => $column));
     }
 
     // Expose data for the property.
@@ -535,10 +535,10 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
       foreach ($all_labels as $label_name => $true) {
         if ($label != $label_name) {
           if (count($field_columns) == 1 || $column == 'value') {
-            $alias_title = t('@label (@name)', array('@label' => $label_name, '@name' => $field_name));
+            $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field_name));
           }
           else {
-            $alias_title = t('@label (@name:@column)', array('@label' => $label_name, '@name' => $field_name, '@column' => $column));
+            $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field_name, '!column' => $column));
           }
           $aliases[] = array(
             'group' => $group_name,
@@ -589,7 +589,7 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
 
       // Expose additional delta column for multiple value fields.
       if ($field_storage->isMultiple()) {
-        $title_delta = t('@label (@name:delta)', array('@label' => $label, '@name' => $field_name));
+        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field_name));
         $title_short_delta = t('@label:delta', array('@label' => $label));
 
         $data[$table_alias]['delta'] = array(
diff --git a/core/modules/views_ui/css/views_ui.admin.theme.css b/core/modules/views_ui/css/views_ui.admin.theme.css
index 5dc2e4d..6e7f1e0 100644
--- a/core/modules/views_ui/css/views_ui.admin.theme.css
+++ b/core/modules/views_ui/css/views_ui.admin.theme.css
@@ -512,14 +512,6 @@ td.group-title {
   margin-right: 0.2083em;
 }
 
-.views-ui-display-tab-setting > span {
-  margin-left: 0.5em; /* LTR */
-}
-[dir="rtl"] .views-ui-display-tab-setting > span {
-  margin-left: 0;
-  margin-right: 0.5em;
-}
-
 /** Applies an overridden(italics) font style to overridden buckets.
  * The better way to implement this would be to add the overridden class
  * to the bucket header when the bucket is overridden and style it as a
diff --git a/core/modules/views_ui/src/Form/Ajax/AddHandler.php b/core/modules/views_ui/src/Form/Ajax/AddHandler.php
index 56cb435..eef8f7d 100644
--- a/core/modules/views_ui/src/Form/Ajax/AddHandler.php
+++ b/core/modules/views_ui/src/Form/Ajax/AddHandler.php
@@ -139,7 +139,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
         foreach ($group_options as $key => $option) {
           $form['options']['name'][$key] = array(
             '#type' => 'checkbox',
-            '#title' => $this->t('@group: @field', array('@group' => $option['group'], '@field' => $option['title'])),
+            '#title' => $this->t('!group: !field', array('!group' => $option['group'], '!field' => $option['title'])),
             '#description' => $option['help'],
             '#return_value' => $key,
             '#prefix' => "<div class='filterable-option'>",
diff --git a/core/modules/views_ui/src/Form/BreakLockForm.php b/core/modules/views_ui/src/Form/BreakLockForm.php
index 89f0ce0..82f1f6f 100644
--- a/core/modules/views_ui/src/Form/BreakLockForm.php
+++ b/core/modules/views_ui/src/Form/BreakLockForm.php
@@ -79,7 +79,7 @@ public function getDescription() {
       '#theme' => 'username',
       '#account' => $account,
     );
-    return $this->t('By breaking this lock, any unsaved changes made by @user will be lost.', array('@user' => drupal_render($username)));
+    return $this->t('By breaking this lock, any unsaved changes made by !user will be lost.', array('!user' => drupal_render($username)));
   }
 
   /**
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index 818984a..dc7a312 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -752,14 +752,14 @@ public function renderDisplayTop(ViewUI $view) {
     foreach (Views::fetchPluginNames('display', NULL, array($view->get('base_table'))) as $type => $label) {
       $element['add_display'][$type] = array(
         '#type' => 'submit',
-        '#value' => $this->t('Add @display', array('@display' => $label)),
+        '#value' => $this->t('Add !display', array('!display' => $label)),
         '#limit_validation_errors' => array(),
         '#submit' => array('::submitDisplayAdd', '::submitDelayDestination'),
         '#attributes' => array('class' => array('add-display')),
         // Allow JavaScript to remove the 'Add ' prefix from the button label when
         // placing the button in a "Add" dropdown menu.
         '#process' => array_merge(array('views_ui_form_button_was_clicked'), $this->elementInfo->getInfoProperty('submit', '#process', array())),
-        '#values' => array($this->t('Add @display', array('@display' => $label)), $label),
+        '#values' => array($this->t('Add !display', array('!display' => $label)), $label),
       );
     }
 
@@ -1130,8 +1130,12 @@ public function getFormBucket(ViewUI $view, $type, $display) {
         $last = end($keys);
         foreach ($contents as $key => $pid) {
           if ($key != $last) {
-            $operator = $group_info['groups'][$gid] == 'OR' ? $this->t('OR') : $this->t('AND');
-            $store[$pid]['#link'] = SafeMarkup::format('@link <span>@operator</span>', ['@link' => $store[$pid]['#link'], '@operator' => $operator]);
+            if ($group_info['groups'][$gid] == 'OR') {
+              $store[$pid]['#link'] = $this->t('!link &nbsp;&nbsp; OR', ['!link' => $store[$pid]['#link']]);
+            }
+            else {
+              $store[$pid]['#link'] = $this->t('!link &nbsp;&nbsp; AND', ['!link' => $store[$pid]['#link']]);
+            }
           }
           $build['fields'][$pid] = $store[$pid];
         }
