phrase 0.0.1 → 0.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.
- data/Gemfile +3 -1
- data/Gemfile.lock +7 -1
- data/cacert.pem +3366 -0
- data/lib/phrase/backend/base.rb +34 -63
- data/lib/phrase/backend/phrase_service.rb +1 -3
- data/lib/phrase/backend.rb +2 -129
- data/lib/phrase/config.rb +49 -15
- data/lib/phrase/engine.rb +15 -10
- data/lib/phrase/extensions/base.rb +1 -0
- data/lib/phrase/extensions/hash.rb +1 -0
- data/lib/phrase/extensions/string.rb +1 -0
- data/lib/phrase/extensions.rb +5 -3
- data/lib/phrase/tool.rb +152 -29
- data/lib/phrase/tool_config.rb +17 -2
- data/lib/phrase/view_helpers.rb +18 -0
- data/lib/phrase.rb +25 -5
- data/phrase.gemspec +4 -3
- metadata +18 -4
data/lib/phrase/tool.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
1
3
|
require 'phrase/tool_config'
|
2
4
|
|
3
5
|
require 'optparse'
|
4
6
|
require 'net/http'
|
7
|
+
require 'net/https'
|
5
8
|
require 'fileutils'
|
6
9
|
|
7
10
|
module PhraseGem
|
@@ -28,6 +31,7 @@ module PhraseGem
|
|
28
31
|
end
|
29
32
|
|
30
33
|
private
|
34
|
+
|
31
35
|
def init(config)
|
32
36
|
secret_param = args.find{ |arg| arg =~ /secret=/ }
|
33
37
|
unless secret_param.to_s.match(/secret=.+/)
|
@@ -39,6 +43,15 @@ module PhraseGem
|
|
39
43
|
secret = secret_param.split("=", 2).last
|
40
44
|
config.secret = secret
|
41
45
|
puts "Wrote secret to config file .phrase"
|
46
|
+
|
47
|
+
default_locale_param = args.find{ |arg| arg =~ /default-locale=/ }
|
48
|
+
if default_locale_param.to_s.match(/default-locale=.+/)
|
49
|
+
locale_name = default_locale_param.split("=", 2).last
|
50
|
+
else
|
51
|
+
locale_name = "en"
|
52
|
+
end
|
53
|
+
create_locale(locale_name, config)
|
54
|
+
make_locale_default(locale_name, config)
|
42
55
|
end
|
43
56
|
|
44
57
|
def push(config)
|
@@ -52,24 +65,23 @@ module PhraseGem
|
|
52
65
|
puts "No config present. Please initialize phrase before pushing or pulling."
|
53
66
|
exit(43)
|
54
67
|
end
|
55
|
-
|
56
|
-
files.each do |file|
|
57
|
-
if file.split('.').last != 'yml'
|
58
|
-
$stderr.puts "Currently only .yml files are supported."
|
59
|
-
exit(43)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
68
|
+
|
63
69
|
upload_files(files, config)
|
64
70
|
end
|
65
71
|
|
66
72
|
def choose_files_to_upload
|
67
73
|
file_name = args[1]
|
74
|
+
|
68
75
|
unless file_name
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
76
|
+
if self.class.rails_default_locale_folder_is_available
|
77
|
+
file_name = self.class.rails_default_locale_folder
|
78
|
+
puts "No file or directory specified, using #{self.class.rails_default_locale_folder}"
|
79
|
+
else
|
80
|
+
$stderr.puts "Need either a file or directory:"
|
81
|
+
$stderr.puts "phrase push FILE"
|
82
|
+
$stderr.puts "phrase push DIRECTORY"
|
83
|
+
exit(46)
|
84
|
+
end
|
73
85
|
end
|
74
86
|
|
75
87
|
unless File.exist?(file_name)
|
@@ -86,34 +98,124 @@ module PhraseGem
|
|
86
98
|
|
87
99
|
def upload_files(files, config)
|
88
100
|
files.each do |file|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
101
|
+
proceed_with_upload = true
|
102
|
+
|
103
|
+
if File.directory?(file)
|
104
|
+
proceed_with_upload = false
|
105
|
+
end
|
106
|
+
|
107
|
+
if is_yaml_file(file)
|
108
|
+
proceed_with_upload = false
|
109
|
+
$stderr.puts "Notice: Could not upload #{file} (extension not supported - see http://phraseapp.com/help for more information)"
|
110
|
+
end
|
111
|
+
|
112
|
+
if proceed_with_upload
|
113
|
+
puts "Uploading #{file}..."
|
114
|
+
params = {
|
115
|
+
'auth_token'=>config.secret,
|
116
|
+
'filename'=> file,
|
117
|
+
'file_content' => File.read(file)
|
118
|
+
}
|
119
|
+
|
120
|
+
http = http_client(config)
|
121
|
+
|
122
|
+
request = Net::HTTP::Post.new("#{config.api_path_prefix}/translation_keys/upload")
|
123
|
+
request.set_form_data(params)
|
124
|
+
res = http.request(request)
|
125
|
+
|
126
|
+
dump_summary_to_file(res, file)
|
127
|
+
unless res.code.to_s =~ /^[23]/
|
128
|
+
print_server_error(res, file)
|
129
|
+
end
|
100
130
|
end
|
101
131
|
end
|
102
132
|
end
|
103
133
|
|
104
134
|
def pull(config)
|
105
135
|
locale = args[1]
|
106
|
-
|
136
|
+
|
137
|
+
locales = []
|
138
|
+
if locale && locale.strip != ''
|
139
|
+
locales = [locale]
|
140
|
+
else
|
141
|
+
locales = fetch_locales(config)
|
142
|
+
end
|
143
|
+
|
144
|
+
locales.each do |locale|
|
145
|
+
fetch_translation_for_locale(config, locale)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def fetch_translation_for_locale(config, locale)
|
107
150
|
print "Downloading phrase.#{locale}.yml..."
|
108
151
|
::FileUtils.mkdir_p("phrase/locales")
|
109
|
-
|
152
|
+
|
153
|
+
http = http_client(config)
|
154
|
+
|
155
|
+
request = Net::HTTP::Get.new("#{config.api_path_prefix}/translations/download?auth_token=#{config.secret}&locale=#{locale}")
|
156
|
+
res = http.request(request)
|
157
|
+
|
110
158
|
if res.code.to_s =~ /200/
|
111
|
-
puts "
|
159
|
+
puts "OK"
|
112
160
|
File.open("phrase/locales/phrase.#{locale}.yml", "w") do |file|
|
113
161
|
file.write(res.body)
|
114
162
|
end
|
115
163
|
else
|
116
|
-
puts "
|
164
|
+
puts "Failed"
|
165
|
+
print_server_error(res)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def fetch_locales(config)
|
170
|
+
http = http_client(config)
|
171
|
+
|
172
|
+
request = Net::HTTP::Get.new("#{config.api_path_prefix}/locales?auth_token=#{config.secret}")
|
173
|
+
res = http.request(request)
|
174
|
+
|
175
|
+
if res.code.to_s =~ /200/
|
176
|
+
puts "Fetched all locales"
|
177
|
+
return JSON.parse(res.body).map { |locale| locale['name'] }
|
178
|
+
else
|
179
|
+
puts "Failed"
|
180
|
+
print_server_error(res)
|
181
|
+
exit(47)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def create_locale(locale_name, config)
|
186
|
+
params = {
|
187
|
+
'auth_token' => config.secret,
|
188
|
+
'locale[name]' => locale_name
|
189
|
+
}
|
190
|
+
|
191
|
+
http = http_client(config)
|
192
|
+
|
193
|
+
request = Net::HTTP::Post.new("#{config.api_path_prefix}/locales")
|
194
|
+
request.set_form_data(params)
|
195
|
+
res = http.request(request)
|
196
|
+
|
197
|
+
if res.code.to_s =~ /200/
|
198
|
+
puts "Created locale \"#{locale_name}\""
|
199
|
+
else
|
200
|
+
puts "Notice: Locale \"#{locale_name}\" could not be created (maybe it already exists)"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def make_locale_default(locale_name, config)
|
205
|
+
params = {
|
206
|
+
'auth_token' => config.secret,
|
207
|
+
}
|
208
|
+
|
209
|
+
http = http_client(config)
|
210
|
+
|
211
|
+
request = Net::HTTP::Put.new("#{config.api_path_prefix}/locales/#{locale_name}/make_default")
|
212
|
+
request.set_form_data(params)
|
213
|
+
res = http.request(request)
|
214
|
+
|
215
|
+
if res.code.to_s =~ /200/
|
216
|
+
puts "Locale \"#{locale_name}\" is now the default locale"
|
217
|
+
else
|
218
|
+
puts "Notice: Locale \"#{locale_name}\" could not be made the default locale"
|
117
219
|
print_server_error(res)
|
118
220
|
end
|
119
221
|
end
|
@@ -127,16 +229,17 @@ module PhraseGem
|
|
127
229
|
begin
|
128
230
|
JSON.parse(body)["error"]
|
129
231
|
rescue JSON::ParserError
|
130
|
-
"
|
232
|
+
"Unknown error"
|
131
233
|
end
|
132
234
|
end
|
133
235
|
|
134
236
|
def print_usage
|
135
237
|
$stderr.puts <<USAGE
|
136
238
|
Welcome to phrase!
|
239
|
+
|
137
240
|
phrase Prints usage
|
138
241
|
|
139
|
-
phrase init --secret=<YOUR SECRET>
|
242
|
+
phrase init --secret=<YOUR SECRET> --default-locale=<YOUR DEFAULT LOCALE>
|
140
243
|
|
141
244
|
phrase push FILE
|
142
245
|
phrase push DIRECTORY
|
@@ -162,5 +265,25 @@ USAGE
|
|
162
265
|
end
|
163
266
|
puts "Summary saved in #{summary_file}"
|
164
267
|
end
|
268
|
+
|
269
|
+
def http_client(config)
|
270
|
+
http = Net::HTTP.new(config.api_host, config.api_port)
|
271
|
+
http.use_ssl = true if config.api_use_ssl == "1"
|
272
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
273
|
+
http.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem")
|
274
|
+
http
|
275
|
+
end
|
276
|
+
|
277
|
+
def is_yaml_file(filepath)
|
278
|
+
!File.directory?(filepath) && filepath.split('.').last != 'yml'
|
279
|
+
end
|
280
|
+
|
281
|
+
def self.rails_default_locale_folder
|
282
|
+
"./config/locales/"
|
283
|
+
end
|
284
|
+
|
285
|
+
def self.rails_default_locale_folder_is_available
|
286
|
+
File.exist?(rails_default_locale_folder) && File.directory?(rails_default_locale_folder)
|
287
|
+
end
|
165
288
|
end
|
166
289
|
end
|
data/lib/phrase/tool_config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module PhraseGem
|
@@ -23,11 +25,24 @@ module PhraseGem
|
|
23
25
|
save_config!
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
27
|
-
ENV.fetch("
|
28
|
+
def api_port
|
29
|
+
ENV.fetch("PHRASE_API_PORT", "443")
|
30
|
+
end
|
31
|
+
|
32
|
+
def api_host
|
33
|
+
ENV.fetch("PHRASE_API_HOST", "phraseapp.com")
|
34
|
+
end
|
35
|
+
|
36
|
+
def api_path_prefix
|
37
|
+
"/api/v1"
|
38
|
+
end
|
39
|
+
|
40
|
+
def api_use_ssl
|
41
|
+
ENV.fetch("PHRASE_API_USE_SSL", "1")
|
28
42
|
end
|
29
43
|
|
30
44
|
private
|
45
|
+
|
31
46
|
def config
|
32
47
|
@config ||= {}
|
33
48
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Phrase::ViewHelpers
|
2
|
+
|
3
|
+
def phrase_javascript(auth_token=nil)
|
4
|
+
auth_token ||= Phrase.auth_token
|
5
|
+
js =
|
6
|
+
%{<script>
|
7
|
+
//<![CDATA[
|
8
|
+
var phrase_auth_token = '#{auth_token}';
|
9
|
+
(function() {
|
10
|
+
var phraseapp = document.createElement('script'); phraseapp.type = 'text/javascript'; phraseapp.async = true;
|
11
|
+
phraseapp.src = ['#{Phrase.js_use_ssl ? 'https' : 'http'}://', '#{Phrase.js_host}/assets/phrase/#{Phrase.client_version}/app.js?', new Date().getTime()].join('');
|
12
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(phraseapp, s);
|
13
|
+
})();
|
14
|
+
//]]>
|
15
|
+
</script>}
|
16
|
+
js.html_safe
|
17
|
+
end
|
18
|
+
end
|
data/lib/phrase.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
|
+
require 'active_support/all'
|
4
|
+
|
3
5
|
module Phrase
|
4
|
-
autoload :Config,
|
6
|
+
autoload :Config, 'phrase/config'
|
7
|
+
|
8
|
+
CLIENT_VERSION = "0.1"
|
5
9
|
|
6
10
|
class << self
|
11
|
+
|
7
12
|
def config
|
8
13
|
Thread.current[:phrase_config] ||= Phrase::Config.new
|
9
14
|
end
|
@@ -12,7 +17,7 @@ module Phrase
|
|
12
17
|
Thread.current[:phrase_config] = value
|
13
18
|
end
|
14
19
|
|
15
|
-
%w(backend
|
20
|
+
%w(enabled backend prefix suffix auth_token client_version js_host js_use_ssl).each do |method|
|
16
21
|
module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1
|
17
22
|
def #{method}
|
18
23
|
config.#{method}
|
@@ -25,10 +30,25 @@ module Phrase
|
|
25
30
|
end
|
26
31
|
DELEGATORS
|
27
32
|
end
|
33
|
+
|
34
|
+
def enabled?
|
35
|
+
enabled
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
39
|
autoload :Extensions, 'phrase/extensions'
|
31
|
-
autoload :
|
32
|
-
|
33
|
-
require
|
40
|
+
autoload :ViewHelpers, 'phrase/view_helpers'
|
41
|
+
|
42
|
+
require 'phrase/engine'
|
43
|
+
require 'phrase/backend'
|
34
44
|
end
|
45
|
+
|
46
|
+
module I18n
|
47
|
+
class << self
|
48
|
+
def translate_with_phrase(*args)
|
49
|
+
Phrase.backend.translate(*args)
|
50
|
+
end
|
51
|
+
alias_method_chain :translate, :phrase
|
52
|
+
alias_method :t, :translate
|
53
|
+
end
|
54
|
+
end
|
data/phrase.gemspec
CHANGED
@@ -4,17 +4,18 @@ $:.unshift lib unless $:.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "phrase"
|
7
|
-
s.version = "0.
|
7
|
+
s.version = "0.1"
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Dynport GmbH"]
|
10
10
|
s.email = ["info@phraseapp.com"]
|
11
11
|
s.homepage = "http://phraseapp.com"
|
12
12
|
s.summary = %q{The best way to manage i18n.}
|
13
|
-
s.description =
|
13
|
+
s.description = %q{phrase allows you to edit translations inline, on the page itself. More information at phraseapp.com}
|
14
14
|
s.required_rubygems_version = ">= 1.3.6"
|
15
15
|
s.rubyforge_project = "phrase"
|
16
16
|
git_files = `git ls-files | grep -v spec/`.split("\n") rescue ''
|
17
17
|
s.files = git_files
|
18
18
|
s.executables = %w(phrase)
|
19
|
-
s.require_paths = ["lib"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.add_dependency('activesupport', '~> 3.0')
|
20
21
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phrase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.1'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,21 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
13
|
-
dependencies:
|
14
|
-
|
12
|
+
date: 2012-06-05 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &70121408406900 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70121408406900
|
25
|
+
description: phrase allows you to edit translations inline, on the page itself. More
|
26
|
+
information at phraseapp.com
|
15
27
|
email:
|
16
28
|
- info@phraseapp.com
|
17
29
|
executables:
|
@@ -24,6 +36,7 @@ files:
|
|
24
36
|
- Gemfile.lock
|
25
37
|
- README.md
|
26
38
|
- bin/phrase
|
39
|
+
- cacert.pem
|
27
40
|
- lib/phrase.rb
|
28
41
|
- lib/phrase/backend.rb
|
29
42
|
- lib/phrase/backend/base.rb
|
@@ -36,6 +49,7 @@ files:
|
|
36
49
|
- lib/phrase/extensions/string.rb
|
37
50
|
- lib/phrase/tool.rb
|
38
51
|
- lib/phrase/tool_config.rb
|
52
|
+
- lib/phrase/view_helpers.rb
|
39
53
|
- phrase.gemspec
|
40
54
|
homepage: http://phraseapp.com
|
41
55
|
licenses: []
|