yatapp 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +88 -19
- data/lib/tasks/yata.rake +1 -1
- data/lib/yatapp.rb +10 -38
- data/lib/yatapp/configuration.rb +5 -1
- data/lib/yatapp/inbox.rb +45 -0
- data/lib/yatapp/socket.rb +235 -0
- data/lib/yatapp/version.rb +1 -1
- data/lib/yatapp/yata_api_caller.rb +47 -43
- data/yatapp.gemspec +6 -3
- metadata +51 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4e4df0058b393f148836a6d4823cc6f9fa5ba2b
|
4
|
+
data.tar.gz: 1454817ed2b8790839ee1dda1cccd44d29653f08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0638437c0d6046cdaae8d5598a6a091a8e7e9a70bd19cbe1b90316a4ec622b166b37aca927d3c8a341cfc10208dac7202b60bc15a9f986dc8cd43c8e4da399e4'
|
7
|
+
data.tar.gz: 56c4ca50d7f120ad2568ff79ae4013bfd91a6adb54842efc860d54e1ee2e0e7cf7af38dd43b462f5f512f452446ffe587f1a031062a4270db828bd0e8d12c8c7
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -18,40 +18,109 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
$ gem install yatapp
|
20
20
|
|
21
|
-
##
|
22
|
-
Before using Yata integration gem you need to configure it.
|
23
|
-
We recommend adding the following lines to freshly created initialiser
|
24
|
-
in your rails project:
|
21
|
+
## Configuration
|
25
22
|
|
23
|
+
Gem can be used in two ways:
|
24
|
+
* integration through API
|
25
|
+
* websocket integration
|
26
|
+
|
27
|
+
### Configuration Parameters
|
28
|
+
|
29
|
+
* `api_access_token` - access key to Yata (Organizations Settings > Security > API token)
|
30
|
+
* `project_id` - project id you wish to fetch from (Organizations Settings > Security> Projects > Id)
|
31
|
+
* `languages` - supported locales, add any locale you wish. Default: `[:en]`
|
32
|
+
* `translation_format` - format you wish to get files in, available for now are (yaml, js, json, properties, xml, strings and plist). Default: `json`
|
33
|
+
* `save_to_path` - you can define where files should be saved. Default: `/config/locales/`
|
34
|
+
* `root` - add locale as root to file with translations. Default: `false`
|
35
|
+
|
36
|
+
First two parameters are required and the rest is optional.
|
37
|
+
|
38
|
+
Translations with root set to `false`:
|
39
|
+
|
40
|
+
```yaml
|
41
|
+
# en.yml
|
42
|
+
|
43
|
+
hello: Hello
|
44
|
+
hello_name: Hello %{name}
|
45
|
+
```
|
46
|
+
|
47
|
+
Translations with root set to `true`:
|
48
|
+
```yaml
|
49
|
+
# en.yml
|
50
|
+
|
51
|
+
en:
|
52
|
+
hello: Hello
|
53
|
+
hello_name: Hello %{name}
|
54
|
+
```
|
55
|
+
|
56
|
+
### API Integration
|
57
|
+
|
58
|
+
Recommended configuration:
|
26
59
|
|
27
60
|
```ruby
|
61
|
+
# config/initializers/yatapp.rb
|
28
62
|
|
29
63
|
include Yatapp
|
30
64
|
|
31
65
|
Yatapp.configure do |c|
|
32
|
-
c.api_access_token = ENV['YATA_API_KEY']
|
66
|
+
c.api_access_token = ENV['YATA_API_KEY']
|
67
|
+
c.project_id = ENV['YATA_PROJECT_ID']
|
68
|
+
c.languages = ['en', 'de', 'en_US']
|
69
|
+
c.translations_format = 'json'
|
33
70
|
end
|
71
|
+
```
|
34
72
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
73
|
+
To save file in a different location from default or add a locale as a root, add to configuration two lines as in example below:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# config/initializers/yatapp.rb
|
77
|
+
|
78
|
+
include Yatapp
|
79
|
+
|
80
|
+
Yatapp.configure do |c|
|
81
|
+
c.api_access_token = ENV['YATA_API_KEY']
|
82
|
+
c.project_id = ENV['YATA_PROJECT_ID']
|
83
|
+
c.languages = ['en', 'de', 'en_US']
|
84
|
+
c.translations_format = 'json'
|
85
|
+
c.save_to_path = '/public/locales/'
|
86
|
+
c.root = true
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
From now on your translations will be saved in `/public/locales/` directory and translations will have locale as a root.
|
91
|
+
|
92
|
+
|
93
|
+
API integration allows you to download all translations using rake task:
|
94
|
+
|
95
|
+
```bash
|
96
|
+
$ rake yata:fetch_translations
|
97
|
+
```
|
98
|
+
|
99
|
+
### Websocket Integration
|
100
|
+
|
101
|
+
Websocket integration connects to Yata server and stays open. All changes in translations are auto-fetched to the app.
|
40
102
|
|
41
|
-
|
42
|
-
# (in this case to support rails assets pipe line)
|
43
|
-
# please notice that if 'save_to_path' is not specified gem will save translations to the local directory
|
44
|
-
# or in case of rails application into 'config/locales' directory
|
103
|
+
When app connects to the Yata server for the first time it downloads all translation and saves them to the i18n store. Then all actions on translations like create, update and delete are broadcasting information and i18n store is updated.
|
45
104
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
105
|
+
Add this line to configuration if you want to enable websocket integration.
|
106
|
+
|
107
|
+
``` ruby
|
108
|
+
# config/initializers/yatapp.rb
|
109
|
+
|
110
|
+
include Yatapp
|
111
|
+
|
112
|
+
Yatapp.configure do |c|
|
113
|
+
c.api_access_token = ENV['YATA_API_KEY']
|
114
|
+
c.project_id = ENV['YATA_PROJECT_ID']
|
115
|
+
c.languages = ['en', 'de', 'en_US']
|
51
116
|
end
|
52
117
|
|
118
|
+
Yatapp.start_websocket
|
119
|
+
|
53
120
|
```
|
54
121
|
|
122
|
+
|
123
|
+
|
55
124
|
## Development
|
56
125
|
|
57
126
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/tasks/yata.rake
CHANGED
data/lib/yatapp.rb
CHANGED
@@ -2,55 +2,27 @@ require "yatapp/version"
|
|
2
2
|
require "yatapp/configuration"
|
3
3
|
require "yatapp/yata_api_caller"
|
4
4
|
require 'yatapp/railtie' if defined?(Rails)
|
5
|
+
require "yatapp/inbox.rb"
|
6
|
+
require "yatapp/socket.rb"
|
5
7
|
|
6
8
|
module Yatapp
|
7
9
|
extend Configuration
|
8
10
|
|
9
11
|
class << self
|
10
|
-
def
|
11
|
-
|
12
|
-
includer.extend(Methods)
|
13
|
-
end
|
14
|
-
|
15
|
-
def api_caller
|
16
|
-
@api_caller ||= YataApiCaller.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def all_projects
|
20
|
-
@all_projects ||= []
|
21
|
-
end
|
22
|
-
|
23
|
-
def all_projects_add(project)
|
24
|
-
@all_projects ||= []
|
25
|
-
@all_projects << project
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module Methods
|
30
|
-
def yata_project
|
31
|
-
@current_project = YataApiCaller.new
|
32
|
-
yield
|
33
|
-
Yatapp.all_projects_add(@current_project)
|
34
|
-
end
|
35
|
-
|
36
|
-
def languages(languages)
|
37
|
-
@current_project.set_languages(languages)
|
38
|
-
end
|
39
|
-
|
40
|
-
def save_to_path(path)
|
41
|
-
@current_project.set_save_to_path(path)
|
12
|
+
def get_translations
|
13
|
+
api_caller.get_translations
|
42
14
|
end
|
43
15
|
|
44
|
-
def
|
45
|
-
|
16
|
+
def download_translations
|
17
|
+
api_caller.download_translations
|
46
18
|
end
|
47
19
|
|
48
|
-
def
|
49
|
-
|
20
|
+
def start_websocket
|
21
|
+
Phoenix::Socket.new unless File.basename($0) == 'rake'
|
50
22
|
end
|
51
23
|
|
52
|
-
def
|
53
|
-
|
24
|
+
def api_caller
|
25
|
+
@api_caller ||= YataApiCaller.new
|
54
26
|
end
|
55
27
|
end
|
56
28
|
end
|
data/lib/yatapp/configuration.rb
CHANGED
data/lib/yatapp/inbox.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'mutex_m'
|
2
|
+
module Phoenix
|
3
|
+
class Inbox
|
4
|
+
# Read it or forget it
|
5
|
+
|
6
|
+
include Mutex_m
|
7
|
+
attr_reader :ttl, :data
|
8
|
+
def initialize(ttl:)
|
9
|
+
@ttl = ttl
|
10
|
+
@bucket = Time.now.to_i / ttl
|
11
|
+
@data = Hash.new { |h, k| h[k] = {} }
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def push(key, val)
|
16
|
+
synchronize do
|
17
|
+
ts = current_timestamp
|
18
|
+
(data[ts][key] = val).tap do
|
19
|
+
if data.keys.size >= 3
|
20
|
+
data.delete_if { |key, _| key < (ts - 1) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :[]=, :push
|
27
|
+
|
28
|
+
def pop(key)
|
29
|
+
synchronize do
|
30
|
+
ts = current_timestamp
|
31
|
+
data[ts - 1].delete(key) { data[ts].delete(key) { yield }}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :delete, :pop
|
36
|
+
|
37
|
+
def key?(key)
|
38
|
+
data.values.any? { |v| v.key?(key) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_timestamp
|
42
|
+
Time.now.to_i / ttl
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'faye/websocket'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'yatapp/inbox'
|
4
|
+
require 'json'
|
5
|
+
require 'cgi'
|
6
|
+
require 'uri'
|
7
|
+
require 'pry'
|
8
|
+
begin
|
9
|
+
require 'rails-i18n'
|
10
|
+
rescue
|
11
|
+
puts "WARNING: Failed to require rails-i18n gem, websocket integration may fail."
|
12
|
+
end
|
13
|
+
|
14
|
+
module Phoenix
|
15
|
+
class Socket
|
16
|
+
include MonitorMixin
|
17
|
+
attr_reader :path, :socket, :inbox, :topic
|
18
|
+
attr_accessor :verbose, :join_options_proc, :connect_options_proc
|
19
|
+
attr_accessor *Yatapp::Configuration::CONFIGURATION_OPTIONS
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
initialize_configuration
|
23
|
+
@path = "ws://run.yatapp.net/socket/websocket?api_token=#{api_access_token}"
|
24
|
+
@topic = "translations:#{project_id}"
|
25
|
+
@join_options = {}
|
26
|
+
@connect_options = {}
|
27
|
+
@inbox = Phoenix::Inbox.new(ttl: 15)
|
28
|
+
super() # MonitorMixin
|
29
|
+
@inbox_cond = new_cond
|
30
|
+
@thread_ready = new_cond
|
31
|
+
@topic_cond = new_cond
|
32
|
+
reset_state_conditions
|
33
|
+
request_reply(event: "ping", payload: {})
|
34
|
+
end
|
35
|
+
|
36
|
+
def request_reply(event:, payload: {}, timeout: 5) # timeout in seconds
|
37
|
+
ref = SecureRandom.uuid
|
38
|
+
synchronize do
|
39
|
+
ensure_connection
|
40
|
+
@topic_cond.wait_until { @topic_joined }
|
41
|
+
EM.next_tick { socket.send({ topic: topic, event: event, payload: payload, ref: ref }.to_json) }
|
42
|
+
log [event, ref]
|
43
|
+
|
44
|
+
# Ruby's condition variables only support timeout on the basic 'wait' method;
|
45
|
+
# This should behave roughly as if wait_until also support a timeout:
|
46
|
+
# `inbox_cond.wait_until(timeout) { inbox.key?(ref) || @dead }
|
47
|
+
#
|
48
|
+
# Note that this serves only to unblock the main thread, and should not halt execution of the
|
49
|
+
# socket connection. Therefore, there is a possibility that the inbox may pile up with
|
50
|
+
# unread messages if a lot of timeouts are encountered. A self-sweeping inbox will
|
51
|
+
# be implemented to prevent this.
|
52
|
+
ts = Time.now
|
53
|
+
loop do
|
54
|
+
inbox_cond.wait(timeout) # waits until time expires or signaled
|
55
|
+
break if inbox.key?(ref) || @dead
|
56
|
+
raise 'timeout' if timeout && Time.now > (ts + timeout)
|
57
|
+
end
|
58
|
+
inbox.delete(ref) { raise "reply #{ref} not found" }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def join_options
|
63
|
+
return @join_options unless join_options_proc
|
64
|
+
join_options_proc.call(@join_options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def connect_options
|
68
|
+
return @connect_options unless connect_options_proc
|
69
|
+
connect_options_proc.call(@connect_options)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_reader :inbox_cond, :thread_ready
|
75
|
+
|
76
|
+
def initialize_configuration
|
77
|
+
options = Yatapp.options
|
78
|
+
Yatapp::Configuration::CONFIGURATION_OPTIONS.each do |key|
|
79
|
+
send("#{key}=", options[key])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def log(msg)
|
84
|
+
return unless @verbose
|
85
|
+
puts "[#{Thread.current[:id]}] #{msg} (#@topic_joined)"
|
86
|
+
end
|
87
|
+
|
88
|
+
def ensure_connection
|
89
|
+
connection_alive? or synchronize do
|
90
|
+
spawn_thread
|
91
|
+
thread_ready.wait(3)
|
92
|
+
if @dead
|
93
|
+
@spawned = false
|
94
|
+
raise 'dead connection timeout'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def connection_alive?
|
100
|
+
@ws_thread&.alive? && !@dead
|
101
|
+
end
|
102
|
+
|
103
|
+
def reset_state_conditions
|
104
|
+
@dead = true # no EM thread active, or the connection has been closed
|
105
|
+
@socket = nil # the Faye::Websocket::Client instance
|
106
|
+
@spawned = false # The thread running (or about to run) EventMachine has been launched
|
107
|
+
@join_ref = SecureRandom.uuid # unique id that Phoenix uses to identify the socket <-> channel connection
|
108
|
+
@topic_joined = false # The initial join request has been acked by the remote server
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_new_key_to_i18n(key, values)
|
112
|
+
values.each do |value|
|
113
|
+
unless I18n.available_locales.include?(value['lang'].to_sym)
|
114
|
+
add_new_locale(value['lang'])
|
115
|
+
end
|
116
|
+
|
117
|
+
key_array = key.split(".")
|
118
|
+
translation_hash = key_array.reverse.inject(value['text']) {|acc, n| {n => acc}}
|
119
|
+
I18n.backend.store_translations(value['lang'].to_sym, translation_hash)
|
120
|
+
puts "new translation added: #{value['lang']} => #{key}: #{value['text']}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_new_locale(lang)
|
125
|
+
existing_locales = I18n.config.available_locales
|
126
|
+
new_locales = existing_locales << lang.to_sym
|
127
|
+
I18n.config.available_locales = new_locales.uniq
|
128
|
+
end
|
129
|
+
|
130
|
+
def handle_message(event)
|
131
|
+
data = JSON.parse(event.data)
|
132
|
+
log event.data
|
133
|
+
synchronize do
|
134
|
+
if data['event'] == 'phx_close'
|
135
|
+
log('handling close from message')
|
136
|
+
handle_close(event)
|
137
|
+
elsif data['event'] == 'new_translation'
|
138
|
+
payload = data['payload']
|
139
|
+
add_new_key_to_i18n(payload['key'], payload['values'])
|
140
|
+
elsif data['event'] == 'updated_translation'
|
141
|
+
payload = data['payload']
|
142
|
+
add_new_key_to_i18n(payload['new_key'], payload['values'])
|
143
|
+
elsif data['event'] == 'deleted translation'
|
144
|
+
puts 'deleted translation'
|
145
|
+
elsif data['ref'] == @join_ref && data['event'] == 'phx_error'
|
146
|
+
# NOTE: For some reason, on errors phx will send the join ref instead of the message ref
|
147
|
+
inbox_cond.broadcast
|
148
|
+
elsif data['ref'] == @join_ref
|
149
|
+
log ['join_ref', @join_ref]
|
150
|
+
@topic_joined = true
|
151
|
+
@topic_cond.broadcast
|
152
|
+
else
|
153
|
+
inbox[data['ref']] = data
|
154
|
+
inbox_cond.broadcast
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def handle_open(event)
|
160
|
+
log 'open'
|
161
|
+
socket.send({ topic: topic, event: "phx_join", payload: join_options, ref: @join_ref, join_ref: @join_ref }.to_json)
|
162
|
+
synchronize do
|
163
|
+
@dead = false
|
164
|
+
thread_ready.broadcast
|
165
|
+
end
|
166
|
+
Yatapp.download_translations
|
167
|
+
end
|
168
|
+
|
169
|
+
def handle_close(event)
|
170
|
+
synchronize do
|
171
|
+
reset_state_conditions
|
172
|
+
inbox_cond.signal
|
173
|
+
thread_ready.signal
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def build_path
|
178
|
+
uri = URI.parse(path)
|
179
|
+
existing_query = CGI.parse(uri.query || '')
|
180
|
+
uri.query = URI.encode_www_form(existing_query.merge(connect_options))
|
181
|
+
uri.to_s
|
182
|
+
end
|
183
|
+
|
184
|
+
def spawn_thread
|
185
|
+
return if @spawned || connection_alive?
|
186
|
+
log 'spawning...'
|
187
|
+
@spawned = true
|
188
|
+
@ws_thread = Thread.new do
|
189
|
+
Thread.current[:id] = "WSTHREAD_#{SecureRandom.hex(3)}"
|
190
|
+
run_event_machine
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def reconnect
|
195
|
+
@spawned = true
|
196
|
+
@ws_thread = Thread.new do
|
197
|
+
Thread.current[:id] = "WSTHREAD_#{SecureRandom.hex(3)}"
|
198
|
+
run_event_machine
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def run_event_machine
|
203
|
+
EM.run do
|
204
|
+
synchronize do
|
205
|
+
log 'em.run.sync'
|
206
|
+
@socket = Faye::WebSocket::Client.new(build_path)
|
207
|
+
socket.on :open do |event|
|
208
|
+
handle_open(event)
|
209
|
+
end
|
210
|
+
|
211
|
+
socket.on :message do |event|
|
212
|
+
handle_message(event)
|
213
|
+
end
|
214
|
+
|
215
|
+
socket.on :close do |event|
|
216
|
+
log [:close, event.code, event.reason]
|
217
|
+
handle_close(event)
|
218
|
+
EM.tick_loop do
|
219
|
+
unless connection_alive?
|
220
|
+
spawn_thread
|
221
|
+
sleep(1)
|
222
|
+
else
|
223
|
+
EM.next_tick { socket.send({ topic: "translations:#{project_id}", event: "ping", payload: {}, ref: @join_ref }.to_json) }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
EventMachine.add_periodic_timer(50) do
|
229
|
+
EM.next_tick { socket.send({ topic: "translations:#{project_id}", event: "ping", payload: {}, ref: @join_ref }.to_json) }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
data/lib/yatapp/version.rb
CHANGED
@@ -1,60 +1,45 @@
|
|
1
|
-
require '
|
2
|
-
require 'typhoeus'
|
3
|
-
require 'typhoeus/adapters/faraday'
|
4
|
-
require 'pry'
|
1
|
+
require 'httparty'
|
5
2
|
|
6
3
|
module Yatapp
|
7
4
|
class YataApiCaller
|
8
5
|
API_VERSION = 'v1'
|
9
6
|
API_END_POINT_URL = "/api/:api_version/project/:project_id/:lang/:format"
|
10
|
-
API_BASE_URL = "http://
|
11
|
-
API_CALLER_ATTRIBUTES = [
|
12
|
-
:connection,
|
13
|
-
:languages,
|
14
|
-
:project_id,
|
15
|
-
:save_to_path,
|
16
|
-
:translation_format
|
17
|
-
].freeze
|
7
|
+
API_BASE_URL = "http://run.yatapp.net"
|
18
8
|
|
19
9
|
attr_accessor *Yatapp::Configuration::CONFIGURATION_OPTIONS
|
20
|
-
attr_reader *API_CALLER_ATTRIBUTES
|
21
10
|
|
22
11
|
def initialize
|
23
|
-
initialize_configuration
|
24
12
|
@translation_format = 'json'
|
25
13
|
@save_to_path = ""
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
def set_languages(languages)
|
30
|
-
@languages = languages
|
31
|
-
end
|
32
|
-
|
33
|
-
def set_project_id(project_id)
|
34
|
-
@project_id = project_id
|
35
|
-
end
|
36
|
-
|
37
|
-
def set_save_to_path(path)
|
38
|
-
@save_to_path = path
|
39
|
-
end
|
40
|
-
|
41
|
-
def set_translation_format(translation_format)
|
42
|
-
@translation_format = translation_format
|
14
|
+
@root = false
|
15
|
+
@languages = ['en']
|
16
|
+
initialize_configuration
|
43
17
|
end
|
44
18
|
|
45
19
|
def get_translations
|
46
20
|
languages.each do |lang|
|
47
21
|
puts "Getting translation for #{lang}"
|
48
22
|
api_url = download_url(lang)
|
49
|
-
api_response =
|
23
|
+
api_response = HTTParty.get(api_url)
|
50
24
|
next if !should_save_the_translation?(api_response)
|
51
25
|
save_translation(lang, api_response)
|
52
26
|
end
|
53
27
|
end
|
54
28
|
|
29
|
+
def download_translations
|
30
|
+
languages.each do |lang|
|
31
|
+
puts "Getting translation for #{lang}"
|
32
|
+
api_url = download_url_websocket(lang)
|
33
|
+
puts api_url
|
34
|
+
api_response = HTTParty.get(api_url)
|
35
|
+
next if !should_save_the_translation?(api_response)
|
36
|
+
add_new_key_to_i18n(lang, JSON.parse(api_response.body))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
55
40
|
private
|
56
41
|
def should_save_the_translation?(api_response)
|
57
|
-
if api_response.
|
42
|
+
if api_response.code != 200
|
58
43
|
puts "INVALID RESPONSE: #{api_response.body}"
|
59
44
|
return false
|
60
45
|
end
|
@@ -68,16 +53,10 @@ module Yatapp
|
|
68
53
|
end
|
69
54
|
end
|
70
55
|
|
71
|
-
def prepare_connection
|
72
|
-
Faraday.new(url: API_BASE_URL) do |faraday|
|
73
|
-
faraday.adapter :typhoeus
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
56
|
def save_translation(lang, response)
|
78
57
|
bfp = save_file_path
|
79
|
-
File.open("#{bfp}#{lang}
|
80
|
-
puts "#{lang}
|
58
|
+
File.open("#{bfp}#{lang}.#{translation_format}", 'wb') { |f| f.write(response.body) }
|
59
|
+
puts "#{lang}.#{translation_format} saved"
|
81
60
|
end
|
82
61
|
|
83
62
|
def save_file_path
|
@@ -89,12 +68,37 @@ module Yatapp
|
|
89
68
|
end
|
90
69
|
|
91
70
|
def download_url(lang)
|
92
|
-
url = API_END_POINT_URL
|
71
|
+
url = API_BASE_URL + API_END_POINT_URL
|
72
|
+
url = url.sub(':project_id', project_id)
|
93
73
|
url = url.sub(':format', translation_format)
|
94
74
|
url = url.sub(':api_version', API_VERSION)
|
95
75
|
url = url.sub(':lang', lang)
|
96
|
-
url = url + "?apiToken=#{api_access_token}"
|
76
|
+
url = url + "?apiToken=#{api_access_token}&root=#{root}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def download_url_websocket(lang)
|
80
|
+
url = API_BASE_URL + API_END_POINT_URL
|
81
|
+
url = url.sub(':project_id', project_id)
|
82
|
+
url = url.sub(':format', 'json')
|
83
|
+
url = url.sub(':api_version', API_VERSION)
|
84
|
+
url = url.sub(':lang', lang)
|
85
|
+
url = url + "?apiToken=#{api_access_token}&root=true"
|
97
86
|
end
|
98
87
|
|
88
|
+
def add_new_key_to_i18n(lang, api_response)
|
89
|
+
unless I18n.available_locales.include?(lang.to_sym)
|
90
|
+
add_new_locale(lang)
|
91
|
+
end
|
92
|
+
|
93
|
+
translations = api_response[lang]
|
94
|
+
I18n.backend.store_translations(lang.to_sym, translations)
|
95
|
+
puts "Loaded all #{lang} translations."
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_new_locale(lang)
|
99
|
+
existing_locales = I18n.config.available_locales
|
100
|
+
new_locales = existing_locales << lang.to_sym
|
101
|
+
I18n.config.available_locales = new_locales.uniq
|
102
|
+
end
|
99
103
|
end
|
100
104
|
end
|
data/yatapp.gemspec
CHANGED
@@ -27,9 +27,12 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
spec.add_dependency '
|
31
|
-
spec.add_dependency '
|
32
|
-
spec.
|
30
|
+
spec.add_dependency 'faye-websocket'
|
31
|
+
spec.add_dependency 'rails-i18n'
|
32
|
+
spec.add_dependency 'httparty'
|
33
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
33
34
|
spec.add_development_dependency "pry"
|
34
35
|
spec.add_development_dependency "rake", "~> 10.0"
|
36
|
+
spec.add_development_dependency "rspec"
|
37
|
+
spec.add_development_dependency "webmock"
|
35
38
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yatapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- luki3k5
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: faye-websocket
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,7 +25,21 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rails-i18n
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: httparty
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - ">="
|
@@ -44,14 +58,14 @@ dependencies:
|
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1.
|
61
|
+
version: '1.16'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1.
|
68
|
+
version: '1.16'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: pry
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,34 @@ dependencies:
|
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: webmock
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
83
125
|
description: This gem allows for easy integration with Yata to fetch translation files
|
84
126
|
from the service
|
85
127
|
email:
|
@@ -101,7 +143,9 @@ files:
|
|
101
143
|
- lib/tasks/yata.rake
|
102
144
|
- lib/yatapp.rb
|
103
145
|
- lib/yatapp/configuration.rb
|
146
|
+
- lib/yatapp/inbox.rb
|
104
147
|
- lib/yatapp/railtie.rb
|
148
|
+
- lib/yatapp/socket.rb
|
105
149
|
- lib/yatapp/version.rb
|
106
150
|
- lib/yatapp/yata_api_caller.rb
|
107
151
|
- yatapp.gemspec
|
@@ -125,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
169
|
version: '0'
|
126
170
|
requirements: []
|
127
171
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
172
|
+
rubygems_version: 2.6.14
|
129
173
|
signing_key:
|
130
174
|
specification_version: 4
|
131
175
|
summary: This gem allows for easy integration with Yata to fetch translation files
|