tr8n_core 4.0.1 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +163 -33
- data/lib/tr8n/application.rb +29 -27
- data/lib/tr8n/base.rb +2 -22
- data/lib/tr8n/cache.rb +9 -9
- data/lib/tr8n/cache_adapters/cdb.rb +2 -2
- data/lib/tr8n/cache_adapters/file.rb +2 -2
- data/lib/tr8n/cache_adapters/memcache.rb +3 -3
- data/lib/tr8n/cache_adapters/redis.rb +3 -3
- data/lib/tr8n/component.rb +1 -1
- data/lib/tr8n/config.rb +256 -202
- data/lib/tr8n/decorators/base.rb +1 -1
- data/lib/tr8n/decorators/default.rb +1 -1
- data/lib/tr8n/decorators/html.rb +4 -4
- data/lib/tr8n/exception.rb +1 -1
- data/lib/tr8n/language.rb +17 -27
- data/lib/tr8n/language_case.rb +4 -3
- data/lib/tr8n/language_case_rule.rb +1 -1
- data/lib/tr8n/language_context.rb +4 -2
- data/lib/tr8n/language_context_rule.rb +1 -1
- data/lib/tr8n/logger.rb +8 -3
- data/lib/tr8n/rules_engine/evaluator.rb +4 -7
- data/lib/tr8n/rules_engine/parser.rb +1 -28
- data/lib/tr8n/session.rb +87 -0
- data/lib/tr8n/source.rb +1 -1
- data/lib/tr8n/tokens/data.rb +2 -2
- data/lib/tr8n/tokens/data_tokenizer.rb +1 -1
- data/lib/tr8n/tokens/decoration_tokenizer.rb +1 -1
- data/lib/tr8n/tokens/hidden.rb +1 -1
- data/lib/tr8n/tokens/method.rb +1 -1
- data/lib/tr8n/tokens/transform.rb +2 -2
- data/lib/tr8n/translation.rb +2 -2
- data/lib/tr8n/translation_key.rb +4 -4
- data/lib/tr8n/translator.rb +1 -1
- data/lib/tr8n/utils.rb +1 -1
- data/lib/tr8n_core/ext/array.rb +4 -4
- data/lib/tr8n_core/ext/date.rb +38 -13
- data/lib/tr8n_core/ext/fixnum.rb +3 -3
- data/lib/tr8n_core/ext/hash.rb +1 -1
- data/lib/tr8n_core/ext/string.rb +3 -3
- data/lib/tr8n_core/ext/time.rb +30 -24
- data/lib/tr8n_core/generators/cache/base.rb +4 -4
- data/lib/tr8n_core/generators/cache/cdb.rb +1 -1
- data/lib/tr8n_core/generators/cache/file.rb +4 -3
- data/lib/tr8n_core/version.rb +2 -2
- data/lib/tr8n_core.rb +1 -1
- data/spec/application_spec.rb +5 -192
- data/spec/base_spec.rb +1 -1
- data/spec/config_spec.rb +21 -5
- data/spec/decorator_spec.rb +1 -1
- data/spec/decorators/base_spec.rb +1 -1
- data/spec/decorators/default_spec.rb +1 -1
- data/spec/decorators/html_spec.rb +8 -8
- data/spec/fixtures/languages/ru.json +36 -4
- data/spec/language_case_rule_spec.rb +1 -1
- data/spec/language_case_spec.rb +1 -1
- data/spec/language_context_rule_spec.rb +1 -1
- data/spec/language_context_spec.rb +1 -1
- data/spec/language_spec.rb +603 -4
- data/spec/rules_engine/evaluator_spec.rb +1 -1
- data/spec/rules_engine/parser_spec.rb +1 -1
- data/spec/{helper.rb → spec_helper.rb} +15 -7
- data/spec/tokens/data_spec.rb +2 -2
- data/spec/tokens/data_tokenizer_spec.rb +1 -1
- data/spec/tokens/decoration_tokenizer_spec.rb +1 -1
- data/spec/tokens/hidden_spec.rb +1 -1
- data/spec/tokens/method_spec.rb +1 -1
- data/spec/tokens/transform_spec.rb +1 -1
- data/spec/translation_key_spec.rb +1 -1
- data/spec/translation_spec.rb +1 -1
- data/spec/utils_spec.rb +1 -3
- metadata +5 -8
- data/config/config.yml +0 -34
- data/config/tokens/data.yml +0 -45
- data/config/tokens/decorations.yml +0 -37
- data/lib/tr8n_core/modules/logger.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a3d5a8a77266054697c3f8dcd30f7fd59a8c563
|
4
|
+
data.tar.gz: 244e312b0f03a9f6f6b232f5357a9b0c7991316d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06e875646e358cd4a3228268d594eec6cc105b5c32176c6b430024de3c806856226b0833a329b060541628803213a8f032a76e2f8eba60e7b84b8291e4957aaf
|
7
|
+
data.tar.gz: d11ddd0b0f3d64bdb7abdfba80c1dcfb4bcc45453c1ca5847bd6076fe7ad7dae124b66bf71562c03ba16a22642890d0e6deea3ccf2e1bda29d5bddbe2134ede4
|
data/README.md
CHANGED
@@ -4,66 +4,196 @@
|
|
4
4
|
|
5
5
|
Tr8n Core Library For Ruby
|
6
6
|
==================
|
7
|
-
|
8
|
-
This library provides a set of Tr8n client side tools that can be used in any ruby based project.
|
9
|
-
|
10
7
|
[![Build Status](https://travis-ci.org/tr8n/tr8n_ruby_core.png?branch=master)](https://travis-ci.org/tr8n/tr8n_ruby_core)
|
11
8
|
[![Coverage Status](https://coveralls.io/repos/tr8n/tr8n_ruby_core/badge.png)](https://coveralls.io/r/tr8n/tr8n_ruby_core)
|
12
9
|
[![Gem Version](https://badge.fury.io/rb/tr8n_core.png)](http://badge.fury.io/rb/tr8n_core)
|
13
10
|
[![Dependency Status](https://www.versioneye.com/user/projects/52e36cc8ec1375c6f4000078/badge.png)](https://www.versioneye.com/user/projects/52e36cc8ec1375c6f4000078)
|
14
11
|
[![Project status](http://stillmaintained.com/tr8n/tr8n_ruby_core.png)](http://stillmaintained.com/tr8n/tr8n_ruby_core.png)
|
15
12
|
|
13
|
+
Tr8n core library for Ruby is a set of classes that provide translation functionality for any Ruby based application.
|
14
|
+
The library uses Tr8n's TML (Translation Markup Language) that allows you to encode complex language structures in simple, yet powerful forms.
|
15
|
+
|
16
|
+
The library works in conjunctions with tr8nhub.com service that provides machine and human translations for your application.
|
17
|
+
In order to use the library, you should sign up at tr8nhub.com, create a new application and copy the application key and secret.
|
18
|
+
|
19
|
+
|
16
20
|
Installation
|
17
21
|
==================
|
18
22
|
|
19
23
|
To install the gem, use:
|
20
24
|
|
21
|
-
|
25
|
+
```ssh
|
26
|
+
gem install tr8n_core
|
27
|
+
```
|
22
28
|
|
23
29
|
|
24
30
|
Usage
|
25
31
|
==================
|
26
32
|
|
27
|
-
The library can be invoked from the IRB. To use tr8n client you must
|
33
|
+
The library can be invoked from the IRB. To use tr8n client you must require it, and instantiate the application with the key and secret of your app from tr8nhub.com:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
irb(main)> require 'tr8n_core'
|
37
|
+
irb(main)> app = Tr8n::Application.init(KEY, SECRET)
|
38
|
+
```
|
39
|
+
|
40
|
+
Now you can use the application to get any language registered with your app:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
irb(main)> english = app.language('en-US')
|
44
|
+
irb(main)> russian = app.language('ru')
|
45
|
+
irb(main)> spanish = app.language('es')
|
46
|
+
irb(main)> chinese = app.language('zh')
|
47
|
+
```
|
48
|
+
|
49
|
+
Simple example:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
irb(main)> english.translate('Hello World')
|
53
|
+
=> "Hello World"
|
54
|
+
irb(main)> russian.translate('Hello World')
|
55
|
+
=> "Привет Мир"
|
56
|
+
irb(main)> spanish.translate('Hello World')
|
57
|
+
=> "Hola Mundo"
|
58
|
+
irb(main)> chinese.translate('Hello World')
|
59
|
+
=> "你好世界"
|
60
|
+
```
|
61
|
+
|
62
|
+
Using description context:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
irb(main)> russian.translate('Invite', 'An invitation')
|
66
|
+
=> "Приглашение"
|
67
|
+
irb(main)> russian.translate('Invite', 'An action to invite')
|
68
|
+
=> "Пригласить"
|
69
|
+
```
|
70
|
+
|
71
|
+
Numeric rules with piped tokens:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
irb(main)> english.translate('You have {count||message}.', :count => 1)
|
75
|
+
=> "You have 1 message."
|
76
|
+
irb(main)> english.translate('You have {count||message}.', :count => 2)
|
77
|
+
=> "You have 2 messages."
|
78
|
+
|
79
|
+
irb(main)> russian.translate('You have {count||message}.', :count => 1)
|
80
|
+
=> "У вас есть 1 сообщение."
|
81
|
+
irb(main)> russian.translate('You have {count||message}.', :count => 2)
|
82
|
+
=> "У вас есть 2 сообщения."
|
83
|
+
irb(main)> russian.translate('You have {count||message}.', :count => 5)
|
84
|
+
=> "У вас есть 5 сообщений."
|
85
|
+
```
|
86
|
+
|
87
|
+
Gender rules:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
irb(main)> user = {:gender => :female, :name => "Anna"}
|
91
|
+
irb(main)> english.translate('{user} updated {user| his, her} profile.', :user => {:object => user, :attribute => :name})
|
92
|
+
=> "Anna updated her profile."
|
93
|
+
|
94
|
+
irb(main)> russian.translate('{user} updated {user| his, her} profile.', :user => {:object => user, :attribute => :name})
|
95
|
+
=> "Anna обновила свой профиль."
|
96
|
+
|
97
|
+
irb(main)> user = {:gender => :male, :name => "Michael"}
|
98
|
+
irb(main)> english.translate('{user} updated {user| his, her} profile.', :user => {:object => user, :attribute => :name})
|
99
|
+
=> "Michael updated his profile."
|
100
|
+
|
101
|
+
irb(main)> russian.translate('{user} updated {user| his, her} profile.', :user => {:object => user, :attribute => :name})
|
102
|
+
=> "Michael обновил свой профиль."
|
103
|
+
```
|
104
|
+
|
105
|
+
Gender rules with language cases:
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
irb(main)> actor = {:gender => :female, :name => "Анна"}
|
109
|
+
irb(main)> target = {:gender => :male, :name => "Михаил"}
|
110
|
+
irb(main)> russian.translate('{actor} sent {target} a gift.', :actor => {:object => actor, :attribute => :name}, :target => {:object => target, :attribute => :name})
|
111
|
+
=> "Анна послала подарок Михаилу."
|
112
|
+
irb(main)> russian.translate('{actor} sent {target} a gift.', :actor => {:object => target, :attribute => :name}, :target => {:object => actor, :attribute => :name})
|
113
|
+
=> "Михаил послал подарок Анне."
|
114
|
+
```
|
28
115
|
|
29
|
-
|
30
|
-
irb(main):002:0> app = Tr8n::Application.init(TR8N_SERVICE_HOST, APPLICATION_KEY, SECRET)
|
31
|
-
irb(main):003:0> russian = app.language('ru')
|
116
|
+
Decoration tokens:
|
32
117
|
|
118
|
+
```ruby
|
119
|
+
irb(main)> english.translate("[bold: This text] should be bold", :bold => lambda{|text| "<strong>#{text}</strong>"})
|
120
|
+
=> "<strong>This text</strong> should be bold"
|
121
|
+
irb(main)> russian.translate("[bold: This text] should be bold", :bold => lambda{|text| "<strong>#{text}</strong>"})
|
122
|
+
=> "<strong>Этот текст</strong> должны быть жирным"
|
123
|
+
```
|
33
124
|
|
34
|
-
|
125
|
+
Nested decoration tokens:
|
35
126
|
|
36
|
-
|
37
|
-
|
127
|
+
```ruby
|
128
|
+
irb(main)> english.translate("[bold: Bold text [italic: with italic text]] together", :bold => "<b>{$0}</b>", :italic => "<i>{$0}</i>")
|
129
|
+
=> "<b>Bold text <i>with italic text</i></b> together"
|
130
|
+
irb(main)> russian.translate("[bold: Bold text [italic: with italic text]] together", :bold => "<b>{$0}</b>", :italic => "<i>{$0}</i>")
|
131
|
+
=> "<b>Жирный текст <i>с курсив</i></b> вместе"
|
132
|
+
```
|
38
133
|
|
39
|
-
|
134
|
+
Data tokens with decoration tokens together:
|
40
135
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
136
|
+
```ruby
|
137
|
+
irb(main)> user = {:gender => :male, :name => "Michael"}
|
138
|
+
irb(main)> english.translate("[bold: {user}] received [link: [bold: {count}] {count|message}]", :user => {:object => user, :attribute => :name}, :bold => "<b>{$0}</b>", :count => 5, :link => "<a href='url'>{$0}</a>")
|
139
|
+
=> "<b>Michael</b> received <a href='url'><b>5</b> messages</a>"
|
140
|
+
irb(main)> russian.translate("[bold: {user}] received [link: [bold: {count}] {count|message}]", :user => {:object => user, :attribute => :name}, :bold => "<b>{$0}</b>", :count => 5, :link => "<a href='url'>{$0}</a>")
|
141
|
+
=> "<b>Michael</b> получил <a href='url'><b>5</b> сообщений</a>"
|
142
|
+
```
|
45
143
|
|
46
|
-
|
144
|
+
PS. The Russian translation on tr8nhub.com could either be provided by a set of 6-9 simple translations for {genders}(male, female, unknown) * count{one, few, many} or by a single advanced translation
|
145
|
+
in the form of:
|
47
146
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
=> "У вас есть 2 сообщения."
|
52
|
-
irb(main):008:0> russian.translate('You have {count||message}.', :count => 5)
|
53
|
-
=> "У вас есть 5 сообщений."
|
147
|
+
```ruby
|
148
|
+
[bold: {user}] {user| male: получил, female: получила} [link: [bold: {count}] {count| one: сообщение, few: сообщения, other: сообщений}]
|
149
|
+
```
|
54
150
|
|
55
|
-
|
151
|
+
Or in a simpler form:
|
56
152
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
=> "Анна послала подарок Михаилу."
|
61
|
-
irb(main):011:0> russian.translate('{actor} sent {target} a gift.', :actor => {:object => target, :attribute => :name}, :target => {:object => actor, :attribute => :name})
|
62
|
-
=> "Михаил послал подарок Анне."
|
153
|
+
```ruby
|
154
|
+
[bold: {user}] {user| получил, получила} [link: [bold: {count}] {count| сообщение, сообщения, сообщений}]
|
155
|
+
```
|
63
156
|
|
64
|
-
|
157
|
+
|
158
|
+
One of the advantages of using TML is the ability to easily switch token values. The above example in a text based email can reuse translations:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
irb(main)> english.translate("[bold: {user}] received [link: [bold: {count}] {count|message}]", :user => {:object => user, :attribute => :name}, :count => 1, :bold => "{$0}", :link => "{$0}")
|
162
|
+
=> "Michael received 1 message"
|
163
|
+
|
164
|
+
irb(main)> russian.translate("[bold: {user}] received [link: [bold: {count}] {count|message}]", :user => {:object => user, :attribute => :name}, :count => 1, :bold => "{$0}", :link => "{$0}")
|
165
|
+
=> "Michael получил 1 сообщение"
|
166
|
+
```
|
167
|
+
|
168
|
+
You should also notice that all of the translation keys you've been using in your experiments will be registered under your application by the tr8nhub service. You can view them all at:
|
169
|
+
|
170
|
+
https://tr8nhub.com/tr8n/app/phrases
|
171
|
+
|
172
|
+
If any translation key you've tried to translate was missing a translation, you can manually translate it using the service (with the help of a machine translation suggestion).
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
irb(main)> russian.translate('This is a new phrase without translations')
|
176
|
+
=> "This is a new phrase without translations"
|
177
|
+
```
|
178
|
+
|
179
|
+
Then without leaving your IRB session, you can call the following method to reset your application cache:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
irb(main)> app.reset_translation_cache
|
183
|
+
```
|
184
|
+
|
185
|
+
Then you can just rerun the translation method with the missing translation and you should get back the translated value.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
irb(main)> russian.translate('This is a new phrase without translations')
|
189
|
+
=> "Это новая фраза без перевода"
|
190
|
+
```
|
191
|
+
|
192
|
+
More Information
|
65
193
|
==================
|
66
194
|
|
67
|
-
|
195
|
+
If you are planning to use Tr8n in Rails application, you should use tr8n_rails_client_sdk gem instead.
|
196
|
+
|
197
|
+
https://github.com/tr8n/tr8n_rails_clientsdk
|
68
198
|
|
69
|
-
|
199
|
+
To read more about TML (Translation Markup Language) syntax, please visit http://wiki.tr8nhub.com
|
data/lib/tr8n/application.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -23,20 +23,25 @@
|
|
23
23
|
|
24
24
|
require 'faraday'
|
25
25
|
|
26
|
+
API_HOST = 'https://tr8nhub.com'
|
26
27
|
API_PATH = '/tr8n/api/'
|
27
28
|
|
28
29
|
class Tr8n::Application < Tr8n::Base
|
29
30
|
attributes :host, :key, :secret, :access_token, :name, :description, :threshold, :default_locale, :default_level
|
30
|
-
has_many :features, :languages, :sources, :components, :tokens
|
31
|
+
has_many :features, :languages, :featured_locales, :sources, :components, :tokens, :css, :shortcuts
|
31
32
|
|
32
|
-
|
33
|
+
# Application Initialization
|
34
|
+
# If host can be provided to point to sandbox or other instance of the service
|
35
|
+
def self.init(key, secret, host = nil, options = {})
|
33
36
|
options[:definition] = true if options[:definition].nil?
|
34
37
|
|
38
|
+
host ||= API_HOST
|
39
|
+
|
35
40
|
Tr8n.cache.reset_version
|
36
41
|
|
37
42
|
Tr8n.logger.info("Initializing application...")
|
38
43
|
|
39
|
-
Tr8n.
|
44
|
+
Tr8n.session.application = Tr8n.cache.fetch(cache_key(key)) do
|
40
45
|
# get access token and store it in the application
|
41
46
|
access_token = api("oauth/request_token", {:client_id => key, :client_secret => secret, :grant_type => :client_credentials}, {:host => host})
|
42
47
|
|
@@ -50,6 +55,7 @@ class Tr8n::Application < Tr8n::Base
|
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
58
|
+
# Initializes the application from a set of attributes received from the API
|
53
59
|
def initialize(attrs = {})
|
54
60
|
super
|
55
61
|
|
@@ -69,10 +75,10 @@ class Tr8n::Application < Tr8n::Base
|
|
69
75
|
end
|
70
76
|
|
71
77
|
@translation_keys = {}
|
78
|
+
@sources_by_key = {}
|
79
|
+
@components_by_key = {}
|
72
80
|
|
73
81
|
@languages_by_locale = nil
|
74
|
-
@sources_by_key = nil
|
75
|
-
@components_by_key = nil
|
76
82
|
@missing_keys_by_sources = nil
|
77
83
|
end
|
78
84
|
|
@@ -82,7 +88,7 @@ class Tr8n::Application < Tr8n::Base
|
|
82
88
|
@languages_by_locale ||= {}
|
83
89
|
return @languages_by_locale[locale] if @languages_by_locale[locale]
|
84
90
|
|
85
|
-
if Tr8n.config.
|
91
|
+
if Tr8n.config.cache[:enabled]
|
86
92
|
language = Tr8n.cache.fetch(Tr8n::Language.cache_key(locale))
|
87
93
|
if language
|
88
94
|
language.application = self
|
@@ -96,7 +102,7 @@ class Tr8n::Application < Tr8n::Base
|
|
96
102
|
# for translator languages will continue to build application cache
|
97
103
|
@languages_by_locale[locale] = get("language", {:locale => locale}, {:class => Tr8n::Language, :attributes => {:application => self}})
|
98
104
|
|
99
|
-
if Tr8n.config.
|
105
|
+
if Tr8n.config.cache[:enabled] and not Tr8n.cache.read_only?
|
100
106
|
Tr8n.cache.store(Tr8n::Language.cache_key(locale), @languages_by_locale[locale])
|
101
107
|
end
|
102
108
|
|
@@ -107,6 +113,10 @@ class Tr8n::Application < Tr8n::Base
|
|
107
113
|
@locales ||= languages.collect{|lang| lang.locale}
|
108
114
|
end
|
109
115
|
|
116
|
+
def url_for(path)
|
117
|
+
"#{host}#{path}"
|
118
|
+
end
|
119
|
+
|
110
120
|
# Mostly used for testing
|
111
121
|
def add_language(new_language)
|
112
122
|
lang = language(new_language.locale, false)
|
@@ -121,14 +131,6 @@ class Tr8n::Application < Tr8n::Base
|
|
121
131
|
def source(key, register = true)
|
122
132
|
key = key.source if key.is_a?(Tr8n::Source)
|
123
133
|
|
124
|
-
@sources_by_key ||= begin
|
125
|
-
srcs = {}
|
126
|
-
(sources || []).each do |src|
|
127
|
-
srcs[src.source] = src
|
128
|
-
end
|
129
|
-
srcs
|
130
|
-
end
|
131
|
-
|
132
134
|
return @sources_by_key[key] if @sources_by_key[key]
|
133
135
|
return nil unless register
|
134
136
|
|
@@ -138,14 +140,6 @@ class Tr8n::Application < Tr8n::Base
|
|
138
140
|
def component(key, register = true)
|
139
141
|
key = key.key if key.is_a?(Tr8n::Component)
|
140
142
|
|
141
|
-
@components_by_key ||= begin
|
142
|
-
cmps = {}
|
143
|
-
(components || []).each do |cmp|
|
144
|
-
cmps[cmp.key] = cmp
|
145
|
-
end
|
146
|
-
cmps
|
147
|
-
end
|
148
|
-
|
149
143
|
return @components_by_key[key] if @components_by_key[key]
|
150
144
|
return nil unless register
|
151
145
|
|
@@ -181,10 +175,17 @@ class Tr8n::Application < Tr8n::Base
|
|
181
175
|
end
|
182
176
|
end
|
183
177
|
|
178
|
+
def reset_translation_cache
|
179
|
+
@translation_keys = {}
|
180
|
+
@sources_by_key = {}
|
181
|
+
@components_by_key = {}
|
182
|
+
end
|
183
|
+
|
184
184
|
def register_missing_key(tkey, source)
|
185
185
|
@missing_keys_by_sources ||= {}
|
186
186
|
@missing_keys_by_sources[source.source] ||= {}
|
187
187
|
@missing_keys_by_sources[source.source][tkey.key] ||= tkey
|
188
|
+
submit_missing_keys if Tr8n.config.submit_missing_keys_realtime
|
188
189
|
end
|
189
190
|
|
190
191
|
def submit_missing_keys
|
@@ -241,7 +242,10 @@ class Tr8n::Application < Tr8n::Base
|
|
241
242
|
end
|
242
243
|
|
243
244
|
def to_cache_hash
|
244
|
-
hash = to_hash(:host, :key, :secret, :access_token,
|
245
|
+
hash = to_hash(:host, :key, :secret, :access_token,
|
246
|
+
:name, :description, :threshold,
|
247
|
+
:default_locale, :default_level, :features,
|
248
|
+
:tokens, :css, :shortcuts)
|
245
249
|
hash["languages"] = []
|
246
250
|
languages.each do |lang|
|
247
251
|
hash["languages"] << lang.to_hash(:locale, :name, :english_name, :native_name, :right_to_left, :flag_url)
|
@@ -252,8 +256,6 @@ class Tr8n::Application < Tr8n::Base
|
|
252
256
|
#######################################################################################################
|
253
257
|
## API Methods
|
254
258
|
#######################################################################################################
|
255
|
-
## TODO: maybe caching can be done generically on the API level during gets?
|
256
|
-
## TODO: think about it...
|
257
259
|
|
258
260
|
def get(path, params = {}, opts = {})
|
259
261
|
api(path, params, opts)
|
data/lib/tr8n/base.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -41,12 +41,6 @@ class Tr8n::Base
|
|
41
41
|
def self.belongs_to(*attrs) self.attributes(*attrs); end
|
42
42
|
def self.has_many(*attrs) self.attributes(*attrs); end
|
43
43
|
|
44
|
-
def self.thread_safe_attributes(*attrs)
|
45
|
-
@thread_safe_attribute_names ||= []
|
46
|
-
@thread_safe_attribute_names += attrs.collect{|a| a.to_sym} unless attrs.nil?
|
47
|
-
@thread_safe_attribute_names
|
48
|
-
end
|
49
|
-
|
50
44
|
def method_missing(meth, *args, &block)
|
51
45
|
method_name = meth.to_s
|
52
46
|
method_suffix = method_name[-1, 1]
|
@@ -56,21 +50,13 @@ class Tr8n::Base
|
|
56
50
|
end
|
57
51
|
|
58
52
|
if self.class.attributes.index(method_key)
|
59
|
-
if
|
53
|
+
if method_suffix == '='
|
60
54
|
attributes[method_key] = args.first
|
61
55
|
return attributes[method_key]
|
62
56
|
end
|
63
57
|
return attributes[method_key]
|
64
58
|
end
|
65
59
|
|
66
|
-
if self.class.thread_safe_attributes.index(method_key)
|
67
|
-
if method_name[-1, 1] == '='
|
68
|
-
Thread.current[method_key] = args.first
|
69
|
-
return Thread.current[method_key]
|
70
|
-
end
|
71
|
-
return Thread.current[method_key]
|
72
|
-
end
|
73
|
-
|
74
60
|
super
|
75
61
|
end
|
76
62
|
|
@@ -90,12 +76,6 @@ class Tr8n::Base
|
|
90
76
|
self.class.hash_value(hash, key, opts)
|
91
77
|
end
|
92
78
|
|
93
|
-
def reset!
|
94
|
-
self.class.thread_safe_attributes.each do |key|
|
95
|
-
Thread.current[key] = nil
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
79
|
def to_hash(*attrs)
|
100
80
|
if attrs.nil? or attrs.empty?
|
101
81
|
# default hashing only includes basic types
|
data/lib/tr8n/cache.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -25,8 +25,8 @@ module Tr8n
|
|
25
25
|
|
26
26
|
def self.cache
|
27
27
|
@cache ||= begin
|
28
|
-
if Tr8n.config.
|
29
|
-
klass = Tr8n::CacheAdapters.const_get(Tr8n.config.
|
28
|
+
if Tr8n.config.cache[:enabled]
|
29
|
+
klass = Tr8n::CacheAdapters.const_get(Tr8n.config.cache[:adapter].camelcase)
|
30
30
|
klass.new
|
31
31
|
else
|
32
32
|
# blank implementation
|
@@ -40,7 +40,7 @@ module Tr8n
|
|
40
40
|
def version
|
41
41
|
@version ||= begin
|
42
42
|
v = fetch('tr8n_cache_version', :skip_version => true)
|
43
|
-
v ? v['version'] : Tr8n.config.
|
43
|
+
v ? v['version'] : Tr8n.config.cache[:version]
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -54,7 +54,7 @@ module Tr8n
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def enabled?
|
57
|
-
Tr8n.config.
|
57
|
+
Tr8n.config.cache[:enabled]
|
58
58
|
end
|
59
59
|
|
60
60
|
def cached_by_source?
|
@@ -126,13 +126,13 @@ module Tr8n
|
|
126
126
|
when Tr8n::Application.cache_prefix
|
127
127
|
return Tr8n::Application.new(JSON.parse(data))
|
128
128
|
when Tr8n::Language.cache_prefix
|
129
|
-
return Tr8n::Language.new(JSON.parse(data).merge(:application => Tr8n.
|
129
|
+
return Tr8n::Language.new(JSON.parse(data).merge(:application => Tr8n.session.application))
|
130
130
|
when Tr8n::Source.cache_prefix
|
131
|
-
return Tr8n::Source.new(JSON.parse(data).merge(:application => Tr8n.
|
131
|
+
return Tr8n::Source.new(JSON.parse(data).merge(:application => Tr8n.session.application))
|
132
132
|
when Tr8n::Component.cache_prefix
|
133
|
-
return Tr8n::Component.new(JSON.parse(data).merge(:application => Tr8n.
|
133
|
+
return Tr8n::Component.new(JSON.parse(data).merge(:application => Tr8n.session.application))
|
134
134
|
when Tr8n::TranslationKey.cache_prefix
|
135
|
-
return Tr8n::TranslationKey.new(JSON.parse(data).merge(:application => Tr8n.
|
135
|
+
return Tr8n::TranslationKey.new(JSON.parse(data).merge(:application => Tr8n.session.application))
|
136
136
|
end
|
137
137
|
|
138
138
|
# API response form will be here
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -30,7 +30,7 @@ class Tr8n::CacheAdapters::Cdb < Tr8n::Cache
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.cache_path
|
33
|
-
"#{Tr8n.config.
|
33
|
+
"#{Tr8n.config.cache[:path]}/cdb/current.cdb"
|
34
34
|
end
|
35
35
|
|
36
36
|
def cached_by_source?
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -24,7 +24,7 @@
|
|
24
24
|
class Tr8n::CacheAdapters::File < Tr8n::Cache
|
25
25
|
|
26
26
|
def self.cache_path
|
27
|
-
"#{Tr8n.config.
|
27
|
+
"#{Tr8n.config.cache[:path]}/files/current"
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.file_name(key)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -27,7 +27,7 @@ class Tr8n::CacheAdapters::Memcache < Tr8n::Cache
|
|
27
27
|
|
28
28
|
def initialize
|
29
29
|
options = { :namespace => "tr8n", :compress => true }
|
30
|
-
@cache = Dalli::Client.new(Tr8n.config.
|
30
|
+
@cache = Dalli::Client.new(Tr8n.config.cache[:host], options)
|
31
31
|
end
|
32
32
|
|
33
33
|
def read_only?
|
@@ -58,7 +58,7 @@ class Tr8n::CacheAdapters::Memcache < Tr8n::Cache
|
|
58
58
|
|
59
59
|
def store(key, data, opts = {})
|
60
60
|
info("Cache store: #{key}")
|
61
|
-
ttl = opts[:ttl] || Tr8n.config.
|
61
|
+
ttl = opts[:ttl] || Tr8n.config.cache[:timeout]
|
62
62
|
@cache.set(versioned_key(key, opts), serialize_object(key, data), ttl)
|
63
63
|
data
|
64
64
|
rescue Exception => ex
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2014 Michael Berkovich, tr8nhub.com
|
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
|
@@ -26,7 +26,7 @@ require 'redis' if defined?(::Redis)
|
|
26
26
|
class Tr8n::CacheAdapters::Redis < Tr8n::Cache
|
27
27
|
|
28
28
|
def initialize
|
29
|
-
cache_host, cache_port = Tr8n.config.
|
29
|
+
cache_host, cache_port = Tr8n.config.cache[:host].split(':') if Tr8n.config.cache[:host]
|
30
30
|
cache_host ||= 'localhost'
|
31
31
|
cache_port ||= 6379
|
32
32
|
|
@@ -61,7 +61,7 @@ class Tr8n::CacheAdapters::Redis < Tr8n::Cache
|
|
61
61
|
|
62
62
|
def store(key, data, opts = {})
|
63
63
|
info("Cache store: #{key}")
|
64
|
-
ttl = opts[:ttl] || Tr8n.config.
|
64
|
+
ttl = opts[:ttl] || Tr8n.config.cache[:timeout]
|
65
65
|
versioned_key = versioned_key(key, opts)
|
66
66
|
|
67
67
|
@cache.set(versioned_key, serialize_object(key, data))
|
data/lib/tr8n/component.rb
CHANGED