i18n-tasks 0.2.1 → 0.2.2
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 +8 -0
 - data/README.md +4 -4
 - data/doc/img/i18n-tasks.gif +0 -0
 - data/i18n-tasks.gemspec +6 -2
 - data/lib/i18n/tasks.rb +1 -0
 - data/lib/i18n/tasks/base_task.rb +8 -14
 - data/lib/i18n/tasks/configuration.rb +38 -0
 - data/lib/i18n/tasks/data_traversal.rb +7 -2
 - data/lib/i18n/tasks/fill_tasks.rb +54 -0
 - data/lib/i18n/tasks/{translation.rb → google_translation.rb} +1 -9
 - data/lib/i18n/tasks/ignore_keys.rb +3 -2
 - data/lib/i18n/tasks/key_pattern_matching.rb +1 -1
 - data/lib/i18n/tasks/missing_keys.rb +13 -23
 - data/lib/i18n/tasks/plural_keys.rb +5 -5
 - data/lib/i18n/tasks/railtie.rb +1 -1
 - data/lib/i18n/tasks/reports/terminal.rb +86 -0
 - data/lib/i18n/tasks/source_keys.rb +0 -20
 - data/lib/i18n/tasks/translation_data.rb +11 -25
 - data/lib/i18n/tasks/untranslated_keys.rb +15 -2
 - data/lib/i18n/tasks/unused_keys.rb +5 -8
 - data/lib/i18n/tasks/version.rb +1 -1
 - data/lib/tasks/i18n-tasks.rake +23 -46
 - data/spec/i18n_tasks_spec.rb +2 -1
 - data/spec/support/i18n_tasks_output_matcher.rb +5 -2
 - metadata +25 -6
 - data/lib/i18n/tasks/output/terminal.rb +0 -67
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 938b362fb2bb4551507b503b2230e7175eff7a97
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 378887ed86ebbf0cffc511d4a5b6ad83627d690f
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 182391f6acbb385bf294cf675debfef292153309bec9beacda7b5f8d6e71b178e21d2a111d7bdf31aec843bc1ec9d7fac53fd1a2a59a098132e887c7653f9de0
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 3f0701378d7ecea4be0f252feae1a59a3ca9f89beeb5f6e14cd0a0f9f8ca6d807bb13ced370425d612c23bfb7c76627eef5509068cf6fc2267e699596cbae2a9
         
     | 
    
        data/CHANGES.md
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # i18n-tasks [](https://travis-ci.org/glebm/i18n-tasks) [](https://codeclimate.com/github/glebm/i18n-tasks)
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
            Tasks to manage missing and unused translations in Rails.
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
         @@ -63,7 +63,7 @@ For more examples see [the tests](/spec/i18n_tasks_spec.rb). 
     | 
|
| 
       63 
63 
     | 
    
         
             
            Simply add to Gemfile:
         
     | 
| 
       64 
64 
     | 
    
         | 
| 
       65 
65 
     | 
    
         
             
            ```ruby
         
     | 
| 
       66 
     | 
    
         
            -
            gem 'i18n-tasks', '~> 0.2. 
     | 
| 
      
 66 
     | 
    
         
            +
            gem 'i18n-tasks', '~> 0.2.2'
         
     | 
| 
       67 
67 
     | 
    
         
             
            ```
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
       69 
69 
     | 
    
         
             
            ## Configuration
         
     | 
| 
         @@ -117,8 +117,8 @@ search: 
     | 
|
| 
       117 
117 
     | 
    
         
             
              # explicitly exclude files (default: blank = exclude no files)
         
     | 
| 
       118 
118 
     | 
    
         
             
              exclude:
         
     | 
| 
       119 
119 
     | 
    
         
             
                - '*.js'
         
     | 
| 
       120 
     | 
    
         
            -
              # you can override the default  
     | 
| 
       121 
     | 
    
         
            -
              pattern: "\\bt[( ]\\s*( 
     | 
| 
      
 120 
     | 
    
         
            +
              # you can override the default key regex pattern:
         
     | 
| 
      
 121 
     | 
    
         
            +
              pattern: "\\bt[( ]\\s*(:?\".+?\"|:?'.+?'|:\\w+)"
         
     | 
| 
       122 
122 
     | 
    
         
             
            ```
         
     | 
| 
       123 
123 
     | 
    
         | 
| 
       124 
124 
     | 
    
         
             
            ### Fine-tuning
         
     | 
    
        data/doc/img/i18n-tasks.gif
    CHANGED
    
    | 
         Binary file 
     | 
    
        data/i18n-tasks.gemspec
    CHANGED
    
    | 
         @@ -8,8 +8,11 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       8 
8 
     | 
    
         
             
              spec.version       = I18n::Tasks::VERSION
         
     | 
| 
       9 
9 
     | 
    
         
             
              spec.authors       = ['glebm']
         
     | 
| 
       10 
10 
     | 
    
         
             
              spec.email         = ['glex.spb@gmail.com']
         
     | 
| 
       11 
     | 
    
         
            -
              spec.summary       = %q{ 
     | 
| 
       12 
     | 
    
         
            -
              spec.description   = %q{ 
     | 
| 
      
 11 
     | 
    
         
            +
              spec.summary       = %q{Tasks to manage missing and unused translations in Rails.}
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.description   = %q{
         
     | 
| 
      
 13 
     | 
    
         
            +
                rake tasks to find unused and missing translations, normalize locale files,
         
     | 
| 
      
 14 
     | 
    
         
            +
                and prefill missing keys. Supports relative and plural keys and Google Translate.
         
     | 
| 
      
 15 
     | 
    
         
            +
            }
         
     | 
| 
       13 
16 
     | 
    
         
             
              spec.homepage      = 'https://github.com/glebm/i18n-tasks'
         
     | 
| 
       14 
17 
     | 
    
         
             
              spec.license       = 'MIT'
         
     | 
| 
       15 
18 
     | 
    
         | 
| 
         @@ -22,6 +25,7 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       22 
25 
     | 
    
         
             
              spec.add_dependency 'activesupport'
         
     | 
| 
       23 
26 
     | 
    
         
             
              spec.add_dependency 'easy_translate'
         
     | 
| 
       24 
27 
     | 
    
         
             
              spec.add_dependency 'term-ansicolor'
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.add_dependency 'terminal-table'
         
     | 
| 
       25 
29 
     | 
    
         
             
              spec.add_development_dependency 'bundler', '~> 1.3'
         
     | 
| 
       26 
30 
     | 
    
         
             
              spec.add_development_dependency 'rake'
         
     | 
| 
       27 
31 
     | 
    
         
             
              spec.add_development_dependency 'rspec-rails'
         
     | 
    
        data/lib/i18n/tasks.rb
    CHANGED
    
    
    
        data/lib/i18n/tasks/base_task.rb
    CHANGED
    
    | 
         @@ -1,19 +1,24 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'i18n/tasks/configuration'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'i18n/tasks/key_pattern_matching'
         
     | 
| 
       3 
4 
     | 
    
         
             
            require 'i18n/tasks/relative_keys'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'i18n/tasks/plural_keys'
         
     | 
| 
       5 
6 
     | 
    
         
             
            require 'i18n/tasks/source_keys'
         
     | 
| 
       6 
7 
     | 
    
         
             
            require 'i18n/tasks/translation_data'
         
     | 
| 
       7 
     | 
    
         
            -
            require 'i18n/tasks/translation'
         
     | 
| 
       8 
8 
     | 
    
         
             
            require 'i18n/tasks/ignore_keys'
         
     | 
| 
       9 
9 
     | 
    
         
             
            require 'i18n/tasks/missing_keys'
         
     | 
| 
       10 
10 
     | 
    
         
             
            require 'i18n/tasks/untranslated_keys'
         
     | 
| 
       11 
11 
     | 
    
         
             
            require 'i18n/tasks/unused_keys'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'i18n/tasks/google_translation'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'i18n/tasks/fill_tasks'
         
     | 
| 
       12 
14 
     | 
    
         | 
| 
       13 
15 
     | 
    
         
             
            module I18n
         
     | 
| 
       14 
16 
     | 
    
         
             
              module Tasks
         
     | 
| 
       15 
17 
     | 
    
         
             
                class BaseTask
         
     | 
| 
      
 18 
     | 
    
         
            +
                  include Configuration
         
     | 
| 
       16 
19 
     | 
    
         
             
                  include KeyPatternMatching
         
     | 
| 
      
 20 
     | 
    
         
            +
                  include IgnoreKeys
         
     | 
| 
      
 21 
     | 
    
         
            +
                  include DataTraversal
         
     | 
| 
       17 
22 
     | 
    
         
             
                  include RelativeKeys
         
     | 
| 
       18 
23 
     | 
    
         
             
                  include PluralKeys
         
     | 
| 
       19 
24 
     | 
    
         
             
                  include SourceKeys
         
     | 
| 
         @@ -21,19 +26,8 @@ module I18n 
     | 
|
| 
       21 
26 
     | 
    
         
             
                  include UntranslatedKeys
         
     | 
| 
       22 
27 
     | 
    
         
             
                  include UnusedKeys
         
     | 
| 
       23 
28 
     | 
    
         
             
                  include TranslationData
         
     | 
| 
       24 
     | 
    
         
            -
                  include  
     | 
| 
       25 
     | 
    
         
            -
                  include  
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                  # i18n-tasks config (defaults + config/i18n-tasks.yml)
         
     | 
| 
       28 
     | 
    
         
            -
                  # @return [Hash{String => String,Hash,Array}]
         
     | 
| 
       29 
     | 
    
         
            -
                  def config
         
     | 
| 
       30 
     | 
    
         
            -
                    I18n::Tasks.config
         
     | 
| 
       31 
     | 
    
         
            -
                  end
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                  def warn_deprecated(message)
         
     | 
| 
       34 
     | 
    
         
            -
                    I18n::Tasks.warn_deprecated(message)
         
     | 
| 
       35 
     | 
    
         
            -
                  end
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 29 
     | 
    
         
            +
                  include FillTasks
         
     | 
| 
      
 30 
     | 
    
         
            +
                  include GoogleTranslation
         
     | 
| 
       37 
31 
     | 
    
         
             
                end
         
     | 
| 
       38 
32 
     | 
    
         
             
              end
         
     | 
| 
       39 
33 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module I18n::Tasks::Configuration
         
     | 
| 
      
 2 
     | 
    
         
            +
              extend ActiveSupport::Concern
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              # i18n-tasks config (defaults + config/i18n-tasks.yml)
         
     | 
| 
      
 5 
     | 
    
         
            +
              # @return [Hash{String => String,Hash,Array}]
         
     | 
| 
      
 6 
     | 
    
         
            +
              def config
         
     | 
| 
      
 7 
     | 
    
         
            +
                @config ||= I18n::Tasks.config
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              DEFAULT_PATTERN = /\bt[( ]\s*(:?".+?"|:?'.+?'|:\w+)/
         
     | 
| 
      
 11 
     | 
    
         
            +
              # search config
         
     | 
| 
      
 12 
     | 
    
         
            +
              # @return [Hash{String => String,Hash,Array}]
         
     | 
| 
      
 13 
     | 
    
         
            +
              def search_config
         
     | 
| 
      
 14 
     | 
    
         
            +
                @search_config ||= begin
         
     | 
| 
      
 15 
     | 
    
         
            +
                  if config.key?(:grep)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    config[:search] ||= config.delete(:grep)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    I18n::Tasks.warn_deprecated 'please rename "grep" key to "search" in config/i18n-tasks.yml'
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  search_config = (config[:search] || {}).with_indifferent_access
         
     | 
| 
      
 20 
     | 
    
         
            +
                  search_config.tap do |conf|
         
     | 
| 
      
 21 
     | 
    
         
            +
                    conf[:paths] = %w(app/) if conf[:paths].blank?
         
     | 
| 
      
 22 
     | 
    
         
            +
                    conf[:include] = Array(conf[:include]) if conf[:include].present?
         
     | 
| 
      
 23 
     | 
    
         
            +
                    conf[:exclude] = Array(conf[:exclude])
         
     | 
| 
      
 24 
     | 
    
         
            +
                    conf[:pattern] = conf[:pattern].present? ? Regexp.new(conf[:pattern]) : DEFAULT_PATTERN
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              # translation config
         
     | 
| 
      
 30 
     | 
    
         
            +
              # @return [Hash{String => String,Hash,Array}]
         
     | 
| 
      
 31 
     | 
    
         
            +
              def translation_config
         
     | 
| 
      
 32 
     | 
    
         
            +
                @translation_config ||= begin
         
     | 
| 
      
 33 
     | 
    
         
            +
                  conf           = (config[:translation] ||= {}).with_indifferent_access
         
     | 
| 
      
 34 
     | 
    
         
            +
                  conf[:api_key] ||= ENV['GOOGLE_TRANSLATE_API_KEY']
         
     | 
| 
      
 35 
     | 
    
         
            +
                  conf
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -2,11 +2,16 @@ module I18n::Tasks::DataTraversal 
     | 
|
| 
       2 
2 
     | 
    
         
             
              # translation of the key found in the passed hash or nil
         
     | 
| 
       3 
3 
     | 
    
         
             
              # @return [String,nil]
         
     | 
| 
       4 
4 
     | 
    
         
             
              def t(hash = data[base_locale], key)
         
     | 
| 
      
 5 
     | 
    
         
            +
                if hash.is_a?(String)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # has is a locale
         
     | 
| 
      
 7 
     | 
    
         
            +
                  raise ArgumentError.new("invalid locale: #{hash}") if hash =~ /\W/
         
     | 
| 
      
 8 
     | 
    
         
            +
                  hash = data[hash]
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
       5 
10 
     | 
    
         
             
                key.split('.').inject(hash) { |r, seg| r[seg] if r }
         
     | 
| 
       6 
11 
     | 
    
         
             
              end
         
     | 
| 
       7 
12 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
              # traverse =>  
     | 
| 
       9 
     | 
    
         
            -
              def  
     | 
| 
      
 13 
     | 
    
         
            +
              # traverse => map if yield(k, v)
         
     | 
| 
      
 14 
     | 
    
         
            +
              def traverse_map_if(hash)
         
     | 
| 
       10 
15 
     | 
    
         
             
                list = []
         
     | 
| 
       11 
16 
     | 
    
         
             
                traverse hash do |k, v|
         
     | 
| 
       12 
17 
     | 
    
         
             
                  mapped = yield(k, v)
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module I18n::Tasks::FillTasks
         
     | 
| 
      
 2 
     | 
    
         
            +
              def add_missing!(locale = base_locale, placeholder = nil)
         
     | 
| 
      
 3 
     | 
    
         
            +
                normalize_store! locale
         
     | 
| 
      
 4 
     | 
    
         
            +
                set_blank_values! locale, locale == base_locale do |keys|
         
     | 
| 
      
 5 
     | 
    
         
            +
                  keys.map { |key|
         
     | 
| 
      
 6 
     | 
    
         
            +
                    placeholder || key.split('.').last.to_s.humanize
         
     | 
| 
      
 7 
     | 
    
         
            +
                  }
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def fill_with_blanks!(locales = nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                locales = non_base_locales(locales)
         
     | 
| 
      
 13 
     | 
    
         
            +
                add_missing! base_locale, ''
         
     | 
| 
      
 14 
     | 
    
         
            +
                normalize_store! locales
         
     | 
| 
      
 15 
     | 
    
         
            +
                locales.each do |locale|
         
     | 
| 
      
 16 
     | 
    
         
            +
                  add_missing! locale, ''
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def fill_with_google_translate!(locales = nil)
         
     | 
| 
      
 21 
     | 
    
         
            +
                normalize_store! base_locale
         
     | 
| 
      
 22 
     | 
    
         
            +
                locales = non_base_locales(locales)
         
     | 
| 
      
 23 
     | 
    
         
            +
                normalize_store! locales
         
     | 
| 
      
 24 
     | 
    
         
            +
                locales.each do |locale|
         
     | 
| 
      
 25 
     | 
    
         
            +
                  set_blank_values! locale do |blank_keys|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    google_translate blank_keys.map { |k| t(k) }, to: locale, from: base_locale
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def fill_with_base_values!(locales = nil)
         
     | 
| 
      
 32 
     | 
    
         
            +
                normalize_store! base_locale
         
     | 
| 
      
 33 
     | 
    
         
            +
                locales = non_base_locales(locales)
         
     | 
| 
      
 34 
     | 
    
         
            +
                normalize_store! locales
         
     | 
| 
      
 35 
     | 
    
         
            +
                locales.each do |locale|
         
     | 
| 
      
 36 
     | 
    
         
            +
                  set_blank_values! locale do |blank_keys|
         
     | 
| 
      
 37 
     | 
    
         
            +
                    blank_keys.map { |k| t(k) }
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              # fill blank values with values from passed block
         
     | 
| 
      
 43 
     | 
    
         
            +
              # @param [String] locale
         
     | 
| 
      
 44 
     | 
    
         
            +
              # @param [true, false] include_missing Include keys present in source but missing from base locale
         
     | 
| 
      
 45 
     | 
    
         
            +
              def set_blank_values!(locale = base_locale, include_missing = (locale == base_locale), &fill_with)
         
     | 
| 
      
 46 
     | 
    
         
            +
                blank_keys = traverse_map_if(data[base_locale]) { |key, value|
         
     | 
| 
      
 47 
     | 
    
         
            +
                  key if !key_value?(key, locale) && !ignore_key?(key, :missing)
         
     | 
| 
      
 48 
     | 
    
         
            +
                }
         
     | 
| 
      
 49 
     | 
    
         
            +
                blank_keys += keys_missing_from_base if include_missing
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                list         = blank_keys.uniq.zip fill_with.call(blank_keys)
         
     | 
| 
      
 52 
     | 
    
         
            +
                data[locale] = data[locale].deep_merge(list_to_tree(list))
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'easy_translate'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            module I18n::Tasks:: 
     | 
| 
      
 3 
     | 
    
         
            +
            module I18n::Tasks::GoogleTranslation
         
     | 
| 
       4 
4 
     | 
    
         
             
              def google_translate(strings, opts)
         
     | 
| 
       5 
5 
     | 
    
         
             
                return [] if strings.empty?
         
     | 
| 
       6 
6 
     | 
    
         
             
                opts = opts.dup
         
     | 
| 
         @@ -9,12 +9,4 @@ module I18n::Tasks::Translation 
     | 
|
| 
       9 
9 
     | 
    
         
             
                end
         
     | 
| 
       10 
10 
     | 
    
         
             
                EasyTranslate.translate strings, opts
         
     | 
| 
       11 
11 
     | 
    
         
             
              end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
              def translation_config
         
     | 
| 
       14 
     | 
    
         
            -
                @translation_config ||= begin
         
     | 
| 
       15 
     | 
    
         
            -
                  conf           = (config[:translation] ||= {}).with_indifferent_access
         
     | 
| 
       16 
     | 
    
         
            -
                  conf[:api_key] ||= ENV['GOOGLE_TRANSLATE_API_KEY']
         
     | 
| 
       17 
     | 
    
         
            -
                  conf
         
     | 
| 
       18 
     | 
    
         
            -
                end
         
     | 
| 
       19 
     | 
    
         
            -
              end
         
     | 
| 
       20 
12 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module I18n::Tasks::IgnoreKeys
         
     | 
| 
       2 
     | 
    
         
            -
              # whether to ignore the key 
     | 
| 
       3 
     | 
    
         
            -
              # will apply global ignore rules 
     | 
| 
      
 2 
     | 
    
         
            +
              # whether to ignore the key
         
     | 
| 
      
 3 
     | 
    
         
            +
              # will also apply global ignore rules
         
     | 
| 
      
 4 
     | 
    
         
            +
              # @param [:missing, :eq_base, :blank, :unused] ignore_type
         
     | 
| 
       4 
5 
     | 
    
         
             
              def ignore_key?(key, ignore_type, locale = nil)
         
     | 
| 
       5 
6 
     | 
    
         
             
                key =~ ignore_pattern(ignore_type, locale)
         
     | 
| 
       6 
7 
     | 
    
         
             
              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 
     | 
    
         
            -
                  warn_deprecated %Q(please change pattern "#{key_pattern}" to "#{key_pattern += '*'}" in config/i18n-tasks.yml)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  I18n::Tasks.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(/\./, '\.').
         
     | 
| 
         @@ -1,33 +1,23 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module I18n::Tasks::MissingKeys
         
     | 
| 
       2 
     | 
    
         
            -
              # missing keys, i.e. key that are in the code but are not in the base locale data
         
     | 
| 
       3 
     | 
    
         
            -
               
     | 
| 
       4 
     | 
    
         
            -
              def keys_missing_base_value
         
     | 
| 
      
 2 
     | 
    
         
            +
              # @return Array missing keys, i.e. key that are in the code but are not in the base locale data
         
     | 
| 
      
 3 
     | 
    
         
            +
              def keys_missing_from_base
         
     | 
| 
       5 
4 
     | 
    
         
             
                find_source_keys.reject { |key|
         
     | 
| 
       6 
5 
     | 
    
         
             
                  key_value?(key, base_locale) || pattern_key?(key) || ignore_key?(key, :missing)
         
     | 
| 
       7 
     | 
    
         
            -
                } 
     | 
| 
      
 6 
     | 
    
         
            +
                }
         
     | 
| 
       8 
7 
     | 
    
         
             
              end
         
     | 
| 
       9 
8 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
              #  
     | 
| 
       11 
     | 
    
         
            -
               
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                r   = []
         
     | 
| 
       15 
     | 
    
         
            -
                traverse data[base_locale] do |key, base_value|
         
     | 
| 
       16 
     | 
    
         
            -
                  value_in_locale = t(trn, key)
         
     | 
| 
       17 
     | 
    
         
            -
                  if value_in_locale.blank? && !ignore_key?(key, :missing)
         
     | 
| 
       18 
     | 
    
         
            -
                    r << {locale: locale, key: key, type: :blank, base_value: base_value}
         
     | 
| 
       19 
     | 
    
         
            -
                  elsif value_in_locale == base_value && !ignore_key?(key, :eq_base, locale)
         
     | 
| 
       20 
     | 
    
         
            -
                    r << {locale: locale, key: key, type: :eq_base, base_value: base_value}
         
     | 
| 
       21 
     | 
    
         
            -
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
              # @return Array keys missing value (but present in base)
         
     | 
| 
      
 10 
     | 
    
         
            +
              def keys_missing_value(locale)
         
     | 
| 
      
 11 
     | 
    
         
            +
                traverse_map_if data[base_locale] do |key, base_value|
         
     | 
| 
      
 12 
     | 
    
         
            +
                  key if !key_value?(key, locale) && !ignore_key?(key, :missing)
         
     | 
| 
       22 
13 
     | 
    
         
             
                end
         
     | 
| 
       23 
     | 
    
         
            -
                r
         
     | 
| 
       24 
14 
     | 
    
         
             
              end
         
     | 
| 
       25 
15 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
              #  
     | 
| 
       27 
     | 
    
         
            -
               
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                }
         
     | 
| 
      
 16 
     | 
    
         
            +
              # @return Array keys missing value (but present in base)
         
     | 
| 
      
 17 
     | 
    
         
            +
              def keys_where_value_eq_base(locale)
         
     | 
| 
      
 18 
     | 
    
         
            +
                traverse_map_if data[base_locale] do |key, base_value|
         
     | 
| 
      
 19 
     | 
    
         
            +
                  key if base_value == t(locale, key) && !ignore_key?(key, :eq_base, locale)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
       32 
21 
     | 
    
         
             
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       33 
23 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,13 +1,13 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module I18n::Tasks::PluralKeys
         
     | 
| 
       2 
2 
     | 
    
         
             
              PLURAL_KEY_RE = /\.(?:zero|one|two|few|many|other)$/
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
              # @param  
     | 
| 
       5 
     | 
    
         
            -
              # @param  
     | 
| 
      
 4 
     | 
    
         
            +
              # @param [String] key i18n key
         
     | 
| 
      
 5 
     | 
    
         
            +
              # @param [String] locale to pull key data from
         
     | 
| 
       6 
6 
     | 
    
         
             
              # @return the base form if the key is a specific plural form (e.g. apple for apple.many), and the key as passed otherwise
         
     | 
| 
       7 
     | 
    
         
            -
              def depluralize_key( 
     | 
| 
       8 
     | 
    
         
            -
                return key if key !~ PLURAL_KEY_RE || t( 
     | 
| 
      
 7 
     | 
    
         
            +
              def depluralize_key(locale = base_locale, key)
         
     | 
| 
      
 8 
     | 
    
         
            +
                return key if key !~ PLURAL_KEY_RE || t(locale, key).is_a?(Hash)
         
     | 
| 
       9 
9 
     | 
    
         
             
                parent_key      = key.split('.')[0..-2] * '.'
         
     | 
| 
       10 
     | 
    
         
            -
                plural_versions = t( 
     | 
| 
      
 10 
     | 
    
         
            +
                plural_versions = t(locale, parent_key)
         
     | 
| 
       11 
11 
     | 
    
         
             
                if plural_versions.is_a?(Hash) && plural_versions.all? { |k, v| ".#{k}" =~ PLURAL_KEY_RE && !v.is_a?(Hash) }
         
     | 
| 
       12 
12 
     | 
    
         
             
                  parent_key
         
     | 
| 
       13 
13 
     | 
    
         
             
                else
         
     | 
    
        data/lib/i18n/tasks/railtie.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # coding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'terminal-table'
         
     | 
| 
      
 3 
     | 
    
         
            +
            module I18n
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Tasks
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Reports
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class Terminal
         
     | 
| 
      
 7 
     | 
    
         
            +
                    include Term::ANSIColor
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def initialize
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @task = I18n::Tasks::BaseTask.new
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    attr_reader :task
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def missing_translations
         
     | 
| 
      
 16 
     | 
    
         
            +
                      recs = task.untranslated_keys
         
     | 
| 
      
 17 
     | 
    
         
            +
                      print_title "Missing keys and translations (#{recs.length})"
         
     | 
| 
      
 18 
     | 
    
         
            +
                      if recs.present?
         
     | 
| 
      
 19 
     | 
    
         
            +
                        type_sym  = {
         
     | 
| 
      
 20 
     | 
    
         
            +
                            :none    => red('✗'),
         
     | 
| 
      
 21 
     | 
    
         
            +
                            :blank   => yellow('∅'),
         
     | 
| 
      
 22 
     | 
    
         
            +
                            :eq_base => bold(blue('='))
         
     | 
| 
      
 23 
     | 
    
         
            +
                        }
         
     | 
| 
      
 24 
     | 
    
         
            +
                        type_desc = {
         
     | 
| 
      
 25 
     | 
    
         
            +
                            :none    => 'key missing',
         
     | 
| 
      
 26 
     | 
    
         
            +
                            :blank   => 'translation blank',
         
     | 
| 
      
 27 
     | 
    
         
            +
                            :eq_base => 'value same as base value'
         
     | 
| 
      
 28 
     | 
    
         
            +
                        }
         
     | 
| 
      
 29 
     | 
    
         
            +
                        $stderr.puts "#{bold 'Types:'} #{type_desc.keys.map { |k| "#{type_sym[k]} #{type_desc[k]}" } * ', '}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                        print_table headings: [magenta(bold('Locale')), bold('Type'), magenta('i18n Key'), bold(cyan "Base value (#{base_locale})")] do |t|
         
     | 
| 
      
 31 
     | 
    
         
            +
                          t.rows = recs.map { |rec|
         
     | 
| 
      
 32 
     | 
    
         
            +
                            if rec[:type] == :none
         
     | 
| 
      
 33 
     | 
    
         
            +
                              locale     = magenta bold rec[:locale]
         
     | 
| 
      
 34 
     | 
    
         
            +
                              base_value = ''
         
     | 
| 
      
 35 
     | 
    
         
            +
                            else
         
     | 
| 
      
 36 
     | 
    
         
            +
                              locale     = magenta rec[:locale]
         
     | 
| 
      
 37 
     | 
    
         
            +
                              base_value = cyan rec[:base_value].try(:strip) || ''
         
     | 
| 
      
 38 
     | 
    
         
            +
                            end
         
     | 
| 
      
 39 
     | 
    
         
            +
                            [{:value => locale, :alignment => :center },
         
     | 
| 
      
 40 
     | 
    
         
            +
                             {:value => type_sym[rec[:type]], :alignment => :center },
         
     | 
| 
      
 41 
     | 
    
         
            +
                             magenta(rec[:key]),
         
     | 
| 
      
 42 
     | 
    
         
            +
                             base_value]
         
     | 
| 
      
 43 
     | 
    
         
            +
                          }
         
     | 
| 
      
 44 
     | 
    
         
            +
                        end
         
     | 
| 
      
 45 
     | 
    
         
            +
                      else
         
     | 
| 
      
 46 
     | 
    
         
            +
                        print_success 'Good job! No translations missing!'
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    def unused_translations
         
     | 
| 
      
 51 
     | 
    
         
            +
                      unused = task.unused_keys
         
     | 
| 
      
 52 
     | 
    
         
            +
                      print_title "Unused i18n keys (#{unused.length})"
         
     | 
| 
      
 53 
     | 
    
         
            +
                      if unused.present?
         
     | 
| 
      
 54 
     | 
    
         
            +
                        print_table headings: [bold(magenta('i18n Key')), cyan("Base value (#{base_locale})")] do |t|
         
     | 
| 
      
 55 
     | 
    
         
            +
                          t.rows = unused.map { |x| [magenta(x[0]), cyan(x[1])] }
         
     | 
| 
      
 56 
     | 
    
         
            +
                        end
         
     | 
| 
      
 57 
     | 
    
         
            +
                      else
         
     | 
| 
      
 58 
     | 
    
         
            +
                        print_success 'Good job! Every translation is used!'
         
     | 
| 
      
 59 
     | 
    
         
            +
                      end
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    private
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    extend Term::ANSIColor
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    def print_title(title)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      $stderr.puts "#{bold cyan title.strip} #{dark "|"} #{bold "i18n-tasks v#{I18n::Tasks::VERSION}"}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    def print_success(message)
         
     | 
| 
      
 71 
     | 
    
         
            +
                      $stderr.puts(bold green message)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                    private
         
     | 
| 
      
 75 
     | 
    
         
            +
                    def indent(txt, n = 2)
         
     | 
| 
      
 76 
     | 
    
         
            +
                      spaces = ' ' * n
         
     | 
| 
      
 77 
     | 
    
         
            +
                      txt.gsub /^/, spaces
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    def print_table(opts, &block)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      puts ::Terminal::Table.new(opts, &block)
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,8 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'find'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            module I18n::Tasks::SourceKeys
         
     | 
| 
       4 
     | 
    
         
            -
              DEFAULT_PATTERN = /\bt[( ]\s*(:?".+?"|:?'.+?'|:\w+)/
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
4 
     | 
    
         
             
              # find all keys in the source (relative keys are returned in absolutized)
         
     | 
| 
       7 
5 
     | 
    
         
             
              # @return [Array<String>]
         
     | 
| 
       8 
6 
     | 
    
         
             
              def find_source_keys
         
     | 
| 
         @@ -29,24 +27,6 @@ module I18n::Tasks::SourceKeys 
     | 
|
| 
       29 
27 
     | 
    
         
             
                    find_source_keys.select { |k| k =~ /\#{.*?}/ || k.ends_with?('.') }.map { |k| k.split(/\.?#/)[0].presence }.compact
         
     | 
| 
       30 
28 
     | 
    
         
             
              end
         
     | 
| 
       31 
29 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
              # grep config, also from config/i18n-tasks.yml
         
     | 
| 
       33 
     | 
    
         
            -
              # @return [Hash{String => String,Hash,Array}]
         
     | 
| 
       34 
     | 
    
         
            -
              def search_config
         
     | 
| 
       35 
     | 
    
         
            -
                @search_config ||= begin
         
     | 
| 
       36 
     | 
    
         
            -
                  if config.key?(:grep)
         
     | 
| 
       37 
     | 
    
         
            -
                    config[:search] ||= config.delete(:grep)
         
     | 
| 
       38 
     | 
    
         
            -
                    warn_deprecated 'please rename "grep" key to "search" in config/i18n-tasks.yml'
         
     | 
| 
       39 
     | 
    
         
            -
                  end
         
     | 
| 
       40 
     | 
    
         
            -
                  search_config = (config[:search] || {}).with_indifferent_access
         
     | 
| 
       41 
     | 
    
         
            -
                  search_config.tap do |conf|
         
     | 
| 
       42 
     | 
    
         
            -
                    conf[:paths] = %w(app/) if conf[:paths].blank?
         
     | 
| 
       43 
     | 
    
         
            -
                    conf[:include] = Array(conf[:include]) if conf[:include].present?
         
     | 
| 
       44 
     | 
    
         
            -
                    conf[:exclude] = Array(conf[:exclude])
         
     | 
| 
       45 
     | 
    
         
            -
                    conf[:pattern] ||= conf[:pattern].present? ? Regexp.new(conf[:pattern]) : DEFAULT_PATTERN
         
     | 
| 
       46 
     | 
    
         
            -
                  end
         
     | 
| 
       47 
     | 
    
         
            -
                end
         
     | 
| 
       48 
     | 
    
         
            -
              end
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
30 
     | 
    
         
             
              # Run given block for every relevant file, according to search_config
         
     | 
| 
       51 
31 
     | 
    
         
             
              # @return [Array] Results of block calls
         
     | 
| 
       52 
32 
     | 
    
         
             
              def traverse_files
         
     | 
| 
         @@ -1,8 +1,6 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'i18n/tasks/data_traversal'
         
     | 
| 
       2 
1 
     | 
    
         
             
            require 'i18n/tasks/data/yaml'
         
     | 
| 
       3 
2 
     | 
    
         | 
| 
       4 
3 
     | 
    
         
             
            module I18n::Tasks::TranslationData
         
     | 
| 
       5 
     | 
    
         
            -
              include I18n::Tasks::DataTraversal
         
     | 
| 
       6 
4 
     | 
    
         | 
| 
       7 
5 
     | 
    
         
             
              # I18n data provider
         
     | 
| 
       8 
6 
     | 
    
         
             
              # @see I18n::Tasks::Data::Yaml
         
     | 
| 
         @@ -21,39 +19,27 @@ module I18n::Tasks::TranslationData 
     | 
|
| 
       21 
19 
     | 
    
         
             
                t(data[locale], key).present?
         
     | 
| 
       22 
20 
     | 
    
         
             
              end
         
     | 
| 
       23 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
              # @return [Array<String>] all available locales
         
     | 
| 
      
 23 
     | 
    
         
            +
              def locales
         
     | 
| 
      
 24 
     | 
    
         
            +
                config[:locales] ||= I18n.available_locales.map(&:to_s)
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       24 
27 
     | 
    
         
             
              # @return [String] default i18n locale
         
     | 
| 
       25 
28 
     | 
    
         
             
              def base_locale
         
     | 
| 
       26 
29 
     | 
    
         
             
                config[:base_locale] ||= I18n.default_locale.to_s
         
     | 
| 
       27 
30 
     | 
    
         
             
              end
         
     | 
| 
       28 
31 
     | 
    
         | 
| 
       29 
     | 
    
         
            -
               
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                 
     | 
| 
      
 32 
     | 
    
         
            +
              def non_base_locales(from = nil)
         
     | 
| 
      
 33 
     | 
    
         
            +
                from = self.locales unless from.present?
         
     | 
| 
      
 34 
     | 
    
         
            +
                Array(from) - [base_locale]
         
     | 
| 
       32 
35 
     | 
    
         
             
              end
         
     | 
| 
       33 
36 
     | 
    
         | 
| 
       34 
37 
     | 
    
         
             
              # write to store, normalizing all data
         
     | 
| 
       35 
     | 
    
         
            -
              def normalize_store!( 
     | 
| 
       36 
     | 
    
         
            -
                 
     | 
| 
      
 38 
     | 
    
         
            +
              def normalize_store!(from = nil)
         
     | 
| 
      
 39 
     | 
    
         
            +
                from = self.locales unless from.present?
         
     | 
| 
      
 40 
     | 
    
         
            +
                Array(from).each do |target_locale|
         
     | 
| 
       37 
41 
     | 
    
         
             
                  # the store itself handles normalization
         
     | 
| 
       38 
42 
     | 
    
         
             
                  data[target_locale] = data[target_locale]
         
     | 
| 
       39 
43 
     | 
    
         
             
                end
         
     | 
| 
       40 
44 
     | 
    
         
             
              end
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
              # fill missing / blank keys with values from passed block
         
     | 
| 
       43 
     | 
    
         
            -
              def fill_blanks!(locale = base_locale, &fill_with)
         
     | 
| 
       44 
     | 
    
         
            -
                blank_keys =
         
     | 
| 
       45 
     | 
    
         
            -
                    if locale == base_locale
         
     | 
| 
       46 
     | 
    
         
            -
                      # for base locale "blank" is: present in source but not in the base locale.
         
     | 
| 
       47 
     | 
    
         
            -
                      keys_missing_base_value.map { |e| e[:key] } +
         
     | 
| 
       48 
     | 
    
         
            -
                          traverse_flat_map(data[base_locale]) { |key, value|
         
     | 
| 
       49 
     | 
    
         
            -
                            key if value.to_s.blank? && !ignore_key?(key, :missing) }
         
     | 
| 
       50 
     | 
    
         
            -
                    else
         
     | 
| 
       51 
     | 
    
         
            -
                      # for other locales "blank" is: present in base but not in the locale itself.
         
     | 
| 
       52 
     | 
    
         
            -
                      traverse_flat_map(data[base_locale]) { |key|
         
     | 
| 
       53 
     | 
    
         
            -
                        key if !key_value?(key, locale) && !ignore_key?(key, :missing) }
         
     | 
| 
       54 
     | 
    
         
            -
                    end
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                list         = blank_keys.uniq.zip fill_with.call(blank_keys)
         
     | 
| 
       57 
     | 
    
         
            -
                data[locale] = data[locale].deep_merge(list_to_tree(list))
         
     | 
| 
       58 
     | 
    
         
            -
              end
         
     | 
| 
       59 
45 
     | 
    
         
             
            end
         
     | 
| 
         @@ -6,7 +6,20 @@ module I18n::Tasks::UntranslatedKeys 
     | 
|
| 
       6 
6 
     | 
    
         
             
              # :base_value — translation value in base locale if one is present
         
     | 
| 
       7 
7 
     | 
    
         
             
              # @return [Array<Hash{Symbol => String,Symbol,nil}>]
         
     | 
| 
       8 
8 
     | 
    
         
             
              def untranslated_keys
         
     | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
      
 9 
     | 
    
         
            +
                keys = keys_missing_from_base.map { |key| {locale: base_locale, key: key, type: :none} } +
         
     | 
| 
      
 10 
     | 
    
         
            +
                    non_base_locales.map { |locale|
         
     | 
| 
      
 11 
     | 
    
         
            +
                      keys_missing_value(locale).map { |key| {locale: locale, key: key, type: :blank, base_value: t(base_locale, key)}} + keys_where_value_eq_base(locale).map { |key|
         
     | 
| 
      
 12 
     | 
    
         
            +
                        {locale: locale, key: key, type: :eq_base, base_value: t(base_locale, key)}
         
     | 
| 
      
 13 
     | 
    
         
            +
                      }
         
     | 
| 
      
 14 
     | 
    
         
            +
                    }.flatten
         
     | 
| 
      
 15 
     | 
    
         
            +
                sort_keys keys
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              # sort first by locale, then by type
         
     | 
| 
      
 19 
     | 
    
         
            +
              # @return Array{Hash}
         
     | 
| 
      
 20 
     | 
    
         
            +
              def sort_keys(keys)
         
     | 
| 
      
 21 
     | 
    
         
            +
                keys.sort { |a, b|
         
     | 
| 
      
 22 
     | 
    
         
            +
                  (l = a[:locale] <=> b[:locale]).zero? ? a[:type] <=> b[:type] : l
         
     | 
| 
      
 23 
     | 
    
         
            +
                }
         
     | 
| 
       11 
24 
     | 
    
         
             
              end
         
     | 
| 
       12 
25 
     | 
    
         
             
            end
         
     | 
| 
         @@ -4,15 +4,12 @@ module I18n 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module Tasks
         
     | 
| 
       5 
5 
     | 
    
         
             
                module UnusedKeys
         
     | 
| 
       6 
6 
     | 
    
         
             
                  # @return [Array<[String, String]>] all the unused translations as an array of [key, value] pairs
         
     | 
| 
       7 
     | 
    
         
            -
                  def unused_keys
         
     | 
| 
       8 
     | 
    
         
            -
                     
     | 
| 
       9 
     | 
    
         
            -
                    d = self.data[base_locale]
         
     | 
| 
       10 
     | 
    
         
            -
                    traverse d do |key, value|
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def unused_keys(locale = base_locale)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    traverse_map_if data[locale] do |key, value|
         
     | 
| 
       11 
9 
     | 
    
         
             
                      next if pattern_key?(key) || ignore_key?(key, :unused)
         
     | 
| 
       12 
     | 
    
         
            -
                      key = depluralize_key( 
     | 
| 
       13 
     | 
    
         
            -
                       
     | 
| 
       14 
     | 
    
         
            -
                    end
         
     | 
| 
       15 
     | 
    
         
            -
                    r.uniq
         
     | 
| 
      
 10 
     | 
    
         
            +
                      key = depluralize_key(locale, key)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      [key, value] unless used_key?(key)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end.uniq
         
     | 
| 
       16 
13 
     | 
    
         
             
                  end
         
     | 
| 
       17 
14 
     | 
    
         
             
                end
         
     | 
| 
       18 
15 
     | 
    
         
             
              end
         
     | 
    
        data/lib/i18n/tasks/version.rb
    CHANGED
    
    
    
        data/lib/tasks/i18n-tasks.rake
    CHANGED
    
    | 
         @@ -1,95 +1,72 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'set'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'i18n/tasks/base_task'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'i18n/tasks/ 
     | 
| 
      
 3 
     | 
    
         
            +
            require 'i18n/tasks/reports/terminal'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'active_support/core_ext/module/delegation'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            namespace :i18n do
         
     | 
| 
       6 
7 
     | 
    
         
             
              desc 'show missing translations'
         
     | 
| 
       7 
8 
     | 
    
         
             
              task :missing => 'i18n:setup' do
         
     | 
| 
       8 
     | 
    
         
            -
                 
     | 
| 
      
 9 
     | 
    
         
            +
                report.missing_translations
         
     | 
| 
       9 
10 
     | 
    
         
             
              end
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
              desc 'show unused translations'
         
     | 
| 
       12 
13 
     | 
    
         
             
              task :unused => 'i18n:setup' do
         
     | 
| 
       13 
     | 
    
         
            -
                 
     | 
| 
      
 14 
     | 
    
         
            +
                report.unused_translations
         
     | 
| 
       14 
15 
     | 
    
         
             
              end
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
              desc 'normalize translation data: sort and move to the right files'
         
     | 
| 
       17 
     | 
    
         
            -
              task :normalize => 'i18n:setup' do
         
     | 
| 
       18 
     | 
    
         
            -
                normalize_store!
         
     | 
| 
      
 18 
     | 
    
         
            +
              task :normalize, [:locales] => 'i18n:setup' do |t, args|
         
     | 
| 
      
 19 
     | 
    
         
            +
                i18n_tasks.normalize_store! args[:locales]
         
     | 
| 
       19 
20 
     | 
    
         
             
              end
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
       21 
22 
     | 
    
         
             
              desc 'add <key: placeholder || key.humanize> to the base locale'
         
     | 
| 
       22 
23 
     | 
    
         
             
              task :add_missing, [:placeholder] => 'i18n:setup' do |t, args|
         
     | 
| 
       23 
     | 
    
         
            -
                 
     | 
| 
       24 
     | 
    
         
            -
                i18n_tasks.fill_blanks!(base_locale) { |keys|
         
     | 
| 
       25 
     | 
    
         
            -
                  keys.map { |key|
         
     | 
| 
       26 
     | 
    
         
            -
                    args[:placeholder] || key.split('.').last.to_s.humanize
         
     | 
| 
       27 
     | 
    
         
            -
                  }
         
     | 
| 
       28 
     | 
    
         
            -
                }
         
     | 
| 
      
 24 
     | 
    
         
            +
                i18n_tasks.add_missing! base_locale, args[:placeholder]
         
     | 
| 
       29 
25 
     | 
    
         
             
              end
         
     | 
| 
       30 
26 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
27 
     | 
    
         
             
              desc 'fill translations with values'
         
     | 
| 
       33 
28 
     | 
    
         
             
              namespace :fill do
         
     | 
| 
       34 
29 
     | 
    
         | 
| 
       35 
30 
     | 
    
         
             
                desc 'add <key: ""> to each locale'
         
     | 
| 
       36 
31 
     | 
    
         
             
                task :blanks, [:locales] => 'i18n:setup' do |t, args|
         
     | 
| 
       37 
     | 
    
         
            -
                   
     | 
| 
       38 
     | 
    
         
            -
                  [base_locale, *non_base_locales].each do |locale|
         
     | 
| 
       39 
     | 
    
         
            -
                    fill_blanks!(locale) { |blank_keys| blank_keys.map { '' } }
         
     | 
| 
       40 
     | 
    
         
            -
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  i18n_tasks.fill_with_blanks! parse_locales args[:locales]
         
     | 
| 
       41 
33 
     | 
    
         
             
                end
         
     | 
| 
       42 
34 
     | 
    
         | 
| 
       43 
35 
     | 
    
         
             
                desc 'add <key: Google Translated value> to each non-base locale, uses env GOOGLE_TRANSLATE_API_KEY'
         
     | 
| 
       44 
36 
     | 
    
         
             
                task :google_translate, [:locales] => 'i18n:setup' do |t, args|
         
     | 
| 
       45 
     | 
    
         
            -
                   
     | 
| 
       46 
     | 
    
         
            -
                  non_base_locales(args).each do |locale|
         
     | 
| 
       47 
     | 
    
         
            -
                    fill_blanks!(locale) { |blank_keys|
         
     | 
| 
       48 
     | 
    
         
            -
                      i18n_tasks.google_translate blank_keys.map { |k| t(k) }, to: locale, from: base_locale
         
     | 
| 
       49 
     | 
    
         
            -
                    }
         
     | 
| 
       50 
     | 
    
         
            -
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  i18n_tasks.fill_with_google_translate! parse_locales args[:locales]
         
     | 
| 
       51 
38 
     | 
    
         
             
                end
         
     | 
| 
       52 
39 
     | 
    
         | 
| 
       53 
40 
     | 
    
         
             
                desc 'add <key: base value> to each non-base locale'
         
     | 
| 
       54 
41 
     | 
    
         
             
                task :base_value, [:locales] => 'i18n:setup' do |t, args|
         
     | 
| 
       55 
     | 
    
         
            -
                   
     | 
| 
       56 
     | 
    
         
            -
                  non_base_locales(args).each do |locale|
         
     | 
| 
       57 
     | 
    
         
            -
                    fill_blanks!(locale) { |blank_keys| blank_keys.map { |k| t(k) } }
         
     | 
| 
       58 
     | 
    
         
            -
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                  i18n_tasks.fill_with_base_values! parse_locales args[:locales]
         
     | 
| 
       59 
43 
     | 
    
         
             
                end
         
     | 
| 
       60 
44 
     | 
    
         
             
              end
         
     | 
| 
       61 
45 
     | 
    
         | 
| 
       62 
46 
     | 
    
         
             
              task 'i18n:setup' => :environment do
         
     | 
| 
       63 
47 
     | 
    
         
             
                if File.exists?('.i18nignore')
         
     | 
| 
       64 
     | 
    
         
            -
                   
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
      
 48 
     | 
    
         
            +
                  I18n::Tasks.warn_deprecated "Looks like you are using .i18ignore. It is no longer used in favour of config/i18n-tasks.yml.\n
         
     | 
| 
      
 49 
     | 
    
         
            +
            See README.md https://github.com/glebm/i18n-tasks"
         
     | 
| 
       66 
50 
     | 
    
         
             
                end
         
     | 
| 
       67 
51 
     | 
    
         
             
              end
         
     | 
| 
       68 
52 
     | 
    
         | 
| 
       69 
53 
     | 
    
         
             
              module I18n::Tasks::RakeHelpers
         
     | 
| 
       70 
     | 
    
         
            -
                 
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                included do
         
     | 
| 
       73 
     | 
    
         
            -
                  delegate :t, :locales, :base_locale, :normalize_store!, :fill_blanks!, to: :i18n_tasks
         
     | 
| 
      
 54 
     | 
    
         
            +
                include Term::ANSIColor
         
     | 
| 
       74 
55 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
                    @i18n_tasks ||= I18n::Tasks::BaseTask.new
         
     | 
| 
       77 
     | 
    
         
            -
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                delegate :base_locale, to: :i18n_tasks
         
     | 
| 
       78 
57 
     | 
    
         | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                def i18n_tasks
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @i18n_tasks ||= I18n::Tasks::BaseTask.new
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
       82 
61 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
      
 62 
     | 
    
         
            +
                def report
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @report ||= I18n::Tasks::Reports::Terminal.new
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
       86 
65 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
                def parse_locales(arg = nil)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  arg.try(:strip).try(:split, /\s*\+\s*/).try(:compact)
         
     | 
| 
       90 
68 
     | 
    
         
             
                end
         
     | 
| 
       91 
69 
     | 
    
         
             
              end
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
70 
     | 
    
         
             
              include I18n::Tasks::RakeHelpers
         
     | 
| 
       94 
     | 
    
         
            -
              include Term::ANSIColor
         
     | 
| 
       95 
71 
     | 
    
         
             
            end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
    
        data/spec/i18n_tasks_spec.rb
    CHANGED
    
    | 
         @@ -17,7 +17,8 @@ describe 'rake i18n' do 
     | 
|
| 
       17 
17 
     | 
    
         
             
              describe 'unused' do
         
     | 
| 
       18 
18 
     | 
    
         
             
                it 'detects unused' do
         
     | 
| 
       19 
19 
     | 
    
         
             
                  TestCodebase.capture_stderr do
         
     | 
| 
       20 
     | 
    
         
            -
                    TestCodebase.rake_result('i18n:unused') 
     | 
| 
      
 20 
     | 
    
         
            +
                    out = TestCodebase.rake_result('i18n:unused')
         
     | 
| 
      
 21 
     | 
    
         
            +
                    out.should be_i18n_keys %w(unused.a unused.numeric unused.plural)
         
     | 
| 
       21 
22 
     | 
    
         
             
                  end.should =~ /Unused i18n keys \(3\)/
         
     | 
| 
       22 
23 
     | 
    
         
             
                end
         
     | 
| 
       23 
24 
     | 
    
         
             
              end
         
     | 
| 
         @@ -5,9 +5,12 @@ RSpec::Matchers.define :be_i18n_keys do |expected| 
     | 
|
| 
       5 
5 
     | 
    
         
             
              end
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
              def extract_keys(actual)
         
     | 
| 
       8 
     | 
    
         
            -
                actual = actual.split("\n").map(&:presence).compact 
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 8 
     | 
    
         
            +
                actual = actual.split("\n").map(&:presence).compact
         
     | 
| 
      
 9 
     | 
    
         
            +
                actual = actual[3..-2] if actual[0] = /^\s*[+-]+\s*$/
         
     | 
| 
      
 10 
     | 
    
         
            +
                actual = actual.map { |row|
         
     | 
| 
      
 11 
     | 
    
         
            +
                  row.gsub(/(?:\s|^)\|(?:\s|$)/, ' ').gsub(/\s+/, ' ').strip.split(' ').map(&:presence).compact
         
     | 
| 
       10 
12 
     | 
    
         
             
                }
         
     | 
| 
      
 13 
     | 
    
         
            +
                return [] if actual.empty?
         
     | 
| 
       11 
14 
     | 
    
         
             
                if actual[0][1] =~ /[✗∅=]/
         
     | 
| 
       12 
15 
     | 
    
         
             
                  locale_col = 0
         
     | 
| 
       13 
16 
     | 
    
         
             
                  key_col    = 2
         
     | 
    
        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.2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.2
         
     | 
| 
       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- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2013-11-24 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rake
         
     | 
| 
         @@ -66,6 +66,20 @@ dependencies: 
     | 
|
| 
       66 
66 
     | 
    
         
             
                - - '>='
         
     | 
| 
       67 
67 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       68 
68 
     | 
    
         
             
                    version: '0'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: terminal-table
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - '>='
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
       69 
83 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       70 
84 
     | 
    
         
             
              name: bundler
         
     | 
| 
       71 
85 
     | 
    
         
             
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
         @@ -122,7 +136,10 @@ dependencies: 
     | 
|
| 
       122 
136 
     | 
    
         
             
                - - '>='
         
     | 
| 
       123 
137 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       124 
138 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       125 
     | 
    
         
            -
            description:  
     | 
| 
      
 139 
     | 
    
         
            +
            description: |2
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  rake tasks to find unused and missing translations, normalize locale files,
         
     | 
| 
      
 142 
     | 
    
         
            +
                  and prefill missing keys. Supports relative and plural keys and Google Translate.
         
     | 
| 
       126 
143 
     | 
    
         
             
            email:
         
     | 
| 
       127 
144 
     | 
    
         
             
            - glex.spb@gmail.com
         
     | 
| 
       128 
145 
     | 
    
         
             
            executables: []
         
     | 
| 
         @@ -140,17 +157,19 @@ files: 
     | 
|
| 
       140 
157 
     | 
    
         
             
            - i18n-tasks.gemspec
         
     | 
| 
       141 
158 
     | 
    
         
             
            - lib/i18n/tasks.rb
         
     | 
| 
       142 
159 
     | 
    
         
             
            - lib/i18n/tasks/base_task.rb
         
     | 
| 
      
 160 
     | 
    
         
            +
            - lib/i18n/tasks/configuration.rb
         
     | 
| 
       143 
161 
     | 
    
         
             
            - lib/i18n/tasks/data/yaml.rb
         
     | 
| 
       144 
162 
     | 
    
         
             
            - lib/i18n/tasks/data_traversal.rb
         
     | 
| 
      
 163 
     | 
    
         
            +
            - lib/i18n/tasks/fill_tasks.rb
         
     | 
| 
      
 164 
     | 
    
         
            +
            - lib/i18n/tasks/google_translation.rb
         
     | 
| 
       145 
165 
     | 
    
         
             
            - lib/i18n/tasks/ignore_keys.rb
         
     | 
| 
       146 
166 
     | 
    
         
             
            - lib/i18n/tasks/key_pattern_matching.rb
         
     | 
| 
       147 
167 
     | 
    
         
             
            - lib/i18n/tasks/missing_keys.rb
         
     | 
| 
       148 
     | 
    
         
            -
            - lib/i18n/tasks/output/terminal.rb
         
     | 
| 
       149 
168 
     | 
    
         
             
            - lib/i18n/tasks/plural_keys.rb
         
     | 
| 
       150 
169 
     | 
    
         
             
            - lib/i18n/tasks/railtie.rb
         
     | 
| 
       151 
170 
     | 
    
         
             
            - lib/i18n/tasks/relative_keys.rb
         
     | 
| 
      
 171 
     | 
    
         
            +
            - lib/i18n/tasks/reports/terminal.rb
         
     | 
| 
       152 
172 
     | 
    
         
             
            - lib/i18n/tasks/source_keys.rb
         
     | 
| 
       153 
     | 
    
         
            -
            - lib/i18n/tasks/translation.rb
         
     | 
| 
       154 
173 
     | 
    
         
             
            - lib/i18n/tasks/translation_data.rb
         
     | 
| 
       155 
174 
     | 
    
         
             
            - lib/i18n/tasks/untranslated_keys.rb
         
     | 
| 
       156 
175 
     | 
    
         
             
            - lib/i18n/tasks/unused_keys.rb
         
     | 
| 
         @@ -192,7 +211,7 @@ rubyforge_project: 
     | 
|
| 
       192 
211 
     | 
    
         
             
            rubygems_version: 2.1.10
         
     | 
| 
       193 
212 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       194 
213 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       195 
     | 
    
         
            -
            summary:  
     | 
| 
      
 214 
     | 
    
         
            +
            summary: Tasks to manage missing and unused translations in Rails.
         
     | 
| 
       196 
215 
     | 
    
         
             
            test_files:
         
     | 
| 
       197 
216 
     | 
    
         
             
            - spec/fixtures/app/assets/javascripts/application.js
         
     | 
| 
       198 
217 
     | 
    
         
             
            - spec/fixtures/app/controllers/events_controller.rb
         
     | 
| 
         @@ -1,67 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # coding: utf-8
         
     | 
| 
       2 
     | 
    
         
            -
            module I18n
         
     | 
| 
       3 
     | 
    
         
            -
              module Tasks
         
     | 
| 
       4 
     | 
    
         
            -
                module Output
         
     | 
| 
       5 
     | 
    
         
            -
                  class Terminal
         
     | 
| 
       6 
     | 
    
         
            -
                    include Term::ANSIColor
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
                    def missing(missing)
         
     | 
| 
       9 
     | 
    
         
            -
                      print_title "Missing keys and translations (#{missing.length})"
         
     | 
| 
       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'}"
         
     | 
| 
       12 
     | 
    
         
            -
                        key_col_width = missing.map { |x| x[:key] }.max_by(&:length).length + 2
         
     | 
| 
       13 
     | 
    
         
            -
                        missing.each { |m| print_missing_translation m, key_col_width: key_col_width }
         
     | 
| 
       14 
     | 
    
         
            -
                      else
         
     | 
| 
       15 
     | 
    
         
            -
                        print_success 'Good job! No translations missing!'
         
     | 
| 
       16 
     | 
    
         
            -
                      end
         
     | 
| 
       17 
     | 
    
         
            -
                    end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                    def unused(unused)
         
     | 
| 
       20 
     | 
    
         
            -
                      print_title "Unused i18n keys (#{unused.length})"
         
     | 
| 
       21 
     | 
    
         
            -
                      if unused.present?
         
     | 
| 
       22 
     | 
    
         
            -
                        key_col_width = unused.max_by { |x| x[0].length }[0].length + 2
         
     | 
| 
       23 
     | 
    
         
            -
                        unused.each { |(key, value)| puts "#{magenta key.ljust(key_col_width)}#{cyan value.to_s.strip}" }
         
     | 
| 
       24 
     | 
    
         
            -
                      else
         
     | 
| 
       25 
     | 
    
         
            -
                        print_success 'Good job! Every translation is used!'
         
     | 
| 
       26 
     | 
    
         
            -
                      end
         
     | 
| 
       27 
     | 
    
         
            -
                    end
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                    private
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       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 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                    def print_missing_translation(m, opts)
         
     | 
| 
       43 
     | 
    
         
            -
                      status_texts = {
         
     | 
| 
       44 
     | 
    
         
            -
                          none:    red("✗".ljust(6)),
         
     | 
| 
       45 
     | 
    
         
            -
                          blank:   yellow(bold '∅'.ljust(6)),
         
     | 
| 
       46 
     | 
    
         
            -
                          eq_base: blue(bold "=".ljust(6))
         
     | 
| 
       47 
     | 
    
         
            -
                      }
         
     | 
| 
       48 
     | 
    
         
            -
                      locale, key, base_value, status_text = m[:locale], m[:key], m[:base_value].to_s.try(:strip), " #{status_texts[m[:type]]}"
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                      key = magenta "#{key}".ljust(opts[:key_col_width])
         
     | 
| 
       51 
     | 
    
         
            -
                      s   = if m[:type] == :none
         
     | 
| 
       52 
     | 
    
         
            -
                              "#{red bold locale.ljust(4)} #{status_text} #{key}"
         
     | 
| 
       53 
     | 
    
         
            -
                            else
         
     | 
| 
       54 
     | 
    
         
            -
                              "#{bold locale.ljust(4)} #{status_text} #{key} #{cyan base_value.strip.gsub("\n", ' ')}"
         
     | 
| 
       55 
     | 
    
         
            -
                            end
         
     | 
| 
       56 
     | 
    
         
            -
                      puts s
         
     | 
| 
       57 
     | 
    
         
            -
                    end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                    private
         
     | 
| 
       60 
     | 
    
         
            -
                    def indent(txt, n = 2)
         
     | 
| 
       61 
     | 
    
         
            -
                      spaces = ' ' * n
         
     | 
| 
       62 
     | 
    
         
            -
                      txt.gsub /^/, spaces
         
     | 
| 
       63 
     | 
    
         
            -
                    end
         
     | 
| 
       64 
     | 
    
         
            -
                  end
         
     | 
| 
       65 
     | 
    
         
            -
                end
         
     | 
| 
       66 
     | 
    
         
            -
              end
         
     | 
| 
       67 
     | 
    
         
            -
            end
         
     |