Skip to content

Commit

Permalink
Allow relative keys in any Ruby object (#381)
Browse files Browse the repository at this point in the history
  • Loading branch information
javierm authored Oct 15, 2021
1 parent b04a9cf commit 265b80d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
20 changes: 17 additions & 3 deletions lib/i18n/tasks/scanners/relative_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ module RelativeKeys
# @param roots [Array<String>] paths to relative roots
# @param calling_method [#call, Symbol, String, false, nil]
# @return [String] absolute version of the key
def absolute_key(key, path, roots: config[:relative_roots], calling_method: nil)
def absolute_key(key, path, roots: config[:relative_roots],
exclude_method_name_paths: config[:exclude_method_name_paths],
calling_method: nil)
return key unless key.start_with?(DOT)
fail 'roots argument is required' unless roots.present?

Expand All @@ -18,7 +20,12 @@ def absolute_key(key, path, roots: config[:relative_roots], calling_method: nil)
fail(CommandError, "Cannot resolve relative key \"#{key}\".\n" \
"Set search.relative_roots in config/i18n-tasks.yml (currently #{roots.inspect})")
normalized_path.sub!(root, '')
"#{prefix(normalized_path, calling_method: calling_method)}#{key}"

if (exclude_method_name_paths || []).map { |p| expand_path(p) }.include?(root)
"#{prefix(normalized_path)}#{key}"
else
"#{prefix(normalized_path, calling_method: calling_method)}#{key}"
end
end

private
Expand All @@ -31,12 +38,19 @@ def absolute_key(key, path, roots: config[:relative_roots], calling_method: nil)
# @return [String] the closest ancestor root for path, with a trailing {File::SEPARATOR}.
def path_root(path, roots)
roots.map do |p|
File.expand_path(p) + File::SEPARATOR
expand_path(p)
end.sort.reverse_each.detect do |root|
path.start_with?(root)
end
end

# Expand a path and add a trailing {File::SEPARATOR}
# @param [String] path relative path
# @return [String] absolute path, with a trailing {File::SEPARATOR}.
def expand_path(path)
File.expand_path(path) + File::SEPARATOR
end

# @param normalized_path [String] path/relative/to/a/root
# @param calling_method [#call, Symbol, String, false, nil]
def prefix(normalized_path, calling_method: nil)
Expand Down
3 changes: 2 additions & 1 deletion lib/i18n/tasks/used_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module I18n::Tasks
module UsedKeys # rubocop:disable Metrics/ModuleLength
SEARCH_DEFAULTS = {
paths: %w[app/].freeze,
relative_exclude_method_name_paths: [],
relative_roots: %w[app/controllers app/helpers app/mailers app/presenters app/views].freeze,
scanners: [
['::I18n::Tasks::Scanners::RubyAstScanner', { only: %w[*.rb] }],
Expand Down Expand Up @@ -105,7 +106,7 @@ def search_config

def merge_scanner_configs(a, b)
a.deep_merge(b).tap do |c|
%i[scanners paths relative_roots].each do |key|
%i[scanners paths relative_exclude_method_name_paths relative_roots].each do |key|
c[key] = a[key] if b[key].blank?
end
%i[exclude].each do |key|
Expand Down
46 changes: 46 additions & 0 deletions spec/relative_keys_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

class RelativeKeysUser
include ::I18n::Tasks::Scanners::RelativeKeys

def config
{}
end
end

RSpec.describe 'Relative keys' do
Expand Down Expand Up @@ -102,5 +106,47 @@ class RelativeKeysUser
end
end
end

context 'using exclude_method_name_paths' do
it 'works' do
key = relative_keys.absolute_key(
'.subject',
'app/mailers/user_mailer.rb',
roots: %w[app/mailers],
exclude_method_name_paths: %w[app/mailers],
calling_method: 'welcome'
)

expect(key).to eq('user_mailer.subject')
end

context 'multiple words in file name' do
it 'works' do
key = relative_keys.absolute_key(
'.subject',
'app/mailers/admin_user_mailer.rb',
roots: %w[app/mailers],
exclude_method_name_paths: %w[app/mailers],
calling_method: 'welcome'
)

expect(key).to eq('admin_user_mailer.subject')
end
end

context 'nested in module' do
it 'works' do
key = relative_keys.absolute_key(
'.subject',
'app/mailers/nested/user_mailer.rb',
roots: %w[app/mailers],
exclude_method_name_paths: %w[app/mailers],
calling_method: 'welcome'
)

expect(key).to eq('nested.user_mailer.subject')
end
end
end
end
end
7 changes: 7 additions & 0 deletions templates/config/i18n-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ search:
# - app/presenters
# - app/views

## Directories where method names which should not be part of a relative key resolution.
# By default, if a relative translation is used inside a method, the name of the method will be considered part of the resolved key.
# Directories listed here will not consider the name of the method part of the resolved key
#
# relative_exclude_method_name_paths:
# -

## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
## %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
exclude:
Expand Down

0 comments on commit 265b80d

Please sign in to comment.