i18n style
Tags: i18n, localization, webdev, vue
Published: 2022-01-26 16:46:20

---
title: i18n style
published: true
description: How to organise your translation files?
tags: i18n, localization, webdev, vue
cover_image: https://images.unsplash.com/photo-1539632346654-dd4c3cffad8c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80
---

### Style Guide

- key pattern: `<page>[.section].<component>[.attribute]`
- `camelCase` for multiple words

### Background


What are possible ways to map strings in JSON?

You would probably start with plain object:
```json
{
  "Login": "Login",
  "Logout": "Logout",
  "New post": "New post",
}
```

And you will create same file for each language, just changing values with translations.

But what if you decide later to change `New post` to `Add post`? You will need to change the key in all language files and in all source code files.

Alternative way is to use more abstract keys, that gives you more flexibility. For example:

```json
{
  "login": "Login",
  "logout": "Logout",
  "new": "New post",
}
```

And what if you now have another feature: `Add event`? You alternatives are:
1) make complex keys
2) group by meaning

Complex-word keys would be:
```json
{
  "login": "Login",
  "logout": "Logout",
  "newPost": "New post",
  "newEvent": "New event",
}
```

And what if now you have a login screen, which has a title, subtitle, 2 fields and submit button?
You might do this:

```json
{
  "loginTitle": "Login",
  "loginSubtitle": "Please login to continue",
  "loginSubmit": "Continue",
  "logout": "Logout",
  "newPost": "New post",
  "newEvent": "New event",
}
```

And what if you have a registration screen which have similar elements?

```json
{
  "loginTitle": "Login",
  "loginSubtitle": "Please login to continue",
  "loginSubmit": "Continue",
  "registerTitle": "Registration",
  "registerSubtitle": "Create new account",
  "registerSubmit": "Start",
  "logout": "Logout",
  "newPost": "New post",
  "newEvent": "New event",
}
```

As you see translation file grows exponentially. You can make life easier for developers and translators by grouping keys:

```json
{
  "login": {
    "title": "Login",
    "subtitle": "Please login to continue",
    "submit": "Continue",
  },
  "register": {
    "title": "Registration",
    "subtitle": "Create new account",
    "submit": "Start",
  },
  "logout": "Logout",
  "post": {
    "new": "New post"
  },
  "event": {
    "new": "New event"
  }
}
```

When grouping elements look for similarities, what those elements have in common and how it would scale.

Input element can have label, placeholder, error. Those are attributes of that element, so it make sense to group values by element name, i.e. in our login screen:

```json
{
  "login": {
    "title": "Login",
    "subtitle": "Please login to continue",
    "submit": "Continue",
    "username": {
      "label": "Enter your username",
      "placeholder": "JohnDoe",
      "error": "Username is a required field",
    }
  },
}
```

But what if there are more error messages later? If we need to add error message for complexity validation (i.e. "Please use numbers, letters, special symbols"). Both are errors, so we would group them under errors.

### How does this look in YML?

YML looks similar to JSON, just without curly brackets:

```yml
login:
  title: Login
  subtitle: Please login to continue
  submit: Continue
  username:
    label: Enter your username
    placeholder: JohnDoe
    error: Username is a required field
```

or you can also do it per line:

```yml
login.title: Login
login.subtitle: Please login to continue
login.submit: Continue
login.username.label: Enter your username
login.username.placeholder: JohnDoe
login.username.error: Username is a required field
```

Last one have few benefits:

- It's easier to review PRs having the whole context, and not just seeing some part of bigger object
- It's easier to find string from `t()` function in the translations

But also you could mix up `login` and `login.title` and destroy the object without even noticing it.

### More on this topic:

- https://dev.to/omaiboroda/three-ways-to-name-i18n-translation-keys-2fed
- https://medium.com/frontmen/web-internationalisation-i18n-lessons-ive-learned-the-hard-way-438a3e157e0
- https://lokalise.com/blog/translation-keys-naming-and-organizing/
- https://phrase.com/blog/posts/ruby-lessons-learned-naming-and-managing-rails-i18n-keys/