Problem/Motivation
A config entity is available in its own base language, but a strict langCode read says otherwise. On an English site, GET /jsonapi/menu/menu/{uuid}?langCode=en returns 404, and GET /jsonapi/menu/menu?langCode=en omits every menu that has no dedicated en override.
Since #3613823 made langCode the only read selector, a client that uniformly appends it cannot read config entities in the site's own language at all.
The clearest symptom is that the error contradicts itself. The strict miss is thrown on an override-only check, while the error body advertises availability computed as base language plus overrides, so the response reads:
{"errors":[{"detail":"The \"en\" translation of the specified resource does not exist. Available translations: en, fr.","meta":{"availableTranslations":["en","fr"]}}]}
The module already defines availability correctly in three other places (availableConfigLangcodes() on both the controller and the access checker, and the ?include= path's membership check). Only two sites, the individual strict-miss gate and the collection filter, use the narrower "has an override" test, and both predate the helper.
This also violates the module's own spec, which defines an available language for config as "a config override or the base config in that language".
Steps to reproduce
- Site with
en(default) andfrconfigured, and a menu with anfrconfig override. GET /jsonapi/menu/menu/{uuid}?langCode=en→404, with a detail that listsenamong the available translations.GET /jsonapi/menu/menu?langCode=en→ the menu is missing from the collection.GET /jsonapi/menu/menu/{uuid}?langCode=fr→200, as expected.GET /jsonapi/node/article/{uuid}?include=node_type&langCode=fr→ the node type is correctly reported undermeta.omitted, showing the include path already gets this right.
Proposed resolution
Use one definition of config availability everywhere: base language plus overrides.
- Individual reads: the strict-miss gate tests membership of
availableConfigLangcodes()instead of override existence. The guard fails open: when the language manager is not aConfigurableLanguageManagerInterfacethe 404 branch is skipped entirely, rather than rejecting everything, matching how the access checker already degrades on a non-multilingual site. - Collections: the strict filter loads each candidate and applies the same membership test. The ids are config entity IDs rather than loaded entities, so the filter loads them; the removed
Accept-Languagearm used the same shape for the same reason. - Fallback mode is untouched. With
includeFallback=1a config entity is already served with the requested language's overrides when present and its base values otherwise, which is the config override layer's own fallback. - The now-unused
configEntityHasOverride()helper is deleted, and bothDIVERGENCE(core):comments are reworded from "no override for that language" to "no content in that language (its base language or an override)".
Issue fork jsonapi_multilingual-3614382
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #4
lauriii