tr8n_core 4.0.7 → 4.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/tr8n/api_client.rb +28 -18
  4. data/lib/tr8n/application.rb +37 -64
  5. data/lib/tr8n/cache.rb +8 -41
  6. data/lib/tr8n/cache_adapters/file.rb +1 -2
  7. data/lib/tr8n/cache_adapters/memcache.rb +2 -2
  8. data/lib/tr8n/cache_adapters/redis.rb +2 -2
  9. data/lib/tr8n/config.rb +48 -13
  10. data/lib/tr8n/decorators/html.rb +3 -10
  11. data/lib/tr8n/language.rb +25 -112
  12. data/lib/tr8n/language_case.rb +1 -1
  13. data/lib/tr8n/session.rb +2 -9
  14. data/lib/tr8n/source.rb +12 -44
  15. data/lib/tr8n/{tokens/data_tokenizer.rb → tokenizers/data.rb} +4 -3
  16. data/lib/tr8n/{tokens/decoration_tokenizer.rb → tokenizers/decoration.rb} +6 -5
  17. data/lib/tr8n/tokenizers/dom.rb +346 -0
  18. data/lib/tr8n/tokens/data.rb +15 -22
  19. data/lib/tr8n/tokens/transform.rb +24 -12
  20. data/lib/tr8n/translation_key.rb +6 -29
  21. data/lib/tr8n/utils.rb +5 -0
  22. data/lib/tr8n_core/version.rb +1 -1
  23. data/lib/tr8n_core.rb +7 -26
  24. metadata +30 -100
  25. data/lib/tr8n/cache_adapters/cdb.rb +0 -87
  26. data/lib/tr8n/tokens/hidden.rb +0 -57
  27. data/spec/application_spec.rb +0 -52
  28. data/spec/base_spec.rb +0 -19
  29. data/spec/cache/adapters/file_spec.rb +0 -32
  30. data/spec/cache/adapters/memcache_spec.rb +0 -15
  31. data/spec/cache/generators/file_generator_spec.rb +0 -30
  32. data/spec/config_spec.rb +0 -32
  33. data/spec/decorator_spec.rb +0 -12
  34. data/spec/decorators/base_spec.rb +0 -14
  35. data/spec/decorators/default_spec.rb +0 -12
  36. data/spec/decorators/html_spec.rb +0 -50
  37. data/spec/ext/array_spec.rb +0 -12
  38. data/spec/ext/hash_spec.rb +0 -15
  39. data/spec/ext/string_spec.rb +0 -10
  40. data/spec/fixtures/application.json +0 -112
  41. data/spec/fixtures/languages/en-US.json +0 -1424
  42. data/spec/fixtures/languages/es.json +0 -291
  43. data/spec/fixtures/languages/ru.json +0 -582
  44. data/spec/fixtures/translations/ru/basic.json +0 -56
  45. data/spec/fixtures/translations/ru/counters.json +0 -43
  46. data/spec/fixtures/translations/ru/genders.json +0 -171
  47. data/spec/fixtures/translations/ru/last_names.txt +0 -200
  48. data/spec/fixtures/translations/ru/names.json +0 -1
  49. data/spec/fixtures/translations/ru/names.txt +0 -458
  50. data/spec/language_case_rule_spec.rb +0 -57
  51. data/spec/language_case_spec.rb +0 -58
  52. data/spec/language_context_rule_spec.rb +0 -75
  53. data/spec/language_context_spec.rb +0 -333
  54. data/spec/language_spec.rb +0 -615
  55. data/spec/logger_spec.rb +0 -15
  56. data/spec/rules_engine/evaluator_spec.rb +0 -150
  57. data/spec/rules_engine/parser_spec.rb +0 -31
  58. data/spec/source_spec.rb +0 -13
  59. data/spec/spec_helper.rb +0 -101
  60. data/spec/tokens/data_spec.rb +0 -114
  61. data/spec/tokens/data_tokenizer_spec.rb +0 -29
  62. data/spec/tokens/decoration_tokenizer_spec.rb +0 -81
  63. data/spec/tokens/hidden_spec.rb +0 -24
  64. data/spec/tokens/method_spec.rb +0 -84
  65. data/spec/tokens/transform_spec.rb +0 -50
  66. data/spec/translation_key_spec.rb +0 -96
  67. data/spec/translation_spec.rb +0 -24
  68. data/spec/utils_spec.rb +0 -62
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c63616cd107057912d9e4751712da3a7b57f1d52
4
- data.tar.gz: 39d042996c73c584256c6d68977e8ef05fb938ea
3
+ metadata.gz: c5d6598f1871117da1975503815421dff165daf9
4
+ data.tar.gz: e60f6a755c7fede60e1b47daf39ff93e0145636f
5
5
  SHA512:
6
- metadata.gz: 44f82a0d70a1dace61537bd714b77cdeabe30ca5eea5720753607de6218a1095d0e3642d6c31beb0dd607c6e87a503b1a7ab3d0c66cbd76ad57e76f07b36ba0a
7
- data.tar.gz: 6d470e0719c0524271f14ab2e178a83e75dcbf65f45c10701fe7ed5350e227d505f59cbe4e0af3724bf4855a74cde3135c183675a843f9101626fa672e81481e
6
+ metadata.gz: ccdd9f1b867a34c5bd87f195f57983606b18bacf0f65a0d227637fb761fd40d9a0050744d617d5d2a422be2c9fb4001f6dd7790a5fc406114716ccb68814a367
7
+ data.tar.gz: 0c718d53381c1ae518576653bd3db3c7a0c57834e2f38593f39c7ab87f66801b000f1cfc13cc0279f2142768c151abc92168ecbd0bcd26888d586088e88a6b8f
data/README.md CHANGED
@@ -7,7 +7,7 @@ Tr8n Core Library For Ruby
7
7
  [![Build Status](https://travis-ci.org/tr8n/tr8n_ruby_core.png?branch=master)](https://travis-ci.org/tr8n/tr8n_ruby_core)
8
8
  [![Coverage Status](https://coveralls.io/repos/tr8n/tr8n_ruby_core/badge.png?branch=master)](https://coveralls.io/r/tr8n/tr8n_ruby_core?branch=master)
9
9
  [![Gem Version](https://badge.fury.io/rb/tr8n_core.png)](http://badge.fury.io/rb/tr8n_core)
10
- [![Dependency Status](https://www.versioneye.com/user/projects/52e36cc8ec1375c6f4000078/badge.png)](https://www.versioneye.com/user/projects/52e36cc8ec1375c6f4000078)
10
+ [![Dependency Status](https://www.versioneye.com/user/projects/53cda688225426d5d500015b/badge.svg?style=flat)](https://www.versioneye.com/user/projects/53cda688225426d5d500015b)
11
11
  [![Project status](http://stillmaintained.com/tr8n/tr8n_ruby_core.png)](http://stillmaintained.com/tr8n/tr8n_ruby_core.png)
12
12
 
13
13
  Tr8n core library for Ruby is a set of classes that provide translation functionality for any Ruby based application.
@@ -210,9 +210,9 @@ Links
210
210
 
211
211
  * Register on TranslationExchange.com: https://translationexchange.com
212
212
 
213
- * Read TranslationExchange's documentation: http://wiki.translationexchange.com
213
+ * Read TranslationExchange's documentation: http://wiki.tr8nhub.com
214
214
 
215
- * Visit TranslationExchange's blog: http://blog.translationexchange.com
215
+ * Visit TranslationExchange's blog: http://blog.tr8nhub.com
216
216
 
217
217
  * Follow TranslationExchange on Twitter: https://twitter.com/translationx
218
218
 
@@ -55,7 +55,7 @@ class Tr8n::ApiClient < Tr8n::Base
55
55
  end
56
56
 
57
57
  def get(path, params = {}, opts = {})
58
- api(path, params.merge(:access_token => access_token, :t => Time.now.to_i), opts)
58
+ api(path, params.merge(:client_id => application.key, :t => Time.now.to_i), opts.merge(:method => :get))
59
59
  end
60
60
 
61
61
  def post(path, params = {}, opts = {})
@@ -70,28 +70,37 @@ class Tr8n::ApiClient < Tr8n::Base
70
70
  application.host || API_HOST
71
71
  end
72
72
 
73
+ def connection
74
+ @connection ||= Faraday.new(:url => host) do |faraday|
75
+ faraday.request(:url_encoded) # form-encode POST params
76
+ # faraday.response :logger # log requests to STDOUT
77
+ faraday.adapter(Faraday.default_adapter) # make requests with Net::HTTP
78
+ end
79
+ end
80
+
73
81
  def api(path, params = {}, opts = {})
74
- Tr8n.logger.trace_api_call(path, params) do
75
- conn = Faraday.new(:url => host) do |faraday|
76
- faraday.request(:url_encoded) # form-encode POST params
77
- # faraday.response :logger # log requests to STDOUT
78
- faraday.adapter(Faraday.default_adapter) # make requests with Net::HTTP
82
+ if opts[:method] == :get and opts[:cache_key]
83
+ data = Tr8n.cache.fetch(opts[:cache_key]) do
84
+ execute_request(path, params, opts)
79
85
  end
86
+ process_response(data, opts)
87
+ else
88
+ process_response(execute_request(path, params, opts), opts)
89
+ end
90
+ end
80
91
 
92
+ def execute_request(path, params = {}, opts = {})
93
+ response = nil
94
+ Tr8n.logger.trace_api_call(path, params) do
81
95
  if opts[:method] == :post
82
- response = conn.post("#{API_PATH}#{path}", params)
96
+ response = connection.post("#{API_PATH}#{path}", params)
83
97
  else
84
- response = conn.get("#{API_PATH}#{path}", params)
85
- end
86
-
87
- data = JSON.parse(response.body)
88
-
89
- unless data["error"].nil?
90
- raise Tr8n::Exception.new("Error: #{data["error"]}")
98
+ response = connection.get("#{API_PATH}#{path}", params)
91
99
  end
92
-
93
- process_response(data, opts)
94
100
  end
101
+ data = JSON.parse(response.body)
102
+ raise Tr8n::Exception.new("Error: #{data["error"]}") unless data["error"].nil?
103
+ data
95
104
  end
96
105
 
97
106
  def object_class(opts)
@@ -101,7 +110,7 @@ class Tr8n::ApiClient < Tr8n::Base
101
110
 
102
111
  def process_response(data, opts)
103
112
  if data["results"]
104
- Tr8n.logger.debug("recieved #{data["results"].size} result(s)")
113
+ Tr8n.logger.debug("received #{data["results"].size} result(s)")
105
114
  return data["results"] unless object_class(opts)
106
115
  objects = []
107
116
  data["results"].each do |data|
@@ -111,7 +120,8 @@ class Tr8n::ApiClient < Tr8n::Base
111
120
  end
112
121
 
113
122
  return data unless object_class(opts)
114
- Tr8n.logger.debug("constructing #{object_class(opts).name}")
123
+ #Tr8n.logger.debug("constructing #{object_class(opts).name}")
115
124
  object_class(opts).new(data.merge(opts[:attributes] || {}))
116
125
  end
126
+
117
127
  end
@@ -37,13 +37,14 @@ class Tr8n::Application < Tr8n::Base
37
37
  has_many :features, :languages, :featured_locales, :sources, :components, :tokens, :css, :shortcuts
38
38
 
39
39
  def fetch
40
- update_attributes(api_client.get("application", {:definition => true}))
41
- self
40
+ update_attributes(api_client.get("application", {:definition => true}, {:cache_key => key}))
42
41
  end
43
42
 
44
43
  def update_attributes(attrs)
45
44
  super
46
45
 
46
+ self.host ||= "https://translationexchange.com"
47
+
47
48
  self.attributes[:languages] = []
48
49
  if hash_value(attrs, :languages)
49
50
  self.attributes[:languages] = hash_value(attrs, :languages).collect{ |l| Tr8n::Language.new(l.merge(:application => self)) }
@@ -65,60 +66,56 @@ class Tr8n::Application < Tr8n::Base
65
66
 
66
67
  @languages_by_locale = nil
67
68
  @missing_keys_by_sources = nil
69
+
70
+ self
68
71
  end
69
72
 
70
- def language(locale = nil, fetch = true)
73
+ def language(locale = nil)
71
74
  locale ||= default_locale || Tr8n.config.default_locale
72
-
73
75
  @languages_by_locale ||= {}
74
76
  return @languages_by_locale[locale] if @languages_by_locale[locale]
75
-
76
- if Tr8n.config.cache[:enabled]
77
- language = Tr8n.cache.fetch(Tr8n::Language.cache_key(locale))
78
- if language
79
- language.application = self
80
- @languages_by_locale[locale] = language
81
- return language
82
- end
83
- end
84
-
85
- return nil unless fetch
86
-
87
77
  @languages_by_locale[locale] = Tr8n::Language.new(:locale => locale, :application => self).fetch
88
-
89
- if Tr8n.config.cache[:enabled] and not Tr8n.cache.read_only?
90
- Tr8n.cache.store(Tr8n::Language.cache_key(locale), @languages_by_locale[locale])
91
- end
92
-
93
- @languages_by_locale[locale]
94
- end
95
-
96
- def locales
97
- @locales ||= languages.collect{|lang| lang.locale}
98
- end
99
-
100
- def url_for(path)
101
- "#{host}#{path}"
102
78
  end
103
79
 
104
80
  # Mostly used for testing
105
81
  def add_language(new_language)
106
- lang = language(new_language.locale, false)
107
- return lang if lang
108
-
82
+ @languages_by_locale ||= {}
83
+ return @languages_by_locale[new_language.locale] if @languages_by_locale[new_language.locale]
109
84
  new_language.application = self
110
85
  self.languages << new_language
111
86
  @languages_by_locale[new_language.locale] = new_language
112
87
  new_language
113
88
  end
114
89
 
115
- def source(key, register = true)
116
- key = key.source if key.is_a?(Tr8n::Source)
90
+ def locales
91
+ @locales ||= languages.collect{|lang| lang.locale}
92
+ end
117
93
 
94
+ def url_for(path)
95
+ "#{host}#{path}"
96
+ end
97
+
98
+ def source(key, locale)
99
+ @sources_by_key ||= {}
118
100
  return @sources_by_key[key] if @sources_by_key[key]
119
- return nil unless register
120
101
 
121
- @sources_by_key[key] ||= api_client.post("source/register", {:source => key}, {:class => Tr8n::Source, :attributes => {:application => self}})
102
+ unless Tr8n.session.current_translator and Tr8n.session.current_translator.inline?
103
+ cache_key = Tr8n::Source.cache_key(key, locale)
104
+ end
105
+
106
+ begin
107
+ @sources_by_key[key] ||= api_client.get(
108
+ "source",
109
+ {:source => key, :locale => locale, :translations => true},
110
+ {
111
+ :class => Tr8n::Source,
112
+ :attributes => {:application => self},
113
+ :cache_key => cache_key
114
+ }
115
+ )
116
+ rescue
117
+ @sources_by_key[key] ||= Tr8n::Source.new(:source => key)
118
+ end
122
119
  end
123
120
 
124
121
  def component(key, register = true)
@@ -165,10 +162,10 @@ class Tr8n::Application < Tr8n::Base
165
162
  @components_by_key = {}
166
163
  end
167
164
 
168
- def register_missing_key(tkey, source)
165
+ def register_missing_key(source_key, tkey)
169
166
  @missing_keys_by_sources ||= {}
170
- @missing_keys_by_sources[source.source] ||= {}
171
- @missing_keys_by_sources[source.source][tkey.key] ||= tkey
167
+ @missing_keys_by_sources[source_key] ||= {}
168
+ @missing_keys_by_sources[source_key][tkey.key] ||= tkey
172
169
  submit_missing_keys if Tr8n.config.submit_missing_keys_realtime
173
170
  end
174
171
 
@@ -214,30 +211,6 @@ class Tr8n::Application < Tr8n::Base
214
211
  hash_value(features, key.to_s)
215
212
  end
216
213
 
217
- #######################################################################################################
218
- ## Cache Methods
219
- #######################################################################################################
220
-
221
- def self.cache_prefix
222
- 'a@'
223
- end
224
-
225
- def self.cache_key(key)
226
- "#{cache_prefix}_[#{key}]"
227
- end
228
-
229
- def to_cache_hash
230
- hash = to_hash(:host, :key, :secret, :access_token,
231
- :name, :description, :threshold,
232
- :default_locale, :default_level, :features,
233
- :tokens, :css, :shortcuts)
234
- hash["languages"] = []
235
- languages.each do |lang|
236
- hash["languages"] << lang.to_hash(:locale, :name, :english_name, :native_name, :right_to_left, :flag_url)
237
- end
238
- hash
239
- end
240
-
241
214
  #######################################################################################################
242
215
  ## API Methods
243
216
  #######################################################################################################
data/lib/tr8n/cache.rb CHANGED
@@ -32,6 +32,8 @@
32
32
 
33
33
  module Tr8n
34
34
 
35
+ CACHE_VERSION_KEY = "__tr8n_version__"
36
+
35
37
  def self.cache
36
38
  @cache ||= begin
37
39
  if Tr8n.config.cache[:enabled]
@@ -48,13 +50,15 @@ module Tr8n
48
50
 
49
51
  def version
50
52
  @version ||= begin
51
- v = fetch('tr8n_cache_version', :skip_version => true)
52
- v ? v['version'] : Tr8n.config.cache[:version]
53
+ v = fetch(CACHE_VERSION_KEY) do
54
+ {'version' => Tr8n.config.cache[:version]}
55
+ end
56
+ v['version']
53
57
  end
54
58
  end
55
59
 
56
60
  def upgrade_version
57
- store('tr8n_cache_version', {'version' => version + 1}, :ttl => 0, :skip_version => true)
61
+ store(CACHE_VERSION_KEY, {'version' => version + 1}, :ttl => 0)
58
62
  @version = nil
59
63
  end
60
64
 
@@ -87,7 +91,7 @@ module Tr8n
87
91
  end
88
92
 
89
93
  def versioned_key(key, opts = {})
90
- return key if opts[:skip_version]
94
+ return key if CACHE_VERSION_KEY == key
91
95
  "tr8n_rc_v#{version}_#{key}"
92
96
  end
93
97
 
@@ -112,42 +116,5 @@ module Tr8n
112
116
  # do nothing
113
117
  end
114
118
 
115
- def serialize_object(key, data)
116
- if [Tr8n::Application.cache_prefix,
117
- Tr8n::Language.cache_prefix,
118
- Tr8n::Source.cache_prefix,
119
- Tr8n::Component.cache_prefix,
120
- Tr8n::TranslationKey.cache_prefix].include?(key[0..1])
121
- json_data = data.to_cache_hash.to_json
122
- else
123
- # the data must be in cacheable form - usually API responses
124
- json_data = data.to_json
125
- end
126
-
127
- #info(json_data)
128
- json_data
129
- end
130
-
131
- def deserialize_object(key, data)
132
- #info(data.inspect)
133
-
134
- case key[0..1]
135
- when Tr8n::Application.cache_prefix
136
- return Tr8n::Application.new(JSON.parse(data))
137
- when Tr8n::Language.cache_prefix
138
- return Tr8n::Language.new(JSON.parse(data).merge(:application => Tr8n.session.application))
139
- when Tr8n::Source.cache_prefix
140
- return Tr8n::Source.new(JSON.parse(data).merge(:application => Tr8n.session.application))
141
- when Tr8n::Component.cache_prefix
142
- return Tr8n::Component.new(JSON.parse(data).merge(:application => Tr8n.session.application))
143
- when Tr8n::TranslationKey.cache_prefix
144
- return Tr8n::TranslationKey.new(JSON.parse(data).merge(:application => Tr8n.session.application))
145
- end
146
-
147
- # API response form will be here
148
- JSON.parse(data)
149
- end
150
-
151
-
152
119
  end
153
120
  end
@@ -53,8 +53,7 @@ class Tr8n::CacheAdapters::File < Tr8n::Cache
53
53
 
54
54
  if File.exists?(path)
55
55
  info("Cache hit: #{key}")
56
- data = File.read(path)
57
- return deserialize_object(key, data)
56
+ return File.read(path)
58
57
  end
59
58
 
60
59
  info("Cache miss: #{key}")
@@ -51,7 +51,7 @@ class Tr8n::CacheAdapters::Memcache < Tr8n::Cache
51
51
  data = @cache.get(versioned_key(key, opts))
52
52
  if data
53
53
  info("Cache hit: #{key}")
54
- return deserialize_object(key, data)
54
+ return data
55
55
  end
56
56
 
57
57
  info("Cache miss: #{key}")
@@ -72,7 +72,7 @@ class Tr8n::CacheAdapters::Memcache < Tr8n::Cache
72
72
  def store(key, data, opts = {})
73
73
  info("Cache store: #{key}")
74
74
  ttl = opts[:ttl] || Tr8n.config.cache[:timeout]
75
- @cache.set(versioned_key(key, opts), serialize_object(key, data), ttl)
75
+ @cache.set(versioned_key(key, opts), data, ttl)
76
76
  data
77
77
  rescue Exception => ex
78
78
  warn("Failed to store data: #{ex.message}")
@@ -55,7 +55,7 @@ class Tr8n::CacheAdapters::Redis < Tr8n::Cache
55
55
  data = @cache.get(versioned_key(key, opts))
56
56
  if data
57
57
  info("Cache hit: #{key}")
58
- return deserialize_object(key, data)
58
+ return data
59
59
  end
60
60
 
61
61
  info("Cache miss: #{key}")
@@ -78,7 +78,7 @@ class Tr8n::CacheAdapters::Redis < Tr8n::Cache
78
78
  ttl = opts[:ttl] || Tr8n.config.cache[:timeout]
79
79
  versioned_key = versioned_key(key, opts)
80
80
 
81
- @cache.set(versioned_key, serialize_object(key, data))
81
+ @cache.set(versioned_key, data)
82
82
  @cache.expire(versioned_key, ttl) if ttl and ttl > 0
83
83
  rescue Exception => ex
84
84
  warn("Failed to store data: #{ex.message}")
data/lib/tr8n/config.rb CHANGED
@@ -78,7 +78,7 @@ module Tr8n
78
78
  attr_accessor :enabled, :default_locale, :default_level, :format, :application, :context_rules, :logger, :cache, :default_tokens, :localization
79
79
 
80
80
  # Used by Rails and Sinatra extensions
81
- attr_accessor :current_locale_method, :current_user_method
81
+ attr_accessor :current_locale_method, :current_user_method, :translator_options
82
82
 
83
83
  # Used for IRB only
84
84
  attr_accessor :submit_missing_keys_realtime
@@ -90,19 +90,41 @@ module Tr8n
90
90
  @format = :html
91
91
 
92
92
  # if running from IRB, make it default to TRUE
93
- @submit_missing_keys_realtime = (['irb', 'pry'].include?($0 || ''))
93
+ @submit_missing_keys_realtime = (%w(irb pry).include?($0 || ''))
94
94
 
95
95
  @current_locale_method = :current_locale
96
96
  @current_user_method = :current_user
97
97
 
98
- #@application = {
99
- # :host => 'https://localhost:3000',
100
- # :key => 'default',
101
- # :secret => '12345',
102
- #}
103
-
104
98
  @application = nil
105
99
 
100
+ @translator_options = {
101
+ debug: false,
102
+ debug_format_html: "<span style='font-size:20px;color:red;'>{</span> {$0} <span style='font-size:20px;color:red;'>}</span>",
103
+ debug_format: '{{{{$0}}}}',
104
+ split_sentences: false,
105
+ nodes: {
106
+ ignored: [],
107
+ scripts: %w(style script),
108
+ inline: %w(a span i b img strong s em u sub sup),
109
+ short: %w(i b),
110
+ splitters: %w(br hr)
111
+ },
112
+ attributes: {
113
+ labels: %w(title alt)
114
+ },
115
+ name_mapping: {
116
+ b: 'bold',
117
+ i: 'italic',
118
+ a: 'link',
119
+ img: 'picture'
120
+ },
121
+ data_tokens: {
122
+ special: false,
123
+ numeric: false,
124
+ numeric_name: 'num'
125
+ }
126
+ }
127
+
106
128
  @context_rules = {
107
129
  :number => {
108
130
  :variables => {
@@ -110,16 +132,16 @@ module Tr8n
110
132
  },
111
133
  :gender => {
112
134
  :variables => {
113
- "@gender" => "gender",
135
+ '@gender' => 'gender',
114
136
  }
115
137
  },
116
138
  :genders => {
117
139
  :variables => {
118
- "@genders" => lambda{|list| list.collect do |u|
119
- u.is_a?(Hash) ? (u["gender"] || u[:gender]) : u.gender
140
+ '@genders' => lambda{|list| list.collect do |u|
141
+ u.is_a?(Hash) ? (u['gender'] || u[:gender]) : u.gender
120
142
  end
121
143
  },
122
- "@size" => lambda{|list| list.size}
144
+ '@size' => lambda{ |list| list.size }
123
145
  }
124
146
  },
125
147
  :date => {
@@ -132,7 +154,7 @@ module Tr8n
132
154
  },
133
155
  :list => {
134
156
  :variables => {
135
- "@count" => lambda{|list| list.size}
157
+ '@count' => lambda{|list| list.size}
136
158
  }
137
159
  },
138
160
  }
@@ -279,6 +301,19 @@ module Tr8n
279
301
  not enabled?
280
302
  end
281
303
 
304
+ def nested_value(hash, key, default_value = nil)
305
+ parts = key.split('.')
306
+ parts.each do |part|
307
+ return default_value unless hash[part.to_sym]
308
+ hash = hash[part.to_sym]
309
+ end
310
+ hash
311
+ end
312
+
313
+ def translator_option(key)
314
+ nested_value(self.translator_options, key)
315
+ end
316
+
282
317
  #########################################################
283
318
  ## Application
284
319
  #########################################################
@@ -40,15 +40,8 @@ class Tr8n::Decorators::Html < Tr8n::Decorators::Base
40
40
  return translated_label unless Tr8n.session.current_translator and Tr8n.session.current_translator.inline?
41
41
  return translated_label if translation_key.locked? and not Tr8n.session.current_translator.manager?
42
42
 
43
- element = 'span'
44
- if options[:use_div]
45
- element = 'div'
46
- end
47
-
48
- if translation_key.id.nil?
49
- return "<#{element} class='tr8n_pending'>#{translated_label}</#{element}>"
50
- end
51
-
43
+ element = 'tr8n:tr'
44
+ element = 'div' if options[:use_div]
52
45
  classes = ['tr8n_translatable']
53
46
 
54
47
  if translation_key.locked?
@@ -63,7 +56,7 @@ class Tr8n::Decorators::Html < Tr8n::Decorators::Base
63
56
  classes << 'tr8n_fallback'
64
57
  end
65
58
 
66
- html = "<#{element} class='#{classes.join(' ')}' data-translation_key_id='#{translation_key.id}'>"
59
+ html = "<#{element} class='#{classes.join(' ')}' data-translation_key='#{translation_key.key}'>"
67
60
  html << translated_label
68
61
  html << "</#{element}>"
69
62
  html