bin/crowdin-cli in crowdin-cli-0.0.9 vs bin/crowdin-cli in crowdin-cli-0.0.10
- old
+ new
@@ -1,50 +1,54 @@
#!/usr/bin/env ruby
require 'pp'
require 'crowdin-cli'
-# using for upload source files
-# return existing directory structure in Crowdin project
+# Return +hierarchy+ of directories and files in Crowdin project
#
-def walk_remote_tree(files, root = '/', result = { dirs: [], files: [] })
+# +files+ - basically, it's project files details from API method `project_info`
+#
+def get_remote_files_hierarchy(files, root = '/', hierarchy = { dirs: [], files: [] })
files.each do |node|
case node['node_type']
when 'directory'
- result[:dirs] << "#{root}#{node['name']}"
- walk_remote_tree(node['files'], root + node['name'] + '/', result)
+ hierarchy[:dirs] << "#{root}#{node['name']}"
+ get_remote_files_hierarchy(node['files'], root + node['name'] + '/', hierarchy)
when 'file'
- result[:files] << "#{root}#{node['name']}"
+ hierarchy[:files] << "#{root}#{node['name']}"
end
end
- return result
+ return hierarchy
end
-# using for upload source files
-# return local directory structute
-# first argument: ['/path/to/admin/en.xml', '/path/to/user/settings/strings.xml']
+# Return +hierarchy+ of local directories and files
#
-def walk_local_tree(files, result = { dirs: [], files: [] })
- result[:files] = files
+# @params [Array] files a list of files in a local directory.
+#
+def get_local_files_hierarchy(files, hierarchy = { dirs: [], files: [] })
+ hierarchy[:files] = files
- files = files.inject([]) do |res, a|
+ dirs = files.inject([]) do |res, a|
res << a.split('/').drop(1).inject([]) do |res, s|
res << res.last.to_s + '/' + s
end
end
- # Ex: files = [["/path", "/path/to", "/path/to/admin", "/path/to/admin/en.xml"], ... ]
+ dirs.map(&:pop) # delete last element from each array
+ hierarchy[:dirs] = dirs.flatten.uniq
- files.map(&:pop) # delete last element from each array
- result[:dirs] = files.flatten.uniq
-
- return result
+ return hierarchy
end
-# +path_ - relative path to file in Crowdin project
-# +export_pattern+ - basically, is a file['translation'] from crowdin.yaml
-# +lang+ - Hash containing language information
+# @param [String] path relative path to file in Crowdin project
+# @param [String] export_pattern basically, is a file['translation'] from crowdin.yaml
+# @param [Hash] lang language information
+# @option lang [String] :name
+# @option lang [String] :crowdin_code
+# @option lang [String] :iso_639_1
+# @option lang [String] :iso_639_3
+# @option lang [String] :locale
#
def export_pattern_to_path(path, export_pattern, lang)
original_path = File.dirname(path)
original_file_name = File.basename(path)
file_extension = File.extname(path)[1..-1]
@@ -58,14 +62,38 @@
'%locale_with_underscore%' => lang['locale'].gsub('-', '_'),
'%android_code%' => android_locale_code(lang['locale']),
'%original_file_name%' => original_file_name,
'%original_path%' => original_path,
'%file_extension%' => file_extension,
- '%file_name%' => file_extension,
+ '%file_name%' => file_name,
})
end
+def android_locale_code(locale_code)
+ locale_code = case locale_code
+ when 'he-IL' then 'iw-IL'
+ when 'yi-DE' then 'ji-DE'
+ when 'id-ID' then 'in-ID'
+ else locale_code
+ end
+ return locale_code.sub('-', '-r')
+end
+
+# Return a string representing that part of the directory tree that is common to all the files
+#
+# @params [Array] paths set of strings representing directory paths
+#
+def find_common_directory_path(paths)
+ return paths.first if paths.length <= 1
+ arr = paths.sort
+ first = arr.first.split('/')
+ last = arr.last.split('/')
+ i = 0
+ i += 1 while first[i] == last[i] && i <= first.length
+ first.slice(0, i).join('/')
+end
+
def unzip_file(file, dest)
# overwrite files if they already exist inside of the extracted path
Zip.options[:on_exists_proc] = true
Zip::ZipFile.open(file) do |zip_file|
@@ -76,19 +104,10 @@
zip_file.extract(f, f_path)
end
end
end
-def android_locale_code(locale_code)
- locale_code = case locale_code
- when 'he-IL' then 'iw-IL'
- when 'yi-DE' then 'ji-DE'
- when 'id-ID' then 'in-ID'
- else locale_code
- end
- return locale_code.sub('-', '-r')
-end
###
include GLI::App
program_desc 'A CLI to sync locale files with crowdin.net'
@@ -120,11 +139,10 @@
# puts options
# puts "`upload all` command ran"
# end
#end
- # TODO: change variables names!
c.desc 'Upload source files'
c.command :sources do |c|
c.action do |global_options, options, args|
project_info = @crowdin.project_info
@@ -132,19 +150,22 @@
# Crowdin supported languages list
supported_languages = @crowdin.supported_languages
source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
- remote_project_tree = walk_remote_tree(project_info['files'])
+ remote_project_tree = get_remote_files_hierarchy(project_info['files'])
local_files = []
+ dest_files = []
@config['files'].each do |file|
if File.exist?("#{@base_path}#{file['source']}")
local_files << { dest: file['source'], source: "#{@base_path}#{file['source']}", export_pattern: file['translation'] }
else
Dir.glob("#{@base_path}#{file['source']}").each do |source|
dest = source.sub("#{@base_path}", '') # relative path in Crowdin
+ dest_files << dest
+
file_pattern = export_pattern_to_path(dest, file['translation'], source_language)
diff = (dest.split('/') - file_pattern.split('/')).join('/')
export_pattern = file['translation'].sub('**', diff)
@@ -152,12 +173,21 @@
end
end
end
- local_project_tree = walk_local_tree(local_files.collect{ |h| h[:dest] })
+ local_project_tree = get_local_files_hierarchy(local_files.collect{ |h| h[:dest] })
+ common_dir = find_common_directory_path(dest_files)
+
+ if common_dir
+ local_files.each{ |file| file[:dest].sub!(common_dir, '') }
+ local_project_tree[:dirs].each{ |dir| dir.sub!(common_dir, '')}
+ local_project_tree[:dirs].delete_if{ |dir| dir == ''}
+ local_project_tree[:files].each{ |file| file.sub!(common_dir, '')}
+ end
+
# Create directory tree
#
create_dirs = local_project_tree[:dirs] - remote_project_tree[:dirs]
create_dirs.each do |dir|
puts "Create directory `#{dir}`"
@@ -207,11 +237,11 @@
c.action do |global_options, options, args|
language = options[:language]
project_info = @crowdin.project_info
- remote_project_tree = walk_remote_tree(project_info['files'])
+ remote_project_tree = get_remote_files_hierarchy(project_info['files'])
if language == 'all'
project_languages = project_info['languages'].collect{ |h| h['code'] }
else
project_languages = [] << language
@@ -222,32 +252,32 @@
source_language = project_info['source_language']['code']
source_language = supported_languages.find{ |lang| lang['crowdin_code'] == source_language }
translated_files = Hash.new{ |hash, key| hash[key] = Array.new }
+ dest_files = []
@config['files'].each do |file|
if File.exists?("#{@base_path}#{file['source']}")
dest = file['source'].sub("#{@base_path}", '')
translation_languages.each do |lang|
source = export_pattern_to_path(dest, file['translation'], lang)
-
translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
end
else
Dir.glob("#{@base_path}#{file['source']}").each do |source|
- dest = source.sub("#{@base_path}", '')
+ dest = source.sub("#{@base_path}", '') # relative path in Crowdin
+ dest_files << dest
file_pattern = export_pattern_to_path(dest, file['translation'], source_language)
diff = (dest.split('/') - file_pattern.split('/')).join('/')
export_pattern = file['translation'].sub('**', diff)
translation_languages.each do |lang|
source = export_pattern_to_path(dest, export_pattern, lang)
-
translated_files[lang['crowdin_code']] << { source: "#{@base_path}#{source}", dest: dest }
end
end
end # if
@@ -256,17 +286,24 @@
params = {}
params[:import_duplicates] = options[:import_dublicates] ? 1 : 0
params[:import_eq_suggestions] = options[:import_eq_suggestions] ? 1 : 0
params[:auto_approve_imported] = options[:auto_approve_imported] ? 1 : 0
+ common_dir = find_common_directory_path(dest_files)
translated_files.each do |language, files|
files.each do |file|
- if File.exist?(file[:source])
- puts "Uploading #{file[:source]}"
- @crowdin.upload_translation([] << file, language, params)
+ file[:dest].sub!(common_dir, '')
+ if remote_project_tree[:files].include?(file[:dest])
+ if File.exist?(file[:source])
+ puts "Uploading #{file[:source].sub(@base_path, '')}"
+ @crowdin.upload_translation([] << file, language, params)
+ else
+ puts "Local file #{file[:source]} not exists"
+ end
else
- puts "Local file #{file[:source]} not exists"
+ # if source file not exist, don't upload translation
+ puts "Skip #{file[:source].sub(@base_path, '')}"
end
end
end
end # action