phrase 0.2.0 → 0.2.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/.gitignore +2 -0
- data/README.md +2 -2
- data/lib/phrase/api/client.rb +40 -24
- data/lib/phrase/tool.rb +55 -38
- data/lib/phrase/{tool_config.rb → tool/config.rb} +1 -2
- data/lib/phrase/tool/options.rb +69 -0
- data/lib/phrase/tool/tag_validator.rb +9 -0
- data/lib/phrase/version.rb +3 -0
- data/phrase.gemspec +5 -3
- metadata +13 -21
data/.gitignore
CHANGED
data/README.md
CHANGED
data/lib/phrase/api/client.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
3
|
require 'addressable/uri'
|
4
|
+
require 'cgi'
|
4
5
|
require 'net/http'
|
5
6
|
require 'net/https'
|
6
7
|
require 'phrase'
|
@@ -44,24 +45,6 @@ class Phrase::Api::Client
|
|
44
45
|
keys = extract_structured_object(result["translate"]) if result["translate"]
|
45
46
|
keys
|
46
47
|
end
|
47
|
-
|
48
|
-
def extract_structured_object(translation)
|
49
|
-
if translation.is_a?(Hash)
|
50
|
-
symbolize_keys(translation)
|
51
|
-
else
|
52
|
-
translation
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def symbolize_keys(hash)
|
57
|
-
hash.symbolize_keys!
|
58
|
-
hash.each do |key, value|
|
59
|
-
if value.is_a?(Hash)
|
60
|
-
hash[key] = symbolize_keys(value)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
hash
|
64
|
-
end
|
65
48
|
|
66
49
|
def find_keys_by_name(key_names=[])
|
67
50
|
result = JSON.parse(perform_api_request("/translation_keys", :get, {:key_names => key_names}))
|
@@ -103,12 +86,14 @@ class Phrase::Api::Client
|
|
103
86
|
end
|
104
87
|
end
|
105
88
|
|
106
|
-
def upload(filename, file_content)
|
89
|
+
def upload(filename, file_content, tags=[])
|
107
90
|
begin
|
108
|
-
|
91
|
+
params = {
|
109
92
|
"filename" => filename,
|
110
93
|
"file_content" => file_content,
|
111
|
-
|
94
|
+
"tags[]" => tags
|
95
|
+
}
|
96
|
+
perform_api_request("/translation_keys/upload", :post, params)
|
112
97
|
rescue Phrase::Api::Exceptions::ServerError => e
|
113
98
|
raise "File #{filename} could not be uploaded"
|
114
99
|
end
|
@@ -116,6 +101,24 @@ class Phrase::Api::Client
|
|
116
101
|
end
|
117
102
|
|
118
103
|
private
|
104
|
+
def extract_structured_object(translation)
|
105
|
+
if translation.is_a?(Hash)
|
106
|
+
symbolize_keys(translation)
|
107
|
+
else
|
108
|
+
translation
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def symbolize_keys(hash)
|
113
|
+
hash.symbolize_keys!
|
114
|
+
hash.each do |key, value|
|
115
|
+
if value.is_a?(Hash)
|
116
|
+
hash[key] = symbolize_keys(value)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
hash
|
120
|
+
end
|
121
|
+
|
119
122
|
def display_api_error(response)
|
120
123
|
error_message = api_error_message(response)
|
121
124
|
$stderr.puts error_message
|
@@ -171,7 +174,7 @@ private
|
|
171
174
|
params.merge!({
|
172
175
|
'auth_token' => @auth_token
|
173
176
|
})
|
174
|
-
|
177
|
+
set_form_data(request, params)
|
175
178
|
request
|
176
179
|
end
|
177
180
|
|
@@ -180,7 +183,7 @@ private
|
|
180
183
|
params.merge!({
|
181
184
|
'auth_token' => @auth_token
|
182
185
|
})
|
183
|
-
|
186
|
+
set_form_data(request, params)
|
184
187
|
request
|
185
188
|
end
|
186
189
|
|
@@ -195,4 +198,17 @@ private
|
|
195
198
|
client.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem")
|
196
199
|
client
|
197
200
|
end
|
198
|
-
|
201
|
+
|
202
|
+
# Support for arrays in POST data
|
203
|
+
# http://blog.assimov.net/blog/2010/06/01/postput-arrays-with-ruby-nethttp-set_form_data/
|
204
|
+
def set_form_data(request, params, separator='&')
|
205
|
+
request.body = params.map do |key, value|
|
206
|
+
if value.instance_of?(Array)
|
207
|
+
value.map {|value_item| "#{CGI::escape(key.to_s)}=#{CGI::escape(value_item.to_s)}"}.join(separator)
|
208
|
+
else
|
209
|
+
"#{CGI::escape(key.to_s)}=#{CGI::escape(value.to_s)}"
|
210
|
+
end
|
211
|
+
end.join(separator)
|
212
|
+
request.content_type = 'application/x-www-form-urlencoded'
|
213
|
+
end
|
214
|
+
end
|
data/lib/phrase/tool.rb
CHANGED
@@ -1,24 +1,27 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
|
-
require 'optparse'
|
4
|
-
require 'net/http'
|
5
|
-
require 'net/https'
|
6
3
|
require 'fileutils'
|
7
|
-
require '
|
4
|
+
require 'rubygems'
|
5
|
+
require 'phrase'
|
8
6
|
|
9
7
|
class Phrase::Tool
|
8
|
+
autoload :Config, 'phrase/tool/config'
|
9
|
+
autoload :Options, 'phrase/tool/options'
|
10
|
+
autoload :TagValidator, 'phrase/tool/tag_validator'
|
10
11
|
|
11
|
-
attr_accessor :config
|
12
|
+
attr_accessor :config, :options
|
12
13
|
|
13
14
|
def initialize(argv)
|
14
15
|
@args = argv
|
15
16
|
end
|
16
17
|
|
17
18
|
def run
|
18
|
-
|
19
|
-
|
19
|
+
subcommand = @args.first
|
20
|
+
|
21
|
+
@config = Phrase::Tool::Config.new
|
22
|
+
@options = Phrase::Tool::Options.new(@args, subcommand)
|
20
23
|
|
21
|
-
case
|
24
|
+
case subcommand
|
22
25
|
when /init/
|
23
26
|
init
|
24
27
|
when /push/
|
@@ -26,42 +29,47 @@ class Phrase::Tool
|
|
26
29
|
when /pull/
|
27
30
|
pull
|
28
31
|
else
|
29
|
-
|
32
|
+
if @options.get(:version)
|
33
|
+
print_version
|
34
|
+
else
|
35
|
+
print_usage
|
36
|
+
end
|
30
37
|
end
|
31
38
|
end
|
32
39
|
|
33
|
-
protected
|
40
|
+
protected
|
41
|
+
|
34
42
|
def init
|
35
|
-
|
36
|
-
unless
|
43
|
+
secret = @options.get(:secret)
|
44
|
+
unless secret.present?
|
37
45
|
$stderr.puts "Need a secret to init, but found none."
|
38
46
|
$stderr.puts "Please provide the --secret=YOUR_SECRET parameter."
|
39
47
|
exit(41)
|
40
48
|
end
|
41
|
-
|
42
|
-
secret = secret_param.split("=", 2).last
|
49
|
+
|
43
50
|
@config.secret = secret
|
44
51
|
puts "Wrote secret to config file .phrase"
|
45
52
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
locale_name = "en"
|
51
|
-
end
|
52
|
-
create_locale(locale_name)
|
53
|
-
make_locale_default(locale_name)
|
53
|
+
default_locale_name = @options.get(:default_locale)
|
54
|
+
create_locale(default_locale_name)
|
55
|
+
make_locale_default(default_locale_name)
|
54
56
|
end
|
55
57
|
|
56
58
|
def push
|
57
59
|
check_config_available
|
60
|
+
tags = @options.get(:tags)
|
61
|
+
unless tags.empty? or valid_tags_are_given?(tags)
|
62
|
+
$stderr.puts "Invalid tags: Only letters, numbers, underscores and dashes are allowed"
|
63
|
+
exit(43)
|
64
|
+
end
|
58
65
|
|
59
66
|
files = choose_files_to_upload
|
60
67
|
if files.empty?
|
61
68
|
puts "Could not find any files to upload :("
|
62
69
|
exit(43)
|
63
70
|
end
|
64
|
-
|
71
|
+
|
72
|
+
upload_files(files, tags)
|
65
73
|
end
|
66
74
|
|
67
75
|
def pull
|
@@ -85,17 +93,23 @@ protected
|
|
85
93
|
|
86
94
|
def print_usage
|
87
95
|
$stderr.puts <<USAGE
|
88
|
-
|
89
|
-
|
90
|
-
phrase Prints usage
|
96
|
+
usage: phrase <command> [<args>]
|
91
97
|
|
92
|
-
phrase init --secret=<YOUR SECRET> --default-locale=<
|
98
|
+
phrase init --secret=<YOUR SECRET> --default-locale=<DEFAULT LOCALE>
|
93
99
|
|
94
|
-
phrase push FILE
|
95
|
-
phrase push DIRECTORY
|
100
|
+
phrase push FILE [--tags=<tags>]
|
101
|
+
phrase push DIRECTORY [--tags=<tags>]
|
102
|
+
|
103
|
+
phrase pull [LOCALE]
|
104
|
+
|
105
|
+
phrase --version
|
96
106
|
USAGE
|
97
107
|
end
|
98
108
|
|
109
|
+
def print_version
|
110
|
+
puts "phrase version #{Phrase::VERSION}"
|
111
|
+
end
|
112
|
+
|
99
113
|
private
|
100
114
|
def choose_files_to_upload
|
101
115
|
file_name = args[1]
|
@@ -124,7 +138,7 @@ private
|
|
124
138
|
end
|
125
139
|
end
|
126
140
|
|
127
|
-
def upload_files(files)
|
141
|
+
def upload_files(files, tags=[])
|
128
142
|
files.each do |file|
|
129
143
|
proceed_with_upload = true
|
130
144
|
|
@@ -134,13 +148,14 @@ private
|
|
134
148
|
|
135
149
|
if is_yaml_file(file)
|
136
150
|
proceed_with_upload = false
|
137
|
-
$stderr.puts "Notice: Could not upload #{file} (extension not supported
|
151
|
+
$stderr.puts "Notice: Could not upload #{file} (extension not supported)"
|
138
152
|
end
|
139
153
|
|
140
154
|
if proceed_with_upload
|
141
155
|
begin
|
142
|
-
|
143
|
-
|
156
|
+
tagged = " (tagged: #{tags.join(", ")})" if tags.size > 0
|
157
|
+
puts "Uploading #{file}#{tagged}..."
|
158
|
+
api_client.upload(file, File.read(file), tags)
|
144
159
|
puts "OK"
|
145
160
|
rescue Exception => e
|
146
161
|
puts "Failed"
|
@@ -209,11 +224,6 @@ private
|
|
209
224
|
def args
|
210
225
|
@args
|
211
226
|
end
|
212
|
-
|
213
|
-
def puts_debug_info
|
214
|
-
puts "ARGS: #{args.join(",")}"
|
215
|
-
puts "Dir.pwd: #{Dir.pwd}"
|
216
|
-
end
|
217
227
|
|
218
228
|
def is_yaml_file(filepath)
|
219
229
|
!File.directory?(filepath) && filepath.split('.').last != 'yml'
|
@@ -230,6 +240,13 @@ private
|
|
230
240
|
end
|
231
241
|
end
|
232
242
|
|
243
|
+
def valid_tags_are_given?(tags)
|
244
|
+
tags.each do |tag|
|
245
|
+
return false unless TagValidator.valid?(tag)
|
246
|
+
end
|
247
|
+
true
|
248
|
+
end
|
249
|
+
|
233
250
|
def self.rails_default_locale_folder
|
234
251
|
"./config/locales/"
|
235
252
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
class Phrase::Tool::Options
|
6
|
+
|
7
|
+
def initialize(args, command="")
|
8
|
+
@command = command
|
9
|
+
@data = {
|
10
|
+
default: {
|
11
|
+
version: false,
|
12
|
+
help: false
|
13
|
+
},
|
14
|
+
init: {
|
15
|
+
secret: "",
|
16
|
+
default_locale: "en"
|
17
|
+
},
|
18
|
+
push: {
|
19
|
+
tags: []
|
20
|
+
},
|
21
|
+
pull: {
|
22
|
+
}
|
23
|
+
}
|
24
|
+
options.parse!(args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get(name)
|
28
|
+
return @data.fetch(command_name).fetch(name.to_sym)
|
29
|
+
rescue => e
|
30
|
+
$stderr.puts "Invalid or missing option \"#{name}\" for command \"#{command_name}\""
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def options
|
36
|
+
case command_name
|
37
|
+
when :init
|
38
|
+
OptionParser.new do |opts|
|
39
|
+
opts.on("--secret=YOUR_AUTH_TOKEN", String, "Your auth token") do |secret|
|
40
|
+
@data[command_name][:secret] = secret
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("--default-locale=en", String, "The default locale for your application") do |default_locale|
|
44
|
+
@data[command_name][:default_locale] = default_locale
|
45
|
+
end
|
46
|
+
end
|
47
|
+
when :push
|
48
|
+
OptionParser.new do |opts|
|
49
|
+
opts.on("--tags=foo,bar", Array, "List of tags for phrase push (separated by comma)") do |tags|
|
50
|
+
@data[command_name][:tags] = tags
|
51
|
+
end
|
52
|
+
end
|
53
|
+
else
|
54
|
+
OptionParser.new do |opts|
|
55
|
+
opts.on_tail("-v", "--version", "Show version number") do |version|
|
56
|
+
@data[:default][:version] = true
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on_tail("-h", "--help", "Show help") do |help|
|
60
|
+
@data[:default][:help] = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def command_name
|
67
|
+
@command_name ||= (@command.present? and @data.has_key?(@command.to_sym)) ? @command.to_sym : :default
|
68
|
+
end
|
69
|
+
end
|
data/phrase.gemspec
CHANGED
@@ -2,15 +2,17 @@
|
|
2
2
|
lib = File.expand_path('../lib/', __FILE__)
|
3
3
|
$:.unshift lib unless $:.include?(lib)
|
4
4
|
|
5
|
+
require 'phrase/version'
|
6
|
+
|
5
7
|
Gem::Specification.new do |s|
|
6
8
|
s.name = "phrase"
|
7
|
-
s.version =
|
9
|
+
s.version = Phrase::VERSION
|
8
10
|
s.platform = Gem::Platform::RUBY
|
9
11
|
s.authors = ["Dynport GmbH"]
|
10
12
|
s.email = ["info@phraseapp.com"]
|
11
|
-
s.homepage = "
|
13
|
+
s.homepage = "https://phraseapp.com"
|
12
14
|
s.summary = %q{The best way to manage i18n.}
|
13
|
-
s.description = %q{phrase allows you to edit translations
|
15
|
+
s.description = %q{phrase allows you to edit translations in-place on the page itself. More information at phraseapp.com}
|
14
16
|
s.required_rubygems_version = ">= 1.3.6"
|
15
17
|
s.rubyforge_project = "phrase"
|
16
18
|
git_files = `git ls-files | grep -v spec/`.split("\n") rescue ''
|
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.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70308573413560 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,15 +21,10 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '3.0'
|
24
|
+
version_requirements: *70308573413560
|
30
25
|
- !ruby/object:Gem::Dependency
|
31
26
|
name: addressable
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
27
|
+
requirement: &70308573428880 !ruby/object:Gem::Requirement
|
33
28
|
none: false
|
34
29
|
requirements:
|
35
30
|
- - ~>
|
@@ -37,13 +32,8 @@ dependencies:
|
|
37
32
|
version: 2.2.8
|
38
33
|
type: :runtime
|
39
34
|
prerelease: false
|
40
|
-
version_requirements:
|
41
|
-
|
42
|
-
requirements:
|
43
|
-
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 2.2.8
|
46
|
-
description: phrase allows you to edit translations inline, on the page itself. More
|
35
|
+
version_requirements: *70308573428880
|
36
|
+
description: phrase allows you to edit translations in-place on the page itself. More
|
47
37
|
information at phraseapp.com
|
48
38
|
email:
|
49
39
|
- info@phraseapp.com
|
@@ -70,10 +60,13 @@ files:
|
|
70
60
|
- lib/phrase/delegate.rb
|
71
61
|
- lib/phrase/engine.rb
|
72
62
|
- lib/phrase/tool.rb
|
73
|
-
- lib/phrase/
|
63
|
+
- lib/phrase/tool/config.rb
|
64
|
+
- lib/phrase/tool/options.rb
|
65
|
+
- lib/phrase/tool/tag_validator.rb
|
66
|
+
- lib/phrase/version.rb
|
74
67
|
- lib/phrase/view_helpers.rb
|
75
68
|
- phrase.gemspec
|
76
|
-
homepage:
|
69
|
+
homepage: https://phraseapp.com
|
77
70
|
licenses: []
|
78
71
|
post_install_message:
|
79
72
|
rdoc_options: []
|
@@ -93,9 +86,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
86
|
version: 1.3.6
|
94
87
|
requirements: []
|
95
88
|
rubyforge_project: phrase
|
96
|
-
rubygems_version: 1.8.
|
89
|
+
rubygems_version: 1.8.10
|
97
90
|
signing_key:
|
98
91
|
specification_version: 3
|
99
92
|
summary: The best way to manage i18n.
|
100
93
|
test_files: []
|
101
|
-
has_rdoc:
|