I'm trying to write a plugin that translate entries programmatically based on subsites that have different language setup.
Normally what happens is this: you setup multi-site, set each sub-site as having a different language and a different url (like @web/de, @web/sv etc), you set a field as translatable by language, then you edit an entry on each of those sub-sites. And the system knows to separate entries by siteId.
Now, I tried the same approach programmatically. I get all the entries for all the subsites like this:
$sites = Craft::$app->getSites()
->getAllSites();
/** @var Entry[] $entries */
$entries = [];
foreach ($sites as $site) {
/** @var Entry $entry */
$entries[$site->language] = Entry::find()
->id($id)
->siteId($site->id)
->one();
}
The I go and get all the fields for the English entry (in my setup is safe to assume that all the sub-sites respect the same field layout/structure). To test this, I dumped the values to compare the English version of the field, with the Swedish version. Values were different, which means I'm looking at the correct fields for the correct sub-entry.
//this is how we get the english fields
$fields = $entries['en']->getType()
->getFieldLayout()
->getFields();
//this is how we translate each field for each language
foreach ($fields as $field) {
if ($field->translationMethod === \craft\base\Field::TRANSLATION_METHOD_LANGUAGE) {
//get english value
$enValue = $entries['en']->getFieldValue($field->handle);
if (!empty($enValue)) {
//translate in all languages
$translations = $this->translate($enValue, array_keys($entries));
foreach ($entries as $lang => $entry) {
$fieldValue = $entry->getFieldValue($field->handle);
//only translate if the destination language/field is in English (not translated yet)
if (('en' !== $lang) && !empty($enValue) && ($enValue === $fieldValue)) {
if (!empty($translations[$lang])) {
//setFieldValue for each language
$entry->setFieldValue($field->handle, $translations[$lang]);
}
}
}
}
}
}
This is how I try to save the entries at the end of it all
//save all non-eng entries
$elements = new Elements();
foreach ($entries as $lang => $entry) {
if (('en' !== $lang) && !$elements->saveElement($entry)) {
echo json_encode($entry->getErrorSummary(true));
die();
}
}
The issue is that it saves the last translated language in all the sub-sites, for some reason, and I don't understand what I'm doing wrong.
$elements->saveElement($entry, true, false)does the same thing, by the way. – dustfeather Feb 11 '21 at 13:44enabledForSite)... – RitterKnight Feb 11 '21 at 18:33