-
Notifications
You must be signed in to change notification settings - Fork 920
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
Provide a hybrid list of locales drawn from CMS-backed and Django-backed sources #15475
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #15475 +/- ##
==========================================
+ Coverage 78.71% 78.78% +0.06%
==========================================
Files 156 157 +1
Lines 8197 8252 +55
==========================================
+ Hits 6452 6501 +49
- Misses 1745 1751 +6 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: We should keep an eye on the refresh stuff in general to ensure we don't get regressions
"/fr/test-page/child-page/", | ||
"/fr/test-page/child-page/", | ||
), | ||
# These two routes do not work, even though a manual test with similar ones |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I poured a lot of time into trying to work out why the page tree did contain this grandchild-page
, when it's clear it's there from the fixture and if you ask for it's url_path
in the debugger. Talking with core Wagtail people too, didn't seem to reveal what was up. Tested manually, though, so I'm OK that this is a false negative. Will be nice to work out why, though. Hopefully it's not a blocker to an r+
|
||
# Use explicit list of lang codes over fluent files | ||
if fallback_lang_codes: | ||
return fallback_lang_codes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note (non-blocking): The fallback_callable
approach was a late addition in order to make the VPN RC (with its inconsistent Django-side db-backed localization) work -- it's quite an outlier of a view for Bedrock.
It may be that the fallback_callable
and the fallback_ftl_files
are actually the only two approaches we need and we ca drop fallback_lang_codes
, because they can be generated from a callable - let's see as we use prefer_cms
more
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I know that annotating the request is not a super-clean way to do things, but I've tried to keep it sensible with "private" attributes.
There's a performance impact here, because we will hit the DB more for views decorated with prefer_cms
, but by its nature a CMS-related view will hit the DB anyway. We could probably optmise with some prefetching if we need to, but I'm hopeful that we won't need to add to the complexity here even more.
Equally, if you can think of a simpler or cleaner approach, I'm definitely happy to hear it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this out locally and both the page language picker and canonical URLs all seemed to work as expected for the VPN resource center index page, and child pages when they exist in the CMS. Great work!
Whilst I'll leave the more in depth Python code review to Rob, the overall approach here seems well thought out, and should give us the flexibility we need to handle all the use cases I can think of for the future.
I noticed there are a couple of comments around one or two tests that don't quite pass as expected, so I do wonder if we should perhaps try and figure out the root cause for those still. But perhaps they are edge cases, that likely exist in Wagtail as opposed to the changes here?
@alexgibson Thanks for the r+
I'm confident that they're either a quirk in Wagtail (the same way that when we create translations sometimes we need to run |
bedrock/cms/utils.py
Outdated
page.get_translations() | ||
.live() | ||
.exclude( | ||
id__in=[x.id for x in page.aliases.all()], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be curious if there's a SQL way to do this? Looks like this might hit the db for the list comprehension separately. Which is probably fine... sometimes successive small simple SQL queries can be better than one larger complex SQL query.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point about hitting the DB twice there. I'll refactor to use Subquery
so we can keep it all ORM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@robhudson will 9397fb6 get me an r+? 🤞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, sorry, thought I approved with comments. I'll take a quick look over again and approve.
...so that we can use it independently of AbstractBedrockCMSPage._patch_request_for_bedrock() in the enhancement to follow
…th may be served by the CMS or the Django fallback view * Expand prefer_cms to take args that tell us what locales are available in the Django fallback version of the page * In prefer_cms annotate the request with lists of locales available in a CMS-backed version of the page and a Django-backed version * Add a new jinja helper to select the most appropriate list of locales to pass to the lang picker UI element
Making it support a list of automatically-detected Fluent files would make the page() helper even busier, with little value: if we need to decorate a page() view with prefer_cms, we can refactor it to be a regular Django view and then decorate in the URLConf or on the view itself (Had to commit all in one go, alas, due to pre-commit constraints)
This is to satisfy situations like the current VPN RC where overall it's available in 10 locales, but it's not consistently translated into all 10, so we can't claim that all pages are available in all of those locales in the picker. This approach makes the locale derivation pluggable
…PN RC article page (The version with data exported from Contentful, ahead of us moving it all to Wagtail)
…switcher code to cope with alt/fallback sources of locale info
99d0cc4
to
9397fb6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tricky stuff, nice work
One-line summary
This changeset ensures that the language picker (and
canonical-url.html
header partial) remains accurate when a page is partly in Wagtail CMS and partly rendered via Django views.Significant changes and points to review
This piece of work was like pulling at a loose thread on a sweater. It may look like there's a lot going on here, so I'll add notes on the Github diff where I think they'll help.
The
prefer_cms
decorator is applied to a regular Django view and will try to load the decorated URL path from the CMS first, then fall back to the original Django view. Previously, when a page came from the CMS, we would set thetranslations
context variable to be a list of locales available in the CMS only, which had the downside that the language picker in the footer didn't mention the locales that were still available via the regular Django view. (The inverse was also true: if you reached a Django-rendered page that was decorated withprefer_cms
, it would not show the locales available in the CMS because it didn't have awareness of them.I tried different ways to get around this, including patching
translations
inlib.l10n_utils.render
(which ended very badly astranslations
is used for more than just the footer picker, such as the logic around deciding whether to redirect to the defaulten-US
locale.)The approach that worked better was to, via the
prefer_cms
decorator, annotate the request with two lists of locale language codes: the locales available from the CMS and those available from the Django view. Then, we use a new Jinja helper to pull together these two lists for use in the language picker (we also use the same helper to provide correct locale lists for the canonical URL links in the header).(Note that this logic only runs on views decorated with
prefer_cms
- otherwise we still use the regulartranslations
context var for such things.)To make this work the
prefer_cms
decorator needs to be told what locales are available in the regular Django view - it was not viable to introspect the view to get hold of the relevant locales. There are three (!) ways to pass this information in:logic as our main
l10n_utils.render()` function.Issue / Bugzilla link
Resolves #15193
Testing
Testing
section on Migrate VPN resource center to Wagtail (#14860) #15236 if you need to set one up locally)en-US
(e.g.what-is-a-vpn
andthe-difference-between-a-vpn-and-a-web-proxy
) - they can just have lorem ipsum content locally - the URL loath is what we are really need hereen-US
versionhead
of the pages should also reflect the other locales available.