Skip to content

Commit 4ce004d

Browse files
committed
Add new Rails/I18nLocaleTexts cop
1 parent 2f3cb4c commit 4ce004d

File tree

5 files changed

+179
-0
lines changed

5 files changed

+179
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#624](https://github.com/rubocop/rubocop-rails/issues/624): Add new `Rails/I18nLocaleTexts` cop. ([@fatkodima][])

config/default.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,12 @@ Rails/I18nLocaleAssignment:
455455
- spec/**/*.rb
456456
- test/**/*.rb
457457

458+
Rails/I18nLocaleTexts:
459+
Description: 'Enforces use of I18n and locale files instead of locale specific strings.'
460+
StyleGuide: 'https://rails.rubystyle.guide/#locale-texts'
461+
Enabled: pending
462+
VersionAdded: '<<next>>'
463+
458464
Rails/IgnoredSkipActionFilterOption:
459465
Description: 'Checks that `if` and `only` (or `except`) are not used together as options of `skip_*` action filter.'
460466
Reference: 'https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options'
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
module Rails
6+
# Enforces use of I18n and locale files instead of locale specific strings.
7+
#
8+
# @example
9+
# # bad
10+
# class User < ApplicationRecord
11+
# validates :email, presence: { message: "must be present" }
12+
# end
13+
#
14+
# # good
15+
# # config/locales/en.yml
16+
# # en:
17+
# # activerecord:
18+
# # errors:
19+
# # models:
20+
# # user:
21+
# # blank: "must be present"
22+
#
23+
# class User < ApplicationRecord
24+
# validates :email, presence: true
25+
# end
26+
#
27+
# # bad
28+
# class PostsController < ApplicationController
29+
# def create
30+
# # ...
31+
# redirect_to root_path, notice: "Post created!"
32+
# end
33+
# end
34+
#
35+
# # good
36+
# # config/locales/en.yml
37+
# # en:
38+
# # posts:
39+
# # create:
40+
# # success: "Post created!"
41+
#
42+
# class PostsController < ApplicationController
43+
# def create
44+
# # ...
45+
# redirect_to root_path, notice: t(".success")
46+
# end
47+
# end
48+
#
49+
# # bad
50+
# class UserMailer < ApplicationMailer
51+
# def welcome(user)
52+
# mail(to: user.email, subject: "Welcome to My Awesome Site")
53+
# end
54+
# end
55+
#
56+
# # good
57+
# # config/locales/en.yml
58+
# # en:
59+
# # user_mailer:
60+
# # welcome:
61+
# # subject: "Welcome to My Awesome Site"
62+
#
63+
# class UserMailer < ApplicationMailer
64+
# def welcome(user)
65+
# mail(to: user.email)
66+
# end
67+
# end
68+
#
69+
class I18nLocaleTexts < Base
70+
MSG = 'Move locale texts to the locale files in the `config/locales` directory.'
71+
72+
RESTRICT_ON_SEND = %i[validates redirect_to []= mail].freeze
73+
74+
def_node_search :validation_message, <<~PATTERN
75+
(pair (sym :message) $str)
76+
PATTERN
77+
78+
def_node_search :redirect_to_flash, <<~PATTERN
79+
(pair (sym {:notice :alert}) $str)
80+
PATTERN
81+
82+
def_node_matcher :flash_assignment?, <<~PATTERN
83+
(send (send nil? :flash) :[]= _ $str)
84+
PATTERN
85+
86+
def_node_search :mail_subject, <<~PATTERN
87+
(pair (sym :subject) $str)
88+
PATTERN
89+
90+
def on_send(node)
91+
case node.method_name
92+
when :validates
93+
validation_message(node) do |text_node|
94+
add_offense(text_node)
95+
end
96+
return
97+
when :redirect_to
98+
text_node = redirect_to_flash(node).to_a.last
99+
when :[]=
100+
text_node = flash_assignment?(node)
101+
when :mail
102+
text_node = mail_subject(node).to_a.last
103+
end
104+
105+
add_offense(text_node) if text_node
106+
end
107+
end
108+
end
109+
end
110+
end

lib/rubocop/cop/rails_cops.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
require_relative 'rails/http_status'
5656
require_relative 'rails/i18n_lazy_lookup'
5757
require_relative 'rails/i18n_locale_assignment'
58+
require_relative 'rails/i18n_locale_texts'
5859
require_relative 'rails/ignored_skip_action_filter_option'
5960
require_relative 'rails/index_by'
6061
require_relative 'rails/index_with'
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe RuboCop::Cop::Rails::I18nLocaleTexts, :config do
4+
it 'registers an offense when using `validates` with text messages' do
5+
expect_offense(<<~RUBY)
6+
validates :email, presence: { message: "must be present" },
7+
^^^^^^^^^^^^^^^^^ Move locale texts to the locale files in the `config/locales` directory.
8+
format: { with: /@/, message: "not an email" },
9+
^^^^^^^^^^^^^^ Move locale texts to the locale files in the `config/locales` directory.
10+
length: { maximum: 64 }
11+
RUBY
12+
end
13+
14+
it 'does not register an offense when using `validates` with localized messages' do
15+
expect_no_offenses(<<~RUBY)
16+
validates :email, presence: { message: :email_missing },
17+
format: { with: /@/, message: I18n.t('email_format') },
18+
length: { maximum: 64 }
19+
RUBY
20+
end
21+
22+
it 'registers an offense when using `redirect_to` with text flash messages' do
23+
expect_offense(<<~RUBY)
24+
redirect_to root_path, notice: "Post created!"
25+
^^^^^^^^^^^^^^^ Move locale texts to the locale files in the `config/locales` directory.
26+
RUBY
27+
end
28+
29+
it 'does not register an offense when using `redirect_to` with localized flash messages' do
30+
expect_no_offenses(<<~RUBY)
31+
redirect_to root_path, notice: t(".success")
32+
RUBY
33+
end
34+
35+
it 'registers an offense when assigning to `flash` text messages' do
36+
expect_offense(<<~RUBY)
37+
flash[:notice] = "Post created!"
38+
^^^^^^^^^^^^^^^ Move locale texts to the locale files in the `config/locales` directory.
39+
RUBY
40+
end
41+
42+
it 'does not register an offense when assigning to `flash` localized messages' do
43+
expect_no_offenses(<<~RUBY)
44+
flash[:notice] = t(".success")
45+
RUBY
46+
end
47+
48+
it 'registers an offense when using `mail` with text subject' do
49+
expect_offense(<<~RUBY)
50+
mail(to: user.email, subject: "Welcome to My Awesome Site")
51+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Move locale texts to the locale files in the `config/locales` directory.
52+
RUBY
53+
end
54+
55+
it 'does not register an offense when using `mail` with localized subject' do
56+
expect_no_offenses(<<~RUBY)
57+
mail(to: user.email)
58+
mail(to: user.email, subject: t("mailers.users.welcome"))
59+
RUBY
60+
end
61+
end

0 commit comments

Comments
 (0)