tr8n 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -27
- data/Gemfile.lock +4 -4
- data/README.rdoc +24 -8
- data/VERSION +1 -1
- data/app/controllers/tr8n/home_controller.rb +0 -12
- data/app/helpers/application_helper.rb +0 -1
- data/app/models/tr8n/language.rb +4 -0
- data/app/models/tr8n/translation.rb +1 -1
- data/app/models/tr8n/translation_key.rb +7 -7
- data/app/views/tr8n/admin/clientsdk/index.html.erb +13 -13
- data/app/views/tr8n/admin/clientsdk/lb_samples.html.erb +1 -0
- data/app/views/tr8n/common/_scripts.html.erb +0 -8
- data/app/views/tr8n/language/select.html.erb +1 -1
- data/app/views/tr8n/phrases/_new_comment.html.erb +1 -1
- data/config/tr8n/config.yml +29 -29
- data/config/tr8n/tokens/data.yml +1 -1
- data/config/tr8n/tokens/decorations.yml +4 -4
- data/lib/application_helper.rb +53 -1
- data/lib/tr8n/controller_methods.rb +45 -7
- data/lib/tr8n/tokens/decoration_token.rb +23 -17
- data/public/tr8n/javascripts/tr8n_client_sdk.js +203 -69
- metadata +18 -10
- data/app/views/tr8n/home/docs.html.erb +0 -3
- data/app/views/tr8n/home/integration.html.erb +0 -564
- data/app/views/tr8n/home/rules.html.erb +0 -668
- data/app/views/tr8n/home/tokens.html.erb +0 -324
- data/lib/tr8n/common_methods.rb +0 -61
- data/lib/tr8n/helper_methods.rb +0 -304
data/lib/application_helper.rb
CHANGED
@@ -22,6 +22,37 @@
|
|
22
22
|
#++
|
23
23
|
|
24
24
|
module ApplicationHelper
|
25
|
+
|
26
|
+
# generates translations json for client sdk
|
27
|
+
def tr8n_translations_js_tag(opts = {})
|
28
|
+
html = []
|
29
|
+
html << "<script>"
|
30
|
+
|
31
|
+
var_name = opts[:id] || :tr8n_translations
|
32
|
+
|
33
|
+
source_names = opts[:sources] || [opts[:source]]
|
34
|
+
sources = Tr8n::TranslationSource.find(:all, :conditions => ["source in (?)", source_names])
|
35
|
+
source_ids = sources.collect{|source| source.id}
|
36
|
+
|
37
|
+
if source_ids.empty?
|
38
|
+
conditions = ["1=2"]
|
39
|
+
else
|
40
|
+
conditions = ["(id in (select distinct(translation_key_id) from tr8n_translation_key_sources where translation_source_id in (?)))"]
|
41
|
+
conditions << source_ids.uniq
|
42
|
+
end
|
43
|
+
|
44
|
+
translations = []
|
45
|
+
Tr8n::TranslationKey.find(:all, :conditions => conditions).each_with_index do |tkey, index|
|
46
|
+
trn = tkey.translate(Tr8n::Config.current_language, {}, {:api => true})
|
47
|
+
translations << trn
|
48
|
+
end
|
49
|
+
|
50
|
+
html << "var #{var_name} = #{translations.to_json};"
|
51
|
+
|
52
|
+
html << "</script>"
|
53
|
+
html.join('').html_safe
|
54
|
+
end
|
55
|
+
|
25
56
|
# translation functions
|
26
57
|
def tr(label, desc = "", tokens = {}, options = {})
|
27
58
|
unless desc.nil? or desc.is_a?(String)
|
@@ -154,7 +185,28 @@ module ApplicationHelper
|
|
154
185
|
end
|
155
186
|
|
156
187
|
def tr8n_client_sdk_scripts_tag(opts = {})
|
157
|
-
|
188
|
+
opts[:default_source] ||= "application"
|
189
|
+
opts[:scheduler_interval] ||= 5000
|
190
|
+
|
191
|
+
opts[:enable_inline_translations] = (Tr8n::Config.current_user_is_translator? and Tr8n::Config.current_translator.enable_inline_translations? and (not Tr8n::Config.current_language.default?))
|
192
|
+
opts[:default_decorations] = Tr8n::Config.default_decoration_tokens
|
193
|
+
opts[:default_tokens] = Tr8n::Config.default_data_tokens
|
194
|
+
opts[:rules] = {
|
195
|
+
:number => Tr8n::Config.rules_engine[:numeric_rule], :gender => Tr8n::Config.rules_engine[:gender_rule],
|
196
|
+
:list => Tr8n::Config.rules_engine[:gender_list_rule], :date => Tr8n::Config.rules_engine[:date_rule]
|
197
|
+
}
|
198
|
+
|
199
|
+
html = [javascript_include_tag("/tr8n/javascripts/tr8n_client_sdk.js")]
|
200
|
+
html << "<script>"
|
201
|
+
html << "function initializeTr8nProxy() {"
|
202
|
+
html << " tr8nProxy = new Tr8n.Proxy(#{opts.to_json});"
|
203
|
+
# html << " Tr8n.Utils.addEvent(window, 'load', function() {"
|
204
|
+
# html << " tr8nProxy = new Tr8n.Proxy(#{opts.to_json});"
|
205
|
+
# html << " });"
|
206
|
+
html << "}"
|
207
|
+
html << "initializeTr8nProxy();"
|
208
|
+
html << "</script>"
|
209
|
+
html.join("\n").html_safe
|
158
210
|
end
|
159
211
|
|
160
212
|
def tr8n_translator_rank_tag(translator, rank = nil)
|
@@ -22,7 +22,6 @@
|
|
22
22
|
#++
|
23
23
|
|
24
24
|
module Tr8n::ControllerMethods
|
25
|
-
include Tr8n::CommonMethods
|
26
25
|
|
27
26
|
def self.included(base)
|
28
27
|
if 'ApplicationController' == base.name
|
@@ -78,12 +77,17 @@ module Tr8n::ControllerMethods
|
|
78
77
|
end
|
79
78
|
|
80
79
|
tr8n_current_user = nil
|
81
|
-
if Tr8n::Config.site_user_info_enabled?
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
if Tr8n::Config.site_user_info_enabled?
|
81
|
+
if self.methods.include?(Tr8n::Config.current_user_method.to_sym)
|
82
|
+
begin
|
83
|
+
tr8n_current_user = eval(Tr8n::Config.current_user_method)
|
84
|
+
tr8n_current_user = nil if tr8n_current_user.class.name != Tr8n::Config.user_class_name
|
85
|
+
rescue Exception => ex
|
86
|
+
raise Tr8n::Exception.new("Tr8n cannot be initialized because #{Tr8n::Config.current_user_method} failed with: #{ex.message}")
|
87
|
+
end
|
88
|
+
else
|
89
|
+
tr8n_current_user = Tr8n::Translator.new
|
90
|
+
Tr8n::Logger.error("Site user integration is enabled, but #{Tr8n::Config.current_user_method} method is not defined")
|
87
91
|
end
|
88
92
|
else
|
89
93
|
tr8n_current_user = Tr8n::Translator.find_by_id(session[:tr8n_translator_id]) if session[:tr8n_translator_id]
|
@@ -99,6 +103,40 @@ module Tr8n::ControllerMethods
|
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
106
|
+
def tr(label, desc = "", tokens = {}, options = {})
|
107
|
+
unless desc.nil? or desc.is_a?(String)
|
108
|
+
raise Tr8n::Exception.new("The second parameter of the tr function must be a description")
|
109
|
+
end
|
110
|
+
|
111
|
+
begin
|
112
|
+
url = request.url
|
113
|
+
host = request.env['HTTP_HOST']
|
114
|
+
source = "#{controller.class.name.underscore.gsub("_controller", "")}/#{controller.action_name}"
|
115
|
+
rescue Exception => ex
|
116
|
+
source = self.class.name
|
117
|
+
url = nil
|
118
|
+
host = 'localhost'
|
119
|
+
end
|
120
|
+
|
121
|
+
options.merge!(:source => source) unless options[:source]
|
122
|
+
options.merge!(:caller => caller)
|
123
|
+
options.merge!(:url => url)
|
124
|
+
options.merge!(:host => host)
|
125
|
+
|
126
|
+
# pp [source, options[:source], url]
|
127
|
+
|
128
|
+
unless Tr8n::Config.enabled?
|
129
|
+
return Tr8n::TranslationKey.substitute_tokens(label, tokens, options)
|
130
|
+
end
|
131
|
+
|
132
|
+
Tr8n::Config.current_language.translate(label, desc, tokens, options)
|
133
|
+
end
|
134
|
+
|
135
|
+
# for translating labels
|
136
|
+
def trl(label, desc = "", tokens = {}, options = {})
|
137
|
+
tr(label, desc, tokens, options.merge(:skip_decorations => true))
|
138
|
+
end
|
139
|
+
|
102
140
|
# flash notice
|
103
141
|
def trfn(label, desc = "", tokens = {}, options = {})
|
104
142
|
flash[:trfn] = tr(label, desc, tokens, options)
|
@@ -68,28 +68,34 @@ module Tr8n
|
|
68
68
|
label.gsub(name, "(#{index})")
|
69
69
|
end
|
70
70
|
|
71
|
-
def handle_default_decorations(
|
72
|
-
unless Tr8n::Config.default_decoration_tokens[
|
71
|
+
def handle_default_decorations(token_name, token_value, token_values)
|
72
|
+
unless Tr8n::Config.default_decoration_tokens[token_name]
|
73
73
|
raise Tr8n::TokenException.new("Invalid decoration token value")
|
74
74
|
end
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
params = [lambda_token_value]
|
79
|
-
params += token_values[lambda_token_name.to_sym] if token_values[lambda_token_name.to_sym]
|
80
|
-
|
81
|
-
params.each_with_index do |param, index|
|
82
|
-
lambda_value.gsub!("{$#{index}}", param.to_s)
|
83
|
-
end
|
76
|
+
default_decoration = Tr8n::Config.default_decoration_tokens[token_name].clone
|
77
|
+
decoration_token_values = token_values[token_name.to_sym] || []
|
84
78
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
79
|
+
if decoration_token_values.is_a?(Array)
|
80
|
+
params = [token_value, decoration_token_values].flatten
|
81
|
+
params.each_with_index do |param, index|
|
82
|
+
default_decoration.gsub!("{$#{index}}", param.to_s)
|
83
|
+
end
|
84
|
+
|
85
|
+
# clean all the rest of the {$num} params, if any
|
86
|
+
param_index = params.size
|
87
|
+
while default_decoration.index("{$#{param_index}}")
|
88
|
+
default_decoration.gsub!("{$#{param_index}}", "")
|
89
|
+
param_index += 1
|
90
|
+
end
|
91
|
+
elsif decoration_token_values.is_a?(Hash)
|
92
|
+
default_decoration.gsub!("{$0}", token_value.to_s)
|
93
|
+
decoration_token_values.keys.each do |key|
|
94
|
+
default_decoration.gsub!("{$#{key}}", decoration_token_values[key])
|
95
|
+
end
|
90
96
|
end
|
91
97
|
|
92
|
-
|
98
|
+
default_decoration
|
93
99
|
end
|
94
100
|
|
95
101
|
def substitute(label, values = {}, options = {}, language = Tr8n::Config.current_language)
|
@@ -99,7 +105,7 @@ module Tr8n
|
|
99
105
|
if method
|
100
106
|
if method.is_a?(Proc)
|
101
107
|
substitution_value = method.call(value)
|
102
|
-
elsif method.is_a?(Array)
|
108
|
+
elsif method.is_a?(Array) or method.is_a?(Hash)
|
103
109
|
substitution_value = handle_default_decorations(name, value, values)
|
104
110
|
elsif method.is_a?(String)
|
105
111
|
substitution_value = method.to_s.gsub("{$0}", value)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/****************************************************************************
|
2
|
-
Copyright (c) 2010 Michael Berkovich
|
2
|
+
Copyright (c) 2010-2011 Michael Berkovich
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
a copy of this software and associated documentation files (the
|
@@ -50,10 +50,11 @@ Tr8n.Proxy = function(options) {
|
|
50
50
|
this.options['url'] = this.options['url'] || '/tr8n/api/v1/language/translate';
|
51
51
|
this.options['scheduler_interval'] = this.options['scheduler_interval'] || 20000;
|
52
52
|
this.logger_enabled = true;
|
53
|
-
|
53
|
+
this.missing_translations_locked = false;
|
54
|
+
this.inline_translations_enabled = this.options['enable_inline_translations'];
|
54
55
|
this.logger = new Tr8n.Proxy.Logger({
|
55
56
|
'proxy': self,
|
56
|
-
'element_id': options['
|
57
|
+
'element_id': options['debugger_element_id']
|
57
58
|
});
|
58
59
|
|
59
60
|
this.language = new Tr8n.Proxy.Language({
|
@@ -91,9 +92,9 @@ Tr8n.Proxy.prototype = {
|
|
91
92
|
return this.translations;
|
92
93
|
},
|
93
94
|
getDecorationFor: function(decoration_name) {
|
94
|
-
if (!this.options['
|
95
|
+
if (!this.options['default_decorations'])
|
95
96
|
return null;
|
96
|
-
return this.options['
|
97
|
+
return this.options['default_decorations'][decoration_name];
|
97
98
|
},
|
98
99
|
getLanguageRuleForType: function(rule_type) {
|
99
100
|
// modify this section to add more rules
|
@@ -117,30 +118,57 @@ Tr8n.Proxy.prototype = {
|
|
117
118
|
return null;
|
118
119
|
},
|
119
120
|
|
120
|
-
registerMissingTranslationKey: function(translation_key) {
|
121
|
-
this.missing_translation_keys = this.missing_translation_keys || {};
|
122
|
-
if (!this.missing_translation_keys[translation_key.key]) {
|
123
|
-
this.missing_translation_keys[translation_key.key] = translation_key;
|
124
|
-
}
|
125
|
-
},
|
126
|
-
|
127
121
|
registerTranslationKeys: function(translations) {
|
128
|
-
this.log("Found " + translations.length + " phrases");
|
122
|
+
this.log("Found " + translations.length + " registered phrases");
|
129
123
|
for (i = 0; i < translations.length; i++) {
|
130
|
-
|
131
|
-
this.
|
124
|
+
var translation_key = translations[i];
|
125
|
+
this.log("Registering " + translation_key['key']);
|
126
|
+
this.translations[translation_key['key']] = translation_key;
|
132
127
|
}
|
133
128
|
},
|
134
|
-
|
129
|
+
initTranslations: function(forced) {
|
130
|
+
if (!forced && this.translations) return;
|
131
|
+
|
132
|
+
var self = this;
|
133
|
+
self.translations = {};
|
134
|
+
|
135
|
+
if (this.options['translations_element_id']) {
|
136
|
+
self.log("Registering page translations...");
|
137
|
+
this.registerTranslationKeys(eval(this.options['translations_element_id']));
|
138
|
+
return;
|
139
|
+
}
|
140
|
+
|
141
|
+
self.log("Fetching translations from the server...");
|
142
|
+
Tr8n.Proxy.Utils.ajax(this.options['url'], {
|
143
|
+
method: 'get',
|
144
|
+
parameters: {'batch': true, 'source': self.options['default_source']},
|
145
|
+
onSuccess: function(response) {
|
146
|
+
self.log("Received response from the server");
|
147
|
+
self.log(response.responseText);
|
148
|
+
self.registerTranslationKeys(eval("[" + response.responseText + "]")[0]['phrases']);
|
149
|
+
}
|
150
|
+
});
|
151
|
+
},
|
152
|
+
|
153
|
+
registerMissingTranslationKey: function(translation_key, token_values, options) {
|
154
|
+
this.missing_translation_keys = this.missing_translation_keys || {};
|
155
|
+
if (!this.missing_translation_keys[translation_key.key]) {
|
156
|
+
this.log('Adding missing translation to the queue: ' + translation_key.key);
|
157
|
+
this.missing_translation_keys[translation_key.key] = {translation_key: translation_key, token_values: token_values, options:options};
|
158
|
+
}
|
159
|
+
},
|
135
160
|
submitMissingTranslationKeys: function() {
|
136
|
-
|
137
|
-
this.log('
|
138
|
-
|
161
|
+
if (this.missing_translations_locked) {
|
162
|
+
this.log('Missing translations are being processed, postponding registration task.');
|
163
|
+
return;
|
139
164
|
}
|
165
|
+
|
166
|
+
this.missing_translation_keys = this.missing_translation_keys || {};
|
140
167
|
|
141
168
|
var phrases = "[";
|
142
169
|
for (var key in this.missing_translation_keys) {
|
143
|
-
var translation_key = this.missing_translation_keys[key];
|
170
|
+
var translation_key = this.missing_translation_keys[key].translation_key;
|
171
|
+
if (translation_key == null) continue;
|
144
172
|
if (phrases!="[") phrases = phrases + ",";
|
145
173
|
phrases = phrases + "{";
|
146
174
|
phrases = phrases + '"label":"' + translation_key.label + '", ';
|
@@ -148,42 +176,51 @@ Tr8n.Proxy.prototype = {
|
|
148
176
|
phrases = phrases + "}";
|
149
177
|
}
|
150
178
|
phrases = phrases + "]";
|
151
|
-
|
179
|
+
|
180
|
+
if (phrases == '[]') {
|
181
|
+
// this.log('No missing translation keys to submit...');
|
182
|
+
return;
|
183
|
+
}
|
152
184
|
|
153
185
|
var self = this;
|
154
186
|
this.debug('Submitting missing translation keys: ' + phrases);
|
155
187
|
Tr8n.Proxy.Utils.ajax(this.options['url'], {
|
156
188
|
method: 'put',
|
157
|
-
parameters: {'source': self.options['
|
189
|
+
parameters: {'source': self.options['default_source'], 'phrases': phrases},
|
158
190
|
onSuccess: function(response) {
|
159
191
|
self.log("Received response from the server");
|
160
192
|
self.log(response.responseText);
|
161
|
-
self.
|
193
|
+
self.updateMissingTranslationKeys(eval("[" + response.responseText + "]")[0]['phrases']);
|
162
194
|
}
|
163
195
|
});
|
164
196
|
},
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
197
|
+
updateMissingTranslationKeys: function(translations) {
|
198
|
+
this.missing_translations_locked = true;
|
199
|
+
this.log("Received " + translations.length + " registered phrases...");
|
200
|
+
for (i = 0; i < translations.length; i++) {
|
201
|
+
var translation_key_data = translations[i];
|
202
|
+
|
203
|
+
this.log("Registering new key " + translation_key_data.key);
|
204
|
+
this.translations[translation_key_data.key] = translation_key_data;
|
205
|
+
var missing_key_data = this.missing_translation_keys[translation_key_data.key];
|
206
|
+
var tr8nElement = Tr8n.element(translation_key_data.key);
|
207
|
+
|
208
|
+
if (tr8nElement && missing_key_data.translation_key) {
|
209
|
+
tr8nElement.innerHTML = missing_key_data.translation_key.translate(this.language, missing_key_data.token_values, {skip_decorations:true});
|
210
|
+
tr8nElement.setAttribute('translation_key_id', translation_key_data['id']);
|
211
|
+
if (this.inline_translations_enabled) {
|
212
|
+
tr8nElement.className = 'tr8n_translatable tr8n_not_translated';
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
delete this.missing_translation_keys[missing_key_data.translation_key.key];
|
217
|
+
}
|
218
|
+
this.missing_translations_locked = false;
|
219
|
+
},
|
183
220
|
runScheduledTasks: function() {
|
184
221
|
var self = this;
|
185
222
|
|
186
|
-
this.log("Running scheduled tasks...");
|
223
|
+
// this.log("Running scheduled tasks...");
|
187
224
|
this.submitMissingTranslationKeys();
|
188
225
|
|
189
226
|
window.setTimeout(function() {
|
@@ -239,7 +276,7 @@ Tr8n.Proxy.TranslationKey.prototype = {
|
|
239
276
|
|
240
277
|
translations = translations['labels'];
|
241
278
|
if (!translations) {
|
242
|
-
this.getLogger().error("Translations are in a
|
279
|
+
this.getLogger().error("Translations are in a weird form...");
|
243
280
|
return null;
|
244
281
|
}
|
245
282
|
|
@@ -247,25 +284,34 @@ Tr8n.Proxy.TranslationKey.prototype = {
|
|
247
284
|
for (var i=0; i<translations.length; i++) {
|
248
285
|
this.getLogger().debug("Checking context rules for:" + translations[i]['label']);
|
249
286
|
|
250
|
-
if (!translations[i]['context'])
|
287
|
+
if (!translations[i]['context']) {
|
288
|
+
this.getLogger().debug("Translation has no context, using it by default");
|
289
|
+
return translations[i];
|
290
|
+
}
|
251
291
|
var valid_context = true;
|
252
292
|
|
253
293
|
for (var token in translations[i]['context']) {
|
254
294
|
if (!valid_context) continue;
|
255
295
|
var token_context = translations[i]['context'][token];
|
256
296
|
var rule_name = this.getProxy().getLanguageRuleForType(token_context['type']);
|
257
|
-
this.getLogger().debug("Evaluating rule:" + rule_name);
|
297
|
+
this.getLogger().debug("Evaluating rule: " + rule_name);
|
258
298
|
var options = {'proxy': this.getProxy()};
|
259
299
|
var rule = eval("new " + rule_name + "(token_context, options)");
|
260
300
|
valid_context = valid_context && rule.evaluate(token, token_values);
|
261
301
|
}
|
262
302
|
|
263
|
-
if (valid_context)
|
303
|
+
if (valid_context) {
|
304
|
+
this.getLogger().debug("Found valid translation: " + translations[i].label);
|
305
|
+
return translations[i];
|
306
|
+
} else {
|
307
|
+
this.getLogger().debug("The rules were not matched for: " + translations[i].label);
|
308
|
+
}
|
264
309
|
}
|
265
310
|
|
266
311
|
this.getLogger().debug('No acceptable ranslations found');
|
267
312
|
return null;
|
268
313
|
},
|
314
|
+
|
269
315
|
translate: function(language, token_values, options) {
|
270
316
|
if (!this.label) {
|
271
317
|
this.getLogger().error('Label must always be provided for the translate method');
|
@@ -273,13 +319,28 @@ Tr8n.Proxy.TranslationKey.prototype = {
|
|
273
319
|
}
|
274
320
|
|
275
321
|
var translations = this.getProxy().getTranslations();
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
322
|
+
var translation_key = translations[this.key];
|
323
|
+
|
324
|
+
if (translation_key) {
|
325
|
+
this.getLogger().debug("Found translations, evaluating rules...");
|
326
|
+
|
327
|
+
this.id = translation_key.id;
|
328
|
+
this.original = translation_key.original;
|
329
|
+
var translation = this.findFirstAcceptableTranslation(translation_key, token_values);
|
330
|
+
|
331
|
+
if (translation) {
|
332
|
+
this.getLogger().debug("Found a valid match: " + translation.label);
|
333
|
+
return this.substituteTokens(translation['label'], token_values, options);
|
334
|
+
} else {
|
335
|
+
this.getLogger().debug("No valid match found, using default language");
|
336
|
+
return this.substituteTokens(this.label, token_values, options);
|
337
|
+
}
|
338
|
+
|
339
|
+
} else {
|
340
|
+
this.getLogger().debug("Translation not found, using default language");
|
341
|
+
}
|
281
342
|
|
282
|
-
this.getProxy().registerMissingTranslationKey(this);
|
343
|
+
this.getProxy().registerMissingTranslationKey(this, token_values, options);
|
283
344
|
this.getLogger().debug('No translation found. Using default...');
|
284
345
|
return this.substituteTokens(this.label, token_values, options);
|
285
346
|
},
|
@@ -306,7 +367,7 @@ Tr8n.Proxy.TranslationKey.prototype = {
|
|
306
367
|
|
307
368
|
substituteTokens: function(label, token_values, options) {
|
308
369
|
this.registerDataTokens(label);
|
309
|
-
if (!this.data_tokens) return label;
|
370
|
+
if (!this.data_tokens) return this.decorateLabel(label, options);
|
310
371
|
for (var i = 0; i < this.data_tokens.length; i++) {
|
311
372
|
label = this.data_tokens[i].substitute(label, token_values || {});
|
312
373
|
}
|
@@ -317,8 +378,38 @@ Tr8n.Proxy.TranslationKey.prototype = {
|
|
317
378
|
label = this.decoration_tokens[i].substitute(label, token_values || {});
|
318
379
|
}
|
319
380
|
|
320
|
-
return label;
|
321
|
-
}
|
381
|
+
return this.decorateLabel(label, options);
|
382
|
+
},
|
383
|
+
|
384
|
+
decorateLabel: function(label, options){
|
385
|
+
options = options || {};
|
386
|
+
if (options['skip_decorations'])
|
387
|
+
return label;
|
388
|
+
|
389
|
+
html = [];
|
390
|
+
html.push("<tr8n ");
|
391
|
+
|
392
|
+
if (this.id)
|
393
|
+
html.push(" translation_key_id='" + this.id + "' ");
|
394
|
+
|
395
|
+
if (this.key)
|
396
|
+
html.push(" id='" + this.key + "' ");
|
397
|
+
|
398
|
+
var klasses = ['tr8n_translatable'];
|
399
|
+
|
400
|
+
if (this.original)
|
401
|
+
klasses.push('tr8n_not_translated');
|
402
|
+
else
|
403
|
+
klasses.push('tr8n_translated');
|
404
|
+
|
405
|
+
if (this.getProxy().inline_translations_enabled && this.id)
|
406
|
+
html.push(" class='" + klasses.join(' ') + "'");
|
407
|
+
|
408
|
+
html.push(">");
|
409
|
+
html.push(label);
|
410
|
+
html.push("</tr8n>");
|
411
|
+
return html.join("");
|
412
|
+
}
|
322
413
|
}
|
323
414
|
|
324
415
|
/****************************************************************************
|
@@ -336,12 +427,26 @@ Tr8n.Proxy.LanguageRule.prototype = {
|
|
336
427
|
},
|
337
428
|
getTokenValue: function(token_name, token_values) {
|
338
429
|
var object = token_values[token_name];
|
339
|
-
if (
|
430
|
+
if (object == null) {
|
340
431
|
this.getLogger().error("Invalid token value for token: " + token_name);
|
341
432
|
}
|
342
433
|
|
343
434
|
return object;
|
344
|
-
}
|
435
|
+
},
|
436
|
+
getDefinitionDescription: function() {
|
437
|
+
var result = [];
|
438
|
+
for (var key in this.definition)
|
439
|
+
result.push(key + ": '" + this.definition[key] + "'");
|
440
|
+
return "{" + result.join(", ") + "}";
|
441
|
+
},
|
442
|
+
sanitizeArrayValue: function(value) {
|
443
|
+
var results = [];
|
444
|
+
var arr = value.split(',');
|
445
|
+
for (var index = 0; index < arr.length; index++) {
|
446
|
+
results.push(Tr8n.Proxy.Utils.trim(arr[index]));
|
447
|
+
}
|
448
|
+
return results;
|
449
|
+
}
|
345
450
|
}
|
346
451
|
|
347
452
|
/****************************************************************************
|
@@ -366,9 +471,10 @@ Tr8n.Proxy.NumericRule.transform = function(count, values) {
|
|
366
471
|
|
367
472
|
Tr8n.Proxy.NumericRule.prototype.evaluate = function(token_name, token_values){
|
368
473
|
// "count":{"value1":"2,3,4","operator":"and","type":"number","multipart":true,"part2":"does_not_end_in","value2":"12,13,14","part1":"ends_in"}
|
474
|
+
|
369
475
|
var object = this.getTokenValue(token_name, token_values);
|
370
|
-
if (
|
371
|
-
|
476
|
+
if (object == null) return false;
|
477
|
+
|
372
478
|
var token_value = null;
|
373
479
|
if (typeof object == 'string' || typeof object == 'number') {
|
374
480
|
token_value = "" + object;
|
@@ -379,10 +485,15 @@ Tr8n.Proxy.NumericRule.prototype.evaluate = function(token_name, token_values){
|
|
379
485
|
return false;
|
380
486
|
}
|
381
487
|
|
382
|
-
|
383
|
-
|
488
|
+
this.getLogger().debug("Rule value: '" + token_value + "' for definition: " + this.getDefinitionDescription());
|
489
|
+
|
490
|
+
var result1 = this.evaluatePartialRule(token_value, this.definition['part1'], this.sanitizeArrayValue(this.definition['value1']));
|
491
|
+
if (this.definition['multipart'] == 'false' || this.definition['multipart'] == false || this.definition['multipart'] == null) return result1;
|
492
|
+
this.getLogger().debug("Part 1: " + result1 + " Processing part 2...");
|
384
493
|
|
385
|
-
var result2 = this.evaluatePartialRule(token_value, this.definition['part2'], this.definition['value2']
|
494
|
+
var result2 = this.evaluatePartialRule(token_value, this.definition['part2'], this.sanitizeArrayValue(this.definition['value2']));
|
495
|
+
this.getLogger().debug("Part 2: " + result2 + " Completing evaluation...");
|
496
|
+
|
386
497
|
if (this.definition['operator'] == "or") return (result1 || result2);
|
387
498
|
return (result1 && result2);
|
388
499
|
}
|
@@ -391,11 +502,11 @@ Tr8n.Proxy.NumericRule.prototype.evaluate = function(token_name, token_values){
|
|
391
502
|
Tr8n.Proxy.NumericRule.prototype.evaluatePartialRule = function(token_value, name, values) {
|
392
503
|
if (name == 'is') {
|
393
504
|
if (Tr8n.Proxy.Utils.indexOf(values, token_value)!=-1) return true;
|
394
|
-
return false
|
505
|
+
return false;
|
395
506
|
}
|
396
507
|
if (name == 'is_not') {
|
397
508
|
if (Tr8n.Proxy.Utils.indexOf(values, token_value)==-1) return true;
|
398
|
-
return false
|
509
|
+
return false;
|
399
510
|
}
|
400
511
|
if (name == 'ends_in') {
|
401
512
|
for(var i=0; i<values.length; i++) {
|
@@ -558,7 +669,7 @@ Tr8n.Proxy.Token.prototype = {
|
|
558
669
|
},
|
559
670
|
register: function(label, options) {
|
560
671
|
if (this.getExpression() == null)
|
561
|
-
alert("
|
672
|
+
alert("Token expression must be provided");
|
562
673
|
|
563
674
|
var tokens = label.match(this.getExpression());
|
564
675
|
if (!tokens) return [];
|
@@ -959,13 +1070,17 @@ Tr8n.Proxy.Utils = {
|
|
959
1070
|
/****************************************************************************
|
960
1071
|
**** Tr8n Proxy Initialization
|
961
1072
|
****************************************************************************/
|
962
|
-
|
1073
|
+
var tr8nProxy;
|
1074
|
+
|
1075
|
+
//
|
1076
|
+
// the following should be done by the tr8n_client_sdk_scripts_tag
|
963
1077
|
//
|
1078
|
+
|
964
1079
|
//function initializeTr8nClientSDK(source, debugger) {
|
965
1080
|
// tr8nProxy = tr8nProxy || new Tr8n.Proxy({
|
966
|
-
// "
|
967
|
-
// "
|
968
|
-
// "
|
1081
|
+
// "default_source": source,
|
1082
|
+
// "debugger_element_id": debugger,
|
1083
|
+
// "default_decorations": {"bold": "<strong>{$0}</strong>", "italic": "<i>{$0}</i>", "link": "<a href='{$href}'>{$0}</a>"},
|
969
1084
|
// "rules": {"number":{"token_suffixes":["count", "num"]},
|
970
1085
|
// "gender":{"token_suffixes":["user", "profile", "actor", "target"]},
|
971
1086
|
// "list":{"token_suffixes":["list"]}, "date":{"token_suffixes":["date"]}
|
@@ -973,6 +1088,25 @@ Tr8n.Proxy.Utils = {
|
|
973
1088
|
// });
|
974
1089
|
//}
|
975
1090
|
|
1091
|
+
// global javascript method
|
1092
|
+
function reloadTranslations() {
|
1093
|
+
tr8nProxy.initTranslations(true);
|
1094
|
+
}
|
1095
|
+
|
1096
|
+
// global javascript method - can be used after initialization
|
1097
|
+
function tr(label, description, tokens, options) {
|
1098
|
+
// tr8nProxy.logger.log("Translating: " + label);
|
1099
|
+
return tr8nProxy.translate(label, description || '', tokens || {}, options || {});
|
1100
|
+
}
|
1101
|
+
|
1102
|
+
// global javascript method - can be used after initialization
|
1103
|
+
function trl(label, description, tokens, options) {
|
1104
|
+
// tr8nProxy.logger.log("Translating: " + label);
|
1105
|
+
options = options || {};
|
1106
|
+
options['skip_decorations'] = true;
|
1107
|
+
return tr8nProxy.translate(label, description || '', tokens || {}, options);
|
1108
|
+
}
|
1109
|
+
|
976
1110
|
/****************************************************************************
|
977
1111
|
***
|
978
1112
|
*** MD5 (Message-Digest Algorithm)
|