i18n-js 4.0.0.alpha1 → 4.0.0.alpha4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d07791eb7f9b879e4d5e6edd43d10564a5efad2f44e3ac0ddd2c892696dbd28b
4
- data.tar.gz: cab23b9274ee26513b48974dd307ad020a1ad3ba88bb36756397d6c47223ffb4
3
+ metadata.gz: 3ecf4853a33adc9a67520a585c733a55e7b05e07bdc436830c519213bfc728b6
4
+ data.tar.gz: 5a1b68a4182bc30fcc3c57438ab226ba72a97a7f16dd6c29ac938106f4c5e00c
5
5
  SHA512:
6
- metadata.gz: 0d0bb95c8e0f01bed11eced7859d6f40d032ca85a03f458d515a4cdcc444a194f315b22db39f0d6956c45951a1cf8e3e28ab06a11abb6165ca7dc5d6fa07baa1
7
- data.tar.gz: a7afe30f6f81a9b7536cb5be2a26112825bd5324443d9fe7edb43779c6084e2c4d4e439814f4458853a6ffaf540afdfc0640f8be2a7cb428b46c45c83313d0bb
6
+ metadata.gz: f8468f07c440fa8c29c84a6550ef8b7d5914cf08ce93d0b02f77caf65838a4057f8a7653cc221c33a1dfaf1ab0486aa195a368248ca9509af4af7071ab76ddaa
7
+ data.tar.gz: cb3822d5fe66aa90b20a4a596869a0adb93c3154d5877f66b1374794961536bc2916c051f8d5ce5f61d2d57c66951c25b477f8b808b7d737b39941875e545afb
@@ -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,18 +2,8 @@
2
2
  name: ruby-tests
3
3
 
4
4
  on:
5
- pull_request:
6
- branches:
7
- - main
8
-
5
+ pull_request_target:
9
6
  push:
10
- branches:
11
- - main
12
- - v4
13
-
14
- schedule:
15
- - cron: "0 10 * * *"
16
-
17
7
  workflow_dispatch:
18
8
  inputs: {}
19
9
 
@@ -24,25 +14,26 @@ jobs:
24
14
  strategy:
25
15
  fail-fast: false
26
16
  matrix:
27
- ruby: [2.6.x, 2.7.x, 3.0.x]
17
+ ruby: ["2.7", "3.0", "3.1"]
28
18
  gemfile:
29
19
  - Gemfile
20
+ if: |
21
+ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request_target' ||
22
+ github.actor != 'dependabot[bot]'
30
23
 
31
24
  steps:
32
- - uses: actions/checkout@v1
25
+ - uses: actions/checkout@v3
33
26
 
34
- - uses: actions/cache@v2
27
+ - uses: actions/cache@v3
28
+ id: bundler-cache
35
29
  with:
36
30
  path: vendor/bundle
37
31
  key: >
38
32
  ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
39
33
  hashFiles(matrix.gemfile) }}
40
- restore-keys: >
41
- ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
42
- hashFiles(matrix.gemfile) }}
43
34
 
44
35
  - name: Set up Ruby
45
- uses: actions/setup-ruby@v1
36
+ uses: ruby/setup-ruby@v1
46
37
  with:
47
38
  ruby-version: ${{ matrix.ruby }}
48
39
 
data/.rubocop.yml CHANGED
@@ -5,6 +5,10 @@ inherit_gem:
5
5
  AllCops:
6
6
  TargetRubyVersion: 2.6
7
7
  NewCops: enable
8
+ Exclude:
9
+ - tmp/**/*
10
+ - vendor/**/*
11
+ - gemfiles/**/*
8
12
 
9
13
  Naming/FileName:
10
14
  Exclude:
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
+ ![This branch contains the code for v4, our next major release.](https://messages-svg.herokuapp.com/warning.svg?message=This%20branch%20contains%20the%20code%20for%20v4%2C%20our%20next%20major%20release.)
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,82 @@ 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
+
73
114
  ## Automatically export translations
74
115
 
116
+ ### Using watchman
117
+
118
+ Create a script at `bin/i18n-watch`.
119
+
120
+ ```bash
121
+ #!/usr/bin/env bash
122
+
123
+ root=`pwd`
124
+
125
+ watchman watch-del "$root"
126
+ watchman watch-project "$root"
127
+ watchman trigger-del "$root" i18n
128
+
129
+ watchman -j <<-JSON
130
+ [
131
+ "trigger",
132
+ "$root",
133
+ {
134
+ "name": "i18n",
135
+ "expression": [
136
+ "anyof",
137
+ ["match", "config/locales/**/*.yml", "wholename"],
138
+ ["match", "config/i18n.yml", "wholename"]
139
+ ],
140
+ "command": ["i18n", "export"]
141
+ }
142
+ ]
143
+ JSON
144
+
145
+ # If you're running this through Foreman,
146
+ # the uncomment the following lines:
147
+ # while true; do
148
+ # sleep 1
149
+ # done
150
+ ```
151
+
152
+ Make it executable with `chmod +x bin/i18n-watch`. To watch for changes, run
153
+ `./bin/i18n-watch`. If you're using Foreman, make sure you uncommented the lines
154
+ that keep the process running (`while..`), and add something like the following
155
+ line to your Procfile:
156
+
157
+ ```
158
+ i18n: ./bin/i18n-watch
159
+ ```
160
+
75
161
  ### Using guard
76
162
 
77
163
  Install [guard](https://rubygems.org/packages/guard) and
@@ -89,7 +175,7 @@ guard(:"i18n-js",
89
175
  end
90
176
  ```
91
177
 
92
- If you files in a different location, the remember to configure file paths
178
+ If your files are located in a different path, remember to configure file paths
93
179
  accordingly.
94
180
 
95
181
  Now you can run `guard start -i`.
@@ -99,11 +185,10 @@ Now you can run `guard start -i`.
99
185
  Create a file under `config/initializers/i18n.rb` with the following content:
100
186
 
101
187
  ```ruby
102
- # frozen_string_literal: true
103
-
104
- require "i18n-js/listen"
105
-
106
- I18nJS.listen
188
+ Rails.application.config.after_initialize do
189
+ require "i18n-js/listen"
190
+ I18nJS.listen
191
+ end
107
192
  ```
108
193
 
109
194
  The code above will watch for changes based on `config/i18n.yml` and
@@ -116,6 +201,31 @@ You're done exporting files, now what? Well, go to
116
201
  [i18n](https://github.com/fnando/i18n) to discover how to use the NPM package
117
202
  that loads all the exported translation.
118
203
 
204
+ ### FAQ
205
+
206
+ #### How can I export translations without having a database around?
207
+
208
+ Some people may have a build process using something like Docker that don't
209
+ necessarily have a database available. In this case, you may define your own
210
+ loading file by using something like
211
+ `i18n export --require ./config/i18n_export.rb`, where `i18n_export.rb` may look
212
+ like this:
213
+
214
+ ```ruby
215
+ # frozen_string_literal: true
216
+
217
+ require "bundler/setup"
218
+ require "rails"
219
+ require "active_support/railtie"
220
+ require "action_view/railtie"
221
+
222
+ I18n.load_path += Dir["./config/locales/**/*.yml"]
223
+ ```
224
+
225
+ Notice that you may not need to load ActiveSupport and ActionView lines, or even
226
+ may need to add additional requires for other libs. With this approach you have
227
+ full control on what's going to be loaded.
228
+
119
229
  ## Maintainer
120
230
 
121
231
  - [Nando Vieira](https://github.com/fnando)
data/exe/i18n CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative "../lib/i18n-js"
4
+ require_relative "../lib/i18n-js/cli"
5
5
  I18nJS::CLI.new(argv: ARGV, stdout: $stdout, stderr: $stderr).call
data/i18n-js.gemspec CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = spec.summary
13
13
  spec.license = "MIT"
14
14
  spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
15
+ spec.metadata = {"rubygems_mfa_required" => "true"}
15
16
 
16
17
  github_url = "https://github.com/fnando/i18n-js"
17
18
  github_tree_url = "#{github_url}/tree/v#{spec.version}"
data/i18njs.png ADDED
Binary file
Binary file
@@ -0,0 +1,123 @@
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
+ load_require_file!(require_file) if require_file
73
+ default_locale = I18n.default_locale
74
+ available_locales = I18n.available_locales
75
+
76
+ mapping = available_locales.each_with_object({}) do |locale, buffer|
77
+ buffer[locale] =
78
+ Glob::Map.call(Glob.filter(I18nJS.translations, ["#{locale}.*"]))
79
+ .map {|key| key.gsub(/^.*?\./, "") }
80
+ end
81
+
82
+ default_locale_keys = mapping.delete(default_locale)
83
+
84
+ ui.stdout_print "=> #{default_locale}: #{default_locale_keys.size} " \
85
+ "translations"
86
+
87
+ total_missing_count = 0
88
+
89
+ mapping.each do |locale, partial_keys|
90
+ extraneous = partial_keys - default_locale_keys
91
+ missing = default_locale_keys - (partial_keys - extraneous)
92
+ total_missing_count += missing.size
93
+ ui.stdout_print "=> #{locale}: #{missing.size} missing, " \
94
+ "#{extraneous.size} extraneous"
95
+
96
+ all_keys = (default_locale_keys + extraneous + missing).uniq.sort
97
+
98
+ all_keys.each do |key|
99
+ label = if extraneous.include?(key)
100
+ ui.yellow("extraneous")
101
+ elsif missing.include?(key)
102
+ ui.red("missing")
103
+ else
104
+ next
105
+ end
106
+
107
+ ui.stdout_print(" - #{locale}.#{key} (#{label})")
108
+ end
109
+ end
110
+
111
+ exit(1) if total_missing_count.nonzero?
112
+ end
113
+
114
+ private def set_defaults!
115
+ config_file = "./config/i18n.yml"
116
+ require_file = "./config/environment.rb"
117
+
118
+ options[:config_file] ||= config_file if File.file?(config_file)
119
+ options[:require_file] ||= require_file if File.file?(require_file)
120
+ end
121
+ end
122
+ end
123
+ 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
@@ -32,19 +32,18 @@ module I18nJS
32
32
  end
33
33
  end
34
34
 
35
- command do # rubocop:disable Metrics/BlockLength
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
@@ -1,12 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../i18n-js"
4
+ require_relative "cli/command"
5
+ require_relative "cli/ui"
6
+ require_relative "cli/init_command"
7
+ require_relative "cli/version_command"
8
+ require_relative "cli/export_command"
9
+ require_relative "cli/check_command"
10
+
3
11
  module I18nJS
4
12
  class CLI
5
13
  attr_reader :ui
6
14
 
7
- def initialize(argv:, stdout:, stderr:)
15
+ def initialize(argv:, stdout:, stderr:, colored: stdout.tty?)
8
16
  @argv = argv.dup
9
- @ui = UI.new(stdout: stdout, stderr: stderr)
17
+ @ui = UI.new(stdout: stdout, stderr: stderr, colored: colored)
10
18
  end
11
19
 
12
20
  def call
@@ -19,7 +27,7 @@ module I18nJS
19
27
  end
20
28
 
21
29
  private def command_classes
22
- [InitCommand, ExportCommand, VersionCommand]
30
+ [InitCommand, ExportCommand, VersionCommand, CheckCommand]
23
31
  end
24
32
 
25
33
  private def commands
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "listen"
4
- require "listen"
5
- require "i18n-js"
6
-
7
3
  module I18nJS
8
4
  class << self
9
5
  attr_accessor :started
@@ -16,6 +12,10 @@ module I18nJS
16
12
  return unless Rails.env.development?
17
13
  return if started
18
14
 
15
+ gem "listen"
16
+ require "listen"
17
+ require "i18n-js"
18
+
19
19
  self.started = true
20
20
 
21
21
  relative_paths =
@@ -43,7 +43,7 @@ module I18nJS
43
43
  @logger ||= ActiveSupport::TaggedLogging.new(Rails.logger)
44
44
  end
45
45
 
46
- def self.listener(config_file, locales_dir) # rubocop:disable Metrics/MethodLength
46
+ def self.listener(config_file, locales_dir)
47
47
  paths = [File.dirname(config_file), locales_dir]
48
48
 
49
49
  Listen.to(*paths) do |changed, added, removed|
@@ -58,6 +58,7 @@ module I18nJS
58
58
 
59
59
  debug(changes.map {|key, value| "#{key}=#{value.inspect}" }.join(", "))
60
60
 
61
+ ::I18n.backend.reload!
61
62
  I18nJS.call(config_file: config_file)
62
63
  end
63
64
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module I18nJS
4
- VERSION = "4.0.0.alpha1"
4
+ VERSION = "4.0.0.alpha4"
5
5
  end
data/lib/i18n-js.rb CHANGED
@@ -7,14 +7,8 @@ require "glob"
7
7
  require "fileutils"
8
8
  require "optparse"
9
9
 
10
- require_relative "./i18n-js/cli"
11
- require_relative "./i18n-js/cli/command"
12
- require_relative "./i18n-js/cli/ui"
13
- require_relative "./i18n-js/cli/init_command"
14
- require_relative "./i18n-js/cli/version_command"
15
- require_relative "./i18n-js/cli/export_command"
16
- require_relative "./i18n-js/schema"
17
- require_relative "./i18n-js/version"
10
+ require_relative "i18n-js/schema"
11
+ require_relative "i18n-js/version"
18
12
 
19
13
  module I18nJS
20
14
  MissingConfigError = Class.new(StandardError)
@@ -27,32 +21,45 @@ module I18nJS
27
21
 
28
22
  config = Glob::SymbolizeKeys.call(config || YAML.load_file(config_file))
29
23
  Schema.validate!(config)
24
+ exported_files = []
30
25
 
31
26
  config[:translations].each do |group|
32
- export_group(group)
27
+ exported_files += export_group(group)
33
28
  end
29
+
30
+ exported_files
34
31
  end
35
32
 
36
33
  def self.export_group(group)
37
34
  filtered_translations = Glob.filter(translations, group[:patterns])
38
35
  output_file_path = File.expand_path(group[:file])
36
+ exported_files = []
39
37
 
40
38
  if output_file_path.include?(":locale")
41
39
  filtered_translations.each_key do |locale|
42
40
  locale_file_path = output_file_path.gsub(/:locale/, locale.to_s)
43
- write_file(locale_file_path, locale => filtered_translations[locale])
41
+ exported_files << write_file(locale_file_path,
42
+ locale => filtered_translations[locale])
44
43
  end
45
44
  else
46
- write_file(output_file_path, filtered_translations)
45
+ exported_files << write_file(output_file_path, filtered_translations)
47
46
  end
47
+
48
+ exported_files
48
49
  end
49
50
 
50
51
  def self.write_file(file_path, translations)
51
52
  FileUtils.mkdir_p(File.dirname(file_path))
52
53
 
54
+ contents = ::JSON.pretty_generate(translations)
55
+ digest = Digest::MD5.hexdigest(contents)
56
+ file_path = file_path.gsub(/:digest/, digest)
57
+
53
58
  File.open(file_path, "w") do |file|
54
- file << ::JSON.pretty_generate(translations)
59
+ file << contents
55
60
  end
61
+
62
+ file_path
56
63
  end
57
64
 
58
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.alpha1
4
+ version: 4.0.0.alpha4
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-05-24 00:00:00.000000000 Z
11
+ date: 2022-07-21 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
@@ -193,12 +197,13 @@ homepage: https://github.com/fnando/i18n-js
193
197
  licenses:
194
198
  - MIT
195
199
  metadata:
200
+ rubygems_mfa_required: 'true'
196
201
  homepage_uri: https://github.com/fnando/i18n-js
197
202
  bug_tracker_uri: https://github.com/fnando/i18n-js/issues
198
- source_code_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha1
199
- changelog_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha1/CHANGELOG.md
200
- documentation_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha1/README.md
201
- license_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha1/LICENSE.md
203
+ source_code_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha4
204
+ changelog_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha4/CHANGELOG.md
205
+ documentation_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha4/README.md
206
+ license_uri: https://github.com/fnando/i18n-js/tree/v4.0.0.alpha4/LICENSE.md
202
207
  post_install_message:
203
208
  rdoc_options: []
204
209
  require_paths:
@@ -214,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
219
  - !ruby/object:Gem::Version
215
220
  version: 1.3.1
216
221
  requirements: []
217
- rubygems_version: 3.2.15
222
+ rubygems_version: 3.3.7
218
223
  signing_key:
219
224
  specification_version: 4
220
225
  summary: Export i18n translations and use them on JavaScript.