How to structure translations

In my current project, it was clear from the beginning that our customers would need the application in several languages. So it was smart to integrate internationalization from the beginning to avoid having to refactor all the templates later.

One question that pops up immediately when putting together a first localized version of a frontend application is: How do I organize the translations file(s) best, so that it doesn’t start to get really messy after a short time?

In my opinion there are two main possibilities to do this (let me know if you have different approaches!):

First option: group the translations per page

This might look like this:

home: {
  key1: "translation",
  key2: "translation"
},
page1: { ... },
page2: { ... },
contact: { ... }

Advantages of this are that it can be started right away without overthinking. If you don’t have an idea yet how your app is going to be structured when it’s finished, this might be a good choice because you can start with one page, then add another and so on. That’s why I would call this approach more agile. You might end up repeating the same translations over and over again though, because the same translations might appear in several pages.

Second option: group the translations logically

Example:

titles: { ... },
actions: {
  edit: "edit",
  delete: "delete"
},
forms: {
  labels: { ... },
  placeholder: { ... },
  validationWarnings: { ... }
},
runningText: { ... }

Advantages of this approach are that it makes maintenance easier IF the wording and structure of the page is already well defined. If you start implementing this, but the structure of your application is still subject to a lot of change, this might cause more work than it saves you because on every change you might end up having to refactor a large part of your translation file. Also you might be tempted to always reuse the same translation keys for the same translations because you think that they represent the same translations logically but then it turns out that they don’t and you have to refactor to be able to use two different ones.

Combining the two approaches

Why don’t we go for a combination of the two? That way we get the best of the two worlds. We have the flexibility of being able to apply bigger changes quickly by adding or removing pages, but at the same time we have a semantic way to organize our translations and we always know where to put everything. That means we might need to duplicate the same translations here and there for different pages, but we also stay very flexible. A translation file now could look like this:

page1: {
  runningText: { ... },
  titles: { ... },
  actions: { ... }
},
page2: {
  runningText: { ... },
  titles: { ... },
  actions: { ... }
},
footer: { ... }

... or we do it the other way round ...

titles: {
  page1: { ... },
  page2: { ... }
},
forms: {
  page1: { ... },
  page2: { ... }
},
actions: {

}

Conclusion

Well, there is not really a conclusion. The best choice differs from project to project. Since I mostly work in startup environments I would always begin with the per page approach, because usually in the beginning you don't even know what you are building. Once the project is more established and well defined, and maybe before actually translating the application to another language, it could make sense to reorganize the translations into a logical structure. That way the application stays easier to maintain and it might be also more efficient to translate because you don't have so much repetition. A combination of the two approaches might also always make sense because you always stay flexible.

Of course all of this is also applicable if you have several translation files for different modules of your application, but so far my projects were small enough so that one file was always sufficient.