Skip to content

Latest commit

 

History

History
192 lines (155 loc) · 5.49 KB

MIGRATING_FROM_V3_TO_V4.md

File metadata and controls

192 lines (155 loc) · 5.49 KB

Migrating from v3 to v4

I18n-js v4 is a breaking change release and diverges quite a lot from how the previous version worked. This guides summarizes the process of upgrading an app that uses i18n-js v3 to v4.

Development

Previously, you could use a middleware to export translations (some people even used this in production 😬). In development, you can now use whatever your want, because i18n-js doesn't make any assumptions. All you need to do is running i18n export, either manually or by using something that listens to file changes.

If you like watchman, you can use something like this:

#!/usr/bin/env bash

root=`pwd`

watchman watch-del "$root"
watchman watch-project "$root"
watchman trigger-del "$root" i18n

watchman -j <<-JSON
[
  "trigger",
  "$root",
  {
    "name": "i18n",
    "expression": [
      "anyof",
      ["match", "config/locales/**/*.yml", "wholename"],
      ["match", "config/locales/**/*.po", "wholename"],
      ["match", "config/i18n.yml", "wholename"]
    ],
    "command": ["i18n", "export"]
  }
]
JSON

# If you're running this through Foreman, then uncomment the following lines:
# while true; do
#   sleep 1
# done

You can also use guard. Make sure you have both guard and guard-compat installed and use Guardfile file with the following contents:

guard(:"i18n-js",
      run_on_start: true,
      config_file: "./config/i18n.yml",
      require_file: "./config/environment.rb") do
  watch(%r{^config/locales/.+\.(yml|po)$})
  watch(%r{^config/i18n.yml$})
  watch("Gemfile")
end

To run guard, use guard start -i.

Finally, you can use listen. Create the file config/initializers/i18n.rb with the following content:

Rails.application.config.after_initialize do
  require "i18n-js/listen"
  # This will only run in development.
  I18nJS.listen
end

Warning:

No matter which approach you choose, the idea is that you precompile your translations when going to production. DO NOT RUN any of the above in production.

Exporting translations

The build process for i18n now relies on an external CLI called i18n. All you need to do is executing i18n export in your build step to generate the json files for your translations.

Using your translations

The JavaScript package is now a separate thing and need to be installed using your favorite tooling (e.g. yarn, npm, pnpm, etc).

$ yarn add i18n-js@latest
$ npm i --save-dev i18n-js@latest

From now on, the way you load translations and set up I18n-js is totally up to you, but means you need to load the json files and attach to the I18n-js instance. This is how I do it in a project I'm doing right now (Rails 7 + esbuild + TypeScript). First, we need to load the I18n-js configuration from the main JavaScript file:

// app/javascript/application.ts
import { i18n } from "./config/i18n";

Then we need to load our translations and instantiate the I18n-js class.

// app/javascript/config/i18n.ts
import { I18n } from "i18n-js";
import translations from "translations.json";

// Fetch user locale from html#lang.
// This value is being set on `app/views/layouts/application.html.erb` and
// is inferred from `ACCEPT-LANGUAGE` header.
const userLocale = document.documentElement.lang;

export const i18n = new I18n();
i18n.store(translations);
i18n.defaultLocale = "en";
i18n.enableFallback = true;
i18n.locale = userLocale;

The best thing about the above is that it is a pretty straightforward pattern in the JavaScript community. It doesn't rely on specific parts from Sprockets (I'm not even using it on my projects) or eRb files.

Ruby on Rails

Upgrading the configuration file

The configuration file loaded from config/i18n.yml has changed. Given the v3 configuration below

---
translations:
  - file: "app/assets/javascripts/date_formats.js"
    only: "*.date.formats"
  - file: "app/assets/javascripts/other.js"
    only: ["*.activerecord", "*.admin.*.title"]
  - file: "app/assets/javascripts/everything_else.js"
    except:
      - "*.activerecord"
      - "*.admin.*.title"
      - "*.date.formats"

the equivalent configuration file for v4 would be

---
translations:
  - file: "app/assets/javascripts/date_formats.js"
    patterns:
      - "*.date.formats"
  - file: "app/assets/javascripts/other.js"
    patterns:
      - "*.activerecord"
      - "*.admin.*.title"
  - file: "app/assets/javascripts/everything_else.js"
    patterns:
      # Notice the exclamation mark.
      - "*"
      - "!*.activerecord"
      - "!*.admin.*.title"
      - "!*.date.formats"

Other configuration options:

  • export_i18n_js: replaced by export_files plugin
  • fallbacks: replaced by embed_fallback_translations plugin
  • js_available_locales: removed (on v4 you can use groups, like in {pt-BR,en}.*)
  • namespace: removed without an equivalent
  • sort_translation_keys: removed (on v4 keys will always be sorted)
  • translations[].prefix: removed without an equivalent
  • translations[].pretty_print: removed (on v4 files will always be exported in a readable format)

Placeholders

Previously, v3 had the %{locale} placeholder, which can be used as part of the directory and/or file name. Now, the syntax is just :locale. Additionally, you can also use :digest, which uses a MD5 hex digest of the exported file.