Git Product home page Git Product logo

rubocop-i18n's Introduction

Rubocop::I18n

Build Status

A set of cops for detecting strings that need i18n decoration in your project.

Supports the following framework styles:

  • gettext
  • rails-i18n

Installation

Add this line to your application's Gemfile:

gem 'rubocop-i18n'

And then execute:

$ bundle

Or install it yourself as:

$ gem install rubocop-i18n

Usage

In your rubocop.yml:

require:
 - rubocop-i18n
...
# You *must* choose GetText or Rails-i18n style checking
# If you want GetText-style checking
I18n/GetText:
  Enabled: true
I18n/RailsI18n:
  Enabled: false
# If you want rails-i18n-style checking
I18n/RailsI18n:
  Enabled: true
I18n/GetText:
  Enabled: false
# If you want custom control of all the cops
I18n/GetText/DecorateString:
  Enabled: false
  # Disable the autocorrect
  AutoCorrect: false
I18n/GetText/DecorateFunctionMessage:
  Enabled: false
I18n/GetText/DecorateStringFormattingUsingInterpolation:
  Enabled: false
I18n/GetText/DecorateStringFormattingUsingPercent:
  Enabled: false
I18n/RailsI18n/DecorateString:
  Enabled: false

Cops

I18n/GetText/DecorateString

This cop is looks for strings that appear to be sentences but are not decorated. Sentences are determined by the STRING_REGEXP.

Error message thrown
decorator is missing around sentence
Bad
"Result is bad."
Good
_("Result is good.")
Ignored
"string"
"A string with out a punctuation at the end"
"a string that doesn't start with a capital letter."

I18n/GetText/DecorateFunctionMessage

This cop looks for any raise or fail functions and checks that the user visible message is using gettext decoration with the _() function. This cop makes sure the message is decorated, as well as checking that the formatting of the message is compliant according to the follow rules. This cop supports autocorrecting of Simple decoration of a message. See the rubocop documentation on how to run autocorrect.

Simple decoration of a message

Simple message strings should be decorated with the _() function

Error message thrown
'raise' function, message string should be decorated
Bad
raise("Warning")
Good
raise(_("Warning"))

Multi-line message

The message should not span multiple lines, it causes issues during the translation process.

Error message thrown
'raise' function, message should not be a multi-line string
Bad
raise("this is a multi" \
"line message")
Good
raise(_("this is a multi line message"))

Concatenated message

The message should not concatenate multiple strings, it causes issues during translation and with the gettext.

Error message thrown
'raise' function, message should not be a concatenated string
Bad
raise("this is a concatenated" + "message")
Good
raise(_("this is a concatenated message"))

Interpolated message

The message should be formated in this particular style. Otherwise it causes issues during translation and with the gettext gem.

Error message thrown
'raise' function, message should use correctly formatted interpolation
Bad
raise("this is an interpolated message IE #{variable}")
Good
raise(_("this is an interpolated message IE %{value0}") % {value0: var,})

No decoration and no string detected

The raise or fail function does not contain any decoration, or a simple string

Error message thrown
'raise' function, message should be decorated
Bad
raise(someOtherFuntioncall(foo, "bar"))
Good

In this raise or fail function, the message does not contain any decoration at all and the message is not a simple string. It may make sense to convert the message to a simple string. eg Simple decoration of a message. Or ignore this raise or fail function following this How to ignore rules in code section.

I18n/GetText/DecorateStringFormattingUsingInterpolation

This cop looks for decorated gettext methods _() and checks that all strings contained within do not use string interpolation '#{}'

Simple decoration of a message

Simple message strings should be decorated with the _() function

Error message thrown
'_' function, message string should not contain #{} formatting
Bad
puts _("a message with a #{'interpolation'}")
Good
puts _("a message that is %{type}") % { type: 'translatable' }

I18n/GetText/DecorateStringFormattingUsingPercent

This cop looks for decorated gettext methods _() and checks that all strings contained within do not use sprintf formatting '%s' etc

Error message thrown
'_' function, message string should not contain sprintf style formatting (ie %s)
Bad
raise(_("Warning is %s") % ['bad'])
Good
raise(_("Warning is %{value}") % { value: 'bad' })

I18n/RailsI18n/DecorateString

This cop looks for decorated rails-i18n methods.

Error message thrown
decorator is missing around sentence
Bad
raise("Warning is %s" % ['bad'])
Good
raise(t("Warning is %{value}") % { value: 'good' })
raise(translate("Warning is %{value}") % { value: 'good' })
raise(I18n.t("Warning is %{value}") % { value: 'good' })

I18n/RailsI18n/DecorateStringFormattingUsingInterpolation

This cop looks for decorated rails-i18n methods like t() and translate() and checks that all strings contained within do not use string interpolation '#{}'

Simple decoration of a message

Simple message strings should be decorated with the t() function

Error message thrown
't' function, message key string should not contain #{} formatting
Bad
puts t("path.to.key.with.#{'interpolation'}")
Good
puts t("path.to.key.with.interpolation")

How to ignore rules in code

It may be necessary to ignore a cop for a particular piece of code. We follow standard rubocop idioms.

raise("We don't want this translated.")                 # rubocop:disable I18n/GetText/DecorateString
raise("We don't want this translated.")                 # rubocop:disable I18n/RailsI18n/DecorateString
raise("We don't want this translated")                  # rubocop:disable I18n/GetText/DecorateFunctionMessage
raise(_("We don't want this translated #{crazy}")       # rubocop:disable I18n/GetText/DecorateStringFormattingUsingInterpolation)
raise(_("We don't want this translated %s") % ['crazy'] # rubocop:disable I18n/GetText/DecorateStringFormattingUsingPercent)

Known Issues

Rubocop currently does not detect Heredoc style messages in functions correctly, which in turn prevents this plugin from detecting them correctly. Not all sprintf formatting strings are detected.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that allows you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which creates a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/puppetlabs/rubocop-i18n. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

rubocop-i18n's People

Contributors

binford2k avatar choubacha avatar davids avatar dependabot-preview[bot] avatar e-gris avatar highb avatar ikapelyukhin avatar joshcooper avatar lucywyman avatar mvz avatar pcarlisle avatar pmcmaw avatar sfeuga avatar tphoney avatar unixmonkey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rubocop-i18n's Issues

Packaged gem releases have overly restrictive file modes

It appears that when the rubocop-i18n gem is being packaged, the file modes of several files in the gem are not world-readable:

root@h6s7vwieu5opjoe:/var/lib/gems/2.5.0/gems/rubocop-i18n-2.0.0# chmod --recursive --changes o+r .
mode of './Rakefile' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './bin/console' changed from 0770 (rwxrwx---) to 0774 (rwxrwxr--)
mode of './.rubocop_todo.yml' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './rubocop-i18n.gemspec' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './.travis.yml' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/rspec/cop_helper.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/rails_i18n.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/gettext.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/rails_i18n/decorate_string.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/gettext/decorate_string.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/gettext/decorate_string_formatting_using_percent.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/gettext/decorate_string_formatting_using_interpolation.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './lib/rubocop/cop/i18n/gettext/decorate_function_message.rb' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './.rubocop.yml' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './README.md' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './CHANGELOG.md' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)
mode of './.gitignore' changed from 0660 (rw-rw----) to 0664 (rw-rw-r--)

The files in lib/ are particularly problematic because if the gem is installed as root (for example, as part of installing the PDK package) then regular users cannot use the gem and receive LoadErrors at runtime.

It appears that rubygems will warn about this condition at gem build time, but it does not fail the build:

$ gem build rubocop-i18n
WARNING: license value 'Apache-2' is invalid. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
Did you mean 'Apache-2.0'?
WARNING: lib/rubocop/cop/i18n.rb is not world-readable
WARNING: open-ended dependency on pry (>= 0, development) is not recommended
use a bounded requirement, such as '~> x.y'
WARNING: open-ended dependency on rb-readline (>= 0, development) is not recommended
use a bounded requirement, such as '~> x.y'
WARNING: See http://guides.rubygems.org/specification-reference/ for help
Successfully built RubyGem
Name: rubocop-i18n
Version: 2.0.0
File: rubocop-i18n-2.0.0.gem

See also puppetlabs/pdk#697

Please split up DecorateFunctionMessage

Use Case

I'm adding checking with rubocop-i18n to an existing code base so there are a lot of offenses. I'd like to fix the low-hanging fruit first, e.g., multi-line strings, and then move on to the more complex work, e.g., eliminating interpolation. The DecorateFunctionMessage cop checks both of these things and more, so slicing up the work becomes harder.

Describe the Solution You Would Like

I'd like to be able to just run a cop that checks for multi-line strings, or interpolation, and also disable each functionality separately in the RuboCop configuration.

Describe Alternatives You've Considered

I'm using grep right now to allow me to only look at multi-line strings, but it feels like a hack and doesn't allow disabling in the RuboCop config.

Changes will be needed after rubocop gem hits 1.0 version

In rubocop gem version 1.0 there will be a breaking change (rubocop/rubocop#8490) that will affect rubocop-i18n. That PR with a breaking change has been already merged into master so that means version 1.0 is going to be released reasonably soon.

This is the description of the breaking change:

Change logic for cop department name computation. Cops inside deep namespaces (5 or more levels deep) now belong to departments with names that are calculated by joining module names starting from the third one with slashes as separators. For example, cop Rubocop::Cop::Foo::Bar::Baz now belongs to Foo/Bar department (previously it was Bar).

Due to this rubocop-i18n will need to update its documentation in README.md file to correctly address new department names. Basically the only thing to do is to add I18n/ before all the departments and cop names that would go in .rubocop.yml file. This is required because all the cops in this gem are "deep" (5 levels of nesting).

So instead of this:

GetText:
RailsI18n:
GetText/DecorateString:
GetText/DecorateFunctionMessage:
GetText/DecorateStringFormattingUsingInterpolation:
GetText/DecorateStringFormattingUsingPercent:
RailsI18n/DecorateString:
RailsI18n/DecorateStringFormattingUsingInterpolation:

it should be like this:

I18n/GetText:
I18n/RailsI18n:
I18n/GetText/DecorateString:
I18n/GetText/DecorateFunctionMessage:
I18n/GetText/DecorateStringFormattingUsingInterpolation:
I18n/GetText/DecorateStringFormattingUsingPercent:
I18n/RailsI18n/DecorateString:
I18n/RailsI18n/DecorateStringFormattingUsingInterpolation:

As far as I can see it's the only change due to that PR.

False positive on an SQL heredoc

The following code is triggering the RailsI18n/DecorateString cop. That doesn't seem like expected behavior, does it?

      sql = <<~SQL
        "#{table_name}"."id" IN (
          SELECT id
          FROM "#{table_name}",
               jsonb_to_recordset("#{table_name}"."tasks") AS tasks(due_on date)
          WHERE tasks.due_on >= ?
            AND tasks.due_on <= ?
        )
      SQL

Don't require translation for strings not used in the application (Rails I18n)

Is your feature request related to a problem? Please describe.
The sentences used exclusively in your test suite don't need translation, as they are neither user facing, nor integrate with Rails I18n afaik.

For example, the common guard clause in spec/rails_helper.rb:

# Prevent database truncation if the environment is production
if Rails.env.production?
  abort('The Rails environment is running in production mode!')
end

Raises a linting error:

spec/rails_helper.rb:7:9: C: I18n/RailsI18n/DecorateString: decorator is missing around sentence
  abort('The Rails environment is running in production mode!')

Describe the solution you'd like
DecorateString cop automatically ignores strings that should not be covered by I18n (e.g. test suite strings not used in the app itself.

Describe alternatives you've considered
Currently I exclude the entire spec folder from the cop using Exclude, however I'm worried that I may be losing linting functionality for strings in the test suite that should be translated. E.g. when testing error notification strings in system specs.

Additional Context

#54 is a similar issue, although specific to Ruby gems rather than Rails apps.

Exclude *.gemspec by default

Is your feature request related to a problem? Please describe.
When using this gem inside a Gem project, all text lines in the Gemspec file will be marked as missing a decorator.

Describe the solution you'd like
ANY gemspec file to be ignored by default

Describe alternatives you've considered
Manually adding a line to RuboCop's config file for every cop, or explicitly adding gemspec files to Global exclude sections

Additional context
Gemspecs should be as lean as possible, and I feel it better to have the Cops ignore these gemspecs by default, and not having to extend my configuration either globally for large projects/custom configurations or to list this lien for every Cop

auto-correct for I18n/RailsI18n/DecorateString

I wish it would auto-correct my code to add the surrounding call to I18n.t()

Describe the solution you'd like
I have yet to look at which other cop that does this already, but I have a feeling we could take example for another cop that does this kind of auto-correct

Describe alternatives you've considered
doing it by hand, after all, I only have a few thousand places to update.

Additional context
N/A

New Cop to disallow use of _() in constants.

Is your feature request related to a problem? Please describe.

It's not uncommon for new users of gettext to use _() in constants, not realize that will translate at first load and not on demand. This is easy to miss in code review.

Describe the solution you'd like

I'd like to see a Cop that checks for usage of _() in constants. Secondarily, if it's possible, it would useful to also detect memoized usage of _() in a class methods or global context.

Describe alternatives you've considered
Additional context

None

Add Documentation with how to trigger the rubocop error

Excuse me, I really appreciate your project, as I need a linter to enforce i18n translations in my views. But can you actually list how to trigger the Rubocop violations? I've installed your gem and added the necessary configuration to the .rubocop.yml added strings with no translations into my view files but it isn't tripping rubocop. Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.