crowdin-cli 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66ad927a1e1132fbcd7e3423ea92d67ab4fcf9ee
4
- data.tar.gz: b82bd71053c5d79e1c710a0f24a272aae0d99289
3
+ metadata.gz: 9f6bb76e96af25bd099e35327e0affba41a15d99
4
+ data.tar.gz: 42379e5aefbf2d76b2650fff116ed5e89f609098
5
5
  SHA512:
6
- metadata.gz: 8bb8e237425d2bf49a2647e4006191cfbdb646b05f144dd96f2dc730bffb285b6d771493dfa2034e7ae86a8cb9c08effa92dad7d908991c8b7159acb729af857
7
- data.tar.gz: c5126f6fc09657b5a67808cdbf2492f515b8a28d421f8fd91b074c931e6e39e202c87cbc1129cb78f0e4bedbcc766e90e654f856e83e8e7a47871ccf0a9ac8d9
6
+ metadata.gz: 0efaaa136de06a8915600bd6c60d7ba6fb48ef5ecb7406c15e0206442577bbb08fe639a910c8a181a0cdef615cfe72ee1e33d0676312341675dcfe40ef1f017d
7
+ data.tar.gz: 585990c4a380dcda6caee000d2b50f7ec949202a00487c2e0092c96e46a7f85de50764f17a2fb1d89c5ca082937f81a476b5ec938f4feb75b9c03dc83f2d2a4b
data/README.md CHANGED
@@ -153,6 +153,50 @@ files:
153
153
 
154
154
  ```
155
155
 
156
+ ### Uploading CSV files via API
157
+
158
+ ```
159
+ ---
160
+ project_identifier: test
161
+ api_key: KeepTheAPIkeySecret
162
+ base_url: http://api.crowdin.net
163
+ base_path: /path/to/your/project
164
+
165
+ files:
166
+ -
167
+ source: '/*.csv'
168
+ translation: '%two_letters_code%/%original_file_name%'
169
+ # Defines whether first line should be imported or it contains columns headers
170
+ first_line_contains_header: true
171
+ # Used only when uploading CSV file to define data columns mapping.
172
+ scheme: "identifier,source_phrase,translation,context,max_length"
173
+ ```
174
+
175
+ #### Multicolumn CSV
176
+
177
+ In case when CSV file should contains translations to all target languages you can use per-file option `multilingual_spreadsheet`.
178
+
179
+ CSV file example:
180
+ ```
181
+ identifier,source_phrase,context,Ukrainian,Russian,French
182
+ ident1,Source 1,Context 1,,,
183
+ ident2,Source 2,Context 2,,,
184
+ ident3,Source 3,Context 3,,,
185
+ ```
186
+
187
+ Configuration file example:
188
+ ```
189
+ files:
190
+ -
191
+ source: multicolumn.csv
192
+ translation: multicolumn.csv
193
+ first_line_contains_header: true
194
+ scheme: "identifier,source_phrase,context,uk,ru,fr"
195
+ multilingual_spreadsheet: true
196
+
197
+ ```
198
+
199
+
156
200
  ## Example Configurations
157
201
 
158
202
  ### GetText Project
@@ -196,25 +240,6 @@ files:
196
240
  ru: ru
197
241
  ```
198
242
 
199
- ### Uploading CSV files via API
200
-
201
- ```
202
- ---
203
- project_identifier: test
204
- api_key: KeepTheAPIkeySecret
205
- base_url: http://api.crowdin.net
206
- base_path: /path/to/your/project
207
-
208
- files:
209
- -
210
- source: '/*.csv'
211
- translation: '%two_letters_code%/%original_file_name%'
212
- # Defines whether first line should be imported or it contains columns headers
213
- first_line_contains_header: true
214
- # Used only when uploading CSV file to define data columns mapping.
215
- scheme: "identifier,source_phrase,translation,context,max_length"
216
- ```
217
-
218
243
  ## Usage
219
244
 
220
245
  When the configuration file is created you are ready to start using `crowdin-cli` to manage your localization resources and automate files synchronization.
@@ -270,4 +295,4 @@ Author: Anton Maminov (anton.maminov@gmail.com)
270
295
 
271
296
  Copyright: 2012-2013 [Crowdin.net](http://crowdin.net/)
272
297
 
273
- This project is licensed under the MIT license, a copy of which can be found in the LICENSE file.
298
+ This project is licensed under the MIT license, a copy of which can be found in the LICENSE file.
@@ -57,22 +57,22 @@ end
57
57
  # @option lang [String] :locale
58
58
  #
59
59
  def export_pattern_to_path(path, export_pattern, lang, languages_mapping = nil)
60
- original_path = File.dirname(path)
60
+ original_path = File.dirname(path)[1..-1]
61
61
  original_file_name = File.basename(path)
62
62
  file_extension = File.extname(path)[1..-1]
63
63
  file_name = File.basename(path, File.extname(path))
64
64
 
65
65
  pattern = {
66
+ '%original_file_name%' => original_file_name,
67
+ '%original_path%' => original_path,
68
+ '%file_extension%' => file_extension,
69
+ '%file_name%' => file_name,
66
70
  '%language%' => lang['name'],
67
71
  '%two_letters_code%' => lang['iso_639_1'],
68
72
  '%three_letters_code%' => lang['iso_639_3'],
69
73
  '%locale%' => lang['locale'],
70
74
  '%locale_with_underscore%' => lang['locale'].gsub('-', '_'),
71
75
  '%android_code%' => android_locale_code(lang['locale']),
72
- '%original_file_name%' => original_file_name,
73
- '%original_path%' => original_path,
74
- '%file_extension%' => file_extension,
75
- '%file_name%' => file_name,
76
76
  }
77
77
 
78
78
  placeholders = pattern.inject([]){ |memo, h| memo << h.first[/%(.*)%/, 1] }
@@ -98,7 +98,8 @@ def construct_export_pattern(path, source, translation)
98
98
  translation = translation.sub('**', double_asterisk)
99
99
  end
100
100
 
101
- export_pattern = translation.split('/').reject(&:empty?).join('/').insert(0, '/')
101
+ export_pattern = translation.split('/').reject(&:empty?).join('/')
102
+ export_pattern.insert(0, '/') if translation.start_with?('/')
102
103
 
103
104
  return export_pattern
104
105
  end
@@ -182,14 +183,16 @@ end
182
183
  #
183
184
  def unzip_file_with_translations(zipfile_name, dest_path, files_list)
184
185
  # overwrite files if they already exist inside of the extracted path
185
- Zip.options[:on_exists_proc] = true
186
+ Zip.on_exists_proc = true
186
187
 
187
188
  # files that exists in archive and doesn't match current project configuration
188
189
  unmatched_files = []
189
190
 
190
- Zip::ZipFile.open(zipfile_name) do |zipfile|
191
+ Zip::File.open(zipfile_name) do |zipfile|
191
192
  zipfile.select{ |zip_entry| zip_entry.file? }.each do |f|
192
- file = files_list['/' + f.name]
193
+ # XXX
194
+ # `f' - relative path in archive
195
+ file = files_list[f.name]
193
196
  if file
194
197
  fpath = File.join(dest_path, file)
195
198
  FileUtils.mkdir_p(File.dirname(fpath))
@@ -221,12 +224,12 @@ sort_help :manually # help commands are ordered in the order declared
221
224
  wrap_help_text :to_terminal
222
225
 
223
226
  desc I18n.t('app.switches.verbose.desc')
224
- switch [:verbose, :v], :negatable => false
227
+ switch [:v, :verbose], :negatable => false
225
228
 
226
229
  desc I18n.t('app.flags.config.desc')
227
230
  default_value File.join(Dir.pwd, 'crowdin.yaml')
228
231
  arg_name '<s>'
229
- flag [:config,:c]
232
+ flag [:c, :config]
230
233
 
231
234
  desc I18n.t('app.commands.upload.desc')
232
235
  long_desc I18n.t('app.commands.upload.long_desc')
@@ -237,6 +240,7 @@ command :upload do |c|
237
240
  c.command :sources do |c|
238
241
 
239
242
  c.desc I18n.t('app.commands.upload.commands.sources.switches.auto_update.desc')
243
+ c.default_value true
240
244
  c.switch ['auto-update']
241
245
 
242
246
  c.action do |global_options, options, args|
@@ -258,12 +262,12 @@ command :upload do |c|
258
262
  puts "Warning: #{placeholder} is not valid variable supported by Crowdin. See http://crowdin.net/page/cli-tool#configuration-file for more details."
259
263
  end
260
264
 
261
- if File.exist?("#{@base_path}#{file['source']}")
265
+ if File.exist?(File.join(@base_path, file['source']))
262
266
  dest = file['source']
263
267
  dest_files << dest
264
268
 
265
- local_file = { dest: dest, source: "#{@base_path}#{file['source']}", export_pattern: file['translation'] }
266
- # Used only when uploading CSV file to define data columns mapping.
269
+ local_file = { dest: dest, source: File.join(@base_path, file['source']), export_pattern: file['translation'] }
270
+ # Used only when uploading CSV file to define data columns mapping
267
271
  local_file.merge!({ sheme: file['scheme'] }) if file.has_key?('scheme')
268
272
  local_file.merge!({ first_line_contains_header: file['first_line_contains_header'] }) if file.has_key?('first_line_contains_header')
269
273
 
@@ -279,7 +283,7 @@ command :upload do |c|
279
283
  else
280
284
  next
281
285
  end
282
- elsif File.fnmatch?(file['source'], dest)
286
+ elsif File.fnmatch?(file['source'], dest, File::FNM_PATHNAME)
283
287
  dest_files << dest
284
288
 
285
289
  export_pattern = construct_export_pattern(dest, file['source'], file['translation'])
@@ -317,7 +321,7 @@ EOS
317
321
  @crowdin.add_directory(dir)
318
322
  end
319
323
 
320
- if options['auto-update'].nil? or options['auto-update']
324
+ if options['auto-update']
321
325
  # Update existing files in Crowdin project
322
326
  #
323
327
  # array containing elements common to the two arrays
@@ -365,7 +369,7 @@ EOS
365
369
  c.desc I18n.t('app.commands.upload.commands.translations.flags.language.desc')
366
370
  c.default_value 'all'
367
371
  c.arg_name 'crowdin_language_code'
368
- c.flag [:language, :l]
372
+ c.flag [:l, :language]
369
373
 
370
374
  c.desc I18n.t('app.commands.upload.commands.translations.switches.import_duplicates.desc')
371
375
  c.switch ['import-duplicates']
@@ -398,11 +402,12 @@ EOS
398
402
  end
399
403
 
400
404
  supported_languages = @crowdin.supported_languages
401
- translation_languages = supported_languages.select{ |lang| project_languages.include?(lang['crowdin_code']) }
402
405
 
403
406
  source_language = project_info['details']['source_language']['code']
404
407
  source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
405
408
 
409
+ translation_languages = supported_languages.select{ |lang| project_languages.include?(lang['crowdin_code']) }
410
+
406
411
  translated_files = Hash.new{ |hash, key| hash[key] = Array.new }
407
412
  dest_files = []
408
413
 
@@ -413,13 +418,22 @@ EOS
413
418
 
414
419
  languages_mapping = file['languages_mapping']
415
420
 
416
- if File.exists?("#{@base_path}#{file['source']}")
421
+ # CSV files only (default: false)
422
+ multilingual_spreadsheet = file['multilingual_spreadsheet'] || false
423
+
424
+ if multilingual_spreadsheet
425
+ file_translation_languages = [] << source_language
426
+ else
427
+ file_translation_languages = translation_languages
428
+ end
429
+
430
+ if File.exists?(File.join(@base_path, file['source']))
417
431
  dest = file['source'].sub("#{@base_path}", '')
418
432
  dest_files << dest
419
433
 
420
- translation_languages.each do |lang|
434
+ file_translation_languages.each do |lang|
421
435
  source = export_pattern_to_path(dest, file['translation'], lang, languages_mapping)
422
- translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
436
+ translated_files[lang['crowdin_code']] << { source: File.join(@base_path, source), dest: dest }
423
437
  end
424
438
  else
425
439
  Find.find(@base_path) do |source_path|
@@ -432,17 +446,17 @@ EOS
432
446
  else
433
447
  next
434
448
  end
435
- elsif File.fnmatch?(file['source'], dest)
449
+ elsif File.fnmatch?(file['source'], dest, File::FNM_PATHNAME)
436
450
  dest_files << dest
437
451
 
438
452
  export_pattern = construct_export_pattern(dest, file['source'], file['translation'])
439
453
 
440
- translation_languages.each do |lang|
454
+ file_translation_languages.each do |lang|
441
455
  source = export_pattern_to_path(dest, export_pattern, lang, languages_mapping)
442
- translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
456
+ translated_files[lang['crowdin_code']] << { source: File.join(@base_path, source), dest: dest }
443
457
  end
444
- end
445
458
 
459
+ end
446
460
  end # Find
447
461
 
448
462
  end # if
@@ -494,7 +508,7 @@ command :download do |c|
494
508
 
495
509
  c.desc I18n.t('app.commands.download.flags.language.desc')
496
510
  c.arg_name 'language_code'
497
- c.flag [:language, :l], :default_value => 'all'
511
+ c.flag [:l, :language], :default_value => 'all'
498
512
 
499
513
  c.action do |global_options ,options, args|
500
514
  language = options[:language]
@@ -516,11 +530,12 @@ command :download do |c|
516
530
  @crowdin.export_translations
517
531
 
518
532
  supported_languages = @crowdin.supported_languages
519
- translation_languages = supported_languages.select{ |lang| project_languages.include?(lang['crowdin_code']) }
520
533
 
521
534
  source_language = project_info['details']['source_language']['code']
522
535
  source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
523
536
 
537
+ translation_languages = supported_languages.select{ |lang| project_languages.include?(lang['crowdin_code']) }
538
+
524
539
  # keys is all possible files in .ZIP archive
525
540
  # values is resulted local files
526
541
  downloadable_files_hash = {}
@@ -528,15 +543,25 @@ command :download do |c|
528
543
  @config['files'].each do |file|
529
544
  languages_mapping = file['languages_mapping'] # Hash or NilClass
530
545
 
531
- if File.exists?("#{@base_path}#{file['source']}")
546
+ # CSV files only (default: false)
547
+ multilingual_spreadsheet = file['multilingual_spreadsheet'] || false
548
+
549
+ if multilingual_spreadsheet
550
+ file_translation_languages = [] << source_language
551
+ else
552
+ file_translation_languages = translation_languages
553
+ end
554
+
555
+ if File.exists?(File.join(@base_path, file['source']))
532
556
  dest = file['source'].sub("#{@base_path}", '')
533
557
 
534
- translation_languages.each do |lang|
558
+ file_translation_languages.each do |lang|
535
559
  zipped_file = export_pattern_to_path(dest, file['translation'], lang)
560
+ zipped_file.sub!(/^\//, '')
536
561
  local_file = export_pattern_to_path(dest, file['translation'], lang, languages_mapping)
537
-
538
562
  downloadable_files_hash[zipped_file] = local_file
539
563
  end
564
+
540
565
  else
541
566
  Find.find(@base_path) do |source_path|
542
567
  dest = source_path.sub(@base_path, '') # relative path in Crowdin
@@ -548,19 +573,18 @@ command :download do |c|
548
573
  else
549
574
  next
550
575
  end
551
- elsif File.fnmatch?(file['source'], dest)
576
+ elsif File.fnmatch?(file['source'], dest, File::FNM_PATHNAME)
552
577
  export_pattern = construct_export_pattern(dest, file['source'], file['translation'])
553
578
 
554
- translation_languages.each do |lang|
579
+ file_translation_languages.each do |lang|
555
580
  zipped_file = export_pattern_to_path(dest, export_pattern, lang)
581
+ zipped_file.sub!(/^\//, '')
556
582
  local_file = export_pattern_to_path(dest, export_pattern, lang, languages_mapping)
557
-
558
583
  downloadable_files_hash[zipped_file] = local_file
559
584
  end
560
- end
561
585
 
586
+ end
562
587
  end # Find
563
-
564
588
  end # if
565
589
  end # @config['files']
566
590
 
@@ -618,7 +642,7 @@ EOS
618
642
 
619
643
  @config['files'].each do |file|
620
644
  file['source'] = '/' + file['source'] unless file['source'].start_with?('/')
621
- file['translation'] = '/' + file['translation'] unless file['translation'].start_with?('/')
645
+ #file['translation'] = '/' + file['translation'] unless file['translation'].start_with?('/')
622
646
 
623
647
  if file['source'].include?('**')
624
648
  if file['source'].scan('**').size > 1
@@ -650,13 +674,6 @@ Warning: Configuration file misses parameter `base_path` that defines your proje
650
674
  EOS
651
675
  end
652
676
 
653
- if @config['remote_path']
654
- @remote_path = @config['remote_path']
655
- @remote_path = '/' + @remote_path unless @remote_path.start_with?('/')
656
- else
657
- @remote_path = ''
658
- end
659
-
660
677
  @preserve_hierarchy = false
661
678
  if @config['preserve_hierarchy']
662
679
  @preserve_hierarchy = case @config['preserve_hierarchy']
@@ -672,7 +689,10 @@ EOS
672
689
  end
673
690
 
674
691
  Crowdin::API.log = Logger.new($stderr) if globals[:verbose]
675
- @crowdin = Crowdin::API.new(api_key: @config['api_key'], project_id: @config['project_identifier'], base_url: @config['base_url'] || 'http://api.crowdin.net')
692
+
693
+ base_url = @config['base_url'] || 'http://api.crowdin.net'
694
+ @crowdin = Crowdin::API.new(api_key: @config['api_key'], project_id: @config['project_identifier'], base_url: base_url)
695
+
676
696
  begin
677
697
  @crowdin.project_info
678
698
  rescue Crowdin::API::Errors::Error => err
@@ -7,6 +7,6 @@ require 'yaml'
7
7
  require 'json'
8
8
  require 'logger'
9
9
  require 'gli'
10
- require 'zip/zip'
10
+ require 'zip'
11
11
  require 'i18n'
12
12
  require 'crowdin-api'
@@ -1,5 +1,5 @@
1
1
  module Crowdin
2
2
  module CLI
3
- VERSION = '0.2.0'
3
+ VERSION = '0.2.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crowdin-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Crowdin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-05 00:00:00.000000000 Z
11
+ date: 2013-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -58,42 +58,42 @@ dependencies:
58
58
  requirements:
59
59
  - - '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 2.6.0
61
+ version: 2.7.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
- version: 2.6.0
68
+ version: 2.7.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubyzip
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '>='
74
74
  - !ruby/object:Gem::Version
75
- version: 0.9.9
75
+ version: 1.0.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '>='
81
81
  - !ruby/object:Gem::Version
82
- version: 0.9.9
82
+ version: 1.0.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: crowdin-api
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - '>='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.0.11
89
+ version: 0.2.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '>='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.0.11
96
+ version: 0.2.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: i18n
99
99
  requirement: !ruby/object:Gem::Requirement