rubocop-i18n 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2792a2344ae871fa62e564786c03d892bd5072d
4
- data.tar.gz: 1354b5ac2e3a9606deb1b9c594edf8a23327db38
3
+ metadata.gz: 3e4f819b3b4f5bc73ec0b02ee1bd567ab2d3a40e
4
+ data.tar.gz: 4d0ec4a7cc1e6046d32421c9253c97a117e74b57
5
5
  SHA512:
6
- metadata.gz: 76633906bc7a3ad0612fff96eab7a80eb21bf26f58b95d6a31c8e24ca2958df6c95f079000c5002785ad184711e207b22b2059383d1791665728a3a73330697e
7
- data.tar.gz: 4f58a7770df70e74ea4d5150140ee35aaef1b31aacd65b776de7c6ceb6f638715756d71bf43dd5a4b870c724496e01fda0e3f95bdee02da3f7755e98935997bc
6
+ metadata.gz: 2b7502eadea26d2982e80cf6c9e49926656cd1c572f12ec1fe8213279ffbf603d222841f522620d77f33a847a1acf365fb661eb59315e0ab70e377d09e2fccde
7
+ data.tar.gz: 9fca0a7581cf5cd57ca7741826d558463bef5e641aa1c96053ee2e3d0b6facaf4da6bb77a21b6bab9b6ff18b77042689a61f9d7ca18848c2b2038d0864c1cc12
data/.gitignore CHANGED
@@ -9,6 +9,7 @@
9
9
  /test/tmp/
10
10
  /test/version_tmp/
11
11
  /tmp/
12
+ /.idea/
12
13
 
13
14
  # Used by dotenv library to load environment variables.
14
15
  # .env
@@ -0,0 +1,16 @@
1
+ # Change Log
2
+
3
+ ## master (unreleased)
4
+
5
+ ### 1.1.0
6
+
7
+ * Added support for DecorateStringFormattingUsingPercent
8
+ * Added support for DecorateStringFormattingUsingInterpolation
9
+
10
+ ### 1.0.0
11
+
12
+ * Improvements to DecorateFunctionMessage
13
+
14
+ ### 0.0.1
15
+
16
+ * Initial import of rubocop rules from https://github.com/tphoney/puppetlabs-mysql/tree/poc_i18nTesting/rubocop by [@tphoney]
data/README.md CHANGED
@@ -29,6 +29,10 @@ GetText/DecorateString:
29
29
  Enabled: false
30
30
  GetText/DecorateFunctionMessage:
31
31
  Enabled: true
32
+ GetText/DecorateStringFormattingUsingInterpolation
33
+ Enabled: true
34
+ GetText/DecorateStringFormattingUsingPercent
35
+ Enabled: true
32
36
  ```
33
37
 
34
38
  ## Cops
@@ -149,16 +153,69 @@ raise(someOtherFuntioncall(foo, "bar"))
149
153
  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](#Simple-decoration-of-a-message).
150
154
  Or ignore this raise or fail function following this [How to ignore rules in code](#How-to-ignore-rules-in-code) section.
151
155
 
156
+ ### GetText/DecorateStringFormattingUsingInterpolation
157
+
158
+ This cop looks for decorated gettext methods _() and checks that all strings contained
159
+ within do not use string interpolation '#{}'
160
+
161
+ #### Simple decoration of a message
162
+
163
+ Simple message strings should be decorated with the _() function
164
+
165
+ ##### Error message thrown
166
+
167
+ ```
168
+ '_' function, message string should not contain #{} formatting
169
+ ```
170
+
171
+ ##### Bad
172
+
173
+ ``` ruby
174
+ puts _("a message with a #{'interpolation'}")
175
+ ```
176
+
177
+ ##### Good
178
+
179
+ ``` ruby
180
+ puts _("a message that is %{type}") % { type: 'translatable' }
181
+ ```
182
+
183
+ ### GetText/DecorateStringFormattingUsingPercent
184
+
185
+ This cop looks for decorated gettext methods _() and checks that all strings contained
186
+ within do not use sprintf formatting '%s' etc
187
+
188
+ ##### Error message thrown
189
+
190
+ ```
191
+ '_' function, message string should not contain sprintf style formatting (ie %s)
192
+ ```
193
+
194
+ ##### Bad
195
+
196
+ ``` ruby
197
+ raise(_("Warning is %s") % ['bad'])
198
+ ```
199
+
200
+ ##### Good
201
+
202
+ ``` ruby
203
+ raise(_("Warning is %{value}") % { value: 'bad' })
204
+ ```
205
+
152
206
  ## How to ignore rules in code
153
207
 
154
208
  It may be necessary to ignore a cop for a particular piece of code. We follow standard rubocop idioms.
155
209
  ``` ruby
156
- raise("We don't want this translated") # rubocop:disable GetText/DecorateFunctionMessage
210
+ raise("We don't want this translated") # rubocop:disable GetText/DecorateFunctionMessage
211
+ raise(_("We don't want this translated #{crazy}") # rubocop:disable GetText/DecorateStringFormattingUsingInterpolation)
212
+ raise(_("We don't want this translated %s") % ['crazy'] # rubocop:disable GetText/DecorateStringFormattingUsingPercent)
157
213
  ```
158
214
 
159
215
  ## Known Issues
160
216
 
161
217
  Rubocop currently does not detect Heredoc style messages in functions correctly, which in turn prevents this plugin from detecting them correctly.
218
+ Not all sprintf formatting strings are detected.
162
219
 
163
220
  ## Development
164
221
 
@@ -2,3 +2,5 @@ require 'rubocop'
2
2
  require 'rubocop/cop/i18n/gettext'
3
3
  require 'rubocop/cop/i18n/gettext/decorate_string'
4
4
  require 'rubocop/cop/i18n/gettext/decorate_function_message'
5
+ require 'rubocop/cop/i18n/gettext/decorate_string_formatting_using_interpolation'
6
+ require 'rubocop/cop/i18n/gettext/decorate_string_formatting_using_percent'
@@ -0,0 +1,67 @@
1
+ module RuboCop
2
+ module Cop
3
+ module I18n
4
+ module GetText
5
+ # When using an decorated string to support I18N, any strings inside the decoration should not contain
6
+ # the '#{}' interpolation string as this makes it hard to translate the strings. This cop checks the
7
+ # decorators listed in SUPPORTED_DECORATORS
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ #
13
+ # _("result is #{this_is_the_result}")
14
+ # n_("a string" + "a string with a #{float_value}")
15
+ #
16
+ # @example
17
+ #
18
+ # # good
19
+ #
20
+ # _("result is %{detail}" % {detail: message})
21
+ #
22
+ class DecorateStringFormattingUsingInterpolation < Cop
23
+
24
+ SUPPORTED_DECORATORS = ['_', 'n_', 'N_']
25
+
26
+ def on_send(node)
27
+ decorator_name = node.loc.selector.source
28
+ return if !supported_decorator_name?(decorator_name)
29
+ _, method_name, *arg_nodes = *node
30
+ if !arg_nodes.empty? && contains_string_formatting_with_interpolation?(arg_nodes)
31
+ message_section = arg_nodes[0]
32
+ add_offense(message_section, :expression, "'#{method_name}' function, message string should not contain \#{} formatting")
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def supported_decorator_name?(decorator_name)
39
+ SUPPORTED_DECORATORS.include?(decorator_name)
40
+ end
41
+
42
+ def string_contains_interpolation_format?(str)
43
+ str.match(/\#{[^}]+}/)
44
+ end
45
+
46
+ def contains_string_formatting_with_interpolation?(node)
47
+ if node.is_a?(Array)
48
+ return node.any? { |n| contains_string_formatting_with_interpolation?(n) }
49
+ end
50
+
51
+ if node.respond_to?(:type)
52
+ if node.type == :str or node.type == :dstr
53
+ return string_contains_interpolation_format?(node.source)
54
+ end
55
+ end
56
+
57
+ if node.respond_to?(:children)
58
+ return node.children.any? { |child| contains_string_formatting_with_interpolation?(child) }
59
+ end
60
+ return false
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,70 @@
1
+ module RuboCop
2
+ module Cop
3
+ module I18n
4
+ module GetText
5
+ # When using a decorated string to support I18N, any strings inside the decoration should not contain sprintf
6
+ # style formatting as this makes it hard to translate the string. This cop checks the decorators listed in
7
+ # SUPPORTED_DECORATORS and checks for each of the formats in SUPPORTED_FORMATS. NOTE: this cop does not
8
+ # check for all possible sprintf formats.
9
+ #
10
+ # @example
11
+ #
12
+ # # bad
13
+ #
14
+ # _("result is %s" % ["value"])
15
+ # n_("a string" + "a string with a %-3.1f" % [size])
16
+ # N_("a string" + "a string with a %04d" % [size])
17
+ #
18
+ # @example
19
+ #
20
+ # # good
21
+ #
22
+ # _("result is %{detail}" % {detail: message})
23
+ #
24
+ class DecorateStringFormattingUsingPercent < Cop
25
+
26
+ SUPPORTED_DECORATORS = ['_', 'n_', 'N_']
27
+ SUPPORTED_FORMATS = %w[b B d i o u x X e E f g G a A c p s]
28
+
29
+ def on_send(node)
30
+ decorator_name = node.loc.selector.source
31
+ return if !supported_decorator_name?(decorator_name)
32
+ _, method_name, *arg_nodes = *node
33
+ if !arg_nodes.empty? && contains_string_with_percent_format?(arg_nodes)
34
+ message_section = arg_nodes[0]
35
+ add_offense(message_section, :expression, "'#{method_name}' function, message string should not contain sprintf style formatting (ie %s)")
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def supported_decorator_name?(decorator_name)
42
+ SUPPORTED_DECORATORS.include?(decorator_name)
43
+ end
44
+
45
+ def string_contains_percent_format?(str)
46
+ SUPPORTED_FORMATS.any? { |format| str.match(/%([-+])?[0-9]*(\.[0-9]*)?#{format}/) }
47
+ end
48
+
49
+ def contains_string_with_percent_format?(node)
50
+ if node.is_a?(Array)
51
+ return node.any? { |n| contains_string_with_percent_format?(n) }
52
+ end
53
+
54
+ if node.respond_to?(:type)
55
+ if node.type == :str or node.type == :dstr
56
+ return string_contains_percent_format?(node.source)
57
+ end
58
+ end
59
+
60
+ if node.respond_to?(:children)
61
+ return node.children.any? { |child| contains_string_with_percent_format?(child) }
62
+ end
63
+ false
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -4,9 +4,9 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "rubocop-i18n"
7
- spec.version = '1.0.0'
8
- spec.authors = ["Brandon High", "TP Honey", "Helen Campbell"]
9
- spec.email = ["brandon.high@puppet.com", "tp@puppet.com", "helen@puppet.com"]
7
+ spec.version = '1.1.0'
8
+ spec.authors = ["Puppet", "Brandon High", "TP Honey", "Helen Campbell"]
9
+ spec.email = ["team-modules@puppet.com", "brandon.high@puppet.com", "tp@puppet.com", "helen@puppet.com"]
10
10
 
11
11
  spec.summary = %q{RuboCop rules for i18n}
12
12
  spec.description = %q{RuboCop rules for detecting and autocorrecting undecorated strings for i18n}
metadata CHANGED
@@ -1,16 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
+ - Puppet
7
8
  - Brandon High
8
9
  - TP Honey
9
10
  - Helen Campbell
10
11
  autorequire:
11
12
  bindir: exe
12
13
  cert_chain: []
13
- date: 2017-09-06 00:00:00.000000000 Z
14
+ date: 2017-10-13 00:00:00.000000000 Z
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: bundler
@@ -99,6 +100,7 @@ dependencies:
99
100
  description: RuboCop rules for detecting and autocorrecting undecorated strings for
100
101
  i18n
101
102
  email:
103
+ - team-modules@puppet.com
102
104
  - brandon.high@puppet.com
103
105
  - tp@puppet.com
104
106
  - helen@puppet.com
@@ -108,6 +110,7 @@ extra_rdoc_files: []
108
110
  files:
109
111
  - ".gitignore"
110
112
  - ".travis.yml"
113
+ - CHANGELOG.md
111
114
  - CODE_OF_CONDUCT.md
112
115
  - Gemfile
113
116
  - LICENSE
@@ -120,6 +123,8 @@ files:
120
123
  - lib/rubocop/cop/i18n/gettext.rb
121
124
  - lib/rubocop/cop/i18n/gettext/decorate_function_message.rb
122
125
  - lib/rubocop/cop/i18n/gettext/decorate_string.rb
126
+ - lib/rubocop/cop/i18n/gettext/decorate_string_formatting_using_interpolation.rb
127
+ - lib/rubocop/cop/i18n/gettext/decorate_string_formatting_using_percent.rb
123
128
  - lib/rubocop/rspec/cop_helper.rb
124
129
  - rubocop-i18n.gemspec
125
130
  homepage: https://github.com/puppetlabs/rubocop-i18n