translatomatic 0.1.0 → 0.1.1
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.
- 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,157 +1,221 @@
|
|
1
|
-
class Translatomatic::Converter
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
1
|
+
class Translatomatic::Converter
|
2
|
+
|
3
|
+
class << self
|
4
|
+
attr_reader :options
|
5
|
+
private
|
6
|
+
include Translatomatic::DefineOptions
|
7
|
+
end
|
8
|
+
|
9
|
+
define_options(
|
10
|
+
{ name: :translator, type: :string, aliases: "-t",
|
11
|
+
desc: "Translator implementation to use",
|
12
|
+
enum: Translatomatic::Translator.names },
|
13
|
+
{ name: :dry_run, type: :boolean, aliases: "-n", desc:
|
14
|
+
"Print actions without performing translations or writing files" },
|
15
|
+
{ name: :use_database, type: :boolean, default: true, desc:
|
16
|
+
"Store and retrieve translations in the database" }
|
17
|
+
)
|
18
|
+
|
19
|
+
# @return [Translatomatic::ConverterStats] translation statistics
|
19
20
|
attr_reader :stats
|
20
21
|
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
22
|
+
# @return [Array<Translatomatic::Model::Text>] A list of translations saved to the database
|
23
|
+
attr_reader :db_translations
|
24
|
+
|
25
|
+
# Create a converter to translate files
|
26
|
+
#
|
27
|
+
# @param options A hash of converter and/or translator options.
|
28
|
+
def initialize(options = {})
|
29
|
+
@dry_run = options[:dry_run]
|
30
|
+
@translator = options[:translator]
|
31
|
+
@listener = options[:listener]
|
32
|
+
|
33
|
+
# use database by default if we're connected to a database
|
34
|
+
use_db = options.include?(:use_database) ? options[:use_database] : true
|
35
|
+
@use_db = use_db && ActiveRecord::Base.connected?
|
36
|
+
|
37
|
+
log.debug("database is disabled") unless @use_db
|
38
|
+
if @translator && !@translator.respond_to?(:translate)
|
39
|
+
klass = Translatomatic::Translator.find(@translator)
|
40
|
+
@translator = klass.new(options)
|
41
|
+
end
|
42
|
+
raise "translator required" unless @translator
|
43
|
+
@translator.listener = @listener if @listener
|
44
|
+
@from_db = 0
|
33
45
|
@from_translator = 0
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# @param [String]
|
46
|
-
# @
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
@db_translations = []
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [Translatomatic::ConverterStats] Translation statistics
|
50
|
+
def stats
|
51
|
+
Translatomatic::ConverterStats.new(@from_db, @from_translator)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Translate contents of source_file to the target locale.
|
55
|
+
# Automatically determines the target filename based on target locale.
|
56
|
+
#
|
57
|
+
# @param [String, Translatomatic::ResourceFile] source_file File to translate
|
58
|
+
# @param [String] to_locale The target locale, e.g. "fr"
|
59
|
+
# @return [Translatomatic::ResourceFile] The translated resource file
|
60
|
+
def translate(source_file, to_locale)
|
61
|
+
if source_file.kind_of?(Translatomatic::ResourceFile::Base)
|
62
|
+
source = source_file
|
63
|
+
else
|
64
|
+
source = Translatomatic::ResourceFile.load(source_file)
|
65
|
+
raise "unsupported file type #{source_file}" unless source
|
66
|
+
end
|
67
|
+
|
68
|
+
to_locale = parse_locale(to_locale)
|
69
|
+
target = Translatomatic::ResourceFile.load(source.path)
|
70
|
+
target.path = source.locale_path(to_locale)
|
71
|
+
target.locale = to_locale
|
72
|
+
translate_to_target(source, target)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Translates a resource file and writes results to a target resource file
|
76
|
+
#
|
77
|
+
# @param source [Translatomatic::ResourceFile] The source
|
78
|
+
# @param target [Translatomatic::ResourceFile] The file to write
|
79
|
+
# @return [Translatomatic::ResourceFile] The translated resource file
|
80
|
+
def translate_to_target(source, target)
|
81
|
+
# perform translation
|
82
|
+
log.info("translating #{source} to #{target}")
|
83
|
+
properties = translate_properties(source.properties, source.locale, target.locale)
|
84
|
+
target.properties = properties
|
85
|
+
unless @dry_run
|
86
|
+
target.path.parent.mkpath
|
87
|
+
target.save
|
88
|
+
end
|
89
|
+
target
|
90
|
+
end
|
91
|
+
|
92
|
+
# Translate values in the hash of properties.
|
93
|
+
# Uses existing translations from the database if available.
|
94
|
+
#
|
95
|
+
# @param [Hash] properties Text to translate
|
96
|
+
# @param [String, Locale] from_locale The locale of the given properties
|
97
|
+
# @param [String, Locale] to_locale The target locale for translations
|
98
|
+
# @return [Hash] Translated properties
|
99
|
+
def translate_properties(properties, from_locale, to_locale)
|
100
|
+
from_locale = parse_locale(from_locale)
|
101
|
+
to_locale = parse_locale(to_locale)
|
102
|
+
|
103
|
+
# sanity check
|
104
|
+
return properties if from_locale.language == to_locale.language
|
105
|
+
|
106
|
+
result = Translatomatic::TranslationResult.new(properties,
|
107
|
+
from_locale, to_locale)
|
108
|
+
|
109
|
+
# translate using strings from the database first
|
110
|
+
db_texts = translate_properties_with_db(result)
|
111
|
+
|
112
|
+
# send remaining unknown strings to translator
|
113
|
+
tr_texts = translate_properties_with_translator(result)
|
114
|
+
|
115
|
+
log.debug("translations from db: %d translator: %d untranslated: %d" %
|
116
|
+
[db_texts.length, tr_texts.length, result.untranslated.length])
|
117
|
+
@listener.untranslated_texts(result.untranslated) if @listener
|
118
|
+
|
119
|
+
result.properties
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
include Translatomatic::Util
|
125
|
+
|
126
|
+
# update result with translations from the database.
|
127
|
+
# returns a list of text records from the database.
|
128
|
+
def translate_properties_with_db(result)
|
129
|
+
db_texts = []
|
130
|
+
unless database_disabled?
|
131
|
+
untranslated = result.untranslated.to_a
|
132
|
+
db_texts = find_database_translations(result, untranslated)
|
133
|
+
|
134
|
+
# find strings in untranslated that were matched in the database
|
135
|
+
original_map = {} # map of original text to translated text from db
|
136
|
+
db_texts.each do |db_text|
|
137
|
+
original_map[db_text.from_text.value] = db_text
|
138
|
+
end
|
139
|
+
matched = untranslated.select { |i| original_map[i.value] }
|
140
|
+
db_texts = db_texts.collect { |i| i.value }
|
141
|
+
result.update_strings(matched, db_texts)
|
142
|
+
@from_db += db_texts.length
|
143
|
+
@listener.translated_texts(db_texts) if @listener
|
53
144
|
end
|
54
|
-
|
55
|
-
to_locale = parse_locale(to_locale)
|
56
|
-
target = Translatomatic::ResourceFile.load(source.path)
|
57
|
-
target.path = source.locale_path(to_locale)
|
58
|
-
target.locale = to_locale
|
59
|
-
translate_to_target(source, target)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Translates a resource file and writes results to a target resource file
|
63
|
-
#
|
64
|
-
# @param source [Translatomatic::ResourceFile] The source
|
65
|
-
# @param target [Translatomatic::ResourceFile] The file to write
|
66
|
-
# @return [Translatomatic::ResourceFile] The translated resource file
|
67
|
-
def translate_to_target(source, target)
|
68
|
-
# perform translation
|
69
|
-
log.info "translating #{source} to #{target}"
|
70
|
-
properties = translate_properties(source.properties, source.locale, target.locale)
|
71
|
-
target.properties = properties
|
72
|
-
target.save unless @dry_run
|
73
|
-
target
|
145
|
+
db_texts
|
74
146
|
end
|
75
147
|
|
76
|
-
#
|
77
|
-
#
|
78
|
-
|
79
|
-
# @param [Hash] properties Text to translate
|
80
|
-
# @param [String, Locale] from_locale The locale of the given properties
|
81
|
-
# @param [String, Locale] to_locale The target locale for translations
|
82
|
-
# @return [Hash] Translated properties
|
83
|
-
def translate_properties(properties, from_locale, to_locale)
|
84
|
-
from_locale = parse_locale(from_locale)
|
85
|
-
to_locale = parse_locale(to_locale)
|
86
|
-
|
87
|
-
# sanity check
|
88
|
-
return properties if from_locale.language == to_locale.language
|
89
|
-
|
90
|
-
result = Translatomatic::TranslationResult.new(properties,
|
91
|
-
from_locale, to_locale)
|
92
|
-
|
93
|
-
# find translations in database first
|
94
|
-
texts = find_database_translations(result)
|
95
|
-
result.update_db_strings(texts)
|
96
|
-
@from_db += texts.length
|
97
|
-
|
98
|
-
# send remaining unknown strings to translator
|
99
|
-
# (copy untranslated set from result)
|
148
|
+
# update result with translations from the translator.
|
149
|
+
# returns a list of strings from the translator.
|
150
|
+
def translate_properties_with_translator(result)
|
100
151
|
untranslated = result.untranslated.to_a.select { |i| translatable?(i) }
|
152
|
+
translated = []
|
101
153
|
@from_translator += untranslated.length
|
102
154
|
if !untranslated.empty? && !@dry_run
|
103
|
-
translated = @translator.translate(untranslated
|
155
|
+
translated = @translator.translate(untranslated.collect { |i| i.to_s },
|
156
|
+
result.from_locale, result.to_locale)
|
104
157
|
result.update_strings(untranslated, translated)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
log.debug("translations from db: %d translator: %d untranslated: %d" %
|
109
|
-
[texts.length, untranslated.length, result.untranslated.length])
|
110
|
-
result.properties
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
def translatable?(string)
|
116
|
-
# don't translate numbers
|
117
|
-
!string.empty? && !string.match(/^[\d,]+$/)
|
118
|
-
end
|
119
|
-
|
120
|
-
def save_database_translations(result, untranslated, translated)
|
121
|
-
ActiveRecord::Base.transaction do
|
122
|
-
from = db_locale(result.from_locale)
|
123
|
-
to = db_locale(result.to_locale)
|
124
|
-
untranslated.zip(translated).each do |t1, t2|
|
125
|
-
save_database_translation(from, to, t1, t2)
|
158
|
+
unless database_disabled?
|
159
|
+
save_database_translations(result, untranslated, translated)
|
126
160
|
end
|
127
161
|
end
|
162
|
+
translated
|
128
163
|
end
|
129
164
|
|
130
|
-
def
|
131
|
-
|
132
|
-
locale: from_locale,
|
133
|
-
value: t1
|
134
|
-
)
|
135
|
-
|
136
|
-
Translatomatic::Model::Text.find_or_create_by!(
|
137
|
-
locale: to_locale,
|
138
|
-
value: t2,
|
139
|
-
from_text: original_text,
|
140
|
-
translator: @translator.class.name.demodulize
|
141
|
-
)
|
142
|
-
end
|
143
|
-
|
144
|
-
def find_database_translations(result)
|
145
|
-
from = db_locale(result.from_locale)
|
146
|
-
to = db_locale(result.to_locale)
|
147
|
-
|
148
|
-
Translatomatic::Model::Text.where({
|
149
|
-
locale: to,
|
150
|
-
from_texts_texts: { locale_id: from, value: result.untranslated.to_a }
|
151
|
-
}).joins(:from_text)
|
152
|
-
end
|
153
|
-
|
154
|
-
def db_locale(locale)
|
155
|
-
Translatomatic::Model::Locale.from_tag(locale)
|
165
|
+
def database_disabled?
|
166
|
+
!@use_db
|
156
167
|
end
|
157
|
-
|
168
|
+
|
169
|
+
def parse_locale(locale)
|
170
|
+
Translatomatic::Locale.parse(locale)
|
171
|
+
end
|
172
|
+
|
173
|
+
def translatable?(string)
|
174
|
+
# don't translate numbers
|
175
|
+
!string.empty? && !string.match(/^[\d,]+$/)
|
176
|
+
end
|
177
|
+
|
178
|
+
def save_database_translations(result, untranslated, translated)
|
179
|
+
ActiveRecord::Base.transaction do
|
180
|
+
from = db_locale(result.from_locale)
|
181
|
+
to = db_locale(result.to_locale)
|
182
|
+
untranslated.zip(translated).each do |t1, t2|
|
183
|
+
save_database_translation(from, to, t1, t2)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def save_database_translation(from_locale, to_locale, t1, t2)
|
189
|
+
original_text = Translatomatic::Model::Text.find_or_create_by!(
|
190
|
+
locale: from_locale,
|
191
|
+
value: t1.to_s
|
192
|
+
)
|
193
|
+
|
194
|
+
text = Translatomatic::Model::Text.find_or_create_by!(
|
195
|
+
locale: to_locale,
|
196
|
+
value: t2.to_s,
|
197
|
+
from_text: original_text,
|
198
|
+
translator: @translator.name
|
199
|
+
)
|
200
|
+
@db_translations += [original_text, text]
|
201
|
+
text
|
202
|
+
end
|
203
|
+
|
204
|
+
def find_database_translations(result, untranslated)
|
205
|
+
from = db_locale(result.from_locale)
|
206
|
+
to = db_locale(result.to_locale)
|
207
|
+
|
208
|
+
# convert untranslated set to strings
|
209
|
+
Translatomatic::Model::Text.where({
|
210
|
+
locale: to,
|
211
|
+
from_texts_texts: {
|
212
|
+
locale_id: from,
|
213
|
+
value: untranslated.collect { |i| i.to_s }
|
214
|
+
}
|
215
|
+
}).joins(:from_text)
|
216
|
+
end
|
217
|
+
|
218
|
+
def db_locale(locale)
|
219
|
+
Translatomatic::Model::Locale.from_tag(locale)
|
220
|
+
end
|
221
|
+
end
|
@@ -1,27 +1,27 @@
|
|
1
|
-
# Translation statistics
|
2
|
-
class Translatomatic::ConverterStats
|
3
|
-
|
4
|
-
# @return [Number] The total number of strings translated.
|
5
|
-
attr_reader :translations
|
6
|
-
|
7
|
-
# @return [Number] The number of translations that came from the database.
|
8
|
-
attr_reader :from_db
|
9
|
-
|
10
|
-
# @return [Number] The number of translations that came from the translator.
|
11
|
-
attr_reader :from_translator
|
12
|
-
|
13
|
-
def initialize(from_db, from_translator)
|
14
|
-
@translations = from_db + from_translator
|
15
|
-
@from_db = from_db
|
16
|
-
@from_translator = from_translator
|
17
|
-
end
|
18
|
-
|
19
|
-
def +(other)
|
20
|
-
self.class.new(@from_db + other.from_db, @from_translator + other.from_translator)
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_s
|
24
|
-
"Total translations: #{@translations} " +
|
25
|
-
"(#{@from_db} from database, #{@from_translator} from translator)"
|
26
|
-
end
|
27
|
-
end
|
1
|
+
# Translation statistics
|
2
|
+
class Translatomatic::ConverterStats
|
3
|
+
|
4
|
+
# @return [Number] The total number of strings translated.
|
5
|
+
attr_reader :translations
|
6
|
+
|
7
|
+
# @return [Number] The number of translations that came from the database.
|
8
|
+
attr_reader :from_db
|
9
|
+
|
10
|
+
# @return [Number] The number of translations that came from the translator.
|
11
|
+
attr_reader :from_translator
|
12
|
+
|
13
|
+
def initialize(from_db, from_translator)
|
14
|
+
@translations = from_db + from_translator
|
15
|
+
@from_db = from_db
|
16
|
+
@from_translator = from_translator
|
17
|
+
end
|
18
|
+
|
19
|
+
def +(other)
|
20
|
+
self.class.new(@from_db + other.from_db, @from_translator + other.from_translator)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
"Total translations: #{@translations} " +
|
25
|
+
"(#{@from_db} from database, #{@from_translator} from translator)"
|
26
|
+
end
|
27
|
+
end
|
@@ -1,105 +1,145 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
|
3
|
-
class Translatomatic::Database
|
4
|
-
|
5
|
-
include Translatomatic::Util
|
6
|
-
|
7
|
-
class << self
|
8
|
-
attr_reader :options
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
class Translatomatic::Database
|
4
|
+
|
5
|
+
include Translatomatic::Util
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_reader :options
|
9
|
+
|
10
|
+
# @param [Hash<Symbol,Object>] options Database options
|
11
|
+
# @return True if we can connect to the database
|
12
|
+
def enabled?(options = {})
|
13
|
+
new(options).connect
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
include Translatomatic::DefineOptions
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(options = {})
|
18
22
|
@env = options[:database_env] || DEFAULT_ENV
|
19
|
-
@db_config =
|
20
|
-
@env_config = @db_config
|
21
|
-
raise "no environment '#{@env}' in #{db_config_path}" unless @env_config[@env]
|
22
|
-
@env_config = @env_config[@env]
|
23
|
-
|
24
|
-
ActiveRecord::
|
25
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
26
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
27
|
-
ActiveRecord::Tasks::DatabaseTasks.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
23
|
+
@db_config = database_config(@env, options)
|
24
|
+
@env_config = @db_config
|
25
|
+
raise "no environment '#{@env}' in #{db_config_path}" unless @env_config[@env]
|
26
|
+
@env_config = @env_config[@env] || {}
|
27
|
+
|
28
|
+
ActiveRecord::Base.configurations = @db_config
|
29
|
+
ActiveRecord::Tasks::DatabaseTasks.env = @env
|
30
|
+
ActiveRecord::Tasks::DatabaseTasks.db_dir = DB_PATH
|
31
|
+
ActiveRecord::Tasks::DatabaseTasks.root = DB_PATH
|
32
|
+
ActiveRecord::Tasks::DatabaseTasks.database_configuration = @db_config
|
33
|
+
create unless exists?
|
34
|
+
migrate
|
35
|
+
end
|
36
|
+
|
37
|
+
# Connect to the database
|
38
|
+
# @return [boolean] True if the connection was established
|
39
|
+
def connect
|
40
|
+
begin
|
41
|
+
ActiveRecord::Base.establish_connection(@env_config)
|
42
|
+
true
|
43
|
+
rescue LoadError
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Disconnect from the database
|
49
|
+
# @return [void]
|
50
|
+
def disconnect
|
51
|
+
ActiveRecord::Base.remove_connection
|
52
|
+
end
|
53
|
+
|
54
|
+
# Test if the database exists
|
55
|
+
# @return [Boolean] true if the database exists
|
56
|
+
def exists?
|
57
|
+
begin
|
58
|
+
return true if sqlite_database_exists?
|
59
|
+
return false unless connect
|
60
|
+
ActiveRecord::Base.connection.tables
|
61
|
+
rescue
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
# Run outstanding migrations against the database
|
68
|
+
# @return [void]
|
69
|
+
def migrate
|
70
|
+
return false unless connect
|
71
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_PATH)
|
72
|
+
ActiveRecord::Base.clear_cache!
|
73
|
+
log.debug "Database migrated."
|
74
|
+
end
|
75
|
+
|
76
|
+
# Create the database
|
77
|
+
# @return [boolean] True if the database was created
|
78
|
+
def create
|
79
|
+
begin
|
80
|
+
ActiveRecord::Tasks::DatabaseTasks.create(@env_config)
|
81
|
+
log.debug "Database created."
|
82
|
+
true
|
83
|
+
rescue LoadError => e
|
84
|
+
log.debug "Database could not be created: " + e.message
|
85
|
+
false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Drop the database
|
90
|
+
# @return [void]
|
91
|
+
def drop
|
92
|
+
disconnect
|
93
|
+
ActiveRecord::Tasks::DatabaseTasks.drop(@env_config)
|
94
|
+
log.debug "Database deleted."
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def sqlite_database_exists?
|
100
|
+
@env_config['adapter'] == 'sqlite3' && File.exist?(@env_config['database'])
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.join_path(*parts)
|
104
|
+
File.realpath(File.join(*parts))
|
105
|
+
end
|
106
|
+
|
107
|
+
DB_PATH = join_path(File.dirname(__FILE__), "..", "..", "db")
|
108
|
+
INTERNAL_CONFIG = File.join(DB_PATH, "database.yml")
|
109
|
+
CUSTOM_CONFIG = File.join(Dir.home, ".translatomatic", "database.yml")
|
110
|
+
DEFAULT_CONFIG = File.exist?(CUSTOM_CONFIG) ? CUSTOM_CONFIG : INTERNAL_CONFIG
|
111
|
+
MIGRATIONS_PATH = File.join(DB_PATH, "migrate")
|
112
|
+
GEM_ROOT = join_path(File.dirname(__FILE__), "..", "..")
|
113
|
+
DEFAULT_ENV = "production"
|
114
|
+
|
115
|
+
define_options(
|
116
|
+
{ name: :database_config, description: "Database config file",
|
117
|
+
default: DEFAULT_CONFIG },
|
118
|
+
{ name: :database_env, description: "Database environment",
|
119
|
+
default: DEFAULT_ENV })
|
37
120
|
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
121
|
+
# return path to database config
|
122
|
+
def database_config_path(options)
|
123
|
+
if options[:database_env] == "test"
|
124
|
+
INTERNAL_CONFIG # rspec
|
125
|
+
elsif options[:database_config]
|
126
|
+
return options[:database_config]
|
127
|
+
else
|
128
|
+
DEFAULT_CONFIG
|
129
|
+
end
|
42
130
|
end
|
43
131
|
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
connect
|
49
|
-
ActiveRecord::Base.connection.tables
|
50
|
-
rescue
|
51
|
-
return false
|
132
|
+
# return database config as a hash
|
133
|
+
def database_config(env, options)
|
134
|
+
if options[:database_config].kind_of?(Hash)
|
135
|
+
return { env => options[:database_config] }
|
52
136
|
end
|
53
|
-
true
|
54
|
-
end
|
55
|
-
|
56
|
-
# Run outstanding migrations against the database
|
57
|
-
# @return [void]
|
58
|
-
def migrate
|
59
|
-
connect
|
60
|
-
ActiveRecord::Migrator.migrate(MIGRATIONS_PATH)
|
61
|
-
ActiveRecord::Base.clear_cache!
|
62
|
-
log.debug "Database migrated."
|
63
|
-
end
|
64
|
-
|
65
|
-
# Create the database
|
66
|
-
# @return [void]
|
67
|
-
def create
|
68
|
-
ActiveRecord::Tasks::DatabaseTasks.create(@env_config)
|
69
|
-
log.debug "Database created."
|
70
|
-
end
|
71
|
-
|
72
|
-
# Drop the database
|
73
|
-
# @return [void]
|
74
|
-
def drop
|
75
|
-
disconnect
|
76
|
-
ActiveRecord::Tasks::DatabaseTasks.drop(@env_config)
|
77
|
-
log.debug "Database deleted."
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
DB_PATH = File.join(File.dirname(__FILE__), "..", "..", "db")
|
83
|
-
INTERNAL_DB_CONFIG = File.join(DB_PATH, "database.yml")
|
84
|
-
CUSTOM_DB_CONFIG = File.join(Dir.home, ".translatomatic", "database.yml")
|
85
|
-
DEFAULT_DB_CONFIG = File.exist?(CUSTOM_DB_CONFIG) ? CUSTOM_DB_CONFIG : INTERNAL_DB_CONFIG
|
86
|
-
MIGRATIONS_PATH = File.join(DB_PATH, "migrate")
|
87
|
-
GEM_ROOT = File.join(File.dirname(__FILE__), "..", "..")
|
88
|
-
DEFAULT_ENV = "production"
|
89
137
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
INTERNAL_DB_CONFIG # rspec
|
99
|
-
elsif options[:database_config]
|
100
|
-
return options[:database_config]
|
101
|
-
else
|
102
|
-
DEFAULT_DB_CONFIG
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
138
|
+
db_config_path = database_config_path(options)
|
139
|
+
dbconfig = File.read(db_config_path)
|
140
|
+
dbconfig.gsub!(/\$HOME/, Dir.home)
|
141
|
+
dbconfig.gsub!(/\$GEM_ROOT/, GEM_ROOT)
|
142
|
+
YAML::load(dbconfig) || {}
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|