missing_t 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- missing_t (0.4.0)
4
+ missing_t (0.4.1)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/lib/missing_t.rb CHANGED
@@ -1,19 +1,24 @@
1
1
  require "yaml"
2
2
 
3
3
  #TODO: Should I feel about these 'global' helper functions?
4
- def hashify(strings)
5
- strings.map { |s| s.split('.') }.each_with_object({}) do |segmented_string, h|
6
- segmented_string.each do |segment|
7
- h[segment] ||= {}
8
- h = h[segment]
9
- end
4
+ def hashify(segments, value)
5
+ return {} if segments.empty?
6
+ s, *rest = segments
7
+ if rest.empty?
8
+ { s => value }
9
+ else
10
+ { s => hashify(rest, value) }
10
11
  end
11
12
  end
12
13
 
13
14
  def print_hash(h, level)
14
15
  h.each_pair do |k,v|
15
- puts %(#{" " * (level*2)}#{k}:)
16
- print_hash(v, level+1)
16
+ if v.respond_to?(:each_pair)
17
+ puts %(#{" " * (level*2)}#{k}:)
18
+ print_hash(v, level+1)
19
+ else
20
+ puts %(#{" " * (level*2)}#{k}: #{v})
21
+ end
17
22
  end
18
23
  end
19
24
 
@@ -23,8 +28,8 @@ class Hash
23
28
  self.merge(other_hash) do |key, oldval, newval|
24
29
  oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
25
30
  newval = newval.to_hash if newval.respond_to?(:to_hash)
26
- if oldval === Hash
27
- if newval === Hash
31
+ if oldval.is_a? Hash
32
+ if newval.is_a? Hash
28
33
  oldval.deep_safe_merge(newval)
29
34
  else
30
35
  oldval
@@ -45,13 +50,13 @@ class MissingT
45
50
 
46
51
  class FileReader
47
52
  def read(file)
48
- open(File.expand_path(file), "r") do |f|
49
- yield f.read
53
+ IO.readlines(file).each do |line|
54
+ yield line
50
55
  end
51
56
  end
52
57
  end
53
58
 
54
- VERSION = "0.4.0"
59
+ VERSION = "0.4.1"
55
60
 
56
61
  def initialize(options={})
57
62
  @reader = options.fetch(:reader, FileReader.new)
@@ -60,11 +65,11 @@ class MissingT
60
65
  end
61
66
 
62
67
  def run
63
- missing_translations = collect
64
- missing_message_strings = missing_translations.values.map { |ms| hashify(ms) }
65
-
66
- missing = missing_message_strings.each_with_object({}) do |h, all_message_strings|
67
- all_message_strings.deep_safe_merge!(h)
68
+ missing = {}
69
+ collect_missing.each do |file, message_strings|
70
+ message_strings.each do |message_string, value|
71
+ missing.deep_safe_merge! hashify(message_string.split('.'), value)
72
+ end
68
73
  end
69
74
 
70
75
  missing.each do |language, missing_for_language|
@@ -74,7 +79,7 @@ class MissingT
74
79
  end
75
80
  end
76
81
 
77
- def collect
82
+ def collect_missing
78
83
  ts = translation_keys
79
84
  #TODO: If no translation keys were found and the languages were not given explicitly
80
85
  # issue a warning and bail out
@@ -84,9 +89,9 @@ class MissingT
84
89
 
85
90
  def get_missing_translations(keys, queries, languages)
86
91
  languages.each_with_object({}) do |lang, missing|
87
- get_missing_translations_for_lang(keys, queries, lang).each do |file, queries|
88
- missing[file] ||= []
89
- missing[file].concat(queries).uniq!
92
+ get_missing_translations_for_language(keys, queries, lang).each do |file, queries_for_language|
93
+ missing[file] ||= {}
94
+ missing[file].merge!(queries_for_language)
90
95
  end
91
96
  end
92
97
  end
@@ -144,30 +149,59 @@ class MissingT
144
149
  end
145
150
 
146
151
  def extract_i18n_queries(file)
147
- i18n_query_pattern = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s*\((.*?)[,\)]/
148
- i18n_query_no_parens_pattern = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s+(['"])(.*?)\1/
149
-
150
- @reader.read(File.expand_path(file)) do |content|
151
- ([]).tap do |i18n_message_strings|
152
- i18n_message_strings.concat content.scan(i18n_query_pattern).map { |match| match[0].gsub(/['"\s]/, '') }
153
- i18n_message_strings.concat content.scan(i18n_query_no_parens_pattern).map { |match| match[1].gsub(/['"\s]/, '') }
152
+ ({}).tap do |queries|
153
+ @reader.read(File.expand_path(file)) do |line|
154
+ qs = scan_line(line)
155
+ queries.merge!(qs)
154
156
  end
155
157
  end
156
158
  end
157
159
 
158
160
  private
159
161
 
160
- def get_missing_translations_for_lang(keys, queries, lang)
161
- queries.map do |file, queries_in_file|
162
- queries_with_no_translation = queries_in_file.reject { |q| has_translation?(keys, lang, q) }
162
+ def get_missing_translations_for_language(keys, queries, l)
163
+ queries.each_with_object({}) do |(file, queries_in_file), missing_translations|
164
+ queries_with_no_translation = queries_in_file.reject { |q, _| has_translation?(keys, l, q) }
163
165
  if queries_with_no_translation.any?
164
- [file, queries_with_no_translation.map { |q| i18n_label(lang, q) }]
166
+ missing_translations[file] = add_langauge_prefix(queries_with_no_translation, l)
165
167
  end
166
- end.compact
168
+ end
169
+ end
170
+
171
+ def add_langauge_prefix(qs, l)
172
+ qs.each_with_object({}) do |(q, v), with_prefix|
173
+ with_prefix["#{l}.#{q}"] = v
174
+ end
167
175
  end
168
176
 
169
177
  def i18n_label(lang, query)
170
178
  "#{lang}.#{query}"
171
179
  end
172
180
 
181
+ def scan_line(line)
182
+ with_parens = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s*\((['"](.*?)['"].*?)\)/
183
+ no_parens = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s+(['"](.*?)['"].*?)/
184
+ [with_parens, no_parens].each_with_object({}) do |pattern, extracted_queries|
185
+ line.scan(pattern).each do |m|
186
+ if m.any?
187
+ message_string = m[1]
188
+ _, *options = m[0].split(',')
189
+ extracted_queries[message_string] = extract_default_value(options)
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ def extract_default_value(message_string_options)
196
+ [/:default\s*=>\s*['"](.*)['"]/, /default:\s*['"](.*)['"]/].each do |default_extractor|
197
+ message_string_options.each do |option|
198
+ if default_key_match=default_extractor.match(option)
199
+ return default_key_match[1]
200
+ end
201
+ end
202
+ end
203
+ ''
204
+ end
205
+
206
+
173
207
  end
@@ -3,10 +3,15 @@ require_relative '../spec_helper'
3
3
  describe "MissingT" do
4
4
  describe "correctly finds all missing translations" do
5
5
  m = MissingT.new({ languages: ["en"], path: "spec/support/new.html.erb" })
6
- m.collect['spec/support/new.html.erb'].should =~ [
7
- "en.flights.new.new_flight", "en.flights.new.name", "en.flights.new.capacity",
8
- "en.flights.new.duration", "en.flights.new.from", "en.flights.new.to",
9
- "en.flights.new.create", "en.flights.new.back"
10
- ]
6
+ m.collect_missing['spec/support/new.html.erb'].should == {
7
+ "en.flights.new.new_flight" => "",
8
+ "en.flights.new.name" => "Name",
9
+ "en.flights.new.capacity" => "Capacity",
10
+ "en.flights.new.duration" => "Duration",
11
+ "en.flights.new.from" => "From",
12
+ "en.flights.new.to" => "",
13
+ "en.flights.new.create" => "Create",
14
+ "en.flights.new.back" => "Back"
15
+ }
11
16
  end
12
17
  end
@@ -32,25 +32,25 @@ describe "MissingT" do
32
32
  content = <<-EOS
33
33
  <div class="title_gray"><span><%= I18n.t("anetcom.member.projects.new.page_title") %></span></div>
34
34
  EOS
35
- @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
35
+ @missing_t.extract_i18n_queries(content).should == {"anetcom.member.projects.new.page_title" => ""}
36
36
  end
37
37
  it "should correctly extract the key not right after the <%= mark" do
38
38
  content = <<-EOS
39
39
  <%= submit_tag I18n.t('anetcom.member.projects.new.create_project'), :class => 'button' %>
40
40
  EOS
41
- @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.create_project"]
41
+ @missing_t.extract_i18n_queries(content).should == {"anetcom.member.projects.new.create_project" => ""}
42
42
  end
43
43
 
44
44
  it "should correctly extract the key when there is an argument in the call" do
45
45
  content = <<-EOS
46
46
  :html => {:title => I18n.t("tog_social.sharing.share_with", :name => shared.name)}
47
47
  EOS
48
- @missing_t.extract_i18n_queries(content).should == ["tog_social.sharing.share_with"]
48
+ @missing_t.extract_i18n_queries(content).should == {"tog_social.sharing.share_with" => ""}
49
49
  end
50
50
 
51
51
  it "should find and correctly extract a dynamic key translation message" do
52
52
  content = %q(<div class="title_gray"><span><%= I18n.t("mycompany.welcome.#{key}") %></span></div>)
53
- @missing_t.extract_i18n_queries(content).should == [%q(mycompany.welcome.#{key})]
53
+ @missing_t.extract_i18n_queries(content).should == {%q(mycompany.welcome.#{key}) => ""}
54
54
  end
55
55
  end
56
56
 
@@ -59,21 +59,21 @@ describe "MissingT" do
59
59
  content = <<-EOS
60
60
  <div class="title_gray"><span><%= t("anetcom.member.projects.new.page_title") %></span></div>
61
61
  EOS
62
- @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
62
+ @missing_t.extract_i18n_queries(content).should == {"anetcom.member.projects.new.page_title" => ""}
63
63
  end
64
64
 
65
65
  it "should find several messages on the same line" do
66
66
  content = <<-EOS
67
- <div class="title_gray"><span><%= t("anetcom.member.projects.new.page_title") %></span><span>t("anetcom.member.projects.new.page_size")</span></div>
67
+ <div class="title_gray"><span><%= t("anetcom.member.projects.new.page_title") %></span><span>t("anetcom.member.projects.new.page_size")</span></div>
68
68
  EOS
69
- @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title", "anetcom.member.projects.new.page_size"]
69
+ @missing_t.extract_i18n_queries(content).should == {"anetcom.member.projects.new.page_title" => "", "anetcom.member.projects.new.page_size" => ""}
70
70
  end
71
71
 
72
72
  it "should find messages with a parens-less call" do
73
73
  content = <<-EOS
74
74
  <div class="title_gray"><span><%= t "anetcom.member.projects.new.page_title" %></span></div>
75
75
  EOS
76
- @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
76
+ @missing_t.extract_i18n_queries(content).should == {"anetcom.member.projects.new.page_title" => ""}
77
77
  end
78
78
  end
79
79
 
@@ -81,14 +81,14 @@ describe "MissingT" do
81
81
  content = <<-EOS
82
82
  <div class="title_gray"><span><%= I18n.translate("anetcom.member.projects.new.page_title") %></span></div>
83
83
  EOS
84
- @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
84
+ @missing_t.extract_i18n_queries(content).should == {"anetcom.member.projects.new.page_title" => ""}
85
85
  end
86
86
 
87
87
  it "should not extract a function call that just ends in t" do
88
88
  content = <<-EOS
89
89
  <div class="title_gray"><span><%= at(3) %></span></div>
90
90
  EOS
91
- @missing_t.extract_i18n_queries(content).should == []
91
+ @missing_t.extract_i18n_queries(content).should == {}
92
92
  end
93
93
 
94
94
  end
@@ -1,18 +1,18 @@
1
- <h1><%= I18n.t("flights.new.new_flight", :default => "New flight") %></h1>
1
+ '<h1><%= I18n.t("flights.new.new_flight") %></h1>'
2
2
 
3
3
  <% form_for(@flight) do |f| %>
4
4
  <%= f.error_messages %>
5
5
 
6
6
  <p>
7
- <%= f.label I18n.t("flights.new.name", :default => "name") %><br />
7
+ <%= f.label I18n.t("flights.new.name", :default => "Name") %><br />
8
8
  <%= f.text_field :name %>
9
9
  </p>
10
10
  <p>
11
- <%= f.label I18n.t("flights.new.capacity", :default => "capacity") %><br />
11
+ <%= f.label I18n.t("flights.new.capacity", :default => "Capacity") %><br />
12
12
  <%= f.text_field :capacity %>
13
13
  </p>
14
14
  <p>
15
- <%= f.label I18n.t("flights.new.duration", :default => "duration") %><br />
15
+ <%= f.label I18n.t("flights.new.duration", :default => "Duration") %><br />
16
16
  <%= f.text_field :duration %>
17
17
  </p>
18
18
  <p>
@@ -20,7 +20,7 @@
20
20
  <%= f.select :from_id, @airport_options %>
21
21
  </p>
22
22
  <p>
23
- <%= f.label :to_id, I18n.t("flights.new.to", :default => "To") %><br />
23
+ <%= f.label :to_id, I18n.t("flights.new.to") %><br />
24
24
  <%= f.select :to_id, @airport_options %>
25
25
  </p>
26
26
  <p>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: missing_t
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-06 00:00:00.000000000 Z
12
+ date: 2013-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -152,7 +152,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
152
  version: '0'
153
153
  segments:
154
154
  - 0
155
- hash: 1881571199484440278
155
+ hash: -2158977663221811532
156
156
  required_rubygems_version: !ruby/object:Gem::Requirement
157
157
  none: false
158
158
  requirements:
@@ -161,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
161
  version: '0'
162
162
  segments:
163
163
  - 0
164
- hash: 1881571199484440278
164
+ hash: -2158977663221811532
165
165
  requirements: []
166
166
  rubyforge_project:
167
167
  rubygems_version: 1.8.23