Problem When the localization REST endpoint fails to return usable JSON, the xwiki-l10n RequireJS loader plugin never resolves its module. Every JavaScript module that declares a xwiki-l10n!... dependency is therefore blocked forever instead of degrading to untranslated keys, so the feature it implements silently never initialises. Steps to reproduce
- Make /xwiki/rest/wikis/<wiki>/localization/translations return something other than the expected JSON — an HTTP error, a network failure, or an HTML error page injected by a reverse proxy / CDN in front of XWiki.
- Load any page whose JavaScript depends on translations through the xwiki-l10n! loader plugin — for example any page containing a Live Data.
Actual behaviour The browser console reports, once per query:
Failed to retrieve the translations for query [...]
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
An issue occurred during the resolution of localization query [object Object]
and the dependent modules never finish loading. A Live Data, for instance, renders the raw translation keys (livedata.pagination.currentEntries, livedata.filter.list.emptyLabel, ...) and no entries at all. Cause In xwiki-platform-localization-webjar/src/main/node/src/l10n.ts, the loader's resolve() rejection handler logs the error but never calls onLoad:
.catch((err: unknown) => {
console.error(
`An issue occurred during the resolution of localization query ${query}`,
err,
);
});
RequireJS waits for onLoad to be called before considering the module loaded, so the promise rejection turns into a permanently pending module. Two smaller problems are visible in the same handler:
- ${query} interpolates the query object, producing the useless [object Object] in the message. It should be serialised.
- The rejection observed in practice is a TypeError: Cannot read properties of undefined (reading 'escapeHTML') rather than the underlying JSON parse error, which suggests the error is being mangled on the way out of the resolver and makes diagnosis harder.
Expected behaviour A failed translation resolution should degrade gracefully rather than break the page: onLoad should still be called — with the untranslated keys, or with an empty map whose get() returns null — so that dependent modules initialise and merely display untranslated labels. The error should stay logged, and the logged message should identify the failing query. How this was found Observed on xwiki.org, where Cloudflare currently answers every /xwiki/rest/** request with a managed-challenge HTML page (403, cf-mitigated: challenge). That Cloudflare rule is a separate, infrastructure-side problem, but it exposed the fact that XWiki has no graceful fallback: instead of a page with untranslated labels, every page containing a Live Data is left non-functional. |