Internationalization
Sveltia CMS comes with first-class support for internationalization (i18n), allowing you to manage content in multiple languages seamlessly. This guide covers the configuration options and best practices for setting up i18n in your Sveltia CMS projects.
Note for Netlify/Decap CMS users
All i18n issues in Netlify/Decap CMS have been resolved in Sveltia CMS, except for issues related to a few unimplemented features. The limitations mentioned in their documentation do not apply to Sveltia CMS.
Why i18n is at the core of Sveltia CMS
Sveltia CMS was originally built for @kyoshino’s Japanese clients, who needed a CMS that could handle multilingual content efficiently. The maintainer is a former long-time localizer for Mozilla and lives in the most diverse city in the world where 150+ languages are spoken.
As a result, i18n support is deeply integrated into Sveltia CMS from the ground up, making it a powerful choice for projects that require multilingual content management.
Configuration
To use i18n support in your Sveltia CMS project, you need to define the i18n option in the top-level, collection-level, and field-level configurations. For a file collection, file-level configuration is also required.
The below example demonstrates how to set up i18n at all levels for an entry collection:
i18n:
structure: multiple_folders
locales: [en, de, fr]
collections:
- name: posts
label: Blog Posts
folder: /content/posts
i18n: true
fields:
- name: title
label: Title
widget: string
i18n: true
- name: date
label: Date
widget: datetime
i18n: duplicate
- name: body
label: Body
widget: richtext
i18n: true[i18n]
structure = "multiple_folders"
locales = ["en", "de", "fr"]
[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
i18n = true
[[collections.fields]]
name = "title"
label = "Title"
widget = "string"
i18n = true
[[collections.fields]]
name = "date"
label = "Date"
widget = "datetime"
i18n = "duplicate"
[[collections.fields]]
name = "body"
label = "Body"
widget = "richtext"
i18n = true{
"i18n": {
"structure": "multiple_folders",
"locales": ["en", "de", "fr"]
},
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"i18n": true,
"fields": [
{
"name": "title",
"label": "Title",
"widget": "string",
"i18n": true
},
{
"name": "date",
"label": "Date",
"widget": "datetime",
"i18n": "duplicate"
},
{
"name": "body",
"label": "Body",
"widget": "richtext",
"i18n": true
}
]
}
]
}{
i18n: {
structure: "multiple_folders",
locales: ["en", "de", "fr"],
},
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
i18n: true,
fields: [
{
name: "title",
label: "Title",
widget: "string",
i18n: true,
},
{
name: "date",
label: "Date",
widget: "datetime",
i18n: "duplicate",
},
{
name: "body",
label: "Body",
widget: "richtext",
i18n: true,
},
],
},
],
}Read on for detailed explanations of each configuration level.
Top-Level Configuration
Let’s start by defining the i18n option at the top-level of your configuration. The i18n option accepts the following properties:
i18n:
structure: multiple_folders
locales: [en, de, fr][i18n]
structure = "multiple_folders"
locales = ["en", "de", "fr"]{
"i18n": {
"structure": "multiple_folders",
"locales": ["en", "de", "fr"]
}
}{
i18n: {
structure: "multiple_folders",
locales: ["en", "de", "fr"],
},
}structure: Defines how localized content is stored. See below for available structures.locales: An array of locale codes representing the supported languages.default_locale: (optional) Explicitly sets the default locale. If not provided, the first locale in thelocalesarray is used.omit_default_locale_from_file_path: (optional) When using a structure that creates separate files for each locale (e.g.,multiple_files), setting this option totruewill omit the locale code from the filename for the default locale. This is useful for frameworks like Zola that expect the default locale to have a specific filename.omit_default_locale_from_preview_path: (optional) When set totrue, the preview URL for the default locale will not include the locale code. This is useful for frameworks that expect the default locale to be served at the root path.
Deprecation Notice
The omit_default_locale_from_filename option is deprecated and will be removed in Sveltia CMS v1.0.0. Use omit_default_locale_from_file_path instead, which works with all multiple files/folders structures, not just the multiple_files structure.
Collection-Level Configuration
You can opt into i18n for a specific collection by setting the i18n option to true. This will use the top-level i18n configuration for that collection.
collections:
- name: posts
i18n: true[[collections]]
name = "posts"
i18n = true{
"collections": [
{
"name": "posts",
"i18n": true
}
]
}{
collections: [
{
name: "posts",
i18n: true,
},
],
}To override the global i18n settings for a specific collection, set the i18n option to an object with the desired configuration.
collections:
- name: posts
i18n:
structure: multiple_files
locales: [en, de, fr, ja][[collections]]
name = "posts"
[collections.i18n]
structure = "multiple_files"
locales = ["en", "de", "fr", "ja"]{
"collections": [
{
"name": "posts",
"i18n": {
"structure": "multiple_files",
"locales": ["en", "de", "fr", "ja"]
}
}
]
}{
collections: [
{
name: "posts",
i18n: {
structure: "multiple_files",
locales: ["en", "de", "fr", "ja"],
},
},
],
}Note that the structure option at the collection level only applies to entry collections. For file collections, see the File Collections section below.
File-Level Configuration
Each file in a file collection can also have the i18n option set to true to enable localization for that specific file. As with collections, the file will use the top-level i18n configuration.
collections:
- name: pages
label: Pages
i18n: true
files:
- name: about
label: About Page
file: content/about.md
i18n: true[[collections]]
name = "pages"
label = "Pages"
i18n = true
[[collections.files]]
name = "about"
label = "About Page"
file = "content/about.md"
i18n = true{
"collections": [
{
"name": "pages",
"label": "Pages",
"i18n": true,
"files": [
{
"name": "about",
"label": "About Page",
"file": "content/about.md",
"i18n": true
}
]
}
]
}{
collections: [
{
name: "pages",
label: "Pages",
i18n: true,
files: [
{
name: "about",
label: "About Page",
file: "content/about.md",
i18n: true,
},
],
},
],
}If you want to override the global i18n settings for a specific file, set the i18n option to an object with the desired configuration. The following example enables localization only for English and French for the about file:
collections:
- name: pages
label: Pages
i18n: true
files:
- name: about
label: About Page
file: content/about.md
i18n:
locales: [en, fr][[collections]]
name = "pages"
label = "Pages"
i18n = true
[[collections.files]]
name = "about"
label = "About Page"
file = "content/about.md"
[collections.files.i18n]
locales = ["en", "fr"]{
"collections": [
{
"name": "pages",
"label": "Pages",
"i18n": true,
"files": [
{
"name": "about",
"label": "About Page",
"file": "content/about.md",
"i18n": {
"locales": ["en", "fr"]
}
}
]
}
]
}{
collections: [
{
name: "pages",
label: "Pages",
i18n: true,
files: [
{
name: "about",
label: "About Page",
file: "content/about.md",
i18n: {
locales: ["en", "fr"],
},
},
],
},
],
}Note that the structure option does not apply to file collections. See the File Collections section below for more details.
Field-Level Configuration
Each field can be localized individually by setting the i18n option. The i18n option for fields accepts the following values:
true- The field can be edited separately for each locale.
- The values are stored separately for each locale.
false(default)- The field can only be edited in the default locale.
- The field is hidden in non-default locales.
- Only the default locale’s value is stored.
duplicate- The field can only be edited in the default locale.
- The field is read-only in non-default locales, displaying the default locale’s value.
- The same value is stored for all locales.
Legacy option values
For backward compatibility with Netlify/Decap CMS, Sveltia CMS also supports translate and none values for the field-level i18n option, which are equivalent to true and false, respectively.
Here’s how the i18n option behaves for different field types:
- The Hidden field type does not have a visible UI representation, but you’ll still need to set the
i18noption totrueorduplicateto store values in non-default locales. - The complex List field type:
truemakes all subfields editable separately for each locale.duplicatemakes all subfields duplicate. When the user adds, reorders, or removes list items in the default locale, the same changes are reflected in other locales. Subfields can be configured with their owni18noptions.
- The Object field type:
truemakes all subfields editable separately for each locale.duplicatemakes all subfields duplicate. Subfields can be configured with their owni18noptions.
Here’s an example of how to configure fields with different i18n options:
fields:
- name: title
label: Title
widget: string
i18n: true
- name: date
label: Date
widget: datetime
i18n: duplicate[[fields]]
label = "Title"
name = "title"
widget = "string"
i18n = true
[[fields]]
label = "Date"
name = "date"
widget = "datetime"
i18n = "duplicate"{
"fields": [
{
"label": "Title",
"name": "title",
"widget": "string",
"i18n": true
},
{
"label": "Date",
"name": "date",
"widget": "datetime",
"i18n": "duplicate"
}
]
}{
fields: [
{
label: "Title",
name: "title",
widget: "string",
i18n: true,
},
{
label: "Date",
name: "date",
widget: "datetime",
i18n: "duplicate",
},
],
}When the i18n options is true, all locale are required to have a value for the field. if you want to make the field required only for specific locales, you can use an array value for the required option, which defaults to true.
In the following example, the summary field is required for English and German locales only:
fields:
- name: summary
label: Summary
widget: string
i18n: true
required: [en, de][[fields]]
label = "Summary"
name = "summary"
widget = "string"
i18n = true
required = ["en", "de"]{
"fields": [
{
"label": "Summary",
"name": "summary",
"widget": "string",
"i18n": true,
"required": ["en", "de"]
}
]
}{
fields: [
{
label: "Summary",
name: "summary",
widget: "string",
i18n: true,
required: ["en", "de"],
},
],
}Managing Content Structure
Sveltia CMS supports four different structures:
single_file: All locales are stored in a single file.multiple_files: Each locale has its own file with the locale code in the filename.multiple_folders: Each locale has its own folder containing the localized files.multiple_root_folders: Each locale has its own root folder containing all collections.
Deprecation Notice
The multiple_folders_i18n_root structure is deprecated and will be removed in Sveltia CMS v1.0.0. Use multiple_root_folders instead, which has a more intuitive name and the same file structure.
Some frameworks and static site generators may have specific requirements for multilingual content organization. Choose the structure that best fits your project’s needs.
When using a structure other than single_file, Sveltia CMS automatically links localized entries and files based on their filenames or folder paths. From the Content Editor perspective, they appear as a single entry or file with multiple locales, regardless of the underlying file structure. There’s no need to manually link translations.
Entry Collections
The structure i18n option defines how localized content is stored for entry collections. Below are examples of each structure type.
Single File
i18n:
structure: single_file
locales: [en, de, fr][i18n]
structure = "single_file"
locales = ["en", "de", "fr"]{
"i18n": {
"structure": "single_file",
"locales": ["en", "de", "fr"]
}
}{
i18n: {
structure: "single_file",
locales: ["en", "de", "fr"],
},
}The single_file structure stores all locales in a single file:
/<folder>/<path>.<extension>The file path remains the same for all locales:
.
└─ content/
└─ pages/
└─ about.mdAnd the file contains all locales in a single file, with locale keys as top-level properties:
de:
title: Über uns
content: Dies ist die deutsche Version der Seite.
en:
title: About Us
content: This is the English version of the page.
fr:
title: À propos de nous
content: Ceci est la version française de la page.Multiple Files
i18n:
structure: multiple_files
locales: [en, de, fr][i18n]
structure = "multiple_files"
locales = ["en", "de", "fr"]{
"i18n": {
"structure": "multiple_files",
"locales": ["en", "de", "fr"]
}
}{
i18n: {
structure: "multiple_files",
locales: ["en", "de", "fr"],
},
}The multiple_files structure creates separate files for each locale, with the locale code included in the filename:
/<folder>/<path>.<locale>.<extension>The file paths for each locale would look like this:
.
└─ content/
└─ pages/
├─ about.de.md # German
├─ about.en.md # English (default locale)
└─ about.fr.md # FrenchOmitting Default Locale from File Path
When the omit_default_locale_from_file_path option is set to true, the path depends on the locale being the default locale or not:
/<folder>/<path>.<extension> # default locale
/<folder>/<path>.<locale>.<extension> # other localesFor example, with en as the default locale, the English file would be named about.md, while the German and French files would retain the locale suffix:
.
└─ content/
└─ pages/
├─ about.md # English (default locale)
├─ about.de.md # German
└─ about.fr.md # FrenchMultiple Folders
i18n:
structure: multiple_folders
locales: [en, de, fr][i18n]
structure = "multiple_folders"
locales = ["en", "de", "fr"]{
"i18n": {
"structure": "multiple_folders",
"locales": ["en", "de", "fr"]
}
}{
i18n: {
structure: "multiple_folders",
locales: ["en", "de", "fr"],
},
}The multiple_folders structure creates separate folders for each locale, containing the localized files:
/<folder>/<locale>/<path>.<extension>The file paths for each locale would look like this:
.
└─ content/
└─ pages/
├─ de/
│ └─ about.md # German
├─ en/
│ └─ about.md # English (default locale)
└─ fr/
└─ about.md # FrenchOmitting Default Locale from File Path
When the omit_default_locale_from_file_path option is set to true, the path depends on the locale being the default locale or not:
/<folder>/<path>.<extension> # default locale
/<folder>/<locale>/<path>.<extension> # other localesFor example, with en as the default locale, the English file would be located at content/pages/about.md, while the German and French files would be located in their respective locale folders:
.
└─ content/
└─ pages/
├─ about.md # English (default locale)
├─ de/
│ └─ about.md # German
└─ fr/
└─ about.md # FrenchMultiple Root Folders
i18n:
structure: multiple_root_folders
locales: [en, de, fr][i18n]
structure = "multiple_root_folders"
locales = ["en", "de", "fr"]{
"i18n": {
"structure": "multiple_root_folders",
"locales": ["en", "de", "fr"]
}
}{
i18n: {
structure: "multiple_root_folders",
locales: ["en", "de", "fr"],
},
}The multiple_root_folders structure creates separate root folders for each locale, containing all collections:
/<locale>/<folder>/<path>.<extension>The file paths for each locale would look like this:
.
├─ de/
│ └─ pages/
│ └─ about.md # German
├─ en/
│ └─ pages/
│ └─ about.md # English (default locale)
└─ fr/
└─ pages/
└─ about.md # FrenchOmitting Default Locale from File Path
When the omit_default_locale_from_file_path option is set to true, the path depends on the locale being the default locale or not:
/<folder>/<path>.<extension> # default locale
/<locale>/<folder>/<path>.<extension> # other localesFor example, with en as the default locale, the English file would be located at pages/about.md, while the German and French files would be located in their respective locale root folders:
.
├─ pages/
│ └─ about.md # English (default locale)
├─ de/
│ └─ pages/
│ └─ about.md # German
└─ fr/
└─ pages/
└─ about.md # FrenchFile Collections
The structure i18n option only applies to entry collections. For file collections, you can use the {{locale}} placeholder in the file path option to create separate files or folders for each locale. If the placeholder is not used, the structure defaults to single_file, meaning the same file is shared across all locales.
The following example demonstrates how to set up a file collection with different i18n structures using the {{locale}} placeholder:
collections:
- name: pages
label: Pages
files:
- name: contact
label: Contact Page
file: content/contact.md # equivalent to single_file
- name: about
label: About Page
file: content/about.{{locale}}.md # multiple_files
- name: products
label: Products Page
file: content/{{locale}}/products.md # multiple_folders
- name: settings
label: Site Settings
file: '{{locale}}/settings.yaml' # multiple_root_folders[[collections]]
name = "pages"
label = "Pages"
[[collections.files]]
name = "contact"
label = "Contact Page"
file = "content/contact.md"
[[collections.files]]
name = "about"
label = "About Page"
file = "content/about.{{locale}}.md"
[[collections.files]]
name = "products"
label = "Products Page"
file = "content/{{locale}}/products.md"
[[collections.files]]
name = "settings"
label = "Site Settings"
file = "{{locale}}/settings.yaml"{
"collections": [
{
"name": "pages",
"label": "Pages",
"files": [
{
"name": "contact",
"label": "Contact Page",
"file": "content/contact.md"
},
{
"name": "about",
"label": "About Page",
"file": "content/about.{{locale}}.md"
},
{
"name": "products",
"label": "Products Page",
"file": "content/{{locale}}/products.md"
},
{
"name": "settings",
"label": "Site Settings",
"file": "{{locale}}/settings.yaml"
}
]
}
]
}{
collections: [
{
name: "pages",
label: "Pages",
files: [
{
name: "contact",
label: "Contact Page",
file: "content/contact.md",
},
{
name: "about",
label: "About Page",
file: "content/about.{{locale}}.md",
},
{
name: "products",
label: "Products Page",
file: "content/{{locale}}/products.md",
},
{
name: "settings",
label: "Site Settings",
file: "{{locale}}/settings.yaml",
},
],
},
],
}The resulting file structure would be:
.
├─ content/
│ ├─ contact.md # shared across all locales (single_file)
│ ├─ about.de.md # German
│ ├─ about.en.md # English (default locale)
│ ├─ about.fr.md # French
│ ├─ de/
│ │ └─ products.md # German
│ ├─ en/
│ │ └─ products.md # English (default locale)
│ └─ fr/
│ └─ products.md # French
├─ de/
│ └─ settings.yaml # German
├─ en/
│ └─ settings.yaml # English (default locale)
└─ fr/
└─ settings.yaml # FrenchOmitting Default Locale from File Path
As with entry collections, the omit_default_locale_from_file_path option can be used to omit the locale code from the file path for the default locale when using the {{locale}} placeholder in file collections. The above example would result in the following file structure if en is the default locale and omit_default_locale_from_file_path is set to true:
.
├─ content/
│ ├─ contact.md # shared across all locales (single_file)
│ ├─ about.md # English (default locale)
│ ├─ about.de.md # German
│ ├─ about.fr.md # French
│ ├─ products.md # English (default locale)
│ ├─ de/
│ │ └─ products.md # German
│ └─ fr/
│ └─ products.md # French
├─ settings.yaml # English (default locale)
├─ de/
│ └─ settings.yaml # German
└─ fr/
└─ settings.yaml # FrenchDisabling Non-Default Locale Content
Developers can specify locales to be enabled by default when users create a new entry draft, using the initial_locales i18n option, which accepts a locale list, default (default locale only) or all (all locales).
The default locale is always enabled, even if it’s excluded from initial_locales, while other locales can be enabled or disabled by users in the Content Editor through the three-dot menu in the top right corner, if this i18n option is defined.
The following example disables German by default, but users can manually enable it if needed. Users can also disable French, which is enabled by default.
i18n:
structure: multiple_files
locales: [en, fr, de]
default_locale: en
initial_locales: [en, fr][i18n]
structure = "multiple_files"
locales = ["en", "fr", "de"]
default_locale = "en"
initial_locales = ["en", "fr"]{
"i18n": {
"structure": "multiple_files",
"locales": ["en", "fr", "de"],
"default_locale": "en",
"initial_locales": ["en", "fr"]
}
}{
i18n: {
structure: "multiple_files",
locales: ["en", "fr", "de"],
default_locale: "en",
initial_locales: ["en", "fr"],
},
}Deprecation Notice
The save_all_locales option has been deprecated in favor of the more flexible initial_locales option and will be removed in Sveltia CMS v1.0.0. If you are upgrading from an older version, update your configuration accordingly: save_all_locales: false is equivalent to initial_locales: all, while save_all_locales: true is equivalent to initial_locales being omitted (all locales enabled by default).
Managing Entry Slugs with I18n
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 or multiple_folders. 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 you create a blog post 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",
},
},
}Making Slugs Editable
To make slugs editable for each locale, you can set the slug option to {{fields._slug | localize}} in your collection configuration:
collections:
- name: posts
label: Blog Posts
folder: /content/posts
slug: "{{fields._slug | localize}}"[[collections]]
name = "posts"
label = "Blog Posts"
folder = "/content/posts"
slug = "{{fields._slug | localize}}"{
"collections": [
{
"name": "posts",
"label": "Blog Posts",
"folder": "/content/posts",
"slug": "{{fields._slug | localize}}"
}
]
}{
collections: [
{
name: "posts",
label: "Blog Posts",
folder: "/content/posts",
slug: "{{fields._slug | localize}}",
},
],
}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}}",
},
],
}Managing Preview Paths with I18n
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.
Other I18n Features
Sveltia CMS embeds i18n support everywhere in the configuration and UI. Here are some additional features that enhance the multilingual content management experience.
- The
summaryentry collection option supports the{{locales}}template tag to show enabled entry locales in the entry list. - The
defaultHidden field option supports the{{locale}}template tag to embed the locale code in an entry. - The
value_fieldRelation field option supports locale prefixes like{{locale}}/{{slug}}, which will be replaced with the current locale for i18n support in Astro. (Discussion) - The Content Editor can be linked to a specific locale using a URL query parameter.
Translating Content
Sveltia CMS provides a built-in mechanism for managing content translations. When you create or edit an entry in one locale, you can easily switch to another locale and provide the translated content. The CMS automatically links the translations together based on the i18n configuration.
Adding or updating translations can be done directly in the Content Editor. When viewing an entry, you can use the locale switcher in the top-right corner to switch between locales. If a translation for the selected locale does not exist, you will see an option to create a new translation.
When creating a new translation, Sveltia CMS will pre-fill the fields with the content from the default locale, allowing you to modify only the necessary parts for the translation. This streamlines the translation process and ensures consistency across different language versions of your content.
Content Editor Features
See the Content Editor I18n Support guide for details on how Sveltia CMS enhances the Content Editor experience for multilingual content management, including locale switching, validation, and previewing.
AI-Powered Translations
Sveltia CMS supports AI-powered translation integrations that can automatically translate content between supported languages. This feature can significantly speed up the localization process, especially for large amounts of content. You can enable AI translations in the CMS settings and choose your preferred translation service. See the Translation Services guide for more details.
Showcase
See our Showcase for examples of websites using Sveltia CMS with i18n support. Most of them come with a link to the source code, which can be a great resource for learning how to implement i18n in your own projects.