i18n_checker 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +6 -1
  3. data/README.md +48 -1
  4. data/Rakefile +11 -1
  5. data/examples/unused/example.haml +1 -0
  6. data/examples/unused/example.rb +11 -0
  7. data/examples/unused/locales/en.yml +7 -0
  8. data/examples/unused/locales/ja.yml +7 -0
  9. data/i18n-checker.gemspec +3 -0
  10. data/lib/i18n_checker/command/check.rb +22 -0
  11. data/lib/i18n_checker/command/clean.rb +21 -0
  12. data/lib/i18n_checker/locale/file.rb +69 -7
  13. data/lib/i18n_checker/locale/files.rb +9 -0
  14. data/lib/i18n_checker/locale/text.rb +12 -0
  15. data/lib/i18n_checker/locale/texts.rb +16 -1
  16. data/lib/i18n_checker/locale.rb +8 -1
  17. data/lib/i18n_checker/{detector/locale_text_not_found.rb → not_found/detector.rb} +4 -4
  18. data/lib/i18n_checker/not_found/reporter/base.rb +17 -0
  19. data/lib/i18n_checker/not_found/reporter/default.rb +30 -0
  20. data/lib/i18n_checker/not_found/reporter.rb +2 -0
  21. data/lib/i18n_checker/{detector/detected_result.rb → not_found/result.rb} +2 -2
  22. data/lib/i18n_checker/{detector/text_result.rb → not_found/text.rb} +2 -2
  23. data/lib/i18n_checker/rake_task/{locale_check.rb → check.rb} +7 -6
  24. data/lib/i18n_checker/rake_task/clean.rb +50 -0
  25. data/lib/i18n_checker/rake_task.rb +2 -1
  26. data/lib/i18n_checker/unused/detector.rb +38 -0
  27. data/lib/i18n_checker/unused/reporter/base.rb +15 -0
  28. data/lib/i18n_checker/unused/reporter/default.rb +37 -0
  29. data/lib/i18n_checker/unused/reporter.rb +2 -0
  30. data/lib/i18n_checker/unused/result.rb +44 -0
  31. data/lib/i18n_checker/unused/text.rb +18 -0
  32. data/lib/i18n_checker/version.rb +1 -1
  33. data/lib/i18n_checker.rb +4 -6
  34. metadata +52 -11
  35. data/lib/i18n_checker/locale_text_not_found_checker.rb +0 -20
  36. data/lib/i18n_checker/reporter/default_reporter.rb +0 -28
  37. data/lib/i18n_checker/reporter/detect_result_reporter.rb +0 -15
  38. data/lib/i18n_checker/reporter.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e19d1fb49c3cf080cc470ee645bdf19bac8ca955
4
- data.tar.gz: f96f63a7b74fe6fa6a002b7520c737610ad4a2c4
3
+ metadata.gz: 5f5558d107c756fa782ad6a425a9c13189e96fc5
4
+ data.tar.gz: 321f55bfa86d773d871532ce7c4aab9105e0eb31
5
5
  SHA512:
6
- metadata.gz: a1d0b632d0049108127d9e34cfb86984edf5475ca6bab05ca623fc5689116edcb4bf69cd0b73b5fd2830cbb58dcb181520fc975f83efe9f1f2ae99b432739d18
7
- data.tar.gz: 06c158aad02010d206904d62cacfc729f0d3500ec9f33ab13a5d412be6b1ac79e745635b0de7e215a54bf30f315c5fa954d2f02dd7ec65d8ab163bb3c8b49edb
6
+ metadata.gz: f83fcce7f6caba897b78d27557090394e69802fd3034ecde81d2dbacafd992b4cbfb464a326535ac16615e9739152085de28b81003b834e685a74de5bd047d1f
7
+ data.tar.gz: df76434f18429622f5da5680e6b55a9db20d138f61d525d83b2bf6bb361b8415878095ebfde46fd55fd6dca76ccfa24305d065c46d07f209ccec6916a249800d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- i18n_checker (0.5.0)
4
+ i18n_checker (0.6.0)
5
5
  colorator (~> 1.1.0)
6
6
  haml_parser (~> 0.4)
7
7
  parser
@@ -44,6 +44,8 @@ GEM
44
44
  diff-lcs (>= 1.2.0, < 2.0)
45
45
  rspec-support (~> 3.6.0)
46
46
  rspec-support (3.6.0)
47
+ rspec-temp_dir (1.0.0)
48
+ rspec (>= 3.0)
47
49
  rubocop (0.47.1)
48
50
  parser (>= 2.3.3.1, < 3.0)
49
51
  powerpack (~> 0.1)
@@ -67,6 +69,7 @@ GEM
67
69
  thor (0.19.4)
68
70
  tins (1.13.2)
69
71
  unicode-display_width (1.1.3)
72
+ yard (0.9.9)
70
73
 
71
74
  PLATFORMS
72
75
  ruby
@@ -78,8 +81,10 @@ DEPENDENCIES
78
81
  onkcop
79
82
  rake (~> 10.0)
80
83
  rspec
84
+ rspec-temp_dir
81
85
  simplecov
82
86
  simplecov-console
87
+ yard
83
88
 
84
89
  BUNDLED WITH
85
90
  1.14.6
data/README.md CHANGED
@@ -14,12 +14,18 @@ Current version supports Ruby source code, Haml template file.
14
14
 
15
15
  ## Basic usage
16
16
 
17
+ Detected out of reference text, Delete unused translation text at once.
17
18
  Add the following tasks to your **Rakefile**.
18
19
 
19
20
  ```ruby
20
21
  require 'i18n_checker/rake_task'
21
22
 
22
- I18nChecker::RakeTask::LocaleCheck.new do |task|
23
+ I18nChecker::RakeTask::Check.new do |task|
24
+ task.source_paths = FileList['app/models/*', 'app/views/*'] # haml templates, ruby sources
25
+ task.locale_file_paths = FileList['config/locales/*'] # locale file paths
26
+ end
27
+
28
+ I18nChecker::RakeTask::Clean do |task|
23
29
  task.source_paths = FileList['app/models/*', 'app/views/*'] # haml templates, ruby sources
24
30
  task.locale_file_paths = FileList['config/locales/*'] # locale file paths
25
31
  end
@@ -29,6 +35,47 @@ After that we just execute the task.
29
35
 
30
36
  ```shell
31
37
  bundle exec rake locale_check
38
+ bundle exec rake locale_clean
39
+ ```
40
+
41
+ ## Check translation of translated text
42
+
43
+ Detect translated text references that are broken.
44
+ It is useful for detecting text that is not in the translation file of a particular language.
45
+
46
+ ```ruby
47
+ require 'i18n_checker/rake_task'
48
+
49
+ I18nChecker::RakeTask::Check.new do |task|
50
+ task.source_paths = FileList['app/models/*', 'app/views/*'] # haml templates, ruby sources
51
+ task.locale_file_paths = FileList['config/locales/*'] # locale file paths
52
+ end
53
+ ```
54
+
55
+ After that we just execute the task.
56
+
57
+ ```shell
58
+ bundle exec rake locale_check
59
+ ```
60
+
61
+ ## Delete unused translated text
62
+
63
+ Using the **locale_clean** task you can delete unused translated text from the file.
64
+ Since you can delete translated text that you do not use safely, you can reduce the maintenance cost by running it periodically.
65
+
66
+ ```ruby
67
+ require 'i18n_checker/rake_task'
68
+
69
+ I18nChecker::RakeTask::Clean do |task|
70
+ task.source_paths = FileList['app/models/*', 'app/views/*'] # haml templates, ruby sources
71
+ task.locale_file_paths = FileList['config/locales/*'] # locale file paths
72
+ end
73
+ ```
74
+
75
+ After that we just execute the task.
76
+
77
+ ```shell
78
+ bundle exec rake locale_clean
32
79
  ```
33
80
 
34
81
  ## Run the test
data/Rakefile CHANGED
@@ -1,12 +1,22 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
+ require 'yard'
3
4
  require 'i18n_checker/rake_task'
4
5
 
5
6
  RSpec::Core::RakeTask.new(:spec)
6
7
 
7
- I18nChecker::RakeTask::LocaleCheck.new do |task|
8
+ I18nChecker::RakeTask::Check.new do |task|
8
9
  task.source_paths = FileList['spec/fixtures/haml/*', 'spec/fixtures/ruby/*']
9
10
  task.locale_file_paths = FileList['spec/fixtures/locales/**']
10
11
  end
11
12
 
13
+ I18nChecker::RakeTask::Clean.new do |task|
14
+ task.source_paths = FileList['examples/unused/**']
15
+ task.locale_file_paths = FileList['examples/unused/locales/**']
16
+ end
17
+
18
+ YARD::Rake::YardocTask.new do |t|
19
+ t.files = ['lib/**/*.rb']
20
+ end
21
+
12
22
  task :default => :spec
@@ -0,0 +1 @@
1
+ %p= t('nested.foo')
@@ -0,0 +1,11 @@
1
+ module Example
2
+ class Example
3
+ def foo
4
+ t('nested.foo')
5
+ end
6
+
7
+ def bar
8
+ I18n.t('nested.bar')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ en:
2
+ nested:
3
+ foo: foo
4
+ bar: bar
5
+ nested2:
6
+ foo: foo
7
+ bar: bar
@@ -0,0 +1,7 @@
1
+ ja:
2
+ nested:
3
+ foo: foo
4
+ bar: bar
5
+ nested2:
6
+ foo: foo
7
+ bar: bar
data/i18n-checker.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
21
  spec.require_paths = ['lib']
22
+ spec.metadata['yard.run'] = 'yri'
22
23
  spec.add_dependency 'haml_parser', '~> 0.4'
23
24
  spec.add_dependency 'colorator', '~> 1.1.0'
24
25
  spec.add_dependency 'parser'
@@ -29,4 +30,6 @@ Gem::Specification.new do |spec|
29
30
  spec.add_development_dependency 'simplecov-console'
30
31
  spec.add_development_dependency 'coveralls'
31
32
  spec.add_development_dependency 'onkcop'
33
+ spec.add_development_dependency 'rspec-temp_dir'
34
+ spec.add_development_dependency 'yard'
32
35
  end
@@ -0,0 +1,22 @@
1
+ require 'i18n_checker/not_found/detector'
2
+ require 'i18n_checker/not_found/text'
3
+ require 'i18n_checker/not_found/result'
4
+
5
+ module I18nChecker
6
+ module Command
7
+ class Check
8
+ def initialize(locale_file_paths: [], source_paths: [], reporter:)
9
+ @reporter = reporter
10
+ @locale_texts = I18nChecker::Locale.texts_of(source_paths)
11
+ @locale_files = I18nChecker::Locale.load_of(locale_file_paths)
12
+ end
13
+
14
+ def check
15
+ not_found_detector = I18nChecker::NotFound::Detector.new(@locale_files)
16
+ not_found_result = @locale_texts.detect(not_found_detector)
17
+ @reporter.report not_found_result
18
+ yield not_found_result if block_given?
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'i18n_checker/unused/detector'
2
+
3
+ module I18nChecker
4
+ module Command
5
+ class Clean
6
+ def initialize(locale_file_paths: [], source_paths: [], reporter:)
7
+ @reporter = reporter
8
+ @locale_texts = I18nChecker::Locale.texts_of(source_paths)
9
+ @locale_files = I18nChecker::Locale.load_of(locale_file_paths)
10
+ @unused_detector = I18nChecker::Unused::Detector.new(@locale_files)
11
+ end
12
+
13
+ def run
14
+ unused_result = @locale_texts.detect(@unused_detector)
15
+ @reporter.report unused_result
16
+ unused_result.apply(@locale_files)
17
+ yield unused_result if block_given?
18
+ end
19
+ end
20
+ end
21
+ end
@@ -2,29 +2,71 @@ require 'yaml'
2
2
 
3
3
  module I18nChecker
4
4
  module Locale
5
+ # Translation file for each language
6
+ #
7
+ # @attr_reader [String] file_name Translation file path
8
+ # @attr_reader [String] lang language
9
+ # @attr_reader [Hash<String,String>] locale_texts translation texts
5
10
  class File
6
- attr_reader :lang, :locale_texts
11
+ attr_reader :file_name, :lang, :locale_texts
7
12
 
8
13
  class << self
9
- def load_yaml(s)
10
- new(YAML.load(s))
11
- end
12
-
14
+ # Read translation file
15
+ #
16
+ # @param yaml_file [String] Translation file path
17
+ # @return [I18nChecker::Locale::File] Translation file
13
18
  def load_yaml_file(yaml_file)
14
- load_yaml(::File.open(yaml_file, &:read))
19
+ new(yaml_file, YAML.load(::File.open(yaml_file, &:read)))
15
20
  end
16
21
  end
17
22
 
18
- def initialize(locale_texts = {})
23
+ # Create a translation file
24
+ #
25
+ # @param yaml_file [String] Translation file path
26
+ # @param locale_texts [Hash<String,String>] translation text
27
+ def initialize(yaml_file, locale_texts = {})
19
28
  lang = locale_texts.keys.first
20
29
  @lang = lang.to_sym
21
30
  @locale_texts = compact_of(locale_texts[lang] || {})
31
+ @file_name = yaml_file
22
32
  end
23
33
 
34
+ # Check for translated text
35
+ #
36
+ # @param locale_text [Stirng] Translation text key
37
+ # @return [Boolean] Returns true if there is translated text
24
38
  def include?(locale_text)
25
39
  @locale_texts.key?(locale_text.text)
26
40
  end
27
41
 
42
+ # Deletes the specified translation text
43
+ #
44
+ # @param locale_text [Array<Stirng>] Translation text key
45
+ # @return [I18nChecker::Locale::File] New translation file
46
+ def remove_texts(locale_texts)
47
+ registry = locale_texts.map { |locale_text| [locale_text, true] }.to_h
48
+
49
+ current_locale_texts = @locale_texts.dup
50
+ current_locale_texts.delete_if { |locale_text| registry.key?(locale_text) }
51
+
52
+ remain_texts = {}
53
+ remain_texts[@lang] = current_locale_texts
54
+
55
+ self.class.new(file_name, remain_texts)
56
+ end
57
+
58
+ # Save the translation file
59
+ #
60
+ # @return [I18nChecker::Locale::File] translation file
61
+ def save
62
+ locale = {}
63
+ locale[@lang.to_s] = tree_of(locale_texts)
64
+ yaml_file = ::File.open(file_name, 'w')
65
+ yaml_file.write(YAML.dump(locale))
66
+ yaml_file.close
67
+ self
68
+ end
69
+
28
70
  private
29
71
 
30
72
  def compact_of(values = {}, path = KeyPath.new)
@@ -40,6 +82,26 @@ module I18nChecker
40
82
  end
41
83
  result
42
84
  end
85
+
86
+ def tree_of(values = [])
87
+ result = {}
88
+ values.each do |path, value|
89
+ dest = nil
90
+ paths = path.split('.')
91
+ last_key = paths.last
92
+ paths.pop
93
+ paths.each do |p|
94
+ if result.key?(p)
95
+ dest = result[p]
96
+ else
97
+ result[p] = {}
98
+ dest = result[p]
99
+ end
100
+ end
101
+ dest[last_key] = value
102
+ end
103
+ result
104
+ end
43
105
  end
44
106
  end
45
107
  end
@@ -9,10 +9,19 @@ module I18nChecker
9
9
 
10
10
  def_delegators :locale_files, :size, :each
11
11
 
12
+ # Translation files for each language
13
+ #
14
+ # @param locale_files [Array<I18nChecker::Locale::File>]
12
15
  def initialize(locale_files = [])
13
16
  @locale_files = locale_files
14
17
  end
15
18
 
19
+ # Execute the specified block and delete the translation file
20
+ #
21
+ # @yield [file] Block to be evaluated
22
+ # @yieldparam [I18nChecker::Locale::File]
23
+ # @yieldreturn [Boolean]
24
+ # @return [I18nChecker::Locale::Files]
16
25
  def delete_if(&block)
17
26
  locale_files.delete_if(&block)
18
27
  self
@@ -1,8 +1,20 @@
1
1
  module I18nChecker
2
2
  module Locale
3
+ # Translation text referenced from the file
4
+ #
5
+ # @attr_reader [String] file File referring to translated text
6
+ # @attr_reader [String] text Translation text key
7
+ # @attr_reader [Fixnum] line Line number of file
8
+ # @attr_reader [Fixnum] column Column number of file
3
9
  class Text
4
10
  attr_reader :file, :text, :line, :column
5
11
 
12
+ # Create translated text
13
+ #
14
+ # @param file [String] File referring to translated text
15
+ # @param text [String] Translation text key
16
+ # @param line [Fixnum] Line number of file
17
+ # @param column [Fixnum] Column number of file
6
18
  def initialize(file:, text:, line:, column:)
7
19
  @file = file
8
20
  @text = text
@@ -3,27 +3,42 @@ require 'i18n_checker/locale/text'
3
3
 
4
4
  module I18nChecker
5
5
  module Locale
6
+ # List of translated text
7
+ #
6
8
  class Texts
7
9
  extend Forwardable
8
10
 
9
11
  include Enumerable
10
12
 
11
- def_delegators :texts, :size, :each
13
+ def_delegators :texts, :size, :each, :select
12
14
 
15
+ # Create list of translated text
16
+ #
17
+ # @param texts [Array<I18nChecker::Locale::Text>] List of translated text
13
18
  def initialize(texts = [])
14
19
  @texts = texts
15
20
  end
16
21
 
22
+ # Combine lists of translated texts
23
+ #
24
+ # @param texts [Enumerable<I18nChecker::Locale::Text>] List of translated text
25
+ # @return [I18nChecker::Locale::Texts<I18nChecker::Locale::Text>] Returns the combined receiver itself
17
26
  def concat(texts)
18
27
  @texts.concat(texts.to_a)
19
28
  self
20
29
  end
21
30
 
31
+ # Delete translated text duplicates
32
+ #
33
+ # @return [I18nChecker::Locale::Texts<I18nChecker::Locale::Text>] Returns the combined receiver itself
22
34
  def uniq!
23
35
  @texts.uniq!
24
36
  self
25
37
  end
26
38
 
39
+ # Compare lists of translated texts
40
+ #
41
+ # @return [Boolean]
27
42
  def ==(other)
28
43
  @texts == other.to_a
29
44
  end
@@ -6,11 +6,18 @@ require 'i18n_checker/locale/collector'
6
6
  module I18nChecker
7
7
  module Locale
8
8
  module Methods
9
+ # Read specified translation file
10
+ #
11
+ # @return [I18nChecker::Locale::Files]
9
12
  def load_of(locale_files)
10
- loaded_locale_files = locale_files.map { |locale_file| I18nChecker::Locale::File.load_yaml_file(locale_file) }
13
+ files = locale_files.delete_if { |resource| ::File.directory?(resource) }.to_a
14
+ loaded_locale_files = files.map { |locale_file| I18nChecker::Locale::File.load_yaml_file(locale_file) }
11
15
  Files.new(loaded_locale_files)
12
16
  end
13
17
 
18
+ # Collect translation text from specified file list
19
+ #
20
+ # @return [I18nChecker::Locale::Texts]
14
21
  def texts_of(resources)
15
22
  caches = I18nChecker::Cache::Files.new
16
23
 
@@ -1,13 +1,13 @@
1
1
  module I18nChecker
2
- module Detector
3
- class LocaleTextNotFound
2
+ module NotFound
3
+ class Detector
4
4
  def initialize(locale_files)
5
5
  @locale_files = locale_files
6
6
  end
7
7
 
8
8
  def detect(locale_texts)
9
9
  results = locale_texts.map { |local_text| detect_not_found(local_text) }
10
- DetectedResult.new(results.compact.flatten)
10
+ Result.new(results.compact.flatten)
11
11
  end
12
12
 
13
13
  private
@@ -16,7 +16,7 @@ module I18nChecker
16
16
  locale_files = @locale_files.dup
17
17
  locale_files.delete_if { |locale_file| locale_file.include?(locale_text) }
18
18
  locale_files.map do |locale_file|
19
- TextResult.new(
19
+ Text.new(
20
20
  locale_text: locale_text,
21
21
  locale_file: locale_file
22
22
  )
@@ -0,0 +1,17 @@
1
+ require 'logger'
2
+
3
+ module I18nChecker
4
+ module NotFound
5
+ module Reporter
6
+ class Base
7
+ def initialize(logger: Logger.new(STDOUT))
8
+ @logger = logger
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :logger
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ require 'colorator'
2
+
3
+ module I18nChecker
4
+ module NotFound
5
+ module Reporter
6
+ class Default < Base
7
+ CHECK_COMPLETED = 'Translation text checking is complete.'.freeze
8
+
9
+ def report(result)
10
+ return passed if result.empty?
11
+ failed(result)
12
+ end
13
+
14
+ def passed
15
+ logger.info CHECK_COMPLETED.green
16
+ logger.info 'There was no translated text that can not be referenced'.green
17
+ end
18
+
19
+ def failed(result)
20
+ logger.info CHECK_COMPLETED.red
21
+ logger.info "There are settings where translated text can not be found\n".red
22
+ result.locale_texts.each do |locale_text|
23
+ logger.info locale_text.file.cyan.to_s
24
+ logger.info " line:#{locale_text.line}, column:#{locale_text.column} - #{locale_text.lang}.#{locale_text.text}"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,2 @@
1
+ require 'i18n_checker/not_found/reporter/base'
2
+ require 'i18n_checker/not_found/reporter/default'
@@ -1,6 +1,6 @@
1
1
  module I18nChecker
2
- module Detector
3
- class DetectedResult
2
+ module NotFound
3
+ class Result
4
4
  attr_reader :locale_texts
5
5
 
6
6
  def initialize(locale_texts = [])
@@ -1,8 +1,8 @@
1
1
  require 'forwardable'
2
2
 
3
3
  module I18nChecker
4
- module Detector
5
- class TextResult
4
+ module NotFound
5
+ class Text
6
6
  extend Forwardable
7
7
 
8
8
  def_delegators :locale_file, :lang
@@ -2,12 +2,13 @@ require 'rake'
2
2
  require 'rake/tasklib'
3
3
  require 'i18n_checker/cache'
4
4
  require 'i18n_checker/locale'
5
- require 'i18n_checker/reporter'
6
- require 'i18n_checker/locale_text_not_found_checker'
5
+ require 'i18n_checker/not_found/reporter/base'
6
+ require 'i18n_checker/not_found/reporter/default'
7
+ require 'i18n_checker/command/check'
7
8
 
8
9
  module I18nChecker
9
10
  module RakeTask
10
- class LocaleCheck < ::Rake::TaskLib
11
+ class Check < ::Rake::TaskLib
11
12
  attr_accessor :name
12
13
  attr_accessor :reporter
13
14
  attr_accessor :source_paths
@@ -22,7 +23,7 @@ module I18nChecker
22
23
  @logger.formatter = proc { |_severity, _datetime, _progname, message|
23
24
  "#{message}\n"
24
25
  }
25
- @reporter = I18nChecker::Reporter::DefaultReporter.new(logger: logger)
26
+ @reporter = I18nChecker::NotFound::Reporter::Default.new(logger: logger)
26
27
  yield self if block_given?
27
28
  define
28
29
  end
@@ -35,12 +36,12 @@ module I18nChecker
35
36
  end
36
37
 
37
38
  def run_task
38
- checker = I18nChecker::LocaleTextNotFoundChecker.new(
39
+ commmand = I18nChecker::Command::Check.new(
39
40
  reporter: reporter,
40
41
  source_paths: source_paths,
41
42
  locale_file_paths: locale_file_paths
42
43
  )
43
- checker.check do |result|
44
+ commmand.check do |result|
44
45
  exit 1 unless result.empty?
45
46
  end
46
47
  end
@@ -0,0 +1,50 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'i18n_checker/cache'
4
+ require 'i18n_checker/locale'
5
+ require 'i18n_checker/unused/detector'
6
+ require 'i18n_checker/unused/reporter/default'
7
+ require 'i18n_checker/command/clean'
8
+
9
+ module I18nChecker
10
+ module RakeTask
11
+ class Clean < ::Rake::TaskLib
12
+ attr_accessor :name
13
+ attr_accessor :reporter
14
+ attr_accessor :source_paths
15
+ attr_accessor :locale_file_paths
16
+ attr_accessor :logger
17
+
18
+ def initialize(name = :locale_clean)
19
+ @name = name
20
+ @source_paths = FileList['app/views/*', 'app/controllers/*', 'app/jobs/*', 'app/models/*', 'app/helpers/*']
21
+ @locale_file_paths = FileList['config/locales/*']
22
+ @logger = Logger.new(STDOUT)
23
+ @logger.formatter = proc { |_severity, _datetime, _progname, message|
24
+ "#{message}\n"
25
+ }
26
+ @reporter = I18nChecker::Unused::Reporter::Default.new(logger: logger)
27
+ yield self if block_given?
28
+ define
29
+ end
30
+
31
+ private
32
+
33
+ def define
34
+ desc 'Delete unused translation text.'
35
+ task(name) { run_task }
36
+ end
37
+
38
+ def run_task
39
+ command = I18nChecker::Command::Clean.new(
40
+ reporter: reporter,
41
+ source_paths: source_paths,
42
+ locale_file_paths: locale_file_paths
43
+ )
44
+ command.run do |result|
45
+ exit 1 unless result.empty?
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1 +1,2 @@
1
- require 'i18n_checker/rake_task/locale_check'
1
+ require 'i18n_checker/rake_task/check'
2
+ require 'i18n_checker/rake_task/clean'
@@ -0,0 +1,38 @@
1
+ require 'i18n_checker/unused/text'
2
+ require 'i18n_checker/unused/result'
3
+
4
+ module I18nChecker
5
+ module Unused
6
+ class Detector
7
+ def initialize(locale_files)
8
+ @locale_files = locale_files
9
+ end
10
+
11
+ def detect(locale_texts)
12
+ unused_texts = cleaned_locale_files(locale_texts).map do |locale_file|
13
+ locale_file.locale_texts.map do |key, _v|
14
+ I18nChecker::Unused::Text.new(
15
+ text: key,
16
+ file: locale_file
17
+ )
18
+ end
19
+ end
20
+ I18nChecker::Unused::Result.new(unused_texts.compact.flatten)
21
+ end
22
+
23
+ private
24
+
25
+ def cleaned_locale_files(locale_texts)
26
+ remove_locale_texts = used_locale_texts(locale_texts)
27
+ @locale_files.map { |locale_file| locale_file.remove_texts(remove_locale_texts) }
28
+ end
29
+
30
+ def used_locale_texts(locale_texts)
31
+ used_locale_texts = locale_texts.dup.select do |locale_text|
32
+ @locale_files.any? { |locale_file| locale_file.include?(locale_text) }
33
+ end
34
+ used_locale_texts.map(&:text)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ module I18nChecker
2
+ module Unused
3
+ module Reporter
4
+ class Base
5
+ def initialize(logger: Logger.new(STDOUT))
6
+ @logger = logger
7
+ end
8
+
9
+ private
10
+
11
+ attr_reader :logger
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ require 'i18n_checker/unused/result'
2
+ require 'i18n_checker/unused/result'
3
+ require 'i18n_checker/unused/detector'
4
+ require 'i18n_checker/unused/reporter/base'
5
+
6
+ module I18nChecker
7
+ module Unused
8
+ module Reporter
9
+ class Default < Base
10
+ CHECK_COMPLETED = 'Checking of unused translated text is finished.'.freeze
11
+
12
+ #
13
+ # @param unused_result [I18nChecker::Unused::Result]
14
+ def report(unused_result)
15
+ return passed if unused_result.empty?
16
+ failed(unused_result)
17
+ end
18
+
19
+ private
20
+
21
+ def passed
22
+ logger.info CHECK_COMPLETED.green
23
+ logger.info 'Unused translation text was not found'.green
24
+ end
25
+
26
+ def failed(unused_result)
27
+ logger.info CHECK_COMPLETED.red
28
+ logger.info "An unused translation text was found.\n".red
29
+ unused_result.locale_files.each do |file_name, unused_texts|
30
+ logger.info file_name.cyan.to_s
31
+ unused_texts.map { |text| logger.info " #{text.text}" }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ require 'i18n_checker/unused/reporter/base'
2
+ require 'i18n_checker/unused/reporter/default'
@@ -0,0 +1,44 @@
1
+ module I18nChecker
2
+ module Unused
3
+ # Detection result of unused translated text
4
+ #
5
+ # @attr_reader [Array<I18nChecker::Unused::Text>] unused_texts
6
+ # @attr_reader [Hash<String, Array<I18nChecker::Unused::File>>] locale_files
7
+ class Result
8
+ attr_reader :unused_texts, :locale_files
9
+
10
+ #
11
+ #
12
+ # @param unused_texts [Array<I18nChecker::Unused::Text>]
13
+ def initialize(unused_texts = [])
14
+ @unused_texts = unused_texts
15
+ @locale_files = unused_texts.group_by(&:file_name)
16
+ end
17
+
18
+ #
19
+ #
20
+ # @return [Boolean]
21
+ def empty?
22
+ unused_texts.empty?
23
+ end
24
+
25
+ # Apply the detected unused translated text to the current translation file.
26
+ # Unused text has been deleted from the translation file.
27
+ #
28
+ # @param target_locale_files [Array<I18nChecker::Locale::File>]
29
+ # @return [Array<I18nChecker::Locale::File>]
30
+ def apply(target_locale_files)
31
+ locale_files = target_locale_files.
32
+ group_by(&:file_name).
33
+ map { |k, v| [k, v.first] }
34
+
35
+ cleanup_locale_files = locale_files.map do |file_name, locale_file|
36
+ return locale_file unless @locale_files.key?(file_name)
37
+ unused_texts = @locale_files[file_name]
38
+ locale_file.remove_texts(unused_texts.map(&:text))
39
+ end
40
+ cleanup_locale_files.each(&:save)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ require 'forwardable'
2
+
3
+ module I18nChecker
4
+ module Unused
5
+ class Text
6
+ extend Forwardable
7
+
8
+ attr_reader :file, :text
9
+
10
+ def_delegators :file, :lang, :file_name
11
+
12
+ def initialize(file:, text:)
13
+ @file = file
14
+ @text = text
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module I18nChecker
2
- VERSION = '0.5.0'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  end
data/lib/i18n_checker.rb CHANGED
@@ -11,12 +11,10 @@ require 'i18n_checker/locale/texts'
11
11
  require 'i18n_checker/locale/key_path'
12
12
  require 'i18n_checker/locale/file'
13
13
  require 'i18n_checker/locale/files'
14
- require 'i18n_checker/detector/locale_text_not_found'
15
- require 'i18n_checker/detector/text_result'
16
- require 'i18n_checker/detector/detected_result'
17
- require 'i18n_checker/reporter/detect_result_reporter'
18
- require 'i18n_checker/reporter/default_reporter'
19
- require 'i18n_checker/locale_text_not_found_checker'
14
+ require 'i18n_checker/unused/detector'
15
+ require 'i18n_checker/unused/reporter'
16
+ require 'i18n_checker/not_found/detector'
17
+ require 'i18n_checker/not_found/reporter'
20
18
 
21
19
  module I18nChecker
22
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n_checker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - holyshared
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-30 00:00:00.000000000 Z
11
+ date: 2017-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml_parser
@@ -150,6 +150,34 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec-temp_dir
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: yard
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
153
181
  description: Verification of translation of Ruby source and Haml template
154
182
  email:
155
183
  - holy.shared.design@gmail.com
@@ -168,13 +196,16 @@ files:
168
196
  - LICENSE
169
197
  - README.md
170
198
  - Rakefile
199
+ - examples/unused/example.haml
200
+ - examples/unused/example.rb
201
+ - examples/unused/locales/en.yml
202
+ - examples/unused/locales/ja.yml
171
203
  - i18n-checker.gemspec
172
204
  - lib/i18n_checker.rb
173
205
  - lib/i18n_checker/cache.rb
174
206
  - lib/i18n_checker/collectible.rb
175
- - lib/i18n_checker/detector/detected_result.rb
176
- - lib/i18n_checker/detector/locale_text_not_found.rb
177
- - lib/i18n_checker/detector/text_result.rb
207
+ - lib/i18n_checker/command/check.rb
208
+ - lib/i18n_checker/command/clean.rb
178
209
  - lib/i18n_checker/locale.rb
179
210
  - lib/i18n_checker/locale/collector.rb
180
211
  - lib/i18n_checker/locale/collector/haml.rb
@@ -185,18 +216,28 @@ files:
185
216
  - lib/i18n_checker/locale/text.rb
186
217
  - lib/i18n_checker/locale/text_processor.rb
187
218
  - lib/i18n_checker/locale/texts.rb
188
- - lib/i18n_checker/locale_text_not_found_checker.rb
219
+ - lib/i18n_checker/not_found/detector.rb
220
+ - lib/i18n_checker/not_found/reporter.rb
221
+ - lib/i18n_checker/not_found/reporter/base.rb
222
+ - lib/i18n_checker/not_found/reporter/default.rb
223
+ - lib/i18n_checker/not_found/result.rb
224
+ - lib/i18n_checker/not_found/text.rb
189
225
  - lib/i18n_checker/rake_task.rb
190
- - lib/i18n_checker/rake_task/locale_check.rb
191
- - lib/i18n_checker/reporter.rb
192
- - lib/i18n_checker/reporter/default_reporter.rb
193
- - lib/i18n_checker/reporter/detect_result_reporter.rb
226
+ - lib/i18n_checker/rake_task/check.rb
227
+ - lib/i18n_checker/rake_task/clean.rb
228
+ - lib/i18n_checker/unused/detector.rb
229
+ - lib/i18n_checker/unused/reporter.rb
230
+ - lib/i18n_checker/unused/reporter/base.rb
231
+ - lib/i18n_checker/unused/reporter/default.rb
232
+ - lib/i18n_checker/unused/result.rb
233
+ - lib/i18n_checker/unused/text.rb
194
234
  - lib/i18n_checker/version.rb
195
235
  - screenshot.png
196
236
  homepage: https://github.com/holyshared/i18n-checker
197
237
  licenses:
198
238
  - MIT
199
- metadata: {}
239
+ metadata:
240
+ yard.run: yri
200
241
  post_install_message:
201
242
  rdoc_options: []
202
243
  require_paths:
@@ -1,20 +0,0 @@
1
- require 'i18n_checker/detector/locale_text_not_found'
2
- require 'i18n_checker/detector/text_result'
3
- require 'i18n_checker/detector/detected_result'
4
-
5
- module I18nChecker
6
- class LocaleTextNotFoundChecker
7
- def initialize(locale_file_paths: [], source_paths: [], reporter:)
8
- @reporter = reporter
9
- @locale_texts = I18nChecker::Locale.texts_of(source_paths)
10
- @locale_files = I18nChecker::Locale.load_of(locale_file_paths)
11
- end
12
-
13
- def check
14
- not_found_detector = I18nChecker::Detector::LocaleTextNotFound.new(@locale_files)
15
- not_found_result = @locale_texts.detect(not_found_detector)
16
- @reporter.report not_found_result
17
- yield not_found_result if block_given?
18
- end
19
- end
20
- end
@@ -1,28 +0,0 @@
1
- require 'colorator'
2
-
3
- module I18nChecker
4
- module Reporter
5
- class DefaultReporter < DetectResultReporter
6
- CHECK_COMPLETED = 'Translation text checking is complete.'.freeze
7
-
8
- def report(result)
9
- return passed if result.empty?
10
- failed(result)
11
- end
12
-
13
- def passed
14
- logger.info CHECK_COMPLETED.green
15
- logger.info 'There was no translated text that can not be referenced'.green
16
- end
17
-
18
- def failed(result)
19
- logger.info CHECK_COMPLETED.red
20
- logger.info "There are settings where translated text can not be found\n".red
21
- result.locale_texts.each do |locale_text|
22
- logger.info locale_text.file.cyan.to_s
23
- logger.info " line:#{locale_text.line}, column:#{locale_text.column} - #{locale_text.lang}.#{locale_text.text}"
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,15 +0,0 @@
1
- require 'logger'
2
-
3
- module I18nChecker
4
- module Reporter
5
- class DetectResultReporter
6
- def initialize(logger: Logger.new(STDOUT))
7
- @logger = logger
8
- end
9
-
10
- private
11
-
12
- attr_reader :logger
13
- end
14
- end
15
- end
@@ -1,7 +0,0 @@
1
- require 'i18n_checker/reporter/detect_result_reporter'
2
- require 'i18n_checker/reporter/default_reporter'
3
-
4
- module I18nChecker
5
- module Reporter
6
- end
7
- end