i18n-js 4.0.0.alpha2 → 4.0.0.alpha5

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: 45e8592f190777f676916988517d474dffb4f18f09120df26733c947d63ca140
4
- data.tar.gz: 04dfd46cfd05501a7cd1e97c5612a1ab5dbec52f98bad5f9119febcf28ce3ab8
3
+ metadata.gz: a5b5c71c903af1425bb6d7b12d0e74dc2da41894cf75a428da19bb11715dc371
4
+ data.tar.gz: 4914b448a0aca280c53412827d11b0148a7ec6393ff875fca78efea84bb68ce2
5
5
  SHA512:
6
- metadata.gz: 96caedcf824fb434a3b77dba666dd23cff72fbfd9f3d3175c928d768920d402f2d9250bb9ff0810e836ff5fbd90d3825b19621a4fd7c27ef10a7a40586990326
7
- data.tar.gz: bc68a8b9e54c991dc21e50ca52986b2f5c39418e6aed3b48664efbcb501e8f34d7a1333a608d6de4b6d5d8bcf7f2fc3c2de5584123b47cc6873e29047da2fdfb
6
+ metadata.gz: dd4f1880a36a9bee698766b843b73489517c1e09c86e143f1e5582811275423714c4c4a741cd01e86c7af558a33866738c9235399b309d09b97fd71375af77cb
7
+ data.tar.gz: 47e0d59fb0d12e2203508ff0c1bef534c9e42a77a895d78bea0d811f97ab6e2d2e0cc4461e46a36ba07016d0d77a4ac488b88fabdf71eb94325080b2fe2acd10
@@ -0,0 +1,5 @@
1
+ ---
2
+ contact_links:
3
+ - name: "🤨 Q&A"
4
+ url: https://github.com/fnando/i18n-js/discussions/new?category=q-a
5
+ about: Have a question? Ask it away here!
@@ -2,7 +2,7 @@
2
2
  name: ruby-tests
3
3
 
4
4
  on:
5
- pull_request:
5
+ pull_request_target:
6
6
  push:
7
7
  workflow_dispatch:
8
8
  inputs: {}
@@ -14,14 +14,17 @@ jobs:
14
14
  strategy:
15
15
  fail-fast: false
16
16
  matrix:
17
- ruby: ["2.7", "3.0"]
17
+ ruby: ["2.7", "3.0", "3.1"]
18
18
  gemfile:
19
19
  - Gemfile
20
+ if: |
21
+ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request_target' ||
22
+ github.actor != 'dependabot[bot]'
20
23
 
21
24
  steps:
22
- - uses: actions/checkout@v1
25
+ - uses: actions/checkout@v3
23
26
 
24
- - uses: actions/cache@v2
27
+ - uses: actions/cache@v3
25
28
  id: bundler-cache
26
29
  with:
27
30
  path: vendor/bundle
data/.rubocop.yml CHANGED
@@ -7,11 +7,10 @@ AllCops:
7
7
  NewCops: enable
8
8
  Exclude:
9
9
  - tmp/**/*
10
+ - vendor/**/*
11
+ - gemfiles/**/*
10
12
 
11
13
  Naming/FileName:
12
14
  Exclude:
13
15
  - lib/i18n-js.rb
14
16
  - lib/guard/i18n-js.rb
15
-
16
- Metrics:
17
- Enabled: false
data/README.md CHANGED
@@ -1,15 +1,30 @@
1
- # i18n-js
2
-
3
- [![Tests](https://github.com/fnando/i18n-js/workflows/ruby-tests/badge.svg)](https://github.com/fnando/i18n-js)
4
- [![Code Climate](https://codeclimate.com/github/fnando/i18n-js/badges/gpa.svg)](https://codeclimate.com/github/fnando/i18n-js)
5
- [![Gem](https://img.shields.io/gem/v/i18n-js.svg)](https://rubygems.org/gems/i18n-js)
6
- [![Gem](https://img.shields.io/gem/dt/i18n-js.svg)](https://rubygems.org/gems/i18n-js)
7
-
8
- Export [i18n](https://rubygems.org/gems/i18n) translations to JSON. A perfect
9
- fit if you want to export translations to JavaScript.
10
-
11
- Oh, you don't use Ruby? No problem! You can still use i18n-js and the
12
- [companion JavaScript package](https://npmjs.com/package/i18n-js).
1
+ <p align="center">
2
+ <img width="250" height="58" src="https://github.com/fnando/i18n-js/raw/main/i18njs.png" alt="i18n.js">
3
+ </p>
4
+
5
+ <p align="center">
6
+ Export <a href="https://rubygems.org/gems/i18n">i18n</a> translations to JSON.
7
+ <br>
8
+ A perfect fit if you want to export translations to JavaScript.
9
+ </p>
10
+
11
+ <p align="center">
12
+ <small>
13
+ Oh, you don't use Ruby? No problem! You can still use i18n-js
14
+ <br>
15
+ and the
16
+ <a href="https://www.npmjs.com/package/i18n-js/v/next">companion JavaScript package</a>.
17
+ </small>
18
+ </p>
19
+
20
+ <p align="center">
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" alt="Gem"></a>
23
+ <a href="https://rubygems.org/gems/i18n-js"><img src="https://img.shields.io/gem/dt/i18n-js.svg" alt="Gem"></a>
24
+ <a href="https://tldrlegal.com/license/mit-license"><img src="https://img.shields.io/:License-MIT-blue.svg" alt="MIT License"></a>
25
+ </p>
26
+
27
+ > **Warning**: This branch contains the code for v4, our next major release.
13
28
 
14
29
  ## Installation
15
30
 
@@ -45,11 +60,16 @@ translations:
45
60
  - "!*.errors"
46
61
  - "!*.number.nth"
47
62
 
48
- - file: app/frontend/locales/:locale.json
63
+ - file: app/frontend/locales/:locale.:digest.json
49
64
  patterns:
50
65
  - "*"
51
66
  ```
52
67
 
68
+ The output path can use the following placeholders:
69
+
70
+ - `:locale`: the language that's being exported.
71
+ - `:digest`: the MD5 hex digest of the exported file.
72
+
53
73
  The Ruby API:
54
74
 
55
75
  ```ruby
@@ -62,16 +82,108 @@ I18nJS.call(config: config)
62
82
  The CLI API:
63
83
 
64
84
  ```console
65
- $ i18n init --config config/i18n.yml
66
- $ i18n export --config config/i18n.yml --require config/environment.rb
85
+ $ i18n --help
86
+ Usage: i18n COMMAND FLAGS
87
+
88
+ Commands:
89
+
90
+ - init: Initialize a project
91
+ - export: Export translations as JSON files
92
+ - version: Show package version
93
+ - check: Check for missing translations
94
+
95
+ Run `i18n COMMAND --help` for more information on specific commands.
67
96
  ```
68
97
 
69
98
  By default, `i18n` will use `config/i18n.yml` and `config/environment.rb` as the
70
99
  configuration files. If you don't have these files, then you'll need to specify
71
100
  both `--config` and `--require`.
72
101
 
102
+ ### Listing missing translations
103
+
104
+ To list missing and extraneous translations, you can use `i18n check`. This
105
+ command will load your translations similarly to how `i18n export` does, but
106
+ will output the list of keys that don't have a matching translation against the
107
+ default locale. Here's an example:
108
+
109
+ ![`i18n check` command in action](https://github.com/fnando/i18n-js/raw/main/images/i18njs-check.gif)
110
+
111
+ This command will exist with status 1 whenever there are missing translations.
112
+ This way you can use it as a CI linting.
113
+
114
+ You can ignore keys by adding a list to the config file:
115
+
116
+ ```yml
117
+ ---
118
+ translations:
119
+ - file: app/frontend/locales/en.json
120
+ patterns:
121
+ - "*"
122
+ - "!*.activerecord"
123
+ - "!*.errors"
124
+ - "!*.number.nth"
125
+
126
+ - file: app/frontend/locales/:locale.:digest.json
127
+ patterns:
128
+ - "*"
129
+
130
+ check:
131
+ ignore:
132
+ - en.mailer.login.subject
133
+ - en.mailer.login.body
134
+ ```
135
+
136
+ > **Note**: In order to avoid mistakenly ignoring keys, this configuration
137
+ > option only accepts the full translation scope, rather than accepting a
138
+ > pattern like `pt.ignored.scope.*`.
139
+
73
140
  ## Automatically export translations
74
141
 
142
+ ### Using watchman
143
+
144
+ Create a script at `bin/i18n-watch`.
145
+
146
+ ```bash
147
+ #!/usr/bin/env bash
148
+
149
+ root=`pwd`
150
+
151
+ watchman watch-del "$root"
152
+ watchman watch-project "$root"
153
+ watchman trigger-del "$root" i18n
154
+
155
+ watchman -j <<-JSON
156
+ [
157
+ "trigger",
158
+ "$root",
159
+ {
160
+ "name": "i18n",
161
+ "expression": [
162
+ "anyof",
163
+ ["match", "config/locales/**/*.yml", "wholename"],
164
+ ["match", "config/i18n.yml", "wholename"]
165
+ ],
166
+ "command": ["i18n", "export"]
167
+ }
168
+ ]
169
+ JSON
170
+
171
+ # If you're running this through Foreman,
172
+ # the uncomment the following lines:
173
+ # while true; do
174
+ # sleep 1
175
+ # done
176
+ ```
177
+
178
+ Make it executable with `chmod +x bin/i18n-watch`. To watch for changes, run
179
+ `./bin/i18n-watch`. If you're using Foreman, make sure you uncommented the lines
180
+ that keep the process running (`while..`), and add something like the following
181
+ line to your Procfile:
182
+
183
+ ```
184
+ i18n: ./bin/i18n-watch
185
+ ```
186
+
75
187
  ### Using guard
76
188
 
77
189
  Install [guard](https://rubygems.org/packages/guard) and
@@ -89,7 +201,7 @@ guard(:"i18n-js",
89
201
  end
90
202
  ```
91
203
 
92
- If you files in a different location, the remember to configure file paths
204
+ If your files are located in a different path, remember to configure file paths
93
205
  accordingly.
94
206
 
95
207
  Now you can run `guard start -i`.
@@ -115,6 +227,31 @@ You're done exporting files, now what? Well, go to
115
227
  [i18n](https://github.com/fnando/i18n) to discover how to use the NPM package
116
228
  that loads all the exported translation.
117
229
 
230
+ ### FAQ
231
+
232
+ #### How can I export translations without having a database around?
233
+
234
+ Some people may have a build process using something like Docker that don't
235
+ necessarily have a database available. In this case, you may define your own
236
+ loading file by using something like
237
+ `i18n export --require ./config/i18n_export.rb`, where `i18n_export.rb` may look
238
+ like this:
239
+
240
+ ```ruby
241
+ # frozen_string_literal: true
242
+
243
+ require "bundler/setup"
244
+ require "rails"
245
+ require "active_support/railtie"
246
+ require "action_view/railtie"
247
+
248
+ I18n.load_path += Dir["./config/locales/**/*.yml"]
249
+ ```
250
+
251
+ Notice that you may not need to load ActiveSupport and ActionView lines, or even
252
+ may need to add additional requires for other libs. With this approach you have
253
+ full control on what's going to be loaded.
254
+
118
255
  ## Maintainer
119
256
 
120
257
  - [Nando Vieira](https://github.com/fnando)
data/i18njs.png ADDED
Binary file
Binary file
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "benchmark"
4
+
5
+ module I18nJS
6
+ class CLI
7
+ class CheckCommand < Command
8
+ command_name "check"
9
+ description "Check for missing translations"
10
+
11
+ parse do |opts|
12
+ opts.banner = "Usage: i18n #{name} [options]"
13
+
14
+ opts.on(
15
+ "-cCONFIG_FILE",
16
+ "--config=CONFIG_FILE",
17
+ "The configuration file that will be used"
18
+ ) do |config_file|
19
+ options[:config_file] = config_file
20
+ end
21
+
22
+ opts.on(
23
+ "-rREQUIRE_FILE",
24
+ "--require=REQUIRE_FILE",
25
+ "A Ruby file that must be loaded"
26
+ ) do |require_file|
27
+ options[:require_file] = require_file
28
+ end
29
+
30
+ opts.on(
31
+ "--[no-]color",
32
+ "Force colored output"
33
+ ) do |colored|
34
+ options[:colored] = colored
35
+ end
36
+
37
+ opts.on("-h", "--help", "Prints this help") do
38
+ ui.exit_with opts.to_s
39
+ end
40
+ end
41
+
42
+ command do
43
+ set_defaults!
44
+ ui.colored = options[:colored]
45
+
46
+ unless options[:config_file]
47
+ ui.fail_with("=> ERROR: you need to specify the config file")
48
+ end
49
+
50
+ ui.stdout_print("=> Config file:", options[:config_file].inspect)
51
+ config_file = File.expand_path(options[:config_file])
52
+
53
+ if options[:require_file]
54
+ ui.stdout_print("=> Require file:", options[:require_file].inspect)
55
+ require_file = File.expand_path(options[:require_file])
56
+ end
57
+
58
+ unless File.file?(config_file)
59
+ ui.fail_with(
60
+ "=> ERROR: config file doesn't exist at",
61
+ config_file.inspect
62
+ )
63
+ end
64
+
65
+ if require_file && !File.file?(require_file)
66
+ ui.fail_with(
67
+ "=> ERROR: require file doesn't exist at",
68
+ require_file.inspect
69
+ )
70
+ end
71
+
72
+ config = Glob::SymbolizeKeys.call(YAML.load_file(config_file))
73
+ Schema.validate!(config)
74
+
75
+ load_require_file!(require_file) if require_file
76
+
77
+ default_locale = I18n.default_locale
78
+ available_locales = I18n.available_locales
79
+ ignored_keys = config.dig(:check, :ignore) || []
80
+
81
+ mapping = available_locales.each_with_object({}) do |locale, buffer|
82
+ buffer[locale] =
83
+ Glob::Map.call(Glob.filter(I18nJS.translations, ["#{locale}.*"]))
84
+ .map {|key| key.gsub(/^.*?\./, "") }
85
+ end
86
+
87
+ default_locale_keys = mapping.delete(default_locale)
88
+
89
+ if ignored_keys.any?
90
+ ui.stdout_print "=> Check #{options[:config_file].inspect} for " \
91
+ "ignored keys."
92
+ end
93
+
94
+ ui.stdout_print "=> #{default_locale}: #{default_locale_keys.size} " \
95
+ "translations"
96
+
97
+ total_missing_count = 0
98
+
99
+ mapping.each do |locale, partial_keys|
100
+ ignored_count = 0
101
+
102
+ # Compute list of filtered keys (i.e. keys not ignored)
103
+ filtered_keys = partial_keys.reject do |key|
104
+ key = "#{locale}.#{key}"
105
+
106
+ ignored = ignored_keys.include?(key)
107
+ ignored_count += 1 if ignored
108
+ ignored
109
+ end
110
+
111
+ extraneous = (partial_keys - default_locale_keys).reject do |key|
112
+ key = "#{locale}.#{key}"
113
+ ignored = ignored_keys.include?(key)
114
+ ignored_count += 1 if ignored
115
+ ignored
116
+ end
117
+
118
+ missing = (default_locale_keys - (filtered_keys - extraneous))
119
+ .reject {|key| ignored_keys.include?("#{locale}.#{key}") }
120
+
121
+ ignored_count += extraneous.size
122
+ total_missing_count += missing.size
123
+
124
+ ui.stdout_print "=> #{locale}: #{missing.size} missing, " \
125
+ "#{extraneous.size} extraneous, " \
126
+ "#{ignored_count} ignored"
127
+
128
+ all_keys = (default_locale_keys + extraneous + missing).uniq.sort
129
+
130
+ all_keys.each do |key|
131
+ next if ignored_keys.include?("#{locale}.#{key}")
132
+
133
+ label = if extraneous.include?(key)
134
+ ui.yellow("extraneous")
135
+ elsif missing.include?(key)
136
+ ui.red("missing")
137
+ else
138
+ next
139
+ end
140
+
141
+ ui.stdout_print(" - #{locale}.#{key} (#{label})")
142
+ end
143
+ end
144
+
145
+ exit(1) if total_missing_count.nonzero?
146
+ end
147
+
148
+ private def set_defaults!
149
+ config_file = "./config/i18n.yml"
150
+ require_file = "./config/environment.rb"
151
+
152
+ options[:config_file] ||= config_file if File.file?(config_file)
153
+ options[:require_file] ||= require_file if File.file?(require_file)
154
+ end
155
+ end
156
+ end
157
+ end
@@ -38,6 +38,32 @@ module I18nJS
38
38
  def options
39
39
  @options ||= {}
40
40
  end
41
+
42
+ private def load_require_file!(require_file)
43
+ require_without_warnings(require_file)
44
+ rescue Exception => error # rubocop:disable Lint/RescueException
45
+ ui.stderr_print("=> ERROR: couldn't load",
46
+ options[:require_file].inspect)
47
+ ui.fail_with(
48
+ "\n#{error_description(error)}\n#{error.backtrace.join("\n")}"
49
+ )
50
+ end
51
+
52
+ private def error_description(error)
53
+ [
54
+ error.class.name,
55
+ error.message
56
+ ].reject(&:empty?).join(" => ")
57
+ end
58
+
59
+ private def require_without_warnings(path)
60
+ old_verbose = $VERBOSE
61
+ $VERBOSE = nil
62
+
63
+ load path
64
+ ensure
65
+ $VERBOSE = old_verbose
66
+ end
41
67
  end
42
68
  end
43
69
  end
@@ -14,7 +14,7 @@ module I18nJS
14
14
  opts.on(
15
15
  "-cCONFIG_FILE",
16
16
  "--config=CONFIG_FILE",
17
- "The configuration file that will be generated"
17
+ "The configuration file that will be used"
18
18
  ) do |config_file|
19
19
  options[:config_file] = config_file
20
20
  end
@@ -35,16 +35,15 @@ module I18nJS
35
35
  command do
36
36
  set_defaults!
37
37
 
38
- ui.stdout_print("=> config file:", options[:config_file].inspect)
39
- ui.stdout_print("=> require file:", options[:require_file].inspect)
40
-
41
38
  unless options[:config_file]
42
39
  ui.fail_with("=> ERROR: you need to specify the config file")
43
40
  end
44
41
 
42
+ ui.stdout_print("=> Config file:", options[:config_file].inspect)
45
43
  config_file = File.expand_path(options[:config_file])
46
44
 
47
45
  if options[:require_file]
46
+ ui.stdout_print("=> Require file:", options[:require_file].inspect)
48
47
  require_file = File.expand_path(options[:require_file])
49
48
  end
50
49
 
@@ -67,7 +66,7 @@ module I18nJS
67
66
  I18nJS.call(config_file: config_file)
68
67
  end
69
68
 
70
- ui.stdout_print("=> done in #{time.round(2)}s")
69
+ ui.stdout_print("=> Done in #{time.round(2)}s")
71
70
  end
72
71
 
73
72
  private def set_defaults!
@@ -77,32 +76,6 @@ module I18nJS
77
76
  options[:config_file] ||= config_file if File.file?(config_file)
78
77
  options[:require_file] ||= require_file if File.file?(require_file)
79
78
  end
80
-
81
- private def load_require_file!(require_file)
82
- require_without_warnings(require_file)
83
- rescue Exception => error # rubocop:disable Lint/RescueException
84
- ui.stderr_print("=> ERROR: couldn't load",
85
- options[:require_file].inspect)
86
- ui.fail_with(
87
- "\n#{error_description(error)}\n#{error.backtrace.join("\n")}"
88
- )
89
- end
90
-
91
- private def error_description(error)
92
- [
93
- error.class.name,
94
- error.message
95
- ].reject(&:empty?).join(" => ")
96
- end
97
-
98
- private def require_without_warnings(path)
99
- old_verbose = $VERBOSE
100
- $VERBOSE = nil
101
-
102
- require path
103
- ensure
104
- $VERBOSE = old_verbose
105
- end
106
79
  end
107
80
  end
108
81
  end
@@ -23,7 +23,9 @@ module I18nJS
23
23
  end
24
24
 
25
25
  command do
26
- file_path = File.expand_path(options[:config_file])
26
+ file_path = File.expand_path(
27
+ options.fetch(:config_file, "config/i18n.yml")
28
+ )
27
29
 
28
30
  if File.file?(file_path)
29
31
  ui.fail_with("ERROR: #{file_path} already exists!")
@@ -3,17 +3,21 @@
3
3
  module I18nJS
4
4
  class CLI
5
5
  class UI
6
- def initialize(stdout:, stderr:)
6
+ attr_reader :stdout, :stderr
7
+ attr_accessor :colored
8
+
9
+ def initialize(stdout:, stderr:, colored: nil)
7
10
  @stdout = stdout
8
11
  @stderr = stderr
12
+ @colored = colored
9
13
  end
10
14
 
11
15
  def stdout_print(*message)
12
- @stdout << "#{message.join(' ')}\n"
16
+ stdout << "#{message.join(' ')}\n"
13
17
  end
14
18
 
15
19
  def stderr_print(*message)
16
- @stderr << "#{message.join(' ')}\n"
20
+ stderr << "#{message.join(' ')}\n"
17
21
  end
18
22
 
19
23
  def fail_with(*message)
@@ -25,6 +29,36 @@ module I18nJS
25
29
  stdout_print(message)
26
30
  exit(0)
27
31
  end
32
+
33
+ def yellow(text)
34
+ ansi(text, 33)
35
+ end
36
+
37
+ def red(text)
38
+ ansi(text, 31)
39
+ end
40
+
41
+ def colored?
42
+ colored_output = if colored.nil?
43
+ stdout.tty?
44
+ else
45
+ colored
46
+ end
47
+
48
+ colored_output && !no_color?
49
+ end
50
+
51
+ def ansi(text, code)
52
+ if colored?
53
+ "\e[#{code}m#{text}\e[0m"
54
+ else
55
+ text
56
+ end
57
+ end
58
+
59
+ def no_color?
60
+ !ENV["NO_COLOR"].nil? && ENV["NO_COLOR"] == "1"
61
+ end
28
62
  end
29
63
  end
30
64
  end
data/lib/i18n-js/cli.rb CHANGED
@@ -6,14 +6,15 @@ require_relative "cli/ui"
6
6
  require_relative "cli/init_command"
7
7
  require_relative "cli/version_command"
8
8
  require_relative "cli/export_command"
9
+ require_relative "cli/check_command"
9
10
 
10
11
  module I18nJS
11
12
  class CLI
12
13
  attr_reader :ui
13
14
 
14
- def initialize(argv:, stdout:, stderr:)
15
+ def initialize(argv:, stdout:, stderr:, colored: stdout.tty?)
15
16
  @argv = argv.dup
16
- @ui = UI.new(stdout: stdout, stderr: stderr)
17
+ @ui = UI.new(stdout: stdout, stderr: stderr, colored: colored)
17
18
  end
18
19
 
19
20
  def call
@@ -26,7 +27,7 @@ module I18nJS
26
27
  end
27
28
 
28
29
  private def command_classes
29
- [InitCommand, ExportCommand, VersionCommand]
30
+ [InitCommand, ExportCommand, VersionCommand, CheckCommand]
30
31
  end
31
32
 
32
33
  private def commands
@@ -4,8 +4,9 @@ module I18nJS
4
4
  class Schema
5
5
  InvalidError = Class.new(StandardError)
6
6
 
7
- ROOT_KEYS = %i[translations].freeze
7
+ ROOT_KEYS = %i[translations check].freeze
8
8
  REQUIRED_ROOT_KEYS = %i[translations].freeze
9
+ REQUIRED_CHECK_KEYS = %i[ignore].freeze
9
10
  REQUIRED_TRANSLATION_KEYS = %i[file patterns].freeze
10
11
  TRANSLATION_KEYS = %i[file patterns].freeze
11
12
 
@@ -25,6 +26,17 @@ module I18nJS
25
26
  expect_required_keys(REQUIRED_ROOT_KEYS, target)
26
27
  reject_extraneous_keys(ROOT_KEYS, target)
27
28
  validate_translations
29
+ validate_check
30
+ end
31
+
32
+ def validate_check
33
+ return unless target.key?(:check)
34
+
35
+ check = target[:check]
36
+
37
+ expect_type(:check, check, Hash, target)
38
+ expect_required_keys(REQUIRED_CHECK_KEYS, check)
39
+ expect_type(:ignore, check[:ignore], Array, check)
28
40
  end
29
41
 
30
42
  def validate_translations
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module I18nJS
4
- VERSION = "4.0.0.alpha2"
4
+ VERSION = "4.0.0.alpha5"
5
5
  end
data/lib/i18n-js.rb CHANGED
@@ -21,32 +21,45 @@ module I18nJS
21
21
 
22
22
  config = Glob::SymbolizeKeys.call(config || YAML.load_file(config_file))
23
23
  Schema.validate!(config)
24
+ exported_files = []
24
25
 
25
26
  config[:translations].each do |group|
26
- export_group(group)
27
+ exported_files += export_group(group)
27
28
  end
29
+
30
+ exported_files
28
31
  end
29
32
 
30
33
  def self.export_group(group)
31
34
  filtered_translations = Glob.filter(translations, group[:patterns])
32
35
  output_file_path = File.expand_path(group[:file])
36
+ exported_files = []
33
37
 
34
38
  if output_file_path.include?(":locale")
35
39
  filtered_translations.each_key do |locale|
36
40
  locale_file_path = output_file_path.gsub(/:locale/, locale.to_s)
37
- write_file(locale_file_path, locale => filtered_translations[locale])
41
+ exported_files << write_file(locale_file_path,
42
+ locale => filtered_translations[locale])
38
43
  end
39
44
  else
40
- write_file(output_file_path, filtered_translations)
45
+ exported_files << write_file(output_file_path, filtered_translations)
41
46
  end
47
+
48
+ exported_files
42
49
  end
43
50
 
44
51
  def self.write_file(file_path, translations)
45
52
  FileUtils.mkdir_p(File.dirname(file_path))
46
53
 
54
+ contents = ::JSON.pretty_generate(translations)
55
+ digest = Digest::MD5.hexdigest(contents)
56
+ file_path = file_path.gsub(/:digest/, digest)
57
+
47
58
  File.open(file_path, "w") do |file|
48
- file << ::JSON.pretty_generate(translations)
59
+ file << contents
49
60
  end
61
+
62
+ file_path
50
63
  end
51
64
 
52
65
  def self.translations
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-js
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.alpha2
4
+ version: 4.0.0.alpha5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-28 00:00:00.000000000 Z
11
+ date: 2022-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glob
@@ -161,6 +161,7 @@ files:
161
161
  - ".github/CODEOWNERS"
162
162
  - ".github/FUNDING.yml"
163
163
  - ".github/ISSUE_TEMPLATE/bug_report.md"
164
+ - ".github/ISSUE_TEMPLATE/config.yml"
164
165
  - ".github/ISSUE_TEMPLATE/feature_request.md"
165
166
  - ".github/PULL_REQUEST_TEMPLATE.md"
166
167
  - ".github/dependabot.yml"
@@ -176,11 +177,14 @@ files:
176
177
  - Rakefile
177
178
  - exe/i18n
178
179
  - i18n-js.gemspec
180
+ - i18njs.png
181
+ - images/i18njs-check.gif
179
182
  - lib/guard/i18n-js.rb
180
183
  - lib/guard/i18n-js/templates/Guardfile
181
184
  - lib/guard/i18n-js/version.rb
182
185
  - lib/i18n-js.rb
183
186
  - lib/i18n-js/cli.rb
187
+ - lib/i18n-js/cli/check_command.rb
184
188
  - lib/i18n-js/cli/command.rb
185
189
  - lib/i18n-js/cli/export_command.rb
186
190
  - lib/i18n-js/cli/init_command.rb
@@ -196,10 +200,10 @@ metadata:
196
200
  rubygems_mfa_required: 'true'
197
201
  homepage_uri: https://github.com/fnando/i18n-js
198
202
  bug_tracker_uri: https://github.com/fnando/i18n-js/issues
199
- source_code_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha2
200
- changelog_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha2/CHANGELOG.md
201
- documentation_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha2/README.md
202
- license_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha2/LICENSE.md
203
+ source_code_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha5
204
+ changelog_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha5/CHANGELOG.md
205
+ documentation_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha5/README.md
206
+ license_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha5/LICENSE.md
203
207
  post_install_message:
204
208
  rdoc_options: []
205
209
  require_paths:
@@ -215,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
219
  - !ruby/object:Gem::Version
216
220
  version: 1.3.1
217
221
  requirements: []
218
- rubygems_version: 3.2.32
222
+ rubygems_version: 3.3.7
219
223
  signing_key:
220
224
  specification_version: 4
221
225
  summary: Export i18n translations and use them on JavaScript.