tr8n 3.0.2 → 3.0.3
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/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)
|