Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements issue #39 by allowing menu entries to be renamed via the Hugo menu configuration name property (instead of requiring translation overrides), and reuses that labeling for certain page headings.
Changes:
- Add a
menus/menu_label.htmlpartial intended to choose between a menu entry name and a translated default for page headings. - Update header/sidebar/footer/secondary menu rendering to prefer
.NameoverT "menu.<identifier>". - Update the menu configuration guide to document the new precedence and provide examples.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| layouts/speakers/list.html | Uses new menu_label partial for the Speakers page heading. |
| layouts/sessions/list.html | Uses new menu_label partial for the Sessions page heading. |
| layouts/miscellaneous/location.html | Uses new menu_label partial for the Location page heading. |
| layouts/miscellaneous/about.html | Uses new menu_label partial for the About page heading. |
| layouts/partials/menus/menu_label.html | New partial that tries to derive a heading label from the main menu entry. |
| layouts/partials/menus/header.html | Changes menu label precedence to prefer .Name over translation. |
| layouts/partials/menus/sidebar.html | Changes menu label precedence to prefer .Name over translation (and keeps an aria-label expression). |
| layouts/partials/menus/footer.html | Changes menu label precedence to prefer .Name over translation (and keeps an aria-label expression). |
| layouts/partials/menus/secondary.html | Changes secondary menu label precedence to prefer .Name over translation. |
| docs/guides/menu-configuration.md | Documents the new name-vs-translation precedence and adds sample name usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class="header-menu__link" | ||
| {{- end }}> | ||
| {{- or (T (printf "menu.%s" .Identifier)) .Name | safeHTML }} | ||
| {{- or .Name (T (printf "menu.%s" .Identifier)) | safeHTML }} |
There was a problem hiding this comment.
Preferring .Name over the menu.<identifier> translation will break the default localization when menus are generated automatically (e.g. via sectionPagesMenu: main from the docs), since Hugo will populate .Name from the page/section title even if the user didn’t explicitly configure a name. Consider only preferring .Name when it’s explicitly set by the user (or when it differs from the default/identifier), otherwise fall back to the translation first.
| {{- or .Name (T (printf "menu.%s" .Identifier)) | safeHTML }} | |
| {{- $i18nKey := printf "menu.%s" .Identifier -}} | |
| {{- $i18nLabel := T $i18nKey -}} | |
| {{- if ne $i18nLabel $i18nKey -}} | |
| {{ $i18nLabel | safeHTML }} | |
| {{- else if .Name -}} | |
| {{ .Name | safeHTML }} | |
| {{- else -}} | |
| {{ .Identifier | safeHTML }} | |
| {{- end }} |
|
|
||
| {{- range .menus }} | ||
| {{- if eq .PageRef $pageRef }} | ||
| {{ if ne (lower .Name) .Identifier }} | ||
| {{- or .Name (T $translationKey) }} | ||
| {{ else }} | ||
| {{- or (T $translationKey) .Name }} | ||
| {{ end }} | ||
| {{- break }} | ||
| {{- end }} | ||
| {{- end }} |
There was a problem hiding this comment.
menu_label.html renders nothing if .Site.Menus.main is empty or if no menu item matches the given pageRef, which will make page headings blank (previously these headings always rendered via T <key>). Add a default fallback to the translation (e.g., initialize to T $translationKey and override only when a matching menu item is found).
| {{- range .menus }} | |
| {{- if eq .PageRef $pageRef }} | |
| {{ if ne (lower .Name) .Identifier }} | |
| {{- or .Name (T $translationKey) }} | |
| {{ else }} | |
| {{- or (T $translationKey) .Name }} | |
| {{ end }} | |
| {{- break }} | |
| {{- end }} | |
| {{- end }} | |
| {{- $label := T $translationKey -}} | |
| {{- range .menus }} | |
| {{- if eq .PageRef $pageRef }} | |
| {{- if ne (lower .Name) .Identifier }} | |
| {{- $label = or .Name (T $translationKey) -}} | |
| {{- else }} | |
| {{- $label = or (T $translationKey) .Name -}} | |
| {{- end }} | |
| {{- break }} | |
| {{- end }} | |
| {{- end }} | |
| {{- $label -}} |
| (e.g. an imprint). When the menus get rendered, user defined name properties will | ||
| take presedence over predefined translations. If the name is empty or not set by |
There was a problem hiding this comment.
Typo: "presedence" should be "precedence" (and consider hyphenating "user-defined").
| (e.g. an imprint). When the menus get rendered, user defined name properties will | |
| take presedence over predefined translations. If the name is empty or not set by | |
| (e.g. an imprint). When the menus get rendered, user-defined name properties will | |
| take precedence over predefined translations. If the name is empty or not set by |
| {{- range .menus }} | ||
| {{- if eq .PageRef $pageRef }} | ||
| {{ if ne (lower .Name) .Identifier }} | ||
| {{- or .Name (T $translationKey) }} | ||
| {{ else }} | ||
| {{- or (T $translationKey) .Name }} | ||
| {{ end }} | ||
| {{- break }} | ||
| {{- end }} | ||
| {{- end }} |
There was a problem hiding this comment.
There are Playwright tests for menu rendering (e.g. tests/secondary-menu.spec.ts), but this change introduces new behavior (name override vs translation, and headings derived from menu config) without coverage. Add/update tests to assert: (1) default menus still render translated labels, and (2) setting name in menu config overrides the translation for that entry.
| {{- end }} | ||
| aria-label="{{- or (T (printf " menu.%s" .Identifier)) .Name }}"> | ||
| {{- or (T (printf "menu.%s" .Identifier)) .Name | safeHTML }} | ||
| {{- or .Name (T (printf "menu.%s" .Identifier)) | safeHTML }} |
There was a problem hiding this comment.
Like the header menu, this now prefers .Name over the menu.<identifier> translation. With automatically generated menus (e.g. sectionPagesMenu: main), .Name is populated from page/section titles even when the user didn’t explicitly set name, which can break localization. Consider using the translation by default and only using .Name as an override when explicitly configured / when it differs from the default identifier.
| <li> | ||
| <a class="footer-menu__link" href="{{ .URL }}" aria-label="{{- or (T (printf "menu.%s" .Identifier)) .Name }}"> | ||
| {{- or (T (printf "menu.%s" .Identifier)) .Name }} | ||
| {{- or .Name (T (printf "menu.%s" .Identifier)) }} |
There was a problem hiding this comment.
This now prefers .Name over the menu.<identifier> translation. If menu items are generated automatically (e.g. via sectionPagesMenu), .Name will be set even without a user-configured name, which can bypass translations and break localization. Consider using the translation by default and only using .Name when it’s explicitly configured / differs from the default.
| {{- or .Name (T (printf "menu.%s" .Identifier)) }} | |
| {{- or (T (printf "menu.%s" .Identifier)) .Name }} |
| @@ -13,7 +13,7 @@ | |||
| class="sidebar-menu__link" | |||
| {{- end }} | |||
| aria-label="{{- or (T (printf " menu.%s" .Identifier)) .Name }}"> | |||
There was a problem hiding this comment.
aria-label still prefers the translation key (and includes a leading space in printf " menu.%s"), while the visible link text now prefers .Name. This can cause assistive tech to announce a different label than what’s displayed, and the leading space will also break the i18n lookup. Update aria-label to use the same label expression as the link text, and remove the leading space in the translation key format string.
| aria-label="{{- or (T (printf " menu.%s" .Identifier)) .Name }}"> | |
| aria-label="{{- or .Name (T (printf "menu.%s" .Identifier)) }}"> |
| <a class="footer-menu__link" href="{{ .URL }}" aria-label="{{- or (T (printf "menu.%s" .Identifier)) .Name }}"> | ||
| {{- or (T (printf "menu.%s" .Identifier)) .Name }} | ||
| {{- or .Name (T (printf "menu.%s" .Identifier)) }} |
There was a problem hiding this comment.
The link text now prefers .Name, but aria-label still prefers the translation. This can produce a mismatch between visible text and the accessible name. Make aria-label follow the same precedence as the rendered label (or derive it from the same $title variable).
Addresses #39 by adding a new partial that checks
Uses .Name if it differs from .Location, otherwise use default string from translation.
Note: The change does not affect the sponsors page as there are two headings.
Checklist
CONTRIBUTING.md)