NEW262140
SVGTests::isValid() does not correctly implement systemLanguage matching per SVG2
https://bugs.webkit.org/show_bug.cgi?id=262140
Summary SVGTests::isValid() does not correctly implement systemLanguage matching per ...
Ahmad Saleem
Reported 2023-09-26 14:21:13 PDT
Hi Team, While going through Blink's commit, I came across another failing test case in Safari 17 (macOS Sonoma). Test Case: https://jsfiddle.net/35yL6qnw/5/ ^ above shows 'en FAIL' in Red (Safari) while show 'EN' in Black (Chrome Canary 119 and Firefox Nightly 120). Blink Commit: https://chromium.googlesource.com/chromium/src.git/+/1f24b02c1e563e405a59d5d44eeb03a6f2c00d59 Web-Spec: https://www.w3.org/TR/SVG11/struct.html#ConditionalProcessingSystemLanguageAttribute ___ Just wanted to raise so we can fix it. Thanks!
Attachments
Ahmad Saleem
Comment 2 2023-09-26 14:59:15 PDT
static bool isLangTagPrefix(const String& langTag, const String& language) { if (!langTag.startsWithIgnoringASCIICase(language)) return false; return langTag.length() == language.length() || langTag[language.length()] == '-'; } static bool matchLanguageList(const String& langTag, const Vector<String>& languages) { for (const auto& value : languages) { if (isLangTagPrefix(langTag, value)) return true; } return false; } and following changes here: "SVGTests::isValid()" for (auto& langTag : attributes->systemLanguage().items()) { if (matchLanguageList(langTag, genericDefaultLanguage)) return false; } ___ It leads to following compile errors: candidate function not viable: no known conversion from 'StringView' to 'const Vector<String>' for 2nd argument and no matching function for call to 'matchLanguageList' ___ Still looking into it but if someone want to take it. Go ahead and run with it. Might not come back soon but good to share what tried to make it easier for others.
Karl Dubost
Comment 3 2023-09-27 01:13:27 PDT
Probably fixing Bug 262146 first would help with this one.
Radar WebKit Bug Importer
Comment 4 2023-10-03 14:22:21 PDT
Karl Dubost
Comment 5 2026-04-08 08:03:06 PDT
## Spec reference https://w3c.github.io/svgwg/svg2-draft/struct.html#ConditionalProcessingSystemLanguageAttribute > "Evaluates to "true" if one of the language tags indicated by user preferences > is a case-insensitive match of one of the language tags given in the value of > this parameter, or if one of the language tags indicated by user preferences is > a case-insensitive prefix of one of the language tags given in the value of this > parameter such that the first tag character following the prefix is "-"." ## Current code https://searchfox.org/wubkat/rev/9971986dcebbc9ad5713a058e7951288c455bbee/Source/WebCore/svg/SVGTests.cpp#72-89 ```cpp bool SVGTests::isValid() const { auto attributes = conditionalProcessingAttributesIfExists(); if (!attributes) return true; String defaultLanguage = WTF::defaultLanguage(); auto genericDefaultLanguage = StringView(defaultLanguage).left(2); for (auto& language : attributes->systemLanguage().items()) { if (language != genericDefaultLanguage) return false; } for (auto& extension : attributes->requiredExtensions().items()) { if (!hasExtension(extension)) return false; } return true; } ```
Karl Dubost
Comment 6 2026-04-08 08:05:51 PDT
1. ALL vs ANY matching (most impactful) The loop returns `false` if ANY listed language does NOT match. This means ALL languages must match. The spec says the opposite: return `true` if ANY listed language matches. Current: `systemLanguage="en, fr, de"` with user language `en` → **false** (because `fr` and `de` don't match) Expected: `systemLanguage="en, fr, de"` with user language `en` → **true** (because `en` matches) This is the primary use case for `systemLanguage` — listing multiple acceptable languages in a `<switch>` element, e.g.: ```xml <text systemLanguage="mi, en"><!-- content for Maori or English speakers --></text> ``` 2. Language tag truncated to 2 characters `StringView(defaultLanguage).left(2)` reduces the user's language tag to its first 2 characters. This means: - User language `zh-Hans` becomes `zh` loses the script subtag - User language `pt-BR` becomes `pt` loses the region subtag - Comparison against listed tag `zh-Hans` would fail because `zh != zh-Hans` 3. Case-sensitive comparison The spec requires "case-insensitive match". The current code uses `!=` which is case-sensitive. A listed tag `"EN"` would not match user language `"en"`. ### 4. No BCP 47 prefix matching The spec says: evaluate to true if a user language tag "is a case-insensitive prefix of one of the language tags given in the value of this parameter such that the first tag character following the prefix is '-'". This means: - User `"en"` should match listed `"en-US"` (prefix + "-") - User `"zh"` should match listed `"zh-Hans"` (prefix + "-") The current code does none of this — it only does exact (truncated) comparison.
Karl Dubost
Comment 7 2026-04-08 08:07:57 PDT
## Steps to reproduce 1. Set browser language to English (`en`) 2. Load an SVG with `<switch>` containing `<text systemLanguage="en, fr">Hello</text>` 3. Expected: text renders (because `en` matches) 4. Actual: text does not render (because `fr` doesn't match and ALL must match) I have fixed the first part about parsing in Bug 262146. This one will be about validation.
Karl Dubost
Comment 8 2026-04-17 07:49:58 PDT
Note You need to log in before you can comment on or make changes to this bug.