Localized Slugs and Preview Paths
When i18n is enabled for an entry collection, managing entry slugs (file names) across different locales can be challenging. Sveltia CMS offers two solutions: localized entry slugs and UUID-based slugs.
Localizing Entry Slugs
In Sveltia CMS, it’s possible to localize entry slugs (filenames) if the i18n structure is multiple_files, multiple_folders or multiple_root_folders, or the folder option contains the {{locale}} placeholder. All you need is the localize filter for slug template tags:
i18n:
structure: multiple_folders
locales: [en, fr]
slug:
encoding: ascii
clean_accents: true
collections:
- name: posts
label: Blog posts
folder: /content/posts
slug: '{{title | localize}}'
format: yaml
i18n: true
fields:
- name: title
label: Title
widget: string
i18n: true[i18n]
structure = "multiple_folders"
locales = ["en", "fr"]
[slug]
encoding = "ascii"
clean_accents = true
[[collections]]
name = "posts"
label = "Blog posts"
folder = "/content/posts"
slug = "{{title | localize}}"
format = "yaml"
i18n = true
[[collections.fields]]
name = "title"
label = "Title"
widget = "string"
i18n = true{
"i18n": {
"structure": "multiple_folders",
"locales": ["en", "fr"]
},
"slug": {
"encoding": "ascii",
"clean_accents": true
},
"collections": [
{
"name": "posts",
"label": "Blog posts",
"folder": "/content/posts",
"slug": "{{title | localize}}",
"format": "yaml",
"i18n": true,
"fields": [
{
"name": "title",
"label": "Title",
"widget": "string",
"i18n": true
}
]
}
]
}{
i18n: {
structure: "multiple_folders",
locales: ["en", "fr"],
},
slug: {
encoding: "ascii",
clean_accents: true,
},
collections: [
{
name: "posts",
label: "Blog posts",
folder: "/content/posts",
slug: "{{title | localize}}",
format: "yaml",
i18n: true,
fields: [
{
name: "title",
label: "Title",
widget: "string",
i18n: true,
},
],
},
],
}With this configuration, an entry is saved with localized filenames, while the default locale’s slug is stored in each file as an extra translationKey property, which is used in Hugo’s multilingual support. Sveltia CMS and Hugo read this property to link localized files.
For example, if a blog post is created with the title “My trip to New York” in English and “Mon voyage à New York” in French, the following files will be created:
content/posts/en/my-trip-to-new-york.yamlyamltranslationKey: my-trip-to-new-york title: My trip to New Yorkcontent/posts/fr/mon-voyage-a-new-york.yamlyamltranslationKey: my-trip-to-new-york title: Mon voyage à New York
You can customize the property name and value for a different framework or i18n library by adding the canonical_slug option to your top-level or collection-level i18n configuration. The example below is for @astrolicious/i18n, which requires a locale prefix in the value (discussion):
i18n:
canonical_slug:
key: defaultLocaleVersion # default: translationKey
value: 'en/{{slug}}' # default: {{slug}}[i18n]
canonical_slug = { key = "defaultLocaleVersion", value = "en/{{slug}}" }{
"i18n": {
"canonical_slug": {
"key": "defaultLocaleVersion",
"value": "en/{{slug}}"
}
}
}{
i18n: {
canonical_slug: {
key: "defaultLocaleVersion",
value: "en/{{slug}}",
},
},
}For Jekyll, you may want to use the ref property:
i18n:
canonical_slug:
key: ref[i18n]
canonical_slug = { key = "ref" }{
"i18n": {
"canonical_slug": {
"key": "ref"
}
}
}{
i18n: {
canonical_slug: {
key: "ref",
},
},
}In a nested collection, the slug names the entry’s folder, so localizing the slugs also gives every locale its own folder names.
Making Slugs Editable
Localized slugs can be edited for each locale in the Slug panel of the Content Editor, which has a section for each locale. When the slugs aren’t localized, a single slug is shared by every locale.
Instead of adding the localize filter to the template tags, you can localize the slugs with the i18n option of the slug options object. It accepts the following values:
true: Each locale has a slug of its own. Every field tag in the template is filled with the locale’s own value, soslug: { template: '{{title}}', i18n: true }is equivalent toslug: '{{title | localize}}'.duplicate(default) orfalse: The default locale’s slug is shared by every locale.
Like the localize filter, the i18n option only has an effect with the multiple_files, multiple_folders or multiple_root_folders structure, or a folder with the {{locale}} placeholder, where each locale has a file of its own.
To have users type a slug for each locale, combine it with the editable option, without a template:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
slug:
editable: true
i18n: true[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
[collections.slug]
editable = true
i18n = true{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"slug": {
"editable": true,
"i18n": true
}
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
slug: {
editable: true,
i18n: true,
},
},
],
}Deprecation Notice
The special {{fields._slug | localize}} slug template tag has been deprecated in favor of the configuration above, and will be removed in Sveltia CMS v1.0.0.
Using Random UUIDs for Slugs
Entry titles and other fields containing non-Latin characters, such as Japanese or Chinese, may not be suitable for generating slugs. To address this issue, Sveltia CMS lets you use random UUIDs as slugs for entries in i18n collections.
This can be achieved by setting the slug option with the {{uuid}}, {{uuid_short}} or {{uuid_shorter}} template tag in your collection configuration:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
slug: "{{uuid_short}}"[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
slug = "{{uuid_short}}"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"slug": "{{uuid_short}}"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
slug: "{{uuid_short}}",
},
],
}Preview Paths
When i18n is enabled for an entry collection, you can manage preview paths for each locale using the preview_path option. This option supports the {{locale}} template tag, which will be replaced with the current locale in the preview URL. For example, if you set the preview_path to /{{locale}}/{{slug}}, the preview URL for an entry with the slug my-post in the fr locale would be /fr/my-post.
The omit_default_locale_from_preview_path option can be used to omit the locale code from the preview path for the default locale. For example, if en is the default locale and omit_default_locale_from_preview_path is set to true, the preview URL for the English version of the entry would be /my-post, while the preview URL for the French version would still be /fr/my-post.
Both options apply to Deploy Previews as well, so each translation of an unpublished entry links to its own page on the preview build. The per-locale links are offered from the locale pane’s options menu in the Content Editor.