i18n-tasks 0.3.4 → 0.3.5

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
  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