forked from rubocop/rubocop-rails
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathi18n_lazy_lookup.rb
96 lines (79 loc) · 2.72 KB
/
i18n_lazy_lookup.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# frozen_string_literal: true
module RuboCop
module Cop
module Rails
# Checks for places where I18n "lazy" lookup can be used.
#
# @example
# # en.yml
# # en:
# # books:
# # create:
# # success: Book created!
#
# # bad
# class BooksController < ApplicationController
# def create
# # ...
# redirect_to books_url, notice: t('books.create.success')
# end
# end
#
# # good
# class BooksController < ApplicationController
# def create
# # ...
# redirect_to books_url, notice: t('.success')
# end
# end
#
class I18nLazyLookup < Base
include VisibilityHelp
extend AutoCorrector
MSG = 'Use "lazy" lookup for the text used in controllers.'
RESTRICT_ON_SEND = %i[translate t].freeze
def_node_matcher :translate_call?, <<~PATTERN
(send nil? {:translate :t} ${sym_type? str_type?} ...)
PATTERN
def on_send(node)
translate_call?(node) do |key_node|
key = key_node.value
return if key.to_s.start_with?('.')
controller, action = controller_and_action(node)
return unless controller && action
scoped_key = get_scoped_key(key_node, controller, action)
return unless key == scoped_key
add_offense(key_node) do |corrector|
unscoped_key = key_node.value.to_s.split('.').last
corrector.replace(key_node, "'.#{unscoped_key}'")
end
end
end
private
def controller_and_action(node)
action_node = node.each_ancestor(:def).first
return unless action_node && node_visibility(action_node) == :public
controller_node = node.each_ancestor(:class).first
return unless controller_node && controller_node.identifier.source.end_with?('Controller')
[controller_node, action_node]
end
def get_scoped_key(key_node, controller, action)
path = controller_path(controller).tr('/', '.')
action_name = action.method_name
key = key_node.value.to_s.split('.').last
"#{path}.#{action_name}.#{key}"
end
def controller_path(controller)
module_name = controller.parent_module_name
controller_name = controller.identifier.source
path = if module_name == 'Object'
controller_name
else
"#{module_name}::#{controller_name}"
end
path.delete_suffix('Controller').underscore
end
end
end
end
end