missing_t 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg
2
+ doc
3
+ Manifest
data/CHANGELOG ADDED
@@ -0,0 +1,5 @@
1
+ v0.1.2 Extraction of I18n messages became better (will now correctly extract messages with dynamic keys, like "myapp.title.#{key}"). Added colorization of output.
2
+
3
+ v0.1.1 Remove dependencies to ruby-debug and pp.
4
+
5
+ v0.1.0 I am alive!
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Balint Erdi (balint.erdi@gmail.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,43 @@
1
+ # Missing T
2
+
3
+ Missing T provides an easy way to see which internationalized messages lack their translations in a ruby project that uses I18n (e.g Rails apps). Instead of going through the translation files manually, you just call Missing T which gives you a list of all missing translation strings. By default it searches for all languages that you have translation files for. If you given it an option it will only search for translations in that language.
4
+
5
+ ## Installation
6
+
7
+ Missing T comes packaged as a gem, so you install it via the normal procedure:
8
+
9
+ $ gem install missing_t
10
+
11
+ Also, if you prefer to use it as a plugin to Rails project, you can simply do the following:
12
+
13
+ $ ./script/plugin install git://github.com/balinterdi/missing_t.git
14
+
15
+ ## Running
16
+
17
+ To find all the messages without translations, you have to be in your project directory and then launch missing_t in the most simple way imaginable:
18
+
19
+ $ missing_t
20
+
21
+ You should see all messages that don't have translations on the screen, broken down per file, e.g:
22
+
23
+ app/views/users/new.html.erb:
24
+ fr.users.name
25
+ fr.users.city_of_residence
26
+ es.users.age
27
+
28
+ app/helpers/user_helper.rb:
29
+ fr.users.travels
30
+
31
+ __NOTE__ If no language code is provided, the script will determine which languages need to have translations by gathering all language codes in the localization files and assuming that if there is at least one translation defined for a language then all translations should be defined for it.
32
+
33
+ If you wish to see all the lacking translations for a certain language, just provide its language code as a parameter:
34
+
35
+ $ missing_t fr
36
+
37
+ ## Epilogue
38
+
39
+ That's all about it, let me know if you find any bugs or have suggestions as to what else should the script do. If you wish you can directly contact me at balint.erdi@gmail.com.
40
+
41
+ [http://github.com/balinterdi/missing_t/](http://github.com/balinterdi/missing_t/)
42
+
43
+ Copyright (c) 2009 Balint Erdi, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gemspec|
6
+ gemspec.name = "missing_t"
7
+ gemspec.summary = "See all the missing I18n translations in your Rails project"
8
+ gemspec.description = <<-EOF
9
+ With missing_t you can easily find all the missing i18n translations in your Rails project.
10
+ EOF
11
+ gemspec.email = "balint.erdi@gmail.com"
12
+ gemspec.homepage = "http://github.com/balinterdi/missing_t"
13
+ gemspec.authors = ["Balint Erdi"]
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
19
+
20
+ task :default => :spec
21
+
22
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
data/bin/missing_t ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
4
+
5
+ require 'missing_t'
6
+
7
+ @missing_t = MissingT.new
8
+
9
+ @missing_t = MissingT.new
10
+ @missing_t.instance_eval do
11
+ parse_options(ARGV)
12
+ find_missing_translations(ARGV[0]).each do |file, queries|
13
+ puts
14
+ puts "#{file}:"
15
+ puts
16
+ queries.each { |q| puts " #{red(q)}" }
17
+ end
18
+ end
19
+
data/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ # this will make it possible to install missing_t
2
+ # as a plugin for a Rails project
3
+ # (from http://railscasts.com/episodes/135-making-a-gem)
4
+ require "missing_t"
data/lib/missing_t.rb ADDED
@@ -0,0 +1,206 @@
1
+ require "yaml"
2
+ require "optparse"
3
+ require "ostruct"
4
+ require "forwardable"
5
+
6
+ class Hash
7
+ def has_nested_key?(key)
8
+ h = self
9
+ key.to_s.split('.').each do |segment|
10
+ return false unless h.key?(segment)
11
+ h = h[segment]
12
+ end
13
+ true
14
+ end
15
+
16
+ # idea snatched from deep_merge in Rails source code
17
+ def deep_safe_merge(other_hash)
18
+ self.merge(other_hash) do |key, oldval, newval|
19
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
20
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
21
+ if oldval.class.to_s == 'Hash'
22
+ if newval.class.to_s == 'Hash'
23
+ oldval.deep_safe_merge(newval)
24
+ else
25
+ oldval
26
+ end
27
+ else
28
+ newval
29
+ end
30
+ end
31
+ end
32
+
33
+ def deep_safe_merge!(other_hash)
34
+ replace(deep_safe_merge(other_hash))
35
+ end
36
+
37
+ end
38
+
39
+ module Helpers
40
+ # snatched from rspec source
41
+ def colour(text, colour_code)
42
+ "#{colour_code}#{text}\e[0m"
43
+ end
44
+
45
+ def green(text); colour(text, "\e[32m"); end
46
+ def red(text); colour(text, "\e[31m"); end
47
+ def magenta(text); colour(text, "\e[35m"); end
48
+ def yellow(text); colour(text, "\e[33m"); end
49
+ def blue(text); colour(text, "\e[34m"); end
50
+
51
+ end
52
+
53
+ class MissingT
54
+ include Helpers
55
+ extend Forwardable
56
+ def_delegators :@translations, :[]
57
+
58
+ # attr_reader :translations
59
+
60
+ def initialize
61
+ @translations = Hash.new
62
+ end
63
+
64
+ def parse_options(args)
65
+ @options = OpenStruct.new
66
+ @options.prefix = nil
67
+ opts = OptionParser.new do |opts|
68
+ opts.on("-f", "--file FILE_OR_DIR",
69
+ "look for missing translations in files under FILE_OR_DIR",
70
+ "(if a file is given, only look in that file)") do |path|
71
+ @options.path = path
72
+ end
73
+ end
74
+
75
+ opts.on_tail("-h", "--help", "Show this message") do
76
+ puts opts
77
+ exit
78
+ end
79
+
80
+ opts.on_tail("--version", "Show version") do
81
+ puts "0.1.2"
82
+ exit
83
+ end
84
+
85
+ opts.parse!(args)
86
+ end
87
+
88
+ # NOTE: this method is needed
89
+ # because attr_reader :translations
90
+ # does not seem to be stubbable
91
+ def translations
92
+ @translations
93
+ end
94
+
95
+ def add_translations(trs)
96
+ translations.deep_safe_merge!(trs)
97
+ end
98
+
99
+ def collect_translations
100
+ locales_pathes = ["config/locales/**/*.yml", "vendor/plugins/**/config/locales/**/*yml", "vendor/plugins/**/locale/**/*yml"]
101
+ locales_pathes.each do |path|
102
+ Dir.glob(path) do |file|
103
+ add_translations(translations_in_file(file))
104
+ end
105
+ end
106
+ end
107
+
108
+ def hashify(strings)
109
+ h = Hash.new
110
+ strings.map { |s| s.split('.') }.
111
+ each do |segmented_string|
112
+ root = h
113
+ segmented_string.each do |segment|
114
+ root[segment] ||= {}
115
+ root = root[segment]
116
+ end
117
+ end
118
+ h
119
+ end
120
+
121
+ def translations_in_file(yaml_file)
122
+ open(yaml_file) { |f| YAML.load(f.read) }
123
+ end
124
+
125
+ def files_with_i18n_queries
126
+ if path = @options.path
127
+ path = path[0...-1] if path[-1..-1] == '/'
128
+ [ Dir.glob("#{path}/**/*.erb"), Dir.glob("#{path}/**/*.rb") ]
129
+ else
130
+ [ Dir.glob("app/**/*.erb"),
131
+ Dir.glob("app/**/controllers/**/*.rb"),
132
+ Dir.glob("app/**/helpers/**/*.rb")]
133
+ end.flatten
134
+ end
135
+
136
+ def get_content_of_file_with_i18n_queries(file)
137
+ f = open(File.expand_path(file), "r")
138
+ content = f.read()
139
+ f.close()
140
+ content
141
+ end
142
+
143
+ def extract_i18n_queries(file)
144
+ i18n_query_pattern = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s*\((.*?)[,\)]/
145
+ i18n_query_no_parens_pattern = /[^\w]+(?:I18n\.translate|I18n\.t|translate|t)\s+(['"])(.*?)\1/
146
+ file_content = get_content_of_file_with_i18n_queries(file)
147
+ file_content.scan(i18n_query_pattern).map { |match| match.first.gsub(/['"\s]/, '') }.
148
+ concat(file_content.scan(i18n_query_no_parens_pattern).map { |match| match[1].gsub(/['"\s]/, '') })
149
+ end
150
+
151
+ def collect_translation_queries
152
+ queries = {}
153
+ files_with_i18n_queries.each do |file|
154
+ queries_in_file = extract_i18n_queries(file)
155
+ unless queries_in_file.empty?
156
+ queries[file] = queries_in_file
157
+ end
158
+ end
159
+ queries
160
+ #TODO: remove duplicate queries across files
161
+ end
162
+
163
+ def has_translation?(lang, query)
164
+ t = translations
165
+ i18n_label(lang, query).split('.').each do |segment|
166
+ return false unless segment =~ /#\{.*\}/ or (t.respond_to?(:key?) and t.key?(segment))
167
+ t = t[segment]
168
+ end
169
+ true
170
+ end
171
+
172
+ def get_missing_translations(queries, lang=nil)
173
+ missing = {}
174
+ languages = lang.nil? ? translations.keys : [lang]
175
+ languages.each do |l|
176
+ get_missing_translations_for_lang(queries, l).each do |file, qs|
177
+ missing[file] ||= []
178
+ missing[file].concat(qs).uniq!
179
+ end
180
+ end
181
+ missing
182
+ end
183
+
184
+ def find_missing_translations(lang=nil)
185
+ collect_translations
186
+ get_missing_translations(collect_translation_queries, lang)
187
+ end
188
+
189
+ private
190
+ def get_missing_translations_for_lang(queries, lang)
191
+ queries.map do |file, queries_in_file|
192
+ queries_with_no_translation = queries_in_file.select { |q| !has_translation?(lang, q) }
193
+ if queries_with_no_translation.empty?
194
+ nil
195
+ else
196
+ [file, queries_with_no_translation.map { |q| i18n_label(lang, q) }]
197
+ end
198
+ end.compact
199
+
200
+ end
201
+
202
+ def i18n_label(lang, query)
203
+ "#{lang}.#{query}"
204
+ end
205
+
206
+ end
data/missing_t.gemspec ADDED
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{missing_t}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Balint Erdi"]
12
+ s.date = %q{2010-09-11}
13
+ s.default_executable = %q{missing_t}
14
+ s.description = %q{ With missing_t you can easily find all the missing i18n translations in your Rails project.
15
+ }
16
+ s.email = %q{balint.erdi@gmail.com}
17
+ s.executables = ["missing_t"]
18
+ s.extra_rdoc_files = [
19
+ "README.markdown"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "CHANGELOG",
24
+ "MIT-LICENSE",
25
+ "README.markdown",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/missing_t",
29
+ "init.rb",
30
+ "lib/missing_t.rb",
31
+ "missing_t.gemspec",
32
+ "spec/missing_t_spec.rb",
33
+ "spec/spec_helper.rb",
34
+ "tasks/missing_t.rake",
35
+ "todos.markdown"
36
+ ]
37
+ s.homepage = %q{http://github.com/balinterdi/missing_t}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.7}
41
+ s.summary = %q{See all the missing I18n translations in your Rails project}
42
+ s.test_files = [
43
+ "spec/missing_t_spec.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ else
53
+ end
54
+ else
55
+ end
56
+ end
57
+
@@ -0,0 +1,217 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ require "mocha"
4
+
5
+ require File.join(File.dirname(__FILE__), 'spec_helper')
6
+
7
+ # use mocha for mocking instead of
8
+ # Rspec's own mock framework
9
+ Spec::Runner.configure do |config|
10
+ config.mock_with :mocha
11
+ end
12
+
13
+ describe "MissingT" do
14
+ before do
15
+ @missing_t = MissingT.new
16
+ @es_translations = {"es"=>
17
+ {"zoo"=>{"elephant"=>"elefante", "bear"=>"oso", "lion"=>"leon", "bee" => "abeja"},
18
+ "lamp"=>"lampa",
19
+ "book"=>"libro",
20
+ "handkerchief"=>"panuelo",
21
+ "pen" => "boli"}}
22
+ @fr_translations = {"fr"=>
23
+ {"zoo"=>{"elephant"=>"elephant", "bear"=>"ours", "lion"=>"lion", "wasp" => "guepe"},
24
+ "lamp"=>"lampe",
25
+ "book"=>"livre",
26
+ "handkerchief"=>"mouchoir",
27
+ "mother" => "mere"}}
28
+
29
+ @other_es_translations = { "es" => {"zoo" => {}}}
30
+ @yet_other_es_translations = { "es" => {"zoo" => {"monkey" => "mono", "horse" => "caballo"}}}
31
+ end
32
+
33
+ describe "adding translations" do
34
+ before do
35
+ @missing_t.add_translations(@es_translations)
36
+ end
37
+
38
+ it "should pick up the new translations" do
39
+ @missing_t.translations.should == @es_translations
40
+ end
41
+
42
+ it "should correctly merge different translations" do
43
+ @missing_t.add_translations(@fr_translations)
44
+ @missing_t["fr"]["zoo"].should have_key("wasp")
45
+ @missing_t["fr"].should have_key("mother")
46
+ @missing_t["es"]["zoo"].should have_key("bee")
47
+ end
48
+
49
+ it "should not overwrite translations keys" do
50
+ @missing_t.add_translations(@other_es_translations)
51
+ @missing_t["es"]["zoo"].should have_key("bear")
52
+ @missing_t["es"]["zoo"].should have_key("bee")
53
+ end
54
+
55
+ it "should add the new translations even if they contain keys already in the translations hash" do
56
+ @missing_t.add_translations(@yet_other_es_translations)
57
+ @missing_t["es"]["zoo"].should have_key("monkey")
58
+ @missing_t["es"]["zoo"].should have_key("bear")
59
+ end
60
+
61
+ end
62
+
63
+ describe "hashification" do
64
+ before do
65
+ queries = ["zoo.bee", "zoo.departments.food", "zoo.departments.qa", "lamp", "mother", "mother.maiden_name"]
66
+ @queries_hash = @missing_t.hashify(queries)
67
+ @h = { "fr" => { "book" => "livre", "zoo" => {"elephant" => "elephant"} } }
68
+ end
69
+
70
+ it "should find a nested key and return it" do
71
+ @h.should have_nested_key('fr.zoo.elephant')
72
+ @h.should have_nested_key('fr.book')
73
+ end
74
+
75
+ it "should return false when it does not have a nested key" do
76
+ @h.should_not have_nested_key('fr.zoo.seal')
77
+ @h.should_not have_nested_key('xxx')
78
+ end
79
+
80
+ it "an empty hash should not have any nested keys" do
81
+ {}.should_not have_nested_key(:puppy)
82
+ end
83
+
84
+ it "should turn strings to hash keys along their separators (dots)" do
85
+ ["zoo", "lamp", "mother"].all? { |k| @queries_hash.key?(k) }.should == true
86
+ ["bee", "departments"].all? { |k| @queries_hash["zoo"].key?(k) }.should == true
87
+ @queries_hash["zoo"]["departments"].should have_key("food")
88
+ @queries_hash["zoo"]["departments"].should have_key("qa")
89
+ end
90
+ end
91
+
92
+ describe "the i18n query extracion" do
93
+ before do
94
+ metaclass = class << @missing_t; self; end
95
+ metaclass.instance_eval do
96
+ define_method :get_content_of_file_with_i18n_queries do |content|
97
+ content
98
+ end
99
+ end
100
+ end
101
+
102
+ it "should correctly extract the I18n.t type of messages" do
103
+ content = <<-EOS
104
+ <div class="title_gray"><span><%= I18n.t("anetcom.member.projects.new.page_title") %></span></div>
105
+ EOS
106
+ @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
107
+ end
108
+
109
+ it "should correctly extract the I18n.t type of messages not right after the <%= mark" do
110
+ content = <<-EOS
111
+ <%= submit_tag I18n.t('anetcom.member.projects.new.create_project'), :class => 'button' %>
112
+ EOS
113
+ @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.create_project"]
114
+ end
115
+
116
+ it "should correctly extract the I18n.t type of messages from a link_to" do
117
+ # honestly, I am not sure anymore why this qualifies as a sep. test case
118
+ # but I am sure there was something special about this one :)
119
+ content = <<-EOS
120
+ <%= link_to I18n.t("tog_headlines.admin.publish"), publish_admin_headlines_story_path(story), :class => 'button' %>
121
+ EOS
122
+ @missing_t.extract_i18n_queries(content).should == ["tog_headlines.admin.publish"]
123
+ end
124
+
125
+ it "should correctly extract the I18n.t type of messages with an argument in the message" do
126
+ content = <<-EOS
127
+ :html => {:title => I18n.t("tog_social.sharing.share_with", :name => shared.name)}
128
+ EOS
129
+ @missing_t.extract_i18n_queries(content).should == ["tog_social.sharing.share_with"]
130
+ end
131
+
132
+ it "should correctly extract the I18n.translate type of messages" do
133
+ content = <<-EOS
134
+ <div class="title_gray"><span><%= I18n.translate("anetcom.member.projects.new.page_title") %></span></div>
135
+ EOS
136
+ @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
137
+ end
138
+
139
+ it "should correctly extract the t type of messages" do
140
+ content = <<-EOS
141
+ <div class="title_gray"><span><%= t("anetcom.member.projects.new.page_title") %></span></div>
142
+ EOS
143
+ @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
144
+ end
145
+
146
+ it "should find several messages on the same line" do
147
+ content = <<-EOS
148
+ <div class="title_gray"><span><%= t("anetcom.member.projects.new.page_title") %></span><span>t("anetcom.member.projects.new.page_size")</span></div>
149
+ EOS
150
+ @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title", "anetcom.member.projects.new.page_size"]
151
+ end
152
+
153
+ it "should find messages with a parens-less call" do
154
+ content = <<-EOS
155
+ <div class="title_gray"><span><%= t "anetcom.member.projects.new.page_title" %></span></div>
156
+ EOS
157
+ @missing_t.extract_i18n_queries(content).should == ["anetcom.member.projects.new.page_title"]
158
+ end
159
+
160
+ it "should not extract a function call that just ends in t" do
161
+ content = <<-EOS
162
+ <div class="title_gray"><span><%= at(3) %></span></div>
163
+ EOS
164
+ @missing_t.extract_i18n_queries(content).should == []
165
+ end
166
+
167
+ it "should find and correctly extract a dynamic key translation message" do
168
+ # @missing_t.stubs(:get_content_of_file_with_i18n_queries).returns(content)
169
+ content = %q(<div class="title_gray"><span><%= I18n.t("mycompany.welcome.#{key}") %></span></div>)
170
+ @missing_t.extract_i18n_queries(content).should == [%q(mycompany.welcome.#{key})]
171
+ end
172
+
173
+ end
174
+
175
+ describe "finding missing translations" do
176
+ before do
177
+ @t_queries = { :fake_file => ["mother", "zoo.bee", "zoo.wasp", "pen"] }
178
+ @missing_t.stubs(:translations).returns(@fr_translations.merge(@es_translations))
179
+ # @missing_t.stubs(:collect_translation_queries).returns(@t_queries)
180
+ end
181
+
182
+ it "should return true if it has a translation given in the I18n form" do
183
+ @missing_t.has_translation?("fr", "zoo.wasp").should == true
184
+ @missing_t.has_translation?("es", "pen").should == true
185
+ end
186
+
187
+ it "should return false if it does not have a translation given in the I18n form" do
188
+ @missing_t.has_translation?("fr", "zoo.bee").should == false
189
+ @missing_t.has_translation?("es", "mother").should == false
190
+ end
191
+
192
+ describe "of dynamic message strings" do
193
+ it "should return true if it has a translation that matches the fix parts" do
194
+ @missing_t.has_translation?("fr", %q(zoo.#{animal})).should == true
195
+ end
196
+
197
+ it "should return false if it does not have a translation that matches all the fix parts" do
198
+ @missing_t.has_translation?("fr", %q(household.#{animal})).should == false
199
+ end
200
+ end
201
+
202
+ it "should correctly get missing translations for a spec. language" do
203
+ miss_entries = @missing_t.get_missing_translations(@t_queries, "fr").map{ |e| e[1] }.flatten
204
+ miss_entries.should include("fr.pen")
205
+ miss_entries.should include("fr.zoo.bee")
206
+ end
207
+
208
+ it "should correctly get missing translations" do
209
+ miss_entries = @missing_t.get_missing_translations(@t_queries).map{ |e| e[1] }.flatten
210
+ miss_entries.should include("fr.zoo.bee")
211
+ miss_entries.should include("fr.pen")
212
+ miss_entries.should include("es.zoo.wasp")
213
+ miss_entries.should include("es.mother")
214
+ end
215
+ end
216
+
217
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "..", "lib", "missing_t")
@@ -0,0 +1,6 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ desc "Run all specs"
4
+ Spec::Rake::SpecTask.new('spec') do |t|
5
+ t.spec_files = FileList['spec/**/*spec.rb']
6
+ end
data/todos.markdown ADDED
@@ -0,0 +1,8 @@
1
+ DONE
2
+ ----
3
+
4
+ * for message strings with dynamic parts, check if there is any translation that matches the non-dynamic part. Only output the message if none found. E.g
5
+
6
+ user.friendships.make.#{action}
7
+
8
+ will output user.friendships.make.#{action} if there are no translation strings that match user.friendships.make. (no matter what comes after the make.)
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: missing_t
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
+ platform: ruby
12
+ authors:
13
+ - Balint Erdi
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-11 00:00:00 +02:00
19
+ default_executable: missing_t
20
+ dependencies: []
21
+
22
+ description: " With missing_t you can easily find all the missing i18n translations in your Rails project.\n"
23
+ email: balint.erdi@gmail.com
24
+ executables:
25
+ - missing_t
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.markdown
30
+ files:
31
+ - .gitignore
32
+ - CHANGELOG
33
+ - MIT-LICENSE
34
+ - README.markdown
35
+ - Rakefile
36
+ - VERSION
37
+ - bin/missing_t
38
+ - init.rb
39
+ - lib/missing_t.rb
40
+ - missing_t.gemspec
41
+ - spec/missing_t_spec.rb
42
+ - spec/spec_helper.rb
43
+ - tasks/missing_t.rake
44
+ - todos.markdown
45
+ has_rdoc: true
46
+ homepage: http://github.com/balinterdi/missing_t
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.7
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: See all the missing I18n translations in your Rails project
79
+ test_files:
80
+ - spec/missing_t_spec.rb
81
+ - spec/spec_helper.rb