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?
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
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.
@wintercounter For Strapi v4, let’s say we have three locales, so:
We have to create two entries with different locale independently.
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.
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
}
});
}
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()}`
}
});
}
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:
I’ve just spent a very decent amount of time scratching my head over this for Strapi v4! The solution I came up with is as follows:
Add the main entity to the db - store the id returned from this query
Add each localized entity to the db - store the ids of each localized entity
Create the relationship between the main entity and the localized entities
Create the reverse relationships between each localized entity and the main entity
const uid = "api::entity.entity";
const { localizations, ...entityWithoutLocalizations } = entity;
try {
// Create main entity without localizations
const addedEntity = await strapi.entityService.create(uid, {
data: entityWithoutLocalizations,
});
// Add the id of the inserted main entity to the entity without localizations - we need this later when we set up the reverse relationship
entityWithoutLocalizations.id = addedEntity.id;
for (let i = 0; i < localizations.length; i++) {
// Create the localization object in the db
const addedLocalization = await strapi.entityService.create(uid, {
data: localizations[i],
});
// Add the id of the localization that was just added to the db to the original data
localizations[i].id = addedLocalization.id;
// Create the relationship between the localization and the main entity
await strapi.query(uid).update({
where: { id: localizations[i].id },
data: { localizations: [entityWithoutLocalizations] },
});
}
// Finally, create the relationship between the main entity and all the localizations
await strapi
.query(uid)
.update({ where: { id: addedEntity.id }, data: { localizations } });
} catch (e) {
console.log(e);
}
Fetching the data from external api and I following the florianmrz . I try someting simillar to i can create and update the products by i can’t sincronize the localizations. Someone knows why?
f
The code provided by @florianmrz works great, but I encountered an issue when I wanted to update an already existing entry and add a localization to it. Specifically, the localizations field would just stay empty.
I eventually figured out that using the Query Engine API instead resolved the problem for me. Here’s the modified code snippet using the Query Engine API to update an existing entry:
// (This exact logic does not work with the Entity Service API)
const updatedMainEntry = await strapi.query('api::item.item').update({
where: { id },
data: {
localizations: [localizedEntry.id],
},
populate: ['localizations'],
});
I hope this helps anyone who might come across this post!
I’m using also 4.24.2, but the solution is not really working for me - only the main language is showing all localised versions in the dashboard, but when switching to the other locales, they are shown like standalone entries - so no connection to the other locales… @Bishop can you confirm me, that this works fine for you?