Localization in Vue 2.0 single file components without using an i18n library

This post is a quick note on localization. Recently I needed to add some localization features to a frontend project running Vue 2.0. Why not just use an i18n package? That would probably have been a good thing to do, but those I found either had confusing documentation, a high number of old unresolved issues on Github, or warnings from npm audit. And my needs were very simple: translate a few text blocks.

Localization is not always easy – how hard is it to get it done without extra dependencies?

Starting simple

Let’s start with a simple Vue app in a single HTML file using a CDN to load Vue.

        <!-- Import VueJS in dev version from CDN -->
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <title>Vue Translation</title>
        <div id="app">
                {{ translations.en.hello }}
            var app = new Vue({
                el: '#app',
                data: {
                    message: 'Hello Vue!',
                    translations: {
                        en: {
                            "hello": "Hello World"
                        no: {
                            "hello": "Hallo Verden"
                        de: {
                            "hello": "Guten Tag, Welt!"
                    locale: 'en'

This will render the English version of “Hello World”. Let us first consider how we are going to get the right text for our locale dynamically. We need a function to load that. Let’s create a methods section in our Vue app, and add a get_text() function:

   {{ get_text('hello') }}
var app = new Vue({
  el: '#app',
  data: {
  methods () {
    get_text (textbit) {
      return this.translations[this.locale][textbit]

OK – so this works, now we are only missing a way to set the preferred language. A simple way for this example is to add a button that sets it when clicked. To make the choice persistent we can save the choice to localStorage.

If you want the example file, you can download it from github.com. It is also published here so you can see it in action.

Translation – is this a good approach?

The answer to that is probably yes and no – it depends on your needs. Here’s what you will miss out on that a good i18n library would solve for you:

  • Dynamic tagging of translation links inline in templates. Making it easier to generate localization files for translators automatically.
  • Pluralization: getting grammar right can be hard. Going from one to several things is hard enough in English – but other languages may be much more difficult to translate because of more variation in the way words and phrases are used in different contexts.

The good things are: no dependencies, and you can use the data structure you want. Giving JSON files to translators works, just show them where to insert the translated strings.

Tip: use `string` for strings instead of ‘string’ or “string”. This makes multiline strings directly usable in your .vue files or .js files.

What about single-file components?

You can use this approach in single-file components without modification. A few notes:

  • Consider using a Vuex store to share state across components instead of relying on localStorage
  • It is probably a good idea to create a global translation file for things that are used in many components, to avoid repeating the same translation many times
  • Finally – if your translation needs are complicated, it is probably better to go with a well maintained i18n library. If you can find one.

3 thoughts on “Localization in Vue 2.0 single file components without using an i18n library

  1. Just to say “tusen takk” to you 😀

    I can’t run node js in my web hosting, just html – js vanilla, so your tuto is soooo usefull xD

    I just have modified a little bit your code to get the browser lang and also to have a default language (if I don’t have the translate for one of the lang, I get it in english)


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s