i18n-tasks 0.3.4 → 0.3.5

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
  SHA1:
3
- metadata.gz: 68c94e2f16413ec396e24e366c2d22107423e5e4
4
- data.tar.gz: 16680455229c39bbfd63b57e6ebeac977041ff98
3
+ metadata.gz: 188bad44ecd17931f47d9a52c8c757090f01b44c
4
+ data.tar.gz: b2be17a08191fed3f80262d829c0a2d6251d3318
5
5
  SHA512:
6
- metadata.gz: a5410cf4b6b5c92058a751fbde9302b8a0fb5c65e3d640e296b6148364ceba9e93eb4299ea07c84c911d7c616129115d3220c042c6e7d56af2bf20cc9d21e06e
7
- data.tar.gz: fff053a40cc87b6c183930cda9b3db27849b94969cfaf32bec104bdf89015e3764d8eb6ca6997fba2c76d51ad994dae2d38302f57a353c281b6281e414bf61af
6
+ metadata.gz: 2ceecebcd0b87015d6d5487f7a4e6e658f76a066d3960cf7b55e741ecbd7f99445c8110cb5b7a33f18f1319d27c6fbab014a7209e57033c071dc220fd815d419
7
+ data.tar.gz: 1de63c98ea3c1e7ad37cd00359e8e7e1cda7cdadfa454b44a7e7ae9a84a0b7789c96828d3093e3ac2bd45095f303fe21f9e4d65d7c37cbd356047505139cc077
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## v0.3.5
2
+
3
+ * `config.locales` is now picked up by default from paths do data files. `base_locale` defaults to `en`.
4
+
1
5
  ## v0.3.3..v0.3.4
2
6
 
3
7
  * Bugfixes
data/README.md CHANGED
@@ -11,20 +11,12 @@ This information is inferred based on the keys the gem detects used with calls s
11
11
 
12
12
  ## Installation
13
13
 
14
- 1. Add to Gemfile:
14
+ Add to Gemfile:
15
15
 
16
16
  ```ruby
17
17
  gem 'i18n-tasks', '~> 0.3.2'
18
18
  ```
19
19
 
20
- 2. Create a config file at `config/i18n-tasks.yml`:
21
-
22
- ```yaml
23
- # config/i18n-tasks.yml
24
- base_locale: en
25
- locales: [es, fr] # This includes base_locale by default
26
- ```
27
-
28
20
  ## Usage
29
21
 
30
22
  Run `i18n-tasks` to get the list of tasks with short descriptions.
@@ -112,9 +104,8 @@ Inspect configuration with `i18n-tasks config`.
112
104
 
113
105
  ### Locales
114
106
 
115
- By default, i18n-tasks will read `I18n.default_locale` and `I18n.available_locales`.
116
- However, i18n-tasks does not load application environment by default,
117
- so it is recommended to set locale settings explicitly:
107
+ By default, `base_locale` is set to `en` and `locales` are inferred from the paths to data files.
108
+ You can override these in the config:
118
109
 
119
110
  ```yaml
120
111
  # config/i18n-tasks.yml
@@ -127,6 +118,7 @@ locales: [es, fr] # This includes base_locale by default
127
118
  The default data adapter supports YAML and JSON files.
128
119
 
129
120
  ```yaml
121
+ # config/i18n-tasks.yml
130
122
  # i18n data storage
131
123
  data:
132
124
  # file_system is the default adapter, you can provide a custom class name here:
@@ -156,6 +148,7 @@ data:
156
148
  Example:
157
149
 
158
150
  ```yaml
151
+ # config/i18n-tasks.yml
159
152
  data:
160
153
  write:
161
154
  # store sorcery and simple_form keys in the respective files:
@@ -170,6 +163,7 @@ data:
170
163
  Configure usage search in `config/i18n-tasks.yml`:
171
164
 
172
165
  ```yaml
166
+ # config/i18n-tasks.yml
173
167
  # i18n usage search in source
174
168
  search:
175
169
  # search these directories (relative to your Rails.root directory, default: 'app/')
@@ -191,6 +185,7 @@ search:
191
185
  To configure paths for relative key resolution:
192
186
 
193
187
  ```yaml
188
+ # config/i18n-tasks.yml
194
189
  # directories containing relative keys
195
190
  relative_roots:
196
191
  # default:
@@ -209,6 +204,7 @@ Tasks may incorrectly report framework i18n keys as missing, also some patterns
209
204
  When all else fails, use the options below.
210
205
 
211
206
  ```yaml
207
+ # config/i18n-tasks.yml
212
208
  # do not report these keys as unused
213
209
  ignore_unused:
214
210
  - category.*.db_name
@@ -240,6 +236,7 @@ ignore:
240
236
  Put the key in `GOOGLE_TRANSLATE_API_KEY` environment variable or in the config file.
241
237
 
242
238
  ```yaml
239
+ # config/i18n-tasks.yml
243
240
  translation:
244
241
  api_key: <Google Translate API key>
245
242
  ```
data/bin/i18n-tasks CHANGED
@@ -28,15 +28,11 @@ if command
28
28
  args = command[2]
29
29
 
30
30
  if opts.empty? && args.empty?
31
- if ENV['VERBOSE']
32
- STDERR.puts Term::ANSIColor.green "i18n-tasks: run #{meth.tr('_', '-')} without arguments"
33
- end
31
+ ::I18n::Tasks.log_verbose "run #{meth.tr('_', '-')} without arguments"
34
32
  cmd.send meth
35
33
  else
36
34
  opts = opts.merge(arguments: args) unless args.empty?
37
- if ENV['VERBOSE']
38
- STDERR.puts Term::ANSIColor.green "i18n-tasks: run #{meth.tr('_', '-')} with #{opts.map { |k, v| "#{k}=#{v}" } * ' '}"
39
- end
35
+ ::I18n::Tasks.log_verbose "run #{meth.tr('_', '-')} with #{opts.map { |k, v| "#{k}=#{v}" } * ' '}"
40
36
  cmd.send meth, opts
41
37
  end
42
38
  else
data/i18n-tasks.gemspec CHANGED
@@ -10,13 +10,12 @@ Gem::Specification.new do |s|
10
10
  s.email = ['glex.spb@gmail.com']
11
11
  s.summary = %q{Manage translations in ruby applications with the awesome power of static analysis — Edit}
12
12
  s.description = %q{
13
- The basic approach to i18n key management in frameworks such as Rails has many flaws.
14
-
13
+ The basic approach to i18n key management in frameworks such as Rails is far from perfect.
15
14
  If you use a key that does not exist, this will only blow up at runtime. Keys left over from removed code accumulate
16
- in the resource files, introducing unnecessary overhead on the translators.
17
- Translation files can quickly turn to disarray.
15
+ in the resource files, introducing unnecessary overhead on the translators. Translation files can quickly turn to disarray.
18
16
 
19
- i18n-tasks solves this problem with static analysis.
17
+ i18n-tasks improves this by using static analysis. It provides tasks to find and manage missing and unused translations.
18
+ This information is inferred based on the keys the gem detects used with calls such as `I18n.t` when scanning the code.
20
19
  }
21
20
  s.homepage = 'https://github.com/glebm/i18n-tasks'
22
21
  if s.respond_to?(:metadata=)
data/lib/i18n/tasks.rb CHANGED
@@ -25,10 +25,7 @@ module I18n
25
25
  HashWithIndifferentAccess.new.merge(file.presence || {})
26
26
  end
27
27
  end
28
-
29
- def warn_deprecated(message)
30
- STDERR.puts Term::ANSIColor.yellow Term::ANSIColor.bold "i18n-tasks: [DEPRECATED] #{message}"
31
- end
28
+ include ::I18n::Tasks::Logging
32
29
  end
33
30
  end
34
31
  end
@@ -10,6 +10,7 @@ require 'i18n/tasks/missing_keys'
10
10
  require 'i18n/tasks/unused_keys'
11
11
  require 'i18n/tasks/google_translation'
12
12
  require 'i18n/tasks/fill_tasks'
13
+ require 'i18n/tasks/logging'
13
14
 
14
15
  module I18n
15
16
  module Tasks
@@ -26,6 +27,7 @@ module I18n
26
27
  include TranslationData
27
28
  include FillTasks
28
29
  include GoogleTranslation
30
+ include Logging
29
31
 
30
32
  def initialize(config = {})
31
33
  self.config = config || {}
@@ -1,6 +1,7 @@
1
1
  require 'ostruct'
2
2
  module I18n::Tasks
3
3
  class CommandsBase
4
+ include ::I18n::Tasks::Logging
4
5
  def locales_opt(locales)
5
6
  return i18n_task.locales if locales == ['all'] || locales == 'all'
6
7
  if locales.present?
@@ -14,9 +15,7 @@ module I18n::Tasks
14
15
 
15
16
  def locales_opt_or_args(opt)
16
17
  locales_opt(opt[:arguments].presence || opt[:locales]).tap do |locales|
17
- if ENV['VERBOSE']
18
- STDERR.puts Term::ANSIColor.green "i18n-tasks: locales are #{locales.inspect}"
19
- end
18
+ log_verbose "locales for the command are #{locales.inspect}"
20
19
  end
21
20
  end
22
21
 
@@ -48,18 +48,26 @@ module I18n::Tasks::Configuration
48
48
  # @return [Array<String>] all available locales, base_locale is always first
49
49
  def locales
50
50
  @config_sections[:locales] ||= begin
51
- locales = (config[:locales] || I18n.available_locales).map(&:to_s)
52
- if locales.include?(base_locale)
53
- [base_locale] + (locales - [base_locale])
51
+ locales = config[:locales]
52
+ locales ||= data.available_locales
53
+ locales = locales.map(&:to_s)
54
+ locales = if locales.include?(base_locale)
55
+ [base_locale] + (locales - [base_locale])
56
+ else
57
+ [base_locale] + locales
58
+ end
59
+ if config[:locales]
60
+ log_verbose "config.locales set to #{locales}"
54
61
  else
55
- [base_locale] + locales
62
+ log_verbose "config.locales inferred from data #{locales}"
56
63
  end
64
+ locales
57
65
  end
58
66
  end
59
67
 
60
68
  # @return [String] default i18n locale
61
69
  def base_locale
62
- @config_sections[:base_locale] ||= config[:base_locale] || I18n.default_locale.to_s
70
+ @config_sections[:base_locale] ||= (config[:base_locale] || 'en').to_s
63
71
  end
64
72
 
65
73
  # evaluated configuration (as the app sees it)
@@ -71,6 +71,28 @@ module I18n::Tasks
71
71
 
72
72
  def reload
73
73
  @locale_data = {}
74
+ @available_locales = nil
75
+ self
76
+ end
77
+
78
+ # Get available locales from the list of file names to read
79
+ def available_locales
80
+ @available_locales ||= begin
81
+ locales = Set.new
82
+ @read.map do |pattern|
83
+ [pattern, Dir.glob(pattern % {locale: '*'})] if pattern.include?('%{locale}')
84
+ end.compact.each do |pattern, paths|
85
+ p = pattern.gsub('\\', '\\\\').gsub('/', '\/').gsub('.', '\.')
86
+ p = p.gsub(/(\*+)/) { $1 == '**' ? '.*' : '[^/]*?' }.gsub('%{locale}', '([^/.]+)')
87
+ re = /\A#{p}\z/
88
+ paths.each do |path|
89
+ if re =~ path
90
+ locales << $1
91
+ end
92
+ end
93
+ end
94
+ locales
95
+ end
74
96
  end
75
97
 
76
98
  protected
@@ -0,0 +1,15 @@
1
+ module I18n::Tasks::Logging
2
+ def warn_deprecated(message)
3
+ log_stderr Term::ANSIColor.yellow Term::ANSIColor.bold "i18n-tasks: [DEPRECATED] #{message}"
4
+ end
5
+
6
+ def log_verbose(message)
7
+ if ENV['VERBOSE']
8
+ log_stderr Term::ANSIColor.green "i18n-tasks: #{message}"
9
+ end
10
+ end
11
+
12
+ def log_stderr(*args)
13
+ STDERR.puts *args
14
+ end
15
+ end
@@ -26,7 +26,7 @@ module I18n::Tasks
26
26
  end
27
27
 
28
28
  def untranslated_keys(locales = nil)
29
- I18n::Tasks.warn_deprecated("#untranslated_keys. Please use #missing_keys instead")
29
+ warn_deprecated '#untranslated_keys. Please use #missing_keys instead'
30
30
  missing_keys(locales: locales)
31
31
  end
32
32
 
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module Tasks
3
- VERSION = '0.3.4'
3
+ VERSION = '0.3.5'
4
4
  end
5
5
  end
@@ -1,41 +1,73 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'File system i18n' do
4
+ describe '#available_locales' do
5
+ before do
6
+ TestCodebase.setup(
7
+ 'config/locales/en.yml' => {en: {}},
8
+ 'config/locales/es.yml' => {es: {}},
9
+ 'config/locales/other.fr.yml' => {fr: {}}
10
+ )
11
+ end
12
+ after do
13
+ TestCodebase.teardown
14
+ end
15
+ let(:data) { I18n::Tasks::Data::FileSystem.new }
16
+ it 'default pattern' do
17
+ data.config = {read: ['config/locales/%{locale}.yml']}
18
+ TestCodebase.in_test_app_dir {
19
+ expect(data.available_locales.sort).to eq(%w(en es).sort)
20
+ }
21
+ end
22
+ it 'more inclusive pattern' do
23
+ data.config = {read: ['config/locales/*%{locale}.yml']}
24
+ TestCodebase.in_test_app_dir {
25
+ expect(data.available_locales.sort).to eq(%w(en es fr).sort)
26
+ }
27
+ end
28
+ it 'another pattern' do
29
+ data.config = {read: ['config/locales/*.%{locale}.yml']}
30
+ TestCodebase.in_test_app_dir {
31
+ expect(data.available_locales.sort).to eq(%w(fr).sort)
32
+ }
33
+ end
34
+ end
35
+
4
36
  describe 'yml' do
5
- let!(:data) { I18n::Tasks::Data::FileSystem.new }
6
- after { TestCodebase.teardown }
37
+ let(:data) { I18n::Tasks::Data::FileSystem.new }
38
+ after { TestCodebase.teardown }
7
39
 
8
- it 'reads' do
9
- data.config = {read: ['a.yml', '{b,c}.yml']}
10
- TestCodebase.setup(
11
- 'a.yml' => {en: {a: 1}}.stringify_keys.to_yaml,
12
- 'b.yml' => {en: {b: 1}}.stringify_keys.to_yaml,
13
- 'c.yml' => {en: {c: 1}}.stringify_keys.to_yaml
14
- )
15
- TestCodebase.in_test_app_dir {
16
- data[:en].symbolize_keys.should == {a: 1, b: 1, c: 1}
17
- }
18
- end
40
+ it '#get' do
41
+ data.config = {read: ['a.yml', '{b,c}.yml']}
42
+ TestCodebase.setup(
43
+ 'a.yml' => {en: {a: 1}}.stringify_keys.to_yaml,
44
+ 'b.yml' => {en: {b: 1}}.stringify_keys.to_yaml,
45
+ 'c.yml' => {en: {c: 1}}.stringify_keys.to_yaml
46
+ )
47
+ TestCodebase.in_test_app_dir {
48
+ expect(data[:en].symbolize_keys).to eq(a: 1, b: 1, c: 1)
49
+ }
50
+ end
19
51
 
20
- it 'writes' do
21
- data.config = {read: 'a.yml', write: [['{:}.*', '\1.%{locale}.yml']]}
22
- keys = {'a' => {'b' => 'c'}, 'x' => 'y'}
23
- locale_data = {'pizza' => keys, 'sushi' => keys}
24
- TestCodebase.setup
25
- TestCodebase.in_test_app_dir {
26
- data[:en] = locale_data
27
- files = %w(pizza.en.yml sushi.en.yml)
28
- Dir['*.yml'].sort.should == files.sort
29
- files.each { |f| YAML.load_file(f)['en'].should == {File.basename(f, '.en.yml') => keys} }
30
- }
31
- end
52
+ it '#set' do
53
+ data.config = {read: 'a.yml', write: [['{:}.*', '\1.%{locale}.yml']]}
54
+ keys = {'a' => {'b' => 'c'}, 'x' => 'y'}
55
+ locale_data = {'pizza' => keys, 'sushi' => keys}
56
+ TestCodebase.setup
57
+ TestCodebase.in_test_app_dir {
58
+ data[:en] = locale_data
59
+ files = %w(pizza.en.yml sushi.en.yml)
60
+ Dir['*.yml'].sort.should == files.sort
61
+ files.each { |f| YAML.load_file(f)['en'].should == {File.basename(f, '.en.yml') => keys} }
62
+ }
63
+ end
32
64
  end
33
65
 
34
66
  describe 'json' do
35
67
  let!(:data) {
36
68
  I18n::Tasks::Data::FileSystem.new(
37
- read: ['config/locales/%{locale}.json'],
38
- write: ['config/locales/%{locale}.json']
69
+ read: ['config/locales/%{locale}.json'],
70
+ write: ['config/locales/%{locale}.json']
39
71
  )
40
72
  }
41
73
  after { TestCodebase.teardown }
@@ -48,7 +80,7 @@ describe 'File system i18n' do
48
80
  'c.json' => {en: {c: 1}}.stringify_keys.to_json
49
81
  )
50
82
  TestCodebase.in_test_app_dir {
51
- data[:en].symbolize_keys.should == {a: 1, b: 1, c: 1}
83
+ expect(data[:en].symbolize_keys).to eq(a: 1, b: 1, c: 1)
52
84
  }
53
85
  end
54
86
 
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Plural keys' do
4
+ let(:task) { ::I18n::Tasks::BaseTask.new }
5
+ before do
6
+ TestCodebase.setup('config/locales/en.yml' => '')
7
+ TestCodebase.in_test_app_dir do
8
+ task.data['en'] = {
9
+ 'regular_key' => 'a',
10
+ 'plural_key' => {
11
+ 'one' => 'one', 'other' => '%{count}'
12
+ },
13
+ 'not_really_plural' => {
14
+ 'one' => 'a',
15
+ 'green' => 'b'
16
+ }
17
+ }
18
+ task.data['en']
19
+ end
20
+ end
21
+
22
+ describe '#depluralize_key' do
23
+ it 'depluralizes plural keys' do
24
+ expect(depluralize('plural_key.one')).to eq('plural_key')
25
+ end
26
+
27
+ it 'ignores regular keys' do
28
+ expect(depluralize('regular_key')).to eq('regular_key')
29
+ end
30
+
31
+ it 'ignores keys that look like plural but are not' do
32
+ expect(depluralize('not_really_plural.one')).to eq('not_really_plural.one')
33
+ end
34
+
35
+ def depluralize(key)
36
+ task.depluralize_key('en', key)
37
+ end
38
+ end
39
+
40
+ after do
41
+ TestCodebase.teardown
42
+ end
43
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
@@ -180,13 +180,12 @@ dependencies:
180
180
  version: '0'
181
181
  description: |2
182
182
 
183
- The basic approach to i18n key management in frameworks such as Rails has many flaws.
184
-
183
+ The basic approach to i18n key management in frameworks such as Rails is far from perfect.
185
184
  If you use a key that does not exist, this will only blow up at runtime. Keys left over from removed code accumulate
186
- in the resource files, introducing unnecessary overhead on the translators.
187
- Translation files can quickly turn to disarray.
185
+ in the resource files, introducing unnecessary overhead on the translators. Translation files can quickly turn to disarray.
188
186
 
189
- i18n-tasks solves this problem with static analysis.
187
+ i18n-tasks improves this by using static analysis. It provides tasks to find and manage missing and unused translations.
188
+ This information is inferred based on the keys the gem detects used with calls such as `I18n.t` when scanning the code.
190
189
  email:
191
190
  - glex.spb@gmail.com
192
191
  executables:
@@ -224,6 +223,7 @@ files:
224
223
  - lib/i18n/tasks/key/usages.rb
225
224
  - lib/i18n/tasks/key_group.rb
226
225
  - lib/i18n/tasks/key_pattern_matching.rb
226
+ - lib/i18n/tasks/logging.rb
227
227
  - lib/i18n/tasks/missing_keys.rb
228
228
  - lib/i18n/tasks/plural_keys.rb
229
229
  - lib/i18n/tasks/relative_keys.rb
@@ -249,6 +249,7 @@ files:
249
249
  - spec/key_group_spec.rb
250
250
  - spec/key_pattern_matching_spec.rb
251
251
  - spec/pattern_scanner_spec.rb
252
+ - spec/plural_keys_spec.rb
252
253
  - spec/readme_spec.rb
253
254
  - spec/relative_keys_spec.rb
254
255
  - spec/spec_helper.rb
@@ -297,6 +298,7 @@ test_files:
297
298
  - spec/key_group_spec.rb
298
299
  - spec/key_pattern_matching_spec.rb
299
300
  - spec/pattern_scanner_spec.rb
301
+ - spec/plural_keys_spec.rb
300
302
  - spec/readme_spec.rb
301
303
  - spec/relative_keys_spec.rb
302
304
  - spec/spec_helper.rb