Tina Docs
Introduction
Core Concepts
Querying Content
Editing
Customizing Tina
Going To Production
Drafts
Guides
Further Reference

Internationalization with TinaCMS

Managing multilingual content is essential for global reach. TinaCMS provides versatile options to facilitate this. This guide focuses on two main strategies:

  • Directory-Based Localization
  • Field-Based Localization

Directory-Based Localization

With directory-based localization, your content should be structured in a directory-based manner, where the locale (e.g., en, fr) lives underneath the collection root (e.g., blog, docs). For example:

.
├── /blog/
│ ├── /en/
│ │ └── hello-world.md
│ └── /fr/
│ └── hello-world.md
└── /docs/
├── /en/
│ └── my-doc.md
└── /fr/
└── my-doc.md
Steps to Implement Directory-Based Localization

In your config.ts, you likely will have one collection that contains all your locales

export const config = {
collections: [
{
label: 'Blog',
name: 'blog',
path: 'content/blog',
// ...other settings
},
}
Routing and File Structure:

Whether you're using Next.js, or another framework, your routing logic should be updated to pick the correct locale based on either the URL or user setting.

// Example: Fetching the page list in NextJS
const getStaticPaths = async({ locales }) {
// ...
})

Using the locale, you can filter for document(s) based on the path

/**
* /pages/post/[filename].tsx
*/
// `locale` is provided alongside `params`
const getStaticProps = async({ params, locale }) {
const tinaProps = await client.BlogPostQuery({
// compose `relativePath` where `locale` is a sub-folder to the `post`
relativePath: `${locale}/${params.filename}.mdx`,
});
return {
props: {
...tinaProps
}
}
}
For more info on setting up the routing for NextJS-specific implementations, see our guide
Content Management

With this setup, editors will browse locales for each collection via the document list.

Localized List

If a user wants to create a new localized version of an existing document, they can click "duplicate document" from the document list, and prepend the desired locale in the new document's filename.

Field-Based Localization

In this approach, each localized field contains nested values for multiple languages. For example, a single Markdown file might look like this:

{
"title": {
"en": "Hello",
"fr": "Bonjour"
}
}
Steps to Implement Field-Based Localization

You will need to modify your TinaCMS schema to include localized fields.

export const pageSchema = {
label: 'Page',
name: 'page',
fields: [
{
label: 'Title',
name: 'title',
type: 'object',
fields: [
{
type: 'string',
name: 'en',
label: 'English',
},
{
type: 'string',
name: 'fr',
label: 'French',
},
],
},
// ...other fields
],
}
Note: If you are using markdown/mdx content, and want to use the markdown body for your content, you might prefer using the directory-based approach to localization.
Display Localized Content:

In your site's components, you can then choose the correct localized field to display based on the current locale.

const PageComponent = ({ data, locale }) => {
const title = data.title[locale]
// ...display content
}
Content Management:

TinaCMS will display all localized fields as children of the root-level field.

Localized Fields