csv2strings 0.2.1 → 0.2.2
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/.gitignore +20 -4
- data/.travis.yml +12 -4
- data/Gemfile +5 -1
- data/README.md +3 -6
- data/Rakefile +4 -2
- data/bin/csv2strings +2 -2
- data/bin/strings2csv +2 -2
- data/csv2strings.gemspec +5 -3
- data/lib/csvconverter.rb +11 -6
- data/lib/{command.rb → csvconverter/command.rb} +0 -3
- data/lib/{csv2strings_command.rb → csvconverter/commands/csv2strings_command.rb} +5 -6
- data/lib/{strings2csv_command.rb → csvconverter/commands/strings2csv_command.rb} +5 -7
- data/lib/csvconverter/csv2strings.rb +132 -0
- data/lib/{google_doc.rb → csvconverter/google_doc.rb} +13 -4
- data/lib/csvconverter/strings2csv.rb +96 -0
- data/test/csvconverter/commands/test_command_csv2strings.rb +36 -0
- data/test/csvconverter/commands/test_command_strings2csv.rb +77 -0
- data/test/{csv2strings/converter_test.rb → csvconverter/test_csv2strings.rb} +5 -7
- data/test/{strings2csv/converter_test.rb → csvconverter/test_strings2csv.rb} +26 -22
- data/test/data/test_with_nil.csv +3 -0
- data/test/data/test_with_nil.strings +4 -0
- data/test/test_helper.rb +8 -2
- metadata +152 -113
- data/Gemfile.lock +0 -49
- data/lib/csv2strings/converter.rb +0 -133
- data/lib/strings2csv/converter.rb +0 -95
- data/test/command_test.rb +0 -90
- data/test/google_doc_test.rb +0 -6
data/Gemfile.lock
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
csv2strings (0.2.1)
|
5
|
-
google_drive (= 0.3.6)
|
6
|
-
nokogiri (= 1.5.10)
|
7
|
-
thor
|
8
|
-
|
9
|
-
GEM
|
10
|
-
remote: http://rubygems.org/
|
11
|
-
specs:
|
12
|
-
faraday (0.8.8)
|
13
|
-
multipart-post (~> 1.2.0)
|
14
|
-
google_drive (0.3.6)
|
15
|
-
nokogiri (>= 1.4.4, != 1.5.2, != 1.5.1)
|
16
|
-
oauth (>= 0.3.6)
|
17
|
-
oauth2 (>= 0.5.0)
|
18
|
-
httpauth (0.2.0)
|
19
|
-
jwt (0.1.6)
|
20
|
-
multi_json (>= 1.0)
|
21
|
-
multi_json (1.3.6)
|
22
|
-
multi_xml (0.5.5)
|
23
|
-
multipart-post (1.2.0)
|
24
|
-
nokogiri (1.5.10)
|
25
|
-
oauth (0.4.7)
|
26
|
-
oauth2 (0.9.2)
|
27
|
-
faraday (~> 0.8)
|
28
|
-
httpauth (~> 0.2)
|
29
|
-
jwt (~> 0.1.4)
|
30
|
-
multi_json (~> 1.0)
|
31
|
-
multi_xml (~> 0.5)
|
32
|
-
rack (~> 1.2)
|
33
|
-
rack (1.5.2)
|
34
|
-
rake (0.9.2.2)
|
35
|
-
simplecov (0.6.4)
|
36
|
-
multi_json (~> 1.0)
|
37
|
-
simplecov-html (~> 0.5.3)
|
38
|
-
simplecov-html (0.5.3)
|
39
|
-
test-unit (2.4.8)
|
40
|
-
thor (0.18.1)
|
41
|
-
|
42
|
-
PLATFORMS
|
43
|
-
ruby
|
44
|
-
|
45
|
-
DEPENDENCIES
|
46
|
-
csv2strings!
|
47
|
-
rake
|
48
|
-
simplecov
|
49
|
-
test-unit
|
@@ -1,133 +0,0 @@
|
|
1
|
-
module CSV2Strings
|
2
|
-
class Converter
|
3
|
-
attr_accessor :csv_filename, :output_file
|
4
|
-
attr_accessor :langs, :default_lang
|
5
|
-
attr_accessor :default_path
|
6
|
-
attr_accessor :excluded_states, :state_column, :keys_column
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(filename, langs, args = {})
|
10
|
-
args.merge!({
|
11
|
-
:excluded_states => [],
|
12
|
-
:state_column => nil,
|
13
|
-
:keys_column => 0})
|
14
|
-
|
15
|
-
@csv_filename = filename
|
16
|
-
@langs = langs
|
17
|
-
|
18
|
-
if !@langs.is_a?(Hash) || @langs.size == 0
|
19
|
-
raise "wrong format or/and languages parameter" + @langs.inspect
|
20
|
-
end
|
21
|
-
@output_file = (@langs.size == 1) ? args[:output_file] : nil
|
22
|
-
|
23
|
-
@default_path = args[:default_path].to_s
|
24
|
-
@excluded_states = args[:excluded_states]
|
25
|
-
@state_column = args[:state_column]
|
26
|
-
@keys_column = args[:keys_column]
|
27
|
-
@default_lang = args[:default_lang]
|
28
|
-
end
|
29
|
-
|
30
|
-
def create_file_from_path(file_path)
|
31
|
-
path = File.dirname(file_path)
|
32
|
-
FileUtils.mkdir_p path
|
33
|
-
return File.new(file_path,"w")
|
34
|
-
end
|
35
|
-
|
36
|
-
def process_header(excludedCols, files, row, index)
|
37
|
-
files[index] = []
|
38
|
-
lang_index = row[index]
|
39
|
-
|
40
|
-
# create output files here
|
41
|
-
if @output_file
|
42
|
-
# one single file
|
43
|
-
files[index] << self.create_file_from_path(@output_file)
|
44
|
-
else
|
45
|
-
# create one file for each languages
|
46
|
-
if self.langs[lang_index].is_a?(Array)
|
47
|
-
|
48
|
-
self.langs[lang_index].each do |locale|
|
49
|
-
filename = self.file_path_for_locale(locale)
|
50
|
-
files[index] << self.create_file_from_path(filename)
|
51
|
-
end
|
52
|
-
elsif self.langs[lang_index].is_a?(String)
|
53
|
-
locale = self.langs[lang_index]
|
54
|
-
filename = self.file_path_for_locale(locale)
|
55
|
-
files[index] << self.create_file_from_path(filename)
|
56
|
-
else
|
57
|
-
raise "wrong format or/and languages parameter"
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def file_path_for_locale(locale)
|
64
|
-
require 'pathname'
|
65
|
-
Pathname.new(self.default_path) + "#{locale}.lproj" + "Localizable.strings"
|
66
|
-
end
|
67
|
-
|
68
|
-
def process_value(row_value, default_value)
|
69
|
-
value = row_value.nil? ? default_value : row_value
|
70
|
-
value = "" if value.nil?
|
71
|
-
value.gsub!(/\\*\"/, "\\\"") #escape double quotes
|
72
|
-
value.gsub!(/\s*(\n|\\\s*n)\s*/, "\\n") #replace new lines with \n + strip
|
73
|
-
value.gsub!(/%\s+([a-zA-Z@])([^a-zA-Z@]|$)/, "%\\1\\2") #repair string formats ("% d points" etc)
|
74
|
-
value.gsub!(/([^0-9\s\(\{\[^])%/, "\\1 %")
|
75
|
-
value.strip!
|
76
|
-
return value
|
77
|
-
end
|
78
|
-
|
79
|
-
# Convert csv file to multiple Localizable.strings files for each column
|
80
|
-
def csv_to_dotstrings(name = self.csv_filename)
|
81
|
-
files = {}
|
82
|
-
rowIndex = 0
|
83
|
-
excludedCols = []
|
84
|
-
defaultCol = 0
|
85
|
-
nb_translations = 0
|
86
|
-
|
87
|
-
CSVParserClass.foreach(name, :quote_char => '"', :col_sep =>',', :row_sep => :auto) do |row|
|
88
|
-
|
89
|
-
if rowIndex == 0
|
90
|
-
return unless row.count > 1 #check there's at least two columns
|
91
|
-
else
|
92
|
-
next if row == nil or row[self.keys_column].nil? #skip empty lines (or sections)
|
93
|
-
end
|
94
|
-
|
95
|
-
row.size.times do |i|
|
96
|
-
next if excludedCols.include? i
|
97
|
-
if rowIndex == 0 #header
|
98
|
-
# ignore all headers not listed in langs to create files
|
99
|
-
(excludedCols << i and next) unless self.langs.has_key?(row[i])
|
100
|
-
self.process_header(excludedCols, files, row, i)
|
101
|
-
# define defaultCol
|
102
|
-
defaultCol = i if self.default_lang == row[i]
|
103
|
-
elsif !self.state_column || (row[self.state_column].nil? or row[self.state_column] == '' or !self.excluded_states.include? row[self.state_column])
|
104
|
-
# TODO: add option to strip the constant or referenced language
|
105
|
-
key = row[self.keys_column].strip
|
106
|
-
value = self.process_value(row[i], row[defaultCol])
|
107
|
-
# files for a given language, i.e could group english US with english UK.
|
108
|
-
localized_files = files[i]
|
109
|
-
if localized_files
|
110
|
-
localized_files.each do |file|
|
111
|
-
nb_translations += 1
|
112
|
-
file.write "\"#{key}\" = \"#{value}\";\n"
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
rowIndex += 1
|
118
|
-
end
|
119
|
-
info = "Created #{files.size} files. Content: #{nb_translations} translations\n"
|
120
|
-
info += "List of created files:\n"
|
121
|
-
|
122
|
-
# closing I/O
|
123
|
-
files.each do |key,locale_files|
|
124
|
-
locale_files.each do |file|
|
125
|
-
info += "#{file.path.to_s}\n"
|
126
|
-
file.close
|
127
|
-
end
|
128
|
-
end
|
129
|
-
info
|
130
|
-
end # end of method
|
131
|
-
|
132
|
-
end # end of class
|
133
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
module Strings2CSV
|
2
|
-
class Converter
|
3
|
-
|
4
|
-
attr_accessor :csv_filename, :headers, :filenames, :default_lang
|
5
|
-
|
6
|
-
def initialize(args = {:filenames => []})
|
7
|
-
if args[:filenames] && args[:headers]
|
8
|
-
raise ArgumentError.new("number of headers and files don't match, don't forget the constant column") unless args[:headers].size == (args[:filenames].size + 1)
|
9
|
-
end
|
10
|
-
|
11
|
-
@filenames = args[:filenames]
|
12
|
-
|
13
|
-
@csv_filename = args[:csv_filename] || "translations.csv"
|
14
|
-
@default_lang = args[:default_lang]
|
15
|
-
@headers = args[:headers] || self.default_headers
|
16
|
-
end
|
17
|
-
|
18
|
-
def default_headers
|
19
|
-
headers = ['Variables']
|
20
|
-
@filenames.each do |fname|
|
21
|
-
headers << basename(fname)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
# Load all strings of a given file
|
27
|
-
def load_strings(strings_filename)
|
28
|
-
strings = {}
|
29
|
-
File.open(strings_filename, 'r') do |strings_file|
|
30
|
-
strings_file.read.each_line do |line|
|
31
|
-
strings.merge!(self.parse_dotstrings_line(line))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
strings
|
35
|
-
end
|
36
|
-
|
37
|
-
def parse_dotstrings_line(line)
|
38
|
-
line.strip!
|
39
|
-
if (line[0] != ?# and line[0] != ?=)
|
40
|
-
m = line.match(/^[^\"]*\"(.+)\"[^=]+=[^\"]*\"(.*)\";/)
|
41
|
-
return {m[1] => m[2]} unless m.nil?
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
# Convert Localizable.strings files to one CSV file
|
47
|
-
# output:
|
48
|
-
def dotstrings_to_csv(write_to_file = true)
|
49
|
-
# Parse .strings files
|
50
|
-
strings = {}
|
51
|
-
keys = nil
|
52
|
-
lang_order = []
|
53
|
-
|
54
|
-
@filenames.each do |fname|
|
55
|
-
header = basename(fname)
|
56
|
-
strings[header] = load_strings(fname)
|
57
|
-
lang_order << header
|
58
|
-
keys ||= strings[header].keys
|
59
|
-
end
|
60
|
-
|
61
|
-
if(write_to_file)
|
62
|
-
# Create csv file
|
63
|
-
puts "Creating #{@csv_filename}"
|
64
|
-
create_csv_file(keys, lang_order, strings)
|
65
|
-
else
|
66
|
-
return keys, lang_order, strings
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def basename(file_path)
|
71
|
-
filename = File.basename(file_path)
|
72
|
-
return filename.split('.')[0].to_sym if file_path
|
73
|
-
end
|
74
|
-
|
75
|
-
# Create the resulting file
|
76
|
-
def create_csv_file(keys, lang_order, strings)
|
77
|
-
raise "csv_filename must not be nil" unless self.csv_filename
|
78
|
-
CSVParserClass.open(self.csv_filename, "wb") do |csv|
|
79
|
-
csv << @headers
|
80
|
-
keys.each do |key|
|
81
|
-
line = [key]
|
82
|
-
default_val = strings[self.default_lang][key] if strings[self.default_lang]
|
83
|
-
lang_order.each do |lang|
|
84
|
-
current_val = strings[lang][key]
|
85
|
-
line << ((lang != self.default_lang and current_val == default_val) ? '' : current_val)
|
86
|
-
end
|
87
|
-
csv << line
|
88
|
-
end
|
89
|
-
puts "Done"
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
data/test/command_test.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
require File.expand_path('../../lib/command', __FILE__)
|
2
|
-
require File.expand_path('../test_helper', __FILE__)
|
3
|
-
|
4
|
-
class CommandTest < Test::Unit::TestCase
|
5
|
-
def test_csv2strings_with_multiple_2_languages
|
6
|
-
command = "./bin/csv2strings"
|
7
|
-
command += " --filename test/data/test_data_multiple_langs.csv"
|
8
|
-
command += " --langs=English:en French:fr"
|
9
|
-
system(command)
|
10
|
-
|
11
|
-
assert File.exist?("./en.lproj/Localizable.strings")
|
12
|
-
assert File.exist?("./fr.lproj/Localizable.strings")
|
13
|
-
|
14
|
-
#clean up
|
15
|
-
system("rm -rf ./en.lproj/")
|
16
|
-
system("rm -rf ./fr.lproj/")
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_csv2strings_with_default_path
|
20
|
-
command = "./bin/csv2strings"
|
21
|
-
command += " --filename test/data/test_data_multiple_langs.csv"
|
22
|
-
command += " --langs=English:en French:fr"
|
23
|
-
command += " --default_path=mynewlocation"
|
24
|
-
system(command)
|
25
|
-
|
26
|
-
# testing
|
27
|
-
assert File.exist?("./mynewlocation/en.lproj/Localizable.strings"), "can't find output file for English"
|
28
|
-
assert File.exist?("./mynewlocation/fr.lproj/Localizable.strings"), "can't find output file for French"
|
29
|
-
|
30
|
-
#clean up
|
31
|
-
system("rm -rf ./mynewlocation")
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_strings2csv
|
35
|
-
command = "./bin/strings2csv"
|
36
|
-
command += " --filenames test/data/test_data.strings"
|
37
|
-
system(command)
|
38
|
-
|
39
|
-
assert File.exist?("translations.csv")
|
40
|
-
|
41
|
-
#clean up
|
42
|
-
system("rm -f translations.csv")
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_strings2csv_with_dryrun_option
|
46
|
-
command = "./bin/strings2csv"
|
47
|
-
command += " --filenames test/data/test_data.strings"
|
48
|
-
command += " --dryrun"
|
49
|
-
system(command)
|
50
|
-
|
51
|
-
assert !File.exist?("translations.csv")
|
52
|
-
|
53
|
-
#clean up
|
54
|
-
system("rm -f translations.csv")
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_strings2csv_with_output_file
|
58
|
-
command = "./bin/strings2csv"
|
59
|
-
command += " -i=test/data/test_data.strings"
|
60
|
-
command += " -o=myfile.csv"
|
61
|
-
system(command)
|
62
|
-
|
63
|
-
assert File.exist?("myfile.csv")
|
64
|
-
|
65
|
-
#clean up
|
66
|
-
system("rm -f myfile.csv")
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_strings2csv_with_headers
|
70
|
-
command = "./bin/strings2csv"
|
71
|
-
command += " -i=test/data/test_data.strings"
|
72
|
-
command += " -h=constants english"
|
73
|
-
system(command)
|
74
|
-
|
75
|
-
#TODO assertion or move test on at lib level
|
76
|
-
|
77
|
-
#clean up
|
78
|
-
system("rm -f translations.csv")
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_strings2csv_with_two_files
|
82
|
-
command = "./bin/strings2csv"
|
83
|
-
command += " --filenames=test/data/test_en.strings test/data/test_fr.strings"
|
84
|
-
command += " --headers=Constants English French"
|
85
|
-
command += " -o=enfr.csv"
|
86
|
-
system(command)
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
|