i18n-tasks 0.1.6 → 0.1.7

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: b5394593809b1be9eabef55d84ee0cf8ce692884
4
- data.tar.gz: 5629b833e0ef043538a387a3eff45a1e16fdbc6f
3
+ metadata.gz: fba31809b28d7db5c2f2febad005236e8e4b7e1b
4
+ data.tar.gz: 0b3f032893745205af5368c017fe092fea521b26
5
5
  SHA512:
6
- metadata.gz: 80141dbe9b294f9e83b3d1a812aa5f3381e2909ddf8175cec2df66dae8da310e6aedda8d36bb7a11c511d04e41a59972469eabe6475b88f0cfa0065034efa9b7
7
- data.tar.gz: a0c620f7af53c0aa9f820afc057eb658f8c84d43caad4a9affdb1854d1b5ecacf76ceef4288b7265eaecca2382e0f3a8e6de226e7c21205c9aaf0d3a54a441a1
6
+ metadata.gz: ca884fd7cd3f02830003fb4fe8e13586fa162c22b328a17c39f0655e08005e03073ac193b6d57c50e3edb619b93bfc316eef873a761fb4bbdaac2d16d05c6375
7
+ data.tar.gz: 3ebcfa3023b2b5c6cb83181382a51253ffca5ce2ed476d9167495da31d19358ed8db3b8bd2401b522295f64312bdad9f51f5884a1de17145474eb3a45458d538
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## v0.1.7
2
+
3
+ * ability to route prefill output via data.write config (@glebm)
4
+ * multiple configuration variables renamed (still understands old syntax with deprecation warnings) (@glebm)
5
+
1
6
  ## v0.1.6
2
7
 
3
8
  * New key pattern syntax for i18n-tasks.yml a la globbing (@glebm)
data/README.md CHANGED
@@ -8,8 +8,9 @@ Rails I18n tasks to find missing / unused translations and more. Works with slim
8
8
  Use `rake -T i18n` to get the list of tasks with descriptions. There are 3 tasks available at the moment:
9
9
 
10
10
  * `i18n:missing` task shows all the keys that have not been translated yet *([source](/lib/i18n/tasks/missing.rb))*
11
- * `i18n:prefill` task normalizes locale files, and adds missing keys from base locale to others *([source](/lib/i18n/tasks/prefill.rb))*
12
11
  * `i18n:unused` task shows potentially unused translations *([source](/lib/i18n/tasks/unused.rb))*
12
+ * `i18n:prefill` task normalizes locale files, and adds missing keys from base locale to others *([source](/lib/i18n/tasks/prefill.rb))*
13
+
13
14
 
14
15
  The `i18n:unused` task will detect pattern translations and not report them, e.g.:
15
16
 
@@ -18,7 +19,7 @@ t 'category.' + category.key # 'category.arts_and_crafts' considered used
18
19
  t "category.#{category.key}" # also works
19
20
  ```
20
21
 
21
- Relative keys (`t '.title'`) are supported. Plural keys (key.one/many/other/etc) are supported.
22
+ Relative keys (`t '.title'`) and plural keys (key.one/many/other/etc) are fully supported.
22
23
 
23
24
  For more examples see [the tests](/spec/i18n_tasks_spec.rb).
24
25
 
@@ -36,9 +37,58 @@ gem 'i18n-tasks', '~> 0.1.0'
36
37
 
37
38
  ## Configuration
38
39
 
39
- Tasks may incorrectly report framework i18n keys as missing. You can add `config/i18n-tasks.yml` to work around this:
40
+ Configuration is read from `i18n-tasks/config.yml`.
41
+
42
+ ### Storage
43
+
44
+ ```yaml
45
+ # i18n data storage
46
+ data:
47
+ # The default YAML adapter supports reading from and writing to YAML files
48
+ adapter: yaml
49
+ # yaml adapter read option is a list of glob patterns of files to read from per-locale
50
+ read:
51
+ # this one is default:
52
+ - 'config/locales/%{locale}.yml'
53
+ # this one would add some more files:
54
+ - 'config/locales/*.%{locale}.yml'
55
+ # yaml adapter write option a list of key pattern => output filename "routes" per-locale
56
+ write:
57
+ # keys matched top to bottom
58
+ - ['devise.*', 'config/locales/devise.%{locale}.yml']
59
+ # default catch-all (same as ['*', 'config/locales/%{locale}.yml'])
60
+ - 'config/locales/%{locale}.yml'
61
+ ```
62
+
63
+ ### Usage search
40
64
 
41
65
  ```yaml
66
+ # i18n usage search in source
67
+ search:
68
+ # search these directories (relative to your Rails.root directory, default: 'app/')
69
+ paths:
70
+ - 'app/'
71
+ - 'vendor/'
72
+ # include only files matching this glob pattern (default: blank = include all files)
73
+ include:
74
+ - '*.rb'
75
+ - '*.html.*'
76
+ - '*.text.*'
77
+ # explicitly exclude files (default: blank = exclude no files)
78
+ exclude: '*.js'
79
+ # search uses grep under the hood
80
+ ```
81
+
82
+ ### Fine-tuning
83
+
84
+ Tasks may incorrectly report framework i18n keys as missing, also some patterns may not be detected.
85
+ When all else fails, use the options below.
86
+
87
+ ```yaml
88
+ # do not report these keys as unused
89
+ ignore_unused:
90
+ - category.*.db_name
91
+
42
92
  # do not report these keys as missing (both on blank value and no key)
43
93
  ignore_missing:
44
94
  - devise.errors.unauthorized # ignore this key
@@ -51,33 +101,9 @@ ignore_eq_base:
51
101
  es,fr:
52
102
  - common.brand
53
103
 
54
- # do not report these keys as unused
55
- ignore_unused:
56
- - category.*
57
-
58
104
  # do not report these keys ever
59
105
  ignore:
60
106
  - kaminari.*
61
-
62
- # where to read locale data from
63
- data:
64
- # read paths for a given %{locale} (supports globs)
65
- paths:
66
- - 'config/locales/%{locale}.yml'
67
- # you can also implement a custom storage layer, see the yaml one below
68
- class: I18n::Tasks::Data::Yaml
69
-
70
- # search configuration (grep arguments)
71
- grep:
72
- # search these directories (relative to your Rails.root directory, default: 'app/')
73
- paths:
74
- - 'app/'
75
- # include only files matching this glob pattern (default: blank = include all files)
76
- include:
77
- - '*.rb'
78
- - '*.html*'
79
- # explicitly exclude files (default: blank = exclude no files)
80
- exclude: '*.js'
81
107
  ```
82
108
 
83
109
  ## HTML report
data/lib/i18n/tasks.rb CHANGED
@@ -1,10 +1,8 @@
1
1
  require 'i18n/tasks/version'
2
2
  require 'i18n/tasks/railtie'
3
- require 'i18n/tasks/key_pattern_matching'
4
-
5
- require 'i18n/tasks/data/yaml'
6
- require 'active_support/hash_with_indifferent_access'
7
- require 'active_support/core_ext/string/access'
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/core_ext/string'
5
+ require 'term/ansicolor'
8
6
 
9
7
  module I18n
10
8
  module Tasks
@@ -17,6 +15,10 @@ module I18n
17
15
  HashWithIndifferentAccess.new.merge(file.presence || {})
18
16
  end
19
17
  end
18
+
19
+ def warn_deprecated(message)
20
+ STDERR.puts Term::ANSIColor.yellow Term::ANSIColor.bold "i18n-tasks: [DEPRECATED] #{message}"
21
+ end
20
22
  end
21
23
  end
22
24
  end
@@ -1,19 +1,18 @@
1
1
  # coding: utf-8
2
- require 'term/ansicolor'
3
- require 'i18n/tasks/usage_search'
4
- require 'i18n/tasks/fuzzy_source_keys'
5
- require 'i18n/tasks/plural_keys'
2
+ require 'i18n/tasks/key_pattern_matching'
6
3
  require 'i18n/tasks/relative_keys'
4
+ require 'i18n/tasks/plural_keys'
5
+ require 'i18n/tasks/source_keys'
7
6
  require 'i18n/tasks/translation_data'
8
7
  require 'i18n/tasks/ignore_keys'
9
8
 
10
9
  module I18n
11
10
  module Tasks
12
11
  class BaseTask
13
- include UsageSearch
14
- include PluralKeys
12
+ include KeyPatternMatching
15
13
  include RelativeKeys
16
- include FuzzySourceKeys
14
+ include PluralKeys
15
+ include SourceKeys
17
16
  include TranslationData
18
17
  include IgnoreKeys
19
18
 
@@ -22,6 +21,11 @@ module I18n
22
21
  def config
23
22
  I18n::Tasks.config
24
23
  end
24
+
25
+ def warn_deprecated(message)
26
+ I18n::Tasks.warn_deprecated(message)
27
+ end
28
+
25
29
  end
26
30
  end
27
31
  end
@@ -1,22 +1,62 @@
1
+ require 'i18n/tasks/data_traversal'
2
+ require 'i18n/tasks/key_pattern_matching'
1
3
  module I18n::Tasks
2
4
  module Data
3
5
  class Yaml
6
+ include ::I18n::Tasks::DataTraversal
7
+ include ::I18n::Tasks::KeyPatternMatching
4
8
  attr_reader :options
5
9
 
10
+ DEFAULTS = {
11
+ read: ['config/locales/%{locale}.yml'],
12
+ write: ['config/locales/%{locale}.yml']
13
+ }.with_indifferent_access
14
+
6
15
  def initialize(options)
7
- @options = options
16
+ opt = (options || {}).with_indifferent_access
17
+ if opt.key?(:paths)
18
+ opt[:read] ||= opt.delete(:paths)
19
+ ::I18n::Tasks.warn_deprecated 'please rename "data.paths" key to "data.read" in config/i18n-tasks.yml'
20
+ end
21
+ opt = DEFAULTS.deep_merge(opt)
22
+ @read = opt[:read]
23
+ @write = opt[:write].map { |x| x.is_a?(String) ? ['*', x] : x }.map { |x|
24
+ [key_pattern_to_re(x[0]), x[1]]
25
+ }
8
26
  end
9
27
 
28
+ # get locale tree
10
29
  def get(locale)
11
- options[:paths].map do |path|
12
- Dir.glob path % { locale: locale }
13
- end.flatten.map do |locale_file|
14
- YAML.load_file locale_file
15
- end.inject({}) do |hash, locale_data|
16
- hash.deep_merge! locale_data || {}
17
- hash
30
+ locale = locale.to_s
31
+ (@locale_data ||= {})[locale] ||= begin
32
+ @read.map do |path|
33
+ Dir.glob path % {locale: locale}
34
+ end.flatten.map do |locale_file|
35
+ YAML.load_file locale_file
36
+ end.inject({}) do |hash, locale_data|
37
+ hash.deep_merge! locale_data || {}
38
+ hash
39
+ end[locale.to_s]
40
+ end
41
+ end
42
+
43
+ alias [] get
44
+
45
+ # set locale tree
46
+ def set(locale, value_tree)
47
+ out = {}
48
+ traverse value_tree do |key, value|
49
+ route = @write.detect { |route| route[0] =~ key }
50
+ (out[route[1] % {locale: locale}] ||= []) << [key, value]
51
+ end
52
+ out.each do |path, data|
53
+ File.open(path, 'w') { |f|
54
+ f.write({locale.to_s => list_to_tree(data)}.to_yaml)
55
+ }
18
56
  end
19
57
  end
58
+
59
+ alias []= set
20
60
  end
21
61
  end
22
62
  end
@@ -0,0 +1,40 @@
1
+ module I18n::Tasks::DataTraversal
2
+ # translation of the key found in the passed hash or nil
3
+ # @return [String,nil]
4
+ def t(hash, key)
5
+ key.split('.').inject(hash) { |r, seg| r[seg] if r }
6
+ end
7
+
8
+ # traverse hash, yielding with full key and value
9
+ # @param hash [Hash{String => String,Hash}] translation data to traverse
10
+ # @yield [full_key, value] yields full key and value for every translation in #hash
11
+ # @return [nil]
12
+ def traverse(path = '', hash)
13
+ q = [[path, hash]]
14
+ until q.empty?
15
+ path, value = q.pop
16
+ if value.is_a?(Hash)
17
+ value.each { |k, v| q << ["#{path}.#{k}", v] }
18
+ else
19
+ yield path[1..-1], value
20
+ end
21
+ end
22
+ end
23
+
24
+ def list_to_tree(list)
25
+ list = list.sort
26
+ tree = {}
27
+ list.each do |key, value|
28
+ key_segments = key.to_s.split('.')
29
+ node = key_segments[0..-2].inject(tree) do |r, segment|
30
+ if r.key?(segment)
31
+ r[segment]
32
+ else
33
+ r[segment] = {}
34
+ end
35
+ end
36
+ node[key_segments.last] = value
37
+ end
38
+ tree
39
+ end
40
+ end
@@ -14,7 +14,7 @@ module I18n::Tasks::KeyPatternMatching
14
14
  # convert key.* to key\..*
15
15
  def key_pattern_to_re(key_pattern)
16
16
  if key_pattern.end_with? '.'
17
- $stderr.puts %Q(i18n-tasks: Deprecated "#{key_pattern}", please change to "#{key_pattern += '*'}".)
17
+ warn_deprecated %Q(please change pattern "#{key_pattern}" to "#{key_pattern += '*'}" in config/i18n-tasks.yml)
18
18
  end
19
19
  /^#{key_pattern.
20
20
  gsub(/\./, '\.').
@@ -29,9 +29,9 @@ module I18n
29
29
  # present in base locale, but untranslated in another locale
30
30
  # @return Array{Hash}
31
31
  def keys_missing_translation(locale)
32
- trn = locale_data(locale)[locale]
32
+ trn = data[locale]
33
33
  r = []
34
- traverse base_locale_data do |key, base_value|
34
+ traverse data[base_locale] do |key, base_value|
35
35
  value_in_locale = t(trn, key)
36
36
  if value_in_locale.blank? && !ignore_key?(key, :missing)
37
37
  r << {locale: locale, key: key, type: :blank, base_value: base_value}
@@ -6,29 +6,38 @@ module I18n
6
6
  include Term::ANSIColor
7
7
 
8
8
  def missing(missing)
9
- $stderr.puts bold cyan "Missing keys and translations (#{missing.length})"
9
+ print_title "Missing keys and translations (#{missing.length})"
10
10
  if missing.present?
11
- $stderr.puts "#{bold 'Legend:'} #{red '✗'} key missing, #{yellow bold '∅'} translation blank, #{blue bold '='} value equal to base locale; #{cyan 'value in base locale'}"
11
+ $stderr.puts "#{bold 'Legend:'} #{on_red '✗'} key missing, #{yellow bold '∅'} translation blank, #{blue bold '='} value equal to base locale, #{cyan 'value in base locale'}"
12
12
  key_col_width = missing.map { |x| x[:key] }.max_by(&:length).length + 2
13
13
  missing.each { |m| print_missing_translation m, key_col_width: key_col_width }
14
14
  else
15
- $stderr.puts(bold green 'Good job! No translations missing!')
15
+ print_success 'Good job! No translations missing!'
16
16
  end
17
17
  end
18
18
 
19
19
  def unused(unused)
20
- $stderr.puts bold cyan("Unused i18n keys (#{unused.length})")
20
+ print_title "Unused i18n keys (#{unused.length})"
21
21
  if unused.present?
22
22
  key_col_width = unused.max_by { |x| x[0].length }[0].length + 2
23
23
  unused.each { |(key, value)| puts "#{magenta key.ljust(key_col_width)}#{cyan value.to_s.strip}" }
24
24
  else
25
- $stderr.puts(bold green 'Good job! Every translation is used!')
25
+ print_success 'Good job! Every translation is used!'
26
26
  end
27
27
  end
28
28
 
29
29
  private
30
30
 
31
31
  extend Term::ANSIColor
32
+
33
+ def print_title(title)
34
+ $stderr.puts "#{bold cyan title.strip} #{dark "|"} #{bold "i18n-tasks v#{I18n::Tasks::VERSION}"}"
35
+ end
36
+
37
+ def print_success(message)
38
+ $stderr.puts(bold green message)
39
+ end
40
+
32
41
  STATUS_TEXTS = {
33
42
  none: red("✗".ljust(6)),
34
43
  blank: yellow(bold '∅'.ljust(6)),
@@ -7,17 +7,9 @@ module I18n
7
7
  def perform
8
8
  # Will also rewrite en, good for ordering
9
9
  I18n.available_locales.map(&:to_s).each do |target_locale|
10
- trn = locale_data(target_locale)
11
- prefilled = { target_locale => base_locale_data }.deep_merge(trn)
12
- File.open(locale_file_path(target_locale), 'w'){ |f| f.write prefilled.to_yaml }
10
+ data[target_locale] = data[base_locale].deep_merge(data[target_locale])
13
11
  end
14
12
  end
15
-
16
- # main locale file path (for writing to)
17
- # @return [String]
18
- def locale_file_path(locale)
19
- "config/locales/#{locale}.yml"
20
- end
21
13
  end
22
14
  end
23
15
  end
@@ -1,19 +1,5 @@
1
1
  require 'open3'
2
- module I18n::Tasks::UsageSearch
3
- # grep config, also from config/i18n-tasks.yml
4
- # @return [Hash{String => String,Hash,Array}]
5
- def grep_config
6
- @grep_config ||= (config[:grep] || {}).with_indifferent_access.tap do |conf|
7
- conf[:paths] = ['app/'] if conf[:paths].blank?
8
- end
9
- end
10
-
11
- # whether the key is used in the source
12
- def used_key?(key)
13
- @used_keys ||= find_source_keys.to_set
14
- @used_keys.include?(key)
15
- end
16
-
2
+ module I18n::Tasks::SourceKeys
17
3
  # find all keys in the source (relative keys are returned in absolutized)
18
4
  # @return [Array<String>]
19
5
  def find_source_keys
@@ -33,8 +19,41 @@ module I18n::Tasks::UsageSearch
33
19
  end
34
20
  end
35
21
 
22
+ # whether the key is used in the source
23
+ def used_key?(key)
24
+ @used_keys ||= find_source_keys.to_set
25
+ @used_keys.include?(key)
26
+ end
27
+
28
+ # dynamically generated keys in the source, e.g t("category.#{category_key}")
29
+ def pattern_key?(key)
30
+ @pattern_keys_re ||= compile_start_with_re(pattern_key_prefixes)
31
+ !!(key =~ @pattern_keys_re)
32
+ end
33
+
34
+ # keys in the source that end with a ., e.g. t("category.#{cat.i18n_key}") or t("category." + category.key)
35
+ def pattern_key_prefixes
36
+ @pattern_keys_prefixes ||=
37
+ find_source_keys.select { |k| k =~ /\#{.*?}/ || k.ends_with?('.') }.map { |k| k.split(/\.?#/)[0].presence }.compact
38
+ end
39
+
36
40
  protected
37
41
 
42
+ # grep config, also from config/i18n-tasks.yml
43
+ # @return [Hash{String => String,Hash,Array}]
44
+ def grep_config
45
+ @grep_config ||= begin
46
+ if config.key?(:grep)
47
+ config[:search] ||= config.delete(:grep)
48
+ warn_deprecated 'please rename "grep" key to "search" in config/i18n-tasks.yml'
49
+ end
50
+ search_config = (config[:search] || {}).with_indifferent_access
51
+ search_config.tap do |conf|
52
+ conf[:paths] = %w(app/) if conf[:paths].blank?
53
+ end
54
+ end
55
+ end
56
+
38
57
  # Run grep searching for source keys and return grep output
39
58
  # @return [String] output of the grep command
40
59
  def run_grep
@@ -1,58 +1,28 @@
1
+ require 'i18n/tasks/data_traversal'
2
+ require 'i18n/tasks/data/yaml'
3
+
1
4
  module I18n::Tasks::TranslationData
2
- # locale data hash, with locale name as root
3
- # @return [Hash{String => String,Hash}] locale data in nested hash format
4
- def locale_data(locale)
5
- locale = locale.to_s
6
- (@locale_data ||= {})[locale] ||= data_source.get(locale) || {}
7
- end
5
+ include I18n::Tasks::DataTraversal
8
6
 
9
7
  # I18n data provider
10
- def data_source
11
- return @source if @source
12
- conf = config[:data] || {}
13
- @source = if conf[:class]
14
- conf[:class].constantize.new(conf.except(:class))
15
- else
16
- I18n::Tasks::Data::Yaml.new(
17
- paths: Array(conf[:paths].presence || ['config/locales/%{locale}.yml'])
18
- )
19
- end
20
- end
21
-
22
- # translation of the key found in the passed hash or nil
23
- # @return [String,nil]
24
- def t(hash, key)
25
- key.split('.').inject(hash) { |r, seg| r[seg] if r }
8
+ # @see I18n::Tasks::Data::Yaml
9
+ def data
10
+ return @data if @data
11
+ conf = (config[:data] || {}).with_indifferent_access
12
+ adapter = (conf[:adapter].presence || conf[:class].presence || :yaml).to_s
13
+ if adapter !~ /[A-Z]/
14
+ adapter = "I18n::Tasks::Data::#{adapter.camelize}"
15
+ end
16
+ @data = adapter.constantize.new(conf.except(:adapter, :class))
26
17
  end
27
18
 
28
- # traverse hash, yielding with full key and value
29
- # @param hash [Hash{String => String,Hash}] translation data to traverse
30
- # @yield [full_key, value] yields full key and value for every translation in #hash
31
- # @return [nil]
32
- def traverse(path = '', hash)
33
- q = [[path, hash]]
34
- until q.empty?
35
- path, value = q.pop
36
- if value.is_a?(Hash)
37
- value.each { |k, v| q << ["#{path}.#{k}", v] }
38
- else
39
- yield path[1..-1], value
40
- end
41
- end
19
+ # whether the value for key exists in locale (defaults: base_locale)
20
+ def key_has_value?(key, locale = base_locale)
21
+ t(data[locale], key).present?
42
22
  end
43
23
 
44
24
  # @return [String] default i18n locale
45
25
  def base_locale
46
26
  I18n.default_locale.to_s
47
27
  end
48
-
49
- # @return [Hash{String => String,Hash}] default i18n locale data
50
- def base_locale_data
51
- locale_data(base_locale)[base_locale]
52
- end
53
-
54
- # whether the value for key exists in locale (defaults: base_locale)
55
- def key_has_value?(key, locale = base_locale)
56
- t(locale_data(locale)[locale], key).present?
57
- end
58
28
  end
@@ -6,11 +6,11 @@ module I18n
6
6
  class Unused < BaseTask
7
7
  # @return [Array<[String, String]>] all the unused translations as an array of [key, value] pairs
8
8
  def find_keys
9
- r = []
10
- data = base_locale_data
11
- traverse data do |key, value|
9
+ r = []
10
+ d = self.data[base_locale]
11
+ traverse d do |key, value|
12
12
  next if pattern_key?(key) || ignore_key?(key, :unused)
13
- key = depluralize_key(key, data)
13
+ key = depluralize_key(key, d)
14
14
  r << [key, value] unless used_key?(key)
15
15
  end
16
16
  r.uniq
@@ -1,5 +1,5 @@
1
1
  module I18n
2
2
  module Tasks
3
- VERSION = '0.1.6'
3
+ VERSION = '0.1.7'
4
4
  end
5
5
  end
@@ -9,3 +9,4 @@ p = t 'ignore_eq_base_all.a'
9
9
  p = t 'ignore_eq_base_es.a'
10
10
  p = t 'numeric.a'
11
11
  p = t 'plural.a', count: 2
12
+ p = t 'devise.a'
@@ -1,25 +1,19 @@
1
- # do not report these keys as missing:
2
- ignore_missing:
3
- - ignored_missing_key.a # one key to ignore
4
- - ignored_pattern.* # ignore the whole pattern
5
-
6
- # do not report these keys when they have the same value as the base locale version
7
- ignore_eq_base:
8
- all:
9
- - ignore_eq_base_all.a
10
- es:
11
- - ignore_eq_base_es.a
12
-
13
- # do not report these keys as unused
14
- ignore_unused:
15
- - ignore_unused.a
16
-
17
- # do not report these keys ever
18
- ignore:
19
- - ignore.a
1
+ # i18n data storage
2
+ data:
3
+ # The default YAML adapter supports reading from and writing to YAML files
4
+ adapter: yaml
5
+ # adapter options
6
+ read:
7
+ - 'config/locales/%{locale}.yml'
8
+ - 'config/locales/*.%{locale}.yml'
9
+ write:
10
+ # keys matched top to bottom
11
+ - ['devise.*', 'config/locales/devise.%{locale}.yml']
12
+ # default catch-all (same as ['*', 'config/locales/%{locale}.yml'])
13
+ - 'config/locales/%{locale}.yml'
20
14
 
21
- # grep configuration
22
- grep:
15
+ # i18n usage search in source
16
+ search:
23
17
  # search these directories (relative to your Rails.root directory, default: 'app/')
24
18
  paths:
25
19
  - 'app/'
@@ -31,11 +25,24 @@ grep:
31
25
  - '*.file'
32
26
  # explicitly exclude files (default: blank = exclude no files)
33
27
  exclude: '*.js'
28
+ # search uses grep under the hood
34
29
 
35
- # how to get the locale data
36
- data:
37
- class: I18n::Tasks::Data::Yaml
38
- paths:
39
- # files for a given %{locale}
40
- - 'config/locales/%{locale}.yml'
41
- - 'config/locales/*.%{locale}.yml'
30
+ # do not report these keys ever
31
+ ignore:
32
+ - ignore.a
33
+
34
+ # do not report these keys as unused
35
+ ignore_unused:
36
+ - ignore_unused.a
37
+
38
+ # do not report these keys as missing:
39
+ ignore_missing:
40
+ - ignored_missing_key.a # one key to ignore
41
+ - ignored_pattern.* # ignore the whole pattern
42
+
43
+ # do not report these keys when they have the same value as the base locale version
44
+ ignore_eq_base:
45
+ all:
46
+ - ignore_eq_base_all.a
47
+ es:
48
+ - ignore_eq_base_es.a
@@ -19,10 +19,14 @@ describe 'rake i18n' do
19
19
  end
20
20
 
21
21
  describe 'prefill' do
22
- it 'detects unused' do
22
+ it 'prefills from en' do
23
23
  TestCodebase.in_test_app_dir { YAML.load_file('config/locales/es.yml')['es']['missing_in_es'].should be_nil }
24
24
  TestCodebase.rake_result('i18n:prefill')
25
- TestCodebase.in_test_app_dir { YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a'].should == 'EN_TEXT' }
25
+ TestCodebase.in_test_app_dir {
26
+ YAML.load_file('config/locales/es.yml')['es']['missing_in_es']['a'].should == 'EN_TEXT'
27
+ YAML.load_file('config/locales/devise.en.yml')['en']['devise']['a'].should == 'EN_TEXT'
28
+ YAML.load_file('config/locales/devise.es.yml')['es']['devise']['a'].should == 'ES_TEXT'
29
+ }
26
30
  end
27
31
  end
28
32
 
@@ -45,7 +49,8 @@ describe 'rake i18n' do
45
49
  'blank_in_es' => {'a' => v},
46
50
  'relative' => {'index' => {'title' => v}},
47
51
  'numeric' => {'a' => v_num},
48
- 'plural' => {'a' => {'one' => v, 'other' => "%{count} #{v}s"}}
52
+ 'plural' => {'a' => {'one' => v, 'other' => "%{count} #{v}s"}},
53
+ 'devise' => {'a' => v}
49
54
  }.tap { |r|
50
55
  gen = r["bench"] = {}
51
56
  BENCH_KEYS.times { |i| gen["key#{i}"] = v }
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.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-12 00:00:00.000000000 Z
11
+ date: 2013-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -128,7 +128,7 @@ files:
128
128
  - lib/i18n/tasks.rb
129
129
  - lib/i18n/tasks/base_task.rb
130
130
  - lib/i18n/tasks/data/yaml.rb
131
- - lib/i18n/tasks/fuzzy_source_keys.rb
131
+ - lib/i18n/tasks/data_traversal.rb
132
132
  - lib/i18n/tasks/ignore_keys.rb
133
133
  - lib/i18n/tasks/key_pattern_matching.rb
134
134
  - lib/i18n/tasks/missing.rb
@@ -137,9 +137,9 @@ files:
137
137
  - lib/i18n/tasks/prefill.rb
138
138
  - lib/i18n/tasks/railtie.rb
139
139
  - lib/i18n/tasks/relative_keys.rb
140
+ - lib/i18n/tasks/source_keys.rb
140
141
  - lib/i18n/tasks/translation_data.rb
141
142
  - lib/i18n/tasks/unused.rb
142
- - lib/i18n/tasks/usage_search.rb
143
143
  - lib/i18n/tasks/version.rb
144
144
  - lib/tasks/i18n-tasks.rake
145
145
  - spec/fixtures/app/assets/javascripts/application.js
@@ -1,20 +0,0 @@
1
- require 'i18n/tasks/key_pattern_matching'
2
-
3
- # e.g t("category.#{category_key}")
4
- module I18n::Tasks
5
- module FuzzySourceKeys
6
- include KeyPatternMatching
7
-
8
- # dynamically generated keys in the source, e.g t("category.#{category_key}")
9
- def pattern_key?(key)
10
- @pattern_keys_re ||= compile_start_with_re(pattern_key_prefixes)
11
- !!(key =~ @pattern_keys_re)
12
- end
13
-
14
- # keys in the source that end with a ., e.g. t("category.#{cat.i18n_key}") or t("category." + category.key)
15
- def pattern_key_prefixes
16
- @pattern_keys_prefixes ||=
17
- find_source_keys.select { |k| k =~ /\#{.*?}/ || k.ends_with?('.') }.map { |k| k.split(/\.?#/)[0].presence }.compact
18
- end
19
- end
20
- end