Drupal Core's JSON:API module serves the language-negotiated translation of an entity and gives you no way to read, create, update, or delete one specific translation on its own. JSON:API Multilingual adds that: per-translation GET, POST, PATCH, and DELETE over the existing JSON:API resource URLs, with a stable HTTP contract that does not depend on Drupal's URL language negotiation.

Selecting a translation

The target language is chosen per request, never by URL path prefix. Use the langCode query string parameter. It is the recommended mechanism for both reads and writes: explicit, cacheable, and accepted on every operation.

?langCode=fr

On reads, add includeFallback=1 to resolve the request through the site's language fallback chain instead of failing strictly (fallback-policy modules such as Language Hierarchy apply automatically; the entity's default translation is the terminal candidate, so an existing entity always returns 200):

?langCode=fr&includeFallback=1

Usage

Read a specific translation (404 if it does not exist):

GET /jsonapi/node/article/{uuid}?langCode=fr

Read with server-side fallback (the language actually served is reported in the Content-Language response header and the langcode attribute):

GET /jsonapi/node/article/{uuid}?langCode=fr&includeFallback=1

Create a new translation of an existing entity (409 if it already exists; only translatable fields may be sent):

POST /jsonapi/node/article/{uuid}?langCode=fr
Content-Type: application/vnd.api+json

{"data":{"type":"node--article","id":"{uuid}","attributes":{"langcode":"fr","title":"..."}}}

Update a single translation (only that translation changes; 404 if it does not exist, use POST to create):

PATCH /jsonapi/node/article/{uuid}?langCode=fr

Delete a single translation (400 for the default translation; DELETE without a language deletes the whole entity):

DELETE /jsonapi/node/article/{uuid}?langCode=fr

Writes (POST, PATCH, DELETE) require JSON:API to be in read-write mode (jsonapi.settings:read_only = false), exactly as for core JSON:API. In read-only mode, writes return 405 Method Not Allowed; reads keep working.

Integrates with

  • JSON:API Menu Items (1.2.8+): its rendered menu-tree endpoint honors the same langCode / includeFallback selection, applied per menu link.
  • Next.js (next_jsonapi) and Decoupled Router: both extend the same JSON:API controller, and this module composes with them rather than clobbering their behavior.
Much of the code for this module has been created through AI assistance or generation, and has been spec'ed, reviewed, tested, and updated by real people.

Project information

Releases