I can't find any programmatic interface to create page translation. All the logics seems being implemented in SubmitTranslationView in wagtail.contrib.simple_translation.views.
So the only way to access those programmatically is by simulating the request to access the views. I wrapped this in a function named translate_page(). To translate a page, we can call this function as:-
page_ja = translate_page(user, page, "ja")
Or we can pass the optional parameter include_subtree:-
page_ja = translate_page(user, page, "ja", include_subtree=True)
And the function is defined as:-
def translate_page(user, page, lang, include_subtree=False): locale, created = Locale.objects.get_or_create(language_code=lang) data = {"locales": [locale.id], "include_subtree": include_subtree} url = reverse( "simple_translation:submit_page_translation", kwargs={"page_id": page.id} ) factory = RequestFactory() request = factory.post(url) request.POST = data request.user = user get_response = lambda request: None middleware = SessionMiddleware(get_response) middleware.process_request(request) request.session.save() messages = FallbackStorage(request) setattr(request, "_messages", messages) SubmitPageTranslationView.model = type(page) SubmitPageTranslationView.as_view()(request, page_id=page.pk) page_translated = page.get_translations()[0].specific return page_translated
I have another function called translate_snippet(). The only difference is just the url to submit and no include_subtree parameter.
For all our sites, we have a setup script that will automatically populating some posts and their translation so that developer can start working right away instead of having to create sample pages manually.
Our page structure is like this:-
HomePage ==> BlogIndexPage ==> BlogPage
And the setup script will do the following:-
This all works well until we're setting new site where the page structure is:-
BlogIndexPage ==> BlogPage
So we omitted HomePage (which I think a bad idea now but let's save it for another topic) since this site is mainly a blog. The first thing I notice after running the setup script is that no translation of the blog posts created, despite we already passed include_subtree when translating BlogIndexPage.
My first gut reaction was it could be some changes in new wagtail versions. Most our sites being created few years ago and still on wagtail 5 but for this new site, we will start with wagtail 6 since it's the latest.
But looking at wagtail's commit logs for simple_translation views.py, the code last changes was three years ago. And we can see the code basically the same between wagtail 5 and 6.
The problem with translate_page function above is that it doesn't check for any errors. Because catching errors mean you have to parse the request's response for some error string. But tracing the code flow lead me to a stage where I can see the code is not executed because the form is not validated.
Printing form.errors showed error messages related to invalid locale. This is strange because we can see in the translate_page function above we're creating the locale if it doesn't exists yet.
And printing the form's self.fields["locales"].choices I can the locale is there in the choice during first call of translate_page() when translating the root page, but the choices was empty when calling it second time to translate BlogIndexPage.
Reading the form's code, locales field's choices is set dynamically in the __init__ method, where locale of the page that already translated will be removed. This could be the reason why the locale was empty in the second call. But the page is not translated yet!
Let's recall back the process:-
And this is where the light bulb (?) came in, after hours of debugging. In the original script, we're translating HomePage to ja first, and then BlogIndexPage with all its children. But in this new script, the root page is BlogIndexPage. So BlogIndexPage already translated the second time we call translate_page!
So that's the reason locales choices become empty.
The above is the detailed content of Wagtail programmatically create page translation. For more information, please follow other related articles on the PHP Chinese website!