Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for translatable foreign keys on inline models (MultipleChooserPanel) #710

Open
alexalligator opened this issue Aug 15, 2023 · 3 comments

Comments

@alexalligator
Copy link

Creating issue after posting to slack #multi-language and discussing with @zerolab

I have a translatable snippet which I add to a page model via an inline model:

@register_snippet
class Material(TranslatableMixin, models.Model):
    name = CharField(...)

class ProductPageMaterial(Orderable):

    page = ParentalKey(
        "app.ProductPage", on_delete=models.CASCADE, related_name="materials"
    )
    material = models.ForeignKey(
        "app.Material", on_delete=models.CASCADE, related_name="+"
    )

    panels = [
        FieldPanel("material"),
    ]

class ProductPage(Page):
    content_panels = Page.content_panels + [
        MultipleChooserPanel(
            "materials", chooser_field_name="material"
        ),
    ]

What happens:

  1. I publish a new default language (norwegian) ProductPage choosing a couple of materials
  2. I translate to english using wagtail-localize. The materials field is hidden from the UI (auto-sync behaviour)
  3. I inspect the new page's materials (instances of ProductPageMaterial) via shell

I see that a new ProductPageMaterial has been created by wagtail/wagtail-localize. It's page foreign key field is pointing the new english version of the page as expected. The material foreign key field, however, is still pointing to a norweigan material.
I would expect to see the local (english) material in the same way I see the local page.

I have made this temporary workaround but don't image it will be relevant for any long term solution:

class InlineModelTranslationHelper:
    page: Page

    target_field_name: str

    def save(self, *args, **kwargs) -> None:
        # Force the target field locale to match the locale of the page.
        # This is because wagtail localize seems to translate the page foreign key
        # but leaves the other foreign key in the original language.
        target_obj: TranslatableMixin = getattr(self, self.target_field_name)
        if not self.page.locale == target_obj.locale:
            logger.info(
                f"Page {self.target_field_name} '{target_obj}' has locale "
                f"{target_obj.locale} but page has locale {self.page.locale}"
            )

            if local_obj := target_obj.get_translation_or_none(locale=self.page.locale):
                logger.info(f"... using an existing translation of {target_obj}.")
            else:
                logger.info(
                    f"... no existing translation for {target_obj} "
                    f"with locale {self.page.locale} so creating a new one."
                )
                # This will crash if the targer object is a page whose parent has not yet been translated.
                local_obj = target_obj.copy_for_translation(locale=self.page.locale)
                local_obj.save()
            setattr(self, self.target_field_name, local_obj)
        return super().save(*args, **kwargs)
@underdoeg
Copy link

I think if you also make ProductPageMaterial translatable it should show up?

@enzedonline
Copy link
Contributor

The key doesn't get translated and will always point to the key in the locale the page was created in. You should be able to get the translated child object by localising it.

page.localized.material.localized

@alexalligator
Copy link
Author

Thanks for your comments, I'll look into them and report back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants