csv2strings 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTA4ZWFmNjA3MzBiZjQ0YzU0MmJhMjk5YmE4MjVhMTA3NTBlNzFhMg==
5
+ data.tar.gz: !binary |-
6
+ MzFmNDRlOGY2ZWQwNzc1MTg1MWU4NGQ4MjBkZjBlYWIzYTY2YTNmYg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NTEyY2M2NmVkN2NiMzcyMzAyOWJkNzg3ODM3MDEwZGU3ZGFlOTM4ZDc5ZjNl
10
+ OGI5YjBkY2U4MTA3ZTMwOTE1NDU5ODNhNjEzNTY5NTJjMTkxY2IwNTY0Njk5
11
+ NjVjOTdiNWIzZmMzODI5Yzg4OWMwM2VhYWRjMmI4OGIzMGNlNGM=
12
+ data.tar.gz: !binary |-
13
+ OTI4YjZjMjIzMWVhZDc2MDI3NDFmYzBlNjE3OWVmYWNmZThkODg0M2EzZWQx
14
+ MGExY2ExMTkwYjExOTkxMzViOTNhYzA1YjQwMjg2NDMzMTQwODUyNWIwZDhj
15
+ NWFlNGVlNmY4YWM5OTk5MDdlMWQwM2I5NTFmY2RlMjI5MmEzM2Y=
@@ -0,0 +1,5 @@
1
+ # This is a sample configuration file
2
+ filenames: ["test/data/test_en.strings", "test/data/test_fr.strings"]
3
+ headers: ["Constants", "English", "French"]
4
+ csv_filename: "testconfig.csv"
5
+ dryrun: true
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *.csv
2
+ *.strings
3
+ *.lproj
4
+ .rbenv-version
5
+ *~
6
+ *#
7
+ *.gem
8
+ *.sublime-project
9
+ #*#
10
+ .csvconverter
11
+ coverage
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - 1.8.7
6
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in teachmehowtomakearubygem.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ csv2strings (0.2)
5
+ thor
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ metaclass (0.0.1)
11
+ mocha (0.10.5)
12
+ metaclass (~> 0.0.1)
13
+ multi_json (1.3.6)
14
+ rake (0.9.2.2)
15
+ simplecov (0.6.4)
16
+ multi_json (~> 1.0)
17
+ simplecov-html (~> 0.5.3)
18
+ simplecov-html (0.5.3)
19
+ test-unit (2.4.8)
20
+ thor (0.17.0)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ csv2strings!
27
+ mocha
28
+ rake
29
+ simplecov
30
+ test-unit
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 François Benaiteau
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ [![Build Status](https://secure.travis-ci.org/netbe/CSV-to-iOS-Localizable.strings-converter.png?branch=master)](http://travis-ci.org/netbe/CSV-to-iOS-Localizable.strings-converter)
2
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/netbe/CSV-to-iOS-Localizable.strings-converter)
3
+ # Introduction
4
+ This script converts a csv file of translations into iOS .strings files and vice-versa.
5
+
6
+ # Setup
7
+
8
+ `gem install csvconverter`
9
+
10
+ # Usage
11
+
12
+ * Convert csv to localizable strings files:
13
+
14
+ `csv2strings <csvfilename>`
15
+
16
+ * Convert localizable strings files to csv:
17
+
18
+ `strings2csv <stringsfile1> <stringsfile2>`
19
+
20
+ * Use configuration file
21
+
22
+ You can use a configuration file to hold all your commandline arguments into a file (previous versions `i18n_config.rb`).
23
+ Place `.csvconverter` file (edit if needed) in the folder with your ``xx.lproj`` and call the script from there. See `.csvconverter.sample`
24
+
25
+
26
+ # Todo
27
+
28
+ See GitHub isssues
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << "test"
5
+ t.test_files = FileList['test/**/*_test.rb']
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
data/bin/csv2strings ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../lib/command', __FILE__)
3
+
4
+
5
+ if ARGV.count == 1 && ARGV[0] == "help"
6
+ Command.start(["help", "csv2strings"],{})
7
+ else
8
+ args = ["csv2strings"]
9
+ args += ARGV
10
+ Command.start(args,{})
11
+ end
data/bin/strings2csv ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../lib/command', __FILE__)
3
+
4
+ if ARGV.count == 1 && ARGV[0] == "help"
5
+ Command.start(["help", "strings2csv"],{})
6
+ else
7
+ args = ["strings2csv"]
8
+ args += ARGV
9
+ Command.start(args,{})
10
+ end
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'csv2strings'
3
+ s.version = '0.2.0'
4
+ s.date = '2013-09-02'
5
+ s.summary = "CSV to iOS Localizable.strings converter"
6
+ s.description = "ruby script converts a CSV file of translations to Localizable.strings files and vice-versa"
7
+ s.authors = ["François Benaiteau"]
8
+ s.email = 'francois.benaiteau@gmail.com'
9
+ s.homepage = 'https://github.com/netbe/CSV-to-iOS-Localizable.strings-converter'
10
+ s.license = 'MIT'
11
+ s.add_dependency "thor"
12
+ s.add_dependency "fastercsv", :require => 'faster_csv' if RUBY_PLATFORM == 'ruby_19'
13
+ s.add_dependency "csv", :require => 'csv' if RUBY_PLATFORM == 'ruby_18'
14
+ s.add_development_dependency "rake"
15
+ s.add_development_dependency "mocha"
16
+ s.add_development_dependency "test-unit"
17
+ s.add_development_dependency "simplecov"
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_path = ['lib']
22
+ end
data/lib/command.rb ADDED
@@ -0,0 +1,66 @@
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__)))
2
+ require 'yaml'
3
+ require 'thor'
4
+ require 'csvconverter'
5
+
6
+ class Command < Thor
7
+
8
+ desc "CSV_FILENAME", "convert CSV file to '.strings' file"
9
+ # required options but handled in method because of options read from yaml file
10
+ method_option :filename, :type => :string, :desc => "CSV file (CSV_FILENAME) to convert from"
11
+ method_option :langs, :type => :hash, :aliases => "-L", :desc => "Languages to convert"
12
+ # optional options
13
+ method_option :excluded_states, :type => :array, :aliases => "-x", :desc => "Exclude rows with given state"
14
+ method_option :state_column, :type => :numeric, :aliases => "-s", :desc => "Position of column for state if any"
15
+ method_option :keys_column, :type => :numeric, :aliases => "-k", :desc => "Position of column for keys"
16
+ method_option :default_lang, :type => :string, :aliases => "-l", :desc => "Default language to use for empty values if any"
17
+ method_option :default_path, :type => :string, :aliases => "-p", :desc => "Path of output files"
18
+ def csv2strings(filename = nil)
19
+ unless filename || options.has_key?('filename')
20
+ puts "No value provided for required options '--filename'"
21
+ help("csv2strings")
22
+ exit
23
+ end
24
+ unless options.has_key?('langs')
25
+ puts "No value provided for required options '--langs'"
26
+ help("csv2strings")
27
+ exit
28
+ end
29
+ filename ||= options['filename']
30
+ args = options.dup
31
+ args.delete(:langs)
32
+ args.delete(:filename)
33
+ converter = CSV2Strings::Converter.new(filename, options[:langs], args)
34
+ converter.csv_to_dotstrings
35
+ end
36
+
37
+ desc "FILENAMES", "convert '.strings' files to CSV file"
38
+ # required options but handled in method because of options read from yaml file
39
+ method_option :filenames, :type => :array, :aliases => "-i", :desc => "location of strings files (FILENAMES)"
40
+ # optional options
41
+ method_option :csv_filename, :type => :string, :aliases => "-o", :desc => "location of output file"
42
+ method_option :headers, :type => :array, :aliases => "-h", :desc => "override headers of columns, default is name of input files and 'Variables' for reference"
43
+ method_option :dryrun, :type => :boolean, :aliases => "-n", :desc => "prints out content of hash without writing file"
44
+ def strings2csv
45
+ unless options.has_key?('filenames')
46
+ puts "No value provided for required options '--filenames'"
47
+ help("strings2csv")
48
+ exit
49
+ end
50
+ converter = Strings2CSV::Converter.new(options)
51
+ debug_values = converter.dotstrings_to_csv(!options[:dryrun])
52
+ puts debug_values.inspect if options[:dryrun]
53
+ end
54
+
55
+ private
56
+ def options
57
+ original_options = super
58
+ return original_options unless File.exists?(".csvconverter")
59
+ defaults = ::YAML::load_file(".csvconverter") || {}
60
+ # add default values for options here
61
+ defaults["csv_filename"] = "translations.csv" unless defaults.has_key?("csv_filename")
62
+ defaults["dryrun"] = false unless defaults.has_key?("dryrun")
63
+ defaults["keys_column"] = 0 unless defaults.has_key?("keys_column")
64
+ Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
65
+ end
66
+ end
@@ -0,0 +1,130 @@
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"
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
+ CSVParserClass.foreach(name, :quote_char => '"', :col_sep =>',', :row_sep => :auto) do |row|
87
+
88
+ if rowIndex == 0
89
+ return unless row.count > 1 #check there's at least two columns
90
+ else
91
+ next if row == nil or row[self.keys_column].nil? #skip empty lines (or sections)
92
+ end
93
+
94
+ row.size.times do |i|
95
+ next if excludedCols.include? i
96
+ if rowIndex == 0 #header
97
+ # ignore all headers not listed in langs to create files
98
+ (excludedCols << i and next) unless self.langs.has_key?(row[i])
99
+ self.process_header(excludedCols, files, row, i)
100
+ # define defaultCol
101
+ defaultCol = i if self.default_lang == row[i]
102
+ elsif !self.state_column || (row[self.state_column].nil? or row[self.state_column] == '' or !self.excluded_states.include? row[self.state_column])
103
+ # TODO: add option to strip the constant or referenced language
104
+ key = row[self.keys_column].strip
105
+ value = self.process_value(row[i], row[defaultCol])
106
+ # files for a given language, i.e could group english US with english UK.
107
+ localized_files = files[i]
108
+ if localized_files
109
+ localized_files.each do |file|
110
+ nb_translations += 1
111
+ file.write "\"#{key}\" = \"#{value}\";\n"
112
+ end
113
+ end
114
+ end
115
+ end
116
+ rowIndex += 1
117
+ end
118
+ puts "\n>>>Created #{files.size} files. Content: #{nb_translations} translations\n"
119
+
120
+ # closing I/O
121
+ files.each do |key,locale_files|
122
+ locale_files.each do |file|
123
+ file.close
124
+ end
125
+ end
126
+
127
+ end # end of method
128
+
129
+ end # end of class
130
+ end
@@ -0,0 +1,16 @@
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__)))
2
+ require 'rubygems'
3
+
4
+ CSVGEM = RUBY_VERSION.match(/^[0-1]\.[0-8]\./) ? 'faster_csv' : 'csv'
5
+
6
+ begin
7
+ require CSVGEM
8
+ rescue LoadError
9
+ puts "Failed to load #{CSVGEM} (ruby #{RUBY_VERSION})"
10
+ puts "gem install #{CSVGEM}"
11
+ exit
12
+ end
13
+
14
+ CSVParserClass = CSVGEM == 'csv' ? CSV : FasterCSV
15
+ require "csv2strings/converter"
16
+ require "strings2csv/converter"
@@ -0,0 +1,95 @@
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
+
@@ -0,0 +1,90 @@
1
+ require 'test_helper'
2
+
3
+ require 'command'
4
+ class CommandTest < Test::Unit::TestCase
5
+ def test_csv2strings_with_multiple_2_languages
6
+ command = "./bin/csv2strings"
7
+ command += " 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 += " 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/csv2strings 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/csv2strings 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
+
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../../../lib/csv2strings/converter', __FILE__)
2
+ require File.expand_path('../../test_helper', __FILE__)
3
+
4
+ class CSV2Strings::ConverterTest < Test::Unit::TestCase
5
+
6
+ def test_converting_csv_to_dotstrings
7
+ csv_file = "test/data/test_data.csv"
8
+ converter = CSV2Strings::Converter.new(csv_file, 'English' => [:en])
9
+ converter.csv_to_dotstrings
10
+ assert File.exists?("en.lproj/Localizable.strings"), "the ouptut file does not exist"
11
+ end
12
+
13
+ def test_converting_csv_to_dotstrings_one_output_option
14
+ csv_file = "test/data/test_data.csv"
15
+ single_file = 'myApp.strings'
16
+ converter = CSV2Strings::Converter.new(csv_file,
17
+ {'English' => [:en]},
18
+ :output_file => single_file)
19
+ converter.csv_to_dotstrings
20
+ assert File.exists?(single_file), "the ouptut file does not exist"
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ variables,English
2
+ ERROR_HANDLER_WARNING_DISMISS,OK
3
+ ANOTHER_STRING,hello
@@ -0,0 +1,2 @@
1
+ "ERROR_HANDLER_WARNING_DISMISS" = "OK";
2
+ "ANOTHER_STRING" = "hello";
@@ -0,0 +1,3 @@
1
+ variables,English,German,French,Spanish
2
+ GREETINGS,Hello,Hallo,Salut,Buenos dias
3
+ ANOTHER_STRING,testEN,,,
@@ -0,0 +1,2 @@
1
+ "GREETINGS" = "Hello";
2
+ "ANOTHER_STRING" = "testEN";
@@ -0,0 +1,2 @@
1
+ "GREETINGS" = "Bonjour";
2
+ "ANOTHER_STRING" = "testFR";
@@ -0,0 +1,96 @@
1
+ require File.expand_path('../../../lib/strings2csv/converter', __FILE__)
2
+ require File.expand_path('../../test_helper', __FILE__)
3
+
4
+ class Strings2CSV::ConverterTest < Test::Unit::TestCase
5
+
6
+ def test_parse_dotstrings_line_with_good_string
7
+ input = String.new(<<-EOS)
8
+ "MY_CONSTANT" = "This is ok";
9
+ EOS
10
+ expected_output = {"MY_CONSTANT"=>"This is ok"}
11
+
12
+ output = Strings2CSV::Converter.new.parse_dotstrings_line input
13
+ assert_equal output, expected_output
14
+ end
15
+
16
+ def test_parse_dotstrings_line_with_single_quote
17
+ input = String.new(<<-EOS)
18
+ "MY_CONSTANT" = "This 'is' ok";
19
+ EOS
20
+ expected_output = {"MY_CONSTANT"=>"This 'is' ok"}
21
+
22
+ output = Strings2CSV::Converter.new.parse_dotstrings_line input
23
+ assert_equal output, expected_output
24
+ end
25
+
26
+ def test_parse_dotstrings_line_with_double_quotes
27
+ input = String.new(<<-EOS)
28
+ "MY_CONSTANT" = "This "is" ok";
29
+ EOS
30
+ expected_output = {"MY_CONSTANT"=>"This \"is\" ok"}
31
+
32
+ output = Strings2CSV::Converter.new.parse_dotstrings_line input
33
+ assert_equal output, expected_output
34
+ end
35
+
36
+ def test_parse_dotstrings_line_with_wrong_string
37
+ input = String.new(<<-EOS)
38
+ "MY_CONSTANT" = "wrong syntax"
39
+ EOS
40
+
41
+ output = Strings2CSV::Converter.new.parse_dotstrings_line input
42
+ assert_nil output, "output should be nil with wrong syntax"
43
+ end
44
+
45
+ def test_load_strings_with_wrong_file
46
+ assert_raise(Errno::ENOENT) do
47
+ output = Strings2CSV::Converter.new.load_strings "file that does not exist.strings"
48
+ end
49
+ end
50
+
51
+ def test_load_strings
52
+ expected_output = {"ERROR_HANDLER_WARNING_DISMISS" => "OK", "ANOTHER_STRING" => "hello"}
53
+ output = Strings2CSV::Converter.new.load_strings "test/data/test_data.strings"
54
+ assert_equal expected_output, output
55
+ end
56
+
57
+ def test_dotstrings_to_csv
58
+ converter = Strings2CSV::Converter.new(:filenames => ["test/data/test_data.strings"])
59
+ keys, lang_order, strings = converter.dotstrings_to_csv(false)
60
+ assert_equal ["test_data".to_sym], lang_order
61
+ assert_equal ["ERROR_HANDLER_WARNING_DISMISS", "ANOTHER_STRING"], keys
62
+ expected_strings = {lang_order[0] => {"ERROR_HANDLER_WARNING_DISMISS" => "OK", "ANOTHER_STRING" => "hello"}}
63
+ assert_equal expected_strings, strings
64
+ end
65
+
66
+ def test_create_csv_file
67
+ keys = ["ERROR_HANDLER_WARNING_DISMISS", "ANOTHER_STRING"]
68
+ lang_order = [:"test_data"]
69
+ strings = {lang_order[0] => {"ERROR_HANDLER_WARNING_DISMISS" => "OK", "ANOTHER_STRING" => "hello"}}
70
+
71
+ converter = Strings2CSV::Converter.new(:headers => %w{variables english})
72
+
73
+ converter.create_csv_file(keys, lang_order, strings)
74
+ assert File.exist?(converter.csv_filename)
75
+ end
76
+
77
+ def test_initialize
78
+ csv_filename = "file.csv"
79
+ filenames = %w{"french.strings english.strings"}
80
+ headers = %w{"constants french english"}
81
+ converter = Strings2CSV::Converter.new({
82
+ :csv_filename => csv_filename,
83
+ :headers => headers,
84
+ :filenames => filenames
85
+ })
86
+
87
+ assert_equal csv_filename, converter.csv_filename
88
+ assert_equal headers, converter.headers
89
+ assert_equal filenames, converter.filenames
90
+ end
91
+
92
+ def test_initialize_with_default_values
93
+ converter = Strings2CSV::Converter.new
94
+ assert_not_nil converter.csv_filename
95
+ end
96
+ end
@@ -0,0 +1,12 @@
1
+ begin
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "test"
5
+ end
6
+ rescue LoadError
7
+ puts 'Coverage disabled, enable by installing simplecov'
8
+ end
9
+
10
+ require 'test/unit'
11
+ require "mocha"
12
+
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: csv2strings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - François Benaiteau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: ruby script converts a CSV file of translations to Localizable.strings
84
+ files and vice-versa
85
+ email: francois.benaiteau@gmail.com
86
+ executables:
87
+ - csv2strings
88
+ - strings2csv
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - .csvconverter.sample
93
+ - .gitignore
94
+ - .travis.yml
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - bin/csv2strings
101
+ - bin/strings2csv
102
+ - csv2strings.gemspec
103
+ - lib/command.rb
104
+ - lib/csv2strings/converter.rb
105
+ - lib/csvconverter.rb
106
+ - lib/strings2csv/converter.rb
107
+ - test/command_test.rb
108
+ - test/csv2strings/converter_test.rb
109
+ - test/data/test_data.csv
110
+ - test/data/test_data.strings
111
+ - test/data/test_data_multiple_langs.csv
112
+ - test/data/test_en.strings
113
+ - test/data/test_fr.strings
114
+ - test/strings2csv/converter_test.rb
115
+ - test/test_helper.rb
116
+ homepage: https://github.com/netbe/CSV-to-iOS-Localizable.strings-converter
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.0.0
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: CSV to iOS Localizable.strings converter
140
+ test_files:
141
+ - test/command_test.rb
142
+ - test/csv2strings/converter_test.rb
143
+ - test/data/test_data.csv
144
+ - test/data/test_data.strings
145
+ - test/data/test_data_multiple_langs.csv
146
+ - test/data/test_en.strings
147
+ - test/data/test_fr.strings
148
+ - test/strings2csv/converter_test.rb
149
+ - test/test_helper.rb