Skip to content

🎨 Added an option to use unicode slugs in URL:s - #29705

Open
dittnamn wants to merge 4 commits into
TryGhost:mainfrom
dittnamn:slug-upgrade
Open

🎨 Added an option to use unicode slugs in URL:s#29705
dittnamn wants to merge 4 commits into
TryGhost:mainfrom
dittnamn:slug-upgrade

Conversation

@dittnamn

Copy link
Copy Markdown
Contributor

fixes #3224
The slugs generated by Ghost have had a lot of issues in how they've been transliterated. Through a change in @tryghost/string a new transliteration library, any-ascii, has been proposed to replace unidecode, see TryGhost/SDK#1011

However, to get a fully internationalized site along with SEO optimized URL:s, that change isn't fully enough. The current change adds an option in Labs where it's possible to enable Unicode slugs instead of performing the transliteration. The Unicode characters in use are limited to those that are registered as letters and numbers, which means that emojis, special characters, etc. still will be removed.

The only "major" change that has been done in Ghost to make this work is actually just to normalize the URL slugs before looking them up in the database. The rest of the code changes are mostly settings to turn the new feature on or off, and to pass the setting along all the way to the slugify() function. Due to the rest of the system already being in Unicode, everything seems to work as it's supposed to.

Instead of using safe() from @tryghost/security, the slug generation has also been changed to utilize slugify() from @tryghost/string directly instead. The routing controllers for rss, collection and channel were previously using safe() as well to slugify the lookups before going to the router, but the entry controller didn't do this. As the router already checks the slugs with isSlug() before passing them further, this was unnecessary and had the potential to break lookups, so it was simply removed.

In addition to using Unicode slugs, there's also an option added to switch which separator the slugs use. Previously, dashes (-) were used as the hardcoded default, but for URL readability, underscores (_) could be preferred, like in the URL:s Wikipedia use. There's also an option for using spaces ( ), but this might still be seen as a bit foreign in URL:s. Out of the major browsers, it's currently just Firefox that show these as spaces by default, with Safari doing it in some situations. Other browsers can show the spaces as %20.

When activated, the Unicode slugs aren't added to member tags, newsletter, services, integrations or benefits, as these aren't user facing.

Note that for this change to work, the changes in TryGhost/SDK#1011 and TryGhost/framework#860 are required.

  • I've read and followed the Contributor Guide
  • I've explained my change
  • I've written an automated test to prove my change works

dittnamn added 4 commits July 30, 2026 20:51
fixes TryGhost#3224
The slugs generated by Ghost have had a lot of issues in how they've
been transliterated. Through a change in @tryghost/string a new
transliteration library, any-ascii, has been proposed to replace
unidecode, see TryGhost/SDK#1011

However, to get a fully internationalized site along with SEO optimized
URL:s, that change isn't fully enough. The current change adds an option
in Labs where it's possible to enable Unicode slugs instead of
performing the transliteration. The Unicode characters in use are
limited to those that are registered as letters and numbers, which means
that emojis, special characters, etc. still will be removed.

The only "major" change that has been done in Ghost to make this work is
actually just to normalize the URL slugs before looking them up in the
database. The rest of the code changes are mostly settings to turn the
new feature on or off, and to pass the setting along all the way to the
slugify() function. Due to the rest of the system already being in
Unicode, everything seems to work as it's supposed to.

Instead of using safe() from @tryghost/security, the slug generation has
also been changed to utilize slugify() from @tryghost/string directly
instead. The routing controllers for rss, collection and channel were
previously using safe() as well to slugify the lookups before going to
the router, but the entry controller didn't do this. As the router
already checks the slugs with isSlug() before passing them further, this
was unnecessary and had the potential to break lookups, so it was simply
removed.

In addition to using Unicode slugs, there's also an option added to
switch which separator the slugs use. Previously, dashes (-) were used
as the hardcoded default, but for URL readability, underscores (_) could
be preferred, like in the URL:s Wikipedia use. There's also an option
for using spaces ( ), but this might still be seen as a bit foreign in
URL:s. Out of the major browsers, it's currently just Firefox that show
these as spaces by default, with Safari doing it in some situations.
Other browsers can show the spaces as %20.

When activated, the Unicode slugs aren't added to member tags,
newsletter, services, integrations or benefits, as these aren't user
facing.

Note that for this change to work, the changes in
TryGhost/SDK#1011 and
TryGhost/framework#860 are required.
@github-actions github-actions Bot added the migration [pull request] Includes migration for review label Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

It looks like this PR contains a migration 👀
Here's the checklist for reviewing migrations:

General requirements

  • ⚠️ Tested performance on staging database servers, as performance on local machines is not comparable to a production environment
  • Satisfies idempotency requirement (both up() and down())
  • Does not reference models
  • Filename is in the correct format (and correctly ordered)
  • Targets the next minor version
  • All code paths have appropriate log messages
  • Uses the correct utils
  • Contains a minimal changeset
  • Does not mix DDL/DML operations
  • Tested in MySQL and SQLite

Schema changes

  • Both schema change and related migration have been implemented
  • For index changes: has been performance tested for large tables
  • For new tables/columns: fields use the appropriate predefined field lengths
  • For new tables/columns: field names follow the appropriate conventions
  • Does not drop a non-alpha table outside of a major version

Data changes

  • Mass updates/inserts are batched appropriately
  • Does not loop over large tables/datasets
  • Defends against missing or invalid data
  • For settings updates: follows the appropriate guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

migration [pull request] Includes migration for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

option to disable unicode character conversion in post slugs.

1 participant