diff --git a/README.md b/README.md index b17f1bca..14ac77b2 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,9 @@ $ i18n-tasks remove-unused These tasks can infer [dynamic keys](#dynamic-keys) such as `t("category.\#{category.name}")` if you set `search.strict` to false, or pass `--no-strict` on the command line. +If you want to keep the ordering from the original language file when using remove-unused, pass +`-k` or `--keep-order`. + ### Normalize data Sort the keys: diff --git a/config/locales/en.yml b/config/locales/en.yml index d51a436c..33c9083f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -13,6 +13,7 @@ en: locales implicitly. confirm: Confirm automatically data_format: 'Data format: %{valid_text}.' + keep_order: Keep the order of the keys key_pattern: Filter by key pattern (e.g. 'common.*') key_pattern_to_rename: Full key (pattern) to rename. Required locale: :i18n_tasks.common.locale diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 407533f4..b3257ea8 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -10,6 +10,7 @@ ru: all_locales: Не ожидать, что маски ключа начинаются с локали. Применять маски ко всем локалям. confirm: Подтвердить автоматом data_format: 'Формат данных: %{valid_text}. %{default_text}.' + keep_order: Keep the order of the keys key_pattern: Маска ключа (например, common.*) key_pattern_to_rename: Полный ключ (шаблон) для переименования. Необходимый параметр. locale: 'Язык. По умолчанию: base' diff --git a/lib/i18n/tasks/command/commands/usages.rb b/lib/i18n/tasks/command/commands/usages.rb index 38c7f249..b6386273 100644 --- a/lib/i18n/tasks/command/commands/usages.rb +++ b/lib/i18n/tasks/command/commands/usages.rb @@ -10,6 +10,11 @@ module Usages '--[no-]strict', t('i18n_tasks.cmd.args.desc.strict') + arg :keep_order, + '-k', + '--keep-order', + t('i18n_tasks.cmd.args.desc.keep_order') + cmd :find, pos: '[pattern]', desc: t('i18n_tasks.cmd.desc.find'), @@ -35,13 +40,14 @@ def unused(opt = {}) cmd :remove_unused, pos: '[locale ...]', desc: t('i18n_tasks.cmd.desc.remove_unused'), - args: %i[locales out_format strict confirm] + args: %i[locales out_format strict keep_order confirm] def remove_unused(opt = {}) unused_keys = i18n.unused_keys(opt.slice(:locales, :strict)) if unused_keys.present? terminal_report.unused_keys(unused_keys) confirm_remove_unused!(unused_keys, opt) + i18n.data.config = i18n.data.config.merge(sort: false) if opt[:'keep-order'] removed = i18n.data.remove_by_key!(unused_keys) log_stderr t('i18n_tasks.remove_unused.removed', count: unused_keys.leaves.count) print_forest removed, opt diff --git a/lib/i18n/tasks/data/file_formats.rb b/lib/i18n/tasks/data/file_formats.rb index e5a09594..6d7d5634 100644 --- a/lib/i18n/tasks/data/file_formats.rb +++ b/lib/i18n/tasks/data/file_formats.rb @@ -45,8 +45,8 @@ def read_file(path) ::File.read(path, encoding: 'UTF-8') end - def write_tree(path, tree) - hash = tree.to_hash(true) + def write_tree(path, tree, sort = true) + hash = tree.to_hash(sort) adapter = self.class.adapter_name_for_path(path) content = adapter_dump(hash, adapter) # Ignore unchanged data diff --git a/lib/i18n/tasks/data/file_system_base.rb b/lib/i18n/tasks/data/file_system_base.rb index 65964f57..af5757df 100644 --- a/lib/i18n/tasks/data/file_system_base.rb +++ b/lib/i18n/tasks/data/file_system_base.rb @@ -21,7 +21,8 @@ class FileSystemBase # rubocop:disable Metrics/ClassLength }.freeze def initialize(config = {}) - self.config = config.except(:base_locale, :locales) + self.config = config.except(:base_locale, :locales) + self.config[:sort] = !config[:keep_order] @base_locale = config[:base_locale] locales = config[:locales].presence @locales = LocaleList.normalize_locale_list(locales || available_locales, base_locale, true) @@ -60,7 +61,7 @@ def set(locale, tree) paths_after = Set.new([]) router.route locale, tree do |path, tree_slice| paths_after << path - write_tree path, tree_slice + write_tree path, tree_slice, config[:sort] end (paths_before - paths_after).each do |path| FileUtils.remove_file(path) if File.exist?(path) diff --git a/spec/i18n_tasks_spec.rb b/spec/i18n_tasks_spec.rb index ae5ec12c..c9471d6a 100644 --- a/spec/i18n_tasks_spec.rb +++ b/spec/i18n_tasks_spec.rb @@ -155,6 +155,56 @@ end end end + + it 'sorts the keys' do + in_test_app_dir do + ENV['CONFIRM'] = '1' + run_cmd 'remove-unused' + en_yml_data = i18n_task.data.reload['en'].select_keys do |_k, node| + node.data[:path] == 'config/locales/en.yml' + end + expect(en_yml_data).to be_present + en_yml_data.nodes do |nodes| + next unless nodes.children + keys = nodes.children.map(&:key) + expect(keys).to eq keys.sort + end + end + end + + it 'removes unused (--keep-order)' do + in_test_app_dir do + t = i18n_task + unused = expected_unused_keys.map { |k| ::I18n::Tasks::SplitKey.split_key(k, 2)[1] } + unused.each do |key| + expect(t.key_value?(key, :en)).to be true + expect(t.key_value?(key, :es)).to be true + end + + ENV['CONFIRM'] = '1' + run_cmd 'remove-unused', '--keep-order' + t.data.reload + unused.each do |key| + expect(t.key_value?(key, :en)).to be false + expect(t.key_value?(key, :es)).to be false + end + end + end + + it 'does not sort the keys (--keep-order)' do + in_test_app_dir do + unused_keys = expected_unused_keys.map { |k| ::I18n::Tasks::SplitKey.split_key(k, 2)[1] } + initial_keys = i18n_task.data['en'].select_keys do |k, _node| + unused_keys.none? { |unused_key| k.include?(unused_key) } + end + ENV['CONFIRM'] = '1' + run_cmd 'remove-unused', '--keep-order' + final_keys = i18n_task.data.reload['en'].select_keys do |k, _node| + unused_keys.none? { |unused_key| k.include?(unused_key) } + end + expect(initial_keys.inspect).to eq(final_keys.inspect) + end + end end describe 'normalize' do