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 +4 -4
- data/CHANGES.md +4 -0
- data/README.md +9 -12
- data/bin/i18n-tasks +2 -6
- data/i18n-tasks.gemspec +4 -5
- data/lib/i18n/tasks.rb +1 -4
- data/lib/i18n/tasks/base_task.rb +2 -0
- data/lib/i18n/tasks/commands_base.rb +2 -3
- data/lib/i18n/tasks/configuration.rb +13 -5
- data/lib/i18n/tasks/data/storage/file_storage.rb +22 -0
- data/lib/i18n/tasks/logging.rb +15 -0
- data/lib/i18n/tasks/missing_keys.rb +1 -1
- data/lib/i18n/tasks/version.rb +1 -1
- data/spec/file_system_data_spec.rb +60 -28
- data/spec/plural_keys_spec.rb +43 -0
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 188bad44ecd17931f47d9a52c8c757090f01b44c
|
4
|
+
data.tar.gz: b2be17a08191fed3f80262d829c0a2d6251d3318
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ceecebcd0b87015d6d5487f7a4e6e658f76a066d3960cf7b55e741ecbd7f99445c8110cb5b7a33f18f1319d27c6fbab014a7209e57033c071dc220fd815d419
|
7
|
+
data.tar.gz: 1de63c98ea3c1e7ad37cd00359e8e7e1cda7cdadfa454b44a7e7ae9a84a0b7789c96828d3093e3ac2bd45095f303fe21f9e4d65d7c37cbd356047505139cc077
|
data/CHANGES.md
CHANGED
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
|
-
|
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,
|
116
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
data/lib/i18n/tasks/base_task.rb
CHANGED
@@ -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
|
-
|
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 =
|
52
|
-
|
53
|
-
|
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
|
-
|
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] ||
|
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
|
-
|
29
|
+
warn_deprecated '#untranslated_keys. Please use #missing_keys instead'
|
30
30
|
missing_keys(locales: locales)
|
31
31
|
end
|
32
32
|
|
data/lib/i18n/tasks/version.rb
CHANGED
@@ -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
|
-
|
6
|
-
|
37
|
+
let(:data) { I18n::Tasks::Data::FileSystem.new }
|
38
|
+
after { TestCodebase.teardown }
|
7
39
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
38
|
-
|
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.
|
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
|
+
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
|
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
|
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
|