missing_t 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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