i18n-js 4.0.0 → 4.2.3
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 +4 -4
- data/.github/workflows/ruby-tests.yml +22 -1
- data/.gitignore +2 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +48 -1
- data/MIGRATING_FROM_V3_TO_V4.md +192 -0
- data/README.md +322 -25
- data/bin/release +81 -0
- data/i18n-js.gemspec +5 -2
- data/lib/guard/i18n-js.rb +21 -4
- data/lib/i18n-js/clean_hash.rb +13 -0
- data/lib/i18n-js/cli/check_command.rb +7 -147
- data/lib/i18n-js/cli/command.rb +10 -0
- data/lib/i18n-js/cli/export_command.rb +17 -3
- data/lib/i18n-js/cli/lint_scripts_command.rb +159 -0
- data/lib/i18n-js/cli/lint_translations_command.rb +157 -0
- data/lib/i18n-js/cli/plugins_command.rb +67 -0
- data/lib/i18n-js/cli.rb +12 -1
- data/lib/i18n-js/embed_fallback_translations_plugin.rb +70 -0
- data/lib/i18n-js/export_files_plugin.rb +103 -0
- data/lib/i18n-js/lint.js +150645 -0
- data/lib/i18n-js/lint.ts +196 -0
- data/lib/i18n-js/listen.rb +25 -10
- data/lib/i18n-js/plugin.rb +103 -0
- data/lib/i18n-js/schema.rb +153 -41
- data/lib/i18n-js/sort_hash.rb +12 -0
- data/lib/i18n-js/version.rb +1 -1
- data/lib/i18n-js.rb +37 -3
- data/package.json +10 -0
- metadata +36 -11
- data/i18njs.png +0 -0
- data/images/i18njs-check.gif +0 -0
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/
|
|
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
|
|
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
|
-
-
|
|
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,181 @@ 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
|
+
##### `export_files`:
|
|
144
|
+
|
|
145
|
+
By default, i18n-js will export only JSON files out of your translations. This
|
|
146
|
+
plugin allows exporting other file formats. To use it, add the following to your
|
|
147
|
+
configuration file:
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
export_files:
|
|
151
|
+
enabled: true
|
|
152
|
+
files:
|
|
153
|
+
- template: path/to/template.erb
|
|
154
|
+
output: "%{dir}/%{base_name}.ts"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
You can export multiple files by define more entries.
|
|
158
|
+
|
|
159
|
+
The output name can use the following placeholders:
|
|
160
|
+
|
|
161
|
+
- `%{dir}`: the directory where the translation file is.
|
|
162
|
+
- `%{name}`: file name with extension.
|
|
163
|
+
- `%{base_name}`: file name without extension.
|
|
164
|
+
- `%{digest}`: MD5 hexdigest from the generated file.
|
|
165
|
+
|
|
166
|
+
The template file must be a valid eRB template. You can execute arbitrary Ruby
|
|
167
|
+
code, so be careful. An example of how you can generate a file can be seen
|
|
168
|
+
below:
|
|
169
|
+
|
|
170
|
+
```erb
|
|
171
|
+
/* eslint-disable */
|
|
172
|
+
<%= banner %>
|
|
173
|
+
|
|
174
|
+
import { i18n } from "config/i18n";
|
|
175
|
+
|
|
176
|
+
i18n.store(<%= JSON.pretty_generate(translations) %>);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
This template is loading the instance from `config/i18n` and storing the
|
|
180
|
+
translations that have been loaded. The
|
|
181
|
+
`banner(comment: "// ", include_time: true)` method is built-in. The generated
|
|
182
|
+
file will look something like this:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
/* eslint-disable */
|
|
186
|
+
// File generated by i18n-js on 2022-12-10 15:37:00 +0000
|
|
187
|
+
|
|
188
|
+
import { i18n } from "config/i18n";
|
|
189
|
+
|
|
190
|
+
i18n.store({
|
|
191
|
+
en: {
|
|
192
|
+
"bunny rabbit adventure": "bunny rabbit adventure",
|
|
193
|
+
"hello sunshine!": "hello sunshine!",
|
|
194
|
+
"time for bed!": "time for bed!",
|
|
195
|
+
},
|
|
196
|
+
es: {
|
|
197
|
+
"bunny rabbit adventure": "conejito conejo aventura",
|
|
198
|
+
bye: "adios",
|
|
199
|
+
"time for bed!": "hora de acostarse!",
|
|
200
|
+
},
|
|
201
|
+
pt: {
|
|
202
|
+
"bunny rabbit adventure": "a aventura da coelhinha",
|
|
203
|
+
bye: "tchau",
|
|
204
|
+
"time for bed!": "hora de dormir!",
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### Plugin API
|
|
210
|
+
|
|
211
|
+
You can transform the exported translations by adding plugins. A plugin must
|
|
212
|
+
inherit from `I18nJS::Plugin` and can have 4 class methods (they're all optional
|
|
213
|
+
and will default to a noop implementation). For real examples, see [lib/i18n-js/embed_fallback_translations_plugin.rb](https://github.com/fnando/i18n-js/blob/main/lib/i18n-js/embed_fallback_translations_plugin.rb) and [lib/i18n-js/export_files_plugin.rb](https://github.com/fnando/i18n-js/blob/main/lib/i18n-js/export_files_plugin.rb)
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
# frozen_string_literal: true
|
|
217
|
+
|
|
218
|
+
module I18nJS
|
|
219
|
+
class SamplePlugin < I18nJS::Plugin
|
|
220
|
+
# This method is responsible for transforming the translations. The
|
|
221
|
+
# translations you'll receive may be already be filtered by other plugins
|
|
222
|
+
# and by the default filtering itself. If you need to access the original
|
|
223
|
+
# translations, use `I18nJS.translations`.
|
|
224
|
+
def transform(translations:)
|
|
225
|
+
# transform `translations` here…
|
|
226
|
+
|
|
227
|
+
translations
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# In case your plugin accepts configuration, this is where you must validate
|
|
231
|
+
# the configuration, making sure only valid keys and type is provided.
|
|
232
|
+
# If the configuration contains invalid data, then you must raise an
|
|
233
|
+
# exception using something like
|
|
234
|
+
# `raise I18nJS::Schema::InvalidError, error_message`.
|
|
235
|
+
#
|
|
236
|
+
# Notice the validation will only happen when the plugin configuration is
|
|
237
|
+
# set (i.e. the configuration contains your config key).
|
|
238
|
+
def validate_schema
|
|
239
|
+
# validate plugin schema here…
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# This method must set up the basic plugin configuration, like adding the
|
|
243
|
+
# config's root key in case your plugin accepts configuration (defined via
|
|
244
|
+
# the config file).
|
|
245
|
+
#
|
|
246
|
+
# If you don't add this key, the linter will prevent non-default keys from
|
|
247
|
+
# being added to the configuration file.
|
|
248
|
+
def setup
|
|
249
|
+
# If you plugin has configuration, uncomment the line below
|
|
250
|
+
# I18nJS::Schema.root_keys << config_key
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# This method is called whenever `I18nJS.call(**kwargs)` finishes exporting
|
|
254
|
+
# JSON files based on your configuration.
|
|
255
|
+
#
|
|
256
|
+
# You can use it to further process exported files, or generate new files
|
|
257
|
+
# based on the translations that have been exported.
|
|
258
|
+
def after_export(files:)
|
|
259
|
+
# process exported files here…
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The class `I18nJS::Plugin` implements some helper methods that you can use:
|
|
266
|
+
|
|
267
|
+
- `I18nJS::Plugin#config_key`: the configuration key that was inferred out of
|
|
268
|
+
your plugin's class name.
|
|
269
|
+
- `I18nJS::Plugin#config`: the plugin configuration.
|
|
270
|
+
- `I18nJS::Plugin#enabled?`: whether the plugin is enabled or not based on the
|
|
271
|
+
plugin's configuration.
|
|
272
|
+
|
|
273
|
+
To distribute this plugin, you need to create a gem package that matches the
|
|
274
|
+
pattern `i18n-js/*_plugin.rb`. You can test whether your plugin will be found by
|
|
275
|
+
installing your gem, opening a iRB session and running
|
|
276
|
+
`Gem.find_files("i18n-js/*_plugin.rb")`. If your plugin is not listed, then you
|
|
277
|
+
need to double check your gem load path and see why the file is not being
|
|
278
|
+
loaded.
|
|
279
|
+
|
|
100
280
|
### Listing missing translations
|
|
101
281
|
|
|
102
|
-
To list missing and extraneous translations, you can use
|
|
103
|
-
command will load your translations similarly to
|
|
104
|
-
will output the list of keys that don't have a
|
|
105
|
-
default locale. Here's an example:
|
|
282
|
+
To list missing and extraneous translations, you can use
|
|
283
|
+
`i18n lint:translations`. This command will load your translations similarly to
|
|
284
|
+
how `i18n export` does, but will output the list of keys that don't have a
|
|
285
|
+
matching translation against the default locale. Here's an example:
|
|
106
286
|
|
|
107
|
-
|
|
287
|
+
```console
|
|
288
|
+
$ i18n lint:translations
|
|
289
|
+
=> Config file: "./config/i18n.yml"
|
|
290
|
+
=> Require file: "./config/environment.rb"
|
|
291
|
+
=> Check "./config/i18n.yml" for ignored keys.
|
|
292
|
+
=> en: 232 translations
|
|
293
|
+
=> pt-BR: 5 missing, 1 extraneous, 1 ignored
|
|
294
|
+
- pt-BR.actors.github.metrics (missing)
|
|
295
|
+
- pt-BR.actors.github.metrics_hint (missing)
|
|
296
|
+
- pt-BR.actors.github.repo_metrics (missing)
|
|
297
|
+
- pt-BR.actors.github.repository (missing)
|
|
298
|
+
- pt-BR.actors.github.user_metrics (missing)
|
|
299
|
+
- pt-BR.github.repository (extraneous)
|
|
300
|
+
```
|
|
108
301
|
|
|
109
302
|
This command will exist with status 1 whenever there are missing translations.
|
|
110
303
|
This way you can use it as a CI linting.
|
|
@@ -125,19 +318,97 @@ translations:
|
|
|
125
318
|
patterns:
|
|
126
319
|
- "*"
|
|
127
320
|
|
|
128
|
-
|
|
321
|
+
lint_translations:
|
|
129
322
|
ignore:
|
|
130
323
|
- en.mailer.login.subject
|
|
131
324
|
- en.mailer.login.body
|
|
132
325
|
```
|
|
133
326
|
|
|
134
|
-
> **Note**:
|
|
135
|
-
>
|
|
136
|
-
>
|
|
327
|
+
> **Note**:
|
|
328
|
+
>
|
|
329
|
+
> In order to avoid mistakenly ignoring keys, this configuration option only
|
|
330
|
+
> accepts the full translation scope, rather than accepting a pattern like
|
|
331
|
+
> `pt.ignored.scope.*`.
|
|
332
|
+
|
|
333
|
+
### Linting your JavaScript/TypeScript files
|
|
334
|
+
|
|
335
|
+
To lint your script files and check for missing translations (which can signal
|
|
336
|
+
that you're either using wrong scopes or forgot to add the translation), use
|
|
337
|
+
`i18n lint:scripts`. This command will parse your JavaScript/TypeScript files
|
|
338
|
+
and extract all scopes being used. This command requires a Node.js runtime. You
|
|
339
|
+
can either specify one via `--node-path`, or let the plugin infer a binary from
|
|
340
|
+
your `$PATH`.
|
|
341
|
+
|
|
342
|
+
The comparison will be made against the export JSON files, which means it'll
|
|
343
|
+
consider transformations performed by plugins (e.g. the output files may be
|
|
344
|
+
affected by `embed_fallback_translations` plugin).
|
|
345
|
+
|
|
346
|
+
The translations that will be extract must be called as one of the following
|
|
347
|
+
ways:
|
|
348
|
+
|
|
349
|
+
- `i18n.t(scope, options)`
|
|
350
|
+
- `i18n.translate(scope, options)`
|
|
351
|
+
- `t(scope, options)`
|
|
352
|
+
|
|
353
|
+
Notice that only literal strings can be used, as in `i18n.t("message")`. If
|
|
354
|
+
you're using dynamic scoping through variables (e.g.
|
|
355
|
+
`const scope = "message"; i18n.t(scope)`), they will be skipped.
|
|
356
|
+
|
|
357
|
+
```console
|
|
358
|
+
$ i18n lint:scripts
|
|
359
|
+
=> Config file: "./config/i18n.yml"
|
|
360
|
+
=> Require file: "./config/environment.rb"
|
|
361
|
+
=> Node: "/Users/fnando/.asdf/shims/node"
|
|
362
|
+
=> Available locales: [:en, :es, :pt]
|
|
363
|
+
=> Patterns: ["!(node_modules)/**/*.js", "!(node_modules)/**/*.ts", "!(node_modules)/**/*.jsx", "!(node_modules)/**/*.tsx"]
|
|
364
|
+
=> 9 translations, 11 missing, 4 ignored
|
|
365
|
+
- test/scripts/lint/file.js:1:1: en.js.missing
|
|
366
|
+
- test/scripts/lint/file.js:1:1: es.js.missing
|
|
367
|
+
- test/scripts/lint/file.js:1:1: pt.js.missing
|
|
368
|
+
- test/scripts/lint/file.js:2:8: en.base.js.missing
|
|
369
|
+
- test/scripts/lint/file.js:2:8: es.base.js.missing
|
|
370
|
+
- test/scripts/lint/file.js:2:8: pt.base.js.missing
|
|
371
|
+
- test/scripts/lint/file.js:4:8: en.js.missing
|
|
372
|
+
- test/scripts/lint/file.js:4:8: es.js.missing
|
|
373
|
+
- test/scripts/lint/file.js:4:8: pt.js.missing
|
|
374
|
+
- test/scripts/lint/file.js:6:1: en.another_ignore_scope
|
|
375
|
+
- test/scripts/lint/file.js:6:1: es.another_ignore_scope
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
This command will list all locales and their missing translations. Avoid listing
|
|
379
|
+
a particular translation, you can set `lint.ignore` on your config file.
|
|
380
|
+
|
|
381
|
+
```yaml
|
|
382
|
+
---
|
|
383
|
+
translations:
|
|
384
|
+
- file: app/frontend/translations.json
|
|
385
|
+
patterns:
|
|
386
|
+
- "*"
|
|
387
|
+
|
|
388
|
+
lint_scripts:
|
|
389
|
+
ignore:
|
|
390
|
+
- ignore_scope # will ignore this scope on all languages
|
|
391
|
+
- pt.another_ignore_scope # will ignore this scope only on `pt`
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
You can also set the patterns that will be looked up. By default, it scans all
|
|
395
|
+
JavaScript and TypeScript files that don't live on `node_modules`.
|
|
396
|
+
|
|
397
|
+
```yaml
|
|
398
|
+
---
|
|
399
|
+
translations:
|
|
400
|
+
- file: app/frontend/translations.json
|
|
401
|
+
patterns:
|
|
402
|
+
- "*"
|
|
403
|
+
|
|
404
|
+
lint:
|
|
405
|
+
patterns:
|
|
406
|
+
- "app/assets/**/*.ts"
|
|
407
|
+
```
|
|
137
408
|
|
|
138
409
|
## Automatically export translations
|
|
139
410
|
|
|
140
|
-
### Using watchman
|
|
411
|
+
### Using [watchman](https://facebook.github.io/watchman/)
|
|
141
412
|
|
|
142
413
|
Create a script at `bin/i18n-watch`.
|
|
143
414
|
|
|
@@ -182,11 +453,11 @@ line to your Procfile:
|
|
|
182
453
|
i18n: ./bin/i18n-watch
|
|
183
454
|
```
|
|
184
455
|
|
|
185
|
-
### Using guard
|
|
456
|
+
### Using [guard](https://rubygems.org/gems/guard)
|
|
186
457
|
|
|
187
|
-
Install [guard](https://rubygems.org/
|
|
188
|
-
[guard-compat](https://rubygems.org/
|
|
189
|
-
|
|
458
|
+
Install [guard](https://rubygems.org/gems/guard) and
|
|
459
|
+
[guard-compat](https://rubygems.org/gems/guard-compat). Then create a Guardfile
|
|
460
|
+
with the following configuration:
|
|
190
461
|
|
|
191
462
|
```ruby
|
|
192
463
|
guard(:"i18n-js",
|
|
@@ -204,7 +475,7 @@ accordingly.
|
|
|
204
475
|
|
|
205
476
|
Now you can run `guard start -i`.
|
|
206
477
|
|
|
207
|
-
### Using listen
|
|
478
|
+
### Using [listen](https://rubygems.org/gems/listen)
|
|
208
479
|
|
|
209
480
|
Create a file under `config/initializers/i18n.rb` with the following content:
|
|
210
481
|
|
|
@@ -216,8 +487,25 @@ end
|
|
|
216
487
|
```
|
|
217
488
|
|
|
218
489
|
The code above will watch for changes based on `config/i18n.yml` and
|
|
219
|
-
`config/locales`. You can customize these options
|
|
220
|
-
|
|
490
|
+
`config/locales`. You can customize these options:
|
|
491
|
+
|
|
492
|
+
- `config_file` - i18n-js configuration file
|
|
493
|
+
- `locales_dir` - one or multiple directories to watch for locales changes
|
|
494
|
+
- `options` - passed directly to
|
|
495
|
+
[listen](https://github.com/guard/listen/#options)
|
|
496
|
+
- `run_on_start` - export files on start. Defaults to `true`. When disabled,
|
|
497
|
+
files will be exported only when there are file changes.
|
|
498
|
+
|
|
499
|
+
Example:
|
|
500
|
+
|
|
501
|
+
```ruby
|
|
502
|
+
I18nJS.listen(
|
|
503
|
+
config_file: "config/i18n.yml",
|
|
504
|
+
locales_dir: ["config/locales", "app/views"],
|
|
505
|
+
options: {only: %r{.yml$}},
|
|
506
|
+
run_on_start: false
|
|
507
|
+
)
|
|
508
|
+
```
|
|
221
509
|
|
|
222
510
|
### Integrating with your frontend
|
|
223
511
|
|
|
@@ -227,6 +515,13 @@ that loads all the exported translation.
|
|
|
227
515
|
|
|
228
516
|
### FAQ
|
|
229
517
|
|
|
518
|
+
#### I'm running v3. Is there a migration plan?
|
|
519
|
+
|
|
520
|
+
[There's a document](https://github.com/fnando/i18n-js/tree/main/MIGRATING_FROM_V3_TO_V4.md)
|
|
521
|
+
outlining some of the things you need to do to migrate from v3 to v4. It may not
|
|
522
|
+
be as complete as we'd like it to be, so let us know if you face any issues
|
|
523
|
+
during the migration is not outline is that document.
|
|
524
|
+
|
|
230
525
|
#### How can I export translations without having a database around?
|
|
231
526
|
|
|
232
527
|
Some people may have a build process using something like Docker that don't
|
|
@@ -246,9 +541,11 @@ require "action_view/railtie"
|
|
|
246
541
|
I18n.load_path += Dir["./config/locales/**/*.yml"]
|
|
247
542
|
```
|
|
248
543
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
544
|
+
> **Note**:
|
|
545
|
+
>
|
|
546
|
+
> You may not need to load ActiveSupport and ActionView lines, or even may need
|
|
547
|
+
> to add additional requires for other libs. With this approach you have full
|
|
548
|
+
> control on what's going to be loaded.
|
|
252
549
|
|
|
253
550
|
## Maintainer
|
|
254
551
|
|
data/bin/release
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "optparse"
|
|
5
|
+
require_relative "../lib/i18n-js/version"
|
|
6
|
+
|
|
7
|
+
def write_file(path, contents)
|
|
8
|
+
File.open(File.expand_path(path), "w") do |io|
|
|
9
|
+
io << contents
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
changelog_path = "./CHANGELOG.md"
|
|
14
|
+
version_path = "./lib/i18n-js/version.rb"
|
|
15
|
+
|
|
16
|
+
version = nil
|
|
17
|
+
segments = I18nJS::VERSION.split(".")
|
|
18
|
+
major, minor, patch = *segments.take(3).map(&:to_i)
|
|
19
|
+
pre = segments[4].to_s
|
|
20
|
+
pre_version = pre.gsub(/[^\d]/m, "").to_i
|
|
21
|
+
date = Time.now.strftime("%b %d, %Y")
|
|
22
|
+
dry_run = false
|
|
23
|
+
alpha = false
|
|
24
|
+
|
|
25
|
+
OptionParser.new do |opts|
|
|
26
|
+
opts.on("--major") do
|
|
27
|
+
version = "#{major + 1}.0.0"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
opts.on("--minor") do
|
|
31
|
+
version = "#{major}.#{minor + 1}.0"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opts.on("--patch") do
|
|
35
|
+
version = "#{major}.#{minor}.#{patch + 1}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on("--alpha") do
|
|
39
|
+
alpha = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on("--dry-run") do
|
|
43
|
+
dry_run = true
|
|
44
|
+
end
|
|
45
|
+
end.parse!
|
|
46
|
+
|
|
47
|
+
version = "#{version}.alpha#{pre_version + 1}" if alpha
|
|
48
|
+
|
|
49
|
+
unless version
|
|
50
|
+
puts "ERROR: You need to use either one of: --major, --minor, --patch"
|
|
51
|
+
exit 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
puts "=> Current version: #{I18nJS::VERSION}"
|
|
55
|
+
puts "=> Next version: #{version}"
|
|
56
|
+
|
|
57
|
+
system "yarn", "install"
|
|
58
|
+
system "yarn", "compile"
|
|
59
|
+
|
|
60
|
+
write_file changelog_path,
|
|
61
|
+
File.read(changelog_path)
|
|
62
|
+
.gsub("Unreleased", "v#{version} - #{date}")
|
|
63
|
+
|
|
64
|
+
puts "=> Updated #{changelog_path}"
|
|
65
|
+
|
|
66
|
+
write_file version_path,
|
|
67
|
+
File.read(version_path)
|
|
68
|
+
.gsub(/VERSION = ".*?"/, %[VERSION = "#{version}"])
|
|
69
|
+
|
|
70
|
+
puts "=> Updated #{version_path}"
|
|
71
|
+
|
|
72
|
+
unless dry_run
|
|
73
|
+
system "git", "add", changelog_path, version_path
|
|
74
|
+
system "git", "commit", "-m", "Bump up version (v#{version})"
|
|
75
|
+
system "rake", "release"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if dry_run
|
|
79
|
+
system "rake", "build"
|
|
80
|
+
system "git", "checkout", changelog_path, version_path
|
|
81
|
+
end
|
data/i18n-js.gemspec
CHANGED
|
@@ -28,19 +28,22 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
29
29
|
`git ls-files -z`
|
|
30
30
|
.split("\x0")
|
|
31
|
-
.reject {|f| f.match(%r{^(test|spec|features)/}) }
|
|
31
|
+
.reject {|f| f.match(%r{^(test|spec|features|images)/}) }
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
spec.files << "lib/i18n-js/lint.js"
|
|
35
|
+
|
|
34
36
|
spec.bindir = "exe"
|
|
35
37
|
spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f) }
|
|
36
38
|
spec.require_paths = ["lib"]
|
|
37
39
|
|
|
38
|
-
spec.add_dependency "glob"
|
|
40
|
+
spec.add_dependency "glob", ">= 0.4.0"
|
|
39
41
|
spec.add_dependency "i18n"
|
|
40
42
|
|
|
41
43
|
spec.add_development_dependency "activesupport"
|
|
42
44
|
spec.add_development_dependency "minitest"
|
|
43
45
|
spec.add_development_dependency "minitest-utils"
|
|
46
|
+
spec.add_development_dependency "mocha"
|
|
44
47
|
spec.add_development_dependency "pry-meta"
|
|
45
48
|
spec.add_development_dependency "rake"
|
|
46
49
|
spec.add_development_dependency "rubocop"
|
data/lib/guard/i18n-js.rb
CHANGED
|
@@ -53,13 +53,30 @@ module Guard
|
|
|
53
53
|
info("Changes detected: #{changes.join(', ')}") if changes
|
|
54
54
|
|
|
55
55
|
@current_thread = Thread.new do
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
capture do
|
|
57
|
+
system "i18n",
|
|
58
|
+
"export",
|
|
59
|
+
"--config",
|
|
60
|
+
config_file.to_s,
|
|
61
|
+
"--require",
|
|
62
|
+
require_file.to_s,
|
|
63
|
+
"--quiet"
|
|
64
|
+
end
|
|
58
65
|
end
|
|
59
66
|
|
|
60
67
|
current_thread.join
|
|
61
68
|
end
|
|
62
69
|
|
|
70
|
+
def capture
|
|
71
|
+
original = $stdout
|
|
72
|
+
$stdout = StringIO.new
|
|
73
|
+
yield
|
|
74
|
+
rescue StandardError
|
|
75
|
+
# noop
|
|
76
|
+
ensure
|
|
77
|
+
$stdout = original
|
|
78
|
+
end
|
|
79
|
+
|
|
63
80
|
def validate_file(key, file)
|
|
64
81
|
return true if file && File.file?(file)
|
|
65
82
|
|
|
@@ -68,11 +85,11 @@ module Guard
|
|
|
68
85
|
end
|
|
69
86
|
|
|
70
87
|
def error(message)
|
|
71
|
-
::Guard::UI.error "[
|
|
88
|
+
::Guard::UI.error "[i18n-js] #{message}"
|
|
72
89
|
end
|
|
73
90
|
|
|
74
91
|
def info(message)
|
|
75
|
-
::Guard::UI.info "[
|
|
92
|
+
::Guard::UI.info "[i18n-js] #{message}"
|
|
76
93
|
end
|
|
77
94
|
end
|
|
78
95
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module I18nJS
|
|
4
|
+
def self.clean_hash(hash)
|
|
5
|
+
hash.keys.each_with_object({}) do |key, buffer|
|
|
6
|
+
value = hash[key]
|
|
7
|
+
|
|
8
|
+
next if value.is_a?(Proc)
|
|
9
|
+
|
|
10
|
+
buffer[key] = value.is_a?(Hash) ? clean_hash(value) : value
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|