i18n-tasks 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/README.md +6 -3
- data/i18n-tasks.gemspec +5 -2
- data/lib/i18n/tasks.rb +3 -5
- data/lib/i18n/tasks/commands_base.rb +5 -0
- data/lib/i18n/tasks/fill_tasks.rb +1 -3
- data/lib/i18n/tasks/key_pattern_matching.rb +0 -16
- data/lib/i18n/tasks/missing_keys.rb +0 -5
- data/lib/i18n/tasks/translation_data.rb +0 -3
- data/lib/i18n/tasks/version.rb +1 -1
- data/spec/google_translate_spec.rb +34 -5
- data/spec/i18n_tasks_spec.rb +11 -15
- data/spec/support/test_codebase.rb +18 -0
- metadata +6 -4
- data/lib/i18n/tasks/data/yaml.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b81678a0e44f5c7593956fbe37f122aff4cdb7fc
|
4
|
+
data.tar.gz: e5bbc6aa629d379ab04551f00d706e714b2b845c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5151ef672fedd86b317900c2621b03a09748e3275efd39221626f101dd895a53336c76ef73e2e973287c40af6d38130323cc89fa178fe0e2bce92fc3d705120
|
7
|
+
data.tar.gz: ec27bed50ae7691827b57619437ce3e3b943a0b01b658e7d350a12ef0af5fa20b921209534ec766e46a8e9864f90fbc67f909c3f15d097263bd0a35845378997
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# i18n-tasks [![Build Status][badge-travis]][travis] [![Coverage Status][badge-coveralls]][coveralls] [![Code Climate][badge-code-climate]][code-climate] [![Flattr this][badge-flattr]][flattr]
|
2
2
|
|
3
|
+
i18n-tasks finds and manages missing and unused translations in your application.
|
4
|
+
|
3
5
|
The basic approach to i18n key management in frameworks such as Rails is far from perfect.
|
4
6
|
If you use a key that does not exist, this will only blow up at runtime. Keys left over from removed code accumulate
|
5
7
|
in the resource files, introducing unnecessary overhead on the translators. Translation files can quickly turn to disarray.
|
6
8
|
|
7
|
-
i18n-tasks improves this by using static analysis. It
|
8
|
-
|
9
|
+
i18n-tasks improves this by using static analysis. It scans calls such as `I18n.t('some.key')` and uses this information to
|
10
|
+
provide reports on key usage, missing and unused keys, and can prefill missing keys, including from Google Translate,
|
11
|
+
and can also remove unused keys.
|
9
12
|
|
10
13
|
<img width="534" height="288" src="https://raw.github.com/glebm/i18n-tasks/master/doc/img/i18n-tasks.png">
|
11
14
|
|
@@ -14,7 +17,7 @@ This information is inferred based on the keys the gem detects used with calls s
|
|
14
17
|
Add to Gemfile:
|
15
18
|
|
16
19
|
```ruby
|
17
|
-
gem 'i18n-tasks', '~> 0.3.
|
20
|
+
gem 'i18n-tasks', '~> 0.3.5'
|
18
21
|
```
|
19
22
|
|
20
23
|
## Usage
|
data/i18n-tasks.gemspec
CHANGED
@@ -10,12 +10,15 @@ 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
|
+
i18n-tasks finds and manages missing and unused translations in your application.
|
14
|
+
|
13
15
|
The basic approach to i18n key management in frameworks such as Rails is far from perfect.
|
14
16
|
If you use a key that does not exist, this will only blow up at runtime. Keys left over from removed code accumulate
|
15
17
|
in the resource files, introducing unnecessary overhead on the translators. Translation files can quickly turn to disarray.
|
16
18
|
|
17
|
-
i18n-tasks improves this by using static analysis. It
|
18
|
-
|
19
|
+
i18n-tasks improves this by using static analysis. It scans calls such as `I18n.t('some.key')` and uses this information to
|
20
|
+
provide reports on key usage, missing and unused keys, and can prefill missing keys, including from Google Translate,
|
21
|
+
and can also remove unused keys.
|
19
22
|
}
|
20
23
|
s.homepage = 'https://github.com/glebm/i18n-tasks'
|
21
24
|
if s.respond_to?(:metadata=)
|
data/lib/i18n/tasks.rb
CHANGED
@@ -19,11 +19,9 @@ module I18n
|
|
19
19
|
)
|
20
20
|
class << self
|
21
21
|
def config
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
HashWithIndifferentAccess.new.merge(file.presence || {})
|
26
|
-
end
|
22
|
+
file = CONFIG_FILES.detect { |f| File.exists?(f) }
|
23
|
+
file = YAML.load(Erubis::Eruby.new(File.read(file)).result) if file
|
24
|
+
HashWithIndifferentAccess.new.merge(file.presence || {})
|
27
25
|
end
|
28
26
|
include ::I18n::Tasks::Logging
|
29
27
|
end
|
@@ -2,6 +2,11 @@ require 'ostruct'
|
|
2
2
|
module I18n::Tasks
|
3
3
|
class CommandsBase
|
4
4
|
include ::I18n::Tasks::Logging
|
5
|
+
|
6
|
+
def initialize(i18n_task = nil)
|
7
|
+
@i18n_task = i18n_task
|
8
|
+
end
|
9
|
+
|
5
10
|
def locales_opt(locales)
|
6
11
|
return i18n_task.locales if locales == ['all'] || locales == 'all'
|
7
12
|
if locales.present?
|
@@ -13,9 +13,7 @@ module I18n::Tasks::FillTasks
|
|
13
13
|
locales: non_base_locales(opts[:locales]),
|
14
14
|
keys: proc { |locale| keys_to_fill(locale).select(&t_proc(from)).select { |k| t(k).is_a?(String) } },
|
15
15
|
values: proc { |keys, locale|
|
16
|
-
google_translate
|
17
|
-
to: locale,
|
18
|
-
from: from
|
16
|
+
google_translate(keys.zip(keys.map(&t_proc(from))), to: locale, from: from).map(&:last)
|
19
17
|
}
|
20
18
|
)
|
21
19
|
update_data opts
|
@@ -28,20 +28,4 @@ module I18n::Tasks::KeyPatternMatching
|
|
28
28
|
gsub(/:/, '(?<=^|\.)[^.]+?(?=\.|$)').
|
29
29
|
gsub(/\{(.*?)}/) { "(#{$1.strip.gsub /\s*,\s*/, '|'})" }
|
30
30
|
end
|
31
|
-
|
32
|
-
# @return [Array<String>] keys sans passed patterns
|
33
|
-
def exclude_patterns(keys, patterns)
|
34
|
-
pattern_re = compile_patterns_re patterns.select { |p| p.end_with?('.') }
|
35
|
-
(keys - patterns).reject { |k| k =~ pattern_re }
|
36
|
-
end
|
37
|
-
|
38
|
-
# compile prefix matching Regexp from the list of prefixes
|
39
|
-
# @return [Regexp] regexp matching any of the prefixes
|
40
|
-
def compile_start_with_re(prefixes)
|
41
|
-
if prefixes.blank?
|
42
|
-
MATCH_NOTHING # match nothing
|
43
|
-
else
|
44
|
-
/^(?:#{prefixes.map { |p| Regexp.escape(p) }.join('|')})/
|
45
|
-
end
|
46
|
-
end
|
47
31
|
end
|
@@ -25,11 +25,6 @@ module I18n::Tasks
|
|
25
25
|
@missing_keys_types ||= [:missing_from_base, :eq_base, :missing_from_locale]
|
26
26
|
end
|
27
27
|
|
28
|
-
def untranslated_keys(locales = nil)
|
29
|
-
warn_deprecated '#untranslated_keys. Please use #missing_keys instead'
|
30
|
-
missing_keys(locales: locales)
|
31
|
-
end
|
32
|
-
|
33
28
|
# @return [KeyGroup] missing keys, i.e. key that are in the code but are not in the base locale data
|
34
29
|
def keys_missing_from_base
|
35
30
|
@keys_missing_from_base ||= begin
|
data/lib/i18n/tasks/version.rb
CHANGED
@@ -1,14 +1,43 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'i18n/tasks/commands'
|
2
3
|
|
3
4
|
describe 'Google Translation' do
|
4
5
|
include I18n::Tasks::GoogleTranslation
|
5
6
|
|
7
|
+
TEST_STRING = 'Hello, %{user}!'
|
8
|
+
TEST_RESULT = 'Hola, %{user}!'
|
9
|
+
|
6
10
|
if ENV['GOOGLE_TRANSLATE_API_KEY']
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
describe 'real world test' do
|
12
|
+
delegate :i18n_cmd, :i18n_task, :in_test_app_dir, to: :TestCodebase
|
13
|
+
|
14
|
+
context 'API' do
|
15
|
+
it 'works' do
|
16
|
+
google_translate(
|
17
|
+
[['common.hello', TEST_STRING]], from: :en, to: :es, key: ENV['GOOGLE_TRANSLATE_API_KEY']
|
18
|
+
).should == [['common.hello', TEST_RESULT]]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
TestCodebase.setup('config/locales/en.yml' => '', 'config/locales/es.yml' => '')
|
24
|
+
end
|
25
|
+
|
26
|
+
after do
|
27
|
+
TestCodebase.teardown
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'command' do
|
31
|
+
let(:task) { i18n_task }
|
32
|
+
let(:cmd) { i18n_cmd(task) }
|
33
|
+
|
34
|
+
it 'works' do
|
35
|
+
in_test_app_dir do
|
36
|
+
task.data[:en] = {'common' => {'hello' => TEST_STRING}}
|
37
|
+
cmd.translate_missing
|
38
|
+
expect(task.data[:es]['common']['hello']).to eq(TEST_RESULT)
|
39
|
+
end
|
40
|
+
end
|
12
41
|
end
|
13
42
|
end
|
14
43
|
end
|
data/spec/i18n_tasks_spec.rb
CHANGED
@@ -4,11 +4,7 @@ require 'i18n/tasks/commands'
|
|
4
4
|
require 'fileutils'
|
5
5
|
|
6
6
|
describe 'i18n-tasks' do
|
7
|
-
|
8
|
-
TestCodebase.in_test_app_dir do
|
9
|
-
capture_stdout { ::I18n::Tasks::Commands.new.send(name, *args, &block) }
|
10
|
-
end
|
11
|
-
end
|
7
|
+
delegate :run_cmd, :i18n_task, :in_test_app_dir, to: :TestCodebase
|
12
8
|
|
13
9
|
describe 'missing' do
|
14
10
|
let (:expected_missing_keys) {
|
@@ -39,8 +35,8 @@ describe 'i18n-tasks' do
|
|
39
35
|
|
40
36
|
describe 'remove_unused' do
|
41
37
|
it 'removes unused' do
|
42
|
-
|
43
|
-
t =
|
38
|
+
in_test_app_dir do
|
39
|
+
t = i18n_task
|
44
40
|
expected_unused_keys.each do |key|
|
45
41
|
expect(t.key_value?(key, :en)).to be_true
|
46
42
|
expect(t.key_value?(key, :es)).to be_true
|
@@ -60,7 +56,7 @@ describe 'i18n-tasks' do
|
|
60
56
|
|
61
57
|
describe 'normalize' do
|
62
58
|
it 'moves keys to the corresponding files as per data.write' do
|
63
|
-
|
59
|
+
in_test_app_dir {
|
64
60
|
expect(File).to_not exist 'config/locales/devise.en.yml'
|
65
61
|
run_cmd :normalize
|
66
62
|
expect(YAML.load_file('config/locales/devise.en.yml')['en']['devise']['a']).to eq 'EN_TEXT'
|
@@ -70,7 +66,7 @@ describe 'i18n-tasks' do
|
|
70
66
|
|
71
67
|
describe 'xlsx_report' do
|
72
68
|
it 'saves' do
|
73
|
-
|
69
|
+
in_test_app_dir {
|
74
70
|
capture_stderr { run_cmd :xlsx_report }
|
75
71
|
expect(File).to exist 'tmp/i18n-report.xlsx'
|
76
72
|
FileUtils.cp('tmp/i18n-report.xlsx', '..')
|
@@ -81,21 +77,21 @@ describe 'i18n-tasks' do
|
|
81
77
|
|
82
78
|
describe 'add_missing' do
|
83
79
|
it 'default placeholder' do
|
84
|
-
|
80
|
+
in_test_app_dir {
|
85
81
|
expect(YAML.load_file('config/locales/en.yml')['en']['used_but_missing']).to be_nil
|
86
82
|
}
|
87
83
|
run_cmd :add_missing, locales: 'base'
|
88
|
-
|
84
|
+
in_test_app_dir {
|
89
85
|
expect(YAML.load_file('config/locales/en.yml')['en']['used_but_missing']['a']).to eq 'A'
|
90
86
|
}
|
91
87
|
end
|
92
88
|
|
93
89
|
it 'placeholder: value' do
|
94
|
-
|
90
|
+
in_test_app_dir {
|
95
91
|
expect(YAML.load_file('config/locales/es.yml')['es']['missing_in_es']).to be_nil
|
96
92
|
}
|
97
93
|
run_cmd :add_missing, locales: 'all', placeholder: 'TRME'
|
98
|
-
|
94
|
+
in_test_app_dir {
|
99
95
|
expect(YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a']).to eq 'TRME'
|
100
96
|
# does not touch existing, but moves to the right file:
|
101
97
|
expect(YAML.load_file('config/locales/devise.es.yml')['es']['devise']['a']).to eq 'ES_TEXT'
|
@@ -106,7 +102,7 @@ describe 'i18n-tasks' do
|
|
106
102
|
describe 'config' do
|
107
103
|
it 'prints config' do
|
108
104
|
expect(YAML.load(run_cmd :config)).to(
|
109
|
-
eq
|
105
|
+
eq(in_test_app_dir { i18n_task.config_for_inspect })
|
110
106
|
)
|
111
107
|
end
|
112
108
|
end
|
@@ -126,7 +122,7 @@ TXT
|
|
126
122
|
|
127
123
|
# --- setup ---
|
128
124
|
BENCH_KEYS = 100
|
129
|
-
before do
|
125
|
+
before(:each) do
|
130
126
|
gen_data = ->(v) {
|
131
127
|
v_num = v.chars.map(&:ord).join('').to_i
|
132
128
|
{
|
@@ -7,6 +7,24 @@ module TestCodebase
|
|
7
7
|
extend self
|
8
8
|
AT = 'tmp/test_codebase'
|
9
9
|
|
10
|
+
def i18n_task(*args)
|
11
|
+
TestCodebase.in_test_app_dir do
|
12
|
+
::I18n::Tasks::BaseTask.new(*args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def i18n_cmd(*args)
|
17
|
+
TestCodebase.in_test_app_dir do
|
18
|
+
::I18n::Tasks::Commands.new(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_cmd(name, *args, &block)
|
23
|
+
in_test_app_dir do
|
24
|
+
capture_stdout { i18n_cmd.send(name, *args, &block) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
10
28
|
def setup(files = {})
|
11
29
|
FileUtils.mkdir_p AT
|
12
30
|
in_test_app_dir do
|
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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
@@ -180,12 +180,15 @@ dependencies:
|
|
180
180
|
version: '0'
|
181
181
|
description: |2
|
182
182
|
|
183
|
+
i18n-tasks finds and manages missing and unused translations in your application.
|
184
|
+
|
183
185
|
The basic approach to i18n key management in frameworks such as Rails is far from perfect.
|
184
186
|
If you use a key that does not exist, this will only blow up at runtime. Keys left over from removed code accumulate
|
185
187
|
in the resource files, introducing unnecessary overhead on the translators. Translation files can quickly turn to disarray.
|
186
188
|
|
187
|
-
i18n-tasks improves this by using static analysis. It
|
188
|
-
|
189
|
+
i18n-tasks improves this by using static analysis. It scans calls such as `I18n.t('some.key')` and uses this information to
|
190
|
+
provide reports on key usage, missing and unused keys, and can prefill missing keys, including from Google Translate,
|
191
|
+
and can also remove unused keys.
|
189
192
|
email:
|
190
193
|
- glex.spb@gmail.com
|
191
194
|
executables:
|
@@ -212,7 +215,6 @@ files:
|
|
212
215
|
- lib/i18n/tasks/data/adapter/yaml_adapter.rb
|
213
216
|
- lib/i18n/tasks/data/file_system.rb
|
214
217
|
- lib/i18n/tasks/data/storage/file_storage.rb
|
215
|
-
- lib/i18n/tasks/data/yaml.rb
|
216
218
|
- lib/i18n/tasks/data_traversal.rb
|
217
219
|
- lib/i18n/tasks/fill_tasks.rb
|
218
220
|
- lib/i18n/tasks/google_translation.rb
|
data/lib/i18n/tasks/data/yaml.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'i18n/tasks/data/file_system'
|
2
|
-
|
3
|
-
module I18n::Tasks
|
4
|
-
module Data
|
5
|
-
class Yaml < FileSystem
|
6
|
-
def initialize(*args)
|
7
|
-
super
|
8
|
-
I18n::Tasks.warn_deprecated "data.adapter set to 'yaml'. please use 'file_system' instead"
|
9
|
-
end
|
10
|
-
register_adapter '*.yml', Adapter::YamlAdapter
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|