i18n-tasks 0.9.25 → 0.9.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/locales/en.yml +3 -0
- data/config/locales/ru.yml +7 -3
- data/lib/i18n/tasks/base_task.rb +2 -0
- data/lib/i18n/tasks/command/commands/eq_base.rb +3 -1
- data/lib/i18n/tasks/command/commands/health.rb +6 -1
- data/lib/i18n/tasks/command/commands/interpolations.rb +22 -0
- data/lib/i18n/tasks/commands.rb +2 -0
- data/lib/i18n/tasks/concurrent/cached_value.rb +34 -2
- data/lib/i18n/tasks/interpolations.rb +29 -0
- data/lib/i18n/tasks/reports/base.rb +4 -0
- data/lib/i18n/tasks/reports/terminal.rb +9 -0
- data/lib/i18n/tasks/translators/deepl_translator.rb +1 -1
- data/lib/i18n/tasks/translators/google_translator.rb +1 -1
- data/lib/i18n/tasks/version.rb +1 -1
- data/templates/config/i18n-tasks.yml +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5c06b9d6d4187eda97fce4acb55c31c8c01534814e8770ed64d3f0f052dbb26
|
4
|
+
data.tar.gz: ec0198e22e8c9b55fd87f386467cb94400a400263405efc42fc5d3696c610e21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89296743377a8207fa571d82c23c1ec36e71b8209f2f949cf8d541ea0ef4db87b1f69e5c28796ee6ebeeddad1c352a2d1b2f14bf685593e828c715dc74a24b18
|
7
|
+
data.tar.gz: b66aaea9115ee5015e9696d562666dbcfeae6f770f4e8558e59257557e9d138249639bdf6a9b9e73ee1acadb88b1ae386f0d1dde1e7b655ff816f15e0a229fc9
|
data/README.md
CHANGED
@@ -22,7 +22,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
|
|
22
22
|
Add i18n-tasks to the Gemfile:
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
gem 'i18n-tasks', '~> 0.9.
|
25
|
+
gem 'i18n-tasks', '~> 0.9.26'
|
26
26
|
```
|
27
27
|
|
28
28
|
Copy the default [configuration file](#configuration):
|
data/config/locales/en.yml
CHANGED
@@ -33,6 +33,7 @@ en:
|
|
33
33
|
%{value_or_default_or_human_key}
|
34
34
|
desc:
|
35
35
|
add_missing: add missing keys to locale data
|
36
|
+
check_consistent_interpolations: verify that all translations use correct interpolation variables
|
36
37
|
check_normalized: verify that all translation data is normalized
|
37
38
|
config: display i18n-tasks configuration
|
38
39
|
data: show locale data
|
@@ -102,6 +103,8 @@ en:
|
|
102
103
|
Google Translate returned no results. Make sure billing information is set at https://code.google.com/apis/console.
|
103
104
|
health:
|
104
105
|
no_keys_detected: No keys detected. Check data.read in config/i18n-tasks.yml.
|
106
|
+
inconsistent_interpolations:
|
107
|
+
none: No inconsistent interpolations found.
|
105
108
|
missing:
|
106
109
|
details_title: Value in other locales or source
|
107
110
|
none: No translations are missing.
|
data/config/locales/ru.yml
CHANGED
@@ -9,7 +9,7 @@ ru:
|
|
9
9
|
desc:
|
10
10
|
all_locales: Не ожидать, что маски ключа начинаются с локали. Применять маски ко всем локалям.
|
11
11
|
confirm: Подтвердить автоматом
|
12
|
-
data_format: 'Формат данных: %{valid_text}.
|
12
|
+
data_format: 'Формат данных: %{valid_text}.'
|
13
13
|
keep_order: Keep the order of the keys
|
14
14
|
key_pattern: Маска ключа (например, common.*)
|
15
15
|
key_pattern_to_rename: Полный ключ (шаблон) для переименования. Необходимый параметр.
|
@@ -21,7 +21,7 @@ ru:
|
|
21
21
|
missing_types: 'Типы недостающих переводов: %{valid}. По умолчанию: все'
|
22
22
|
new_key_name: Новое имя, интерполирует оригинальное название как %{key}. Необходимый параметр.
|
23
23
|
nostdin: Не читать дерево из стандартного ввода
|
24
|
-
out_format: 'Формат вывода: %{valid_text}.
|
24
|
+
out_format: 'Формат вывода: %{valid_text}.'
|
25
25
|
pattern_router: 'Использовать pattern_router: ключи распределятся по файлам согласно data.write'
|
26
26
|
strict: Не угадывать динамические использования ключей, например `t("category.#{category.key}")`
|
27
27
|
translation_backend: Движок перевода (google или deepl)
|
@@ -30,6 +30,8 @@ ru:
|
|
30
30
|
%{value_or_default_or_human_key}
|
31
31
|
desc:
|
32
32
|
add_missing: добавить недостающие ключи к переводам
|
33
|
+
check_consistent_interpolations: убедитесь, что во всех переводах используются правильные
|
34
|
+
интерполяционные переменные
|
33
35
|
check_normalized: проверить, что все файлы переводов нормализованы
|
34
36
|
config: показать конфигурацию
|
35
37
|
data: показать данные переводов
|
@@ -99,12 +101,14 @@ ru:
|
|
99
101
|
в https://code.google.com/apis/console.
|
100
102
|
health:
|
101
103
|
no_keys_detected: Ключи не обнаружены. Проверьте data.read в config/i18n-tasks.yml.
|
104
|
+
inconsistent_interpolations:
|
105
|
+
none: Не найдено несогласованных интерполяций.
|
102
106
|
missing:
|
103
107
|
details_title: На других языках или в коде
|
104
108
|
none: Всё переведено.
|
105
109
|
remove_unused:
|
106
110
|
confirm:
|
107
|
-
one:
|
111
|
+
one: "%{count} перевод будут удалён из %{locales}."
|
108
112
|
other: Переводы (%{count}) будут удалены из %{locales}.
|
109
113
|
noop: Нет неиспользуемых ключей
|
110
114
|
removed: Удалены ключи (%{count})
|
data/lib/i18n/tasks/base_task.rb
CHANGED
@@ -10,6 +10,7 @@ require 'i18n/tasks/html_keys'
|
|
10
10
|
require 'i18n/tasks/used_keys'
|
11
11
|
require 'i18n/tasks/ignore_keys'
|
12
12
|
require 'i18n/tasks/missing_keys'
|
13
|
+
require 'i18n/tasks/interpolations'
|
13
14
|
require 'i18n/tasks/unused_keys'
|
14
15
|
require 'i18n/tasks/translation'
|
15
16
|
require 'i18n/tasks/locale_pathname'
|
@@ -30,6 +31,7 @@ module I18n
|
|
30
31
|
include UsedKeys
|
31
32
|
include IgnoreKeys
|
32
33
|
include MissingKeys
|
34
|
+
include Interpolations
|
33
35
|
include UnusedKeys
|
34
36
|
include Translation
|
35
37
|
include Logging
|
@@ -12,7 +12,9 @@ module I18n::Tasks
|
|
12
12
|
args: %i[locales out_format]
|
13
13
|
|
14
14
|
def eq_base(opt = {})
|
15
|
-
|
15
|
+
forest = i18n.eq_base_keys(opt)
|
16
|
+
print_forest forest, opt, :eq_base_keys
|
17
|
+
:exit_1 unless forest.empty?
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
@@ -16,7 +16,12 @@ module I18n::Tasks
|
|
16
16
|
stats = i18n.forest_stats(forest)
|
17
17
|
fail CommandError, t('i18n_tasks.health.no_keys_detected') if stats[:key_count].zero?
|
18
18
|
terminal_report.forest_stats forest, stats
|
19
|
-
[
|
19
|
+
[
|
20
|
+
missing(opt),
|
21
|
+
unused(opt),
|
22
|
+
check_consistent_interpolations(opt),
|
23
|
+
check_normalized(opt)
|
24
|
+
].detect { |result| result == :exit_1 }
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module I18n::Tasks
|
4
|
+
module Command
|
5
|
+
module Commands
|
6
|
+
module Interpolations
|
7
|
+
include Command::Collection
|
8
|
+
|
9
|
+
cmd :check_consistent_interpolations,
|
10
|
+
pos: '[locale ...]',
|
11
|
+
desc: t('i18n_tasks.cmd.desc.check_consistent_interpolations'),
|
12
|
+
args: %i[locales out_format]
|
13
|
+
|
14
|
+
def check_consistent_interpolations(opt = {})
|
15
|
+
forest = i18n.inconsistent_interpolations(opt.slice(:locales, :base_locale))
|
16
|
+
print_forest forest, opt, :inconsistent_interpolations
|
17
|
+
:exit_1 unless forest.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/i18n/tasks/commands.rb
CHANGED
@@ -5,6 +5,7 @@ require 'i18n/tasks/command/collection'
|
|
5
5
|
require 'i18n/tasks/command/commands/health'
|
6
6
|
require 'i18n/tasks/command/commands/missing'
|
7
7
|
require 'i18n/tasks/command/commands/usages'
|
8
|
+
require 'i18n/tasks/command/commands/interpolations'
|
8
9
|
require 'i18n/tasks/command/commands/eq_base'
|
9
10
|
require 'i18n/tasks/command/commands/data'
|
10
11
|
require 'i18n/tasks/command/commands/tree'
|
@@ -17,6 +18,7 @@ module I18n::Tasks
|
|
17
18
|
include Command::Commands::Health
|
18
19
|
include Command::Commands::Missing
|
19
20
|
include Command::Commands::Usages
|
21
|
+
include Command::Commands::Interpolations
|
20
22
|
include Command::Commands::EqBase
|
21
23
|
include Command::Commands::Data
|
22
24
|
include Command::Commands::Tree
|
@@ -18,10 +18,42 @@ module I18n::Tasks::Concurrent
|
|
18
18
|
|
19
19
|
# @return [Object] Result of the computation.
|
20
20
|
def get
|
21
|
-
return
|
21
|
+
return get_result_volatile unless get_result_volatile == NULL
|
22
22
|
@mutex.synchronize do
|
23
|
-
|
23
|
+
next unless get_result_volatile == NULL
|
24
|
+
set_result_volatile @computation.call
|
25
|
+
@computation = nil
|
24
26
|
end
|
27
|
+
get_result_volatile
|
25
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Ruby instance variable volatility is currently unspecified:
|
33
|
+
# https://bugs.ruby-lang.org/issues/11539
|
34
|
+
#
|
35
|
+
# Below are the implementations for major ruby engines, based on concurrent-ruby.
|
36
|
+
# rubocop:disable Lint/DuplicateMethods,Naming/AccessorMethodName
|
37
|
+
case RUBY_ENGINE
|
38
|
+
when 'rbx'
|
39
|
+
def get_result_volatile
|
40
|
+
Rubinius.memory_barrier
|
41
|
+
@result
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_result_volatile(value)
|
45
|
+
@result = value
|
46
|
+
Rubinius.memory_barrier
|
47
|
+
end
|
48
|
+
else
|
49
|
+
def get_result_volatile
|
50
|
+
@result
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_result_volatile(value)
|
54
|
+
@result = value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
# rubocop:enable Lint/DuplicateMethods,Naming/AccessorMethodName
|
26
58
|
end
|
27
59
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module I18n::Tasks
|
4
|
+
module Interpolations
|
5
|
+
VARIABLE_REGEX = /%{[^}]+}/
|
6
|
+
|
7
|
+
def inconsistent_interpolations(locales: nil, base_locale: nil) # rubocop:disable Metrics/AbcSize
|
8
|
+
locales ||= self.locales
|
9
|
+
base_locale ||= self.base_locale
|
10
|
+
result = empty_forest
|
11
|
+
|
12
|
+
data[base_locale].key_values.each do |key, value|
|
13
|
+
next if !value.is_a?(String) || ignore_key?(key, :inconsistent_interpolations)
|
14
|
+
base_vars = Set.new(value.scan(VARIABLE_REGEX))
|
15
|
+
(locales - [base_locale]).each do |current_locale|
|
16
|
+
node = data[current_locale].first.children[key]
|
17
|
+
next unless node&.value&.is_a?(String)
|
18
|
+
vars = node.value.scan(VARIABLE_REGEX)
|
19
|
+
unless vars.size == base_vars.size && vars.all? { |v| base_vars.include?(v) }
|
20
|
+
result.merge!(node.walk_to_root.reduce(nil) { |c, p| [p.derive(children: c)] })
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
result.each { |root| root.data[:type] = :inconsistent_interpolations }
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -21,6 +21,10 @@ module I18n::Tasks::Reports
|
|
21
21
|
"Missing translations (#{forest.leaves.count || '∅'})"
|
22
22
|
end
|
23
23
|
|
24
|
+
def inconsistent_interpolations_title(forest)
|
25
|
+
"Inconsistent interpolations (#{forest.leaves.count || '∅'})"
|
26
|
+
end
|
27
|
+
|
24
28
|
def unused_title(key_values)
|
25
29
|
"Unused keys (#{key_values.count || '∅'})"
|
26
30
|
end
|
@@ -25,6 +25,15 @@ module I18n
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
def inconsistent_interpolations(forest = task.inconsistent_interpolations)
|
29
|
+
if forest.present?
|
30
|
+
print_title inconsistent_interpolations_title(forest)
|
31
|
+
show_tree(forest)
|
32
|
+
else
|
33
|
+
print_success I18n.t('i18n_tasks.inconsistent_interpolations.none')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
28
37
|
def icon(type)
|
29
38
|
glyph = missing_type_info(type)[:glyph]
|
30
39
|
{ missing_used: Rainbow(glyph).red, missing_diff: Rainbow(glyph).yellow }[type]
|
@@ -61,7 +61,7 @@ module I18n::Tasks::Translators
|
|
61
61
|
|
62
62
|
def configure_api_key!
|
63
63
|
api_key = @i18n_tasks.translation_config[:deepl_api_key]
|
64
|
-
fail CommandError, I18n.t('i18n_tasks.deepl_translate.errors.no_api_key') if api_key.blank?
|
64
|
+
fail ::I18n::Tasks::CommandError, I18n.t('i18n_tasks.deepl_translate.errors.no_api_key') if api_key.blank?
|
65
65
|
DeepL.configure { |config| config.auth_key = api_key }
|
66
66
|
end
|
67
67
|
end
|
@@ -59,7 +59,7 @@ module I18n::Tasks::Translators
|
|
59
59
|
)
|
60
60
|
key ||= translation_config[:api_key]
|
61
61
|
end
|
62
|
-
fail CommandError, I18n.t('i18n_tasks.google_translate.errors.no_api_key') if key.blank?
|
62
|
+
fail ::I18n::Tasks::CommandError, I18n.t('i18n_tasks.google_translate.errors.no_api_key') if key.blank?
|
63
63
|
key
|
64
64
|
end
|
65
65
|
end
|
data/lib/i18n/tasks/version.rb
CHANGED
@@ -111,6 +111,10 @@ search:
|
|
111
111
|
# fr,es:
|
112
112
|
# - common.brand
|
113
113
|
|
114
|
+
## Exclude these keys from the `i18n-tasks check-consistent-interpolations` report:
|
115
|
+
# ignore_inconsistent_interpolations:
|
116
|
+
# - 'activerecord.attributes.*'
|
117
|
+
|
114
118
|
## Ignore these keys completely:
|
115
119
|
# ignore:
|
116
120
|
# - kaminari.*
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- glebm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -282,6 +282,7 @@ files:
|
|
282
282
|
- lib/i18n/tasks/command/commands/data.rb
|
283
283
|
- lib/i18n/tasks/command/commands/eq_base.rb
|
284
284
|
- lib/i18n/tasks/command/commands/health.rb
|
285
|
+
- lib/i18n/tasks/command/commands/interpolations.rb
|
285
286
|
- lib/i18n/tasks/command/commands/meta.rb
|
286
287
|
- lib/i18n/tasks/command/commands/missing.rb
|
287
288
|
- lib/i18n/tasks/command/commands/tree.rb
|
@@ -312,6 +313,7 @@ files:
|
|
312
313
|
- lib/i18n/tasks/data/tree/traversal.rb
|
313
314
|
- lib/i18n/tasks/html_keys.rb
|
314
315
|
- lib/i18n/tasks/ignore_keys.rb
|
316
|
+
- lib/i18n/tasks/interpolations.rb
|
315
317
|
- lib/i18n/tasks/key_pattern_matching.rb
|
316
318
|
- lib/i18n/tasks/locale_list.rb
|
317
319
|
- lib/i18n/tasks/locale_pathname.rb
|