tml 4.3.1

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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +243 -0
  4. data/Rakefile +9 -0
  5. data/lib/tml.rb +56 -0
  6. data/lib/tml/api/client.rb +206 -0
  7. data/lib/tml/api/post_office.rb +71 -0
  8. data/lib/tml/application.rb +254 -0
  9. data/lib/tml/base.rb +116 -0
  10. data/lib/tml/cache.rb +143 -0
  11. data/lib/tml/cache_adapters/file.rb +89 -0
  12. data/lib/tml/cache_adapters/memcache.rb +104 -0
  13. data/lib/tml/cache_adapters/memory.rb +85 -0
  14. data/lib/tml/cache_adapters/redis.rb +108 -0
  15. data/lib/tml/config.rb +410 -0
  16. data/lib/tml/decorators/base.rb +52 -0
  17. data/lib/tml/decorators/default.rb +43 -0
  18. data/lib/tml/decorators/html.rb +102 -0
  19. data/lib/tml/exception.rb +35 -0
  20. data/lib/tml/ext/array.rb +86 -0
  21. data/lib/tml/ext/date.rb +99 -0
  22. data/lib/tml/ext/fixnum.rb +47 -0
  23. data/lib/tml/ext/hash.rb +99 -0
  24. data/lib/tml/ext/string.rb +56 -0
  25. data/lib/tml/ext/time.rb +89 -0
  26. data/lib/tml/generators/cache/base.rb +117 -0
  27. data/lib/tml/generators/cache/file.rb +159 -0
  28. data/lib/tml/language.rb +175 -0
  29. data/lib/tml/language_case.rb +105 -0
  30. data/lib/tml/language_case_rule.rb +76 -0
  31. data/lib/tml/language_context.rb +117 -0
  32. data/lib/tml/language_context_rule.rb +56 -0
  33. data/lib/tml/languages/en.json +1363 -0
  34. data/lib/tml/logger.rb +109 -0
  35. data/lib/tml/rules_engine/evaluator.rb +162 -0
  36. data/lib/tml/rules_engine/parser.rb +65 -0
  37. data/lib/tml/session.rb +199 -0
  38. data/lib/tml/source.rb +106 -0
  39. data/lib/tml/tokenizers/data.rb +96 -0
  40. data/lib/tml/tokenizers/decoration.rb +204 -0
  41. data/lib/tml/tokenizers/dom.rb +346 -0
  42. data/lib/tml/tokens/data.rb +403 -0
  43. data/lib/tml/tokens/method.rb +61 -0
  44. data/lib/tml/tokens/transform.rb +223 -0
  45. data/lib/tml/translation.rb +67 -0
  46. data/lib/tml/translation_key.rb +178 -0
  47. data/lib/tml/translator.rb +47 -0
  48. data/lib/tml/utils.rb +130 -0
  49. data/lib/tml/version.rb +34 -0
  50. metadata +121 -0
@@ -0,0 +1,89 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ class Tml::CacheAdapters::File < Tml::Cache
34
+
35
+ def self.cache_path
36
+ "#{Tml.config.cache[:path]}/#{Tml.config.cache[:version]}"
37
+ end
38
+
39
+ def self.file_path(key)
40
+ File.join(cache_path, "#{key}.json")
41
+ end
42
+
43
+ def cache_name
44
+ 'file'
45
+ end
46
+
47
+ def segmented?
48
+ return true if Tml.config.cache[:segmented].nil?
49
+ Tml.config.cache[:segmented]
50
+ end
51
+
52
+ def fetch(key, opts = {})
53
+ info("Fetching key: #{key}")
54
+
55
+ path = self.class.file_path(key)
56
+
57
+ if File.exists?(path)
58
+ info("Cache hit: #{key}")
59
+ return JSON.parse(File.read(path))
60
+ end
61
+
62
+ info("Cache miss: #{key}")
63
+
64
+ return nil unless block_given?
65
+
66
+ yield
67
+ end
68
+
69
+ def store(key, data, opts = {})
70
+ warn('This is a readonly cache')
71
+ end
72
+
73
+ def delete(key, opts = {})
74
+ warn('This is a readonly cache')
75
+ end
76
+
77
+ def exist?(key, opts = {})
78
+ File.exists?(self.class.file_path(key))
79
+ end
80
+
81
+ def clear(opts = {})
82
+ warn('This is a readonly cache')
83
+ end
84
+
85
+ def read_only?
86
+ true
87
+ end
88
+
89
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ require 'dalli' if defined?(Dalli)
34
+
35
+ class Tml::CacheAdapters::Memcache < Tml::Cache
36
+
37
+ def initialize
38
+ options = { :namespace => Tml.config.cache[:namespace] || 'tml', :compress => Tml.config.cache[:compress].nil? ? true : Tml.config.cache[:compress]}
39
+ @cache = Dalli::Client.new(Tml.config.cache[:host], options)
40
+ end
41
+
42
+ def cache_name
43
+ 'memcache'
44
+ end
45
+
46
+ def read_only?
47
+ false
48
+ end
49
+
50
+ def fetch(key, opts = {})
51
+ data = @cache.get(versioned_key(key, opts))
52
+ if data
53
+ info("Cache hit: #{key}")
54
+ return data
55
+ end
56
+
57
+ info("Cache miss: #{key}")
58
+
59
+ return nil unless block_given?
60
+
61
+ data = yield
62
+
63
+ store(key, data)
64
+
65
+ data
66
+ rescue Exception => ex
67
+ warn("Failed to retrieve data: #{key}")
68
+ return nil unless block_given?
69
+ yield
70
+ end
71
+
72
+ def store(key, data, opts = {})
73
+ info("Cache store: #{key}")
74
+ ttl = opts[:ttl] || Tml.config.cache[:timeout]
75
+ @cache.set(versioned_key(key, opts), data, ttl)
76
+ data
77
+ rescue Exception => ex
78
+ warn("Failed to store data: #{key}")
79
+ data
80
+ end
81
+
82
+ def delete(key, opts = {})
83
+ info("Cache delete: #{key}")
84
+ @cache.delete(versioned_key(key, opts))
85
+ key
86
+ rescue Exception => ex
87
+ warn("Failed to delete data: #{key}")
88
+ key
89
+ end
90
+
91
+ def exist?(key, opts = {})
92
+ data = @cache.get(versioned_key(key, opts))
93
+ not data.nil?
94
+ rescue Exception => ex
95
+ warn("Failed to check if key exists: #{key}")
96
+ false
97
+ end
98
+
99
+ def clear(opts = {})
100
+ info("Cache clear")
101
+ rescue Exception => ex
102
+ warn("Failed to clear cache: #{key}")
103
+ end
104
+ end
@@ -0,0 +1,85 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ class Tml::CacheAdapters::Memory < Tml::Cache
34
+
35
+ def self.cache
36
+ @cache ||= {}
37
+ end
38
+
39
+ def self.clear_cache
40
+ @cache = {}
41
+ end
42
+
43
+ def cache_name
44
+ 'memory'
45
+ end
46
+
47
+ def fetch(key, opts = {})
48
+ return yield if Tml.session.inline_mode?
49
+ return yield unless Tml.cache.read_only?
50
+
51
+ data = self.class.cache[key]
52
+
53
+ if data
54
+ info("Cache hit: #{key}")
55
+ return data
56
+ end
57
+
58
+ info("Cache miss: #{key}")
59
+
60
+ return nil unless block_given?
61
+
62
+ data = yield
63
+
64
+ store(key, data)
65
+
66
+ data
67
+ end
68
+
69
+ def store(key, data, opts = {})
70
+ self.class.cache[key] = data
71
+ end
72
+
73
+ def delete(key, opts = {})
74
+ self.class.cache[key] = nil
75
+ end
76
+
77
+ def exist?(key, opts = {})
78
+ not self.class.cache[key].nil?
79
+ end
80
+
81
+ def clear(opts = {})
82
+ self.class.clear_cache
83
+ end
84
+
85
+ end
@@ -0,0 +1,108 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+
34
+ require 'redis' if defined?(::Redis)
35
+
36
+ class Tml::CacheAdapters::Redis < Tml::Cache
37
+
38
+ def initialize
39
+ cache_host, cache_port = Tml.config.cache[:host].split(':') if Tml.config.cache[:host]
40
+ cache_host ||= 'localhost'
41
+ cache_port ||= 6379
42
+
43
+ @cache = ::Redis.new(host: cache_host, port: cache_port)
44
+ end
45
+
46
+ def cache_name
47
+ "redis"
48
+ end
49
+
50
+ def read_only?
51
+ false
52
+ end
53
+
54
+ def fetch(key, opts = {})
55
+ data = @cache.get(versioned_key(key, opts))
56
+ if data
57
+ info("Cache hit: #{key}")
58
+ return data
59
+ end
60
+
61
+ info("Cache miss: #{key}")
62
+
63
+ return nil unless block_given?
64
+
65
+ data = yield
66
+
67
+ store(key, data)
68
+
69
+ data
70
+ rescue Exception => ex
71
+ warn("Failed to retrieve data: #{ex.message}")
72
+ return nil unless block_given?
73
+ yield
74
+ end
75
+
76
+ def store(key, data, opts = {})
77
+ info("Cache store: #{key}")
78
+ ttl = opts[:ttl] || Tml.config.cache[:timeout]
79
+ versioned_key = versioned_key(key, opts)
80
+
81
+ @cache.set(versioned_key, data)
82
+ @cache.expire(versioned_key, ttl) if ttl and ttl > 0
83
+ rescue Exception => ex
84
+ warn("Failed to store data: #{ex.message}")
85
+ data
86
+ end
87
+
88
+ def delete(key, opts = {})
89
+ info("Cache delete: #{key}")
90
+ @cache.del(versioned_key(key, opts))
91
+ rescue Exception => ex
92
+ warn("Failed to delete data: #{ex.message}")
93
+ key
94
+ end
95
+
96
+ def exist?(key, opts = {})
97
+ data = @cache.exist(versioned_key(key, opts))
98
+ not data.nil?
99
+ rescue Exception => ex
100
+ warn("Failed to check if key exists: #{ex.message}")
101
+ false
102
+ end
103
+
104
+ def clear(opts = {})
105
+ info('Cache clear has no effect')
106
+ end
107
+
108
+ end
data/lib/tml/config.rb ADDED
@@ -0,0 +1,410 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ module Tml
34
+
35
+ class << self
36
+ attr_accessor :config
37
+ end
38
+
39
+ # Initializes default config
40
+
41
+ def self.config
42
+ @config ||= Tml::Config.new
43
+ end
44
+
45
+ # Allows you to configure Tml
46
+ #
47
+ # Tml.configure do |config|
48
+ # config.application = {:key => "", :secret => ""}
49
+ #
50
+ # end
51
+ #
52
+
53
+ def self.configure
54
+ yield(self.config)
55
+ end
56
+
57
+ # Allows you to create a block to perform something on adjusted config settings
58
+ # Once the block exists, the config will be reset back to what it was before:
59
+ #
60
+ # Tml.with_config_settings do |config|
61
+ # config.format = :text
62
+ #
63
+ # Do something....
64
+ #
65
+ # end
66
+ #
67
+
68
+ def self.with_config_settings
69
+ old_config = @config.dup
70
+ yield(@config)
71
+ @config = old_config
72
+ end
73
+
74
+ # Acts as a global singleton that holds all Tml configuration
75
+ # The class can be extended with a different implementation, as long as the interface is supported
76
+ class Config
77
+ # Configuration Attributes
78
+ attr_accessor :enabled, :default_locale, :default_level, :format, :application, :context_rules, :logger, :cache, :default_tokens, :localization
79
+
80
+ # Used by Rails and Sinatra extensions
81
+ attr_accessor :current_locale_method, :current_user_method, :translator_options
82
+
83
+ # Used for IRB only
84
+ attr_accessor :submit_missing_keys_realtime
85
+
86
+ def initialize
87
+ @enabled = true
88
+ @default_locale = 'en'
89
+ @default_level = 0
90
+ @format = :html
91
+
92
+ # if running from IRB, make it default to TRUE
93
+ @submit_missing_keys_realtime = (%w(irb pry).include?($0 || ''))
94
+
95
+ @current_locale_method = :current_locale
96
+ @current_user_method = :current_user
97
+
98
+ @application = nil
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
+
128
+ @context_rules = {
129
+ :number => {
130
+ :variables => {
131
+ }
132
+ },
133
+ :gender => {
134
+ :variables => {
135
+ '@gender' => 'gender',
136
+ }
137
+ },
138
+ :genders => {
139
+ :variables => {
140
+ '@genders' => lambda{|list| list.collect do |u|
141
+ u.is_a?(Hash) ? (u['gender'] || u[:gender]) : u.gender
142
+ end
143
+ },
144
+ '@size' => lambda{ |list| list.size }
145
+ }
146
+ },
147
+ :date => {
148
+ :variables => {
149
+ }
150
+ },
151
+ :time => {
152
+ :variables => {
153
+ }
154
+ },
155
+ :list => {
156
+ :variables => {
157
+ '@count' => lambda{|list| list.size}
158
+ }
159
+ },
160
+ }
161
+
162
+ @logger = {
163
+ :enabled => false,
164
+ :path => './log/tml.log',
165
+ :level => 'debug'
166
+ }
167
+
168
+ @cache = {
169
+ :enabled => false,
170
+ :host => 'localhost:11211',
171
+ :adapter => 'memcache',
172
+ :version => 1,
173
+ :timeout => 3600
174
+ }
175
+
176
+ @default_tokens = {
177
+ :html => {
178
+ :data => {
179
+ :ndash => "&ndash;", # –
180
+ :mdash => "&mdash;", # —
181
+ :iexcl => "&iexcl;", # ¡
182
+ :iquest => "&iquest;", # ¿
183
+ :quot => "&quot;", # "
184
+ :ldquo => "&ldquo;", # “
185
+ :rdquo => "&rdquo;", # ”
186
+ :lsquo => "&lsquo;", # ‘
187
+ :rsquo => "&rsquo;", # ’
188
+ :laquo => "&laquo;", # «
189
+ :raquo => "&raquo;", # »
190
+ :nbsp => "&nbsp;", # space
191
+ :lsaquo => "&lsaquo;", # ‹
192
+ :rsaquo => "&rsaquo;", # ›
193
+ :br => "<br/>", # line break
194
+ :lbrace => "{",
195
+ :rbrace => "}",
196
+ :trade => "&trade;", # TM
197
+ },
198
+ :decoration => {
199
+ :strong => "<strong>{$0}</strong>",
200
+ :bold => "<strong>{$0}</strong>",
201
+ :b => "<strong>{$0}</strong>",
202
+ :em => "<em>{$0}</em>",
203
+ :italic => "<i>{$0}</i>",
204
+ :i => "<i>{$0}</i>",
205
+ :link => "<a href='{$href}'>{$0}</a>",
206
+ :br => "<br>{$0}",
207
+ :strike => "<strike>{$0}</strike>",
208
+ :div => "<div id='{$id}' class='{$class}' style='{$style}'>{$0}</div>",
209
+ :span => "<span id='{$id}' class='{$class}' style='{$style}'>{$0}</span>",
210
+ :h1 => "<h1>{$0}</h1>",
211
+ :h2 => "<h2>{$0}</h2>",
212
+ :h3 => "<h3>{$0}</h3>",
213
+ }
214
+ },
215
+ :text => {
216
+ :data => {
217
+ :ndash => "–",
218
+ :mdash => "-",
219
+ :iexcl => "¡",
220
+ :iquest => "¿",
221
+ :quot => '"',
222
+ :ldquo => "“",
223
+ :rdquo => "”",
224
+ :lsquo => "‘",
225
+ :rsquo => "’",
226
+ :laquo => "«",
227
+ :raquo => "»",
228
+ :nbsp => " ",
229
+ :lsaquo => "‹",
230
+ :rsaquo => "›",
231
+ :br => "\n",
232
+ :lbrace => "{",
233
+ :rbrace => "}",
234
+ :trade => "™",
235
+ },
236
+ :decoration => {
237
+ :strong => "{$0}",
238
+ :bold => "{$0}",
239
+ :b => "{$0}",
240
+ :em => "{$0}",
241
+ :italic => "{$0}",
242
+ :i => "{$0}",
243
+ :link => "{$0}:{$1}",
244
+ :br => "\n{$0}",
245
+ :strike => "{$0}",
246
+ :div => "{$0}",
247
+ :span => "{$0}",
248
+ :h1 => "{$0}",
249
+ :h2 => "{$0}",
250
+ :h3 => "{$0}",
251
+ }
252
+ }
253
+ }
254
+
255
+ @localization = {
256
+ :default_day_names => ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
257
+ :default_abbr_day_names => ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
258
+ :default_month_names => ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
259
+ :default_abbr_month_names => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
260
+ :custom_date_formats => {
261
+ :default => '%m/%d/%Y', # 07/4/2008
262
+ :short_numeric => '%m/%d', # 07/4
263
+ :short_numeric_year => '%m/%d/%y', # 07/4/08
264
+ :long_numeric => '%m/%d/%Y', # 07/4/2008
265
+ :verbose => '%A, %B %d, %Y', # Friday, July 4, 2008
266
+ :monthname => '%B %d', # July 4
267
+ :monthname_year => '%B %d, %Y', # July 4, 2008
268
+ :monthname_abbr => '%b %d', # Jul 4
269
+ :monthname_abbr_year => '%b %d, %Y', # Jul 4, 2008
270
+ :date_time => '%m/%d/%Y at %H:%M', # 01/03/1010 at 5:30
271
+ },
272
+ :token_mapping => {
273
+ "%a" => "{short_week_day_name}",
274
+ "%A" => "{week_day_name}",
275
+ "%b" => "{short_month_name}",
276
+ "%B" => "{month_name}",
277
+ "%p" => "{am_pm}",
278
+ "%d" => "{days}",
279
+ "%e" => "{day_of_month}",
280
+ "%j" => "{year_days}",
281
+ "%m" => "{months}",
282
+ "%W" => "{week_num}",
283
+ "%w" => "{week_days}",
284
+ "%y" => "{short_years}",
285
+ "%Y" => "{years}",
286
+ "%l" => "{trimed_hour}",
287
+ "%H" => "{full_hours}",
288
+ "%I" => "{short_hours}",
289
+ "%M" => "{minutes}",
290
+ "%S" => "{seconds}",
291
+ "%s" => "{since_epoch}"
292
+ }
293
+ }
294
+ end
295
+
296
+ def enabled?
297
+ enabled
298
+ end
299
+
300
+ def disabled?
301
+ not enabled?
302
+ end
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
+
317
+ def cache_enabled?
318
+ cache[:enabled].nil? || Tml.config.cache[:enabled]
319
+ end
320
+
321
+ #########################################################
322
+ ## Application
323
+ #########################################################
324
+
325
+ #def default_locale
326
+ # return Tml.session.application.default_locale if Tml.session.application
327
+ # @default_locale
328
+ #end
329
+ #
330
+ #def default_level
331
+ # return Tml.session.application.default_level if Tml.session.application
332
+ # @default_level
333
+ #end
334
+
335
+ def default_language
336
+ @default_language ||= begin
337
+ file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tml_core', 'languages', "#{Tml.config.default_locale}.json"))
338
+ Tml::Language.new(JSON.parse(File.read(file)))
339
+ end
340
+ end
341
+
342
+ def default_application
343
+ @default_application ||= Tml::Application.new(:host => Tml::Api::Client::API_HOST)
344
+ end
345
+
346
+ #########################################################
347
+ ## Decorations
348
+ #########################################################
349
+
350
+ def decorator_class
351
+ return Tml::Decorators::Html if @format == :html
352
+ Tml::Decorators::Default
353
+ end
354
+
355
+ def default_token_value(token_name, type = :data, format = :html)
356
+ default_tokens[format.to_sym][type.to_sym][token_name.to_sym]
357
+ end
358
+
359
+ def set_default_token(token_name, value, type = :data, format = :html)
360
+ default_tokens[format.to_sym] ||= {}
361
+ default_tokens[format.to_sym][type.to_sym] ||= {}
362
+ default_tokens[format.to_sym][type.to_sym][token_name.to_sym] = value
363
+ end
364
+
365
+ #########################################################
366
+ ## Localization
367
+ #########################################################
368
+
369
+ def strftime_symbol_to_token(symbol)
370
+ localization[:token_mapping][symbol]
371
+ end
372
+
373
+ def default_day_names
374
+ localization[:default_day_names]
375
+ end
376
+
377
+ def default_day_name(index)
378
+ "" + default_day_names[index]
379
+ end
380
+
381
+ def default_abbr_day_names
382
+ localization[:default_abbr_day_names]
383
+ end
384
+
385
+ def default_abbr_day_name(index)
386
+ '' + default_abbr_day_names[index]
387
+ end
388
+
389
+ def default_month_names
390
+ localization[:default_month_names]
391
+ end
392
+
393
+ def default_month_name(index)
394
+ '' + default_month_names[index]
395
+ end
396
+
397
+ def default_abbr_month_names
398
+ localization[:default_abbr_month_names]
399
+ end
400
+
401
+ def default_abbr_month_name(index)
402
+ '' + default_abbr_month_names[index]
403
+ end
404
+
405
+ def default_date_formats
406
+ localization[:custom_date_formats]
407
+ end
408
+
409
+ end
410
+ end