i18n-js 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b2fdace9fca14d471ff34c3b24055d4093d82ce2a1f72f2df06364a98454a31
4
- data.tar.gz: 9ea6bd71626357c8fce24c28e991b9edc96f8a3230e55c4d55cf1dec3813c94e
3
+ metadata.gz: 60f1ad0e9477d8e6570573f64ac2a55136653da8e4791c6fc32e69c9547e197b
4
+ data.tar.gz: d46a3d8b8a25020635d9c108b2cb2caf3a256e419112a21a0d986f94e1e19c37
5
5
  SHA512:
6
- metadata.gz: 2c8da0348d02f04d805a013dadd24beb08fb7de555bfdded51e4e6c7c29ba392978a723b7e95be9d752dda2b35bbe6d6aefe4d4cf9166c1ddca09f003712533f
7
- data.tar.gz: 882af1975b1f2e479ad4d8bdcbe812175fae165c80a2f915223e14fc71fb0b3236774254e103754169eab5a3d577e219e10803fd05e14fa3bac82471e4c770e1
6
+ metadata.gz: a1d63d094866a836a69a9b3fc8f2989608a1b794daf5d5c82062e17b3bcb07ab7fb0ec8f2c05aa27a2585236cff33d974c313ca81be96de129340ecce8f78490
7
+ data.tar.gz: 7ec126b41663f765a421950c1ddcb215d460681355088fc77731673c44f3baf590cc58c6e5841bc9dda6f58732249488cdad3b020287b57d7d1de70cf8e95716
@@ -9,12 +9,15 @@ on:
9
9
 
10
10
  jobs:
11
11
  build:
12
- name: Tests with Ruby ${{ matrix.ruby }} and ${{ matrix.gemfile }}
12
+ name:
13
+ Tests with Ruby ${{ matrix.ruby }}, Node ${{ matrix.node }} and ${{
14
+ matrix.gemfile }}
13
15
  runs-on: "ubuntu-latest"
14
16
  strategy:
15
17
  fail-fast: false
16
18
  matrix:
17
19
  ruby: ["2.7", "3.0", "3.1"]
20
+ node: ["16", "18"]
18
21
  gemfile:
19
22
  - Gemfile
20
23
  if: |
@@ -32,6 +35,23 @@ jobs:
32
35
  ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
33
36
  hashFiles(matrix.gemfile) }}
34
37
 
38
+ - uses: actions/cache@v3
39
+ id: npm-cache
40
+ with:
41
+ path: vendor/bundle
42
+ key: >
43
+ ${{ runner.os }}-${{ matrix.node }}-npm-${{
44
+ hashFiles('package.json') }}
45
+
46
+ - name: Set up Node
47
+ uses: actions/setup-node@v2-beta
48
+ with:
49
+ node-version: ${{ matrix.node }}
50
+
51
+ - name: Install npm dependencies
52
+ run: |
53
+ yarn install
54
+
35
55
  - name: Set up Ruby
36
56
  uses: ruby/setup-ruby@v1
37
57
  with:
@@ -49,4 +69,5 @@ jobs:
49
69
  env:
50
70
  BUNDLE_GEMFILE: ${{ matrix.gemfile }}
51
71
  run: |
72
+ yarn compile
52
73
  bundle exec rake
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
  /vendor/
10
10
  *.log
11
11
  *.lock
12
+ /lib/**/*.js
13
+ /test/output
data/.rubocop.yml CHANGED
@@ -14,3 +14,6 @@ Naming/FileName:
14
14
  Exclude:
15
15
  - lib/i18n-js.rb
16
16
  - lib/guard/i18n-js.rb
17
+
18
+ Style/PerlBackrefs:
19
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -11,6 +11,25 @@ Prefix your message with one of the following:
11
11
  - [Security] in case of vulnerabilities.
12
12
  -->
13
13
 
14
- ## Jul 29, 2022
14
+ ## v4.1.0 - Dec 09, 2022
15
+
16
+ - [Added] Parse configuration files as erb.
17
+ - [Changed] `I18n.listen(run_on_start:)` was added to control if files should be
18
+ exported during `I18n.listen`'s boot. The default value is `true`.
19
+ - [Added] Now it's possible to transform translations before exporting them
20
+ using a stable plugin api.
21
+ - [Deprecated] The `i18n check` has been deprecated. Use
22
+ `i18n lint:translations` instead.
23
+ - [Added] Use `i18n lint:scripts` to lint JavaScript/TypeScript.
24
+ - [Fixed] Expand paths passed to `I18nJS.listen(locales_dir:)`.
25
+
26
+ ## v4.0.1 - Aug 25, 2022
27
+
28
+ - [Fixed] Shell out export to avoid handling I18n reloading heuristics.
29
+ - [Changed] `I18nJS.listen` now accepts a directories list to watch.
30
+ - [Changed] `I18nJS.listen` now accepts
31
+ [listen](https://rubygems.org/gems/listen) options via `:options`.
32
+
33
+ ## v4.0.0 - Jul 29, 2022
15
34
 
16
35
  - Official release of i18n-js v4.0.0.
@@ -0,0 +1,191 @@
1
+ # Migrating from v3 to v4
2
+
3
+ I18n-js v4 is a breaking change release and diverges quite a lot from how the
4
+ previous version worked. This guides summarizes the process of upgrading an app
5
+ that uses i18n-js v3 to v4.
6
+
7
+ ## Development
8
+
9
+ Previously, you could use a middleware to export translations (some people even
10
+ used this in production 😬). In development, you can now use whatever your want,
11
+ because i18n-js doesn't make any assumptions. All you need to do is running
12
+ `i18n export`, either manually or by using something that listens to file
13
+ changes.
14
+
15
+ If you like watchman, you can use something like this:
16
+
17
+ ```bash
18
+ #!/usr/bin/env bash
19
+
20
+ root=`pwd`
21
+
22
+ watchman watch-del "$root"
23
+ watchman watch-project "$root"
24
+ watchman trigger-del "$root" i18n
25
+
26
+ watchman -j <<-JSON
27
+ [
28
+ "trigger",
29
+ "$root",
30
+ {
31
+ "name": "i18n",
32
+ "expression": [
33
+ "anyof",
34
+ ["match", "config/locales/**/*.yml", "wholename"],
35
+ ["match", "config/locales/**/*.po", "wholename"],
36
+ ["match", "config/i18n.yml", "wholename"]
37
+ ],
38
+ "command": ["i18n", "export"]
39
+ }
40
+ ]
41
+ JSON
42
+
43
+ # If you're running this through Foreman, then uncomment the following lines:
44
+ # while true; do
45
+ # sleep 1
46
+ # done
47
+ ```
48
+
49
+ You can also use guard. Make sure you have both
50
+ [guard](https://rubygems.org/packages/guard) and
51
+ [guard-compat](https://rubygems.org/packages/guard-compat) installed and use
52
+ Guardfile file with the following contents:
53
+
54
+ ```ruby
55
+ guard(:"i18n-js",
56
+ run_on_start: true,
57
+ config_file: "./config/i18n.yml",
58
+ require_file: "./config/environment.rb") do
59
+ watch(%r{^config/locales/.+\.(yml|po)$})
60
+ watch(%r{^config/i18n.yml$})
61
+ watch("Gemfile")
62
+ end
63
+ ```
64
+
65
+ To run guard, use `guard start -i`.
66
+
67
+ Finally, you can use [listen](https://rubygems.org/gems/listen). Create the file
68
+ `config/initializers/i18n.rb` with the following content:
69
+
70
+ ```ruby
71
+ Rails.application.config.after_initialize do
72
+ require "i18n-js/listen"
73
+ # This will only run in development.
74
+ I18nJS.listen
75
+ end
76
+ ```
77
+
78
+ > **Warning**:
79
+ >
80
+ > No matter which approach you choose, the idea is that you _precompile_ your
81
+ > translations when going to production. DO NOT RUN any of the above in
82
+ > production.
83
+
84
+ ## Exporting translations
85
+
86
+ The build process for i18n now relies on an external CLI called `i18n`. All you
87
+ need to do is executing `i18n export` in your build step to generate the json
88
+ files for your translations.
89
+
90
+ ## Using your translations
91
+
92
+ The JavaScript package is now a separate thing and need to be installed using
93
+ your favorite tooling (e.g. yarn, npm, pnpm, etc).
94
+
95
+ ```console
96
+ $ yarn add i18n-js@latest
97
+ $ npm i --save-dev i18n-js@latest
98
+ ```
99
+
100
+ From now on, the way you load translations and set up I18n-js is totally up to
101
+ you, but means you need to load the json files and attach to the I18n-js
102
+ instance. This is how I do it in a project I'm doing right now (Rails 7 +
103
+ esbuild + TypeScript). First, we need to load the I18n-js configuration from the
104
+ main JavaScript file:
105
+
106
+ ```typescript
107
+ // app/javascript/application.ts
108
+ import { i18n } from "./config/i18n";
109
+ ```
110
+
111
+ Then we need to load our translations and instantiate the I18n-js class.
112
+
113
+ ```typescript
114
+ // app/javascript/config/i18n.ts
115
+ import { I18n } from "i18n-js";
116
+ import translations from "translations.json";
117
+
118
+ // Fetch user locale from html#lang.
119
+ // This value is being set on `app/views/layouts/application.html.erb` and
120
+ // is inferred from `ACCEPT-LANGUAGE` header.
121
+ const userLocale = document.documentElement.lang;
122
+
123
+ export const i18n = new I18n();
124
+ i18n.store(translations);
125
+ i18n.defaultLocale = "en";
126
+ i18n.enableFallback = true;
127
+ i18n.locale = userLocale;
128
+ ```
129
+
130
+ The best thing about the above is that it is a pretty straightforward pattern in
131
+ the JavaScript community. It doesn't rely on specific parts from Sprockets (I'm
132
+ not even using it on my projects) or eRb files.
133
+
134
+ ## Ruby on Rails
135
+
136
+ ### Upgrading the configuration file
137
+
138
+ The configuration file loaded from `config/i18n.yml` has changed. Given the v3
139
+ configuration below
140
+
141
+ ```yaml
142
+ ---
143
+ translations:
144
+ - file: "app/assets/javascripts/date_formats.js"
145
+ only: "*.date.formats"
146
+ - file: "app/assets/javascripts/other.js"
147
+ only: ["*.activerecord", "*.admin.*.title"]
148
+ - file: "app/assets/javascripts/everything_else.js"
149
+ except:
150
+ - "*.activerecord"
151
+ - "*.admin.*.title"
152
+ - "*.date.formats"
153
+ ```
154
+
155
+ the equivalent configuration file for v4 would be
156
+
157
+ ```yaml
158
+ ---
159
+ translations:
160
+ - file: "app/assets/javascripts/date_formats.js"
161
+ patterns:
162
+ - "*.date.formats"
163
+ - file: "app/assets/javascripts/other.js"
164
+ patterns:
165
+ - "*.activerecord"
166
+ - "*.admin.*.title"
167
+ - file: "app/assets/javascripts/everything_else.js"
168
+ patterns:
169
+ # Notice the exclamation mark.
170
+ - "!*.activerecord"
171
+ - "!*.admin.*.title"
172
+ - "!*.date.formats"
173
+ ```
174
+
175
+ Other configuration options:
176
+
177
+ - `export_i18n_js`: removed without an equivalent
178
+ - `fallbacks`: removed without an equivalent
179
+ - `js_available_locales`: removed (on v4 you can use groups, like in
180
+ `{pt-BR,en}.*`)
181
+ - `namespace`: removed without an equivalent
182
+ - `sort_translation_keys`: removed (on v4 keys will always be sorted)
183
+ - `translations[].prefix`: removed without an equivalent
184
+ - `translations[].pretty_print`: removed (on v4 files will always be exported in
185
+ a readable format)
186
+
187
+ ### Placeholders
188
+
189
+ Previously, v3 had the `%{locale}` placeholder, which can be used as part of the
190
+ directory and/or file name. Now, the syntax is just `:locale`. Additionally, you
191
+ can also use `:digest`, which uses a MD5 hex digest of the exported file.
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img width="250" height="58" src="https://github.com/fnando/i18n-js/raw/main/i18njs.png" alt="i18n.js">
2
+ <img width="250" height="58" src="https://github.com/fnando/i18n-js/raw/main/images/i18njs.png" alt="i18n.js">
3
3
  </p>
4
4
 
5
5
  <p align="center">
@@ -12,14 +12,14 @@
12
12
  <small>
13
13
  Oh, you don't use Ruby? No problem! You can still use i18n-js
14
14
  <br>
15
- and the
16
- <a href="https://www.npmjs.com/package/i18n-js/v/next">companion JavaScript package</a>.
15
+ and the
16
+ <a href="https://www.npmjs.com/package/i18n-js/v/latest">companion JavaScript package</a>.
17
17
  </small>
18
18
  </p>
19
19
 
20
20
  <p align="center">
21
21
  <a href="https://github.com/fnando/i18n-js"><img src="https://github.com/fnando/i18n-js/workflows/ruby-tests/badge.svg" alt="Tests"></a>
22
- <a href="https://rubygems.org/gems/i18n-js"><img src="https://img.shields.io/gem/v/i18n-js.svg?include_prereleases" alt="Gem"></a>
22
+ <a href="https://rubygems.org/gems/i18n-js"><img src="https://img.shields.io/gem/v/i18n-js.svg" alt="Gem"></a>
23
23
  <a href="https://rubygems.org/gems/i18n-js"><img src="https://img.shields.io/gem/dt/i18n-js.svg" alt="Gem"></a>
24
24
  <a href="https://tldrlegal.com/license/mit-license"><img src="https://img.shields.io/:License-MIT-blue.svg" alt="MIT License"></a>
25
25
  </p>
@@ -45,6 +45,14 @@ About patterns:
45
45
  - `*.messages.*`
46
46
  - Patterns starting with `!` are excluded.
47
47
  - `!*.activerecord.*` will exclude all ActiveRecord translations.
48
+ - You can use groups:
49
+ - `{pt-BR,en}.js.*` will include only `pt-BR` and `en` translations, even if
50
+ more languages are available.
51
+
52
+ > **Note**:
53
+ >
54
+ > Patterns use [glob](https://rubygems.org/gems/glob), so check it out for the
55
+ > most up-to-date documentation about what's available.
48
56
 
49
57
  The config file:
50
58
 
@@ -68,6 +76,22 @@ The output path can use the following placeholders:
68
76
  - `:locale`: the language that's being exported.
69
77
  - `:digest`: the MD5 hex digest of the exported file.
70
78
 
79
+ The config file is processed as erb, so you can have dynamic content on it if
80
+ you want. The following example shows how to use groups from a variable.
81
+
82
+ ```yml
83
+ ---
84
+ <% group = "{en,pt}" %>
85
+
86
+ translations:
87
+ - file: app/frontend/translations.json
88
+ patterns:
89
+ - "<%= group %>.*"
90
+ - "!<%= group %>.activerecord"
91
+ - "!<%= group %>.errors"
92
+ - "!<%= group %>.number.nth"
93
+ ```
94
+
71
95
  The Ruby API:
72
96
 
73
97
  ```ruby
@@ -88,7 +112,9 @@ Commands:
88
112
  - init: Initialize a project
89
113
  - export: Export translations as JSON files
90
114
  - version: Show package version
91
- - check: Check for missing translations
115
+ - plugins: List plugins that will be activated
116
+ - lint:translations: Check for missing translations
117
+ - lint:scripts: Lint files using TypeScript
92
118
 
93
119
  Run `i18n COMMAND --help` for more information on specific commands.
94
120
  ```
@@ -97,14 +123,126 @@ By default, `i18n` will use `config/i18n.yml` and `config/environment.rb` as the
97
123
  configuration files. If you don't have these files, then you'll need to specify
98
124
  both `--config` and `--require`.
99
125
 
126
+ ### Plugins
127
+
128
+ #### Built-in plugins:
129
+
130
+ ##### `embed_fallback_translations`:
131
+
132
+ Embed fallback translations inferred from the default locale. This can be useful
133
+ in cases where you have multiple large translation files and don't want to load
134
+ the default locale together with the target locale.
135
+
136
+ To use it, add the following to your configuration file:
137
+
138
+ ```yaml
139
+ embed_fallback_translations:
140
+ enabled: true
141
+ ```
142
+
143
+ #### Plugin API
144
+
145
+ You can transform the exported translations by adding plugins. A plugin must
146
+ inherit from `I18nJS::Plugin` and can have 3 class methods. The following
147
+ example shows how the built-in `embed_fallback_translations` plugin is
148
+ implemented.
149
+
150
+ ```ruby
151
+ # frozen_string_literal: true
152
+
153
+ module I18nJS
154
+ require "i18n-js/plugin"
155
+
156
+ class EmbedFallbackTranslationsPlugin < I18nJS::Plugin
157
+ CONFIG_KEY = :embed_fallback_translations
158
+
159
+ # This method must set up the basic plugin configuration, like adding the
160
+ # config's root key in case your plugin accepts configuration (defined via
161
+ # the config file).
162
+ #
163
+ # If you don't add this key, the linter will prevent non-default keys from
164
+ # being added to the configuration file.
165
+ def self.setup
166
+ I18nJS::Schema.root_keys << CONFIG_KEY
167
+ end
168
+
169
+ # In case your plugin accepts configuration, this is where you must validate
170
+ # the configuration, making sure only valid keys and type is provided.
171
+ # If the configuration contains invalid data, then you must raise an
172
+ # exception using something like
173
+ # `raise I18nJS::Schema::InvalidError, error_message`.
174
+ def self.validate_schema(config:)
175
+ return unless config.key?(CONFIG_KEY)
176
+
177
+ plugin_config = config[CONFIG_KEY]
178
+ valid_keys = %i[enabled]
179
+ schema = I18nJS::Schema.new(config)
180
+
181
+ schema.expect_required_keys(valid_keys, plugin_config)
182
+ schema.reject_extraneous_keys(valid_keys, plugin_config)
183
+ schema.expect_enabled_config(CONFIG_KEY, plugin_config[:enabled])
184
+ end
185
+
186
+ # This method is responsible for transforming the translations. The
187
+ # translations you'll receive may be already be filtered by other plugins
188
+ # and by the default filtering itself. If you need to access the original
189
+ # translations, use `I18nJS.translations`.
190
+ #
191
+ # Make sure you always check whether your plugin is active before
192
+ # transforming translations; otherwise, opting out transformation won't be
193
+ # possible.
194
+ def self.transform(translations:, config:)
195
+ return translations unless config.dig(CONFIG_KEY, :enabled)
196
+
197
+ translations_glob = Glob.new(translations)
198
+ translations_glob << "*"
199
+
200
+ mapping = translations.keys.each_with_object({}) do |locale, buffer|
201
+ buffer[locale] = Glob.new(translations[locale]).tap do |glob|
202
+ glob << "*"
203
+ end
204
+ end
205
+
206
+ default_locale = I18n.default_locale
207
+ default_locale_glob = mapping.delete(default_locale)
208
+ default_locale_paths = default_locale_glob.paths
209
+
210
+ mapping.each do |locale, glob|
211
+ missing_keys = default_locale_paths - glob.paths
212
+
213
+ missing_keys.each do |key|
214
+ components = key.split(".").map(&:to_sym)
215
+ fallback_translation = translations.dig(default_locale, *components)
216
+
217
+ next unless fallback_translation
218
+
219
+ translations_glob.set([locale, key].join("."), fallback_translation)
220
+ end
221
+ end
222
+
223
+ translations_glob.to_h
224
+ end
225
+ end
226
+
227
+ I18nJS.register_plugin(EmbedFallbackTranslationsPlugin)
228
+ end
229
+ ```
230
+
231
+ To distribute this plugin, you need to create a gem package that matches the
232
+ pattern `i18n-js/*_plugin.rb`. You can test whether your plugin will be found by
233
+ installing your gem, opening a iRB session and running
234
+ `Gem.find_files("i18n-js/*_plugin.rb")`. If your plugin is not listed, then you
235
+ need to double check your gem load path and see why the file is not being
236
+ loaded.
237
+
100
238
  ### Listing missing translations
101
239
 
102
- To list missing and extraneous translations, you can use `i18n check`. This
103
- command will load your translations similarly to how `i18n export` does, but
104
- will output the list of keys that don't have a matching translation against the
105
- default locale. Here's an example:
240
+ To list missing and extraneous translations, you can use
241
+ `i18n lint:translations`. This command will load your translations similarly to
242
+ how `i18n export` does, but will output the list of keys that don't have a
243
+ matching translation against the default locale. Here's an example:
106
244
 
107
- ![`i18n check` command in action](https://github.com/fnando/i18n-js/raw/main/images/i18njs-check.gif)
245
+ ![`i18n lint:translations` command in action](https://github.com/fnando/i18n-js/raw/main/images/i18njs-check.gif)
108
246
 
109
247
  This command will exist with status 1 whenever there are missing translations.
110
248
  This way you can use it as a CI linting.
@@ -125,19 +263,97 @@ translations:
125
263
  patterns:
126
264
  - "*"
127
265
 
128
- check:
266
+ lint_translations:
129
267
  ignore:
130
268
  - en.mailer.login.subject
131
269
  - en.mailer.login.body
132
270
  ```
133
271
 
134
- > **Note**: In order to avoid mistakenly ignoring keys, this configuration
135
- > option only accepts the full translation scope, rather than accepting a
136
- > pattern like `pt.ignored.scope.*`.
272
+ > **Note**:
273
+ >
274
+ > In order to avoid mistakenly ignoring keys, this configuration option only
275
+ > accepts the full translation scope, rather than accepting a pattern like
276
+ > `pt.ignored.scope.*`.
277
+
278
+ ### Linting your JavaScript/TypeScript files
279
+
280
+ To lint your script files and check for missing translations (which can signal
281
+ that you're either using wrong scopes or forgot to add the translation), use
282
+ `i18n lint:scripts`. This command will parse your JavaScript/TypeScript files
283
+ and extract all scopes being used. This command requires a Node.js runtime. You
284
+ can either specify one via `--node-path`, or let the plugin infer a binary from
285
+ your `$PATH`.
286
+
287
+ The comparison will be made against the export JSON files, which means it'll
288
+ consider transformations performed by plugins (e.g. the output files may be
289
+ affected by `embed_fallback_translations` plugin).
290
+
291
+ The translations that will be extract must be called as one of the following
292
+ ways:
293
+
294
+ - `i18n.t(scope, options)`
295
+ - `i18n.translate(scope, options)`
296
+ - `t(scope, options)`
297
+
298
+ Notice that only literal strings can be used, as in `i18n.t("message")`. If
299
+ you're using dynamic scoping through variables (e.g.
300
+ `const scope = "message"; i18n.t(scope)`), they will be skipped.
301
+
302
+ ```console
303
+ $ i18n lint:scripts --config test/config/lint.yml --require test/config/require.rb
304
+ => Config file: "test/config/lint.yml"
305
+ => Require file: "test/config/require.rb"
306
+ => Node: "/Users/fnando/.asdf/shims/node"
307
+ => Available locales: [:en, :es, :pt]
308
+ => Patterns: ["!(node_modules)/**/*.js", "!(node_modules)/**/*.ts", "!(node_modules)/**/*.jsx", "!(node_modules)/**/*.tsx"]
309
+ => 9 translations, 11 missing, 4 ignored
310
+ - test/scripts/lint/file.js:1:1: en.js.missing
311
+ - test/scripts/lint/file.js:1:1: es.js.missing
312
+ - test/scripts/lint/file.js:1:1: pt.js.missing
313
+ - test/scripts/lint/file.js:2:8: en.base.js.missing
314
+ - test/scripts/lint/file.js:2:8: es.base.js.missing
315
+ - test/scripts/lint/file.js:2:8: pt.base.js.missing
316
+ - test/scripts/lint/file.js:4:8: en.js.missing
317
+ - test/scripts/lint/file.js:4:8: es.js.missing
318
+ - test/scripts/lint/file.js:4:8: pt.js.missing
319
+ - test/scripts/lint/file.js:6:1: en.another_ignore_scope
320
+ - test/scripts/lint/file.js:6:1: es.another_ignore_scope
321
+ ```
322
+
323
+ This command will list all locales and their missing translations. Avoid listing
324
+ a particular translation, you can set `lint.ignore` on your config file.
325
+
326
+ ```yaml
327
+ ---
328
+ translations:
329
+ - file: app/frontend/translations.json
330
+ patterns:
331
+ - "*"
332
+
333
+ lint_scripts:
334
+ ignore:
335
+ - ignore_scope # will ignore this scope on all languages
336
+ - pt.another_ignore_scope # will ignore this scope only on `pt`
337
+ ```
338
+
339
+ You can also set the patterns that will be looked up. By default, it scans all
340
+ JavaScript and TypeScript files that don't live on `node_modules`.
341
+
342
+ ```yaml
343
+ ---
344
+ translations:
345
+ - file: app/frontend/translations.json
346
+ patterns:
347
+ - "*"
348
+
349
+ lint:
350
+ patterns:
351
+ - "app/assets/**/*.ts"
352
+ ```
137
353
 
138
354
  ## Automatically export translations
139
355
 
140
- ### Using watchman
356
+ ### Using [watchman](https://facebook.github.io/watchman/)
141
357
 
142
358
  Create a script at `bin/i18n-watch`.
143
359
 
@@ -182,11 +398,11 @@ line to your Procfile:
182
398
  i18n: ./bin/i18n-watch
183
399
  ```
184
400
 
185
- ### Using guard
401
+ ### Using [guard](https://rubygems.org/gems/guard)
186
402
 
187
- Install [guard](https://rubygems.org/packages/guard) and
188
- [guard-compat](https://rubygems.org/packages/guard-compat). Then create a
189
- Guardfile with the following configuration:
403
+ Install [guard](https://rubygems.org/gems/guard) and
404
+ [guard-compat](https://rubygems.org/gems/guard-compat). Then create a Guardfile
405
+ with the following configuration:
190
406
 
191
407
  ```ruby
192
408
  guard(:"i18n-js",
@@ -204,7 +420,7 @@ accordingly.
204
420
 
205
421
  Now you can run `guard start -i`.
206
422
 
207
- ### Using listen
423
+ ### Using [listen](https://rubygems.org/gems/listen)
208
424
 
209
425
  Create a file under `config/initializers/i18n.rb` with the following content:
210
426
 
@@ -216,8 +432,25 @@ end
216
432
  ```
217
433
 
218
434
  The code above will watch for changes based on `config/i18n.yml` and
219
- `config/locales`. You can customize these options with
220
- `I18nJS.listen(config_file: "config/i18n.yml", locales_dir: "config/locales")`.
435
+ `config/locales`. You can customize these options:
436
+
437
+ - `config_file` - i18n-js configuration file
438
+ - `locales_dir` - one or multiple directories to watch for locales changes
439
+ - `options` - passed directly to
440
+ [listen](https://github.com/guard/listen/#options)
441
+ - `run_on_start` - export files on start. Defaults to `true`. When disabled,
442
+ files will be exported only when there are file changes.
443
+
444
+ Example:
445
+
446
+ ```ruby
447
+ I18nJS.listen(
448
+ config_file: "config/i18n.yml",
449
+ locales_dir: ["config/locales", "app/views"],
450
+ options: {only: %r{.yml$}},
451
+ run_on_start: false
452
+ )
453
+ ```
221
454
 
222
455
  ### Integrating with your frontend
223
456
 
@@ -227,6 +460,13 @@ that loads all the exported translation.
227
460
 
228
461
  ### FAQ
229
462
 
463
+ #### I'm running v3. Is there a migration plan?
464
+
465
+ [There's a document](https://github.com/fnando/i18n-js/tree/main/MIGRATING_FROM_V3_TO_V4.md)
466
+ outlining some of the things you need to do to migrate from v3 to v4. It may not
467
+ be as complete as we'd like it to be, so let's know if you face any issues
468
+ during the migration is not outline is that document.
469
+
230
470
  #### How can I export translations without having a database around?
231
471
 
232
472
  Some people may have a build process using something like Docker that don't
@@ -246,9 +486,11 @@ require "action_view/railtie"
246
486
  I18n.load_path += Dir["./config/locales/**/*.yml"]
247
487
  ```
248
488
 
249
- Notice that you may not need to load ActiveSupport and ActionView lines, or even
250
- may need to add additional requires for other libs. With this approach you have
251
- full control on what's going to be loaded.
489
+ > **Note**:
490
+ >
491
+ > You may not need to load ActiveSupport and ActionView lines, or even may need
492
+ > to add additional requires for other libs. With this approach you have full
493
+ > control on what's going to be loaded.
252
494
 
253
495
  ## Maintainer
254
496