Skip to content

feat(i18n): consume Polylang translated slugs in nav and routing #55

@JohnRDOrazio

Description

@JohnRDOrazio

Problem

URLs in the site's static navigation never use translated slugs. Example: in the Header dropdown under Governance, "Criteri di valutazione" links to:

https://catholicdigitalcommons.org/it/governance/project-governance/project-vetting-criteria

The page renders Italian content (because WPGraphQL+Polylang resolves the English URI to the Italian translation server-side), but the URL itself stays in English.

The Italian slugs do exist in WordPress — Polylang auto-generated them from translated post titles (e.g. governanza-del-progetto). They're simply never consumed by the Next.js front-end.

Why

Two missing pieces:

  1. src/i18n/routing.ts:7 defines no pathnames map. Without one, createNavigation(routing) (src/i18n/navigation.ts) only prepends the locale; it never translates path segments.
  2. components/Header.tsx (and components/Footer.tsx) hardcode English paths (/governance/project-governance/project-vetting-criteria, etc.). With no pathnames map, those strings pass through verbatim.

The catch-all route app/[lang]/[[...slug]]/page.tsx:27 then does getPage(slug.join('/'), lang) against a WPGraphQL query (page(id: $slug, idType: URI).translation(language: $language)) that resolves English URIs to translations — which is why the page loads at all, but explains why nobody noticed the URL stayed English.

Suggested implementation

  1. Generate a pathnames map at build time from getAllPages(locale) for each locale. Key: canonical English URI; values: per-locale translated paths. Keep as a generated file (e.g. src/i18n/pathnames.generated.ts) regenerated on deploy. (The getAllPages query already returns slug per locale; a small extension to include parent-slug chains is enough to compose translated paths.)
  2. Add pathnames to defineRouting in src/i18n/routing.ts.
  3. Update the catch-all route to look up pages by language-aware URI. Two options:
    • switch GET_PAGE_BY_SLUG to use nodeByUri(uri: $uri) and pass the locale-prefixed URI, or
    • reverse-map the incoming localized slug → canonical English slug before calling getPage (using the same pathnames map).
  4. Header/Footer remain unchanged — they keep their canonical English hrefs; next-intl substitutes the localized path automatically once pathnames is configured.

Dependencies

Depends on #53 and the sitemap fix being resolved first, since they share the WP query layer (GET_ALL_PAGES, GET_CHILD_PAGES).

Open questions

  • Italian governance root currently has slug governance-2 (WP collision suffix because English took governance). Worth renaming to governanza in WP admin before the pathnames map gets baked in, so users don't have to re-bookmark.
  • Whether to drive the Header from a Polylang-managed nav menu in WP (more work, more maintainable as pages get renamed) vs. keeping it hardcoded with a generated pathnames map.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions