Problem
WCAG 2.5.3 Label in Name requires that the accessible name of a control contains the visible label text. In ConfigTranslationController, "Edit", "Delete", and "Add" links are repeated for every language with no aria-label or visually-hidden text to distinguish them.
Visible text: "Edit", "Delete", "Add" (repeated per language row)
Accessible name: "Edit", "Delete", "Add" (identical for every row)
A speech recognition user who says "Click Edit" will see all matching links highlighted with numbers. They must then say the correct number to select the one they want — for every single action.
Proposed resolution
Add aria-label attributes that include the language name:
For the original language edit link (around line 210):
$operations['edit'] = [ 'title' => $this->t('Edit'), 'url' => Url::fromRoute($mapper->getBaseRouteName(), $mapper->getBaseRouteParameters(), ['query' => ['destination' => $mapper->getOverviewPath()]]), 'attributes' => [ 'aria-label' => $this->t('Edit @language', ['@language' => $language->getName()]), ], ];
For translated language links (around lines 230-266):
$operations['add'] = [ 'title' => $this->t('Add'), 'url' => Url::fromRoute($mapper->getAddRouteName(), $mapper->getAddRouteParameters()), 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 880]), 'aria-label' => $this->t('Add @language translation', ['@language' => $language->getName()]), ], ]; $operations['edit'] = [ 'title' => $this->t('Edit'), 'url' => Url::fromRoute($mapper->getEditRouteName(), $mapper->getEditRouteParameters()), 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 880]), 'aria-label' => $this->t('Edit @language translation', ['@language' => $language->getName()]), ], ]; $operations['delete'] = [ 'title' => $this->t('Delete'), 'url' => Url::fromRoute($mapper->getDeleteRouteName(), $mapper->getDeleteRouteParameters()), 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 880]), 'aria-label' => $this->t('Delete @language translation', ['@language' => $language->getName()]), ], ];
File
core/modules/config_translation/src/Controller/ConfigTranslationController.php— lines 209-266
Test
Add a FunctionalJavascript test that:
- Enables multilingual with at least two languages
- Visits a config translation overview page
- Asserts each language row's Edit, Delete, and Add links have unique aria-labels containing the language name
Related
AI Disclaimer: This was done with a lot of help from AI.
Comments
Comment #2
mgiffordComment #3
mgifford