How to create localized entries from code?

System Information
  • Strapi Version:
  • Operating System:
  • Database:
  • Node Version:
  • NPM Version:
  • Yarn Version:

Hello! Is there a way to create localized entries from code? I can’t find any documentation on the subject. All that is listed is the Localization API, which works well for creating localized versions of entries, but can they be created directly from code?

Something like:

await strapi.services.page.create({
  Title: "Test fi",
  locale: "fi",
  localizations: [
    {
      Title: "Test en",
      locale: "en",
    },
  ],
});

Regards,
Tuomas

Hi,

I’m currently using this in my own take of the strapi-plugin-import-content plugin (GitHub - kiddicolour/strapi-plugin-import-content)

What I ended up with is a 2 step process:

  1. Creat the localized records, using the id from the record containing the default language values
    see line 54 of the import-content service

  2. Update all the records with the localizations array including the id
    see line 173 of the import-content service

This makes sure all relations are set and the admin displays the translations correctly linked.

Hope this helps!

Kind regards,

Keep in mind that the above plugin does more than just importing localizations and quite some abstractions are in place. The key takeaway is (as far as I reverse engineered all this): the localizations array can only contain the id, locale (and published_at column if draftAndPublish is enabled). I could be wrong though, but this approach works for me :wink:

Thanks for the explanation!

I checked your plugin, trying to do the same but it’s simply not working for me.

I created 2 separate entries, now trying to link together. ID 293367 is en locale, 316045 is fr . On the admin panel they appear fine when checking with different locales.

 await strapi.services.keywords.update(
    {
        id: 293367
    },
    {
        localizations: [{ id: 316045, locale: 'fr' }]
    }
)

The result I get after the update:

{
  id: 293367,
  Word: 'car',
  created_at: 2021-09-22T09:28:00.000Z,
  updated_at: 2021-10-14T21:02:52.000Z,
  created_by: null,
  updated_by: null,
  locale: 'en',
  localizations: []
}

Any ideas?

@wintercounter For Strapi v4, let’s say we have three locales, so:

  1. We have to create two entries with different locale independently.
  2. Create (not update any or root!) the third entry with different locale by setting another two localized entries as ‘localizations’ - all three entries will be synchronized.
    Check repo …/packages/plugins/i18n/server/services/entity-service-decorator.js - decorator create vs. update methods.

Hi!.

As @wintercounter says, It’s not working on strapi v4.

I created an entity as a spanish translation of an existent english entity, and setted its localizations with the id of the existent one.

On the admin panel, the new translation has a relationship with the existent entity:

But the existent entity ignores the new translation:

The automatic syncing mentioned by @ShiS seems not working. Maybe I’m doing something wrong.

This is my code:

async function save(service, entityObj, entityId, availableLocales, locale) {
  entityObj['locale'] = locale;

  // gets the existent entity
  const relatedTranslation = await localizationRepository.getLocalization(
    service, availableLocales, entityId
  );

  // set the existent entity as a translation of the new one
  if (relatedTranslation !== null) {
    entityObj['localizations'] = relatedTranslation.id;
  }

  // creates the new entity
  const translation = await service.create({ data: entityObj });

  // set the new entity as a existent entity translation
  await updateRelatedTranslationLocations(
    service, locale, translation, relatedTranslation
  );
}

async function updateRelatedTranslationLocations(service, locale, translation, relatedTranslation) {
  const localization = {
    id: translation.id,
    locale: locale
  };

  const relatedTranslationLocalizations = relatedTranslation.localizations.concat([localization]);

  // try to sync the translations, but seems to do nothing
  await service.update(relatedTranslation.id, {
    data: {
      localizations: relatedTranslationLocalizations
    }
  });
}

Any help will be appreciated, thanks!.

As a workaround, I could store and link a new translation with its original one with the following request, which is made from the admin panel when you create a new translation:

async function save(entityName, translation, related) {
    await axios({
        method: 'POST',
        url: `/content-manager/collection-types/api::${entityName}.${entityName}`,
        params: {
            'plugins[i18n][locale]': translation.locale, // new entity locale
            'plugins[i18n][relatedEntityId]': related // original related entity id to link with the new one
        },
        data: translation, // new entity data
        headers: {
            Authorization: `Bearer ${auth.getToken()}`
        }
    });
}

Hope it could be useful for somebody.

I used the same controller that handles the normal localization request with URL (/api/:entity/:id/localizations) to create my localization from code. You can access it with the strapi.controller function like this:

        await strapi.controller(`api::${entity}.${entity}`).createLocalization(ctx)

This is how I added the data for new localization and :id from URL, which is the entry in main locale:

        ctx.params.id = mainLocale.id;
        ctx.request.body = newEntity;

newEntity is just an object with translated (or not) data, but make sure to add ‘locale’ entry to it before creating the localization.