Nuxt3 internationalization: You don't need a plugin for that.

I have started to embrace the build-it-yourself first before using a plugin idea. Most of the time, your problem is more straightforward, and a "do it all" plugin will likely be overkill.

When we started with our Nuxt3 development, we built eight months before the actual stable release. It came with its challenges; mostly, there would be no working plugins, which let us develop solutions for ourselves.

I created a simple solution for the internationalization plugin, which was relatively easy to make.

Why would you build yourself?

Before I show a demo and explain the code, let's discuss why you should develop it and when to go for a plugin.

✅ Pro: upgrading is painless
Internationalization is a stateless plugin; it doesn't update much unless a new feature arrives, but a simple version will last you for years without needing to change, so why look at a changelog to figure out if it would still work?

✅ Pro: complete control over how it works
You own the code and understand the inner works, which helps you adjust to your personal needs; maybe you are not a fan of $t() and instead have it work differently, or possibly you are used to $i() you can name it however you and your team wants it.

✅ Pro: just enough code
If you want a translation with a toggle, it is simple enough to make it ourselves; the code will be tiny compared to some solutions out there that might support multiple frameworks with all their unique ways of reactivity.

❌ Con: there might be a more efficient implementation
This plugin is just part of a bigger problem, and spending day and night optimizing for that framework with all bells and whistles might be too much.

❌ Con: path based translation
very common to do translations based on paths, /en/homepage and /es/homepage. While this is not hard, I don't have that requirement so it won't be in the example code.

Coding time

Three parts need to be looked at:

plugins/i18n.ts is where all the logic is, and here is where you will import the translation files stored in lang/ directory. There is also an optional plugin (plugins/language.server.ts) that will work if SSR is enabled, it will read the accept-language header and check if it can toggle to the preferred language, or it will read the cookie set with that language of choice when the user toggled to their language.

In the composable, we will store the language the user has selected in a useLang(), which we will toggle within our app to be the language the user wants to see.

You will write your JSON translations in the lang/ directory. Writing the JSON should be very straightforward, and you can use nested or array-like entries home: { title:'...'} or titles: ['...','...','...'].

The last part to look at is the component itself. The component/LangToggle.vue is just a simple toggle between languages, which sets the language that we store in the composable useLang(). The optional code here is where we set the cookie so the server can read the language in advance before serving any content in the future.


I hope you found this short helpful/educational and will use it in your next project or have learned something about how a simple translation plugin would work.

© 2023 Max van der Schee