Skip to content

Commit

Permalink
Fixes dynamic key matching issue with nested #{}
Browse files Browse the repository at this point in the history
Refs #180
  • Loading branch information
glebm committed Dec 22, 2015
1 parent 5c29a6f commit 7fdfb16
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
33 changes: 30 additions & 3 deletions lib/i18n/tasks/key_pattern_matching.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'strscan'

module I18n::Tasks::KeyPatternMatching
extend self
MATCH_NOTHING = /\z\A/.freeze
Expand Down Expand Up @@ -30,20 +32,45 @@ def key_pattern_re_body(key_pattern)
gsub(/\{(.*?)}/) { "(#{$1.strip.gsub /\s*,\s*/, '|'.freeze})" }
end

def key_match_pattern(k)
def key_match_pattern(k, replacement: ':'.freeze)
@key_match_pattern ||= {}
@key_match_pattern[k] ||= begin
"#{k.gsub(KEY_INTERPOLATION_RE, ':'.freeze)}#{':'.freeze if k.end_with?('.'.freeze)}"
"#{replace_key_interpolations(k, replacement)}#{replacement if k.end_with?('.'.freeze)}"
end
end

# @return true if the key looks like an expression
KEY_INTERPOLATION_RE = /(?:\#{.*?}|\*+|\:+)/.freeze
KEY_INTERPOLATION_RE = /\#{/.freeze
def key_expression?(k)
@key_is_expr ||= {}
if @key_is_expr[k].nil?
@key_is_expr[k] = (k =~ KEY_INTERPOLATION_RE || k.end_with?('.'.freeze))
end
@key_is_expr[k]
end

private

# Replace interpolations.
# @param key [String]
# @param replacement [String]
# @return [String]
def replace_key_interpolations(key, replacement)
scanner = StringScanner.new(key)
braces = []
result = []
while (match_until = scanner.scan_until(/(?:#?\{|})/.freeze) )
if scanner.matched == '#{'.freeze
braces << scanner.matched
result << match_until[0..-3] if braces.length == 1
elsif scanner.matched == '}'
prev_brace = braces.pop
result << replacement if braces.empty? && prev_brace == '#{'.freeze
else
braces << '{'.freeze
end
end
result << key[scanner.pos..-1] unless scanner.eos?
result.join
end
end
7 changes: 7 additions & 0 deletions spec/key_pattern_matching_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,12 @@
expect([$1, $2]).to eq(['x', 'c'])
end
end

describe 'key_match_pattern' do
it 'handles nested {}' do
expect(key_match_pattern('a.#{b.gsub(%r{/{}{}}, x)}.#{c}.title')).to(
eq 'a.:.:.title')
end
end
end
end

0 comments on commit 7fdfb16

Please sign in to comment.