From ecf396842fcb7a34ecbf59d5c56d419e2fb1df15 Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Tue, 21 Nov 2023 13:58:37 +0000 Subject: [PATCH] MDL-80185 lang: use iso6391 language code for HTML lang attributes. This resolves accessibility issues where Moodle language pack codes didn't always map to correspondingly named iso6391 codes. Where this value is defined in the language configuration, it will now be used. --- lib/classes/output/language_menu.php | 2 +- lib/tests/weblib_test.php | 5 +++-- lib/weblib.php | 16 ++++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/classes/output/language_menu.php b/lib/classes/output/language_menu.php index 846362bbe5e..a6cb9cf7376 100644 --- a/lib/classes/output/language_menu.php +++ b/lib/classes/output/language_menu.php @@ -151,7 +151,7 @@ class language_menu implements \renderable, \templatable { if ($langparam) { $attributes = [ 'data-lang' => $langparam, - 'lang' => $langparam, + 'lang' => get_html_lang_attribute_value($langparam), ]; } $lang = new \action_menu_link_secondary($node['url'], null, $node['title'], $attributes); diff --git a/lib/tests/weblib_test.php b/lib/tests/weblib_test.php index 98d25d2160f..4dc96ae6548 100644 --- a/lib/tests/weblib_test.php +++ b/lib/tests/weblib_test.php @@ -1163,9 +1163,10 @@ EXPECTED; */ public function get_html_lang_attribute_value_provider() { return [ - 'Empty lang code' => [' ', 'unknown'], + 'Empty lang code' => [' ', 'en'], 'English' => ['en', 'en'], - 'English, US' => ['en_us', 'en-us'], + 'English, US' => ['en_us', 'en'], + 'Unknown' => ['xx', 'en'], ]; } diff --git a/lib/weblib.php b/lib/weblib.php index 733ea344b8a..41f9c629b44 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -2283,11 +2283,19 @@ function highlightfast($needle, $haystack) { * @return string */ function get_html_lang_attribute_value(string $langcode): string { - if (empty(trim($langcode))) { - // If the language code passed is an empty string, return 'unknown'. - return 'unknown'; + $langcode = clean_param($langcode, PARAM_LANG); + if ($langcode === '') { + return 'en'; } - return str_replace('_', '-', $langcode); + + // Grab language ISO code from lang config. If it differs from English, then it's been specified and we can return it. + $langiso = (string) (new lang_string('iso6391', 'core_langconfig', null, $langcode)); + if ($langiso !== 'en') { + return $langiso; + } + + // Where we cannot determine the value from lang config, use the first two characters from the lang code. + return substr($langcode, 0, 2); } /**