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.
@@ -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
- javascript_include_tag("/tr8n/javascripts/tr8n_client_sdk.js", :locals => {:opts => opts})
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
- 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}")
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(lambda_token_name, lambda_token_value, token_values)
72
- unless Tr8n::Config.default_decoration_tokens[lambda_token_name]
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
- lambda_value = Tr8n::Config.default_decoration_tokens[lambda_token_name].clone
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
- # clean all the rest of the {$num} params, if any
86
- param_index = params.size
87
- while lambda_value.index("{$#{param_index}}")
88
- lambda_value.gsub!("{$#{param_index}}", "")
89
- param_index += 1
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
- lambda_value
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, Geni Inc
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['debugger']
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['decorations'])
95
+ if (!this.options['default_decorations'])
95
96
  return null;
96
- return this.options['decorations'][decoration_name];
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
- this.log("Registering " + translations[i]['key']);
131
- this.translations[translations[i]['key']] = translations[i];
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
- if (!this.missing_translation_keys) {
137
- this.log('No missing translation keys to submit...');
138
- return;
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
- this.missing_translation_keys = null;
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['source'], 'phrases': phrases},
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.registerTranslationKeys(eval("[" + response.responseText + "]")[0]['phrases']);
193
+ self.updateMissingTranslationKeys(eval("[" + response.responseText + "]")[0]['phrases']);
162
194
  }
163
195
  });
164
196
  },
165
-
166
- initTranslations: function(forced) {
167
- if (!forced && this.translations) return;
168
-
169
- var self = this;
170
- self.log("Fetching translations from the server...");
171
- self.translations = {};
172
- Tr8n.Proxy.Utils.ajax(this.options['url'], {
173
- method: 'get',
174
- parameters: {'batch': true, 'source': self.options['source']},
175
- onSuccess: function(response) {
176
- self.log("Received response from the server");
177
- self.log(response.responseText);
178
- self.registerTranslationKeys(eval("[" + response.responseText + "]")[0]['phrases']);
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 weid form...");
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']) return translations[i];
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) return translations[i];
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
- if (translations[this.key]) {
277
- var translation = this.findFirstAcceptableTranslation(translations[this.key], token_values);
278
- if (!translation) return this.substituteTokens(this.label, token_values, options);
279
- return this.substituteTokens(translation['label'], token_values, options);
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 (!object) {
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 (!object) return false;
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
- var result1 = this.evaluatePartialRule(token_value, this.definition['part1'], this.definition['value1'].split(','));
383
- if (!this.definition['multipart']) return result1;
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'].split(','));
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("Expression must be provided");
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
- //var tr8nProxy;
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
- // "source": source,
967
- // "debugger": debugger,
968
- // "decorations": {"bold": "<strong>{$0}</strong>", "italic": "<i>{$0}</i>", "link": "<a href='{$href}'>{$0}</a>"},
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)