🌍 Internationalization (i18n)
The Internationalization (i18n) feature allows Strapi users to create, manage and distribute localized content in different languages, called "locales". For more information about the concept of internationalization, please refer to the W3C definition.
The i18n feature:
- allows admin panel users to create several localized versions of their content (see User Guide)
- allows developers to build localized projects by fetching and consuming the right content depending on the country/language of the audience.
The i18n feature does not automatically translate the users' content nor adapt the admin interface to languages specificities (e.g., displaying the admin panel in Right To Left format).
- In Strapi 5, i18n is no longer a plugin and is installed by default. You can still decide to enable/disable it on a content-type, and enable/disable it at the field-level in an i18n-enabled content-type.
- Since i18n is part of the Strapi core, this might affect how some parameters are sent to the Content Manager (see the related breaking change entry).
Configuration of the default locale
A STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE
environment variable can be configured to set the default locale for your environment. The value used for this variable should be an ISO country code (see full list of available locales).
This is useful when a Strapi application is deployed in production, with the i18n feature installed and enabled for your content types the first time. On a fresh i18n installation, en
is set as default locale. If the database does not contain any locale, and no STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE
is set for the environment, all documents of content types that have localization enabled will be automatically migrated to the en
locale.
Use locale
with the REST API
The Internationalization (i18n) feature adds new abilities to the REST API.
To work with API content for a locale, please ensure the locale has been already added to Strapi in the admin panel.
The locale
API parameter can be used to work documents only for a specified locale. locale
takes a locale code as a value (see full list of available locales).
If the locale
parameter is not defined, it will be set to the default locale. en
is the default locale when a new Strapi project is created, but another locale can be set as the default locale in the admin panel.
For instance, by default, a GET request to /api/restaurants
will return the same response as a request to /api/restaurants?locale=en
.
The following table lists the new possible use cases added by i18n to the REST API and gives syntax examples (you can click on requests to jump to the corresponding section with more details):
- For collection types
- For single types
Use case | Syntax example and link for more information |
---|---|
Get all documents in a specific locale | GET /api/restaurants?locale=fr |
Get a specific locale version for a document | GET /api/restaurants/abcdefghijklmno456?locale=fr |
Create a new document for the default locale | POST /api/restaurants + pass attributes in the request body |
Create a new document for a specific locale | POST /api/restaurants + pass attributes and locale in the request body |
Create a new, or update an existing, locale version for an existing document | PUT /api/restaurants/abcdefghijklmno456?locale=fr + pass attributes in the request body |
Delete a specific locale version of a document | DELETE /api/restaurants/abcdefghijklmno456?locale=fr |
Use case | Syntax example and link for more information |
---|---|
Get a specific locale version for a document | GET /api/homepage?locale=fr |
Create a new, or update an existing, locale version for an existing document | PUT /api/homepage?locale=fr + pass attributes in the request body |
Delete a specific locale version of a document | DELETE /api/homepage?locale=fr |
Get all documents in a specific locale
GET http://localhost:1337/api/restaurants?locale=fr
{
"data": [
{
"id": 5,
"documentId": "h90lgohlzfpjf3bvan72mzll",
"Title": "Meilleures pizzas",
"Body": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"text": "On déguste les meilleures pizzas de la ville à la Pizzeria Arrivederci."
}
]
}
],
"createdAt": "2024-03-06T22:08:59.643Z",
"updatedAt": "2024-03-06T22:10:21.127Z",
"publishedAt": "2024-03-06T22:10:21.130Z",
"locale": "fr"
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}
Get a document in a specific locale
To get a specific document in a given locale, add the locale
parameter to the query:
Use case | Syntax format and link for more information |
---|---|
In a collection type | GET /api/content-type-plural-name/document-id?locale=locale-code |
In a single type | GET /api/content-type-singular-name?locale=locale-code |
Collection types
To get a specific document in a collection type in a given locale, add the locale
parameter to the query, after the documentId
:
GET /api/restaurants/lr5wju2og49bf820kj9kz8c3?locale=fr
{
"data": [
{
"id": 22,
"documentId": "lr5wju2og49bf820kj9kz8c3",
"Name": "Biscotte Restaurant",
"Description": [
{
"type": "paragraph",
"children": [
{
"type": "text",
"text": "Bienvenue au restaurant Biscotte! Le Restaurant Biscotte propose une cuisine à base de produits frais et de qualité, souvent locaux, biologiques lorsque cela est possible, et toujours produits par des producteurs passionnés."
}
]
}
],
// …
"locale": "fr"
},
// …
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 3
}
}
}
Single types
To get a specific single type document in a given locale, add the locale
parameter to the query, after the single type name:
GET /api/homepage?locale=fr
{
"data": {
"id": 10,
"documentId": "ukbpbnu8kbutpn98rsanyi50",
"Title": "Page d'accueil",
"Body": null,
"createdAt": "2024-03-07T13:28:26.349Z",
"updatedAt": "2024-03-07T13:28:26.349Z",
"publishedAt": "2024-03-07T13:28:26.353Z",
"locale": "fr"
},
"meta": {}
}
Create a new localized document for a collection type
To create a localized document from scratch, send a POST request to the Content API. Depending on whether you want to create it for the default locale or for another locale, you might need to pass the locale
parameter in the request's body
Use case | Syntax format and link for more information |
---|---|
Create for the default locale | POST /api/content-type-plural-name |
Create for a specific locale | POST /api/content-type-plural-name + pass locale in request body |
For the default locale
If no locale has been passed in the request body, the document is created using the default locale for the application:
POST http://localhost:1337/api/restaurants
{
"data": {
"Name": "Oplato",
}
}
{
"data": {
"id": 13,
"documentId": "jae8klabhuucbkgfe2xxc5dj",
"Name": "Oplato",
"Description": null,
"createdAt": "2024-03-06T22:19:54.646Z",
"updatedAt": "2024-03-06T22:19:54.646Z",
"publishedAt": "2024-03-06T22:19:54.649Z",
"locale": "en"
},
"meta": {}
}
For a specific locale
To create a localized entry for a locale different from the default one, add the locale
attribute to the body of the POST request:
POST http://localhost:1337/api/restaurants
{
"data": {
"Name": "She's Cake",
"locale": "fr"
}
}
{
"data": {
"id": 15,
"documentId": "ldcmn698iams5nuaehj69j5o",
"Name": "She's Cake",
"Description": null,
"createdAt": "2024-03-06T22:21:18.373Z",
"updatedAt": "2024-03-06T22:21:18.373Z",
"publishedAt": "2024-03-06T22:21:18.378Z",
"locale": "en"
},
"meta": {}
}
Create a new, or update an existing, locale version for an existing document
With PUT
requests sent to an existing document, you can:
- create another locale version of the document,
- or update an existing locale version of the document.
Send the PUT
request to the appropriate URL, adding the locale=your-locale-code
parameter to the query URL and passing attributes in a data
object in the request's body:
Use case | Syntax format and link for more information |
---|---|
In a collection type | PUT /api/content-type-plural-name/document-id?locale=locale-code |
In a single type | PUT /api/content-type-singular-name?locale=locale-code |
When creating a localization for existing localized entries, the body of the request can only accept localized fields.
The Content-Type should have the createLocalization
permission enabled, otherwise the request will return a 403: Forbidden
status.
It is not possible to change the locale of an existing localized entry. When updating a localized entry, if you set a locale
attribute in the request body it will be ignored.
In a collection type
To create a new locale for an existing document in a collection type, add the locale
parameter to the query, after the documentId
, and pass data to the request's body:
PUT http://localhost:1337/api/restaurants/lr5wju2og49bf820kj9kz8c3?locale=fr
{
data: {
"Name": "She's Cake in French",
}
}
{
"data": {
"id": 19,
"documentId": "lr5wju2og49bf820kj9kz8c3",
"Name": "She's Cake in French",
"Description": null,
"createdAt": "2024-03-07T12:13:09.551Z",
"updatedAt": "2024-03-07T12:13:09.551Z",
"publishedAt": "2024-03-07T12:13:09.554Z",
"locale": "fr"
},
"meta": {}
}
In a single type
To create a new locale for an existing single type document, add the locale
parameter to the query, after the single type name, and pass data to the request's body:
PUT http://localhost:1337/api/homepage?locale=fr
{
"data": {
"Title": "Page d'accueil"
}
}
{
"data": {
"id": 10,
"documentId": "ukbpbnu8kbutpn98rsanyi50",
"Title": "Page d'accueil",
"Body": null,
"createdAt": "2024-03-07T13:28:26.349Z",
"updatedAt": "2024-03-07T13:28:26.349Z",
"publishedAt": "2024-03-07T13:28:26.353Z",
"locale": "fr"
},
"meta": {}
}
Delete a locale version of a document
To delete a locale version of a document, send a DELETE
request with the appropriate locale
parameter.
DELETE
requests only send a 204 HTTP status code on success and do not return any data in the response body.
In a collection type
To delete only a specific locale version of a document in a collection type, add the locale
parameter to the query after the documentId
:
DELETE /api/restaurants/abcdefghijklmno456?locale=fr
In a single type
To delete only a specific locale version of a single type document, add the locale
parameter to the query after the single type name:
DELETE /api/homepage?locale=fr
Use locale
with the GraphQL API
The i18n feature adds new features to the GraphQL API:
- The
locale
field is added to the GraphQL schema. - GraphQL can be used:
Fetch all documents in a specific locale
To fetch all documents for a specific locale, pass the locale
argument to the query:
query {
restaurants(locale: "fr") {
documentId
name
locale
}
}
{
"data": {
"restaurants": [
{
"documentId": "a1b2c3d4e5d6f7g8h9i0jkl",
"name": "Restaurant Biscotte",
"locale": "fr"
},
{
"documentId": "m9n8o7p6q5r4s3t2u1v0wxyz",
"name": "Pizzeria Arrivederci",
"locale": "fr"
},
]
}
}
Fetch a document in a specific locale
To fetch a documents for a specific locale, pass the documentId
and the locale
arguments to the query:
query Restaurant($documentId: ID!, $locale: I18NLocaleCode) {
restaurant(documentId: "a1b2c3d4e5d6f7g8h9i0jkl", locale: "fr") {
documentId
name
description
locale
}
}
{
"data": {
"restaurant": {
"documentId": "lviw819d5htwvga8s3kovdij",
"name": "Restaurant Biscotte",
"description": "Bienvenue au restaurant Biscotte!",
"locale": "fr"
}
}
}
Create a new localized document
The locale
field can be passed to create a localized document for a specific locale (for more information about mutations with GraphQL, see the GraphQL API documentation).
mutation CreateRestaurant($data: RestaurantInput!, $locale: I18NLocaleCode) {
createRestaurant(
data: {
name: "Brasserie Bonjour",
description: "Description in French goes here"
},
locale: "fr"
) {
documentId
name
description
locale
}
Update a document for a specific locale
A locale
argument can be passed in the mutation to update a document for a given locale (for more information about mutations with GraphQL, see the GraphQL API documentation).
mutation UpdateRestaurant($documentId: ID!, $data: RestaurantInput!, $locale: I18NLocaleCode) {
updateRestaurant(
documentId: "a1b2c3d4e5d6f7g8h9i0jkl"
data: {
description: "New description in French"
},
locale: "fr"
) {
documentId
name
description
locale
}
Delete a locale for a document
Pass the locale
argument in the mutation to delete a specific localization for a document :
mutation DeleteRestaurant($documentId: ID!, $locale: I18NLocaleCode) {
deleteRestaurant(documentId: "xzmzdo4k0z73t9i68a7yx2kk", locale: "fr") {
documentId
}
}