-
-
Notifications
You must be signed in to change notification settings - Fork 134
feat: Add LOCALIZE_MENU_ITEMS setting for i18n locale-aware menus (fixes #242) #528
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
base: master
Are you sure you want to change the base?
Changes from 5 commits
12b27fd
6c2b9ea
8aee5b3
4fb5438
5806693
6760fd4
3b32e5a
ea7cb20
6ad26ca
464a360
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,19 @@ | ||
| import sys | ||
|
|
||
| from django.conf import settings as django_settings | ||
| from cogwheels import BaseAppSettingsHelper | ||
|
|
||
|
|
||
| class WagtailmenusSettingsHelper(BaseAppSettingsHelper): | ||
| deprecations = () | ||
|
|
||
| def __getattr__(self, name): | ||
| value = super().__getattr__(name) | ||
| # Auto-detect locale-awareness from Wagtail's own i18n flag when the | ||
| # wagtailmenus-specific setting has not been explicitly overridden. | ||
| if name == 'LOCALIZE_MENU_ITEMS' and not value and not self.is_overridden('LOCALIZE_MENU_ITEMS'): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Quick question: what is
|
||
| return bool(getattr(django_settings, 'WAGTAIL_I18N_ENABLED', False)) | ||
| return value | ||
|
|
||
|
|
||
| sys.modules[__name__] = WagtailmenusSettingsHelper() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -963,6 +963,11 @@ def get_top_level_items(self): | |
| # allow this query result to be reused by get_pages_for_display() | ||
| self._raw_menu_items = menu_items | ||
|
|
||
| # pages_for_display triggers get_pages_for_display(), which populates | ||
| # self._localize_id_map when LOCALIZE_MENU_ITEMS is active. | ||
| pages = self.pages_for_display | ||
| localize_map = getattr(self, '_localize_id_map', {}) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This bit made me a bit anxious: If we I was wondering whether we could to extract this computation to a cached_property so that |
||
|
|
||
| top_level_items = [] | ||
| for item in menu_items: | ||
|
|
||
|
|
@@ -971,10 +976,14 @@ def get_top_level_items(self): | |
| top_level_items.append(item) | ||
| continue | ||
|
|
||
| # Translate the stored (default-locale) FK to the active-locale id | ||
| # when localization is active, without mutating item.link_page_id. | ||
| lookup_id = localize_map.get(item.link_page_id, item.link_page_id) | ||
|
|
||
| # But, we only want to include links to pages if the page was | ||
| # in the get_pages_for_display() result | ||
| try: | ||
| item.link_page = self.pages_for_display[item.link_page_id] | ||
| item.link_page = pages[lookup_id] | ||
| top_level_items.append(item) | ||
| except KeyError: | ||
| continue | ||
|
|
@@ -996,22 +1005,49 @@ def get_pages_for_display(self): | |
| # Start with an empty queryset, and expand as needed | ||
| queryset = Page.objects.none() | ||
|
|
||
| # When localization is active, record a mapping of stored (default-locale) | ||
| # page ID → active-locale page ID so that get_top_level_items() can look | ||
| # up pages in pages_for_display using the right key without mutating the | ||
| # stored FK on the menu item. | ||
| localize_id_map = {} | ||
|
|
||
| for item in (item for item in menu_items if item.link_page): | ||
| if settings.LOCALIZE_MENU_ITEMS: | ||
| # Resolve the active-locale page without touching item.link_page | ||
| # (avoids persisting the swap via admin save). | ||
| effective_page = item.link_page.localized or item.link_page | ||
| if effective_page.pk != item.link_page.pk: | ||
| localize_id_map[item.link_page.pk] = effective_page.pk | ||
| else: | ||
| effective_page = item.link_page | ||
|
|
||
| if( | ||
| item.allow_subnav and | ||
| item.link_page.depth >= settings.SECTION_ROOT_DEPTH | ||
| effective_page.depth >= settings.SECTION_ROOT_DEPTH | ||
| ): | ||
| # Add this branch to the overall `queryset` | ||
| queryset = queryset | Page.objects.filter( | ||
| path__startswith=item.link_page.path, | ||
| depth__lt=item.link_page.depth + self.max_levels, | ||
| path__startswith=effective_page.path, | ||
| depth__lt=effective_page.depth + self.max_levels, | ||
| ) | ||
| else: | ||
| # Add this page only to the overall `queryset` | ||
| queryset = queryset | Page.objects.filter(id=item.link_page_id) | ||
|
|
||
| # Filter out pages unsutable display | ||
| queryset = self.get_base_page_queryset() & queryset | ||
| queryset = queryset | Page.objects.filter(id=effective_page.pk) | ||
|
|
||
| # Store the mapping so get_top_level_items() can translate lookup keys. | ||
| self._localize_id_map = localize_id_map | ||
|
|
||
| if settings.LOCALIZE_MENU_ITEMS: | ||
| # `queryset` already contains the localized pages. | ||
| # Apply the same live/show_in_menus/expired constraints as | ||
| # get_base_page_queryset() but only against the small set of pages | ||
| # in `queryset` (scales with menu size, not site size). | ||
| queryset = self.get_base_page_queryset().filter( | ||
| id__in=queryset.values('id') | ||
| ) | ||
| else: | ||
| # Filter out pages unsuitable for display | ||
| queryset = self.get_base_page_queryset() & queryset | ||
|
|
||
| # Always return 'specific' page instances | ||
| return queryset.specific() | ||
|
|
||
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.
nitpick: Order menu settings alphabetically.