i18n-tasks 0.3.9 → 0.3.10

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