crowdin-cli 0.0.3 → 0.0.4

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Anton Maminov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,108 @@
1
+ # Crowdin-CLI
2
+
3
+ A Command-Line Interface to sync files between your computer/server and [Crowdin](crowdin.net).
4
+
5
+ It is cross-platform and runs in a terminal (Linux, MacOS X) or in cmd.exe (Windows).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```
12
+ gem 'crowdin-cli'
13
+ ```
14
+
15
+ And then execute:
16
+ ```
17
+ $ bundle
18
+ ```
19
+
20
+ Or install it yourself as:
21
+ ```
22
+ $ gem install crowdin-cli
23
+ ```
24
+
25
+ ## Configuration
26
+
27
+ Now that the tool in installed, you'll have to configure your project. Basically, `crowdin-cli` is to be run on a project directory, and looks for a `crowdin.yaml` file containing your project information.
28
+
29
+ Create a `crowdin.yaml` YAML file in your root project directory with the following structure:
30
+
31
+ ```
32
+ ---
33
+ project_id: test
34
+ api_key: KeepTheAPIkeySecret
35
+ base_url: http://api.crowdin.net
36
+ base_path: /path/to/your/project
37
+
38
+ files:
39
+ -
40
+ source: /locale/en/LC_MESSAGES/messages.po
41
+ translation: /locale/%two_letter_code%/LC_MESSAGES/%original_file_name%
42
+ ```
43
+
44
+ * `api_key` - Crowdin Project API key
45
+ * `project_id` - Crowdin project name
46
+ * `base_url` - (default: http://api.crowdin.net)
47
+ * `base_path` - defines what directory we have to scan(default: current directory)
48
+ * `files`
49
+ * `source` - defines only files we will upload as sources
50
+ * `translation` - attribute defines where translations should be placed after downloading (also we have to check those path to detect and upload existing translations)
51
+
52
+ Use the following placeholders to put appropriate variables into the resulting file name:
53
+ * `%language%` - Language name (i.e. Ukrainian)
54
+ * `%two_letter_code%` - Language code ISO 639-1 (i.e. uk)
55
+ * `%three_letter_code%` - Language code ISO 639-2/T (i.e. ukr)
56
+ * `%locale%` - Locale (like uk-UA)
57
+ * `%locale_with_underscore%` - Locale (i.e. uk_UA)
58
+ * `%original_file_name%` - Original file name
59
+ * `%android_code%` - Android Locale identifier used to name "values-" directories
60
+ * `%original_path%` - Take parent folders names in Crowdin project to build file path in resulted bundle
61
+ * `%file_extension%` - Original file extension
62
+ * `%file_name%` - File name without extension
63
+
64
+ Example for Android projects:
65
+ ```
66
+ /values-%android_code%/%original_file_name%
67
+ ```
68
+ Example for Gettext projects:
69
+ ```
70
+ /locale/%two_letter_code%/LC_MESSAGES/%original_file_name%
71
+ ```
72
+
73
+ Also you can add and upload all directories mathing the pattern including all nested files and localizable files.
74
+
75
+ Create a `crowdin.yaml` YAML file in your root project directory with the following structure:
76
+ ```
77
+ ---
78
+ project_id: test
79
+ api_key: KeepTheAPIkeySecret
80
+ base_url: http://api.crowdin.net
81
+ base_path: /path/to/your/project
82
+
83
+ files:
84
+ -
85
+ source: /locale/en/**/*.po
86
+ translation: /locale/%two_letter_code%/**/%original_file_name%
87
+ ```
88
+ ## Usage
89
+
90
+
91
+ ## Supported Rubies
92
+
93
+ Tested with the following Ruby versions:
94
+
95
+ - MRI 1.9.3
96
+ - JRuby 1.7.0
97
+
98
+ ## Contributing
99
+
100
+ 1. Fork it
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create new Pull Request
105
+
106
+ ## License
107
+
108
+ This library is distributed under the MIT license. Please see the LICENSE file.
@@ -1,13 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'pp'
4
- require 'json'
5
- require 'gli'
6
- require 'zip/zip'
7
- require 'crowdin-api'
8
4
  require 'crowdin-cli'
9
5
 
10
- # повертає структуру директорій на сервері
6
+ # using for upload source files
7
+ # return existing directory structure in Crowdin project
11
8
  #
12
9
  def walk_remote_tree(files, root = '/', result = { dirs: [], files: [] })
13
10
  files.each do |node|
@@ -23,20 +20,18 @@ def walk_remote_tree(files, root = '/', result = { dirs: [], files: [] })
23
20
  return result
24
21
  end
25
22
 
26
-
27
- # Повертає локальну структуру директорій
28
- # На вході масив файлів, наприклад:
29
- # ['/path/to/admin/en.xml', '/path/to/user/settings/strings.xml']
30
- # Результат хеш { dirs:[послідовний масив директорій для створення], files: [] }
23
+ # using for upload source files
24
+ # return local directory structute
25
+ # first argument: ['/path/to/admin/en.xml', '/path/to/user/settings/strings.xml']
31
26
  #
32
27
  def walk_local_tree(files, result = { dirs: [], files: [] })
33
28
  result[:files] = files
34
29
 
35
- files = files.inject([]){ |res, a|
36
- res << a.split('/').drop(1).inject([]){ |res, s|
30
+ files = files.inject([]) do |res, a|
31
+ res << a.split('/').drop(1).inject([]) do |res, s|
37
32
  res << res.last.to_s + '/' + s
38
- }
39
- }
33
+ end
34
+ end
40
35
  # Ex: files = [["/path", "/path/to", "/path/to/admin", "/path/to/admin/en.xml"], ... ]
41
36
 
42
37
  files.map(&:pop) # delete last element from each array
@@ -69,7 +64,6 @@ def android_locale_code(locale_code)
69
64
  return locale_code.sub('-', '-r')
70
65
  end
71
66
 
72
-
73
67
  ###
74
68
  include GLI::App
75
69
 
@@ -85,7 +79,6 @@ default_value File.join(Dir.pwd, 'crowdin.yaml')
85
79
  arg_name '<s>'
86
80
  flag [:c, :config]
87
81
 
88
-
89
82
  desc 'Upload existing translations to Crowdin project'
90
83
  #arg_name 'Describe arguments to upload here'
91
84
  command :upload do |c|
@@ -109,27 +102,53 @@ command :upload do |c|
109
102
  c.desc 'Upload source files'
110
103
  c.command :sources do |c|
111
104
  c.action do |global_options, options, args|
112
- project_info = @crowdin.project_info(:json)
113
- project_info = JSON.parse(project_info)
105
+ project_info = @crowdin.project_info
114
106
 
115
- remote_project_tree = walk_remote_tree(project_info['files'])
107
+ #source_language = project_info['info']['source_language']
108
+ source_language = 'en'
109
+
110
+ # Crowdin supported languages list
111
+ supported_languages = @crowdin.supported_languages['languages']
112
+ source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
113
+
114
+ remote_project_tree = walk_remote_tree(project_info['info']['files']['items'])
116
115
 
117
116
  local_files = []
118
117
  @config['files'].each do |file|
119
- local_file = "#{@local_path}#{@sources_root}#{file['source']}"
120
-
121
- if File.exist?(local_file)
122
- local_files << { dest: file['source'], source: local_file, export_pattern: file['translation'] }
118
+ if File.exist?("#{@base_path}#{file['source']}")
119
+ local_files << { dest: file['source'], source: "#{@base_path}#{file['source']}", export_pattern: file['translation'] }
123
120
  else
124
- Dir.glob(local_file).each do |f|
125
- local_files << { dest: f.sub("#{@local_path}#{@sources_root}", ''), source: f, export_pattern: file['translation'] }
121
+ Dir.glob("#{@base_path}#{file['source']}").each do |source|
122
+ dest = source.sub("#{@base_path}", '') # relative path in Crowdin
123
+ original_path = File.dirname(dest)
124
+ original_file_name = File.basename(dest)
125
+ file_extension = File.extname(dest)
126
+ file_name = File.basename(dest, file_extension)
127
+
128
+ file_pattern = file['translation'].gsub(/%.+?%/, {
129
+ '%language%' => source_language['name'],
130
+ '%two_letter_code%' => source_language['iso_639_1'],
131
+ '%tree_letter_code%' => source_language['iso_639_3'],
132
+ '%locale%' => source_language['locale'],
133
+ '%locale_with_underscore%' => source_language['locale'].gsub('-', '_'),
134
+ '%original_file_name%' => original_file_name,
135
+ '%android_code%' => android_locale_code(source_language['locale']),
136
+ '%original_path%' => original_path,
137
+ '%file_extension%' => file_extension,
138
+ '%file_name%' => file_extension,
139
+ })
140
+
141
+ diff = (dest.split('/') - file_pattern.split('/')).join('/')
142
+ export_pattern = file['translation'].sub('**', diff)
143
+
144
+ local_files << { dest: dest, source: source, export_pattern: export_pattern }
126
145
  end
146
+
127
147
  end
128
148
  end
129
149
 
130
150
  local_project_tree = walk_local_tree(local_files.collect{ |h| h[:dest] })
131
151
 
132
- #=begin
133
152
  # Create directory tree
134
153
  #
135
154
  create_dirs = local_project_tree[:dirs] - remote_project_tree[:dirs]
@@ -157,12 +176,10 @@ command :upload do |c|
157
176
  puts "Add new file `#{file[:dest]}`"
158
177
  @crowdin.add_file([] << file)
159
178
  end
160
- #=end
161
179
 
162
180
  end # action
163
181
  end # command
164
182
 
165
-
166
183
  c.desc 'Upload translation files'
167
184
  c.command :translations do |c|
168
185
 
@@ -184,46 +201,34 @@ command :upload do |c|
184
201
  c.action do |global_options, options, args|
185
202
  language = options[:language]
186
203
 
187
- project_info = @crowdin.project_info(:json)
188
- project_info = JSON.parse(project_info)
204
+ project_info = @crowdin.project_info
205
+
206
+ remote_project_tree = walk_remote_tree(project_info['info']['files']['items'])
189
207
 
190
- # Array of project languages
191
208
  if language == 'all'
192
- project_languages = project_info['languages'].collect{ |h| h['code'] }
209
+ project_languages = project_info['info']['languages']['items'].collect{ |h| h['code'] }
193
210
  else
194
211
  project_languages = [] << language
195
212
  end
196
213
 
197
- # Crowdin supported languages list
198
- supported_languages = @crowdin.supported_languages(:json)
199
- supported_languages = JSON.parse(supported_languages)
200
- supported_languages.select!{ |lang| project_languages.include?(lang['crowdin_code']) }
214
+ supported_languages = @crowdin.supported_languages['languages']
215
+ translation_languages = supported_languages.select{ |lang| project_languages.include?(lang['crowdin_code']) }
216
+
217
+ source_language = 'en'
218
+ source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
201
219
 
202
220
  translated_files = Hash.new{ |hash, key| hash[key] = Array.new }
203
221
 
204
- # Тут робиться багато припіздатєнької роботи :)
205
- # TODO тут тре всьо нахуй переписати!!! НЕНАВИСТЬ
206
222
  @config['files'].each do |file|
207
- translation = file['translation']
208
- source = file['source'] # relative path to source file in Crowdin project
209
-
210
- sources = []
211
- if File.exists?("#{@local_path}#{@sources_root}#{source}")
212
- sources << source
213
- else
214
- Dir.glob("#{@local_path}#{@sources_root}#{source}").each do |f|
215
- sources << f.sub("#{@local_path}#{@sources_root}", '')
216
- end
217
- end
218
-
219
- sources.each do |source|
220
- original_path = source.split('/')[1...-1].join('/')
221
- original_file_name = source.split('/').last
222
- file_extension = original_file_name.split('.').last
223
- file_name = original_file_name.split('.').shift
224
-
225
- supported_languages.each do |lang|
226
- file = translation.gsub(/%.+?%/, {
223
+ if File.exists?("#{@base_path}#{file['source']}")
224
+ dest = file['source'].sub("#{@base_path}", '')
225
+ original_path = File.dirname(dest)
226
+ original_file_name = File.basename(dest)
227
+ file_extension = File.extname(dest)[1..-1]
228
+ file_name = File.basename(dest, file_extension)
229
+
230
+ translation_languages.each do |lang|
231
+ source = file['translation'].gsub(/%.+?%/, {
227
232
  '%language%' => lang['name'],
228
233
  '%two_letter_code%' => lang['iso_639_1'],
229
234
  '%tree_letter_code%' => lang['iso_639_3'],
@@ -235,18 +240,60 @@ command :upload do |c|
235
240
  '%file_extension%' => file_extension,
236
241
  '%file_name%' => file_extension,
237
242
  })
238
- translated_files[lang['crowdin_code']] << { source: @local_path + file, dest: source }
243
+
244
+ translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
239
245
  end
246
+ else
247
+ Dir.glob("#{@base_path}#{file['source']}").each do |source|
248
+ dest = source.sub("#{@base_path}", '')
249
+ original_path = File.dirname(dest)
250
+ original_file_name = File.basename(dest)
251
+ file_extension = File.extname(dest)
252
+ file_name = File.basename(dest, file_extension)
253
+
254
+ file_pattern = file['translation'].gsub(/%.+?%/, {
255
+ '%language%' => source_language['name'],
256
+ '%two_letter_code%' => source_language['iso_639_1'],
257
+ '%tree_letter_code%' => source_language['iso_639_3'],
258
+ '%locale%' => source_language['locale'],
259
+ '%locale_with_underscore%' => source_language['locale'].gsub('-', '_'),
260
+ '%original_file_name%' => original_file_name,
261
+ '%android_code%' => android_locale_code(source_language['locale']),
262
+ '%original_path%' => original_path,
263
+ '%file_extension%' => file_extension,
264
+ '%file_name%' => file_extension,
265
+ })
240
266
 
241
- end
267
+ diff = (dest.split('/') - file_pattern.split('/')).join('/')
268
+ export_pattern = file['translation'].sub('**', diff)
269
+
270
+ translation_languages.each do |lang|
271
+ source = export_pattern.gsub(/%.+?%/, {
272
+ '%language%' => lang['name'],
273
+ '%two_letter_code%' => lang['iso_639_1'],
274
+ '%tree_letter_code%' => lang['iso_639_3'],
275
+ '%locale%' => lang['locale'],
276
+ '%locale_with_underscore%' => lang['locale'].gsub('-', '_'),
277
+ '%original_file_name%' => original_file_name,
278
+ '%android_code%' => android_locale_code(lang['locale']),
279
+ '%original_path%' => original_path,
280
+ '%file_extension%' => file_extension,
281
+ '%file_name%' => file_extension,
282
+ })
283
+
284
+ translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
285
+ end
242
286
 
243
- end
287
+ end
288
+ end # if
289
+ end # @config['files']
244
290
 
245
291
  params = {}
246
292
  params[:import_duplicates] = options[:import_dublicates] ? 1 : 0
247
293
  params[:import_eq_suggestions] = options[:import_eq_suggestions] ? 1 : 0
248
294
  params[:auto_approve_imported] = options[:auto_approve_imported] ? 1 : 0
249
295
 
296
+
250
297
  translated_files.each do |language, files|
251
298
  files.each do |file|
252
299
  if File.exist?(file[:source])
@@ -263,7 +310,6 @@ command :upload do |c|
263
310
 
264
311
  end
265
312
 
266
-
267
313
  desc 'Download existing translations'
268
314
  #arg_name 'Describe arguments to download here'
269
315
  command :download do |c|
@@ -281,7 +327,7 @@ command :download do |c|
281
327
  file = Tempfile.new(language)
282
328
  begin
283
329
  @crowdin.download_translation(language, :output => file)
284
- unzip_file(file, @local_path)
330
+ unzip_file(file, @base_path)
285
331
  ensure
286
332
  file.close
287
333
  file.unlink # delete the temp file
@@ -299,20 +345,18 @@ pre do |global ,command, options, args|
299
345
 
300
346
  @config = YAML.load_file(global[:config])
301
347
 
302
- #@local_path = @config['local_path'] || Dir.pwd
303
- if @config['local_path']
304
- if @config['local_path'].start_with?('/')
305
- @local_path = @config['local_path']
348
+ #@base_path = @config['base_path'] || Dir.pwd
349
+ if @config['base_path']
350
+ if @config['base_path'].start_with?('/')
351
+ @base_path = @config['base_path']
306
352
  else
307
- @local_path = Dir.pwd + '/' + @config['local_path']
353
+ @base_path = Dir.pwd + '/' + @config['base_path']
308
354
  end
309
355
  else
310
- @local_path = Dir.pwd
356
+ @base_path = Dir.pwd
311
357
  end
312
358
 
313
- @sources_root = @config['sources_root']
314
-
315
- @crowdin = Crowdin::API.new(api_key: @config['api_key'], project_id: @config['project_id'], base_url: @config['base_url'])
359
+ @crowdin = Crowdin::API.new(api_key: @config['api_key'], project_id: @config['project_id'], base_url: @config['base_url'] || 'http://api.crowdin.net')
316
360
 
317
361
  puts "Executing #{command.name}" if global[:v]
318
362
  true
@@ -4,3 +4,7 @@ require 'crowdin-cli/version.rb'
4
4
  # you just need to require this one file in your bin file
5
5
 
6
6
  require 'yaml'
7
+ require 'json'
8
+ require 'gli'
9
+ require 'zip/zip'
10
+ require 'crowdin-api'
@@ -1,5 +1,5 @@
1
1
  module Crowdin
2
2
  module CLI
3
- VERSION = '0.0.3'
3
+ VERSION = '0.0.4'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crowdin-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-27 00:00:00.000000000 Z
12
+ date: 2012-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - '='
100
100
  - !ruby/object:Gem::Version
101
- version: 0.0.3
101
+ version: 0.0.4
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,30 +106,25 @@ dependencies:
106
106
  requirements:
107
107
  - - '='
108
108
  - !ruby/object:Gem::Version
109
- version: 0.0.3
109
+ version: 0.0.4
110
110
  description:
111
- email: anton.linux@gmail.com
111
+ email:
112
+ - anton.linux@gmail.com
112
113
  executables:
113
114
  - crowdin-cli
114
115
  extensions: []
115
- extra_rdoc_files:
116
- - README.rdoc
117
- - crowdin-cli.rdoc
116
+ extra_rdoc_files: []
118
117
  files:
119
118
  - bin/crowdin-cli
120
119
  - lib/crowdin-cli/version.rb
121
120
  - lib/crowdin-cli.rb
122
- - README.rdoc
123
- - crowdin-cli.rdoc
121
+ - README.md
122
+ - LICENSE
124
123
  homepage: https://github.com/mamantoha/crowdin-cli
125
- licenses: []
124
+ licenses:
125
+ - LICENSE
126
126
  post_install_message:
127
- rdoc_options:
128
- - --title
129
- - crowdin-cli
130
- - --main
131
- - README.rdoc
132
- - -ri
127
+ rdoc_options: []
133
128
  require_paths:
134
129
  - lib
135
130
  - lib
@@ -138,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
133
  requirements:
139
134
  - - ! '>='
140
135
  - !ruby/object:Gem::Version
141
- version: '0'
136
+ version: 1.9.3
142
137
  required_rubygems_version: !ruby/object:Gem::Requirement
143
138
  none: false
144
139
  requirements:
@@ -150,5 +145,5 @@ rubyforge_project:
150
145
  rubygems_version: 1.8.24
151
146
  signing_key:
152
147
  specification_version: 3
153
- summary: A description of your project
148
+ summary: Crowdin CLI
154
149
  test_files: []
@@ -1,21 +0,0 @@
1
- = crowdin-cli
2
-
3
- Describe your project here
4
-
5
- == Configuration
6
- Create a `.crowdin` YAML file in your root project directory with the following structure:
7
-
8
- ```yaml
9
- ---
10
- project_id: ''
11
- api_key: ''
12
- server: 'http://api.crowdin.net'
13
-
14
- files:
15
- -
16
- source-file-path: locale/en/LC_MESSAGES/messages.po
17
- translations: locale/<two-letters-code>/LC_MESSAGES/<original-file-name>
18
- ```
19
-
20
- :include:crowdin-cli.rdoc
21
-
@@ -1,5 +0,0 @@
1
- = crowdin-cli
2
-
3
- Generate this with
4
- crowdin-cli rdoc
5
- After you have described your command line interface