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,90 +1,90 @@
|
|
1
|
-
# Module to encode and decode unicode chars.
|
2
|
-
# This code is highly influced by Florian Frank's JSON gem
|
3
|
-
# @see https://github.com/jnbt/java-properties
|
4
|
-
# @see https://github.com/flori/json/
|
5
|
-
|
6
|
-
module Translatomatic::EscapedUnicode
|
7
|
-
|
8
|
-
# Decodes all unicode chars from escape sequences
|
9
|
-
# @param text [String]
|
10
|
-
# @return [String] The encoded text for chaining
|
11
|
-
def self.unescape(text)
|
12
|
-
string = text.dup
|
13
|
-
string = string.gsub(%r((?:\\[uU](?:[A-Fa-f\d]{4}))+)) do |c|
|
14
|
-
c.downcase!
|
15
|
-
bytes = EMPTY_8BIT_STRING.dup
|
16
|
-
i = 0
|
17
|
-
while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
|
18
|
-
bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
|
19
|
-
i += 1
|
20
|
-
end
|
21
|
-
bytes.encode("utf-8", "utf-16be")
|
22
|
-
end
|
23
|
-
string.force_encoding(::Encoding::UTF_8)
|
24
|
-
|
25
|
-
text.replace string
|
26
|
-
text
|
27
|
-
end
|
28
|
-
|
29
|
-
# Decodes all unicode chars into escape sequences
|
30
|
-
# @param text [String]
|
31
|
-
# @return [String] The decoded text for chaining
|
32
|
-
def self.escape(text)
|
33
|
-
string = text.dup
|
34
|
-
string.force_encoding(::Encoding::ASCII_8BIT)
|
35
|
-
string.gsub!(/["\\\x0-\x1f]/n) { |c| MAP[c] || c }
|
36
|
-
string.gsub!(/(
|
37
|
-
(?:
|
38
|
-
[\xc2-\xdf][\x80-\xbf] |
|
39
|
-
[\xe0-\xef][\x80-\xbf]{2} |
|
40
|
-
[\xf0-\xf4][\x80-\xbf]{3}
|
41
|
-
)+ |
|
42
|
-
[\x80-\xc1\xf5-\xff] # invalid
|
43
|
-
)/nx) { |c|
|
44
|
-
c.size == 1 and raise "Invalid utf8 byte: '#{c}'"
|
45
|
-
s = c.encode("utf-16be", "utf-8").unpack('H*')[0]
|
46
|
-
s.force_encoding(::Encoding::ASCII_8BIT)
|
47
|
-
s.gsub!(/.{4}/n, '\\\\u\&')
|
48
|
-
s.force_encoding(::Encoding::UTF_8)
|
49
|
-
}
|
50
|
-
string.force_encoding(::Encoding::UTF_8)
|
51
|
-
text.replace string
|
52
|
-
text
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
MAP = {
|
58
|
-
"\x0" => '\u0000',
|
59
|
-
"\x1" => '\u0001',
|
60
|
-
"\x2" => '\u0002',
|
61
|
-
"\x3" => '\u0003',
|
62
|
-
"\x4" => '\u0004',
|
63
|
-
"\x5" => '\u0005',
|
64
|
-
"\x6" => '\u0006',
|
65
|
-
"\x7" => '\u0007',
|
66
|
-
"\xb" => '\u000b',
|
67
|
-
"\xe" => '\u000e',
|
68
|
-
"\xf" => '\u000f',
|
69
|
-
"\x10" => '\u0010',
|
70
|
-
"\x11" => '\u0011',
|
71
|
-
"\x12" => '\u0012',
|
72
|
-
"\x13" => '\u0013',
|
73
|
-
"\x14" => '\u0014',
|
74
|
-
"\x15" => '\u0015',
|
75
|
-
"\x16" => '\u0016',
|
76
|
-
"\x17" => '\u0017',
|
77
|
-
"\x18" => '\u0018',
|
78
|
-
"\x19" => '\u0019',
|
79
|
-
"\x1a" => '\u001a',
|
80
|
-
"\x1b" => '\u001b',
|
81
|
-
"\x1c" => '\u001c',
|
82
|
-
"\x1d" => '\u001d',
|
83
|
-
"\x1e" => '\u001e',
|
84
|
-
"\x1f" => '\u001f',
|
85
|
-
}
|
86
|
-
|
87
|
-
EMPTY_8BIT_STRING = ''
|
88
|
-
EMPTY_8BIT_STRING.force_encoding(::Encoding::ASCII_8BIT)
|
89
|
-
|
90
|
-
end
|
1
|
+
# Module to encode and decode unicode chars.
|
2
|
+
# This code is highly influced by Florian Frank's JSON gem
|
3
|
+
# @see https://github.com/jnbt/java-properties
|
4
|
+
# @see https://github.com/flori/json/
|
5
|
+
|
6
|
+
module Translatomatic::EscapedUnicode
|
7
|
+
|
8
|
+
# Decodes all unicode chars from escape sequences
|
9
|
+
# @param text [String]
|
10
|
+
# @return [String] The encoded text for chaining
|
11
|
+
def self.unescape(text)
|
12
|
+
string = text.dup
|
13
|
+
string = string.gsub(%r((?:\\[uU](?:[A-Fa-f\d]{4}))+)) do |c|
|
14
|
+
c.downcase!
|
15
|
+
bytes = EMPTY_8BIT_STRING.dup
|
16
|
+
i = 0
|
17
|
+
while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
|
18
|
+
bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
|
19
|
+
i += 1
|
20
|
+
end
|
21
|
+
bytes.encode("utf-8", "utf-16be")
|
22
|
+
end
|
23
|
+
string.force_encoding(::Encoding::UTF_8)
|
24
|
+
|
25
|
+
text.replace string
|
26
|
+
text
|
27
|
+
end
|
28
|
+
|
29
|
+
# Decodes all unicode chars into escape sequences
|
30
|
+
# @param text [String]
|
31
|
+
# @return [String] The decoded text for chaining
|
32
|
+
def self.escape(text)
|
33
|
+
string = text.dup
|
34
|
+
string.force_encoding(::Encoding::ASCII_8BIT)
|
35
|
+
string.gsub!(/["\\\x0-\x1f]/n) { |c| MAP[c] || c }
|
36
|
+
string.gsub!(/(
|
37
|
+
(?:
|
38
|
+
[\xc2-\xdf][\x80-\xbf] |
|
39
|
+
[\xe0-\xef][\x80-\xbf]{2} |
|
40
|
+
[\xf0-\xf4][\x80-\xbf]{3}
|
41
|
+
)+ |
|
42
|
+
[\x80-\xc1\xf5-\xff] # invalid
|
43
|
+
)/nx) { |c|
|
44
|
+
c.size == 1 and raise "Invalid utf8 byte: '#{c}'"
|
45
|
+
s = c.encode("utf-16be", "utf-8").unpack('H*')[0]
|
46
|
+
s.force_encoding(::Encoding::ASCII_8BIT)
|
47
|
+
s.gsub!(/.{4}/n, '\\\\u\&')
|
48
|
+
s.force_encoding(::Encoding::UTF_8)
|
49
|
+
}
|
50
|
+
string.force_encoding(::Encoding::UTF_8)
|
51
|
+
text.replace string
|
52
|
+
text
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
MAP = {
|
58
|
+
"\x0" => '\u0000',
|
59
|
+
"\x1" => '\u0001',
|
60
|
+
"\x2" => '\u0002',
|
61
|
+
"\x3" => '\u0003',
|
62
|
+
"\x4" => '\u0004',
|
63
|
+
"\x5" => '\u0005',
|
64
|
+
"\x6" => '\u0006',
|
65
|
+
"\x7" => '\u0007',
|
66
|
+
"\xb" => '\u000b',
|
67
|
+
"\xe" => '\u000e',
|
68
|
+
"\xf" => '\u000f',
|
69
|
+
"\x10" => '\u0010',
|
70
|
+
"\x11" => '\u0011',
|
71
|
+
"\x12" => '\u0012',
|
72
|
+
"\x13" => '\u0013',
|
73
|
+
"\x14" => '\u0014',
|
74
|
+
"\x15" => '\u0015',
|
75
|
+
"\x16" => '\u0016',
|
76
|
+
"\x17" => '\u0017',
|
77
|
+
"\x18" => '\u0018',
|
78
|
+
"\x19" => '\u0019',
|
79
|
+
"\x1a" => '\u001a',
|
80
|
+
"\x1b" => '\u001b',
|
81
|
+
"\x1c" => '\u001c',
|
82
|
+
"\x1d" => '\u001d',
|
83
|
+
"\x1e" => '\u001e',
|
84
|
+
"\x1f" => '\u001f',
|
85
|
+
}
|
86
|
+
|
87
|
+
EMPTY_8BIT_STRING = ''
|
88
|
+
EMPTY_8BIT_STRING.force_encoding(::Encoding::ASCII_8BIT)
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Translatomatic::Extractor
|
2
|
+
class Base
|
3
|
+
|
4
|
+
def initialize(path)
|
5
|
+
@path = path.kind_of?(Pathname) ? path : Pathname.new(path)
|
6
|
+
@contents = @path.read
|
7
|
+
end
|
8
|
+
|
9
|
+
def extract
|
10
|
+
@contents.scan(/\"(.*?[^\\])"|'(.*?[^\\])'/).flatten.compact
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module Translatomatic
|
5
|
+
class HTTPRequest
|
6
|
+
|
7
|
+
attr_accessor :multipart_boundary
|
8
|
+
|
9
|
+
def initialize(url)
|
10
|
+
@uri = url.respond_to?(:host) ? url : URI.parse(url)
|
11
|
+
@multipart_boundary = SecureRandom.hex(16)
|
12
|
+
end
|
13
|
+
|
14
|
+
def start(options = {})
|
15
|
+
options = options.merge(use_ssl: @uri.scheme == "https")
|
16
|
+
Net::HTTP.start(@uri.host, @uri.port, options) do |http|
|
17
|
+
@http = http
|
18
|
+
yield http
|
19
|
+
end
|
20
|
+
@http = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(query = nil)
|
24
|
+
uri = @uri
|
25
|
+
if query
|
26
|
+
uri = @uri.dup
|
27
|
+
uri.query = URI.encode_www_form(query)
|
28
|
+
end
|
29
|
+
request = Net::HTTP::Get.new(uri)
|
30
|
+
request['User-Agent'] = USER_AGENT
|
31
|
+
send_request(request)
|
32
|
+
end
|
33
|
+
|
34
|
+
def post(body, options = {})
|
35
|
+
request = Net::HTTP::Post.new(@uri)
|
36
|
+
request['User-Agent'] = USER_AGENT
|
37
|
+
content_type = options[:content_type]
|
38
|
+
|
39
|
+
if options[:multipart]
|
40
|
+
content_type = "multipart/form-data; boundary=#{@multipart_boundary}"
|
41
|
+
request.body = multipartify(body)
|
42
|
+
elsif body.kind_of?(Hash)
|
43
|
+
request.set_form_data(body)
|
44
|
+
else
|
45
|
+
request.body = body
|
46
|
+
end
|
47
|
+
request.content_type = content_type if content_type
|
48
|
+
|
49
|
+
send_request(request)
|
50
|
+
end
|
51
|
+
|
52
|
+
def file(*args)
|
53
|
+
FileParam.new(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def param(*args)
|
57
|
+
Param.new(*args)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
USER_AGENT = "Translatomatic #{VERSION} (+#{URL})"
|
63
|
+
|
64
|
+
# Formats a basic string key/value pair for a multipart post
|
65
|
+
class Param
|
66
|
+
attr_accessor :key, :value
|
67
|
+
|
68
|
+
def initialize(key:, value:)
|
69
|
+
@key = key
|
70
|
+
@value = value
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
return header(header_data) + "\r\n#{value}\r\n"
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def header_data
|
80
|
+
name = CGI::escape(key.to_s)
|
81
|
+
{ "Content-Disposition": "form-data", name: %Q("#{name}") }
|
82
|
+
end
|
83
|
+
|
84
|
+
def header(options)
|
85
|
+
out = []
|
86
|
+
idx = 0
|
87
|
+
options.each do |key, value|
|
88
|
+
separator = idx == 0 ? ": " : "="
|
89
|
+
out << "#{key}#{separator}#{value}"
|
90
|
+
idx += 1
|
91
|
+
end
|
92
|
+
out.join("; ") + "\r\n"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Formats the contents of a file or string for a multipart post
|
97
|
+
class FileParam < Param
|
98
|
+
attr_accessor :filename, :content, :mime_type
|
99
|
+
|
100
|
+
def initialize(key:, filename:, content:, mime_type:)
|
101
|
+
@key = key
|
102
|
+
@filename = filename
|
103
|
+
@content = content
|
104
|
+
@mime_type = mime_type
|
105
|
+
end
|
106
|
+
|
107
|
+
def to_s
|
108
|
+
return header(header_data) +
|
109
|
+
header("Content-Type": mime_type) + "\r\n#{content}\r\n"
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def header_data
|
115
|
+
super.merge({ filename: %Q("#{filename}") })
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def multipartify(parts)
|
120
|
+
string_parts = parts.collect do |p|
|
121
|
+
"--" + @multipart_boundary + "\r\n" + p.to_s
|
122
|
+
end
|
123
|
+
string_parts.join("") + "--" + @multipart_boundary + "--\r\n"
|
124
|
+
end
|
125
|
+
|
126
|
+
def send_request(req)
|
127
|
+
response = @http.request(req)
|
128
|
+
raise response.body unless response.kind_of? Net::HTTPSuccess
|
129
|
+
response
|
130
|
+
end
|
131
|
+
|
132
|
+
end # class
|
133
|
+
end # module
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Translatomatic::Locale
|
2
|
+
|
3
|
+
attr_reader :language
|
4
|
+
attr_reader :script
|
5
|
+
attr_reader :region
|
6
|
+
|
7
|
+
def self.parse(tag, validate = true)
|
8
|
+
locale = tag.kind_of?(Translatomatic::Locale) ? tag : new(tag)
|
9
|
+
validate && !locale.valid? ? nil : locale
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.default
|
13
|
+
DEFAULT_LOCALE
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(tag)
|
17
|
+
data = I18n::Locale::Tag::Rfc4646.tag(tag)
|
18
|
+
if data
|
19
|
+
@language = data.language
|
20
|
+
@script = data.script
|
21
|
+
@region = data.region
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid?
|
26
|
+
# test if lang is a valid ISO 639-1 language
|
27
|
+
VALID_LANGUAGES.include?(language)
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
[language, script, region].compact.join("-")
|
32
|
+
end
|
33
|
+
|
34
|
+
def eql?(other)
|
35
|
+
other.kind_of?(Translatomatic::Locale) && other.hash == hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(other)
|
39
|
+
eql?(other)
|
40
|
+
end
|
41
|
+
|
42
|
+
def hash
|
43
|
+
[language, script, region].hash
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# list of 2 letter country codes
|
49
|
+
VALID_LANGUAGES = ::I18nData.languages.keys.collect { |i| i.downcase }.sort
|
50
|
+
DEFAULT_LOCALE = parse(I18n.default_locale)
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Translatomatic::Logger
|
2
|
+
attr_accessor :progressbar
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@logger = Logger.new(STDOUT)
|
6
|
+
@logger.level = ENV['DEBUG'] ? Logger::DEBUG : Logger::INFO
|
7
|
+
@logger.formatter = proc do |severity, datetime, progname, msg|
|
8
|
+
"#{msg}\n"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(name, *args)
|
13
|
+
handle_logger_method(name, args) if @logger.respond_to?(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def finish
|
17
|
+
@progressbar.finish if @progressbar
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def handle_logger_method(name, args)
|
23
|
+
@progressbar.clear if @progressbar
|
24
|
+
@logger.send(name, *args)
|
25
|
+
@progressbar.refresh(force: true) if @progressbar && !@progressbar.stopped?
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -1,22 +1,21 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
module Model
|
3
|
-
class Locale < ActiveRecord::Base
|
4
|
-
has_many :texts, class_name: "Translatomatic::Model::Text"
|
5
|
-
validates_presence_of :language
|
6
|
-
validates_uniqueness_of :language, scope: [:script, :region]
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
1
|
+
module Translatomatic
|
2
|
+
module Model
|
3
|
+
class Locale < ActiveRecord::Base
|
4
|
+
has_many :texts, class_name: "Translatomatic::Model::Text"
|
5
|
+
validates_presence_of :language
|
6
|
+
validates_uniqueness_of :language, scope: [:script, :region]
|
7
|
+
|
8
|
+
# create a locale record from an I18n::Locale::Tag object or string
|
9
|
+
def self.from_tag(tag)
|
10
|
+
tag = Translatomatic::Locale.parse(tag)
|
11
|
+
find_or_create_by!({
|
12
|
+
language: tag.language, script: tag.script, region: tag.region
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
[language, script, region].compact.join("-")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,13 +1,17 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
module Model
|
3
|
-
class Text < ActiveRecord::Base
|
4
|
-
belongs_to :locale, class_name: "Translatomatic::Model::Locale"
|
5
|
-
belongs_to :from_text, class_name: "Translatomatic::Model::Text"
|
6
|
-
has_many :translations, class_name: "Translatomatic::Model::Text",
|
7
|
-
foreign_key: :from_text_id, dependent: :delete_all
|
8
|
-
|
9
|
-
validates_presence_of :value
|
10
|
-
validates_presence_of :locale
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
module Translatomatic
|
2
|
+
module Model
|
3
|
+
class Text < ActiveRecord::Base
|
4
|
+
belongs_to :locale, class_name: "Translatomatic::Model::Locale"
|
5
|
+
belongs_to :from_text, class_name: "Translatomatic::Model::Text"
|
6
|
+
has_many :translations, class_name: "Translatomatic::Model::Text",
|
7
|
+
foreign_key: :from_text_id, dependent: :delete_all
|
8
|
+
|
9
|
+
validates_presence_of :value
|
10
|
+
validates_presence_of :locale
|
11
|
+
|
12
|
+
def is_translated?
|
13
|
+
!from_text_id.nil?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/translatomatic/model.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Translatomatic::Model; end
|
2
|
-
|
3
|
-
require 'translatomatic/model/locale'
|
4
|
-
require 'translatomatic/model/text'
|
1
|
+
module Translatomatic::Model; end
|
2
|
+
|
3
|
+
require 'translatomatic/model/locale'
|
4
|
+
require 'translatomatic/model/text'
|
@@ -1,24 +1,24 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
class Option
|
3
|
-
attr_reader :name, :required, :use_env, :description
|
4
|
-
|
5
|
-
def initialize(data = {})
|
6
|
-
@name = data[:name]
|
7
|
-
@required = data[:required]
|
8
|
-
@use_env = data[:use_env]
|
9
|
-
@description = data[:desc]
|
10
|
-
@data = data
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_hash
|
14
|
-
@data
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
module DefineOptions
|
19
|
-
private
|
20
|
-
def define_options(*options)
|
21
|
-
@options = options.collect { |i| Translatomatic::Option.new(i) }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
1
|
+
module Translatomatic
|
2
|
+
class Option
|
3
|
+
attr_reader :name, :required, :use_env, :description
|
4
|
+
|
5
|
+
def initialize(data = {})
|
6
|
+
@name = data[:name]
|
7
|
+
@required = data[:required]
|
8
|
+
@use_env = data[:use_env]
|
9
|
+
@description = data[:desc]
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_hash
|
14
|
+
@data
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module DefineOptions
|
19
|
+
private
|
20
|
+
def define_options(*options)
|
21
|
+
@options = options.collect { |i| Translatomatic::Option.new(i) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# implements Converter listener
|
2
|
+
class Translatomatic::ProgressUpdater
|
3
|
+
def initialize(progressbar)
|
4
|
+
@progressbar = progressbar
|
5
|
+
end
|
6
|
+
|
7
|
+
def translated_texts(texts)
|
8
|
+
@progressbar.progress += texts.length
|
9
|
+
end
|
10
|
+
|
11
|
+
def untranslated_texts(texts)
|
12
|
+
@progressbar.total -= texts.length
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|