The new language switcher added in v1.1.0 (resources/js/components/LocaleSwitcher.vue) represents each of the 16 locales with a country flag, sourced from App\Enums\User\Locale::flag() (app/Enums/User/Locale.php:50). Two problems with this:
-
Flags are a documented anti-pattern for language selection. W3C internationalisation guidance is explicit: "Do not use flag icons to indicate languages! Flags represent countries, not languages." (W3C: Indicating the language of a link). Flags have nationalistic connotations that can be unwelcome to speakers of the same language in other countries.
-
The current mapping can't avoid being wrong. With 16 locales spanning many countries each: English => 'US' excludes ~59 other English-speaking countries; Arabic => 'SA' picks one country for 22 Arabic-speaking ones; Chinese => 'CN', Russian => 'RU' and Greek => 'GR' are each guaranteed to be the wrong flag for a large share of their speakers.
The fix is already in the code: Locale::label() produces correct endonyms (English, Українська, Español, 日本語, العربية…) which the switcher already renders next to each flag. Removing flag() and the
elements would leave a clean, standard text-only selector – optionally with a globe icon on the trigger, which is the W3C's suggested neutral affordance. The alt text on the flag images is already the language name, so nothing is lost for screen readers.
The new language switcher added in v1.1.0 (resources/js/components/LocaleSwitcher.vue) represents each of the 16 locales with a country flag, sourced from App\Enums\User\Locale::flag() (app/Enums/User/Locale.php:50). Two problems with this:
Flags are a documented anti-pattern for language selection. W3C internationalisation guidance is explicit: "Do not use flag icons to indicate languages! Flags represent countries, not languages." (W3C: Indicating the language of a link). Flags have nationalistic connotations that can be unwelcome to speakers of the same language in other countries.
The current mapping can't avoid being wrong. With 16 locales spanning many countries each: English => 'US' excludes ~59 other English-speaking countries; Arabic => 'SA' picks one country for 22 Arabic-speaking ones; Chinese => 'CN', Russian => 'RU' and Greek => 'GR' are each guaranteed to be the wrong flag for a large share of their speakers.
The fix is already in the code: Locale::label() produces correct endonyms (English, Українська, Español, 日本語, العربية…) which the switcher already renders next to each flag. Removing flag() and the
elements would leave a clean, standard text-only selector – optionally with a globe icon on the trigger, which is the W3C's suggested neutral affordance. The alt text on the flag images is already the language name, so nothing is lost for screen readers.