translate-rails3-plus 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,45 +1,45 @@
1
- <%
2
- from_text = lookup(from_locale, key)
3
- to_text = lookup(to_locale, key)
4
- field_name = "key[#{key}]"
5
- %>
6
-
7
- <div class="translation">
8
- <% if from_text.present? %>
9
-
10
- <ol>
11
- <% from_text.each_with_index do |from_text_section, index| %>
12
- <%
13
- from_text_section = from_text_section.to_s
14
- line_size = 100
15
- n_lines = n_lines(from_text_section, line_size)
16
- # this is needed so the controller doesn't freak out when there is no translations found
17
- # for this element yet...
18
- to_text = Array.new if to_text.blank?
19
- %>
20
- <li class="single-translation">
21
- <p class="translation-text"><%= from_text_section %></p>
22
- <p class="edit-form" >
23
- <% if n_lines > 1 %>
24
- <%= text_area_tag("#{field_name}[#{index}]", to_text[index], :size => "#{line_size}x#{n_lines}", :id => "#{key}[#{index}]", :class=>'edit-field') %>
25
- <% else %>
26
- <%= text_field_tag("#{field_name}[#{index}]", to_text[index], :size => line_size, :id => "#{key}[#{index}]", :class=>'edit-field') %>
27
- <% end %>
28
- <%= translate_link("#{key}[#{index}]", from_text_section, @from_locale, @to_locale) %>
29
- </p>
30
- <div class="error-text"></div>
31
- </li>
32
- <% end %>
33
- </ol>
34
-
35
- <% end %>
36
- <p>
37
- <em>
38
- <br/>
39
- <strong>Key:</strong><%=h key %><br/>
40
- <% if @files[key] %>
41
- <strong>File:</strong><%= @files[key].join("<br/>") %>
42
- <% end %>
43
- </em>
44
- </p>
45
- </div>
1
+ <%
2
+ from_text = lookup(from_locale, key)
3
+ to_text = lookup(to_locale, key)
4
+ field_name = "key[#{key}]"
5
+ %>
6
+
7
+ <div class="translation">
8
+ <% if from_text.present? %>
9
+
10
+ <ol>
11
+ <% from_text.each_with_index do |from_text_section, index| %>
12
+ <%
13
+ from_text_section = from_text_section.to_s
14
+ line_size = 100
15
+ n_lines = n_lines(from_text_section, line_size)
16
+ # this is needed so the controller doesn't freak out when there is no translations found
17
+ # for this element yet...
18
+ to_text = Array.new if to_text.blank?
19
+ %>
20
+ <li class="single-translation">
21
+ <p class="translation-text"><%= from_text_section %></p>
22
+ <p class="edit-form" >
23
+ <% if n_lines > 1 %>
24
+ <%= text_area_tag("#{field_name}[#{index}]", to_text[index], :size => "#{line_size}x#{n_lines}", :id => "#{key}[#{index}]", :class=>'edit-field') %>
25
+ <% else %>
26
+ <%= text_field_tag("#{field_name}[#{index}]", to_text[index], :size => line_size, :id => "#{key}[#{index}]", :class=>'edit-field') %>
27
+ <% end %>
28
+ <%= translate_link("#{key}[#{index}]", from_text_section, @from_locale, @to_locale) %>
29
+ </p>
30
+ <div class="error-text"></div>
31
+ </li>
32
+ <% end %>
33
+ </ol>
34
+
35
+ <% end %>
36
+ <p>
37
+ <em>
38
+ <br/>
39
+ <strong>Key:</strong><%=h key %><br/>
40
+ <% if @files[key] %>
41
+ <strong>File:</strong><%= @files[key].join("<br/>") %>
42
+ <% end %>
43
+ </em>
44
+ </p>
45
+ </div>
@@ -1,24 +1,24 @@
1
- <%
2
- # Expects locals:
3
- #
4
- # total_entries
5
- # per_page
6
-
7
- n_pages = total_entries/per_page + (total_entries % per_page > 0 ? 1 : 0)
8
- current_page = (params[:page] || 1).to_i
9
- %>
10
-
11
- <% if n_pages > 1 %>
12
- <h2>Pages:</h2>
13
- <div class="clearfix">
14
- <ul class="paging">
15
- <% (1..n_pages).each do |page_number| %>
16
- <% if current_page == page_number %>
17
- <li class="selected"><%= link_to(page_number, params.merge(:page => page_number), :title => "Page #{page_number}" ) %></li>
18
- <% else %>
19
- <li><%= link_to(page_number, params.merge(:page => page_number), :title => "Page #{page_number}") %></li>
20
- <% end %>
21
- <% end %>
22
- </ul>
23
- </div>
24
- <% end %>
1
+ <%
2
+ # Expects locals:
3
+ #
4
+ # total_entries
5
+ # per_page
6
+
7
+ n_pages = total_entries/per_page + (total_entries % per_page > 0 ? 1 : 0)
8
+ current_page = (params[:page] || 1).to_i
9
+ %>
10
+
11
+ <% if n_pages > 1 %>
12
+ <h2>Pages:</h2>
13
+ <div class="clearfix">
14
+ <ul class="paging">
15
+ <% (1..n_pages).each do |page_number| %>
16
+ <% if current_page == page_number %>
17
+ <li class="selected"><%= link_to(page_number, params.merge(:page => page_number), :title => "Page #{page_number}" ) %></li>
18
+ <% else %>
19
+ <li><%= link_to(page_number, params.merge(:page => page_number), :title => "Page #{page_number}") %></li>
20
+ <% end %>
21
+ <% end %>
22
+ </ul>
23
+ </div>
24
+ <% end %>
@@ -1,35 +1,35 @@
1
- <%
2
- from_text = lookup(from_locale, key)
3
- to_text = lookup(to_locale, key)
4
- line_size = 100
5
- n_lines = n_lines(from_text, line_size)
6
- field_name = "key[#{key}]"
7
- %>
8
-
9
- <div class="translation single-translation" >
10
- <% if from_text.present? %>
11
- <% if from_text.starts_with?(" ") || from_text.ends_with?(" ")%>
12
- <%= simple_format("&rarr;" + h(from_text) + "&larr;", :class => "translation-text" ) %>
13
- <% else %>
14
- <%= simple_format(h(from_text), :class => "translation-text") %>
15
- <% end %>
16
- <% end %>
17
- <p class="edit-form">
18
- <% if n_lines > 1 %>
19
- <%= text_area_tag(field_name, to_text, :size => "#{line_size}x#{n_lines}", :id => key, :class=>'edit-field') %>
20
- <% else %>
21
- <%= text_field_tag(field_name, to_text, :size => line_size, :id => key, :class=>'edit-field') %>
22
- <% end %>
23
- </p>
24
- <div class="error-text"></div>
25
- <p>
26
- <em>
27
- <%= translate_link(key, from_text, @from_locale, @to_locale) %>
28
- <br/>
29
- <strong>Key:</strong><%=h key %><br/>
30
- <% if @files[key] %>
31
- <strong>File:</strong><%= @files[key].join("<br/>") %>
32
- <% end %>
33
- </em>
34
- </p>
35
- </div>
1
+ <%
2
+ from_text = lookup(from_locale, key)
3
+ to_text = lookup(to_locale, key)
4
+ line_size = 100
5
+ n_lines = n_lines(from_text, line_size)
6
+ field_name = "key[#{key}]"
7
+ %>
8
+
9
+ <div class="translation single-translation" >
10
+ <% if from_text.present? %>
11
+ <% if from_text.starts_with?(" ") || from_text.ends_with?(" ")%>
12
+ <%= simple_format("&rarr;" + h(from_text) + "&larr;", :class => "translation-text" ) %>
13
+ <% else %>
14
+ <%= simple_format(h(from_text), :class => "translation-text") %>
15
+ <% end %>
16
+ <% end %>
17
+ <p class="edit-form">
18
+ <% if n_lines > 1 %>
19
+ <%= text_area_tag(field_name, to_text, :size => "#{line_size}x#{n_lines}", :id => key, :class=>'edit-field') %>
20
+ <% else %>
21
+ <%= text_field_tag(field_name, to_text, :size => line_size, :id => key, :class=>'edit-field') %>
22
+ <% end %>
23
+ </p>
24
+ <div class="error-text"></div>
25
+ <p>
26
+ <em>
27
+ <%= translate_link(key, from_text, @from_locale, @to_locale) %>
28
+ <br/>
29
+ <strong>Key:</strong><%=h key %><br/>
30
+ <% if @files[key] %>
31
+ <strong>File:</strong><%= @files[key].join("<br/>") %>
32
+ <% end %>
33
+ </em>
34
+ </p>
35
+ </div>
@@ -1,96 +1,96 @@
1
- <%
2
- show_filters = ["all", "untranslated", "translated"]
3
- show_filters << "changed" if @from_locale != @to_locale
4
- %>
5
-
6
- <fieldset>
7
- <legend>Search filter</legend>
8
- <div id="show-sort">
9
- <p>
10
- <label>Show:</label> <%= raw simple_filter(show_filters) %>
11
- </p>
12
- <p>
13
- <label>Sort by:</label> <%= raw simple_filter(["key", "text"], 'sort_by') %>
14
- </p>
15
- </div>
16
- <%= form_tag(params, :method => :get) do %>
17
- <div id="languages">
18
- <p>
19
- <%= hidden_field_tag(:filter, params[:filter]) %>
20
- <%= hidden_field_tag(:sort_by, params[:sort_by]) %>
21
- <label>Translate from</label>
22
- <%= select_tag(:from_locale, options_for_select(from_locales, @from_locale.to_sym)) %> <span>to</span>
23
- <%= select_tag(:to_locale, options_for_select(to_locales, @to_locale.to_sym)) %>
24
- <%= submit_tag "Display" %>
25
- </p>
26
- </div>
27
- <div id="filter-pattern">
28
- <p>
29
- <label for="key_pattern_value">Key</label>
30
- <%= select_tag(:key_type, options_for_select([["contains", 'contains'], ["starts with", 'starts_with']], params[:key_type])) %>
31
- <%= text_field_tag(:key_pattern, params[:key_pattern], :size => 50, :id => "key_pattern_value", :class => "text-default") %>
32
- </p>
33
- <p>
34
- <label for="text_pattern_value">Text</label>
35
- <%= select_tag(:text_type, options_for_select(['contains', 'equals'], params[:text_type])) %>
36
- <%= text_field_tag(:text_pattern, params[:text_pattern], :size => 50, :id => "text_pattern_value", :class => "text-default") %>
37
- </p>
38
- <p>
39
- <label for="translated_text_pattern_value">Translated Text</label>
40
- <%= select_tag(:translated_text_type, options_for_select(['contains', 'equals'], params[:translated_text_type])) %>
41
- <%= text_field_tag(:translated_text_pattern, params[:translated_text_pattern], :size => 50, :id => "translated_text_pattern_value", :class => "text-default") %>
42
- </p>
43
- <p>
44
- <%= submit_tag "Search" %>
45
- <%= link_to "clear", params.merge({:text_pattern => nil, :translated_text_pattern => nil, :key_pattern => nil}) %>
46
- </p>
47
- </div>
48
- <% end %>
49
- <p class="hits">
50
- Found <strong><%= @total_entries %></strong> messages
51
- </p>
52
- <p>
53
- <%= link_to "Reload messages", translate_reload_path %>
54
- </p>
55
- </fieldset>
56
-
57
-
58
- <div class="paging">
59
- <%= render :partial => 'pagination', :locals => {:total_entries => @total_entries, :per_page => per_page} %>
60
- </div>
61
-
62
- <% if @total_entries > 0 %>
63
- <%= form_tag(translate_path, :name => 'translate_form') do %>
64
- <div>
65
- <%= hidden_field_tag(:filter, params[:filter], :id => "hid_filter") %>
66
- <%= hidden_field_tag(:sort_by, params[:sort_by], :id => "hid_sort_by") %>
67
- <%= hidden_field_tag(:key_type, params[:key_type], :id => "hid_key_type") %>
68
- <%= hidden_field_tag(:key_pattern, params[:key_pattern], :id => "hid_key_pattern") %>
69
- <%= hidden_field_tag(:text_type, params[:text_type], :id => "hid_text_type") %>
70
- <%= hidden_field_tag(:text_pattern, params[:text_pattern], :id => "hid_text_pattern") %>
71
- </div>
72
- <div class="translations">
73
- <h2>Translations from <span class='big-locale'><%= @from_locale %></span> to <span class='big-locale'><%= @to_locale %></span></h2>
74
- <p class="translate">
75
- <input onclick="testAndSave();" type="button" value="Save Translations">
76
- </p>
77
- <% @paginated_keys.each do |key| %>
78
- <%=
79
- from_text = lookup(@from_locale, key)
80
- render (from_text.is_a?(Array) ? 'array_form' : 'string_form'), {
81
- :from_locale => @from_locale,
82
- :to_locale => @to_locale,
83
- :key => key,
84
- }
85
- %>
86
- <% end %>
87
- <p class="translate">
88
- <input onclick="testAndSave();" type="button" value="Save Translations">
89
- </p>
90
- </div>
91
- <% end %>
92
- <% end %>
93
-
94
- <div class="paging">
95
- <%= render :partial => 'pagination', :locals => {:total_entries => @total_entries, :per_page => per_page} %>
96
- </div>
1
+ <%
2
+ show_filters = ["all", "untranslated", "translated"]
3
+ show_filters << "changed" if @from_locale != @to_locale
4
+ %>
5
+
6
+ <fieldset>
7
+ <legend>Search filter</legend>
8
+ <div id="show-sort">
9
+ <p>
10
+ <label>Show:</label> <%= raw simple_filter(show_filters) %>
11
+ </p>
12
+ <p>
13
+ <label>Sort by:</label> <%= raw simple_filter(["key", "text"], 'sort_by') %>
14
+ </p>
15
+ </div>
16
+ <%= form_tag(params, :method => :get) do %>
17
+ <div id="languages">
18
+ <p>
19
+ <%= hidden_field_tag(:filter, params[:filter]) %>
20
+ <%= hidden_field_tag(:sort_by, params[:sort_by]) %>
21
+ <label>Translate from</label>
22
+ <%= select_tag(:from_locale, options_for_select(from_locales, @from_locale.to_sym)) %> <span>to</span>
23
+ <%= select_tag(:to_locale, options_for_select(to_locales, @to_locale.to_sym)) %>
24
+ <%= submit_tag "Display" %>
25
+ </p>
26
+ </div>
27
+ <div id="filter-pattern">
28
+ <p>
29
+ <label for="key_pattern_value">Key</label>
30
+ <%= select_tag(:key_type, options_for_select([["contains", 'contains'], ["starts with", 'starts_with']], params[:key_type])) %>
31
+ <%= text_field_tag(:key_pattern, params[:key_pattern], :size => 50, :id => "key_pattern_value", :class => "text-default") %>
32
+ </p>
33
+ <p>
34
+ <label for="text_pattern_value">Text</label>
35
+ <%= select_tag(:text_type, options_for_select(['contains', 'equals'], params[:text_type])) %>
36
+ <%= text_field_tag(:text_pattern, params[:text_pattern], :size => 50, :id => "text_pattern_value", :class => "text-default") %>
37
+ </p>
38
+ <p>
39
+ <label for="translated_text_pattern_value">Translated Text</label>
40
+ <%= select_tag(:translated_text_type, options_for_select(['contains', 'equals'], params[:translated_text_type])) %>
41
+ <%= text_field_tag(:translated_text_pattern, params[:translated_text_pattern], :size => 50, :id => "translated_text_pattern_value", :class => "text-default") %>
42
+ </p>
43
+ <p>
44
+ <%= submit_tag "Search" %>
45
+ <%= link_to "clear", params.merge({:text_pattern => nil, :translated_text_pattern => nil, :key_pattern => nil}) %>
46
+ </p>
47
+ </div>
48
+ <% end %>
49
+ <p class="hits">
50
+ Found <strong><%= @total_entries %></strong> messages
51
+ </p>
52
+ <p>
53
+ <%= link_to "Reload messages", translate_reload_path %>
54
+ </p>
55
+ </fieldset>
56
+
57
+
58
+ <div class="paging">
59
+ <%= render :partial => 'pagination', :locals => {:total_entries => @total_entries, :per_page => per_page} %>
60
+ </div>
61
+
62
+ <% if @total_entries > 0 %>
63
+ <%= form_tag(translate_path, :name => 'translate_form') do %>
64
+ <div>
65
+ <%= hidden_field_tag(:filter, params[:filter], :id => "hid_filter") %>
66
+ <%= hidden_field_tag(:sort_by, params[:sort_by], :id => "hid_sort_by") %>
67
+ <%= hidden_field_tag(:key_type, params[:key_type], :id => "hid_key_type") %>
68
+ <%= hidden_field_tag(:key_pattern, params[:key_pattern], :id => "hid_key_pattern") %>
69
+ <%= hidden_field_tag(:text_type, params[:text_type], :id => "hid_text_type") %>
70
+ <%= hidden_field_tag(:text_pattern, params[:text_pattern], :id => "hid_text_pattern") %>
71
+ </div>
72
+ <div class="translations">
73
+ <h2>Translations from <span class='big-locale'><%= @from_locale %></span> to <span class='big-locale'><%= @to_locale %></span></h2>
74
+ <p class="translate">
75
+ <input onclick="testAndSave();" type="button" value="Save Translations">
76
+ </p>
77
+ <% @paginated_keys.each do |key| %>
78
+ <%=
79
+ from_text = lookup(@from_locale, key)
80
+ render (from_text.is_a?(Array) ? 'array_form' : 'string_form'), {
81
+ :from_locale => @from_locale,
82
+ :to_locale => @to_locale,
83
+ :key => key,
84
+ }
85
+ %>
86
+ <% end %>
87
+ <p class="translate">
88
+ <input onclick="testAndSave();" type="button" value="Save Translations">
89
+ </p>
90
+ </div>
91
+ <% end %>
92
+ <% end %>
93
+
94
+ <div class="paging">
95
+ <%= render :partial => 'pagination', :locals => {:total_entries => @total_entries, :per_page => per_page} %>
96
+ </div>
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
- Rails.application.routes.draw do
2
- get 'translate' => 'translate#index', :as => :translate_list
3
- post 'translate' => 'translate#translate', :as => :translate
4
- get 'translate/reload' => 'translate#reload', :as => :translate_reload
5
- end
1
+ Rails.application.routes.draw do
2
+ get 'translate' => 'translate#index', :as => :translate_list
3
+ post 'translate' => 'translate#translate', :as => :translate
4
+ get 'translate/reload' => 'translate#reload', :as => :translate_reload
5
+ end
data/init.rb CHANGED
@@ -1 +1 @@
1
- require 'translate'
1
+ require 'translate'
@@ -1,200 +1,200 @@
1
- require 'yaml'
2
-
3
- class Hash
4
- def deep_merge(other)
5
- # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
6
- merger = proc { |key, v1, v2| (Hash === v1 && Hash === v2) ? v1.merge(v2, &merger) : v2 }
7
- merge(other, &merger)
8
- end
9
-
10
- def set(keys, value)
11
- key = keys.shift
12
- if keys.empty?
13
- self[key] = value
14
- else
15
- self[key] ||= {}
16
- self[key].set keys, value
17
- end
18
- end
19
-
20
- if ENV['SORT']
21
- # copy of ruby's to_yaml method, prepending sort.
22
- # before each so we get an ordered yaml file
23
- def to_yaml( opts = {} )
24
- YAML::quick_emit( self, opts ) do |out|
25
- out.map( taguri, to_yaml_style ) do |map|
26
- sort.each do |k, v| #<- Adding sort.
27
- map.add( k, v )
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
34
-
35
- namespace :translate do
36
- desc "Show duplicate keys for locale LOCALE"
37
- task :duplicates => :environment do
38
- from_locale = I18n.default_locale
39
- duplicates = Translate::Keys.new.duplicate_keys
40
-
41
- messages = []
42
- duplicates.each do |locale, keys|
43
- keys.each do |key|
44
- from_text = I18n.backend.send(:lookup, from_locale, key)
45
- next if from_text.blank?
46
- messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
47
- end
48
- end
49
-
50
- if messages.present?
51
- messages.each { |m| puts m }
52
- else
53
- puts "No duplicate keys"
54
- end
55
- end
56
-
57
- desc "Show untranslated keys for locale LOCALE"
58
- task :untranslated => :environment do
59
- from_locale = I18n.default_locale
60
- untranslated = Translate::Keys.new.untranslated_keys
61
-
62
- messages = []
63
- untranslated.each do |locale, keys|
64
- keys.each do |key|
65
- from_text = I18n.backend.send(:lookup, from_locale, key)
66
- next if from_text.blank?
67
- messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
68
- end
69
- end
70
-
71
- if messages.present?
72
- messages.each { |m| puts m }
73
- else
74
- puts "No untranslated keys"
75
- end
76
- end
77
-
78
- desc "Show I18n keys that are missing in the config/locales/default_locale.yml YAML file"
79
- task :missing => :environment do
80
- missing = Translate::Keys.new.missing_keys.inject([]) do |keys, (key, filename)|
81
- keys << "#{key} in \t #{filename} is missing"
82
- end
83
- puts missing.present? ? missing.join("\n") : "No missing translations in the default locale file"
84
- end
85
-
86
- desc "Remove all translation texts that are no longer present in the locale they were translated from"
87
- task :remove_obsolete_keys => :environment do
88
- I18n.backend.send(:init_translations)
89
- master_locale = ENV['LOCALE'] || I18n.default_locale
90
- Translate::Keys.translated_locales.each do |locale|
91
- texts = {}
92
- Translate::Keys.new.i18n_keys(locale).each do |key|
93
- if I18n.backend.send(:lookup, master_locale, key).to_s.present?
94
- texts[key] = I18n.backend.send(:lookup, locale, key)
95
- end
96
- end
97
- I18n.backend.send(:translations)[locale] = nil # Clear out all current translations
98
- I18n.backend.store_translations(locale, Translate::Keys.to_deep_hash(texts))
99
- Translate::Storage.new(locale).write_to_file
100
- end
101
- end
102
-
103
- desc "Merge I18n keys from log/translations.yml into config/locales/*.yml (for use with the Rails I18n TextMate bundle)"
104
- task :merge_keys => :environment do
105
- I18n.backend.send(:init_translations)
106
- new_translations = YAML::load(IO.read(File.join(Rails.root, "log", "translations.yml")))
107
- raise("Can only merge in translations in single locale") if new_translations.keys.size > 1
108
- locale = new_translations.keys.first
109
-
110
- overwrites = false
111
- Translate::Keys.to_shallow_hash(new_translations[locale]).keys.each do |key|
112
- new_text = key.split(".").inject(new_translations[locale]) { |hash, sub_key| hash[sub_key] }
113
- existing_text = I18n.backend.send(:lookup, locale.to_sym, key)
114
- if existing_text && new_text != existing_text
115
- puts "ERROR: key #{key} already exists with text '#{existing_text.inspect}' and would be overwritten by new text '#{new_text}'. " +
116
- "Set environment variable OVERWRITE=1 if you really want to do this."
117
- overwrites = true
118
- end
119
- end
120
-
121
- if !overwrites || ENV['OVERWRITE']
122
- I18n.backend.store_translations(locale, new_translations[locale])
123
- Translate::Storage.new(locale).write_to_file
124
- end
125
- end
126
-
127
- desc "Apply Google translate to auto translate all texts in locale ENV['FROM'] to locale ENV['TO']"
128
- task :google => :environment do
129
- raise "Please specify FROM and TO locales as environment variables" if ENV['FROM'].blank? || ENV['TO'].blank?
130
-
131
- # Depends on httparty gem
132
- # http://www.robbyonrails.com/articles/2009/03/16/httparty-goes-foreign
133
- class GoogleApi
134
- include HTTParty
135
- base_uri 'ajax.googleapis.com'
136
- def self.translate(string, to, from)
137
- tries = 0
138
- begin
139
- get("/ajax/services/language/translate",
140
- :query => {:langpair => "#{from}|#{to}", :q => string, :v => 1.0},
141
- :format => :json)
142
- rescue
143
- tries += 1
144
- puts("SLEEPING - retrying in 5...")
145
- sleep(5)
146
- retry if tries < 10
147
- end
148
- end
149
- end
150
-
151
- I18n.backend.send(:init_translations)
152
-
153
- start_at = Time.now
154
- translations = {}
155
- Translate::Keys.new.i18n_keys(ENV['FROM']).each do |key|
156
- from_text = I18n.backend.send(:lookup, ENV['FROM'], key).to_s
157
- to_text = I18n.backend.send(:lookup, ENV['TO'], key)
158
- if !from_text.blank? && to_text.blank?
159
- print "#{key}: '#{from_text[0, 40]}' => "
160
- if !translations[from_text]
161
- response = GoogleApi.translate(from_text, ENV['TO'], ENV['FROM'])
162
- translations[from_text] = response["responseData"] && response["responseData"]["translatedText"]
163
- end
164
- if !(translation = translations[from_text]).blank?
165
- translation.gsub!(/\(\(([a-z_.]+)\)\)/i, '{{\1}}')
166
- # Google translate sometimes replaces {{foobar}} with (()) foobar. We skip these
167
- if translation !~ /\(\(\)\)/
168
- puts "'#{translation[0, 40]}'"
169
- I18n.backend.store_translations(ENV['TO'].to_sym, Translate::Keys.to_deep_hash({key => translation}))
170
- else
171
- puts "SKIPPING since interpolations were messed up: '#{translation[0,40]}'"
172
- end
173
- else
174
- puts "NO TRANSLATION - #{response.inspect}"
175
- end
176
- end
177
- end
178
-
179
- puts "\nTime elapsed: #{(((Time.now - start_at) / 60) * 10).to_i / 10.to_f} minutes"
180
- Translate::Storage.new(ENV['TO'].to_sym).write_to_file
181
- end
182
-
183
- desc "List keys that have changed I18n texts between YAML file ENV['FROM_FILE'] and YAML file ENV['TO_FILE']. Set ENV['VERBOSE'] to see changes"
184
- task :changed => :environment do
185
- from_hash = Translate::Keys.to_shallow_hash(Translate::File.new(ENV['FROM_FILE']).read)
186
- to_hash = Translate::Keys.to_shallow_hash(Translate::File.new(ENV['TO_FILE']).read)
187
- from_hash.each do |key, from_value|
188
- if (to_value = to_hash[key]) && to_value != from_value
189
- key_without_locale = key[/^[^.]+\.(.+)$/, 1]
190
- if ENV['VERBOSE']
191
- puts "KEY: #{key_without_locale}"
192
- puts "FROM VALUE: '#{from_value}'"
193
- puts "TO VALUE: '#{to_value}'"
194
- else
195
- puts key_without_locale
196
- end
197
- end
198
- end
199
- end
200
- end
1
+ require 'yaml'
2
+
3
+ class Hash
4
+ def deep_merge(other)
5
+ # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
6
+ merger = proc { |key, v1, v2| (Hash === v1 && Hash === v2) ? v1.merge(v2, &merger) : v2 }
7
+ merge(other, &merger)
8
+ end
9
+
10
+ def set(keys, value)
11
+ key = keys.shift
12
+ if keys.empty?
13
+ self[key] = value
14
+ else
15
+ self[key] ||= {}
16
+ self[key].set keys, value
17
+ end
18
+ end
19
+
20
+ if ENV['SORT']
21
+ # copy of ruby's to_yaml method, prepending sort.
22
+ # before each so we get an ordered yaml file
23
+ def to_yaml( opts = {} )
24
+ YAML::quick_emit( self, opts ) do |out|
25
+ out.map( taguri, to_yaml_style ) do |map|
26
+ sort.each do |k, v| #<- Adding sort.
27
+ map.add( k, v )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ namespace :translate do
36
+ desc "Show duplicate keys for locale LOCALE"
37
+ task :duplicates => :environment do
38
+ from_locale = I18n.default_locale
39
+ duplicates = Translate::Keys.new.duplicate_keys
40
+
41
+ messages = []
42
+ duplicates.each do |locale, keys|
43
+ keys.each do |key|
44
+ from_text = I18n.backend.send(:lookup, from_locale, key)
45
+ next if from_text.blank?
46
+ messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
47
+ end
48
+ end
49
+
50
+ if messages.present?
51
+ messages.each { |m| puts m }
52
+ else
53
+ puts "No duplicate keys"
54
+ end
55
+ end
56
+
57
+ desc "Show untranslated keys for locale LOCALE"
58
+ task :untranslated => :environment do
59
+ from_locale = I18n.default_locale
60
+ untranslated = Translate::Keys.new.untranslated_keys
61
+
62
+ messages = []
63
+ untranslated.each do |locale, keys|
64
+ keys.each do |key|
65
+ from_text = I18n.backend.send(:lookup, from_locale, key)
66
+ next if from_text.blank?
67
+ messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
68
+ end
69
+ end
70
+
71
+ if messages.present?
72
+ messages.each { |m| puts m }
73
+ else
74
+ puts "No untranslated keys"
75
+ end
76
+ end
77
+
78
+ desc "Show I18n keys that are missing in the config/locales/default_locale.yml YAML file"
79
+ task :missing => :environment do
80
+ missing = Translate::Keys.new.missing_keys.inject([]) do |keys, (key, filename)|
81
+ keys << "#{key} in \t #{filename} is missing"
82
+ end
83
+ puts missing.present? ? missing.join("\n") : "No missing translations in the default locale file"
84
+ end
85
+
86
+ desc "Remove all translation texts that are no longer present in the locale they were translated from"
87
+ task :remove_obsolete_keys => :environment do
88
+ I18n.backend.send(:init_translations)
89
+ master_locale = ENV['LOCALE'] || I18n.default_locale
90
+ Translate::Keys.translated_locales.each do |locale|
91
+ texts = {}
92
+ Translate::Keys.new.i18n_keys(locale).each do |key|
93
+ if I18n.backend.send(:lookup, master_locale, key).to_s.present?
94
+ texts[key] = I18n.backend.send(:lookup, locale, key)
95
+ end
96
+ end
97
+ I18n.backend.send(:translations)[locale] = nil # Clear out all current translations
98
+ I18n.backend.store_translations(locale, Translate::Keys.to_deep_hash(texts))
99
+ Translate::Storage.new(locale).write_to_file
100
+ end
101
+ end
102
+
103
+ desc "Merge I18n keys from log/translations.yml into config/locales/*.yml (for use with the Rails I18n TextMate bundle)"
104
+ task :merge_keys => :environment do
105
+ I18n.backend.send(:init_translations)
106
+ new_translations = YAML::load(IO.read(File.join(Rails.root, "log", "translations.yml")))
107
+ raise("Can only merge in translations in single locale") if new_translations.keys.size > 1
108
+ locale = new_translations.keys.first
109
+
110
+ overwrites = false
111
+ Translate::Keys.to_shallow_hash(new_translations[locale]).keys.each do |key|
112
+ new_text = key.split(".").inject(new_translations[locale]) { |hash, sub_key| hash[sub_key] }
113
+ existing_text = I18n.backend.send(:lookup, locale.to_sym, key)
114
+ if existing_text && new_text != existing_text
115
+ puts "ERROR: key #{key} already exists with text '#{existing_text.inspect}' and would be overwritten by new text '#{new_text}'. " +
116
+ "Set environment variable OVERWRITE=1 if you really want to do this."
117
+ overwrites = true
118
+ end
119
+ end
120
+
121
+ if !overwrites || ENV['OVERWRITE']
122
+ I18n.backend.store_translations(locale, new_translations[locale])
123
+ Translate::Storage.new(locale).write_to_file
124
+ end
125
+ end
126
+
127
+ desc "Apply Google translate to auto translate all texts in locale ENV['FROM'] to locale ENV['TO']"
128
+ task :google => :environment do
129
+ raise "Please specify FROM and TO locales as environment variables" if ENV['FROM'].blank? || ENV['TO'].blank?
130
+
131
+ # Depends on httparty gem
132
+ # http://www.robbyonrails.com/articles/2009/03/16/httparty-goes-foreign
133
+ class GoogleApi
134
+ include HTTParty
135
+ base_uri 'ajax.googleapis.com'
136
+ def self.translate(string, to, from)
137
+ tries = 0
138
+ begin
139
+ get("/ajax/services/language/translate",
140
+ :query => {:langpair => "#{from}|#{to}", :q => string, :v => 1.0},
141
+ :format => :json)
142
+ rescue
143
+ tries += 1
144
+ puts("SLEEPING - retrying in 5...")
145
+ sleep(5)
146
+ retry if tries < 10
147
+ end
148
+ end
149
+ end
150
+
151
+ I18n.backend.send(:init_translations)
152
+
153
+ start_at = Time.now
154
+ translations = {}
155
+ Translate::Keys.new.i18n_keys(ENV['FROM']).each do |key|
156
+ from_text = I18n.backend.send(:lookup, ENV['FROM'], key).to_s
157
+ to_text = I18n.backend.send(:lookup, ENV['TO'], key)
158
+ if !from_text.blank? && to_text.blank?
159
+ print "#{key}: '#{from_text[0, 40]}' => "
160
+ if !translations[from_text]
161
+ response = GoogleApi.translate(from_text, ENV['TO'], ENV['FROM'])
162
+ translations[from_text] = response["responseData"] && response["responseData"]["translatedText"]
163
+ end
164
+ if !(translation = translations[from_text]).blank?
165
+ translation.gsub!(/\(\(([a-z_.]+)\)\)/i, '{{\1}}')
166
+ # Google translate sometimes replaces {{foobar}} with (()) foobar. We skip these
167
+ if translation !~ /\(\(\)\)/
168
+ puts "'#{translation[0, 40]}'"
169
+ I18n.backend.store_translations(ENV['TO'].to_sym, Translate::Keys.to_deep_hash({key => translation}))
170
+ else
171
+ puts "SKIPPING since interpolations were messed up: '#{translation[0,40]}'"
172
+ end
173
+ else
174
+ puts "NO TRANSLATION - #{response.inspect}"
175
+ end
176
+ end
177
+ end
178
+
179
+ puts "\nTime elapsed: #{(((Time.now - start_at) / 60) * 10).to_i / 10.to_f} minutes"
180
+ Translate::Storage.new(ENV['TO'].to_sym).write_to_file
181
+ end
182
+
183
+ desc "List keys that have changed I18n texts between YAML file ENV['FROM_FILE'] and YAML file ENV['TO_FILE']. Set ENV['VERBOSE'] to see changes"
184
+ task :changed => :environment do
185
+ from_hash = Translate::Keys.to_shallow_hash(Translate::File.new(ENV['FROM_FILE']).read)
186
+ to_hash = Translate::Keys.to_shallow_hash(Translate::File.new(ENV['TO_FILE']).read)
187
+ from_hash.each do |key, from_value|
188
+ if (to_value = to_hash[key]) && to_value != from_value
189
+ key_without_locale = key[/^[^.]+\.(.+)$/, 1]
190
+ if ENV['VERBOSE']
191
+ puts "KEY: #{key_without_locale}"
192
+ puts "FROM VALUE: '#{from_value}'"
193
+ puts "TO VALUE: '#{to_value}'"
194
+ else
195
+ puts key_without_locale
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end