allcaps / wagtail-translate

MIT License
3 stars 2 forks source link

Make language and translator configuration flexible #7

Open saevarom opened 2 weeks ago

saevarom commented 2 weeks ago

A proposal:

I am wondering if the configuration and translators could be configured so that for the most basic needs developers could set up default translators for specific language pairings. It's possibly a niche situation but Icelandic for example does not have great support in most machine translation services, and the specific local Icelandic ones have no support for translation between languages other than Icelandic to/from some other language.

Also, I think it would be valuable for developers to have a few default translation actions available to import and connect. For example, it would be nice to have an action that auto-translates and publishes, and then another one that would auto-translate and save as a draft, etc.

So we would need to have some configuration options for developers to set a default translator class and a default action. Then, for more specific needs, there could be a more detailed mapping between languages to specify a translator class and even the action to perform.

For the developer, this could look like something along the lines of:

WAGTAIL_TRANSLATE_DEFAULT_CLASS = "myapp.translators.DeepLTranslator" # None by default
WAGTAIL_TRANSLATE_DEFAULT_ACTION = "wagtail_translate.actions.translate_and_draft" # this could be the default
WAGTAIL_TRANSLATE_MAPPINGS = [ # default empty
    {
        "class": "myapp.translators.IcelandicTranslator",
        "pairs": ["is-en", "is-pl", "en-is", "pl-is"],
        "action": "wagtail_translate.actions.translate_and_publish",
    }
]

For those wanting to create their own actions, the translate mappings could help them pick the correct translator class, by using something like:

from wagtail_translate import get_translator_class
Translator = get_translator_class(source_lang, dest_lang)

Things to develop to achieve this

Let me know what you think

allcaps commented 2 weeks ago

Hi @saevarom,

Thank you for your proposal! Appreciated!

I acknowledge the need to simplify the onboarding story. The current situation is a hurdle. However, I believe that the flexibility offered by the signal receiver aligns better with the diverse requirements of multi-language projects. I just have to communicate the advantages better.

While additional settings might seem to simplify the initial setup, they can also make it harder to do additional customisations. The signal receiver provides developers direct access to the behaviours. Allowing them to implement their specific project requirements.

Going forward, I'll simplify the signal receiver example, and will add additional examples for:

Your requirement for multiple translation services can be implemented like this:

# Your signals.py
from django.dispatch import receiver
from wagtail.models import Page, TranslatableMixin
from wagtail_translate.translators.deepl import DeeplTranslator
from myapp.translators.special import IcelandicTranslator
from wagtail_translate.signals import copy_for_translation_done  # For Wagtail < 6.2

@receiver(copy_for_translation_done)
def my_translation_done_receiver(sender, source_obj, target_obj, **kwargs):
    source_language_code = source_obj.locale.language_code
    target_language_code = target_obj.locale.language_code

    mapping = {
          ("en", "is"): IcelandicTranslator,
          ("is", "en"): IcelandicTranslator,
    }
    translator_class = mapping.get((source_language, target_language_code), DeeplTranslator)
    translator = translator_class(source_language_code, target_language_code)
    translated_obj = translator.translate_obj(source_obj, target_obj)

    if isinstance(translated_obj, Page):
        translated_obj.save_revision()
    else:
        translated_obj.save()

Does that make sense?

saevarom commented 2 weeks ago

Sure, this is a good implementation of my specific use-case, thanks!

I think the custom signal receiver will always be something that is needed for custom cases. I think, however, for about 95% of cases, that standard receivers and simple settings could work. For the rest you can have examples and point to reference implementations in docs and e.g. the standard receivers.

The custom signal receiver will always present challenges for the package maintainers, since that ties your hands a bit regarding API changes, etc. :)

allcaps commented 2 weeks ago

I made a PR introducing a default app. https://github.com/allcaps/wagtail-translate/pull/14

Readme rendered https://github.com/allcaps/wagtail-translate/blob/4bee3b81e015a99a42ba0ea0faa38831251bbb3d/README.md

Maybe you can have a look? And provide feedback?

saevarom commented 1 week ago

Interesting, will take a look!