translate-rails3-plus 0.0.6 → 0.0.7
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/README.md +9 -6
- data/VERSION +1 -1
- data/app/controllers/translate_controller.rb +217 -222
- data/lib/tasks/translate.rake +22 -0
- data/lib/translate/keys.rb +9 -0
- metadata +9 -4
data/README.md
CHANGED
@@ -21,12 +21,13 @@ Rake Tasks
|
|
21
21
|
|
22
22
|
In addition to the web UI this plugin adds the following rake tasks:
|
23
23
|
|
24
|
-
translate:untranslated
|
25
|
-
translate:missing
|
26
|
-
translate:remove_obsolete_keys
|
27
|
-
translate:merge_keys
|
28
|
-
translate:google
|
29
|
-
translate:changed
|
24
|
+
translate:untranslated
|
25
|
+
translate:missing
|
26
|
+
translate:remove_obsolete_keys
|
27
|
+
translate:merge_keys
|
28
|
+
translate:google
|
29
|
+
translate:changed
|
30
|
+
translate:duplicates
|
30
31
|
|
31
32
|
The missing task shows you any I18n keys in your code that do not have translations in the YAML file for your default locale, i.e. config/locales/sv.yml.
|
32
33
|
|
@@ -37,6 +38,8 @@ The google task is used for auto translating from one locale to another using Go
|
|
37
38
|
|
38
39
|
The changed rake task can show you between one YAML file to another which keys have had their texts changed.
|
39
40
|
|
41
|
+
The duplicates task can show you strings that are the same in both locales.
|
42
|
+
|
40
43
|
Installation
|
41
44
|
------------
|
42
45
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
@@ -1,222 +1,217 @@
|
|
1
|
-
class TranslateController < ActionController::Base
|
2
|
-
# It seems users with active_record_store may get a "no :secret given" error if we don't disable csrf protection,
|
3
|
-
skip_before_filter :verify_authenticity_token
|
4
|
-
|
5
|
-
layout 'translate'
|
6
|
-
|
7
|
-
before_filter :init_translations
|
8
|
-
before_filter :set_locale
|
9
|
-
|
10
|
-
# GET /translate
|
11
|
-
def index
|
12
|
-
initialize_keys
|
13
|
-
filter_by_key_pattern
|
14
|
-
filter_by_text_pattern
|
15
|
-
filter_by_translated_text_pattern
|
16
|
-
filter_by_translated_or_changed
|
17
|
-
sort_keys
|
18
|
-
paginate_keys
|
19
|
-
@total_entries = @keys.size
|
20
|
-
@page_title = page_title
|
21
|
-
end
|
22
|
-
|
23
|
-
# POST /translate
|
24
|
-
def translate
|
25
|
-
processed_parameters = process_array_parameters(params[:key])
|
26
|
-
I18n.backend.store_translations(@to_locale, Translate::Keys.to_deep_hash(processed_parameters))
|
27
|
-
Translate::Storage.new(@to_locale).write_to_file
|
28
|
-
Translate::Log.new(@from_locale, @to_locale, params[:key].keys).write_to_file
|
29
|
-
force_init_translations # Force reload from YAML file
|
30
|
-
flash[:notice] = "Translations stored"
|
31
|
-
redirect_to params.slice(:filter, :sort_by, :key_type, :key_pattern, :text_type, :text_pattern, :translated_text_type, :translated_text_pattern).merge({:action => :index})
|
32
|
-
end
|
33
|
-
|
34
|
-
# GET /translate/reload
|
35
|
-
def reload
|
36
|
-
Translate::Keys.files = nil
|
37
|
-
redirect_to :action => 'index'
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def initialize_keys
|
42
|
-
@files = Translate::Keys.files
|
43
|
-
@keys = (@files.keys.map(&:to_s) + Translate::Keys.new.i18n_keys(@from_locale)).uniq
|
44
|
-
@keys.reject! do |key|
|
45
|
-
from_text = lookup(@from_locale, key)
|
46
|
-
# When translating from one language to another, make sure there is a text to translate from.
|
47
|
-
# The only supported formats are String and Array. We don't support other formats
|
48
|
-
(@from_locale != @to_locale && !from_text.present?) || (from_text.present? && !from_text.is_a?(String) && !from_text.is_a?(Array))
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def page_title
|
53
|
-
"Translate"
|
54
|
-
end
|
55
|
-
|
56
|
-
def lookup(locale, key)
|
57
|
-
I18n.backend.send(:lookup, locale, key)
|
58
|
-
end
|
59
|
-
helper_method :lookup
|
60
|
-
|
61
|
-
def from_locales
|
62
|
-
# Attempt to get the list of locale from configuration
|
63
|
-
from_loc = Rails.application.config.from_locales if Rails.application.config.respond_to?(:from_locales)
|
64
|
-
return I18n.available_locales if from_loc.blank?
|
65
|
-
raise StandardError, "from_locale expected to be an array" if from_loc.class != Array
|
66
|
-
from_loc
|
67
|
-
end
|
68
|
-
helper_method :from_locales
|
69
|
-
|
70
|
-
def to_locales
|
71
|
-
to_loc = Rails.application.config.to_locales if Rails.application.config.respond_to?(:to_locales)
|
72
|
-
return I18n.available_locales if to_loc.blank?
|
73
|
-
raise StandardError, "to_locales expected to be an array" if to_loc.class != Array
|
74
|
-
to_loc
|
75
|
-
end
|
76
|
-
helper_method :to_locales
|
77
|
-
|
78
|
-
def filter_by_translated_or_changed
|
79
|
-
params[:filter] ||= 'all'
|
80
|
-
return if params[:filter] == 'all'
|
81
|
-
@keys.reject! do |key|
|
82
|
-
case params[:filter]
|
83
|
-
when 'untranslated'
|
84
|
-
lookup(@to_locale, key).present?
|
85
|
-
when 'translated'
|
86
|
-
lookup(@to_locale, key).blank?
|
87
|
-
when 'changed'
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
165
|
-
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
def
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
def
|
176
|
-
|
177
|
-
end
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
end
|
195
|
-
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
@
|
203
|
-
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
end
|
219
|
-
end
|
220
|
-
reconstructed_hash
|
221
|
-
end
|
222
|
-
end
|
1
|
+
class TranslateController < ActionController::Base
|
2
|
+
# It seems users with active_record_store may get a "no :secret given" error if we don't disable csrf protection,
|
3
|
+
skip_before_filter :verify_authenticity_token
|
4
|
+
|
5
|
+
layout 'translate'
|
6
|
+
|
7
|
+
before_filter :init_translations
|
8
|
+
before_filter :set_locale
|
9
|
+
|
10
|
+
# GET /translate
|
11
|
+
def index
|
12
|
+
initialize_keys
|
13
|
+
filter_by_key_pattern
|
14
|
+
filter_by_text_pattern
|
15
|
+
filter_by_translated_text_pattern
|
16
|
+
filter_by_translated_or_changed
|
17
|
+
sort_keys
|
18
|
+
paginate_keys
|
19
|
+
@total_entries = @keys.size
|
20
|
+
@page_title = page_title
|
21
|
+
end
|
22
|
+
|
23
|
+
# POST /translate
|
24
|
+
def translate
|
25
|
+
processed_parameters = process_array_parameters(params[:key])
|
26
|
+
I18n.backend.store_translations(@to_locale, Translate::Keys.to_deep_hash(processed_parameters))
|
27
|
+
Translate::Storage.new(@to_locale).write_to_file
|
28
|
+
Translate::Log.new(@from_locale, @to_locale, params[:key].keys).write_to_file
|
29
|
+
force_init_translations # Force reload from YAML file
|
30
|
+
flash[:notice] = "Translations stored"
|
31
|
+
redirect_to params.slice(:filter, :sort_by, :key_type, :key_pattern, :text_type, :text_pattern, :translated_text_type, :translated_text_pattern).merge({:action => :index})
|
32
|
+
end
|
33
|
+
|
34
|
+
# GET /translate/reload
|
35
|
+
def reload
|
36
|
+
Translate::Keys.files = nil
|
37
|
+
redirect_to :action => 'index'
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def initialize_keys
|
42
|
+
@files = Translate::Keys.files
|
43
|
+
@keys = (@files.keys.map(&:to_s) + Translate::Keys.new.i18n_keys(@from_locale)).uniq
|
44
|
+
@keys.reject! do |key|
|
45
|
+
from_text = lookup(@from_locale, key)
|
46
|
+
# When translating from one language to another, make sure there is a text to translate from.
|
47
|
+
# The only supported formats are String and Array. We don't support other formats
|
48
|
+
(@from_locale != @to_locale && !from_text.present?) || (from_text.present? && !from_text.is_a?(String) && !from_text.is_a?(Array))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def page_title
|
53
|
+
"Translate"
|
54
|
+
end
|
55
|
+
|
56
|
+
def lookup(locale, key)
|
57
|
+
I18n.backend.send(:lookup, locale, key)
|
58
|
+
end
|
59
|
+
helper_method :lookup
|
60
|
+
|
61
|
+
def from_locales
|
62
|
+
# Attempt to get the list of locale from configuration
|
63
|
+
from_loc = Rails.application.config.from_locales if Rails.application.config.respond_to?(:from_locales)
|
64
|
+
return I18n.available_locales if from_loc.blank?
|
65
|
+
raise StandardError, "from_locale expected to be an array" if from_loc.class != Array
|
66
|
+
from_loc
|
67
|
+
end
|
68
|
+
helper_method :from_locales
|
69
|
+
|
70
|
+
def to_locales
|
71
|
+
to_loc = Rails.application.config.to_locales if Rails.application.config.respond_to?(:to_locales)
|
72
|
+
return I18n.available_locales if to_loc.blank?
|
73
|
+
raise StandardError, "to_locales expected to be an array" if to_loc.class != Array
|
74
|
+
to_loc
|
75
|
+
end
|
76
|
+
helper_method :to_locales
|
77
|
+
|
78
|
+
def filter_by_translated_or_changed
|
79
|
+
params[:filter] ||= 'all'
|
80
|
+
return if params[:filter] == 'all'
|
81
|
+
@keys.reject! do |key|
|
82
|
+
case params[:filter]
|
83
|
+
when 'untranslated'
|
84
|
+
lookup(@to_locale, key).present?
|
85
|
+
when 'translated'
|
86
|
+
lookup(@to_locale, key).blank?
|
87
|
+
when 'changed'
|
88
|
+
lookup(@from_locale, key).to_s == lookup(@to_locale, key).to_s
|
89
|
+
when 'list_changed'
|
90
|
+
fr = lookup(@from_locale, key).to_s.squish
|
91
|
+
to = lookup(@to_locale, key).to_s.squish
|
92
|
+
if fr.downcase != to.downcase
|
93
|
+
p '--'
|
94
|
+
p 'c:' + fr
|
95
|
+
p 'g:' + to
|
96
|
+
end
|
97
|
+
fr.downcase == to.downcase
|
98
|
+
else
|
99
|
+
raise "Unknown filter '#{params[:filter]}'"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def filter_by_key_pattern
|
105
|
+
return if params[:key_pattern].blank?
|
106
|
+
@keys.reject! do |key|
|
107
|
+
case params[:key_type]
|
108
|
+
when "starts_with"
|
109
|
+
!key.starts_with?(params[:key_pattern])
|
110
|
+
when "contains"
|
111
|
+
key.index(params[:key_pattern]).nil?
|
112
|
+
else
|
113
|
+
raise "Unknown key_type '#{params[:key_type]}'"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def filter_by_text_pattern
|
119
|
+
return if params[:text_pattern].blank?
|
120
|
+
@keys.reject! do |key|
|
121
|
+
case params[:text_type]
|
122
|
+
when 'contains'
|
123
|
+
!lookup(@from_locale, key).present? || !lookup(@from_locale, key).to_s.downcase.index(params[:text_pattern].downcase)
|
124
|
+
when 'equals'
|
125
|
+
!lookup(@from_locale, key).present? || lookup(@from_locale, key).to_s.downcase != params[:text_pattern].downcase
|
126
|
+
else
|
127
|
+
raise "Unknown text_type '#{params[:text_type]}'"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def filter_by_translated_text_pattern
|
133
|
+
return if params[:translated_text_pattern].blank?
|
134
|
+
@keys.reject! do |key|
|
135
|
+
case params[:translated_text_type]
|
136
|
+
when 'contains' then
|
137
|
+
!lookup(@to_locale, key).present? || !lookup(@to_locale, key).to_s.downcase.index(params[:translated_text_pattern].downcase)
|
138
|
+
when 'equals' then
|
139
|
+
!lookup(@to_locale, key).present? || lookup(@to_locale, key).to_s.downcase != params[:translated_text_pattern].downcase
|
140
|
+
else
|
141
|
+
raise "Unknown translated_text_type '#{params[:translated_text_type]}'"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def sort_keys
|
147
|
+
params[:sort_by] ||= "key"
|
148
|
+
case params[:sort_by]
|
149
|
+
when "key"
|
150
|
+
@keys.sort!
|
151
|
+
when "text"
|
152
|
+
@keys.sort! do |key1, key2|
|
153
|
+
if lookup(@from_locale, key1).present? && lookup(@from_locale, key2).present?
|
154
|
+
lookup(@from_locale, key1).to_s.downcase <=> lookup(@from_locale, key2).to_s.downcase
|
155
|
+
elsif lookup(@from_locale, key1).present?
|
156
|
+
-1
|
157
|
+
else
|
158
|
+
1
|
159
|
+
end
|
160
|
+
end
|
161
|
+
else
|
162
|
+
raise "Unknown sort_by '#{params[:sort_by]}'"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def paginate_keys
|
167
|
+
params[:page] ||= 1
|
168
|
+
@paginated_keys = @keys[offset, per_page]
|
169
|
+
end
|
170
|
+
|
171
|
+
def offset
|
172
|
+
(params[:page].to_i - 1) * per_page
|
173
|
+
end
|
174
|
+
|
175
|
+
def per_page
|
176
|
+
50
|
177
|
+
end
|
178
|
+
helper_method :per_page
|
179
|
+
|
180
|
+
def init_translations
|
181
|
+
I18n.backend.send(:init_translations) unless I18n.backend.initialized?
|
182
|
+
end
|
183
|
+
|
184
|
+
def force_init_translations
|
185
|
+
I18n.backend.send(:init_translations)
|
186
|
+
end
|
187
|
+
|
188
|
+
def default_locale
|
189
|
+
I18n.default_locale
|
190
|
+
end
|
191
|
+
|
192
|
+
def default_to_locale
|
193
|
+
:en
|
194
|
+
end
|
195
|
+
|
196
|
+
def set_locale
|
197
|
+
session[:from_locale] ||= default_locale
|
198
|
+
session[:to_locale] ||= default_to_locale
|
199
|
+
session[:from_locale] = params[:from_locale] if params[:from_locale].present?
|
200
|
+
session[:to_locale] = params[:to_locale] if params[:to_locale].present?
|
201
|
+
@from_locale = session[:from_locale].to_sym
|
202
|
+
@to_locale = session[:to_locale].to_sym
|
203
|
+
end
|
204
|
+
|
205
|
+
def process_array_parameters(parameter)
|
206
|
+
reconstructed_hash = Hash.new
|
207
|
+
|
208
|
+
parameter.each do |key, value|
|
209
|
+
if value.is_a?(String)
|
210
|
+
reconstructed_hash[key] = value
|
211
|
+
elsif value.is_a?(Hash)
|
212
|
+
reconstructed_hash[key] = Translate::Keys.arraylize(value)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
reconstructed_hash
|
216
|
+
end
|
217
|
+
end
|
data/lib/tasks/translate.rake
CHANGED
@@ -33,6 +33,27 @@ class Hash
|
|
33
33
|
end
|
34
34
|
|
35
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
|
+
|
36
57
|
desc "Show untranslated keys for locale LOCALE"
|
37
58
|
task :untranslated => :environment do
|
38
59
|
from_locale = I18n.default_locale
|
@@ -42,6 +63,7 @@ namespace :translate do
|
|
42
63
|
untranslated.each do |locale, keys|
|
43
64
|
keys.each do |key|
|
44
65
|
from_text = I18n.backend.send(:lookup, from_locale, key)
|
66
|
+
next if from_text.blank?
|
45
67
|
messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
|
46
68
|
end
|
47
69
|
end
|
data/lib/translate/keys.rb
CHANGED
@@ -26,6 +26,15 @@ class Translate::Keys
|
|
26
26
|
Translate::Keys.to_shallow_hash(I18n.backend.send(:translations)[locale.to_sym]).keys.sort
|
27
27
|
end
|
28
28
|
|
29
|
+
def duplicate_keys
|
30
|
+
Translate::Keys.translated_locales.inject({}) do |missing, locale|
|
31
|
+
missing[locale] = i18n_keys(I18n.default_locale).map do |key|
|
32
|
+
I18n.backend.send(:lookup, locale, key) == I18n.backend.send(:lookup, I18n.default_locale, key) ? key : nil
|
33
|
+
end.compact
|
34
|
+
missing
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
29
38
|
def untranslated_keys
|
30
39
|
Translate::Keys.translated_locales.inject({}) do |missing, locale|
|
31
40
|
missing[locale] = i18n_keys(I18n.default_locale).map do |key|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: translate-rails3-plus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -16,7 +16,7 @@ date: 2012-07-09 00:00:00.000000000 Z
|
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: ya2yaml
|
19
|
-
requirement:
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ~>
|
@@ -24,7 +24,12 @@ dependencies:
|
|
24
24
|
version: '0.30'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.30'
|
28
33
|
description: ! 'This plugin provides a web interface for translating Rails I18n texts
|
29
34
|
|
30
35
|
(requires Rails 3.0 or higher) from one locale to another.
|
@@ -101,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
106
|
version: '0'
|
102
107
|
requirements: []
|
103
108
|
rubyforge_project:
|
104
|
-
rubygems_version: 1.8.
|
109
|
+
rubygems_version: 1.8.24
|
105
110
|
signing_key:
|
106
111
|
specification_version: 3
|
107
112
|
summary: Newsdesk translate plugin for Rails 3
|