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 +4 -4
- data/README.md +45 -20
- data/bin/crowdin-cli +64 -44
- data/lib/crowdin-cli.rb +1 -1
- data/lib/crowdin-cli/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f6bb76e96af25bd099e35327e0affba41a15d99
|
4
|
+
data.tar.gz: 42379e5aefbf2d76b2650fff116ed5e89f609098
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/bin/crowdin-cli
CHANGED
@@ -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('/')
|
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.
|
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::
|
191
|
+
Zip::File.open(zipfile_name) do |zipfile|
|
191
192
|
zipfile.select{ |zip_entry| zip_entry.file? }.each do |f|
|
192
|
-
|
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 [:
|
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
|
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?(
|
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:
|
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']
|
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 [:
|
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
|
-
|
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
|
-
|
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:
|
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
|
-
|
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:
|
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 [:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/crowdin-cli.rb
CHANGED
data/lib/crowdin-cli/version.rb
CHANGED
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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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
|
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
|
96
|
+
version: 0.2.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: i18n
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|