crowdin-cli 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -0
- data/bin/crowdin-cli +79 -42
- data/lib/crowdin-cli.rb +1 -0
- data/lib/crowdin-cli/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -4,6 +4,8 @@ A Command-Line Interface to sync files between your computer/server and [Crowdin
|
|
4
4
|
|
5
5
|
It is cross-platform and runs in a terminal (Linux, MacOS X) or in cmd.exe (Windows).
|
6
6
|
|
7
|
+
> **WARNING**: This is a development version: It contains the latest changes, but may also have severe known issues, including crashes and data loss situations. In fact, it may not work at all.
|
8
|
+
|
7
9
|
## Installation
|
8
10
|
|
9
11
|
Add this line to your application's Gemfile:
|
data/bin/crowdin-cli
CHANGED
@@ -3,46 +3,50 @@
|
|
3
3
|
require 'pp'
|
4
4
|
require 'crowdin-cli'
|
5
5
|
|
6
|
-
#
|
7
|
-
# return existing directory structure in Crowdin project
|
6
|
+
# Return +hierarchy+ of directories and files in Crowdin project
|
8
7
|
#
|
9
|
-
|
8
|
+
# +files+ - basically, it's project files details from API method `project_info`
|
9
|
+
#
|
10
|
+
def get_remote_files_hierarchy(files, root = '/', hierarchy = { dirs: [], files: [] })
|
10
11
|
files.each do |node|
|
11
12
|
case node['node_type']
|
12
13
|
when 'directory'
|
13
|
-
|
14
|
-
|
14
|
+
hierarchy[:dirs] << "#{root}#{node['name']}"
|
15
|
+
get_remote_files_hierarchy(node['files'], root + node['name'] + '/', hierarchy)
|
15
16
|
when 'file'
|
16
|
-
|
17
|
+
hierarchy[:files] << "#{root}#{node['name']}"
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
return
|
21
|
+
return hierarchy
|
21
22
|
end
|
22
23
|
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
24
|
+
# Return +hierarchy+ of local directories and files
|
25
|
+
#
|
26
|
+
# @params [Array] files a list of files in a local directory.
|
26
27
|
#
|
27
|
-
def
|
28
|
-
|
28
|
+
def get_local_files_hierarchy(files, hierarchy = { dirs: [], files: [] })
|
29
|
+
hierarchy[:files] = files
|
29
30
|
|
30
|
-
|
31
|
+
dirs = files.inject([]) do |res, a|
|
31
32
|
res << a.split('/').drop(1).inject([]) do |res, s|
|
32
33
|
res << res.last.to_s + '/' + s
|
33
34
|
end
|
34
35
|
end
|
35
|
-
#
|
36
|
-
|
37
|
-
files.map(&:pop) # delete last element from each array
|
38
|
-
result[:dirs] = files.flatten.uniq
|
36
|
+
dirs.map(&:pop) # delete last element from each array
|
37
|
+
hierarchy[:dirs] = dirs.flatten.uniq
|
39
38
|
|
40
|
-
return
|
39
|
+
return hierarchy
|
41
40
|
end
|
42
41
|
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
42
|
+
# @param [String] path relative path to file in Crowdin project
|
43
|
+
# @param [String] export_pattern basically, is a file['translation'] from crowdin.yaml
|
44
|
+
# @param [Hash] lang language information
|
45
|
+
# @option lang [String] :name
|
46
|
+
# @option lang [String] :crowdin_code
|
47
|
+
# @option lang [String] :iso_639_1
|
48
|
+
# @option lang [String] :iso_639_3
|
49
|
+
# @option lang [String] :locale
|
46
50
|
#
|
47
51
|
def export_pattern_to_path(path, export_pattern, lang)
|
48
52
|
original_path = File.dirname(path)
|
@@ -60,10 +64,34 @@ def export_pattern_to_path(path, export_pattern, lang)
|
|
60
64
|
'%original_file_name%' => original_file_name,
|
61
65
|
'%original_path%' => original_path,
|
62
66
|
'%file_extension%' => file_extension,
|
63
|
-
'%file_name%' =>
|
67
|
+
'%file_name%' => file_name,
|
64
68
|
})
|
65
69
|
end
|
66
70
|
|
71
|
+
def android_locale_code(locale_code)
|
72
|
+
locale_code = case locale_code
|
73
|
+
when 'he-IL' then 'iw-IL'
|
74
|
+
when 'yi-DE' then 'ji-DE'
|
75
|
+
when 'id-ID' then 'in-ID'
|
76
|
+
else locale_code
|
77
|
+
end
|
78
|
+
return locale_code.sub('-', '-r')
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return a string representing that part of the directory tree that is common to all the files
|
82
|
+
#
|
83
|
+
# @params [Array] paths set of strings representing directory paths
|
84
|
+
#
|
85
|
+
def find_common_directory_path(paths)
|
86
|
+
return paths.first if paths.length <= 1
|
87
|
+
arr = paths.sort
|
88
|
+
first = arr.first.split('/')
|
89
|
+
last = arr.last.split('/')
|
90
|
+
i = 0
|
91
|
+
i += 1 while first[i] == last[i] && i <= first.length
|
92
|
+
first.slice(0, i).join('/')
|
93
|
+
end
|
94
|
+
|
67
95
|
def unzip_file(file, dest)
|
68
96
|
# overwrite files if they already exist inside of the extracted path
|
69
97
|
Zip.options[:on_exists_proc] = true
|
@@ -78,15 +106,6 @@ def unzip_file(file, dest)
|
|
78
106
|
end
|
79
107
|
end
|
80
108
|
|
81
|
-
def android_locale_code(locale_code)
|
82
|
-
locale_code = case locale_code
|
83
|
-
when 'he-IL' then 'iw-IL'
|
84
|
-
when 'yi-DE' then 'ji-DE'
|
85
|
-
when 'id-ID' then 'in-ID'
|
86
|
-
else locale_code
|
87
|
-
end
|
88
|
-
return locale_code.sub('-', '-r')
|
89
|
-
end
|
90
109
|
|
91
110
|
###
|
92
111
|
include GLI::App
|
@@ -122,7 +141,6 @@ command :upload do |c|
|
|
122
141
|
# end
|
123
142
|
#end
|
124
143
|
|
125
|
-
# TODO: change variables names!
|
126
144
|
c.desc 'Upload source files'
|
127
145
|
c.command :sources do |c|
|
128
146
|
c.action do |global_options, options, args|
|
@@ -134,15 +152,18 @@ command :upload do |c|
|
|
134
152
|
supported_languages = @crowdin.supported_languages
|
135
153
|
source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
|
136
154
|
|
137
|
-
remote_project_tree =
|
155
|
+
remote_project_tree = get_remote_files_hierarchy(project_info['files'])
|
138
156
|
|
139
157
|
local_files = []
|
158
|
+
dest_files = []
|
140
159
|
@config['files'].each do |file|
|
141
160
|
if File.exist?("#{@base_path}#{file['source']}")
|
142
161
|
local_files << { dest: file['source'], source: "#{@base_path}#{file['source']}", export_pattern: file['translation'] }
|
143
162
|
else
|
144
163
|
Dir.glob("#{@base_path}#{file['source']}").each do |source|
|
145
164
|
dest = source.sub("#{@base_path}", '') # relative path in Crowdin
|
165
|
+
dest_files << dest
|
166
|
+
|
146
167
|
file_pattern = export_pattern_to_path(dest, file['translation'], source_language)
|
147
168
|
|
148
169
|
diff = (dest.split('/') - file_pattern.split('/')).join('/')
|
@@ -154,7 +175,16 @@ command :upload do |c|
|
|
154
175
|
end
|
155
176
|
end
|
156
177
|
|
157
|
-
local_project_tree =
|
178
|
+
local_project_tree = get_local_files_hierarchy(local_files.collect{ |h| h[:dest] })
|
179
|
+
|
180
|
+
common_dir = find_common_directory_path(dest_files)
|
181
|
+
|
182
|
+
if common_dir
|
183
|
+
local_files.each{ |file| file[:dest].sub!(common_dir, '') }
|
184
|
+
local_project_tree[:dirs].each{ |dir| dir.sub!(common_dir, '')}
|
185
|
+
local_project_tree[:dirs].delete_if{ |dir| dir == ''}
|
186
|
+
local_project_tree[:files].each{ |file| file.sub!(common_dir, '')}
|
187
|
+
end
|
158
188
|
|
159
189
|
# Create directory tree
|
160
190
|
#
|
@@ -209,7 +239,7 @@ command :upload do |c|
|
|
209
239
|
|
210
240
|
project_info = @crowdin.project_info
|
211
241
|
|
212
|
-
remote_project_tree =
|
242
|
+
remote_project_tree = get_remote_files_hierarchy(project_info['files'])
|
213
243
|
|
214
244
|
if language == 'all'
|
215
245
|
project_languages = project_info['languages'].collect{ |h| h['code'] }
|
@@ -224,6 +254,7 @@ command :upload do |c|
|
|
224
254
|
source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
|
225
255
|
|
226
256
|
translated_files = Hash.new{ |hash, key| hash[key] = Array.new }
|
257
|
+
dest_files = []
|
227
258
|
|
228
259
|
@config['files'].each do |file|
|
229
260
|
if File.exists?("#{@base_path}#{file['source']}")
|
@@ -231,12 +262,12 @@ command :upload do |c|
|
|
231
262
|
|
232
263
|
translation_languages.each do |lang|
|
233
264
|
source = export_pattern_to_path(dest, file['translation'], lang)
|
234
|
-
|
235
265
|
translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
|
236
266
|
end
|
237
267
|
else
|
238
268
|
Dir.glob("#{@base_path}#{file['source']}").each do |source|
|
239
|
-
dest = source.sub("#{@base_path}", '')
|
269
|
+
dest = source.sub("#{@base_path}", '') # relative path in Crowdin
|
270
|
+
dest_files << dest
|
240
271
|
|
241
272
|
file_pattern = export_pattern_to_path(dest, file['translation'], source_language)
|
242
273
|
|
@@ -245,7 +276,6 @@ command :upload do |c|
|
|
245
276
|
|
246
277
|
translation_languages.each do |lang|
|
247
278
|
source = export_pattern_to_path(dest, export_pattern, lang)
|
248
|
-
|
249
279
|
translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
|
250
280
|
end
|
251
281
|
|
@@ -258,14 +288,21 @@ command :upload do |c|
|
|
258
288
|
params[:import_eq_suggestions] = options[:import_eq_suggestions] ? 1 : 0
|
259
289
|
params[:auto_approve_imported] = options[:auto_approve_imported] ? 1 : 0
|
260
290
|
|
291
|
+
common_dir = find_common_directory_path(dest_files)
|
261
292
|
|
262
293
|
translated_files.each do |language, files|
|
263
294
|
files.each do |file|
|
264
|
-
|
265
|
-
|
266
|
-
|
295
|
+
file[:dest].sub!(common_dir, '')
|
296
|
+
if remote_project_tree[:files].include?(file[:dest])
|
297
|
+
if File.exist?(file[:source])
|
298
|
+
puts "Uploading #{file[:source].sub(@base_path, '')}"
|
299
|
+
@crowdin.upload_translation([] << file, language, params)
|
300
|
+
else
|
301
|
+
puts "Local file #{file[:source]} not exists"
|
302
|
+
end
|
267
303
|
else
|
268
|
-
|
304
|
+
# if source file not exist, don't upload translation
|
305
|
+
puts "Skip #{file[:source].sub(@base_path, '')}"
|
269
306
|
end
|
270
307
|
end
|
271
308
|
end
|
data/lib/crowdin-cli.rb
CHANGED
data/lib/crowdin-cli/version.rb
CHANGED
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.
|
4
|
+
version: 0.0.10
|
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-10-
|
12
|
+
date: 2012-10-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|