translatomatic 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitattributes +1 -0
- data/.gitignore +15 -12
- data/.rspec +3 -3
- data/.travis.yml +32 -50
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +29 -5
- data/Guardfile +48 -0
- data/LICENSE.txt +21 -21
- data/README.de.md +92 -0
- data/README.es.md +92 -0
- data/README.fr.md +92 -0
- data/README.it.md +92 -0
- data/README.ja.md +92 -0
- data/README.md +96 -74
- data/Rakefile +6 -6
- data/bin/setup +8 -8
- data/bin/translatomatic +6 -6
- data/bin/travis +26 -0
- data/db/database.yml +9 -9
- data/db/migrate/201712170000_initial.rb +24 -23
- data/lib/translatomatic/cli.rb +204 -80
- data/lib/translatomatic/config.rb +12 -26
- data/lib/translatomatic/converter.rb +206 -142
- data/lib/translatomatic/converter_stats.rb +27 -27
- data/lib/translatomatic/database.rb +139 -99
- data/lib/translatomatic/escaped_unicode.rb +90 -90
- data/lib/translatomatic/extractor/base.rb +14 -0
- data/lib/translatomatic/extractor/ruby.rb +5 -0
- data/lib/translatomatic/extractor.rb +4 -0
- data/lib/translatomatic/http_request.rb +133 -0
- data/lib/translatomatic/locale.rb +52 -0
- data/lib/translatomatic/logger.rb +28 -0
- data/lib/translatomatic/model/locale.rb +21 -22
- data/lib/translatomatic/model/text.rb +17 -13
- data/lib/translatomatic/model.rb +4 -4
- data/lib/translatomatic/option.rb +24 -24
- data/lib/translatomatic/progress_updater.rb +15 -0
- data/lib/translatomatic/resource_file/base.rb +169 -137
- data/lib/translatomatic/resource_file/html.rb +46 -28
- data/lib/translatomatic/resource_file/markdown.rb +54 -0
- data/lib/translatomatic/resource_file/plist.rb +30 -29
- data/lib/translatomatic/resource_file/properties.rb +72 -60
- data/lib/translatomatic/resource_file/resw.rb +30 -0
- data/lib/translatomatic/resource_file/text.rb +29 -28
- data/lib/translatomatic/resource_file/xcode_strings.rb +71 -65
- data/lib/translatomatic/resource_file/xml.rb +79 -59
- data/lib/translatomatic/resource_file/yaml.rb +82 -80
- data/lib/translatomatic/resource_file.rb +76 -74
- data/lib/translatomatic/string.rb +160 -0
- data/lib/translatomatic/tmx/document.rb +100 -0
- data/lib/translatomatic/tmx/translation_unit.rb +19 -0
- data/lib/translatomatic/tmx.rb +4 -0
- data/lib/translatomatic/translation_result.rb +75 -57
- data/lib/translatomatic/translator/base.rb +83 -47
- data/lib/translatomatic/translator/frengly.rb +57 -64
- data/lib/translatomatic/translator/google.rb +31 -30
- data/lib/translatomatic/translator/microsoft.rb +33 -32
- data/lib/translatomatic/translator/my_memory.rb +64 -55
- data/lib/translatomatic/translator/yandex.rb +39 -37
- data/lib/translatomatic/translator.rb +63 -63
- data/lib/translatomatic/util.rb +15 -24
- data/lib/translatomatic/version.rb +4 -3
- data/lib/translatomatic.rb +32 -27
- data/translatomatic.gemspec +43 -45
- metadata +52 -18
- data/Gemfile.lock +0 -137
@@ -1,137 +1,169 @@
|
|
1
|
-
# @abstract Subclasses implement different types of resource files
|
2
|
-
class Translatomatic::ResourceFile::Base
|
3
|
-
|
4
|
-
attr_accessor :locale
|
5
|
-
attr_accessor :path
|
6
|
-
|
7
|
-
# @return [Hash<String,String>] key -> value properties
|
8
|
-
attr_reader :properties
|
9
|
-
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# @
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
#
|
57
|
-
# @
|
58
|
-
def
|
59
|
-
@properties
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
#
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
1
|
+
# @abstract Subclasses implement different types of resource files
|
2
|
+
class Translatomatic::ResourceFile::Base
|
3
|
+
|
4
|
+
attr_accessor :locale
|
5
|
+
attr_accessor :path
|
6
|
+
|
7
|
+
# @return [Hash<String,String>] key -> value properties
|
8
|
+
attr_reader :properties
|
9
|
+
|
10
|
+
# @return [Array<String>] File extensions supported by this resource file
|
11
|
+
def self.extensions
|
12
|
+
raise "extensions must be implemented by subclass"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Create a new resource file.
|
16
|
+
# If locale is unspecified, attempts to determine the locale of the file
|
17
|
+
# automatically, and if that fails, uses the default locale.
|
18
|
+
# @param [String] path Path to the file
|
19
|
+
# @param [String] locale Locale of the file contents
|
20
|
+
# @return [Translatomatic::ResourceFile::Base] the resource file.
|
21
|
+
def initialize(path, locale = nil)
|
22
|
+
@path = path.kind_of?(Pathname) ? path : Pathname.new(path)
|
23
|
+
@locale = locale || detect_locale || Translatomatic::Locale.default
|
24
|
+
raise "unable to determine locale" unless @locale && @locale.language
|
25
|
+
@valid = false
|
26
|
+
@properties = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [String] The format of this resource file, e.g. "Properties"
|
30
|
+
def format
|
31
|
+
self.class.name.demodulize.downcase.to_sym
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a path for the current resource file with a given locale
|
35
|
+
# @param [String] locale for the path
|
36
|
+
# @return [Pathname] The path of this resource file modified for the given locale
|
37
|
+
def locale_path(locale)
|
38
|
+
basename = path.sub_ext('').basename.to_s
|
39
|
+
|
40
|
+
extlist = extension_list
|
41
|
+
if extlist.length >= 2 && loc_idx = find_locale(extlist)
|
42
|
+
# extension(s) contains locale, replace it
|
43
|
+
extlist[loc_idx] = locale.to_s
|
44
|
+
elsif valid_locale?(basename)
|
45
|
+
# basename is a locale name, replace it
|
46
|
+
path.dirname + (locale.to_s + path.extname)
|
47
|
+
else
|
48
|
+
# remove any underscore and trailing text from basename
|
49
|
+
deunderscored = basename.sub(/_.*?$/, '')
|
50
|
+
# add _locale.ext
|
51
|
+
filename = deunderscored + "_" + locale.to_s + path.extname
|
52
|
+
path.dirname + filename
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set all properties
|
57
|
+
# @param [Hash<String,String>] properties New properties
|
58
|
+
def properties=(properties)
|
59
|
+
# use set rather that set @properties directly as subclasses override set()
|
60
|
+
properties.each do |key, value|
|
61
|
+
set(key, value)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get the value of a property
|
66
|
+
# @param [String] name The name of the property
|
67
|
+
# @return [String] The value of the property
|
68
|
+
def get(name)
|
69
|
+
@properties[name]
|
70
|
+
end
|
71
|
+
|
72
|
+
# Set a property
|
73
|
+
# @param [String] key The name of the property
|
74
|
+
# @param [String] value The new value of the property
|
75
|
+
# @return [String] The new value of the property
|
76
|
+
def set(name, value)
|
77
|
+
@properties[name] = value
|
78
|
+
end
|
79
|
+
|
80
|
+
# Test if the current resource file is valid
|
81
|
+
# @return true if the current file is valid
|
82
|
+
def valid?
|
83
|
+
@valid
|
84
|
+
end
|
85
|
+
|
86
|
+
# Save the resource file.
|
87
|
+
# @param [Pathname] target The destination path
|
88
|
+
# @param [Hash<Symbol, Object>] options Output format options
|
89
|
+
# @return [void]
|
90
|
+
def save(target = path, options = {})
|
91
|
+
raise "save(path) must be implemented by subclass"
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [String] String representation of this file
|
95
|
+
def to_s
|
96
|
+
"#{path.basename.to_s} (#{locale})"
|
97
|
+
end
|
98
|
+
|
99
|
+
def sentences
|
100
|
+
sentences = []
|
101
|
+
properties.values.each do |value|
|
102
|
+
string = Translatomatic::String.new(value, locale)
|
103
|
+
sentences += string.sentences
|
104
|
+
end
|
105
|
+
sentences
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
include Translatomatic::Util
|
111
|
+
|
112
|
+
def created_by
|
113
|
+
date = DateTime.now.strftime("%Y-%m-%d %H:%M")
|
114
|
+
"Created by Translatomatic #{Translatomatic::VERSION} #{date}"
|
115
|
+
end
|
116
|
+
|
117
|
+
# detect locale from filename
|
118
|
+
def detect_locale
|
119
|
+
tag = nil
|
120
|
+
basename = path.sub_ext('').basename.to_s
|
121
|
+
directory = path.dirname.basename.to_s
|
122
|
+
extlist = extension_list
|
123
|
+
|
124
|
+
if basename.match(/_([-\w]{2,})$/i)
|
125
|
+
# locale after underscore in filename
|
126
|
+
tag = $1
|
127
|
+
elsif directory.match(/^([-\w]+)\.lproj$/)
|
128
|
+
# xcode localized strings
|
129
|
+
tag = $1
|
130
|
+
elsif extlist.length >= 2 && loc_idx = find_locale(extlist)
|
131
|
+
# multiple parts to extension, e.g. index.html.en
|
132
|
+
tag = extlist[loc_idx]
|
133
|
+
elsif valid_locale?(basename)
|
134
|
+
# try to match on entire basename
|
135
|
+
# (support for rails en.yml)
|
136
|
+
tag = basename
|
137
|
+
elsif valid_locale?(path.parent.basename)
|
138
|
+
# try to match on parent directory, e.g. strings/en-US/text.resw
|
139
|
+
tag = path.parent.basename
|
140
|
+
end
|
141
|
+
|
142
|
+
tag ? Translatomatic::Locale.parse(tag, true) : nil
|
143
|
+
end
|
144
|
+
|
145
|
+
def valid_locale?(tag)
|
146
|
+
Translatomatic::Locale.new(tag).valid?
|
147
|
+
end
|
148
|
+
|
149
|
+
# test if the list of strings contains a valid locale
|
150
|
+
# return the index to the locale, or nil if no locales found
|
151
|
+
def find_locale(list)
|
152
|
+
list.find_index { |i| valid_locale?(i) }
|
153
|
+
end
|
154
|
+
|
155
|
+
# ext_sub() only removes the last extension
|
156
|
+
def strip_extensions
|
157
|
+
filename = path.basename.to_s
|
158
|
+
filename.sub!(/\..*$/, '')
|
159
|
+
path.parent + filename
|
160
|
+
end
|
161
|
+
|
162
|
+
# for index.html.de, returns ['html', 'de']
|
163
|
+
def extension_list
|
164
|
+
filename = path.basename.to_s
|
165
|
+
idx = filename.index('.')
|
166
|
+
idx && idx < filename.length - 1 ? filename[idx + 1..-1].split('.') : []
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
@@ -1,33 +1,51 @@
|
|
1
|
-
module Translatomatic::ResourceFile
|
2
|
-
class HTML < XML
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
1
|
+
module Translatomatic::ResourceFile
|
2
|
+
class HTML < XML
|
3
|
+
|
4
|
+
# (see Translatomatic::ResourceFile::Base.extensions)
|
5
|
+
def self.extensions
|
6
|
+
%w{html htm shtml}
|
7
|
+
end
|
8
|
+
|
9
|
+
# (see Translatomatic::ResourceFile::Base#locale_path)
|
10
|
+
def locale_path(locale)
|
11
|
+
extlist = extension_list
|
12
|
+
if extlist.length >= 2 && loc_idx = find_locale(extlist)
|
13
|
+
# part of the extension is the locale
|
14
|
+
# replace that part with the new locale
|
15
|
+
extlist[loc_idx] = locale.to_s
|
16
|
+
new_extension = extlist.join(".")
|
17
|
+
return strip_extensions.sub_ext("." + new_extension)
|
18
|
+
else
|
19
|
+
# add locale extension
|
19
20
|
ext = path.extname
|
20
|
-
|
21
|
-
|
21
|
+
# TODO: need configurable order for locale & ext here?
|
22
|
+
#path.sub_ext("#{ext}." + locale.to_s)
|
23
|
+
path.sub_ext("." + locale.to_s + ext)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# (see Translatomatic::ResourceFile::Base#save)
|
28
|
+
def save(target = path, options = {})
|
29
|
+
if @doc
|
30
|
+
add_created_by unless options[:no_created_by]
|
31
|
+
target.write(@doc.to_html)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
22
36
|
|
23
|
-
|
24
|
-
|
37
|
+
def text_nodes_xpath
|
38
|
+
'//*[not(self::code)]/text()'
|
25
39
|
end
|
26
40
|
|
27
|
-
|
28
|
-
|
29
|
-
target.write(@doc.to_html) if @doc
|
41
|
+
def add_created_by
|
42
|
+
@created_by ||= @doc.root.add_previous_sibling(comment(created_by))
|
30
43
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
44
|
+
|
45
|
+
def read_doc(path)
|
46
|
+
Nokogiri::HTML(path.open) do |config|
|
47
|
+
config.noblanks
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'kramdown'
|
2
|
+
require 'reverse_markdown'
|
3
|
+
|
4
|
+
module Translatomatic::ResourceFile
|
5
|
+
class Markdown < HTML
|
6
|
+
|
7
|
+
# (see Translatomatic::ResourceFile::Base.extensions)
|
8
|
+
def self.extensions
|
9
|
+
%w{md}
|
10
|
+
end
|
11
|
+
|
12
|
+
# (see Translatomatic::ResourceFile::Base#save)
|
13
|
+
def save(target = path, options = {})
|
14
|
+
if @doc
|
15
|
+
begin
|
16
|
+
add_created_by unless options[:no_created_by]
|
17
|
+
html = @doc.to_html
|
18
|
+
# convert html back to markdown
|
19
|
+
markdown = ReverseMarkdown.convert(html, unknown_tags: :bypass)
|
20
|
+
target.write(markdown.chomp)
|
21
|
+
rescue Exception => e
|
22
|
+
puts "error: #{e.message}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def add_created_by
|
30
|
+
@created_by ||= begin
|
31
|
+
body = @doc.at('body')
|
32
|
+
body.add_child("<p><i>#{created_by}</i></p>")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def read(path)
|
37
|
+
begin
|
38
|
+
# read markdown and convert to html
|
39
|
+
markdown = path.read
|
40
|
+
html = Kramdown::Document.new(markdown).to_html
|
41
|
+
# parse html with nokogiri
|
42
|
+
@doc = Nokogiri::HTML(html) do |config|
|
43
|
+
config.noblanks
|
44
|
+
end
|
45
|
+
init_nodemap(@doc)
|
46
|
+
rescue Exception => e
|
47
|
+
log.error(e.message)
|
48
|
+
@valid = false
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end # class
|
54
|
+
end # module
|
@@ -1,29 +1,30 @@
|
|
1
|
-
module Translatomatic::ResourceFile
|
2
|
-
class Plist < XML
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
1
|
+
module Translatomatic::ResourceFile
|
2
|
+
class Plist < XML
|
3
|
+
|
4
|
+
# (see Translatomatic::ResourceFile::Base.extensions)
|
5
|
+
def self.extensions
|
6
|
+
%w{plist}
|
7
|
+
end
|
8
|
+
|
9
|
+
# (see Translatomatic::ResourceFile::Base#locale_path)
|
10
|
+
# @note localization files in XCode use the following file name
|
11
|
+
# convention: Project/locale.lproj/filename
|
12
|
+
# @todo refactor this and xcode_strings.rb to use the same code
|
13
|
+
def locale_path(locale)
|
14
|
+
if path.to_s.match(/\/([-\w]+).lproj\/.+.plist$/)
|
15
|
+
# xcode style
|
16
|
+
filename = path.basename
|
17
|
+
path.parent.parent + (locale.to_s + ".lproj") + filename
|
18
|
+
else
|
19
|
+
super(locale)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def text_nodes_xpath
|
26
|
+
'//*[not(self::key)]/text()'
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class
|
30
|
+
end # module
|
@@ -1,60 +1,72 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Translatomatic::ResourceFile
|
4
|
+
class Properties < Base
|
5
|
+
|
6
|
+
# (see Translatomatic::ResourceFile::Base.extensions)
|
7
|
+
def self.extensions
|
8
|
+
%w{properties}
|
9
|
+
end
|
10
|
+
|
11
|
+
# (see Translatomatic::ResourceFile::Base#initialize)
|
12
|
+
def initialize(path, locale = nil)
|
13
|
+
super(path, locale)
|
14
|
+
@valid = true
|
15
|
+
@properties = @path.exist? ? read(@path) : {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# (see Translatomatic::ResourceFile::Base#save)
|
19
|
+
def save(target = path, options = {})
|
20
|
+
out = ""
|
21
|
+
out += add_created_by unless options[:no_created_by]
|
22
|
+
properties.each do |key, value|
|
23
|
+
# TODO: maintain original line ending format?
|
24
|
+
value = value.gsub("\n", "\\n") # convert newlines to \n
|
25
|
+
out += "#{key} = #{value}\n"
|
26
|
+
end
|
27
|
+
# escape unicode characters
|
28
|
+
out = Translatomatic::EscapedUnicode.escape(out)
|
29
|
+
target.write(out)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def add_created_by
|
35
|
+
comment(created_by)
|
36
|
+
end
|
37
|
+
|
38
|
+
def comment(text)
|
39
|
+
"# #{text}\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
# parse key = value property file
|
43
|
+
def read(path)
|
44
|
+
contents = path.read
|
45
|
+
# convert escaped unicode characters into unicode
|
46
|
+
contents = Translatomatic::EscapedUnicode.unescape(contents)
|
47
|
+
result = {}
|
48
|
+
contents.gsub!(/\\\s*\n\s*/m, '') # put multi line strings on one line
|
49
|
+
lines = contents.split("\n")
|
50
|
+
|
51
|
+
lines.each do |line|
|
52
|
+
line.strip!
|
53
|
+
next if line.length == 0
|
54
|
+
equal_idx = line.index("=")
|
55
|
+
|
56
|
+
if line[0] == ?! || line[0] == ?#
|
57
|
+
# comment
|
58
|
+
# TODO: translate comments or keep originals?
|
59
|
+
next
|
60
|
+
elsif equal_idx.nil?
|
61
|
+
@valid = false
|
62
|
+
return {}
|
63
|
+
end
|
64
|
+
name, value = line.split(/\s*=\s*/, 2)
|
65
|
+
value = value.gsub("\\n", "\n") # convert \n to newlines
|
66
|
+
result[name] = value
|
67
|
+
end
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|