i18n-tasks 0.3.9 → 0.3.10

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: aeddb130b04e94eb44c9a80da3746896933e2272
4
- data.tar.gz: 17f53cf4fe0015cfd6edf18613d7253ea2d61952
3
+ metadata.gz: 601f3e2a8ac21ec9d8f83aa71f5723623b109f69
4
+ data.tar.gz: 5a9396e63a232357fd63d1d260a80ddfd274dea4
5
5
  SHA512:
6
- metadata.gz: 690d937228ea48e53dbc4bb690b04af94e39b1c9d843e163f00f3a96b2377d86727f4e0e2bb277fb9d49677371fe5f17fb1feeb2a88f569d9a20f1acb3534901
7
- data.tar.gz: ce79dd5249253f465be6fd14f7a0af74b5d44fbea2e61027a4b4e290fc90ee2838830cebdfe2106d55e1ce9fb646aaae6c3ba5cc5bcbe69d2c206d914830074d
6
+ metadata.gz: 80187dee2d375fbe01e79313c6d7bd24927c91da51c52b102661f7b13378547c16743b571c0ebdb7fd3d29d35777db48900ce66f5d23108069d6f06f0510ac7b
7
+ data.tar.gz: fe57c3b82c6d24c3d43c3203a184b21d99a04ec639d142aee38b1f336587d74308937ea9a7a33ac8a8a9b1d16296e83bf58e46749bbbbfb453a715cf0087924e
data/CHANGES.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  * Fix regression: Remove ActiveSupport::HashWithIndifferentAccess from locale data output
4
4
 
5
+ ## 0.3.10
6
+
7
+ * New (de)serialization options in config
8
+ * `add-missing` placeholder argument can now use %{base_value}.
9
+
5
10
  ## 0.3.8
6
11
 
7
12
  * Fix activesupport ~3.x compatibility issue (#45).
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
  platform :rbx do
7
7
  gem 'rubysl', '~> 2.0'
8
8
  gem 'rubysl-mutex_m', '~> 2.0'
9
+ gem 'psych'
9
10
  group :development do
10
11
  gem 'racc'
11
12
  end
data/README.md CHANGED
@@ -1,4 +1,4 @@
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]
1
+ # i18n-tasks [![Build Status][badge-travis]][travis] [![Coverage Status][badge-coveralls]][coveralls] [![Code Climate][badge-code-climate]][code-climate] [![Gemnasium][badge-gemnasium]][gemnasium]
2
2
 
3
3
  i18n-tasks finds and manages missing and unused translations in your application.
4
4
 
@@ -7,7 +7,7 @@ If you use a key that does not exist, this will only blow up at runtime. Keys le
7
7
  in the resource files and introduce unnecessary overhead on the translators. Translation files can quickly turn to disarray.
8
8
 
9
9
  i18n-tasks improves this by using static analysis. It scans calls such as `I18n.t('some.key')` and provides reports on key usage, missing, and unused keys.
10
- It can also can pre-fill missing keys, including from Google Translate, and it can remove unused keys as well.
10
+ It can also pre-fill missing keys, including from Google Translate, and it can remove unused keys as well.
11
11
 
12
12
  i18n-tasks can be used with any project using [i18n][i18n-gem] (default in Rails), or similar, even if it isn't ruby.
13
13
 
@@ -18,7 +18,7 @@ i18n-tasks can be used with any project using [i18n][i18n-gem] (default in Rails
18
18
  Add to Gemfile:
19
19
 
20
20
  ```ruby
21
- gem 'i18n-tasks', '~> 0.3.7'
21
+ gem 'i18n-tasks', '~> 0.3.10'
22
22
  ```
23
23
 
24
24
  i18n-tasks does not load or execute any of the application's code but performs static-only analysic.
@@ -55,6 +55,8 @@ To add missing values to the base locale only:
55
55
  ```bash
56
56
  # most task accept locales as first argument. `base` and `all` are special
57
57
  i18n-tasks add-missing base
58
+ # add-missing accepts a placeholder argument, with optional base_value interpolation
59
+ i18n-tasks add-missing -p 'PLEASE-TRANSLATE %{base_value}' fr
58
60
  ```
59
61
 
60
62
  Translate missing values with Google Translate ([more below on the API key](#translation-config)).
@@ -142,6 +144,11 @@ data:
142
144
  - ['devise.*', 'config/locales/devise.%{locale}.yml']
143
145
  # default catch-all:
144
146
  - 'config/locales/%{locale}.yml' # path is short for ['*', path]
147
+ # configure YAML / JSON serializer options (when using the default adapter)
148
+ yaml:
149
+ write:
150
+ # do not wrap lines at 80 characters (default)
151
+ line_width: -1
145
152
  ```
146
153
 
147
154
  #### Key pattern syntax
@@ -254,23 +261,23 @@ You might want to test for missing and unused translations as part of your test
254
261
  This is how you can do it with rspec:
255
262
 
256
263
  ```ruby
257
- # spec/i18n_keys_spec.rb:
264
+ # spec/i18n_spec.rb:
258
265
  require 'spec_helper'
259
-
260
266
  require 'i18n/tasks'
261
267
 
262
- describe 'Translation keys' do
268
+ describe 'I18n' do
263
269
  let(:i18n) { I18n::Tasks::BaseTask.new }
264
270
 
265
- it 'are all present' do
266
- expect(i18n.missing_keys).to have(0).keys
271
+ it 'does not have missing keys' do
272
+ count = i18n.missing_keys.count
273
+ fail "There are #{count} missing i18n keys! Run 'i18n-tasks missing' for more details." unless count.zero?
267
274
  end
268
275
 
269
- it 'are all used' do
270
- expect(i18n.unused_keys).to have(0).keys
276
+ it 'does not have unused keys' do
277
+ count = i18n.unused_keys.count
278
+ fail "There are #{count} unused i18n keys! Run 'i18n-tasks unused' for more details." unless count.zero?
271
279
  end
272
280
  end
273
-
274
281
  ```
275
282
 
276
283
  ## XLSX
@@ -292,12 +299,12 @@ This was originally developed for [Zuigo](http://zuigo.com/), a platform to orga
292
299
 
293
300
  [MIT license]: /LICENSE.txt
294
301
  [travis]: https://travis-ci.org/glebm/i18n-tasks
295
- [badge-travis]: https://travis-ci.org/glebm/i18n-tasks.png?branch=master
302
+ [badge-travis]: http://img.shields.io/travis/glebm/i18n-tasks.svg
296
303
  [coveralls]: https://coveralls.io/r/glebm/i18n-tasks?branch=master
297
- [badge-coveralls]: https://coveralls.io/repos/glebm/i18n-tasks/badge.png?branch=master
304
+ [badge-coveralls]: http://img.shields.io/coveralls/glebm/i18n-tasks.svg
305
+ [gemnasium]: https://gemnasium.com/glebm/i18n-tasks
306
+ [badge-gemnasium]: https://gemnasium.com/glebm/i18n-tasks.svg
298
307
  [code-climate]: https://codeclimate.com/github/glebm/i18n-tasks
299
- [badge-code-climate]: https://codeclimate.com/github/glebm/i18n-tasks.png
300
- [badge-flattr]: https://api.flattr.com/button/flattr-badge-large.png
301
- [flattr]: https://flattr.com/submit/auto?user_id=glebm&url=https%3A%2F%2Fgithub.com%2Fglebm%2Fi18n-tasks
308
+ [badge-code-climate]: http://img.shields.io/codeclimate/github/glebm/i18n-tasks.svg
302
309
  [i18n-gem]: https://github.com/svenfuchs/i18n "svenfuchs/i18n on Github"
303
310
  [screenshot-find]: https://raw.github.com/glebm/i18n-tasks/master/doc/img/i18n-usages.png "i18n-tasks find output screenshot"
data/bin/i18n-tasks CHANGED
@@ -4,21 +4,30 @@ require 'i18n/tasks'
4
4
  require 'i18n/tasks/commands'
5
5
  require 'slop'
6
6
 
7
+ err = proc { |message, exit_code|
8
+ STDERR.puts Term::ANSIColor.yellow('i18n-tasks: ' + message)
9
+ exit exit_code
10
+ }
11
+
7
12
  command = nil
8
- slop = Slop.parse(help: true) do
9
- on('-v', '--version', 'Print the version') {
10
- puts I18n::Tasks::VERSION
11
- exit
12
- }
13
- ::I18n::Tasks::Commands.cmds.each do |name, attr|
14
- command name.tr('_', '-') do
15
- description attr.desc if attr.desc
16
- instance_exec(&attr.opts) if attr.opts
17
- run do |opts, args|
18
- command = [name, opts, args]
13
+ begin
14
+ slop = Slop.parse(help: true) do
15
+ on('-v', '--version', 'Print the version') {
16
+ puts I18n::Tasks::VERSION
17
+ exit
18
+ }
19
+ ::I18n::Tasks::Commands.cmds.each do |name, attr|
20
+ command name.tr('_', '-') do
21
+ description attr.desc if attr.desc
22
+ instance_exec(&attr.opts) if attr.opts
23
+ run do |opts, args|
24
+ command = [name, opts, args]
25
+ end
19
26
  end
20
27
  end
21
28
  end
29
+ rescue Slop::Error => e
30
+ err.call(e.message, 64)
22
31
  end
23
32
 
24
33
  if command
@@ -40,7 +49,5 @@ if command
40
49
  # i18n-tasks missing | head
41
50
  end
42
51
  else
43
- STDERR.puts Term::ANSIColor.red "Command unknown: #{ARGV[0]}" if ARGV[0]
44
- puts slop.help
45
- exit 64
52
+ err.call("Command unknown: #{ARGV[0]}", 64) if ARGV[0]
46
53
  end
@@ -11,7 +11,7 @@ module I18n::Tasks
11
11
  desc 'show missing translations'
12
12
  opts do
13
13
  on '-l', :locales=, 'Filter by locale (default: all)', on_locale_opt
14
- on '-t', :types, 'Filter by type (types: missing_from_base, eq_base, missing_from_locale)', as: Array, delimiter: /[+:,]/, argument: true, optional: false
14
+ on '-t', :types=, 'Filter by type (types: missing_from_base, eq_base, missing_from_locale)', as: Array, delimiter: /[+:,]/
15
15
  end
16
16
  cmd :missing do |opt = {}|
17
17
  parse_locales! opt
@@ -25,8 +25,8 @@ module I18n::Tasks
25
25
 
26
26
  desc 'translate missing keys with Google Translate'
27
27
  opts do
28
- on '-l', :locales, 'Locales to translate (default: all)', on_locale_opt
29
- on '-f', :from, 'Locale to translate from (default: base)', default: 'base', argument: true, optional: false
28
+ on '-l', :locales=, 'Locales to translate (default: all)', on_locale_opt
29
+ on '-f', :from=, 'Locale to translate from (default: base)', default: 'base', argument: true, optional: false
30
30
  end
31
31
  cmd :translate_missing do |opt = {}|
32
32
  opt[:from] = base_locale if opt[:from].blank? || opt[:from] == 'base'
@@ -36,21 +36,30 @@ module I18n::Tasks
36
36
 
37
37
  desc 'add missing keys to the locales'
38
38
  opts do
39
- on '-l', :locales, 'Locales to add keys into (default: all)', on_locale_opt
40
- on '-p', :placeholder, 'Value for empty keys (default: base value or key.humanize)', argument: true, optional: false
39
+ on '-l', :locales=, 'Locales to add keys into (default: all)', on_locale_opt
40
+ on '-p', :placeholder=, 'Value for empty keys (default: base value or key.humanize)', argument: true, optional: false
41
41
  end
42
42
  cmd :add_missing do |opt = {}|
43
43
  parse_locales! opt
44
44
  opt[:value] ||= opt.delete(:placeholder) || proc { |key, locale|
45
45
  # default to base value or key.humanize
46
- locale == base_locale && t(locale, base_locale) || key.split('.').last.to_s.humanize
46
+ locale != base_locale && t(key, base_locale) || key.split('.').last.to_s.humanize
47
47
  }
48
+
49
+ v = opt[:value]
50
+ if v.is_a?(String) && v.include?('%{base_value}')
51
+ opt[:value] = proc { |key, locale|
52
+ base_value = t(key, base_locale) || ''
53
+ v % {base_value: base_value}
54
+ }
55
+ end
56
+
48
57
  i18n_task.fill_missing_value opt
49
58
  end
50
59
 
51
60
  desc 'show where the keys are used in the code'
52
61
  opts do
53
- on '-p', :pattern, 'Show only keys matching pattern', argument: true, optional: false
62
+ on '-p', :pattern=, 'Show only keys matching pattern', argument: true, optional: false
54
63
  end
55
64
  cmd :find do |opt = {}|
56
65
  opt[:filter] ||= opt.delete(:pattern) || opt[:arguments].try(:first)
@@ -95,7 +104,7 @@ module I18n::Tasks
95
104
 
96
105
  desc 'save missing and unused translations to an Excel file'
97
106
  opts do
98
- on :path, 'Destination path', default: 'tmp/i18n-report.xlsx'
107
+ on :path=, 'Destination path', default: 'tmp/i18n-report.xlsx'
99
108
  end
100
109
  cmd :xlsx_report do |opt = {}|
101
110
  begin
@@ -7,13 +7,13 @@ module I18n::Tasks
7
7
  extend self
8
8
 
9
9
  # @return [Hash] locale tree
10
- def parse(str)
11
- JSON.parse(str)
10
+ def parse(str, opts)
11
+ JSON.parse(str, opts || {})
12
12
  end
13
13
 
14
14
  # @return [String]
15
- def dump(tree)
16
- JSON.generate(tree)
15
+ def dump(tree, opts)
16
+ JSON.generate(tree, opts || {})
17
17
  end
18
18
 
19
19
  end
@@ -6,13 +6,13 @@ module I18n::Tasks
6
6
  extend self
7
7
 
8
8
  # @return [Hash] locale tree
9
- def parse(str)
10
- YAML.load(str)
9
+ def parse(str, options)
10
+ YAML.load(str, options || {})
11
11
  end
12
12
 
13
13
  # @return [String]
14
- def dump(tree)
15
- tree.to_yaml
14
+ def dump(tree, options)
15
+ tree.to_yaml(options || {})
16
16
  end
17
17
 
18
18
  end
@@ -12,29 +12,31 @@ module I18n
12
12
 
13
13
  protected
14
14
 
15
- def load_file(file)
16
- adapter_for(file).parse(
17
- ::File.read(file)
18
- )
15
+ def load_file(path)
16
+ adapter_name, adapter_pattern, adapter = adapter_for(path)
17
+ adapter_options = (config[adapter_name] || {})[:read]
18
+ adapter.parse(::File.read(path), adapter_options)
19
19
  end
20
20
 
21
21
  def write_tree(path, tree)
22
22
  ::File.open(path, 'w') { |f|
23
- f.write(adapter_for(path).dump(tree.to_hash))
23
+ adapter_name, adapter_pattern, adapter = adapter_for(path)
24
+ adapter_options = (config[adapter_name] || {})[:write]
25
+ f.write(adapter.dump(tree.to_hash, adapter_options))
24
26
  }
25
27
  end
26
28
 
27
29
  module ClassMethods
28
30
  # @param pattern [String] File.fnmatch pattern
29
31
  # @param adapter [responds to parse(string)->hash and dump(hash)->string]
30
- def register_adapter(pattern, adapter)
31
- (@fn_patterns ||= {})[pattern] = adapter
32
+ def register_adapter(name, pattern, adapter)
33
+ (@fn_patterns ||= []) << [name, pattern, adapter]
32
34
  end
33
35
 
34
36
  def adapter_for(path)
35
- @fn_patterns.detect { |pattern, adapter|
37
+ @fn_patterns.detect { |(name, pattern, adapter)|
36
38
  ::File.fnmatch(pattern, path)
37
- }[1] or raise "Adapter not found for #{path}. Registered adapters: #{@fn_patterns.inspect}"
39
+ } or raise "Adapter not found for #{path}. Registered adapters: #{@fn_patterns.inspect}"
38
40
  end
39
41
  end
40
42
  end
@@ -5,8 +5,8 @@ require 'i18n/tasks/data/adapter/yaml_adapter'
5
5
  module I18n::Tasks
6
6
  module Data
7
7
  class FileSystem < FileSystemBase
8
- register_adapter '*.yml', Adapter::YamlAdapter
9
- register_adapter '*.json', Adapter::JsonAdapter
8
+ register_adapter :yaml, '*.yml', Adapter::YamlAdapter
9
+ register_adapter :json, '*.json', Adapter::JsonAdapter
10
10
  end
11
11
  end
12
12
  end
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module Tasks
3
- VERSION = '0.3.9'
3
+ VERSION = '0.3.10'
4
4
  end
5
5
  end
@@ -1,7 +1,7 @@
1
1
  p #{t('ca.a')} #{t 'ca.b'} #{t "ca.c"}
2
2
  p #{t 'ca.d'} #{t 'ca.f', i: 'world'} #{t 'ca.e', i: 'world'}
3
3
  p #{t 'missing_in_es.a'} #{t 'same_in_es.a'} #{t 'blank_in_es.a'}
4
- p = t 'used_but_missing.a'
4
+ p = t 'used_but_missing.key'
5
5
  p = t 'x', scope: 'scoped'
6
6
  p = t 'x', scope: [:very, :scoped]
7
7
  p = t 'x', scope: [:scoped, code]
@@ -14,6 +14,9 @@ data:
14
14
  - ['devise.*', 'config/locales/devise.%{locale}.yml']
15
15
  # default catch-all (same as ['*', 'config/locales/%{locale}.yml'])
16
16
  - 'config/locales/%{locale}.yml'
17
+ yaml:
18
+ write:
19
+ line_width: -1
17
20
 
18
21
  # i18n usage search in source
19
22
  search:
@@ -8,7 +8,7 @@ describe 'i18n-tasks' do
8
8
 
9
9
  describe 'missing' do
10
10
  let (:expected_missing_keys) {
11
- %w( en.used_but_missing.a en.relative.index.missing
11
+ %w( en.used_but_missing.key en.relative.index.missing
12
12
  es.missing_in_es.a es.blank_in_es.a es.same_in_es.a
13
13
  en.hash.pattern_missing.a en.hash.pattern_missing.b
14
14
  en.missing_symbol_key en.missing_symbol.key_two en.missing_symbol.key_three )
@@ -76,13 +76,23 @@ describe 'i18n-tasks' do
76
76
  end
77
77
 
78
78
  describe 'add_missing' do
79
- it 'default placeholder' do
79
+ it 'default placeholder: key.humanize for base_locale' do
80
80
  in_test_app_dir {
81
81
  expect(YAML.load_file('config/locales/en.yml')['en']['used_but_missing']).to be_nil
82
82
  }
83
83
  run_cmd :add_missing, locales: 'base'
84
84
  in_test_app_dir {
85
- expect(YAML.load_file('config/locales/en.yml')['en']['used_but_missing']['a']).to eq 'A'
85
+ expect(YAML.load_file('config/locales/en.yml')['en']['used_but_missing']['key']).to eq 'Key'
86
+ }
87
+ end
88
+
89
+ it 'default placeholder: base_value for non-base locale' do
90
+ in_test_app_dir {
91
+ expect(YAML.load_file('config/locales/es.yml')['es']['missing_in_es']).to be_nil
92
+ }
93
+ run_cmd :add_missing, locales: 'es'
94
+ in_test_app_dir {
95
+ expect(YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a']).to eq 'EN_TEXT'
86
96
  }
87
97
  end
88
98
 
@@ -97,6 +107,16 @@ describe 'i18n-tasks' do
97
107
  expect(YAML.load_file('config/locales/devise.es.yml')['es']['devise']['a']).to eq 'ES_TEXT'
98
108
  }
99
109
  end
110
+
111
+ it 'placeholder: value with base_value' do
112
+ in_test_app_dir {
113
+ expect(YAML.load_file('config/locales/es.yml')['es']['missing_in_es']).to be_nil
114
+ }
115
+ run_cmd :add_missing, locales: 'all', placeholder: 'TRME %{base_value}'
116
+ in_test_app_dir {
117
+ expect(YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a']).to eq 'TRME EN_TEXT'
118
+ }
119
+ end
100
120
  end
101
121
 
102
122
  describe 'config' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.3.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-04 00:00:00.000000000 Z
11
+ date: 2014-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis