June 16, 2022
By James Perkins
When working on a website you may need to introduce internationalization also known as i18n. While Tina currently doesn’t offer a plugin or native support we can leverage Next.js’s i18n feature to create a site that has internationalization support.
To create our project we can use the create-tina-app
that will use one of our starters. For this blog post, we are going to use the barebones starter.
npx create-tina-app@latest tina-internationalization✔ Which package manager would you like to use? › Yarn✔ What starter code would you like to use? › Bare bones starter
Now we have a basic project setup we are going to do the following things to make i18n work:
next.config.js
file that contains all the locales we want to support.getStaticPaths
and getStaticProps
next.config.js
The next.config.js
allows you to create advanced configurations for your Next.js sites, including what locales you want to support on your site.
If you want to read more about next.config.js and all the configurations you can set, check out the next.js documentation.
To support different locales we need to add the i18n
object to the configuration:
(module.exports = {"i18n": {}})
Then inside the i18n object, we need to add two things, a locales
array, and a defaultLocale
. The defaultLocale
will be used if someone visits a locale you don’t support. In our example, we are going to support en-US
and fr
(module.exports = {"i18n": {"locales": ["en-US", "fr"],"defaultLocale": "en-US"}})
getStaticPaths
Now we have configured our Next.js application to use locales we now to need to update our getStaticPaths
to use them. Open up the blog post file found under pages/posts/[slug].js
and at the bottom of the file you will see the following:
export const getStaticPaths = async () => {const postsResponse = await staticRequest({query: `{postConnection {edges {node {_sys {filename}}}}}`,variables: {},})const paths = postsResponse.postConnection.edges.map(x => {return { params: { slug: x.node._sys.filename } }})return {paths,fallback: 'blocking',}}
We can pass locales as a prop to the getStaticPaths
function and Next.js will send the array of all configured locales. We can also update paths to start as an empty array:
export const getStaticPaths = async ({locales}) => {const paths = [];...
Now we have the ability to access each locale we need to update our paths
variable to include the locale
. We will need to map over each locale so we can create a path for each one.
postsResponse.postConnection.edges.map(post => {// ensure a `path` is created for each `locale`locales.map(locale => {paths.push({params: { slug: post.node._sys.filename },locale,})})})
The completed getStaticPaths
should look like this:
export const getStaticPaths = async ({ locales }) => {const paths = []const postsResponse = await staticRequest({query: `{postConnection {edges {node {_sys {filename}}}}}`,variables: {},})postsResponse.postConnection.edges.map(post => {// ensure a `path` is created for each `locale`locales.map(locale => {paths.push({params: { slug: post.node._sys.filename },locale,})})})return {paths,fallback: 'blocking',}}
getStaticProps
We need to make a small change to our getStaticProps
function to look for the locale and add that to the relative path so we are editing the correct file.
++ relativePath: `${ctx.locale}/${ctx.params.slug}.md`,-- relativePath: `${ctx.params.slug}.md`,
With this change, we can now open any of the support locale URLs. Our application is now ready to support our locales, but how do we create new files for each locale?
To create our files we are going to leverage a filename structure of <locale>/posname
the locale will be handled by Next.js So a filename of fr/bonjour
will be treated as <domain>/fr/another-post
in your Next.js application.
Below is an example of the file structure.
The best way to keep up with Tina is to subscribe to our newsletter. We send out updates every two weeks. Updates include new features, what we have been working on, blog posts you may have missed, and more!
You can subscribe by following this link and entering your email: https://tina.io/community/
Tina has a community Discord full of Jamstack lovers and Tina enthusiasts. When you join, you will find a place:
Our Twitter account (@tinacms) announces the latest features, improvements, and sneak peeks to Tina. We would also be psyched if you tagged us in projects you have built.
© TinaCMS 2019–2024