Content Internationalization (i18n) beta is live 馃實

Hello,

I鈥檓 currently testing i18n plugin with Strapi and I have one question. I have some function like that below

Przechwytywanie

This piece of code create new entries only for my default locale. How I can improve it so that it also create entires for other locales ?

You need to include the locale key and set it to the shortcode, we have our docs PR pending for the dev docs that can give more context: https://github.com/strapi/documentation/pull/224

These will be released on Wednesday (dev docs and user docs), not the I18N feature which I believe is slated for Thursday.

1 Like

Hi everyone,

We have released the beta.3 version of I18N for testing, this will be the final beta release before the stable one. (Assuming no major issues come up).

Rough Change-log is:

  • Fixed an issue with default locale not being set / Switching default locale
  • Fix an issue with localization of media fields
  • The i18n plugin is now installed by default (not enabled, does not affect existing projects that will update)
  • Fix single type delete
  • Fix issue fetching single-type entries that have localization enabled
  • Fix single type updates (PUT)
  • Fix bulk delete on entries that aren鈥檛 in default locale
  • Fix sticky header and select the first locale for copy by default
  • Update Buffet.js to 3.3.5
  • Various dependency updates (merged from master branch)

For a more detailed changelog, please review the features/i18n branch on GitHub: Commits 路 strapi/strapi 路 GitHub

Creating a new project on this beta is the same as before:

npx create-strapi-app@beta test-project --quickstart --no-run (remove the --quickstart and --no-run if you want to test on other databases).

At this time, if you want to test upgrading existing applications there should be no migration steps (minus installing the i18n plugin) but we still do not recommend this version for production usage

If you update your existing project, you do so at your own risk, please do not post bug reports on GitHub until the stable version is released.


If you want to review both the User and Developer docs for I18N you can find them here (please don鈥檛 comment on them) and they will be released before the stable on Wednesday.

8 Likes

Awesome feature. Great work! Just tried it out and it works fine with most of my content types. But when I enable it for one specific content type, strapi actually crashes. How/where do you want me to report that issue?

[2021-04-20T14:59:04.305Z] [2021-04-20t14:59:04.304z] debug 鉀旓笍 Server wasn't able to start properly.
[2021-04-20T14:59:04.305Z] [2021-04-20t14:59:04.305z] error Error: Unknown type "updateRecipesInput". Did you mean "updateRecipeInput", "createRecipeInput", "deleteRecipeInput", "editRecipeInput", or "updateRoleInput"?
    at assertValidSDL (/Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/graphql/validation/validate.js:107:11)
    at Object.buildASTSchema (/Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/graphql/utilities/buildASTSchema.js:45:34)
    at Object.buildSchemaFromTypeDefinitions (/Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/graphql-tools/dist/generate/buildSchemaFromTypeDefinitions.js:25:28)
    at makeExecutableSchema (/Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/graphql-tools/dist/makeExecutableSchema.js:26:29)
    at Object.generateSchema (/Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/strapi-plugin-graphql/services/schema-generator.js:101:18)
    at Object.initialize (/Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/strapi-plugin-graphql/hooks/graphql/index.js:76:74)
    at /Users/vinzenzweber/Development/rootshealth/glucose-cms/node_modules/strapi/lib/hooks/index.js:37:28
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
1 Like

Can you give us a bit more information that content-type?

It seems to be an issue with the GraphQL plugin while it creates the schema. I tried to extract the part of my project that would make the app crash and summarised it here: https://github.com/vinzenzweber/strapi-i18n-debug

So after a little testing the one thing that makes all the difference is wether I create a content-type with Display name ending with an 鈥渟鈥. Using 鈥淩ecipe鈥 as Display name works fine, while 鈥淩ecipes鈥 would crash the app. Same for 鈥淟esson鈥 vs 鈥淟essons鈥 etc.

@vinzenzweber can you test this PR?

2 Likes

Awesome, that fixed my bug! Love how quick you guys handled this! :raised_hands:

I just installed the newest version, which works great for most of the things, but I stumbled upon some problems (I already mentioned some of them here, but maybe you overlooked it).

When querying with GraphQL, I can only specify the locale for a Content Type which has localization enabled, which makes sense in the first place, but has a major drawback: I can鈥檛 populate a relation with the needed locale. For example if I have a Content Type Hotel and a Content Type WelcomeMessage and the hotel has a 1-1 relation with the welcome message and my query looks like this:

query FindHotel($id: ID!) {
  hotels(where: { id: $id }) {
    id
    name
    welcomeMessage {
      title
      locale
    }
  }
}

How is it possible to retrieve a different locale for the welcomeMessage then the default one? As a workaround, I could just query the localizations field on welcomeMessage and filter the content on the client side, which would be less than ideal and not very scalable.

Also, it is not possible to specify the locale when querying a single instance of a collection type by ID (screenshot of the generated schema):

Proposed solution for the above problems:
Instead of always returning the default locale or adding a locale parameter to each and every query, you could simply use the Accept-Language header which every browser sends by default to determine the current content language. This would also work nicely with nested GQL queries.

In the meantime, is there any other possibility to make nested queries fully localized, e.g. by manipulating the context object or something?

It is still in progress and it seems not to be finished any soon as far as I can understand. Is there any workaround documented which we can use as a base?

Thanks

Hi @sam-pires @Jab : could you confirm you are looking into the possibility to derive localised relationships when clicking 鈥淔ill in from another locale鈥 ? My CMS manager is getting crazy :smiley:

Are you talking about this? Unable to disable localization for relationship fields. 路 Issue #10322 路 strapi/strapi 路 GitHub

Hello @justus
Thanks for the feedback :+1: It鈥檚 made on purpose.
We took that decision to stay coherent with the current behavior on RBAC when you add a new field or CT: by default the permissions are not checked. So that motivated us to apply the same behavior for i18n.
I agree that it鈥檚 might not be the fastest way to get roles ready, but we consider that it is safer to hide newly created content (CT, field, I18n activation) by default and then to allow access to it, than the other way around :slight_smile:

Hello @wlixw87

Here is some info you probably wait for :slight_smile:
(cc @glo and @LuisAlaguna)

We don鈥檛 take the relations when using the 鈥渇ill in from鈥 feature because of a technical limitation. In some cases, depending on the relationship type between 2 entities, and depending on the activation of i18n on only one or both Collection-types (CT), recreating the same relation in several locales could break it.
e.g. In the case where i18n is activated on a CT but not on the other one, and where the relationship type is one-to-one, then if we just recreate the same relation in a new locale we break it on the other side of the relation (the other CT) without knowing it.

We thought about limiting the use of some relationship types in the CTB (content type builder) directly to avoid ending up in this kind of situation. But i18n being a plugin we were too limited and it would have been too complex to implement.

To avoid having the same issue when adding a relation manually from the Edit View, we now apply a filter on the relations you can add, depending on whether i18n is activated on one or both CTs you鈥檒l only be able to create a relation to an entity with the same locale.

That鈥檚 also why localization is forced on Relational fields.

The good news is that the new db model in the v4 will solve this technical limitation :slight_smile:
I18n helped us identify several limitations in our model and the v4 is here to make Strapi more robust and offer more flexibility.

Feel free if you have any questions.


By the way, talking about relations, we are currently doing some researches on this topic and it would be awesome if you could share some info about your Strapi projects, your use cases, and needs regarding relations in this forum post. It鈥檚 gonna help us make the most of the new model in the v4 :wink:

Hi guys,

I鈥檓 quite new at the Strapi and I have a problem how fetch localized data using GraphQL. Here I found the information how to query data using REST API, but I cannot find what I鈥檓 doing wrong using GraphQL.

This is a JSON structure of response for the default lang (de-CH):

{
鈥渋d鈥: 5,
鈥渓ocale鈥: 鈥渄e-CH鈥,
鈥減ublished_at鈥: 鈥2021-05-11T12:04:23.616Z鈥,
鈥渃reated_at鈥: 鈥2021-05-11T11:56:10.146Z鈥,
鈥渦pdated_at鈥: 鈥2021-05-11T16:44:59.947Z鈥,
鈥渕ainTitle鈥: null,
鈥渃ontent鈥: null,
鈥渙penDialogButtonLabel鈥: "Ich abonniere! ",
鈥渟eo鈥: {
鈥渋d鈥: 40,
鈥渕etaTitle鈥: 鈥淜ommt bald鈥,
鈥渕etaDescription鈥: 鈥淜ommt bald desc鈥,
鈥渕etaKeywords鈥: 鈥溾,
鈥減reventIndexing鈥: false,
鈥渃annonicalLink鈥: null,
鈥渟haredImage鈥: null
},
鈥渄ialog鈥: {
鈥渋d鈥: 5,
鈥淭itle鈥: null,
鈥淥fferSummary鈥: null,
鈥淐onfiramtionReminder鈥: null,
鈥淩epeatConfirmationReminder鈥: null,
鈥淐lause鈥: null,
鈥渢itle鈥: null,
鈥渃onfiramtionReminder鈥: null,
鈥渞epeatConfirmationReminder鈥: null,
鈥渃lause鈥: null,
鈥渙fferSummary鈥: null,
鈥渇orm鈥: null
},
鈥渓ogo鈥: null,
鈥渓ocalizations鈥: [
{
鈥渋d鈥: 3,
鈥渓ocale鈥: 鈥減l-PL鈥,
鈥減ublished_at鈥: 鈥2021-05-12T17:14:19.643Z鈥
},
{
鈥渋d鈥: 6,
鈥渓ocale鈥: 鈥渆n-GB鈥,
鈥減ublished_at鈥: 鈥2021-05-12T17:16:01.446Z鈥
}
]
}

When I test the query without any filters like this:

query MyQuery {
strapiComingSoon {
openDialogButtonLabel
locale
}
}

I get the correct response:

{
鈥渄ata鈥: {
鈥渟trapiComingSoon鈥: {
鈥渙penDialogButtonLabel鈥: "Ich abonniere! ",
鈥渓ocale鈥: 鈥渄e-CH鈥
}
},
鈥渆xtensions鈥: {
鈥渆nableRefresh鈥: 鈥1鈥
}
}

This is a JSON structure of response for PL version (url/page?_locale=pl=PL)

{
鈥渋d鈥: 3,
鈥渓ocale鈥: 鈥減l-PL鈥,
鈥減ublished_at鈥: 鈥2021-05-12T17:14:19.643Z鈥,
鈥渃reated_at鈥: 鈥2021-05-07T12:55:24.182Z鈥,
鈥渦pdated_at鈥: 鈥2021-05-12T17:14:19.859Z鈥,
鈥渕ainTitle鈥: 鈥淪trona w budowie鈥,
鈥渃ontent鈥: null,
鈥渙penDialogButtonLabel鈥: 鈥淶apisuj臋 si臋!鈥,
鈥渟eo鈥: {
鈥渋d鈥: 41,
鈥渕etaTitle鈥: 鈥淪trona w budowie鈥,
鈥渕etaDescription鈥: 鈥淥pis strony w budowie鈥,
鈥渕etaKeywords鈥: null,
鈥減reventIndexing鈥: false,
鈥渃annonicalLink鈥: null,
鈥渟haredImage鈥: null
},
鈥渄ialog鈥: {
鈥渋d鈥: 6,
鈥淭itle鈥: null,
鈥淥fferSummary鈥: null,
鈥淐onfiramtionReminder鈥: null,
鈥淩epeatConfirmationReminder鈥: null,
鈥淐lause鈥: null,
鈥渢itle鈥: null,
鈥渃onfiramtionReminder鈥: null,
鈥渞epeatConfirmationReminder鈥: null,
鈥渃lause鈥: null,
鈥渙fferSummary鈥: null,
鈥渇orm鈥: null
},
鈥渓ogo鈥: null,
鈥渓ocalizations鈥: [
{
鈥渋d鈥: 5,
鈥渓ocale鈥: 鈥渄e-CH鈥,
鈥減ublished_at鈥: 鈥2021-05-11T12:04:23.616Z鈥
},
{
鈥渋d鈥: 6,
鈥渓ocale鈥: 鈥渆n-GB鈥,
鈥減ublished_at鈥: 鈥2021-05-12T17:16:01.446Z鈥
}
]
}

And when I trying query using GraphQL like this (with filter):

query MyQuery {
strapiComingSoon(locale: {eq: 鈥減l-PL鈥潁) {
openDialogButtonLabel
locale
}
}

In response I get:

{
鈥渄ata鈥: {
鈥渟trapiComingSoon鈥: null
},
鈥渆xtensions鈥: {
鈥渆nableRefresh鈥: 鈥1鈥
}
}

What should I do to fetch Polish version of the Single Type? Thanks in advance for every help

Is it also working for images or text only?

Right now it works for every field by default: it creates a new object, somehow they are linked, but the localization object, let鈥檚 say a page, it a new page; hence, you can fulfill it as you want: same image but with different languange, or same video but in another language, different relations, etc. The last one is annoying because, in our case, we don鈥檛 want to localize the relationship fields, and right now it is imposible to unlocalize them.

1 Like

Thank you Luis, and before internationalization i18n, how did you implemented multilanguage and images? (Maybe you did, just an assumption)

I never had the need to localize images, but for localizing text I used to create a field with the same name but localization short label suffixed.