Multilingual slug strategy: Polylang free constraints, Pro purchase decision #56
JohnRDOrazio
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Context
The CDCF website runs WordPress + Polylang (free) in directory mode (
/it/...,/es/..., etc.), with WPGraphQL feeding a Next.js front-end. We have multilingual page translations for IT, ES, FR, PT, DE in addition to the EN canonical.Polylang free relies on WordPress's built-in
wp_unique_post_slug()for slug uniqueness — and that function enforces uniqueness globally, not per-language. So if the EN pagegovernanceis created first and an IT translation also wants to be calledgovernance, WordPress silently appends a numeric suffix →governance-2. Same thing happens to ES/FR/PT/DE if they want the same string.This is a known limitation of Polylang free. The paid version (Polylang Pro) ships a "Share slugs" feature that hooks into
wp_unique_post_slugand skips the uniqueness check when the colliding post is in a different language. The setting is visible but disabled in our admin (screenshot below) with the message "To enable this feature, you need Polylang Pro."Scope: how widespread is the problem in our content?
I scanned all 24 EN pages and their translations. Every "section root" page has the issue, plus numerous other top-level pages:
governancegovernance-2gobernanza✅gouvernance✅governanca✅governance-3manifestomanifesto-4contactcontact-2contact-3contact-4contact-5contact-6blogblog-2blog-3blog-4blog-5blog-6communitycommunity-2community-3community-4community-5community-6projectsprojects-2projects-3projects-4projects-5projects-6aboutabout-2about-3about-4about-5about-6That's 27 pages with numeric collision suffixes in their URLs across the site.
For pages where the natural translation produces a different word (
gobernanza,gouvernance,governancafor "governance"), Polylang free works fine. For pages where the same word would be the natural choice in two or more languages (likemanifesto,blog,about,contact,community,projects— many of which are actually loanwords or shared roots in romance languages), every language after the first to claim the slug gets a numeric suffix.These ugly numeric suffixes appear in user-visible URLs (
https://catholicdigitalcommons.org/it/projects-2/...) and weaken multilingual SEO, since the URL no longer carries semantic content for that locale.There's also a separate but related editorial problem: 5 leaf pages have slugs >50 characters in every non-EN locale (e.g.
criteri-di-valutazione-dei-progetti-cdcf-quadro-generale, 56 chars). That's not caused by the slug-collision issue and would need a content-team pass regardless of which option below we choose.The three options
Option A — translate around the collisions (no spend, more editorial work)
For every collision, pick a target-language word that's distinct from the EN slug:
governanza, DEverwaltung(or German team's preference). The other three are already fine.contatti, EScontacto, FRcontact-nousornous-contacter, PTcontato, DEkontakt. All natural in their language.blogis normal — but it collides. Could usearticoli, but loses the "blog" framing. Same for ES/FR/PT/DE.comunita, EScomunidad, FRcommunaute, PTcomunidade, DEgemeinschaft.progetti, ESproyectos, FRprojets, PTprojetos, DEprojekte.chi-siamo, ESquienes-somos, FRa-propos, PTsobre, DEuber-uns.manifestois the natural word. Forced into something less natural likenosso-manifesto.Pros: zero ongoing cost; URLs read fully in their target language; no plugin dependency; aligned with Polylang's free model.
Cons: editorial work for ~27 pages now; some slugs feel forced (e.g. having to invent
articolifor what is universally called a "blog" in Italian, or PTmanifestolosing its natural slug); every future page needs the same vigilance; the "Project Governance" sub-tree already has translated slugs that may want loanword reconsideration regardless (governance-del-progettoreads more idiomatically in Italian tech contexts thangovernanza-del-progetto).Effort estimate: ~1 day editorial pass for current pages + small recurring cost per new page.
Option B — implement a custom
wp_unique_post_slugfilter (no spend, more code/risk)Add a hook in our custom theme (
wordpress/themes/cdcf-headless/functions.php) that interceptswp_unique_post_slug()and returns the original (non-suffixed) slug when the colliding post is in a different Polylang language. ~20 lines of PHP. This is essentially a free re-implementation of what Polylang Pro's "Share slugs" feature does internally.Pros: zero recurring cost; one-time code change; URLs become identical to Option C result.
Cons:
Effort estimate: ~2-4 hours initial implementation, plus unknown ongoing debugging if edge cases surface.
Option C — purchase Polylang Pro (recurring spend, no editorial constraint)
The "Share slugs" toggle becomes available. We can decide per-page whether two languages share a slug, or whether they translate. URL collision suffixes go away.
Approximate pricing (verify with vendor before purchase): around €99/year for 1 site, €199/year for 3 sites, with discounts for renewals after the first year. (Numbers from Polylang Pro pricing page as of last public reference; exact figures should be re-checked at purchase time.) Polylang Pro also bundles other features we may not currently use (translated URL slugs for taxonomies, language switcher widget improvements, REST API support refinements, custom post type translation management). So part of the value is unlocked features beyond just "Share slugs".
Pros: solves the problem cleanly; supports the plugin's authors; unlocks other useful features (some of which we'd benefit from as the site grows — for instance, translated CPT slugs would matter when we expose more public CPT archives); editorial team can focus on content quality not URL gymnastics; small dollar amount for a foundation of our type.
Cons: recurring cost forever; one more vendor dependency; if we ever drop Polylang the migration is bigger; we may not use enough of the Pro features to justify the price relative to Option A's editorial effort.
Effort estimate: ~30 min purchase + install + flip toggle + manually rename ~27 slugs (or write a one-shot migration script using our existing
cdcf_api.py).Recommendation framework for the finance committee
The decision is fundamentally about trade-off between recurring cost and recurring editorial constraint:
Key data points for the committee
-Nslug as a redirect alias OR ensuring no external bookmarks/inbound links exist (none of these pages are old enough to have meaningful inbound links yet, so this is a one-time low-cost fix if done now).Open questions to resolve before the committee meeting
verwaltung(or alternative) is acceptable for the IT root vsgovernanceloanword.governanceas the loanword for technical sub-pages (recommended), or usegovernanzaconsistently (more bureaucratic register).Related issues
The slug strategy decided in this discussion will inform how #55 is implemented (specifically: which paths get baked into the
pathnamesmap at build time).Beta Was this translation helpful? Give feedback.
All reactions