Bug 291956

Summary: i18n placeholder bugs
Product: WebKit Reporter: lcohen
Component: WebKit ExtensionsAssignee: Nobody <webkit-unassigned>
Status: NEW    
Severity: Normal CC: alexeiatyahoodotcom, carlosj-webkit-bugzilla, timothy, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: Safari 18   
Hardware: Mac (Apple Silicon)   
OS: macOS 15   
See Also: https://bugs.webkit.org/show_bug.cgi?id=306492

lcohen
Reported 2025-04-23 07:19:23 PDT
I've noticed two bugs when using placeholders with i18n.getMessage(): 1) When two placeholders surround a word without intervening spaces (i.e. "$START_LINK_TAG$here$END_LINK_TAG"), the substitution is incorrect (doesn't include the inner word and includes the placeholder title instead of the placeholder content). Spaces need to be added in between the placeholders and inner word for the substitution to be correct, but that workaround causes other minor issues. 2) If you pass an integer as a placeholder (i.e. chrome.i18n.getMessage("example_message", [intValue]), the placeholder is missing from the resulting message. This can be worked around by casting the numeric placeholder value to string first, but Webkit should handle this case. Neither of these issues occur in Chrome or Firefox. Steps to reproduce: - Add the following code to these Safari Web Extension files (or use this demo extension: https://github.com/lenacohen/Safari-Test-Extensions/tree/main/dnr-placeholder-bugs/i18n%20Placeholder%20Bugs) _locales/en/messages.json: "popup_instructions_original": { "message": "Integer placeholders don't appear instead of being cast as strings. Placeholders surrounding a word break unless there's at least one inner space: $COUNT$ potential $LINK_START$trackers$LINK_END$ blocked", "description": "Popup message shown when at least one tracker was blocked.", "placeholders": { "count": { "content": "$1", "example": "15" }, "link_start": { "content": "$2", "example": "<a href='https://privacybadger.org/#What-is-a-third-party-tracker'>" }, "link_end": { "content": "</a>" } } }, popup.js: document.addEventListener('DOMContentLoaded', () => { const msg = chrome.i18n.getMessage("popup_instructions_original", [ 5, "<a target='_blank' title='What is a third-party tracker?' href='https://privacybadger.org/#What-is-a-third-party-tracker'>", "</a>" ]); document.getElementById('placeholder-test-original').innerHTML = msg; }); popup.html: <p id="placeholder-test-original"></p> Expected Result: Popup contains the phrase "5 potential trackers blocked" ("trackers" is linked to https://privacybadger.org/#What-is-a-third-party-tracker) Actual result: The popup instead says: " potential LINK_END$ blocked" Workarounds: We've resorted to adding an extra space between the word and its surrounding placeholders (i.e. “… $LINK_START$ trackers $LINK_END$ …”, “… $LINK_START$trackers $LINK_END$ …”, or “… $LINK_START$ trackers$LINK_END$ …” The problem with this workaround is: 1) it's difficult to manage with translators who will likely remove the space 2) it is an issue in some locales (e.g. Chinese) where characters should be next to each other with no spaces and we don't want to introduce a weird space
Attachments
Radar WebKit Bug Importer
Comment 1 2025-04-23 07:21:02 PDT
Carlos J.
Comment 2 2026-01-06 11:03:29 PST
Simplified cross-browser demo extension: https://jeurissen.co/webext-demos/i18n-placeholders
Alexei
Comment 3 2026-03-12 06:34:23 PDT
This is still a problem with Safari 26.3 Additionally, we discovered a variant of this bug where two consecutive placeholders result in garbled output. For example: "widget_placeholder_pb_has_replaced": { "message": "Privacy Badger заменил $START_ANCHOR_TAG$ виджет $WIDGET$ $END_ANCHOR_TAG$", "description": "...", "placeholders": { "widget": { "content": "$1", "example": "Google reCAPTCHA" }, "start_anchor_tag": { "content": "$2", "example": "<a href='...'>" }, "end_anchor_tag": { "content": "$3", "example": "</a>" } } }, Expected: Privacy Badger заменил <a href="...">виджет Facebook Video </a> Actual: Privacy Badger заменил <a href="...">виджет Facebook Video $</a>ivacy Badger заменил <a href="...">виджет Facebook Video $3
Carlos J.
Comment 4 2026-04-08 06:34:49 PDT
Updated the demo extension to clearly indicate the incorrect results mentioned by Alexei above: https://jeurissen.co/webext-demos/i18n-placeholders The extension highlights expected vs actual.
Note You need to log in before you can comment on or make changes to this bug.