zmeygo 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +120 -0
- data/README.ro.rdoc +0 -0
- data/README.ru.rdoc +0 -0
- data/Rakefile +2 -0
- data/TODO +2 -0
- data/bin/zg +61 -0
- data/lib/zmeygo/base.rb +39 -0
- data/lib/zmeygo/cache.rb +53 -0
- data/lib/zmeygo/client.rb +217 -0
- data/lib/zmeygo/command.rb +40 -0
- data/lib/zmeygo/configuration.rb +39 -0
- data/lib/zmeygo/constant.rb +8 -0
- data/lib/zmeygo/i18n_backend.rb +20 -0
- data/lib/zmeygo/version.rb +3 -0
- data/lib/zmeygo.rb +27 -0
- data/templates/zmeygo.yml.template +15 -0
- data/test/ext_i18n_test.rb +31 -0
- data/test/test_helper.rb +1 -0
- data/zmeygo.gemspec +24 -0
- metadata +77 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
= Zmeygo Client
|
2
|
+
|
3
|
+
Zmeygo client is a convinient tool to interface with zmeygo.com service. Zmeygo
|
4
|
+
service helps you to manage internationalization data of your rails applications.
|
5
|
+
|
6
|
+
== Why you need zmeygo client?
|
7
|
+
|
8
|
+
To syncronize with server. To manage i18n data, you need to push it on zmeygo.com server. i18n data are all keys you provide to I18n.translate (or its alias I18n.t) method. You can use client to <i>push keys to</i> the server. Also you can use client to <i>pull keys from</i> the server.
|
9
|
+
|
10
|
+
== Install
|
11
|
+
|
12
|
+
Install it as you would do for any other ruby gem
|
13
|
+
|
14
|
+
gem install zmeygo
|
15
|
+
|
16
|
+
After you do so you will have available zg executable. Check it with command:
|
17
|
+
|
18
|
+
zg help
|
19
|
+
|
20
|
+
Besides being available as an executable, zmeygo is available as gem which can
|
21
|
+
be included in Rails project. More on this later.
|
22
|
+
|
23
|
+
== Usage
|
24
|
+
|
25
|
+
=== Configuration
|
26
|
+
|
27
|
+
Every time you will run zg command it will check for configutation file
|
28
|
+
.zmeygo/config.yml in your home folder. To generate a template for config file
|
29
|
+
run command
|
30
|
+
|
31
|
+
zg init
|
32
|
+
|
33
|
+
Then go and edit ~/.zmeygo/config.yml. In config file add correct values for
|
34
|
+
|
35
|
+
* api_token - you can see your api_token in your user profile in zmeygo.com
|
36
|
+
|
37
|
+
* default_project - One user will have associated more the one project. Zmeygo client right now can work only with one of them - default project. When you will run zg command to push keys on the server, they will be pushed automatically to default project. Right now there is no other way to specify other project.
|
38
|
+
|
39
|
+
* locale_dir - this is place where zg client will download all pulled locale files from the server
|
40
|
+
Below is an example of ~/.zmego/config.yml file:
|
41
|
+
|
42
|
+
→ cat ~/.zmeygo/config.yml
|
43
|
+
# Configuration file for zmeygo
|
44
|
+
#
|
45
|
+
|
46
|
+
defaults: &defaults
|
47
|
+
server: http://zmeygo.com
|
48
|
+
api_token: 4e02abc123ef7e3528001231
|
49
|
+
default_project: my_proj
|
50
|
+
locale_dir: /home/john/rails_projects/my_proj/config/locales
|
51
|
+
|
52
|
+
development:
|
53
|
+
<<: *defaults
|
54
|
+
|
55
|
+
production:
|
56
|
+
<<: *defaults
|
57
|
+
|
58
|
+
=== Check server connection
|
59
|
+
|
60
|
+
In order to check server connectivity run command
|
61
|
+
|
62
|
+
zg ping
|
63
|
+
|
64
|
+
If you don't have connection to the server, then most probably you are behind
|
65
|
+
proxy (like me in the office). Setup environment variable $http_proxy or/and
|
66
|
+
$https_proxy and smart zg will detect and use it. If that didn't work like ISP
|
67
|
+
support says **check if you have plugged internet cable** :D
|
68
|
+
|
69
|
+
It will display OK if you can connect to server. Now you are ready for real
|
70
|
+
action!
|
71
|
+
|
72
|
+
=== Pull data from server
|
73
|
+
|
74
|
+
One of two greatest thing that zmeygo client was designed for is to pull data from
|
75
|
+
server. Command:
|
76
|
+
|
77
|
+
zg pull
|
78
|
+
|
79
|
+
This command will download locales files of default project (specified in config
|
80
|
+
file) to location locale_dir also specified in configuration file. This command
|
81
|
+
is a shortcut for downloading manually locale files. There will be downloaded
|
82
|
+
one file per locale. Existing locale files will be overriden.
|
83
|
+
|
84
|
+
=== Push data to server
|
85
|
+
|
86
|
+
Second of the greatest thing that zmeygo client was designed for is to push data
|
87
|
+
to the server. The command:
|
88
|
+
|
89
|
+
zg push
|
90
|
+
|
91
|
+
Will push all locally cached i18n key to the server. To list locally cached keys
|
92
|
+
use command:
|
93
|
+
|
94
|
+
zg list cache
|
95
|
+
|
96
|
+
I18n keys are stored in cached by zmeygo gem included in Rails application. Next
|
97
|
+
section describes this in detail.
|
98
|
+
|
99
|
+
=== Use zmeygo gem from Rails application
|
100
|
+
|
101
|
+
To make possible pushing of i18n keys to the zmeygo server, include zmeygo gem
|
102
|
+
into your rails project with gem 'zmeygo' in Gemfile. Then in your development
|
103
|
+
environment put
|
104
|
+
|
105
|
+
Zmeygo.configure
|
106
|
+
|
107
|
+
which will load configurations from ~/.zmeygo/config.yml file. Zmeygo gem adds
|
108
|
+
custom exception handler to I18n gem, thus every missing translation exeption
|
109
|
+
thrown by I18n will insert missing key into zmeygo local cache. This means that
|
110
|
+
you just add as usual I18n.t call to the view, then while you are browsing your
|
111
|
+
application views, missing keys will be collected by zmeygo locally. Here and
|
112
|
+
there, run somewhere in command line:
|
113
|
+
|
114
|
+
zg push
|
115
|
+
|
116
|
+
This will push all cached key to zmeygo server. And voila, you can translate
|
117
|
+
your keys to whatever locale you choose on the server.
|
118
|
+
|
119
|
+
Send all your questions to: eugen@zmeygo.com
|
120
|
+
|
data/README.ro.rdoc
ADDED
File without changes
|
data/README.ru.rdoc
ADDED
File without changes
|
data/Rakefile
ADDED
data/bin/zg
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require File.join(File.dirname(__FILE__),'../lib/zmeygo/base')
|
7
|
+
|
8
|
+
USAGE = <<USAGE
|
9
|
+
Client v#{Zmeygo::VERSION} used for zmeygo.com service.
|
10
|
+
----------------------------------------
|
11
|
+
Usage: zg COMMAND [options]
|
12
|
+
where COMMAND is one of following:
|
13
|
+
ping - run this command to check server connectivity.
|
14
|
+
config - generates configuration file in ~/zmeygo.yml
|
15
|
+
list [projects|locales|config|cache] - see respective details. See below.
|
16
|
+
pull - retrieve locales for specified project (and optionaly locale)
|
17
|
+
help - displays this screen
|
18
|
+
|
19
|
+
Below follows description of options for list command:
|
20
|
+
projects
|
21
|
+
lists all projects available for given api token
|
22
|
+
locales
|
23
|
+
lists all locales for default project
|
24
|
+
config
|
25
|
+
lists server url and default project's name
|
26
|
+
cache
|
27
|
+
lists all keys that were cached by I18n.t call and are ready to be sent to server
|
28
|
+
(server given by 'list config' option)
|
29
|
+
USAGE
|
30
|
+
|
31
|
+
# when no arguments are specified, then display help and exist
|
32
|
+
if ARGV.size < 1
|
33
|
+
OptparseZmeygo.parse([].push("--help"))
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
commands = {}
|
39
|
+
case ARGV[0]
|
40
|
+
when 'help'
|
41
|
+
puts USAGE
|
42
|
+
when 'push'
|
43
|
+
ARGV.shift
|
44
|
+
commands[:push] = true
|
45
|
+
when 'ping'
|
46
|
+
ARGV.shift
|
47
|
+
commands[:ping] = true
|
48
|
+
when 'pull'
|
49
|
+
ARGV.shift
|
50
|
+
commands[:pull] = true
|
51
|
+
when 'init'
|
52
|
+
ARGV.shift
|
53
|
+
commands[:init] = true
|
54
|
+
when 'list'
|
55
|
+
ARGV.shift
|
56
|
+
commands[:list] = ARGV.shift || true #need true here to make this at least reach client.list command
|
57
|
+
else
|
58
|
+
puts 'Unknown command. Run with --help to see all options or check http://zmeygo.com/help for documentation'
|
59
|
+
end
|
60
|
+
|
61
|
+
Zmeygo::Command.new(commands)
|
data/lib/zmeygo/base.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'json'
|
5
|
+
require 'i18n'
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/core_ext/hash'
|
8
|
+
require 'yaml'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
require File.join(File.dirname(__FILE__),'/version')
|
12
|
+
require File.join(File.dirname(__FILE__),'/constant')
|
13
|
+
require File.join(File.dirname(__FILE__),'/configuration')
|
14
|
+
require File.join(File.dirname(__FILE__),'/client')
|
15
|
+
require File.join(File.dirname(__FILE__),'/command')
|
16
|
+
require File.join(File.dirname(__FILE__),'/cache')
|
17
|
+
|
18
|
+
module Zmeygo
|
19
|
+
class << self
|
20
|
+
attr_accessor :client
|
21
|
+
attr_accessor :config
|
22
|
+
attr_accessor :cache
|
23
|
+
attr_accessor :logger
|
24
|
+
|
25
|
+
def method_missing(method, *args)
|
26
|
+
self.cache.respond_to?(method)? cache.send(method, *args) : super
|
27
|
+
end
|
28
|
+
|
29
|
+
def configure
|
30
|
+
self.config ||= Configuration.new
|
31
|
+
if block_given?
|
32
|
+
yield(config)
|
33
|
+
end
|
34
|
+
self.cache = Cache.new
|
35
|
+
self.logger = Logger.new($stdout)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/zmeygo/cache.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Zmeygo
|
4
|
+
# Cache is responsable to gather missing keys from I18n.t/I18n.translate
|
5
|
+
# calls and once in a while send them to server.
|
6
|
+
# Server where keys will be sent is configured in config file Zmeygo.config['server']
|
7
|
+
# All keys sent are for project mentioned in Zmeygo.config['default_project']
|
8
|
+
class Cache
|
9
|
+
attr_accessor :config
|
10
|
+
attr_accessor :missing_keys
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
self.config = Zmeygo.config
|
14
|
+
self.missing_keys = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_cache_proj
|
18
|
+
proj = validate_config!
|
19
|
+
proj
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_cache
|
23
|
+
proj = validate_config!
|
24
|
+
self.missing_keys[proj]
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_to_cache(key)
|
28
|
+
proj = validate_config!
|
29
|
+
self.missing_keys[proj] ||= {}
|
30
|
+
self.missing_keys[proj][key] = true
|
31
|
+
File.open(File.expand_path(Constant::CACHE_FILE),'w') do |f|
|
32
|
+
f.write(Marshal.dump(self.missing_keys))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def clear_cache
|
37
|
+
proj = validate_config!
|
38
|
+
self.missing_keys[proj].clear
|
39
|
+
File.truncate(File.expand_path(Constant::CACHE_FILE),0)
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_config!
|
43
|
+
proj = self.config['default_project']
|
44
|
+
if proj.blank?
|
45
|
+
raise "Please provide default project name in ~/.zmeygo/config.yml file"
|
46
|
+
end
|
47
|
+
self.missing_keys[proj] ||= {}
|
48
|
+
proj
|
49
|
+
end
|
50
|
+
|
51
|
+
end # Cache
|
52
|
+
end # Zmeygo
|
53
|
+
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'ya2yaml'
|
3
|
+
|
4
|
+
module Zmeygo
|
5
|
+
class Client
|
6
|
+
|
7
|
+
attr_accessor :config, :options
|
8
|
+
|
9
|
+
def initialize(options={})
|
10
|
+
self.options = options
|
11
|
+
self.config = Zmeygo.config
|
12
|
+
end
|
13
|
+
|
14
|
+
def push
|
15
|
+
url = "#{config['server']}/api/pushmissing?api_token=#{config['api_token']}"
|
16
|
+
hash = {}
|
17
|
+
keys = []
|
18
|
+
File.open(File.expand_path(Constant::CACHE_FILE,'r')) do |f|
|
19
|
+
data = f.read
|
20
|
+
begin
|
21
|
+
hash = Marshal.load(data)
|
22
|
+
rescue
|
23
|
+
puts "No cache"
|
24
|
+
return
|
25
|
+
end
|
26
|
+
end
|
27
|
+
Zmeygo.clear_cache
|
28
|
+
begin
|
29
|
+
puts "POST #{url}" if options[:verbose]
|
30
|
+
response = RestClient.post(url,:data => hash)
|
31
|
+
rescue
|
32
|
+
puts "Direct http request #{url} failed!" if options[:verbose]
|
33
|
+
if RestClient.proxy.nil?
|
34
|
+
puts "Now retrying through proxy..." if options[:verbose]
|
35
|
+
if ENV['http_proxy']
|
36
|
+
puts "Environment variable http_proxy found." if options[:verbose]
|
37
|
+
RestClient.proxy = ENV['http_proxy']
|
38
|
+
retry
|
39
|
+
end
|
40
|
+
end
|
41
|
+
puts "http request #{url} failed!"
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
if response.code == 200
|
45
|
+
reply = JSON.parse(response.body)
|
46
|
+
elsif response.code == 401
|
47
|
+
puts "Invalid api_token given."
|
48
|
+
elsif response.code == 500
|
49
|
+
puts "Ooops! Internal server error."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ping
|
54
|
+
puts "pinging server #{config[:server]} ..." if options[:verbose]
|
55
|
+
http_connect('ping') do |reply|
|
56
|
+
reply['message']
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def list_config
|
61
|
+
puts "Server: #{config[:server]}"
|
62
|
+
puts "Default project: #{config[:default_project]}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def list
|
66
|
+
case options[:list]
|
67
|
+
when "projects"
|
68
|
+
return list_projects
|
69
|
+
when "locales"
|
70
|
+
return list_locales
|
71
|
+
when "config"
|
72
|
+
return list_config
|
73
|
+
when 'cache'
|
74
|
+
return list_cache
|
75
|
+
else
|
76
|
+
return "list what? projects or locales or cache?"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def list_cache
|
81
|
+
hash = {}
|
82
|
+
total = 0
|
83
|
+
File.open(File.expand_path(Constant::CACHE_FILE,'r')) do |f|
|
84
|
+
data = f.read
|
85
|
+
begin
|
86
|
+
hash = Marshal.load(data)
|
87
|
+
rescue
|
88
|
+
puts "No cache"
|
89
|
+
return
|
90
|
+
end
|
91
|
+
end
|
92
|
+
if hash.empty?
|
93
|
+
puts "No cache"
|
94
|
+
else
|
95
|
+
hash.each_pair do |proj,v|
|
96
|
+
puts "===== #{proj} ====="
|
97
|
+
v.each_pair do |key,options|
|
98
|
+
puts "#{key} => #{options}"
|
99
|
+
total += 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
"==== Total #{total} keys ===="
|
104
|
+
end
|
105
|
+
|
106
|
+
def list_projects
|
107
|
+
http_connect('available_projects') do |reply|
|
108
|
+
if reply['message'] == 'OK'
|
109
|
+
return reply['data']
|
110
|
+
else
|
111
|
+
return reply['message']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def list_locales
|
117
|
+
project = options[:project]
|
118
|
+
project ||= config['default_project']
|
119
|
+
|
120
|
+
if project.nil?
|
121
|
+
return "Please provide project name for which I should list locales. Use -p option."
|
122
|
+
end
|
123
|
+
http_connect("available_locales/#{project}") do |reply|
|
124
|
+
if reply['message'] == 'OK'
|
125
|
+
return reply['data']
|
126
|
+
else
|
127
|
+
puts "#{reply['message']}"
|
128
|
+
return reply['message']
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def translate
|
134
|
+
project,locale,key = options[:project],options[:locale],options[:key]
|
135
|
+
project ||= config.default_project
|
136
|
+
|
137
|
+
http_connect("tr/#{project}/#{locale}/#{key}") do |reply|
|
138
|
+
if reply['message'] == 'OK'
|
139
|
+
return reply['data']
|
140
|
+
else
|
141
|
+
return reply['message']
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def pull
|
147
|
+
project, locale = options[:project],options[:locale]
|
148
|
+
project ||= config['default_project']
|
149
|
+
if project.nil?
|
150
|
+
puts "Please provide project name from where to pull i18n keys from. Either use -p option or specify default project in config file."
|
151
|
+
return
|
152
|
+
end
|
153
|
+
puts "Will save locales to #{config[:locale_dir]}"
|
154
|
+
if locale.nil?
|
155
|
+
# pull all available locales
|
156
|
+
locales = list_locales
|
157
|
+
# for each available locale requst i18n data
|
158
|
+
locales.split(',').each do |loc|
|
159
|
+
pull_translations(project,loc)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
pull_translations(project,locale)
|
163
|
+
end
|
164
|
+
"Done."
|
165
|
+
end
|
166
|
+
|
167
|
+
def http_connect(path)
|
168
|
+
url = "#{config['server']}/api/#{path}?api_token=#{config['api_token']}"
|
169
|
+
begin
|
170
|
+
puts "GET #{url}" if options[:verbose]
|
171
|
+
response = RestClient.get(url)
|
172
|
+
rescue
|
173
|
+
puts "Direct http request #{url} failed!" if options[:verbose]
|
174
|
+
if RestClient.proxy.nil?
|
175
|
+
puts "Now retrying through proxy..." if options[:verbose]
|
176
|
+
if ENV['http_proxy']
|
177
|
+
puts "Environment variable http_proxy found." if options[:verbose]
|
178
|
+
RestClient.proxy = ENV['http_proxy']
|
179
|
+
retry
|
180
|
+
end
|
181
|
+
end
|
182
|
+
puts "http request #{url} failed!"
|
183
|
+
exit
|
184
|
+
end
|
185
|
+
if response.code == 200
|
186
|
+
reply = JSON.parse(response.body)
|
187
|
+
yield(reply)
|
188
|
+
elsif response.code == 401
|
189
|
+
puts "Invalid api_token given."
|
190
|
+
elsif response.code == 500
|
191
|
+
puts "Ooops! Internal server error."
|
192
|
+
end
|
193
|
+
end
|
194
|
+
private
|
195
|
+
def pull_translations(project,locale_code)
|
196
|
+
request_line = "tr/#{project}/#{locale_code}"
|
197
|
+
http_connect(request_line) do |reply|
|
198
|
+
if reply['message'] == 'OK'
|
199
|
+
hash_result = reply['data']
|
200
|
+
config['locale_dir'] ||= File.join(FileUtils.pwd,'locales')
|
201
|
+
folder = config['locale_dir']
|
202
|
+
unless File.exists?(folder)
|
203
|
+
FileUtils.mkdir_p(folder)
|
204
|
+
end
|
205
|
+
File.open(folder + "/#{locale_code}.yml", 'w') do |f|
|
206
|
+
puts "saving file #{locale_code}.yml..."
|
207
|
+
f.write(hash_result.ya2yaml)
|
208
|
+
end
|
209
|
+
else
|
210
|
+
puts "Message: #{reply['message']}"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Zmeygo
|
3
|
+
class Command
|
4
|
+
|
5
|
+
attr_accessor :options, :client
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
if options[:init]
|
9
|
+
src_file = File.join(File.dirname(__FILE__),'../..','templates','zmeygo.yml.template')
|
10
|
+
dest_dir = File.expand_path(
|
11
|
+
File.dirname(Constant::DEFAULT_CONFIG_FILE)
|
12
|
+
)
|
13
|
+
dest_file = File.expand_path(Constant::DEFAULT_CONFIG_FILE)
|
14
|
+
unless File.exists?(dest_dir)
|
15
|
+
FileUtils.mkdir_p dest_dir
|
16
|
+
end
|
17
|
+
unless File.exists?(dest_file)
|
18
|
+
puts "Creating config file #{dest_file}..."
|
19
|
+
system "cp #{src_file} #{dest_file}"
|
20
|
+
puts "Done."
|
21
|
+
exit
|
22
|
+
else
|
23
|
+
puts "config file #{Constant::DEFAULT_CONFIG_FILE} already exists. Nothing to do."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Zmeygo.configure
|
28
|
+
|
29
|
+
self.options = options
|
30
|
+
self.client = Zmeygo::Client.new(options)
|
31
|
+
|
32
|
+
[:push,:pull,:list, :ping].each do |command|
|
33
|
+
ret = client.send(command) if options[command]
|
34
|
+
if ret.present?
|
35
|
+
puts ret
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
module Zmeygo
|
4
|
+
require 'yaml'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
class Configuration
|
8
|
+
attr_accessor :server, :api_token, :locale_dir, :default_project
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
src_file = File.join(File.dirname(__FILE__),'../..','templates','zmeygo.yml.template')
|
12
|
+
dest_dir = File.dirname(File.expand_path(Constant::DEFAULT_CONFIG_FILE))
|
13
|
+
dest_file = File.expand_path(Constant::DEFAULT_CONFIG_FILE)
|
14
|
+
|
15
|
+
unless File.exists?(dest_file)
|
16
|
+
puts "making folder #{dest_dir}"
|
17
|
+
FileUtils.mkdir dest_dir
|
18
|
+
system "cp #{src_file} #{dest_file}"
|
19
|
+
end
|
20
|
+
|
21
|
+
conf_all = YAML.load_file(File.expand_path(dest_file))
|
22
|
+
|
23
|
+
#TODO: change env to vailue of either RAILS_ENV, RACK_ENV or ZMEYGO_ENV
|
24
|
+
env = 'development'
|
25
|
+
conf = conf_all[env]
|
26
|
+
|
27
|
+
self.server = conf['server']
|
28
|
+
self.api_token = conf['api_token']
|
29
|
+
self.locale_dir = conf['locale_dir']
|
30
|
+
self.default_project = conf['default_project']
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](key)
|
34
|
+
if self.respond_to?(key)
|
35
|
+
send(key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Zmeygo
|
4
|
+
class I18nBackend
|
5
|
+
|
6
|
+
attr_accessor :client
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
@collection = {}
|
10
|
+
@options = options
|
11
|
+
Zmeygo.configure
|
12
|
+
self.client = Zmeygo::Client.new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def translate(locale, key, options = {})
|
16
|
+
client.translate(nil,locale,key)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/zmeygo.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__),'/zmeygo/base')
|
3
|
+
|
4
|
+
module I18n
|
5
|
+
class << self
|
6
|
+
def custom_exception_handler(*args)
|
7
|
+
args.shift
|
8
|
+
locale = args.shift
|
9
|
+
key = args.shift
|
10
|
+
Zmeygo.add_to_cache(key)
|
11
|
+
# return an aproximation of translation
|
12
|
+
# This is last part of dot separated key, with _ replaced with space,
|
13
|
+
# capitalized and inserted between square brakets. I found this to be best
|
14
|
+
# aproximation of future translation.
|
15
|
+
arr = key.to_s.split('.')
|
16
|
+
last = if arr.respond_to?(:last)
|
17
|
+
arr.last
|
18
|
+
else
|
19
|
+
arr
|
20
|
+
end
|
21
|
+
"["+last.tr('_',' ').capitalize+"]"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
I18n.exception_handler = :custom_exception_handler
|
25
|
+
end
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Configuration file for zmeygo
|
2
|
+
#
|
3
|
+
|
4
|
+
defaults: &defaults
|
5
|
+
server: http://zmeygo.com
|
6
|
+
api_token: <your account api_token here>
|
7
|
+
locale_dir: <full path to where locales files should be stored>
|
8
|
+
default_project: my_project_name
|
9
|
+
|
10
|
+
development:
|
11
|
+
<<: *defaults
|
12
|
+
|
13
|
+
production:
|
14
|
+
<<: *defaults
|
15
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'/test_helper')
|
2
|
+
require File.join(File.dirname(__FILE__),'../lib/zmeygo')
|
3
|
+
|
4
|
+
class ExtI18nTest < Test::Unit::TestCase
|
5
|
+
# check if i18n.t method indeed populates Zmeygo.missing_keys
|
6
|
+
def test_assert_i18n_translate
|
7
|
+
Zmeygo.clear_cache
|
8
|
+
assert_equal 0, Zmeygo.get_cache.size
|
9
|
+
I18n.t :key1
|
10
|
+
I18n.t :key2
|
11
|
+
assert_equal 2, Zmeygo.get_cache.size
|
12
|
+
assert Zmeygo.get_cache.include?(:key1)
|
13
|
+
assert Zmeygo.get_cache.include?(:key2)
|
14
|
+
end
|
15
|
+
|
16
|
+
# c
|
17
|
+
def test_if_i18n_correctly_populates_cache
|
18
|
+
Zmeygo.clear_cache
|
19
|
+
assert_equal 0, Zmeygo.get_cache.size
|
20
|
+
I18n.t :some_key
|
21
|
+
I18n.t :other_key
|
22
|
+
I18n.t 'text.signin'
|
23
|
+
cache = Zmeygo.get_cache.clone
|
24
|
+
proj = Zmeygo.get_cache_proj
|
25
|
+
assert_equal Zmeygo.config['default_project'],proj
|
26
|
+
assert cache.include?(:some_key)
|
27
|
+
assert cache.include?(:other_key)
|
28
|
+
assert cache.include?('text.signin')
|
29
|
+
assert cache.size == 3
|
30
|
+
end
|
31
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'test/unit'
|
data/zmeygo.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require 'zmeygo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "zmeygo"
|
8
|
+
s.version = Zmeygo::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Eugen Ciur"]
|
11
|
+
s.email = ["ciur.eugen@gmail.com"]
|
12
|
+
s.homepage = "http://zmeygo.com"
|
13
|
+
s.summary = "Zmeygo - smart and friendly drago that helps you localize any ruby application"
|
14
|
+
s.description = "Syncs local i18n data with Zmeygo server"
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.require_path = 'lib'
|
21
|
+
s.bindir = 'bin'
|
22
|
+
s.executables = ["zg"]
|
23
|
+
s.default_executable = "zg"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zmeygo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: "0.1"
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eugen Ciur
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-09-02 00:00:00 +03:00
|
14
|
+
default_executable: zg
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Syncs local i18n data with Zmeygo server
|
18
|
+
email:
|
19
|
+
- ciur.eugen@gmail.com
|
20
|
+
executables:
|
21
|
+
- zg
|
22
|
+
extensions: []
|
23
|
+
|
24
|
+
extra_rdoc_files: []
|
25
|
+
|
26
|
+
files:
|
27
|
+
- .gitignore
|
28
|
+
- Gemfile
|
29
|
+
- README.rdoc
|
30
|
+
- README.ro.rdoc
|
31
|
+
- README.ru.rdoc
|
32
|
+
- Rakefile
|
33
|
+
- TODO
|
34
|
+
- bin/zg
|
35
|
+
- lib/zmeygo.rb
|
36
|
+
- lib/zmeygo/base.rb
|
37
|
+
- lib/zmeygo/cache.rb
|
38
|
+
- lib/zmeygo/client.rb
|
39
|
+
- lib/zmeygo/command.rb
|
40
|
+
- lib/zmeygo/configuration.rb
|
41
|
+
- lib/zmeygo/constant.rb
|
42
|
+
- lib/zmeygo/i18n_backend.rb
|
43
|
+
- lib/zmeygo/version.rb
|
44
|
+
- templates/zmeygo.yml.template
|
45
|
+
- test/ext_i18n_test.rb
|
46
|
+
- test/test_helper.rb
|
47
|
+
- zmeygo.gemspec
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://zmeygo.com
|
50
|
+
licenses: []
|
51
|
+
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.5.2
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Zmeygo - smart and friendly drago that helps you localize any ruby application
|
76
|
+
test_files: []
|
77
|
+
|