i18n_linter 0.1.0
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 +7 -0
 - data/README.md +95 -0
 - data/config/default.yml +36 -0
 - data/exe/i18n_linter +28 -0
 - data/lib/i18n_linter/config.rb +75 -0
 - data/lib/i18n_linter/constants.rb +101 -0
 - data/lib/i18n_linter/helpers/digger.rb +31 -0
 - data/lib/i18n_linter/linter.rb +112 -0
 - data/lib/i18n_linter/options.rb +24 -0
 - data/lib/i18n_linter/result.rb +15 -0
 - data/lib/i18n_linter/result_set.rb +25 -0
 - data/lib/i18n_linter/rules/class_name.rb +14 -0
 - data/lib/i18n_linter/rules/constant.rb +18 -0
 - data/lib/i18n_linter/rules/environment_variable.rb +19 -0
 - data/lib/i18n_linter/rules/http_headers.rb +44 -0
 - data/lib/i18n_linter/rules/logger.rb +19 -0
 - data/lib/i18n_linter/rules/middle_space.rb +11 -0
 - data/lib/i18n_linter/rules/mime_type.rb +27 -0
 - data/lib/i18n_linter/rules/puts.rb +19 -0
 - data/lib/i18n_linter/rules/query.rb +12 -0
 - data/lib/i18n_linter/rules/reg_exp.rb +11 -0
 - data/lib/i18n_linter/rules/scope.rb +13 -0
 - data/lib/i18n_linter/rules/strftime.rb +14 -0
 - data/lib/i18n_linter/rules/underscore.rb +20 -0
 - data/lib/i18n_linter/rules/words.rb +11 -0
 - data/lib/i18n_linter/rules.rb +30 -0
 - data/lib/i18n_linter/runner.rb +54 -0
 - data/lib/i18n_linter/string_line.rb +15 -0
 - data/lib/i18n_linter/token.rb +15 -0
 - data/lib/i18n_linter/version.rb +5 -0
 - data/lib/i18n_linter.rb +37 -0
 - metadata +143 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 546355f63e25c1190ee40b9754f0c4da3c975eae482294e7e6cdf5d05ac6adf8
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 5c67c90c7145f8cad0be840c4f612532f01a724a2152b702d15479e741e1425c
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 22ed44d204dbfa491c700496ee972863baac3cd6c5aacc6f30f6d2276e052adb4fdb68717e763a3cd82f3fd3c786d582562644e3e0a33447ce7a5ea891209a88
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 9c926cc219f5e2ffe66104c74db113abcd2b8f017a3e1bf1f5e1abe9ee4f369efaeeced79a5724c2265bd1a901a60e9dcd0dd6484490515a34041c563338b7dd
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,95 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # I18nLinter
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            [](https://circleci.com/gh/rootstrap/i18n_linter/tree/master)
         
     | 
| 
      
 4 
     | 
    
         
            +
            [](https://codeclimate.com/repos/5c6b0bbdd561465d35008579/maintainability)
         
     | 
| 
      
 5 
     | 
    
         
            +
            [](https://codeclimate.com/repos/5c6b0bbdd561465d35008579/test_coverage)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Internationalization linter for your Ruby on Rails projects.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 10 
     | 
    
         
            +
            All you have to do is run the following command:
         
     | 
| 
      
 11 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 12 
     | 
    
         
            +
            $ gem install i18n_linter
         
     | 
| 
      
 13 
     | 
    
         
            +
            ```
         
     | 
| 
      
 14 
     | 
    
         
            +
            If you want to install using `bundler`, add this to the `Gemfile` under the `development` group:
         
     | 
| 
      
 15 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 16 
     | 
    
         
            +
            gem 'i18n_linter', require: false
         
     | 
| 
      
 17 
     | 
    
         
            +
            ```
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 20 
     | 
    
         
            +
            Just type `i18n_linter` in a Ruby on Rails project's folder and watch the strings that could be internationalized. Note: only strings in ruby files will be reported.
         
     | 
| 
      
 21 
     | 
    
         
            +
            ```
         
     | 
| 
      
 22 
     | 
    
         
            +
            $ cd my/ruby_on_rails/project
         
     | 
| 
      
 23 
     | 
    
         
            +
            $ i18n_linter [options]
         
     | 
| 
      
 24 
     | 
    
         
            +
            ```
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            ## Options
         
     | 
| 
      
 27 
     | 
    
         
            +
            The available options are:
         
     | 
| 
      
 28 
     | 
    
         
            +
            ```
         
     | 
| 
      
 29 
     | 
    
         
            +
            -f PATTERN, --files=PATTERN     Pattern to find files, default: -f '**/*.rb'
         
     | 
| 
      
 30 
     | 
    
         
            +
            -o FILE, --out=FILE,            Write output to a file instead of STDOUT
         
     | 
| 
      
 31 
     | 
    
         
            +
            ```
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            For example:
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ```
         
     | 
| 
      
 36 
     | 
    
         
            +
            $ i18n_linter -f users_controller.rb
         
     | 
| 
      
 37 
     | 
    
         
            +
            ```
         
     | 
| 
      
 38 
     | 
    
         
            +
            ```
         
     | 
| 
      
 39 
     | 
    
         
            +
            $ i18n_linter -f app/controllers/**/*.rb -o i18n_linter_output.txt
         
     | 
| 
      
 40 
     | 
    
         
            +
            ```
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ## Configuration
         
     | 
| 
      
 43 
     | 
    
         
            +
            The behavior of I18nLinter can be controlled via the `.i18n_linter.yml` configuration file.
         
     | 
| 
      
 44 
     | 
    
         
            +
            It's possible to enable or disable Rules and exclude files from the validations as follows:
         
     | 
| 
      
 45 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 46 
     | 
    
         
            +
            Linter:
         
     | 
| 
      
 47 
     | 
    
         
            +
              Include:
         
     | 
| 
      
 48 
     | 
    
         
            +
                - '**/*.rb'
         
     | 
| 
      
 49 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 50 
     | 
    
         
            +
                - 'spec/**/*'
         
     | 
| 
      
 51 
     | 
    
         
            +
            Rules:
         
     | 
| 
      
 52 
     | 
    
         
            +
              Uppercase:
         
     | 
| 
      
 53 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 54 
     | 
    
         
            +
              MiddleSpace:
         
     | 
| 
      
 55 
     | 
    
         
            +
                Enabled: false
         
     | 
| 
      
 56 
     | 
    
         
            +
            ```
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            ## Example
         
     | 
| 
      
 59 
     | 
    
         
            +
            Imagine a source file sample.rb containing:
         
     | 
| 
      
 60 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 61 
     | 
    
         
            +
            class UserController < ApplicationController
         
     | 
| 
      
 62 
     | 
    
         
            +
              rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              def show
         
     | 
| 
      
 65 
     | 
    
         
            +
                @user = User.find(params[:id])
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              private
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              def render_not_found
         
     | 
| 
      
 71 
     | 
    
         
            +
                render json: { error: "Couldn't find the record" }, status: :not_found
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
      
 74 
     | 
    
         
            +
            ```
         
     | 
| 
      
 75 
     | 
    
         
            +
            I18nLinter will return the following warnings in this file:
         
     | 
| 
      
 76 
     | 
    
         
            +
            ```
         
     | 
| 
      
 77 
     | 
    
         
            +
            $ i18n_linter -f sample.rb
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            sample.rb:11:26
         
     | 
| 
      
 80 
     | 
    
         
            +
            10:    def render_not_found
         
     | 
| 
      
 81 
     | 
    
         
            +
            11:      render json: { error: "Couldn't find the record" }, status: :not_found
         
     | 
| 
      
 82 
     | 
    
         
            +
            12:    end
         
     | 
| 
      
 83 
     | 
    
         
            +
            ----------------
         
     | 
| 
      
 84 
     | 
    
         
            +
            ```
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 87 
     | 
    
         
            +
            Bug reports (please use Issues) and pull requests are welcome on GitHub at https://github.com/rootstrap/i18n_linter. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            ## License
         
     | 
| 
      
 90 
     | 
    
         
            +
            The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            ## Credits
         
     | 
| 
      
 93 
     | 
    
         
            +
            **I18nLinter** is maintained by [Rootstrap](http://www.rootstrap.com) with the help of our [contributors](https://github.com/rootstrap/i18n_linter/contributors).
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
            [<img src="https://s3-us-west-1.amazonaws.com/rootstrap.com/img/rs.png" width="100"/>](http://www.rootstrap.com)
         
     | 
    
        data/config/default.yml
    ADDED
    
    | 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Linter:
         
     | 
| 
      
 2 
     | 
    
         
            +
              Include:
         
     | 
| 
      
 3 
     | 
    
         
            +
                - '**/*.rb'
         
     | 
| 
      
 4 
     | 
    
         
            +
              Exclude:
         
     | 
| 
      
 5 
     | 
    
         
            +
                - 'config/**/*'
         
     | 
| 
      
 6 
     | 
    
         
            +
                - 'spec/**/*'
         
     | 
| 
      
 7 
     | 
    
         
            +
                - 'db/**/*'
         
     | 
| 
      
 8 
     | 
    
         
            +
            Rules:
         
     | 
| 
      
 9 
     | 
    
         
            +
              ClassName:
         
     | 
| 
      
 10 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 11 
     | 
    
         
            +
              Constant:
         
     | 
| 
      
 12 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 13 
     | 
    
         
            +
              EnvironmentVariable:
         
     | 
| 
      
 14 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 15 
     | 
    
         
            +
              HttpHeaders:
         
     | 
| 
      
 16 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 17 
     | 
    
         
            +
              Logger:
         
     | 
| 
      
 18 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 19 
     | 
    
         
            +
              MiddleSpace:
         
     | 
| 
      
 20 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 21 
     | 
    
         
            +
              MimeType:
         
     | 
| 
      
 22 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 23 
     | 
    
         
            +
              Puts:
         
     | 
| 
      
 24 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 25 
     | 
    
         
            +
              Query:
         
     | 
| 
      
 26 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 27 
     | 
    
         
            +
              RegExp:
         
     | 
| 
      
 28 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 29 
     | 
    
         
            +
              Scope:
         
     | 
| 
      
 30 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 31 
     | 
    
         
            +
              Strftime:
         
     | 
| 
      
 32 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 33 
     | 
    
         
            +
              Underscore:
         
     | 
| 
      
 34 
     | 
    
         
            +
                Enabled: true
         
     | 
| 
      
 35 
     | 
    
         
            +
              Words:
         
     | 
| 
      
 36 
     | 
    
         
            +
                Enabled: true
         
     | 
    
        data/exe/i18n_linter
    ADDED
    
    | 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'i18n_linter'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'i18n_linter/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'i18n_linter/runner'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'i18n_linter/options'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'i18n_linter/config'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Version = I18nLinter::VERSION
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            config = I18nLinter::Config.new
         
     | 
| 
      
 13 
     | 
    
         
            +
            options = I18nLinter::Options.new(config)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            opt = OptionParser.new
         
     | 
| 
      
 16 
     | 
    
         
            +
            opt.banner = 'Usage: i18n_linter'
         
     | 
| 
      
 17 
     | 
    
         
            +
            opt.on('-f PATTERN', '--files=PATTERN', "Pattern to find files, default: -f '**/*.rb'") do |pattern|
         
     | 
| 
      
 18 
     | 
    
         
            +
              options.files = [pattern]
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
      
 20 
     | 
    
         
            +
            opt.on('-o FILE', '--out=FILE', 'Write output to a file instead of STDOUT') do |file|
         
     | 
| 
      
 21 
     | 
    
         
            +
              options.out_file = file
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            opt.parse!
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            runner = I18nLinter::Runner.new(options, config)
         
     | 
| 
      
 27 
     | 
    
         
            +
            ret = runner.run
         
     | 
| 
      
 28 
     | 
    
         
            +
            exit(ret)
         
     | 
| 
         @@ -0,0 +1,75 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Config
         
     | 
| 
      
 7 
     | 
    
         
            +
                DOTFILE = '.i18n_linter.yml'
         
     | 
| 
      
 8 
     | 
    
         
            +
                I18N_LINTER_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
         
     | 
| 
      
 9 
     | 
    
         
            +
                DEFAULT_FILE = File.join(I18N_LINTER_HOME, 'config', 'default.yml')
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 12 
     | 
    
         
            +
                  path = File.exist?(DOTFILE) ? DOTFILE : DEFAULT_FILE
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @hash = load_yaml_configuration(path)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  add_missing_rules(@hash['Rules'])
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def patterns_to_include
         
     | 
| 
      
 18 
     | 
    
         
            +
                  linter_patterns['Include'] || []
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def patterns_to_exclude
         
     | 
| 
      
 22 
     | 
    
         
            +
                  linter_patterns['Exclude'] || []
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def enabled_positive_rules
         
     | 
| 
      
 26 
     | 
    
         
            +
                  all_rules.keys.select { |rule| positive_rule?(rule) && enabled_rule?(rule) }
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def enabled_negative_rules
         
     | 
| 
      
 30 
     | 
    
         
            +
                  all_rules.keys.select { |rule| negative_rule?(rule) && enabled_rule?(rule) }
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                private
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def [](key)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @hash[key]
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def linter_patterns
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @linter_patterns ||= self['Linter'] || {}
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def all_rules
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @all_rules ||= self['Rules'] || {}
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def enabled_rule?(rule)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  all_rules[rule]['Enabled']
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def positive_rule?(rule)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  Rules::POSITIVE_RULES.include?(rule)
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def negative_rule?(rule)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  Rules::NEGATIVE_RULES.include?(rule)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def load_yaml_configuration(path)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  yaml_code = File.read(path)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  hash = YAML.safe_load(yaml_code, [Regexp, Symbol], [], false, path) || {}
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  raise(TypeError, "Malformed configuration in #{path}") unless hash.is_a?(Hash)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  hash
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def add_missing_rules(loaded_rules)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  missing = (Rules::POSITIVE_RULES + Rules::NEGATIVE_RULES) - loaded_rules.keys
         
     | 
| 
      
 70 
     | 
    
         
            +
                  missing.each do |rule|
         
     | 
| 
      
 71 
     | 
    
         
            +
                    loaded_rules.store(rule, 'Enabled' => true)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Constants
         
     | 
| 
      
 5 
     | 
    
         
            +
                HTTP_HEADERS = %w[
         
     | 
| 
      
 6 
     | 
    
         
            +
                  Accept
         
     | 
| 
      
 7 
     | 
    
         
            +
                  Accept-Charset
         
     | 
| 
      
 8 
     | 
    
         
            +
                  Accept-Encoding
         
     | 
| 
      
 9 
     | 
    
         
            +
                  Accept-Language
         
     | 
| 
      
 10 
     | 
    
         
            +
                  Accept-Ranges
         
     | 
| 
      
 11 
     | 
    
         
            +
                  Access-Control-Allow-Credentials
         
     | 
| 
      
 12 
     | 
    
         
            +
                  Access-Control-Allow-Headers
         
     | 
| 
      
 13 
     | 
    
         
            +
                  Access-Control-Allow-Methods
         
     | 
| 
      
 14 
     | 
    
         
            +
                  Access-Control-Allow-Origin
         
     | 
| 
      
 15 
     | 
    
         
            +
                  Access-Control-Expose-Headers
         
     | 
| 
      
 16 
     | 
    
         
            +
                  Access-Control-Max-Age
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Access-Control-Request-Headers
         
     | 
| 
      
 18 
     | 
    
         
            +
                  Access-Control-Request-Method
         
     | 
| 
      
 19 
     | 
    
         
            +
                  Age
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Allow
         
     | 
| 
      
 21 
     | 
    
         
            +
                  Alt-Svc
         
     | 
| 
      
 22 
     | 
    
         
            +
                  Authorization
         
     | 
| 
      
 23 
     | 
    
         
            +
                  Cache-Control
         
     | 
| 
      
 24 
     | 
    
         
            +
                  Clear-Site-Data
         
     | 
| 
      
 25 
     | 
    
         
            +
                  Connection
         
     | 
| 
      
 26 
     | 
    
         
            +
                  Content-Disposition
         
     | 
| 
      
 27 
     | 
    
         
            +
                  Content-Encoding
         
     | 
| 
      
 28 
     | 
    
         
            +
                  Content-Language
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Content-Length
         
     | 
| 
      
 30 
     | 
    
         
            +
                  Content-Location
         
     | 
| 
      
 31 
     | 
    
         
            +
                  Content-Range
         
     | 
| 
      
 32 
     | 
    
         
            +
                  Content-Security-Policy
         
     | 
| 
      
 33 
     | 
    
         
            +
                  Content-Security-Policy-Report-Only
         
     | 
| 
      
 34 
     | 
    
         
            +
                  Content-Type
         
     | 
| 
      
 35 
     | 
    
         
            +
                  Cookie
         
     | 
| 
      
 36 
     | 
    
         
            +
                  Cookie2
         
     | 
| 
      
 37 
     | 
    
         
            +
                  DNT
         
     | 
| 
      
 38 
     | 
    
         
            +
                  Date
         
     | 
| 
      
 39 
     | 
    
         
            +
                  ETag
         
     | 
| 
      
 40 
     | 
    
         
            +
                  Early-Data
         
     | 
| 
      
 41 
     | 
    
         
            +
                  Expect
         
     | 
| 
      
 42 
     | 
    
         
            +
                  Expect-CT
         
     | 
| 
      
 43 
     | 
    
         
            +
                  Expires
         
     | 
| 
      
 44 
     | 
    
         
            +
                  Feature-Policy
         
     | 
| 
      
 45 
     | 
    
         
            +
                  Forwarded
         
     | 
| 
      
 46 
     | 
    
         
            +
                  From
         
     | 
| 
      
 47 
     | 
    
         
            +
                  Host
         
     | 
| 
      
 48 
     | 
    
         
            +
                  If-Match
         
     | 
| 
      
 49 
     | 
    
         
            +
                  If-Modified-Since
         
     | 
| 
      
 50 
     | 
    
         
            +
                  If-None-Match
         
     | 
| 
      
 51 
     | 
    
         
            +
                  If-Range
         
     | 
| 
      
 52 
     | 
    
         
            +
                  If-Unmodified-Since
         
     | 
| 
      
 53 
     | 
    
         
            +
                  Index
         
     | 
| 
      
 54 
     | 
    
         
            +
                  Keep-Alive
         
     | 
| 
      
 55 
     | 
    
         
            +
                  Large-Allocation
         
     | 
| 
      
 56 
     | 
    
         
            +
                  Last-Modified
         
     | 
| 
      
 57 
     | 
    
         
            +
                  Location
         
     | 
| 
      
 58 
     | 
    
         
            +
                  Origin
         
     | 
| 
      
 59 
     | 
    
         
            +
                  Pragma
         
     | 
| 
      
 60 
     | 
    
         
            +
                  Proxy-Authenticate
         
     | 
| 
      
 61 
     | 
    
         
            +
                  Proxy-Authorization
         
     | 
| 
      
 62 
     | 
    
         
            +
                  Public-Key-Pins
         
     | 
| 
      
 63 
     | 
    
         
            +
                  Public-Key-Pins-Report-Only
         
     | 
| 
      
 64 
     | 
    
         
            +
                  Range
         
     | 
| 
      
 65 
     | 
    
         
            +
                  Referer
         
     | 
| 
      
 66 
     | 
    
         
            +
                  Referrer-Policy
         
     | 
| 
      
 67 
     | 
    
         
            +
                  Retry-After
         
     | 
| 
      
 68 
     | 
    
         
            +
                  Sec-WebSocket-Accept
         
     | 
| 
      
 69 
     | 
    
         
            +
                  Server
         
     | 
| 
      
 70 
     | 
    
         
            +
                  Server-Timing
         
     | 
| 
      
 71 
     | 
    
         
            +
                  Set-Cookie
         
     | 
| 
      
 72 
     | 
    
         
            +
                  Set-Cookie2
         
     | 
| 
      
 73 
     | 
    
         
            +
                  SourceMap
         
     | 
| 
      
 74 
     | 
    
         
            +
                  Strict-Transport-Security
         
     | 
| 
      
 75 
     | 
    
         
            +
                  TE
         
     | 
| 
      
 76 
     | 
    
         
            +
                  Timing-Allow-Origin
         
     | 
| 
      
 77 
     | 
    
         
            +
                  Tk
         
     | 
| 
      
 78 
     | 
    
         
            +
                  Trailer
         
     | 
| 
      
 79 
     | 
    
         
            +
                  Transfer-Encoding
         
     | 
| 
      
 80 
     | 
    
         
            +
                  Upgrade-Insecure-Requests
         
     | 
| 
      
 81 
     | 
    
         
            +
                  User-Agent
         
     | 
| 
      
 82 
     | 
    
         
            +
                  Vary
         
     | 
| 
      
 83 
     | 
    
         
            +
                  Via
         
     | 
| 
      
 84 
     | 
    
         
            +
                  WWW-Authenticate
         
     | 
| 
      
 85 
     | 
    
         
            +
                  Warning
         
     | 
| 
      
 86 
     | 
    
         
            +
                  X-Content-Type-Options
         
     | 
| 
      
 87 
     | 
    
         
            +
                  X-DNS-Prefetch-Control
         
     | 
| 
      
 88 
     | 
    
         
            +
                  X-Forwarded-For
         
     | 
| 
      
 89 
     | 
    
         
            +
                  X-Forwarded-Host
         
     | 
| 
      
 90 
     | 
    
         
            +
                  X-Forwarded-Proto
         
     | 
| 
      
 91 
     | 
    
         
            +
                  X-Frame-Options
         
     | 
| 
      
 92 
     | 
    
         
            +
                  X-XSS-Protection
         
     | 
| 
      
 93 
     | 
    
         
            +
                ].freeze
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                QUERY_METHODS = %w[
         
     | 
| 
      
 96 
     | 
    
         
            +
                  annotate find find_by create_with distinct eager_load extending extract_associated from group
         
     | 
| 
      
 97 
     | 
    
         
            +
                  having includes joins left_outer_joins limit lock none offset optimizer_hints order
         
     | 
| 
      
 98 
     | 
    
         
            +
                  preload readonly references reorder reselect reverse_order select where
         
     | 
| 
      
 99 
     | 
    
         
            +
                ].freeze
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,31 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Digger
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(type)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @type = type
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def find(targets, tree)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  return false unless tree.is_a? Array
         
     | 
| 
      
 11 
     | 
    
         
            +
                  return true if target_found?(targets, tree)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  tree.each do |item|
         
     | 
| 
      
 14 
     | 
    
         
            +
                    return true if find(targets, item)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  false
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def target_found?(targets, tree)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  matches_type?(tree[0]) && matches_target?(tree[1], targets)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def matches_type?(item)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  item == @type
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def matches_target?(item, targets)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  targets.include?(item)
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,112 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'i18n_linter'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'colorize'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Linter
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(options, config)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @config = config
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @strings = []
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def lint(filename:, file:)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  parsed_file = tokenize_file(filename, file)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  find_strings(filename, parsed_file)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  compile(filename)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def show_errors(results)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 22 
     | 
    
         
            +
                  results.each do |result|
         
     | 
| 
      
 23 
     | 
    
         
            +
                    file = File.readlines(result.filename)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    line = result.line
         
     | 
| 
      
 25 
     | 
    
         
            +
                    print_block(result, file, line)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                private
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def tokenize_file(filename, file)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  Ripper.sexp(file, filename)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def get_token(file, index)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  file[index]
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def get_string_array(file, current_index)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  rest_of_file(file, current_index).take_while { |token|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    !%i[on_tstring_end on_label_end].include?(token.type)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  }.map(&:content)
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def rest_of_file(file, current_index)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  file.last(file.length - current_index)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def find_strings(filename, tokens)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  return unless array?(tokens)
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  if array?(tokens[0])
         
     | 
| 
      
 54 
     | 
    
         
            +
                    tokens.each { |child| find_strings(filename, child) }
         
     | 
| 
      
 55 
     | 
    
         
            +
                  else
         
     | 
| 
      
 56 
     | 
    
         
            +
                    check_rules(filename, tokens)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                def check_rules(filename, tokens)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  if string_element?(tokens)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    string = tokens[1]
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @strings << StringLine.new(tokens[2], string) if Rules.check_string_rules(@config, string)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  else
         
     | 
| 
      
 65 
     | 
    
         
            +
                    test_rules(filename, tokens)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def array?(elem)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  elem.class == Array
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def string_element?(elem)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  elem[0] == :@tstring_content
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def compile(filename)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  result_set = ResultSet.new
         
     | 
| 
      
 79 
     | 
    
         
            +
                  @strings.each do |string_line|
         
     | 
| 
      
 80 
     | 
    
         
            +
                    result_set.add_result(Result.new(filename, string_line, string_line.string))
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                  @strings = []
         
     | 
| 
      
 83 
     | 
    
         
            +
                  result_set
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def test_rules(filename, tokens)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  return if tokens.empty? || Rules.check_negative_rules(@config, tokens)
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  check_rest_of_tokens(filename, tokens)
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def check_rest_of_tokens(filename, tokens)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  tokens[1..-1].each { |child| find_strings(filename, child) }
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                def print_block(result, file, line)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  line_number = line.line_number
         
     | 
| 
      
 98 
     | 
    
         
            +
                  column_number = line.column_number
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  previous_line = file[line_number - 2] if line_number > 2
         
     | 
| 
      
 101 
     | 
    
         
            +
                  current_line = file[line_number - 1]
         
     | 
| 
      
 102 
     | 
    
         
            +
                  next_line = file[line_number] if line_number < file.length
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  output = "#{result.filename}:#{line_number}:#{column_number}\n".colorize(:green)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  output += "#{line_number - 1}:  #{previous_line}" if previous_line
         
     | 
| 
      
 106 
     | 
    
         
            +
                  output += "#{line_number}:  #{current_line}".colorize(:yellow)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  output += "#{line_number + 1}:  #{next_line}" if next_line
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  puts output
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Options
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_writer :files
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_accessor :out_file
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(config)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @config = config
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def files
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return Dir[*@files].uniq.sort if @files
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  supported_files.sort
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                private
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def supported_files
         
     | 
| 
      
 21 
     | 
    
         
            +
                  (Dir.glob(@config.patterns_to_include, 0) - Dir.glob(@config.patterns_to_exclude, 0)).uniq
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Result
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :filename
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :line
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :string
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(filename, line, string)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @filename = filename
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @line = line
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @string = string
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              class ResultSet
         
     | 
| 
      
 5 
     | 
    
         
            +
                include Enumerable
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @results = []
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def add_result(result)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @results << result
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def each
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @results.each do |result|
         
     | 
| 
      
 17 
     | 
    
         
            +
                    yield result
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def success?
         
     | 
| 
      
 22 
     | 
    
         
            +
                  count.zero?
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class ClassName
         
     | 
| 
      
 6 
     | 
    
         
            +
                  CLASS_NAME_LABEL = 'class_name:'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    tokens[0] == :assoc_new &&
         
     | 
| 
      
 10 
     | 
    
         
            +
                      I18nLinter::Digger.new(:@label).find([CLASS_NAME_LABEL], tokens[1])
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Constant
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    tokens[0] == :assign && constant_assign(tokens)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  private
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def constant_assign(tokens)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    assign_tokens = tokens[1]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    assign_tokens[0] == :var_field && assign_tokens[1][0] == :@const
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class EnvironmentVariable
         
     | 
| 
      
 6 
     | 
    
         
            +
                  ENV_CONST = 'ENV'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    reference_or_method(tokens) && I18nLinter::Digger.new(:@const).find([ENV_CONST], tokens[1])
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def reference_or_method(tokens)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    %i[aref method_add_arg].include?(tokens[0])
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class HttpHeaders
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    tokens[0] == :assoc_new && literal_or_symbol(tokens)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  private
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def literal_or_symbol(tokens)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    literal_symbol_tokens = tokens[1]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    (literal(literal_symbol_tokens) || symbol(literal_symbol_tokens)) &&
         
     | 
| 
      
 15 
     | 
    
         
            +
                      string_content(literal_symbol_tokens)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def literal(tokens)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    tokens[0] == :string_literal
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def symbol(tokens)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    tokens[0] == :dyna_symbol
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def string_content(tokens)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    content_tokens = tokens[1]
         
     | 
| 
      
 28 
     | 
    
         
            +
                    content_tokens[0] == :string_content && header_string(content_tokens)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def header_string(tokens)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    header_tokens = tokens[1]
         
     | 
| 
      
 33 
     | 
    
         
            +
                    header_tokens[0] == :@tstring_content && http_header(header_tokens)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def http_header(tokens)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    string = tokens[1].downcase
         
     | 
| 
      
 38 
     | 
    
         
            +
                    I18nLinter::Constants::HTTP_HEADERS.map(&:downcase).any? do |header|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      string.include?(header)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Logger
         
     | 
| 
      
 6 
     | 
    
         
            +
                  LOGGER_IDENT = 'logger'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    command_or_method(tokens) && I18nLinter::Digger.new(:@ident).find([LOGGER_IDENT], tokens[1])
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def command_or_method(tokens)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    %i[command_call method_add_block method_add_arg].include?(tokens[0])
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'mime/types'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 7 
     | 
    
         
            +
                class MimeType
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    tokens[0] == :string_content && mime_type?(tokens)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def mime_type?(tokens)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    string_tokens = tokens[1]
         
     | 
| 
      
 16 
     | 
    
         
            +
                    return false unless string_tokens
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    string_tokens[0] == :@tstring_content && check_mime_types(string_tokens)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def check_mime_types(tokens)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    string = tokens[1]
         
     | 
| 
      
 23 
     | 
    
         
            +
                    MIME::Types.any? { |mime| string.include?(mime) }
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Puts
         
     | 
| 
      
 6 
     | 
    
         
            +
                  PUTS_IDENT = 'puts'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    command_or_method(tokens) && I18nLinter::Digger.new(:@ident).find([PUTS_IDENT], tokens[1])
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  private
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def command_or_method(tokens)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    %i[command method_add_arg].include?(tokens[0])
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Strftime
         
     | 
| 
      
 6 
     | 
    
         
            +
                  STRFTIME_IDENT = 'strftime'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    tokens[0] == :method_add_arg &&
         
     | 
| 
      
 10 
     | 
    
         
            +
                      I18nLinter::Digger.new(:@ident).find([STRFTIME_IDENT], tokens[1])
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Underscore
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def check(tokens)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    tokens[0] == :string_content && underscore?(tokens)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  private
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def underscore?(tokens)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    string_tokens = tokens[1]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    return false unless string_tokens
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    string_tokens[0] == :@tstring_content && /\_/ =~ string_tokens[1]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Rules
         
     | 
| 
      
 5 
     | 
    
         
            +
                POSITIVE_RULES = %w[MiddleSpace Words].freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
                # Rules that filter the strings found
         
     | 
| 
      
 7 
     | 
    
         
            +
                NEGATIVE_RULES = %w[
         
     | 
| 
      
 8 
     | 
    
         
            +
                  ClassName Constant EnvironmentVariable HttpHeaders
         
     | 
| 
      
 9 
     | 
    
         
            +
                  Logger MimeType Puts Query RegExp Scope Strftime Underscore
         
     | 
| 
      
 10 
     | 
    
         
            +
                ].freeze
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def check_rule(rule, string_or_tokens)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    Kernel.const_get("I18nLinter::Rules::#{rule}").new.check(string_or_tokens)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def check_positive_rules(config, string)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    config.enabled_positive_rules.any? { |rule| Rules.check_rule(rule, string) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def check_negative_rules(config, tokens)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    config.enabled_negative_rules.any? { |rule| Rules.check_rule(rule, tokens) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def check_string_rules(config, string)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    check_positive_rules(config, string)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'i18n_linter/linter'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'i18n_linter/options'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'i18n_linter/config'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 8 
     | 
    
         
            +
              class Runner
         
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(options, config)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @linter = I18nLinter.linter.new(options, config)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def run
         
     | 
| 
      
 15 
     | 
    
         
            +
                  $stdout = StringIO.new
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  result = @options.files.map { |file|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    lint_result = lint(file)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    if lint_result.success?
         
     | 
| 
      
 20 
     | 
    
         
            +
                      true
         
     | 
| 
      
 21 
     | 
    
         
            +
                    else
         
     | 
| 
      
 22 
     | 
    
         
            +
                      @linter.show_errors(lint_result)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      false
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  }.all?
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  handle_results
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  $stdout = STDOUT
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  result
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                private
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def handle_results
         
     | 
| 
      
 37 
     | 
    
         
            +
                  output_file = @options.out_file
         
     | 
| 
      
 38 
     | 
    
         
            +
                  output = $stdout.string
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  if output_file
         
     | 
| 
      
 41 
     | 
    
         
            +
                    File.open(output_file, 'w') do |file|
         
     | 
| 
      
 42 
     | 
    
         
            +
                      file.write output
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  else
         
     | 
| 
      
 45 
     | 
    
         
            +
                    STDOUT.puts output
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def lint(filename)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  file = File.read(filename)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @linter.lint(filename: filename, file: file)
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 4 
     | 
    
         
            +
              class StringLine
         
     | 
| 
      
 5 
     | 
    
         
            +
                attr_reader :line_number
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :column_number
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :string
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def initialize(coords, string)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @line_number = coords[0]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @column_number = coords[1]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @string = string
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/i18n_linter.rb
    ADDED
    
    | 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'i18n_linter/linter'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'i18n_linter/rules'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'i18n_linter/rules/middle_space'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'i18n_linter/rules/words'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'i18n_linter/rules/environment_variable'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'i18n_linter/rules/class_name'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'i18n_linter/rules/constant'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'i18n_linter/rules/logger'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'i18n_linter/rules/puts'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'i18n_linter/rules/scope'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'i18n_linter/rules/strftime'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'i18n_linter/rules/http_headers'
         
     | 
| 
      
 16 
     | 
    
         
            +
            require 'i18n_linter/rules/underscore'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 'i18n_linter/rules/reg_exp'
         
     | 
| 
      
 18 
     | 
    
         
            +
            require 'i18n_linter/rules/query'
         
     | 
| 
      
 19 
     | 
    
         
            +
            require 'i18n_linter/rules/mime_type'
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            require 'i18n_linter/helpers/digger'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require 'i18n_linter/options'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require 'i18n_linter/constants'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 'i18n_linter/result'
         
     | 
| 
      
 25 
     | 
    
         
            +
            require 'i18n_linter/token'
         
     | 
| 
      
 26 
     | 
    
         
            +
            require 'i18n_linter/result_set'
         
     | 
| 
      
 27 
     | 
    
         
            +
            require 'i18n_linter/string_line'
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            require 'ripper'
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            module I18nLinter
         
     | 
| 
      
 32 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 33 
     | 
    
         
            +
                def linter
         
     | 
| 
      
 34 
     | 
    
         
            +
                  ::I18nLinter::Linter
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,143 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: i18n_linter
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Franco Pariani
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-10-04 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: colorize
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: 0.8.1
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: 0.8.1
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: reek
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '5.2'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '5.2'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '3.8'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '3.8'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: rubocop
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: 0.59.2
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: 0.59.2
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: simplecov
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: 0.13.0
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: 0.13.0
         
     | 
| 
      
 83 
     | 
    
         
            +
            description: i18n linter plugin
         
     | 
| 
      
 84 
     | 
    
         
            +
            email: franco@rootstrap.com
         
     | 
| 
      
 85 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 86 
     | 
    
         
            +
            - i18n_linter
         
     | 
| 
      
 87 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 88 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 89 
     | 
    
         
            +
            files:
         
     | 
| 
      
 90 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 91 
     | 
    
         
            +
            - config/default.yml
         
     | 
| 
      
 92 
     | 
    
         
            +
            - exe/i18n_linter
         
     | 
| 
      
 93 
     | 
    
         
            +
            - lib/i18n_linter.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - lib/i18n_linter/config.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - lib/i18n_linter/constants.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - lib/i18n_linter/helpers/digger.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - lib/i18n_linter/linter.rb
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib/i18n_linter/options.rb
         
     | 
| 
      
 99 
     | 
    
         
            +
            - lib/i18n_linter/result.rb
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib/i18n_linter/result_set.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib/i18n_linter/rules.rb
         
     | 
| 
      
 102 
     | 
    
         
            +
            - lib/i18n_linter/rules/class_name.rb
         
     | 
| 
      
 103 
     | 
    
         
            +
            - lib/i18n_linter/rules/constant.rb
         
     | 
| 
      
 104 
     | 
    
         
            +
            - lib/i18n_linter/rules/environment_variable.rb
         
     | 
| 
      
 105 
     | 
    
         
            +
            - lib/i18n_linter/rules/http_headers.rb
         
     | 
| 
      
 106 
     | 
    
         
            +
            - lib/i18n_linter/rules/logger.rb
         
     | 
| 
      
 107 
     | 
    
         
            +
            - lib/i18n_linter/rules/middle_space.rb
         
     | 
| 
      
 108 
     | 
    
         
            +
            - lib/i18n_linter/rules/mime_type.rb
         
     | 
| 
      
 109 
     | 
    
         
            +
            - lib/i18n_linter/rules/puts.rb
         
     | 
| 
      
 110 
     | 
    
         
            +
            - lib/i18n_linter/rules/query.rb
         
     | 
| 
      
 111 
     | 
    
         
            +
            - lib/i18n_linter/rules/reg_exp.rb
         
     | 
| 
      
 112 
     | 
    
         
            +
            - lib/i18n_linter/rules/scope.rb
         
     | 
| 
      
 113 
     | 
    
         
            +
            - lib/i18n_linter/rules/strftime.rb
         
     | 
| 
      
 114 
     | 
    
         
            +
            - lib/i18n_linter/rules/underscore.rb
         
     | 
| 
      
 115 
     | 
    
         
            +
            - lib/i18n_linter/rules/words.rb
         
     | 
| 
      
 116 
     | 
    
         
            +
            - lib/i18n_linter/runner.rb
         
     | 
| 
      
 117 
     | 
    
         
            +
            - lib/i18n_linter/string_line.rb
         
     | 
| 
      
 118 
     | 
    
         
            +
            - lib/i18n_linter/token.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - lib/i18n_linter/version.rb
         
     | 
| 
      
 120 
     | 
    
         
            +
            homepage: http://rubygems.org/gems/i18n_linter
         
     | 
| 
      
 121 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 122 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 123 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 124 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 125 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 126 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 127 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 128 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 129 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 130 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 131 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 132 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 133 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 134 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 135 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 136 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 137 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 138 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 139 
     | 
    
         
            +
            rubygems_version: 3.0.4
         
     | 
| 
      
 140 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 141 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 142 
     | 
    
         
            +
            summary: i18n linter plugin
         
     | 
| 
      
 143 
     | 
    
         
            +
            test_files: []
         
     |