Internationalization (i18n) available in Strapi v3.6 🌍

Hello everybody!

This day has come, Internationalization is released in the new 3.6 version!
It is available for free, without limitations.

With this feature, you can:

  • Create multiple versions (locales) of your content
  • Choose what content types and fields are localized and what are not
  • Copy & paste content from one locale to another
  • Set up granular permission rights for each locale

To try it out, update your Strapi version to 3.6. Have a look at the documentation and user guide for more details.

Let us know what you think about the feature! :heart:

6 Likes

Congrats!

Should I post questions and issues regarding the i18n feature from now on here?

I created a new post yesterday on the beta forum topic: Content Internationalization (i18n) beta is live 🌍 - #58 by scriptify

1 Like

Thank you all for the great team on i18n support.

Can you please clarify how Relations can be excluded from localization? I have a blog where posts will belong to the same categories, no matter the locale. I don’t want to duplicate all the relationships for each individual language. I see there is no option to disable localization in the latest strapi version or the docs Fields for Content Types - Strapi User Guide

Also, regarding alt texts for media files, is there any plan on adding localization to the field?

Much appreciated.

1 Like

I have also realised that even though a slug is acting as UUID it will require a unique translation, which doesn’t really make sense. Can you please clarify how this would be supposed to work (eg: slugs for blog posts)

Thanks

1 Like

We released our i18n plugin documentation during the StrapiConf :slight_smile:

We had some constraints on relations due to various types (ex: oneToMany, manyToOne, oneToOne, and manyToMany) but we will be expanding i18n support for these in the v4. Originally the i18n plugin was scheduled to be developed on the v4 but we decided to build most of it in the v3 instead however we had to cut certain features due to the framework limitations in the Strapi v3 version.

This is one of the features I mentioned above that was cut for the Strapi v3 version due to framework limitations. We will have more information as we continue the design on the Strapi v4.

Slugs (UIDs) are a unique field type generated either on their own or by referencing a field. Due to the nature of being unique we apply database constraints in the database layer. Since we store all localized content in a single database table you cannot have the same value for multiple entries on this field. UIDs could also be unique globally throughout the entire Strapi application thus in our current v3 framework it is not possible to have multiple localized version that share the same UID. This is something we are looking at changing in the Strapi v4 with our new database layer. More details will come on that in our v4 RFC that should be released later this quarter.

I’ve already read the documentation, but it doesn’t address any of the issues I mentioned in my post.

I’d urgently need some help regarding those issues, they are crucial for my project.

Relations are always localized and you cannot share a oneToOne relation with multiple locales. Each localized entry is a new entry in the database and in a oneToOne relation you cannot attach one-side to multiple entries. All locales of a content-type share the same database table but they are not the same entry. Localized entries basically have a hidden relationship between them but they are each independent of each other.

So the two options are either:

  • Change the relationship type to something that would allow for the welcome message to be attached to multiple hotel entries (localized entities)
  • Duplicate the welcome message and attach it to the localized entry.

Thanks for the answer.
From an API perspective, this is less than ideal, as a developer I’d expect that setting a top level locale variable would affect all the content in the query, like it’s for most other Headless CMS (e.g. when using with Next.js, everything else is a huge pain). If you have e.g. a look at DatoCMS, the whole GQL query gets localized, which, IMO, should be the default behavior when using such an API. Also, the Accept-Language header should be taken into account for those queries. As the GQL resolvers aren’t directly correlated with the DB structure underneath, this shouldn’t be too hard to implement. If that’s more suitable, I could open an issue in GH and try to prepare a PR.

Before a PR it might be better to discuss it on an RFC first: GitHub - strapi/rfcs: RFCs for Strapi future changes

(Also this will change in the v4, we originally wanted to do it in the v4 but we are completely changing the the storage system then, you’ll have more details on that once we release the v4 RFCs)

Ok, but this isn’t something which is planned for the near future, correct?
So I’ll need to query each collection separately, which isn’t a huge problem but a bit cumbersome.
Thanks for your time.

As a workaround i think it’s possible to wrap the relation object into component and disable the localization for the component field. It will nest the data though.

@DMehaffy is it 100% sure that in v4 the full relation internationalization support will be available?

Not 100% sure, v4 is still going through major design before we even start implementing anything.

Thank you for your great work on the i18n plugin really nice work ! just a little suggestion maybe some locales flags would be nice to implement ?

I was really looking forward to the i18n feature. However I am not fully satisfied. I dont like the concept of having one instance per locale. And it is strange not to be able to use a UUID for all instances.

I used to work with Directus which was a better concept in my perspective:
They use translations which looks like that:

{
      "nodes": [
        {
          "price": "10",
          "translations": [
            {
              "language": "en",
              "description": "Lorem ipsum dolor sit amet, consetetur sadipscing"
            },
            {
              "language": "de",
              "description": "Lorem ipsum dolor sit amet, consetetur sadipscing"
            }
          ]
        },
        {
          "price": "20",
          "translations": [
            {
              "language": "en",
              "description": "Lorem ipsum dolor sit amet, consetetur sadipscing",
            },
            {
              "language": "de",
              "description": "Lorem ipsum dolor sit amet, consetetur sadipscing"
            }
          ]
        },
}