tr8n_core 4.0.7 → 4.0.9

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.
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