logaling-command 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2011 Miho SUZUKI
3
+ # Copyright (C) 2012 Miho SUZUKI
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -14,159 +14,95 @@
14
14
  #
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- begin
19
- require 'psych'
20
- rescue LoadError => e
21
- raise LoadError unless e.message =~ /psych/
22
- puts "please install psych first."
23
- end
24
- require "yaml"
25
- require "csv"
26
- require "fileutils"
27
-
28
17
  module Logaling
29
18
  class Glossary
30
- class << self
31
- def load(file)
32
- load_glossary(file)
33
- end
34
-
35
- def load_glossary(file)
36
- case File.extname(file)
37
- when ".csv"
38
- load_glossary_csv(file)
39
- when ".tsv"
40
- load_glossary_tsv(file)
41
- when ".yml"
42
- load_glossary_yml(file)
43
- end
44
- end
19
+ SUPPORTED_FILE_TYPE = %w(yml tsv csv)
45
20
 
46
- def load_glossary_yml(path)
47
- YAML::load_file(path) || []
48
- end
21
+ attr_reader :name, :source_language, :target_language
49
22
 
50
- def load_glossary_tsv(path)
51
- load_glossary_csv(path, "\t")
52
- end
23
+ def initialize(name, source_language, target_language, project=nil)
24
+ @name = name
25
+ @source_language = source_language
26
+ @target_language = target_language
27
+ @project = project
28
+ end
53
29
 
54
- def load_glossary_csv(path, sep=",")
55
- glossary = []
56
- CSV.open(path, "r:utf-8", {:col_sep => sep}) do |csv|
57
- csv.each do |row|
58
- glossary << {"source_term" => row[0], "target_term" => row[1], "note" => ""} if row.size >= 2
59
- end
60
- end
61
- glossary
30
+ def terms
31
+ raise Logaling::GlossaryDBNotFound unless File.exist?(@project.glossary_db_path)
32
+ index
33
+ terms = []
34
+ Logaling::GlossaryDB.open(@project.glossary_db_path, "utf8") do |db|
35
+ terms = db.translation_list(self)
62
36
  end
37
+ terms
63
38
  end
64
- attr_reader :glossary, :source_language, :target_language
65
39
 
66
- def initialize(glossary, source_language, target_language, logaling_home)
67
- @logaling_home = logaling_home
68
- @glossary = glossary
69
- @source_language = source_language
70
- @target_language = target_language
40
+ def bilingual_pair_exists?(source_term, target_term, note=nil)
41
+ raise Logaling::GlossaryDBNotFound unless File.exist?(@project.glossary_db_path)
42
+ index
43
+ terms = []
44
+ Logaling::GlossaryDB.open(@project.glossary_db_path, "utf8") do |db|
45
+ terms = db.get_bilingual_pair(source_term, target_term, @name, note)
46
+ end
47
+ !terms.empty?
71
48
  end
72
49
 
73
50
  def add(source_term, target_term, note)
74
- FileUtils.touch(source_path) unless File.exist?(source_path)
75
-
76
- glossary = Glossary.load_glossary(source_path)
77
- glossary << build_term(source_term, target_term, note)
78
- dump_glossary(glossary)
79
- rescue
80
- raise GlossaryNotFound
51
+ glossary_source.add(source_term, target_term, note)
81
52
  end
82
53
 
83
54
  def update(source_term, target_term, new_target_term, note)
84
- raise GlossaryNotFound unless File.exist?(source_path)
85
-
86
- glossary = Glossary.load_glossary(source_path)
87
-
88
- target_index = find_term_index(glossary, source_term, target_term)
89
- if target_index
90
- glossary[target_index] = rebuild_term(glossary[target_index], source_term, new_target_term, note)
91
- dump_glossary(glossary)
92
- else
93
- raise TermError, "Can't found term '#{source_term}: #{target_term}' in '#{@glossary}'"
94
- end
55
+ glossary_source.update(source_term, target_term, new_target_term, note)
95
56
  end
96
57
 
97
58
  def delete(source_term, target_term)
98
- raise GlossaryNotFound unless File.exist?(source_path)
99
-
100
- glossary = Glossary.load_glossary(source_path)
101
- target_index = find_term_index(glossary, source_term, target_term)
102
- unless target_index
103
- raise TermError, "Can't found term '#{source_term} #{target_term}' in '#{@glossary}'" unless target_index
104
- end
105
-
106
- glossary.delete_at(target_index)
107
- dump_glossary(glossary)
59
+ glossary_source.delete(source_term, target_term)
108
60
  end
109
61
 
110
62
  def delete_all(source_term, force=false)
111
- raise GlossaryNotFound unless File.exist?(source_path)
112
-
113
- glossary = Glossary.load_glossary(source_path)
114
- delete_candidates = target_terms(glossary, source_term)
115
- if delete_candidates.empty?
116
- raise TermError, "Can't found term '#{source_term} in '#{@glossary}'"
117
- end
118
-
119
- if delete_candidates.size == 1 || force
120
- glossary.delete_if{|term| term['source_term'] == source_term }
121
- dump_glossary(glossary)
122
- else
123
- raise TermError, "There are duplicate terms in glossary.\n" +
124
- "If you really want to delete, please put `loga delete [SOURCE_TERM] --force`\n" +
125
- " or `loga delete [SOURCE_TERM] [TARGET_TERM]`"
126
- end
63
+ glossary_source.delete_all(source_term, force)
127
64
  end
128
65
 
129
- def source_path
130
- if @source_path
131
- @source_path
66
+ def glossary_source
67
+ if @glossary_source
68
+ @glossary_source
132
69
  else
133
- fname = [@glossary, @source_language, @target_language].join(".")
134
- @source_path = File.join(@logaling_home, "projects", @glossary, "glossary", "#{fname}.yml")
70
+ file_name = [@name, @source_language, @target_language, 'yml'].join('.')
71
+ source_dir = @project.glossary_source_path
72
+ FileUtils.mkdir_p(source_dir)
73
+ source_path = File.join(source_dir, file_name)
74
+ @glossary_source = Logaling::GlossarySource.create(source_path, self)
135
75
  end
136
76
  end
137
77
 
138
- private
139
- def build_term(source_term, target_term, note)
140
- note ||= ''
141
- {'source_term' => source_term, 'target_term' => target_term, 'note' => note}
78
+ def to_s
79
+ [@name, @source_language, @target_language].join('.')
142
80
  end
143
81
 
144
- def rebuild_term(current, source_term, target_term, note)
145
- if current['target_term'] != target_term && (note.nil? || note == "")
146
- note = current['note']
147
- end
148
- target_term = current['target_term'] if target_term == ""
149
- build_term(source_term, target_term, note)
150
- end
151
-
152
- def find_term_index(glossary, source_term, target_term='')
153
- glossary.find_index do |term|
154
- if target_term.empty?
155
- term['source_term'] == source_term
156
- else
157
- term['source_term'] == source_term && term['target_term'] == target_term
82
+ private
83
+ def index
84
+ Logaling::GlossaryDB.open(@project.glossary_db_path, "utf8") do |db|
85
+ db.recreate_table
86
+ glossary_sources.each do |glossary_source|
87
+ unless db.glossary_source_exist?(glossary_source)
88
+ puts "now index #{@name}..."
89
+ db.index_glossary_source(glossary_source)
90
+ end
91
+ end
92
+ indexed_glossary_sources = db.glossary_sources_related_on_glossary(self)
93
+ (indexed_glossary_sources - glossary_sources).each do |removed_glossary_source|
94
+ puts "now deindex #{@name}..."
95
+ db.deindex_glossary_source(removed_glossary_source)
158
96
  end
159
97
  end
160
98
  end
161
99
 
162
- def target_terms(glossary, source_term)
163
- glossary.select {|term| term['source_term'] == source_term }
164
- end
165
-
166
- def dump_glossary(glossary)
167
- File.open(source_path, "w") do |f|
168
- f.puts(glossary.to_yaml)
100
+ def glossary_sources
101
+ glob_condition = SUPPORTED_FILE_TYPE.map do |type|
102
+ file_name = [self.to_s, type].join('.')
103
+ File.join(@project.glossary_source_path, file_name)
169
104
  end
105
+ Dir.glob(glob_condition).map {|source_path| GlossarySource.create(source_path, self)}
170
106
  end
171
107
  end
172
108
  end
@@ -49,11 +49,10 @@ module Logaling
49
49
  end
50
50
 
51
51
  def recreate_table
52
- version = Groonga["configurations"] ? get_config("version") : 0
53
- if version.to_i != VERSION
52
+ unless latest_version?
54
53
  remove_schema
55
54
  populate_schema
56
- add_config("version", VERSION.to_s)
55
+ update_version_to_latest
57
56
  end
58
57
  end
59
58
 
@@ -62,41 +61,63 @@ module Logaling
62
61
  @database = nil
63
62
  end
64
63
 
65
- def deindex_glossary(glossary_name, glossary_source)
66
- delete_translations_by_glossary_source(glossary_source)
67
- delete_glossary(glossary_name)
68
- delete_glossary_source(glossary_source)
64
+ def deindex_glossary(glossary, glossary_source)
65
+ delete_translations_by_glossary_source(glossary_source.source_path)
66
+ delete_glossary(glossary.name)
67
+ delete_glossary_source(glossary_source.source_path)
69
68
  end
70
69
 
71
- def index_glossary(glossary, glossary_name, glossary_source, source_language, target_language, indexed_at)
70
+ def deindex_glossary_source(glossary_source)
71
+ delete_translations_by_glossary_source(glossary_source.source_path)
72
+ delete_glossary_source(glossary_source.source_path)
73
+ end
74
+
75
+ def index_glossary_source(glossary_source)
76
+ delete_terms if offline_index?
77
+ glossary = glossary_source.glossary
78
+
79
+ deindex_glossary_source(glossary_source)
80
+
81
+ add_glossary_source(glossary_source)
82
+ glossary_source.load.each do |term|
83
+ source_term = term['source_term']
84
+ target_term = term['target_term']
85
+ note = term['note']
86
+ add_translation(glossary.name, glossary_source.source_path, glossary.source_language, glossary.target_language, source_term, target_term, note)
87
+ end
88
+
89
+ create_terms if offline_index?
90
+ end
91
+
92
+ def index_glossary(glossary, glossary_source)
72
93
  delete_terms if offline_index?
73
94
 
74
- deindex_glossary(glossary_name, glossary_source)
95
+ deindex_glossary(glossary, glossary_source)
75
96
 
76
- add_glossary_source(glossary_source, indexed_at)
77
- add_glossary(glossary_name)
78
- glossary.each do |term|
97
+ add_glossary_source(glossary_source)
98
+ add_glossary(glossary)
99
+ glossary_source.load.each do |term|
79
100
  source_term = term['source_term']
80
101
  target_term = term['target_term']
81
102
  note = term['note']
82
- add_translation(glossary_name, glossary_source, source_language, target_language, source_term, target_term, note)
103
+ add_translation(glossary.name, glossary_source.source_path, glossary.source_language, glossary.target_language, source_term, target_term, note)
83
104
  end
84
105
 
85
106
  create_terms if offline_index?
86
107
  end
87
108
 
88
- def lookup(source_term, glossary_source=nil)
109
+ def lookup(source_term, glossary=nil)
89
110
  records_selected = Groonga["translations"].select do |record|
90
111
  conditions = [record.source_term =~ source_term]
91
- if glossary_source
92
- conditions << (record.source_language =~ glossary_source.source_language) if glossary_source.source_language
93
- conditions << (record.target_language =~ glossary_source.target_language) if glossary_source.target_language
112
+ if glossary
113
+ conditions << (record.source_language =~ glossary.source_language) if glossary.source_language
114
+ conditions << (record.target_language =~ glossary.target_language) if glossary.target_language
94
115
  end
95
116
  conditions
96
117
  end
97
- if glossary_source
118
+ if glossary
98
119
  specified_glossary = records_selected.select do |record|
99
- record.glossary == glossary_source.glossary
120
+ record.glossary == glossary.name
100
121
  end
101
122
  specified_glossary.each do |record|
102
123
  record.key._score += 10
@@ -113,13 +134,8 @@ module Logaling
113
134
  :normalize => true}
114
135
  snippet = records_selected.expression.snippet(["<snippet>", "</snippet>"], options)
115
136
  struct_result(records, snippet)
116
- ensure
117
- snippet.close if snippet
118
- records_selected.expression.close if records_selected
119
- specified_glossary.expression.close if specified_glossary
120
137
  end
121
138
 
122
-
123
139
  def lookup_dictionary(search_word)
124
140
  records_selected_source = Groonga["translations"].select do |record|
125
141
  target = record.match_target do |match_record|
@@ -150,74 +166,71 @@ module Logaling
150
166
  snippet = records_selected.expression.snippet(["<snippet>", "</snippet>"], options)
151
167
 
152
168
  struct_result(records, snippet)
153
- ensure
154
- snippet.close if snippet
155
- records_selected.expression.close if records_selected
156
169
  end
157
170
 
158
- def translation_list(glossary_source)
171
+ def translation_list(glossary, order='ascending')
159
172
  records_raw = Groonga["translations"].select do |record|
160
173
  [
161
- record.glossary == glossary_source.glossary,
162
- record.source_language == glossary_source.source_language,
163
- record.target_language == glossary_source.target_language
174
+ record.glossary == glossary.name,
175
+ record.source_language == glossary.source_language,
176
+ record.target_language == glossary.target_language
164
177
  ]
165
178
  end
166
179
 
167
180
  records = records_raw.sort([
168
- {:key=>"source_term", :order=>'ascending'},
169
- {:key=>"target_term", :order=>'ascending'}])
181
+ {:key => "source_term", :order => order},
182
+ {:key => "target_term", :order => order}
183
+ ])
170
184
 
171
185
  struct_result(records)
172
- ensure
173
- records_raw.expression.close
174
186
  end
175
187
 
176
- def get_bilingual_pair(source_term, target_term, glossary)
188
+ def get_bilingual_pair(source_term, target_term, glossary, note=nil)
177
189
  records = Groonga["translations"].select do |record|
178
- [
179
- record.glossary == glossary,
180
- record.source_term == source_term,
181
- record.target_term == target_term
182
- ]
183
- end
184
-
185
- struct_result(records)
186
- ensure
187
- records.expression.close
188
- end
189
-
190
- def get_bilingual_pair_with_note(source_term, target_term, note, glossary)
191
- records = Groonga["translations"].select do |record|
192
- [
193
- record.glossary == glossary,
194
- record.source_term == source_term,
195
- record.target_term == target_term,
196
- record.note == note
197
- ]
190
+ if note
191
+ [
192
+ record.glossary == glossary,
193
+ record.source_term == source_term,
194
+ record.target_term == target_term,
195
+ record.note == note
196
+ ]
197
+ else
198
+ [
199
+ record.glossary == glossary,
200
+ record.source_term == source_term,
201
+ record.target_term == target_term
202
+ ]
203
+ end
198
204
  end
199
-
200
205
  struct_result(records)
201
- ensure
202
- records.expression.close
203
206
  end
204
207
 
205
- def glossary_source_exist?(glossary_source, indexed_at)
208
+ def glossary_source_exist?(glossary_source)
206
209
  glossary = Groonga["glossary_sources"].select do |record|
207
210
  [
208
- record.key == glossary_source,
209
- record.indexed_at == indexed_at
211
+ record.key == glossary_source.source_path,
212
+ record.indexed_at == glossary_source.mtime
210
213
  ]
211
214
  end
212
215
  !glossary.size.zero?
213
- ensure
214
- glossary.expression.close
215
216
  end
216
217
 
217
- def get_all_glossary_source
218
- Groonga["glossary_sources"].sort([
218
+ def get_all_glossary_sources
219
+ source_paths = Groonga["glossary_sources"].sort([
219
220
  {:key=>"_key", :order=>'ascending'}
220
221
  ]).map{|record| record.key}
222
+ source_paths.map do |source_path|
223
+ glossary_name, source_language, target_language = File.basename(source_path).split(/\./)
224
+ glossary = Glossary.new(glossary_name, source_language, target_language)
225
+ GlossarySource.create(source_path, glossary)
226
+ end
227
+ end
228
+
229
+ def glossary_sources_related_on_glossary(glossary)
230
+ records = Groonga["glossary_sources"].select do |record|
231
+ [record.key =~ glossary.to_s]
232
+ end
233
+ records.map{|record| GlossarySource.create(record.key.key, glossary) }
221
234
  end
222
235
 
223
236
  def get_all_glossary
@@ -235,12 +248,10 @@ module Logaling
235
248
  records.each do |record|
236
249
  record.key.delete
237
250
  end
238
- ensure
239
- records.expression.close
240
251
  end
241
252
 
242
- def add_glossary_source(glossary_source, indexed_at)
243
- Groonga["glossary_sources"].add(glossary_source, :indexed_at => indexed_at)
253
+ def add_glossary_source(glossary_source)
254
+ Groonga["glossary_sources"].add(glossary_source.source_path, :indexed_at => glossary_source.mtime)
244
255
  end
245
256
 
246
257
  def delete_glossary(glossary_name)
@@ -251,12 +262,10 @@ module Logaling
251
262
  records.each do |record|
252
263
  record.key.delete
253
264
  end
254
- ensure
255
- records.expression.close
256
265
  end
257
266
 
258
- def add_glossary(glossary_name)
259
- Groonga["glossaries"].add(glossary_name)
267
+ def add_glossary(glossary)
268
+ Groonga["glossaries"].add(glossary.name)
260
269
  end
261
270
 
262
271
  def delete_translations_by_glossary_source(glossary_source)
@@ -267,8 +276,6 @@ module Logaling
267
276
  records.each do |record|
268
277
  record.key.delete
269
278
  end
270
- ensure
271
- records.expression.close
272
279
  end
273
280
 
274
281
  def delete_terms
@@ -345,11 +352,9 @@ module Logaling
345
352
 
346
353
  def remove_schema
347
354
  Groonga::Schema.define do |schema|
348
- schema.remove_table("configurations") if Groonga["configurations"]
349
- schema.remove_table("translations") if Groonga["translations"]
350
- schema.remove_table("glossaries") if Groonga["glossaries"]
351
- schema.remove_table("glossary_sources") if Groonga["glossary_sources"]
352
- schema.remove_table("terms") if Groonga["terms"]
355
+ %w(configurations translations glossaries glossary_sources terms).each do |table|
356
+ schema.remove_table(table) if Groonga[table]
357
+ end
353
358
  end
354
359
  end
355
360
 
@@ -360,8 +365,8 @@ module Logaling
360
365
  def struct_result(records, snippet=nil)
361
366
  records.map do |record|
362
367
  term = record.key
363
- snipped_source_term = snippet ? snip_source_term(term, snippet) : []
364
- snipped_target_term = snippet ? snip_target_term(term, snippet) : []
368
+ snipped_source_term = snippet ? struct_snipped_term(term.source_term, snippet) : []
369
+ snipped_target_term = snippet ? struct_snipped_term(term.target_term, snippet) : []
365
370
  {:glossary_name => term.glossary.key,
366
371
  :source_language => term.source_language,
367
372
  :target_language => term.target_language,
@@ -387,14 +392,21 @@ module Logaling
387
392
  structed_source_term
388
393
  end
389
394
 
390
- def snip_source_term(term, snippet)
391
- snipped_text = snippet.execute(term.source_term).join
392
- struct_snipped_text(snipped_text)
395
+ def struct_snipped_term(term, snippet)
396
+ snipped_text = snippet.execute(term).join
397
+ snipped_text.empty? ? [term] : struct_snipped_text(snipped_text)
398
+ end
399
+
400
+ def latest_version?
401
+ current_version == VERSION
402
+ end
403
+
404
+ def current_version
405
+ Groonga["configurations"] ? get_config("version").to_i : 0
393
406
  end
394
407
 
395
- def snip_target_term(term, snippet)
396
- snipped_text = snippet.execute(term.target_term).join
397
- struct_snipped_text(snipped_text)
408
+ def update_version_to_latest
409
+ add_config("version", VERSION.to_s)
398
410
  end
399
411
 
400
412
  def get_config(conf_key)
@@ -406,8 +418,6 @@ module Logaling
406
418
  config.conf_value
407
419
  end
408
420
  value.size > 0 ? value[0] : ""
409
- ensure
410
- records.expression.close
411
421
  end
412
422
 
413
423
  def add_config(conf_key, conf_value)
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Miho SUZUKI
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "logaling/glossary_sources/glossary_yaml_source"
19
+ require "logaling/glossary_sources/glossary_csv_source"
20
+ require "logaling/glossary_sources/glossary_tsv_source"
21
+
22
+ module Logaling
23
+ class GlossarySource
24
+ def self.create(source_path, glossary)
25
+ case File.extname(source_path)
26
+ when ".csv"
27
+ GlossarySources::GlossaryCsvSource.new(source_path, glossary)
28
+ when ".tsv"
29
+ GlossarySources::GlossaryTsvSource.new(source_path, glossary)
30
+ when ".yml"
31
+ GlossarySources::GlossaryYamlSource.new(source_path, glossary)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2012 Koji SHIMADA <koji.shimada@enishi-tech.com>
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module Logaling
19
+ module GlossarySources
20
+ class Base
21
+ attr_reader :source_path, :glossary
22
+
23
+ def initialize(source_path, glossary)
24
+ @source_path = source_path
25
+ @glossary = glossary
26
+ end
27
+
28
+ def eql?(other)
29
+ return false unless self.class == other.class
30
+ @source_path == other.source_path
31
+ end
32
+
33
+ def hash
34
+ @source_path.hash
35
+ end
36
+
37
+ def mtime
38
+ File.mtime(@source_path)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2012 Koji SHIMADA <koji.shimada@enishi-tech.com>
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "logaling/glossary_sources/base"
19
+ require "csv"
20
+
21
+ module Logaling::GlossarySources
22
+ class GlossaryCsvSource < Base
23
+ def load
24
+ glossary_source = []
25
+ CSV.open(source_path, "r:utf-8", {:col_sep => ','}) do |csv|
26
+ csv.each do |row|
27
+ glossary_source << {"source_term" => row[0], "target_term" => row[1], "note" => ""} if row.size >= 2
28
+ end
29
+ end
30
+ glossary_source
31
+ end
32
+ end
33
+ end