Skip to content

Commit

Permalink
Add missing-plural-keys
Browse files Browse the repository at this point in the history
  • Loading branch information
Gargron committed Oct 25, 2018
1 parent 9a4f7a1 commit c421e75
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 18 deletions.
3 changes: 3 additions & 0 deletions config/i18n-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ search:
- lib/
exclude:
- 'tmp/*'

ignore_missing:
- i18n.plural.keys
4 changes: 4 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ en:
health: is everything OK?
irb: start REPL session within i18n-tasks context
missing: show missing translations
missing_plural_keys: show missing pluralizations
mv: rename/merge the keys in locale data that match the given pattern
normalize: 'normalize translation data: sort and move to the right files'
remove_unused: remove unused keys
Expand Down Expand Up @@ -108,6 +109,9 @@ en:
missing:
details_title: Value in other locales or source
none: No translations are missing.
missing_plural_keys:
details_title: Missing plural forms
none: All pluralizations are complete.
remove_unused:
confirm:
one: "%{count} translation will be removed from %{locales}."
Expand Down
4 changes: 4 additions & 0 deletions config/locales/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ ru:
health: Всё ОК?
irb: начать REPL сессию в контексте i18n-tasks
missing: показать недостающие переводы
missing_plural_keys: показать недостающие плюрализации
mv: переименовать / объединить ключи, которые соответствуют заданному шаблону
normalize: нормализовать файлы переводов (сортировка и распределение)
remove_unused: удалить неиспользуемые ключи
Expand Down Expand Up @@ -106,6 +107,9 @@ ru:
missing:
details_title: На других языках или в коде
none: Всё переведено.
missing_plural_keys:
details_title: Отсутствующие формы множественного числа
none: Все множественное число являются полными.
remove_unused:
confirm:
one: "%{count} перевод будут удалён из %{locales}."
Expand Down
1 change: 1 addition & 0 deletions i18n-tasks.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ TEXT
s.add_dependency 'highline', '>= 2.0.0'
s.add_dependency 'i18n'
s.add_dependency 'parser', '>= 2.2.3.0'
s.add_dependency 'rails-i18n'
s.add_dependency 'rainbow', '>= 2.2.2', '< 4.0'
s.add_dependency 'terminal-table', '>= 1.5.1'
s.add_development_dependency 'axlsx', '~> 2.0'
Expand Down
6 changes: 6 additions & 0 deletions lib/i18n/tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ module Data

# Add internal locale data to i18n gem load path
require 'i18n'

Dir[File.join(I18n::Tasks.gem_path, 'config', 'locales', '*.yml')].each do |locale_file|
I18n.config.load_path << locale_file
end

# Load pluralization data
require 'rails-i18n'
I18n.enforce_available_locales = false
RailsI18n::Railtie.add('rails/pluralization/*.rb')
11 changes: 11 additions & 0 deletions lib/i18n/tasks/command/commands/missing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ def missing(opt = {})
:exit_1 unless forest.empty?
end

cmd :missing_plural_keys,
pos: '[locale ...]',
desc: t('i18n_tasks.cmd.desc.missing_plural_keys'),
args: %i[locales out_format]

def missing_plural_keys(opt = {})
forest = i18n.missing_plural_keys(opt.slice(:locales))
print_forest forest, opt, :missing_plural_keys
:exit_1 unless forest.empty?
end

cmd :translate_missing,
pos: '[locale ...]',
desc: t('i18n_tasks.cmd.desc.translate_missing'),
Expand Down
22 changes: 22 additions & 0 deletions lib/i18n/tasks/plural_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@ def collapse_plural_nodes!(tree)
tree
end

def missing_plural_keys(locales: nil) # rubocop:disable Metrics/AbcSize
locales ||= self.locales

locales.each_with_object(empty_forest) do |locale, tree|
next unless I18n.exists?(:'i18n.plural.keys', locale)

required_keys = Set.new(I18n.t(:'i18n.plural.keys', locale: locale, resolve: false))

data[locale].leaves.map(&:parent).compact.uniq.each do |node|
children = node.children
present_keys = Set.new(children.to_hash.keys.map(&:to_sym))
next if !plural_forms?(children) || present_keys >= required_keys
node.value = children.to_hash
node.children = nil
node.data[:missing_keys] = (required_keys - present_keys).to_a
tree.merge!(node.walk_to_root.reduce(nil) { |c, p| [p.derive(children: c)] })
end

tree.each { |root| root.data[:type] = :missing_plural_keys }
end
end

# @param [String] key i18n key
# @param [String] locale to pull key data from
# @return [String] the base form if the key is a specific plural form (e.g. apple for apple.many), the key otherwise.
Expand Down
4 changes: 4 additions & 0 deletions lib/i18n/tasks/reports/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ def missing_title(forest)
"Missing translations (#{forest.leaves.count || '∅'})"
end

def missing_plural_keys_title(forest)
"Missing plural keys (#{forest.leaves.count || '∅'})"
end

def inconsistent_interpolations_title(forest)
"Inconsistent interpolations (#{forest.leaves.count || '∅'})"
end
Expand Down
18 changes: 18 additions & 0 deletions lib/i18n/tasks/reports/terminal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ def inconsistent_interpolations(forest = task.inconsistent_interpolations)
end
end

def missing_plural_keys(forest = task.missing_plural_keys) # rubocop:disable Metrics/AbcSize
forest = collapse_missing_tree! forest
if forest.present?
print_title missing_plural_keys_title(forest)
print_table headings: [Rainbow(I18n.t('i18n_tasks.common.locale')).cyan.bright,
Rainbow(I18n.t('i18n_tasks.common.key')).cyan.bright,
I18n.t('i18n_tasks.missing_plural_keys.details_title')] do |t|
t.rows = sort_by_attr!(forest_to_attr(forest)).map do |a|
[{ value: Rainbow(format_locale(a[:locale])).cyan, alignment: :center },
format_key(a[:key], a[:data]),
a[:data][:missing_keys].join(', ')]
end
end
else
print_success I18n.t('i18n_tasks.missing_plural_keys.none')
end
end

def icon(type)
glyph = missing_type_info(type)[:glyph]
{ missing_used: Rainbow(glyph).red, missing_diff: Rainbow(glyph).yellow }[type]
Expand Down
62 changes: 44 additions & 18 deletions spec/plural_keys_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,39 @@

RSpec.describe 'Plural keys' do
let(:task) { ::I18n::Tasks::BaseTask.new }
before do
TestCodebase.setup('config/locales/en.yml' => '')
TestCodebase.in_test_app_dir do
tree = ::I18n::Tasks::Data::Tree::Siblings.from_nested_hash('en' => {
'regular_key' => 'a',
'plural_key' => {
'one' => 'one', 'other' => '%{count}'
},
'not_really_plural' => {
'one' => 'a',
'green' => 'b'
}
})
task.data['en'] = tree
task.data['en']
end

let(:base_keys) do
{
regular_key: 'a',

plural_key: {
one: 'one',
other: '%{count}'
},

not_really_plural: {
one: 'a',
green: 'b'
},

nested: {
plural_key: {
zero: 'none',
one: 'one',
other: '%{count}'
}
}
}
end

around do |ex|
TestCodebase.setup(
'config/i18n-tasks.yml' => { base_locale: 'en', locales: %w[en ar] }.to_yaml,
'config/locales/en.yml' => { en: base_keys }.to_yaml,
'config/locales/ar.yml' => { ar: base_keys }.to_yaml
)
TestCodebase.in_test_app_dir { ex.call }
TestCodebase.teardown
end

describe '#depluralize_key' do
Expand All @@ -40,7 +57,16 @@ def depluralize(key)
end
end

after do
TestCodebase.teardown
describe '#missing_plural_keys' do
it 'returns keys with missing pluralizations' do
wrong = task.missing_plural_keys
leaves = wrong.leaves.to_a

expect(leaves.size).to eq 2
expect(leaves[0].full_key).to eq 'ar.plural_key'
expect(leaves[0].data[:missing_keys]).to eq %i[zero two few many]
expect(leaves[1].full_key).to eq 'ar.nested.plural_key'
expect(leaves[1].data[:missing_keys]).to eq %i[two few many]
end
end
end

0 comments on commit c421e75

Please sign in to comment.