tr8n 3.0.2 → 3.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)