phrase 0.1.4 → 0.2.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -6,6 +6,6 @@ gem "activesupport", :require => "active_support"
6
6
  group :test do
7
7
  gem 'rspec'
8
8
  gem 'i18n'
9
- gem 'webmock', '~>1.7.0'
10
- gem 'vcr', '~>1.11'
9
+ gem 'webmock'
10
+ gem 'vcr'
11
11
  end
data/Gemfile.lock CHANGED
@@ -2,7 +2,7 @@ GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
4
  activesupport (3.0.0)
5
- addressable (2.2.7)
5
+ addressable (2.2.8)
6
6
  crack (0.3.1)
7
7
  diff-lcs (1.1.3)
8
8
  i18n (0.6.0)
@@ -15,9 +15,9 @@ GEM
15
15
  rspec-expectations (2.8.0)
16
16
  diff-lcs (~> 1.1.2)
17
17
  rspec-mocks (2.8.0)
18
- vcr (1.11.3)
19
- webmock (1.7.10)
20
- addressable (~> 2.2, > 2.2.5)
18
+ vcr (2.2.1)
19
+ webmock (1.8.7)
20
+ addressable (>= 2.2.7)
21
21
  crack (>= 0.1.7)
22
22
 
23
23
  PLATFORMS
@@ -28,5 +28,5 @@ DEPENDENCIES
28
28
  i18n
29
29
  json
30
30
  rspec
31
- vcr (~> 1.11)
32
- webmock (~> 1.7.0)
31
+ vcr
32
+ webmock
data/bin/phrase CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'phrase/tool'
4
- PhraseGem::Tool.new(ARGV).run
4
+ Phrase::Tool.new(ARGV).run
@@ -0,0 +1,168 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'phrase'
6
+ require 'phrase/api'
7
+
8
+ class Phrase::Api::Client
9
+
10
+ METHOD_GET = :get
11
+ METHOD_POST = :post
12
+ METHOD_PUT = :put
13
+
14
+ attr_reader :auth_token
15
+
16
+ def initialize(auth_token)
17
+ raise "No auth token specified!" if (auth_token.nil? or auth_token.blank?)
18
+ @auth_token = auth_token
19
+ end
20
+
21
+ def fetch_locales
22
+ result = perform_api_request("/locales", :get)
23
+ locales = []
24
+ JSON.parse(result).map do |locale|
25
+ locales << locale['name']
26
+ end
27
+ locales
28
+ end
29
+
30
+ def translate(key)
31
+ raise "You must specify a key" if key.nil? or key.blank?
32
+ keys = {}
33
+ result = JSON.parse(perform_api_request("/translation_keys/translate", :get, {:key => key}))
34
+ if result["translate"]
35
+ keys = result["translate"]
36
+ end
37
+ keys
38
+ end
39
+
40
+ def create_locale(name)
41
+ raise "You must specify a name" if name.nil? or name.blank?
42
+
43
+ begin
44
+ perform_api_request("/locales", :post, {
45
+ "locale[name]" => name
46
+ })
47
+ rescue Phrase::Api::Exceptions::ServerError => e
48
+ raise "Locale #{name} could not be created (Maybe it already exists)"
49
+ end
50
+ true
51
+ end
52
+
53
+ def make_locale_default(name)
54
+ raise "You must specify a name" if name.nil? or name.blank?
55
+
56
+ begin
57
+ perform_api_request("/locales/#{name}/make_default", :put)
58
+ rescue Phrase::Api::Exceptions::ServerError => e
59
+ raise "Locale #{name} could not be made the default locale"
60
+ end
61
+ true
62
+ end
63
+
64
+ def download_translations_for_locale(name)
65
+ raise "You must specify a name" if name.nil? or name.blank?
66
+
67
+ begin
68
+ content = perform_api_request("/translations/download", :get, {'locale' => name})
69
+ return content
70
+ rescue Phrase::Api::Exceptions::ServerError => e
71
+ raise "Translations #{name} could not be downloaded"
72
+ end
73
+ end
74
+
75
+ def upload(filename, file_content)
76
+ begin
77
+ perform_api_request("/translation_keys/upload", :post, {
78
+ "filename" => filename,
79
+ "file_content" => file_content,
80
+ })
81
+ rescue Phrase::Api::Exceptions::ServerError => e
82
+ raise "File #{filename} could not be uploaded"
83
+ end
84
+ true
85
+ end
86
+
87
+ private
88
+ def display_api_error(response)
89
+ error_message = api_error_message(response)
90
+ $stderr.puts error_message
91
+ end
92
+
93
+ def api_error_message(response)
94
+ message = ""
95
+ begin
96
+ error = JSON.parse(response.body)["error"]
97
+ if error.class == String
98
+ message = error
99
+ else
100
+ message = JSON.parse(response.body)["message"]
101
+ end
102
+ rescue JSON::ParserError
103
+ end
104
+ message = "Unknown Error" if message.blank?
105
+ "Error: #{message} (#{response.code})"
106
+ end
107
+
108
+ def perform_api_request(endpoint, method=METHOD_GET, params={})
109
+ request = case method
110
+ when METHOD_GET
111
+ get_request(endpoint, params)
112
+ when METHOD_POST
113
+ post_request(endpoint, params)
114
+ when METHOD_PUT
115
+ put_request(endpoint, params)
116
+ else
117
+ raise "Invalid Request Method: #{method}"
118
+ end
119
+ response = http_client.request(request)
120
+ code = response.code.to_i
121
+ if (code == 200)
122
+ return response.body
123
+ else
124
+ error_message = api_error_message(response)
125
+ raise Phrase::Api::Exceptions::Unauthorized.new(error_message) if (code == 401)
126
+ raise Phrase::Api::Exceptions::ServerError.new(error_message)
127
+ end
128
+ end
129
+
130
+ def get_request(endpoint, params={})
131
+ query_string = "?auth_token=#{@auth_token}"
132
+ params.each do |key, value|
133
+ query_string << "&#{key}=#{value}"
134
+ end unless params.empty?
135
+ request = Net::HTTP::Get.new("#{api_path_for(endpoint)}#{query_string}")
136
+ request
137
+ end
138
+
139
+ def post_request(endpoint, params={})
140
+ request = Net::HTTP::Post.new("#{api_path_for(endpoint)}")
141
+ params.merge!({
142
+ 'auth_token' => @auth_token
143
+ })
144
+ request.set_form_data(params)
145
+ request
146
+ end
147
+
148
+ def put_request(endpoint, params={})
149
+ request = Net::HTTP::Put.new("#{api_path_for(endpoint)}")
150
+ params.merge!({
151
+ 'auth_token' => @auth_token
152
+ })
153
+ request.set_form_data(params)
154
+ request
155
+ end
156
+
157
+ def api_path_for(endpoint)
158
+ "#{Phrase::Api::Config.api_path_prefix}#{endpoint}"
159
+ end
160
+
161
+ def http_client
162
+ client = Net::HTTP.new(Phrase::Api::Config.api_host, Phrase::Api::Config.api_port)
163
+ client.use_ssl = true if Phrase::Api::Config.api_use_ssl?
164
+ client.verify_mode = OpenSSL::SSL::VERIFY_NONE
165
+ client.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem")
166
+ client
167
+ end
168
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'phrase'
4
+ require 'phrase/api'
5
+
6
+ class Phrase::Api::Config
7
+ def self.api_port
8
+ ENV.fetch("PHRASE_API_PORT", "443")
9
+ end
10
+
11
+ def self.api_host
12
+ ENV.fetch("PHRASE_API_HOST", "phraseapp.com")
13
+ end
14
+
15
+ def self.api_path_prefix
16
+ "/api/#{Phrase::API_VERSION}"
17
+ end
18
+
19
+ def self.api_use_ssl?
20
+ (ENV.fetch("PHRASE_API_USE_SSL", "1") == "1")
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'phrase'
4
+ require 'phrase/api'
5
+
6
+ module Phrase::Api::Exceptions
7
+ class Unauthorized < StandardError; end
8
+ class ServerError < StandardError; end
9
+ end
data/lib/phrase/api.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Phrase::Api
2
+ end
3
+
4
+ require 'phrase/api/client'
5
+ require 'phrase/api/config'
6
+ require 'phrase/api/exceptions'
@@ -1,20 +1,22 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
+ require 'phrase/delegate'
4
+
3
5
  module Phrase::Backend::Base
4
6
 
5
7
  def translate(*args)
6
8
  if Phrase.enabled?
7
9
  key = lookup_normalized_key(*args)
8
- decorate_translation(key[:key])
10
+ phrase_delegate_for(key[:key])
9
11
  else
10
12
  I18n.translate_without_phrase(*args)
11
13
  end
12
14
  end
13
15
 
14
16
  protected
15
- def decorate_translation(key=nil)
17
+ def phrase_delegate_for(key=nil)
16
18
  return nil unless key.presence
17
- "#{Phrase.prefix}phrase_#{key}#{Phrase.suffix}"
19
+ Phrase::Delegate.new(key)
18
20
  end
19
21
 
20
22
  def lookup_normalized_key(*args)
data/lib/phrase/config.rb CHANGED
@@ -1,68 +1,70 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- module Phrase
4
- class Config
5
- def client_version
6
- Phrase::CLIENT_VERSION
7
- end
3
+ class Phrase::Config
4
+ def client_version
5
+ Phrase::CLIENT_VERSION
6
+ end
8
7
 
9
- def auth_token
10
- @@auth_token = "" if !defined? @@auth_token or @@auth_token.nil?
11
- @@auth_token
12
- end
13
-
14
- def auth_token=(auth_token)
15
- @@auth_token = auth_token
16
- end
17
-
18
- def enabled
19
- @@enabled = true if !defined? @@enabled or @@enabled.nil?
20
- @@enabled
21
- end
22
-
23
- def enabled=(enabled)
24
- @@enabled = enabled
25
- end
26
-
27
- def backend
28
- @@backend ||= Backend::PhraseService.new
29
- end
30
-
31
- def backend=(backend)
32
- @@backend = backend
33
- end
34
-
35
- def prefix
36
- @@prefix ||= "{{__"
37
- end
38
-
39
- def prefix=(prefix)
40
- @@prefix = prefix
41
- end
42
-
43
- def suffix
44
- @@suffix ||= "__}}"
45
- end
46
-
47
- def suffix=(suffix)
48
- @@suffix = suffix
49
- end
50
-
51
- def js_host
52
- @@js_host ||= 'phraseapp.com'
53
- end
54
-
55
- def js_host=(js_host)
56
- @@js_host = js_host
57
- end
58
-
59
- def js_use_ssl
60
- @@js_use_ssl = true if !defined? @@js_use_ssl or @@js_use_ssl.nil?
61
- @@js_use_ssl
62
- end
8
+ def api_version
9
+ Phrase::API_VERSION
10
+ end
11
+
12
+ def auth_token
13
+ @@auth_token = "" if !defined? @@auth_token or @@auth_token.nil?
14
+ @@auth_token
15
+ end
16
+
17
+ def auth_token=(auth_token)
18
+ @@auth_token = auth_token
19
+ end
20
+
21
+ def enabled
22
+ @@enabled = true if !defined? @@enabled or @@enabled.nil?
23
+ @@enabled
24
+ end
25
+
26
+ def enabled=(enabled)
27
+ @@enabled = enabled
28
+ end
63
29
 
64
- def js_use_ssl=(js_use_ssl)
65
- @@js_use_ssl = js_use_ssl
66
- end
30
+ def backend
31
+ @@backend ||= Phrase::Backend::PhraseService.new
32
+ end
33
+
34
+ def backend=(backend)
35
+ @@backend = backend
36
+ end
37
+
38
+ def prefix
39
+ @@prefix ||= "{{__"
40
+ end
41
+
42
+ def prefix=(prefix)
43
+ @@prefix = prefix
44
+ end
45
+
46
+ def suffix
47
+ @@suffix ||= "__}}"
48
+ end
49
+
50
+ def suffix=(suffix)
51
+ @@suffix = suffix
52
+ end
53
+
54
+ def js_host
55
+ @@js_host ||= 'phraseapp.com'
56
+ end
57
+
58
+ def js_host=(js_host)
59
+ @@js_host = js_host
60
+ end
61
+
62
+ def js_use_ssl
63
+ @@js_use_ssl = true if !defined? @@js_use_ssl or @@js_use_ssl.nil?
64
+ @@js_use_ssl
65
+ end
66
+
67
+ def js_use_ssl=(js_use_ssl)
68
+ @@js_use_ssl = js_use_ssl
67
69
  end
68
70
  end
@@ -0,0 +1,55 @@
1
+ require 'phrase/api'
2
+
3
+ class Phrase::Delegate
4
+ attr_accessor :key, :api_client
5
+
6
+ def initialize(key)
7
+ @key = key
8
+ end
9
+
10
+ def to_s
11
+ "#{decorated_key_name}"
12
+ end
13
+
14
+ def method_missing(*args, &block)
15
+ if @key.respond_to?(args.first)
16
+ to_s.send(*args)
17
+ else
18
+ data = translation_or_subkeys
19
+ if data.is_a?(String)
20
+ to_s
21
+ elsif data.respond_to?(args.first)
22
+ data.send(*args, &block)
23
+ else
24
+ log "You are trying to execute the method ##{args.first} on a translation key which is not supported. Please make sure you treat your translations as strings only."
25
+ nil
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+ def decorated_key_name
32
+ "#{Phrase.prefix}phrase_#{@key}#{Phrase.suffix}"
33
+ end
34
+
35
+ def translation_or_subkeys
36
+ begin
37
+ api_client.translate(@key)
38
+ rescue Exception => e
39
+ log "Server Error: #{e.message}"
40
+ end
41
+ end
42
+
43
+ def api_client
44
+ @api_client ||= Phrase::Api::Client.new(Phrase.auth_token)
45
+ end
46
+
47
+ def log(message)
48
+ message = "phrase: #{message}"
49
+ if defined?(Rails)
50
+ Rails.logger.warn(message)
51
+ else
52
+ $stderr.puts message
53
+ end
54
+ end
55
+ end
data/lib/phrase/engine.rb CHANGED
@@ -4,11 +4,9 @@ require 'phrase'
4
4
  require 'i18n'
5
5
 
6
6
  if defined? Rails
7
- module Phrase
8
- class Engine < Rails::Engine
9
- initializer 'phrase' do |app|
10
- ActionView::Base.send :include, Phrase::ViewHelpers
11
- end
7
+ class Phrase::Engine < Rails::Engine
8
+ initializer 'phrase' do |app|
9
+ ActionView::Base.send :include, Phrase::ViewHelpers
12
10
  end
13
11
  end
14
12
  end
data/lib/phrase/tool.rb CHANGED
@@ -1,277 +1,240 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- require 'phrase/tool_config'
4
-
5
3
  require 'optparse'
6
4
  require 'net/http'
7
5
  require 'net/https'
8
6
  require 'fileutils'
7
+ require 'phrase/tool_config'
9
8
 
10
- module PhraseGem
11
- class Tool
9
+ class Phrase::Tool
10
+
11
+ attr_accessor :config
12
+
13
+ def initialize(argv)
14
+ @args = argv
15
+ end
12
16
 
13
- def initialize(argv)
14
- @args = argv
17
+ def run
18
+ @config = Phrase::ToolConfig.new
19
+ command = args.first
20
+
21
+ case command
22
+ when /init/
23
+ init
24
+ when /push/
25
+ push
26
+ when /pull/
27
+ pull
28
+ else
29
+ print_usage
15
30
  end
31
+ end
16
32
 
17
- def run
18
- config = ToolConfig.new
19
- command = args.first
20
-
21
- case command
22
- when /init/
23
- init(config)
24
- when /push/
25
- push(config)
26
- when /pull/
27
- pull(config)
28
- else
29
- print_usage
30
- end
33
+ protected
34
+ def init
35
+ secret_param = args.find{ |arg| arg =~ /secret=/ }
36
+ unless secret_param.to_s.match(/secret=.+/)
37
+ $stderr.puts "Need a secret to init, but found none."
38
+ $stderr.puts "Please provide the --secret=YOUR_SECRET parameter."
39
+ exit(41)
31
40
  end
32
41
 
33
- private
42
+ secret = secret_param.split("=", 2).last
43
+ @config.secret = secret
44
+ puts "Wrote secret to config file .phrase"
34
45
 
35
- def init(config)
36
- secret_param = args.find{ |arg| arg =~ /secret=/ }
37
- unless secret_param.to_s.match(/secret=.+/)
38
- $stderr.puts "Need a secret to init, but found none."
39
- $stderr.puts "Please provide the --secret=YOUR_SECRET parameter."
40
- exit(41)
41
- end
46
+ default_locale_param = args.find{ |arg| arg =~ /default-locale=/ }
47
+ if default_locale_param.to_s.match(/default-locale=.+/)
48
+ locale_name = default_locale_param.split("=", 2).last
49
+ else
50
+ locale_name = "en"
51
+ end
52
+ create_locale(locale_name)
53
+ make_locale_default(locale_name)
54
+ end
42
55
 
43
- secret = secret_param.split("=", 2).last
44
- config.secret = secret
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)
56
+ def push
57
+ check_config_available
58
+
59
+ files = choose_files_to_upload
60
+ if files.empty?
61
+ puts "Could not find any files to upload :("
62
+ exit(43)
55
63
  end
64
+ upload_files(files)
65
+ end
56
66
 
57
- def push(config)
58
- files = choose_files_to_upload
59
- if files.empty?
60
- puts "Could not find any files to upload :("
61
- exit(43)
62
- end
63
-
64
- if !config.secret || config.secret.empty?
65
- puts "No config present. Please initialize phrase before pushing or pulling."
66
- exit(43)
67
- end
68
-
69
- upload_files(files, config)
67
+ def pull
68
+ check_config_available
69
+
70
+ create_locales_folder!
71
+
72
+ locale = args[1]
73
+ locales = []
74
+ if locale && locale.strip != ''
75
+ locales = [locale]
76
+ else
77
+ locales = fetch_locales
70
78
  end
79
+
80
+ locales.each do |locale_name|
81
+ print "Downloading phrase.#{locale_name}.yml..."
82
+ fetch_translations_for_locale(locale_name)
83
+ end
84
+ end
85
+
86
+ def print_usage
87
+ $stderr.puts <<USAGE
88
+ Welcome to phrase!
71
89
 
72
- def choose_files_to_upload
73
- file_name = args[1]
74
-
75
- unless file_name
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
85
- end
90
+ phrase Prints usage
86
91
 
87
- unless File.exist?(file_name)
88
- $stderr.puts "The file #{file_name} could not be found."
89
- exit(42)
90
- end
92
+ phrase init --secret=<YOUR SECRET> --default-locale=<YOUR DEFAULT LOCALE>
91
93
 
92
- if File.directory?(file_name)
93
- files = Dir.glob("#{File.expand_path(file_name)}/**")
94
- else
95
- files = [file_name]
94
+ phrase push FILE
95
+ phrase push DIRECTORY
96
+ USAGE
97
+ end
98
+
99
+ private
100
+ def choose_files_to_upload
101
+ file_name = args[1]
102
+
103
+ unless file_name
104
+ if self.class.rails_default_locale_folder_is_available
105
+ file_name = self.class.rails_default_locale_folder
106
+ puts "No file or directory specified, using #{self.class.rails_default_locale_folder}"
107
+ else
108
+ $stderr.puts "Need either a file or directory:"
109
+ $stderr.puts "phrase push FILE"
110
+ $stderr.puts "phrase push DIRECTORY"
111
+ exit(46)
96
112
  end
97
113
  end
98
114
 
99
- def upload_files(files, config)
100
- files.each do |file|
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
- unless res.code.to_s =~ /^[23]/
127
- print_server_error(res, file)
128
- end
129
- end
130
- end
115
+ unless File.exist?(file_name)
116
+ $stderr.puts "The file #{file_name} could not be found."
117
+ exit(42)
131
118
  end
132
119
 
133
- def pull(config)
134
- locale = args[1]
135
-
136
- locales = []
137
- if locale && locale.strip != ''
138
- locales = [locale]
139
- else
140
- locales = fetch_locales(config)
141
- end
142
-
143
- locales.each do |locale|
144
- fetch_translation_for_locale(config, locale)
145
- end
120
+ if File.directory?(file_name)
121
+ files = Dir.glob("#{File.expand_path(file_name)}/**")
122
+ else
123
+ files = [file_name]
146
124
  end
125
+ end
126
+
127
+ def upload_files(files)
128
+ files.each do |file|
129
+ proceed_with_upload = true
147
130
 
148
- def fetch_translation_for_locale(config, locale)
149
- print "Downloading phrase.#{locale}.yml..."
150
- ::FileUtils.mkdir_p("phrase/locales")
151
-
152
- http = http_client(config)
153
-
154
- request = Net::HTTP::Get.new("#{config.api_path_prefix}/translations/download?auth_token=#{config.secret}&locale=#{locale}")
155
- res = http.request(request)
156
-
157
- if res.code.to_s =~ /200/
158
- puts "OK"
159
- File.open("phrase/locales/phrase.#{locale}.yml", "w") do |file|
160
- file.write(res.body)
161
- end
162
- else
163
- puts "Failed"
164
- print_server_error(res)
131
+ if File.directory?(file)
132
+ proceed_with_upload = false
165
133
  end
166
- end
167
134
 
168
- def fetch_locales(config)
169
- http = http_client(config)
170
-
171
- request = Net::HTTP::Get.new("#{config.api_path_prefix}/locales?auth_token=#{config.secret}")
172
- res = http.request(request)
173
-
174
- if res.code.to_s =~ /200/
175
- puts "Fetched all locales"
176
- return JSON.parse(res.body).map { |locale| locale['name'] }
177
- else
178
- puts "Failed"
179
- print_server_error(res)
180
- exit(47)
135
+ if is_yaml_file(file)
136
+ proceed_with_upload = false
137
+ $stderr.puts "Notice: Could not upload #{file} (extension not supported - see http://phraseapp.com/help for more information)"
181
138
  end
182
- end
183
139
 
184
- def create_locale(locale_name, config)
185
- params = {
186
- 'auth_token' => config.secret,
187
- 'locale[name]' => locale_name
188
- }
189
-
190
- http = http_client(config)
191
-
192
- request = Net::HTTP::Post.new("#{config.api_path_prefix}/locales")
193
- request.set_form_data(params)
194
- res = http.request(request)
195
-
196
- if res.code.to_s =~ /200/
197
- puts "Created locale \"#{locale_name}\""
198
- else
199
- puts "Notice: Locale \"#{locale_name}\" could not be created (maybe it already exists)"
140
+ if proceed_with_upload
141
+ begin
142
+ puts "Uploading #{file}..."
143
+ api_client.upload(file, File.read(file))
144
+ puts "OK"
145
+ rescue Exception => e
146
+ puts "Failed"
147
+ print_server_error(e.message, file)
148
+ end
200
149
  end
201
150
  end
202
-
203
- def make_locale_default(locale_name, config)
204
- params = {
205
- 'auth_token' => config.secret,
206
- }
151
+ end
207
152
 
208
- http = http_client(config)
209
-
210
- request = Net::HTTP::Put.new("#{config.api_path_prefix}/locales/#{locale_name}/make_default")
211
- request.set_form_data(params)
212
- res = http.request(request)
213
-
214
- if res.code.to_s =~ /200/
215
- puts "Locale \"#{locale_name}\" is now the default locale"
216
- else
217
- puts "Notice: Locale \"#{locale_name}\" could not be made the default locale"
218
- print_server_error(res)
219
- end
153
+ def fetch_translations_for_locale(name)
154
+ begin
155
+ content = api_client.download_translations_for_locale(name)
156
+ puts "OK"
157
+ store_translations_file(name, content)
158
+ rescue Exception => e
159
+ puts "Failed"
160
+ print_server_error(e.message)
220
161
  end
221
-
222
- def print_server_error(res, filename=nil)
223
- error_message = server_error_message(res.body)
224
- $stderr.puts "Server error: #{res.code} - #{error_message} (#{filename})"
162
+ end
163
+
164
+ def store_translations_file(name, content)
165
+ File.open("phrase/locales/phrase.#{name}.yml", "w") do |file|
166
+ file.write(content)
225
167
  end
226
-
227
- def server_error_message(body)
228
- begin
229
- JSON.parse(body)["error"]
230
- rescue JSON::ParserError
231
- "Unknown error"
232
- end
168
+ end
169
+
170
+ def fetch_locales
171
+ begin
172
+ locales = api_client.fetch_locales
173
+ puts "Fetched all locales"
174
+ return locales
175
+ rescue Exception => e
176
+ puts "Failed"
177
+ print_server_error(e.message)
178
+ exit(47)
233
179
  end
234
-
235
- def print_usage
236
- $stderr.puts <<USAGE
237
- Welcome to phrase!
238
-
239
- phrase Prints usage
240
-
241
- phrase init --secret=<YOUR SECRET> --default-locale=<YOUR DEFAULT LOCALE>
242
-
243
- phrase push FILE
244
- phrase push DIRECTORY
245
- USAGE
180
+ end
181
+
182
+ def create_locale(name)
183
+ begin
184
+ api_client.create_locale(name)
185
+ puts "Created locale \"#{name}\""
186
+ rescue Exception => e
187
+ puts "Notice: Locale \"#{name}\" could not be created (maybe it already exists)"
246
188
  end
247
-
248
- def args
249
- @args
189
+ end
190
+
191
+ def make_locale_default(name)
192
+ begin
193
+ api_client.make_locale_default(name)
194
+ puts "Locale \"#{name}\" is now the default locale"
195
+ rescue Exception => e
196
+ puts "Notice: Locale \"#{name}\" could not be made the default locale"
197
+ print_server_error(e.message)
250
198
  end
199
+ end
200
+
201
+ def api_client
202
+ Phrase::Api::Client.new(@config.secret)
203
+ end
251
204
 
252
- def puts_debug_info
253
- puts "ARGS: #{args.join(",")}"
254
- puts "Dir.pwd: #{Dir.pwd}"
255
- end
256
-
257
- def http_client(config)
258
- http = Net::HTTP.new(config.api_host, config.api_port)
259
- http.use_ssl = true if config.api_use_ssl == "1"
260
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
261
- http.ca_file = File.join(File.dirname(__FILE__), "..", "..", "cacert.pem")
262
- http
263
- end
264
-
265
- def is_yaml_file(filepath)
266
- !File.directory?(filepath) && filepath.split('.').last != 'yml'
267
- end
268
-
269
- def self.rails_default_locale_folder
270
- "./config/locales/"
271
- end
272
-
273
- def self.rails_default_locale_folder_is_available
274
- File.exist?(rails_default_locale_folder) && File.directory?(rails_default_locale_folder)
205
+ def print_server_error(message, filename=nil)
206
+ $stderr.puts "#{message} (#{filename})"
207
+ end
208
+
209
+ def args
210
+ @args
211
+ end
212
+
213
+ def puts_debug_info
214
+ puts "ARGS: #{args.join(",")}"
215
+ puts "Dir.pwd: #{Dir.pwd}"
216
+ end
217
+
218
+ def is_yaml_file(filepath)
219
+ !File.directory?(filepath) && filepath.split('.').last != 'yml'
220
+ end
221
+
222
+ def create_locales_folder!
223
+ ::FileUtils.mkdir_p("phrase/locales")
224
+ end
225
+
226
+ def check_config_available
227
+ if !@config.secret || @config.secret.empty?
228
+ $stderr.puts "No config present. You need to initialize phrase first."
229
+ exit(43)
275
230
  end
276
231
  end
277
- end
232
+
233
+ def self.rails_default_locale_folder
234
+ "./config/locales/"
235
+ end
236
+
237
+ def self.rails_default_locale_folder_is_available
238
+ File.exist?(rails_default_locale_folder) && File.directory?(rails_default_locale_folder)
239
+ end
240
+ end
@@ -1,56 +1,37 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
+ require 'phrase'
3
4
  require 'json'
4
5
 
5
- module PhraseGem
6
- class ToolConfig
7
-
8
- def initialize
9
- if File.exist?(".phrase")
10
- begin
11
- contents = File.read(".phrase")
12
- @config = JSON.parse(contents)
13
- rescue JSON::ParserError => err
14
- $stderr.puts "Could not parse config file: #{err}"
15
- end
6
+ class Phrase::ToolConfig
7
+ def initialize
8
+ if File.exist?(".phrase")
9
+ begin
10
+ contents = File.read(".phrase")
11
+ @config = JSON.parse(contents)
12
+ rescue JSON::ParserError => err
13
+ $stderr.puts "Could not parse config file: #{err}"
16
14
  end
17
15
  end
16
+ end
17
+
18
+ def secret
19
+ config["secret"]
20
+ end
18
21
 
19
- def secret
20
- config["secret"]
21
- end
22
-
23
- def secret=(new_secret)
24
- config["secret"] = new_secret
25
- save_config!
26
- end
27
-
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")
42
- end
43
-
44
- private
45
-
46
- def config
47
- @config ||= {}
48
- end
22
+ def secret=(new_secret)
23
+ config["secret"] = new_secret
24
+ save_config!
25
+ end
26
+
27
+ private
28
+ def config
29
+ @config ||= {}
30
+ end
49
31
 
50
- def save_config!
51
- File.open(".phrase", "w+") do |file|
52
- file.write(JSON.pretty_generate(config))
53
- end
32
+ def save_config!
33
+ File.open(".phrase", "w+") do |file|
34
+ file.write(JSON.pretty_generate(config))
54
35
  end
55
36
  end
56
37
  end
data/lib/phrase.rb CHANGED
@@ -6,6 +6,7 @@ module Phrase
6
6
  autoload :Config, 'phrase/config'
7
7
 
8
8
  CLIENT_VERSION = "0.1"
9
+ API_VERSION = "v1"
9
10
 
10
11
  class << self
11
12
 
data/phrase.gemspec CHANGED
@@ -4,7 +4,7 @@ $:.unshift lib unless $:.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "phrase"
7
- s.version = "0.1.4"
7
+ s.version = "0.2.0.beta.2"
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Dynport GmbH"]
10
10
  s.email = ["info@phraseapp.com"]
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phrase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
5
- prerelease:
4
+ version: 0.2.0.beta.2
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Dynport GmbH
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-14 00:00:00.000000000 Z
12
+ date: 2012-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70112071528200 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70112071528200
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
25
30
  description: phrase allows you to edit translations inline, on the page itself. More
26
31
  information at phraseapp.com
27
32
  email:
@@ -38,10 +43,15 @@ files:
38
43
  - bin/phrase
39
44
  - cacert.pem
40
45
  - lib/phrase.rb
46
+ - lib/phrase/api.rb
47
+ - lib/phrase/api/client.rb
48
+ - lib/phrase/api/config.rb
49
+ - lib/phrase/api/exceptions.rb
41
50
  - lib/phrase/backend.rb
42
51
  - lib/phrase/backend/base.rb
43
52
  - lib/phrase/backend/phrase_service.rb
44
53
  - lib/phrase/config.rb
54
+ - lib/phrase/delegate.rb
45
55
  - lib/phrase/engine.rb
46
56
  - lib/phrase/tool.rb
47
57
  - lib/phrase/tool_config.rb
@@ -67,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
77
  version: 1.3.6
68
78
  requirements: []
69
79
  rubyforge_project: phrase
70
- rubygems_version: 1.8.10
80
+ rubygems_version: 1.8.24
71
81
  signing_key:
72
82
  specification_version: 3
73
83
  summary: The best way to manage i18n.