translatomatic 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +19 -0
- data/.gitignore +0 -0
- data/.travis.yml +7 -7
- data/.yardopts +9 -0
- data/Gemfile +4 -4
- data/Guardfile +0 -0
- data/README.de.md +61 -16
- data/README.es.md +60 -15
- data/README.fr.md +61 -16
- data/README.it.md +60 -15
- data/README.ja.md +59 -14
- data/README.ko.md +137 -0
- data/README.md +58 -13
- data/README.ms.md +137 -0
- data/README.pt.md +137 -0
- data/README.ru.md +137 -0
- data/README.sv.md +137 -0
- data/README.zh.md +137 -0
- data/bin/setup +8 -8
- data/bin/translatomatic +6 -6
- data/bin/travis +1 -1
- data/config/locales/translatomatic/de.yml +104 -0
- data/config/locales/translatomatic/en.yml +101 -0
- data/config/locales/translatomatic/es.yml +105 -0
- data/config/locales/translatomatic/fr.yml +105 -0
- data/config/locales/translatomatic/it.yml +103 -0
- data/config/locales/translatomatic/ja.yml +102 -0
- data/config/locales/translatomatic/ko.yml +101 -0
- data/config/locales/translatomatic/ms.yml +103 -0
- data/config/locales/translatomatic/pt.yml +105 -0
- data/config/locales/translatomatic/ru.yml +103 -0
- data/config/locales/translatomatic/sv.yml +103 -0
- data/config/locales/translatomatic/zh.yml +102 -0
- data/db/migrate/201712170000_initial.rb +2 -1
- data/lib/translatomatic/cli/base.rb +73 -0
- data/lib/translatomatic/cli/common_options.rb +14 -0
- data/lib/translatomatic/cli/config.rb +81 -0
- data/lib/translatomatic/cli/database.rb +29 -0
- data/lib/translatomatic/cli/main.rb +112 -0
- data/lib/translatomatic/cli/translate.rb +146 -0
- data/lib/translatomatic/cli.rb +8 -216
- data/lib/translatomatic/config.rb +143 -0
- data/lib/translatomatic/converter.rb +196 -149
- data/lib/translatomatic/converter_stats.rb +18 -14
- data/lib/translatomatic/database.rb +35 -37
- data/lib/translatomatic/escaped_unicode.rb +1 -1
- data/lib/translatomatic/extractor/base.rb +2 -0
- data/lib/translatomatic/extractor/ruby.rb +1 -0
- data/lib/translatomatic/extractor.rb +1 -0
- data/lib/translatomatic/http_request.rb +43 -14
- data/lib/translatomatic/locale.rb +28 -4
- data/lib/translatomatic/logger.rb +21 -13
- data/lib/translatomatic/model/locale.rb +5 -1
- data/lib/translatomatic/model/text.rb +2 -0
- data/lib/translatomatic/model.rb +1 -0
- data/lib/translatomatic/option.rb +75 -10
- data/lib/translatomatic/progress_updater.rb +7 -3
- data/lib/translatomatic/resource_file/base.rb +41 -18
- data/lib/translatomatic/resource_file/html.rb +11 -14
- data/lib/translatomatic/resource_file/markdown.rb +13 -12
- data/lib/translatomatic/resource_file/plist.rb +3 -14
- data/lib/translatomatic/resource_file/properties.rb +21 -3
- data/lib/translatomatic/resource_file/resw.rb +1 -0
- data/lib/translatomatic/resource_file/text.rb +1 -0
- data/lib/translatomatic/resource_file/xcode_strings.rb +23 -14
- data/lib/translatomatic/resource_file/xml.rb +34 -22
- data/lib/translatomatic/resource_file/yaml.rb +39 -5
- data/lib/translatomatic/resource_file.rb +7 -5
- data/lib/translatomatic/string.rb +40 -12
- data/lib/translatomatic/tmx/document.rb +11 -12
- data/lib/translatomatic/tmx/translation_unit.rb +5 -1
- data/lib/translatomatic/tmx.rb +2 -0
- data/lib/translatomatic/translation.rb +30 -0
- data/lib/translatomatic/translation_result.rb +45 -45
- data/lib/translatomatic/translator/base.rb +128 -83
- data/lib/translatomatic/translator/frengly.rb +62 -57
- data/lib/translatomatic/translator/google.rb +35 -31
- data/lib/translatomatic/translator/microsoft.rb +41 -33
- data/lib/translatomatic/translator/my_memory.rb +68 -64
- data/lib/translatomatic/translator/yandex.rb +56 -39
- data/lib/translatomatic/translator.rb +99 -63
- data/lib/translatomatic/util.rb +31 -1
- data/lib/translatomatic/version.rb +4 -1
- data/lib/translatomatic.rb +17 -0
- data/translatomatic.gemspec +5 -4
- metadata +56 -16
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'date'
|
2
2
|
|
3
3
|
module Translatomatic::ResourceFile
|
4
|
+
# Properties resource file
|
5
|
+
# @see https://docs.oracle.com/javase/tutorial/essential/environment/properties.html
|
4
6
|
class Properties < Base
|
5
7
|
|
6
8
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
@@ -21,7 +23,7 @@ module Translatomatic::ResourceFile
|
|
21
23
|
out += add_created_by unless options[:no_created_by]
|
22
24
|
properties.each do |key, value|
|
23
25
|
# TODO: maintain original line ending format?
|
24
|
-
value = value.gsub("\n", "\\n") # convert newlines to \n
|
26
|
+
value = value.gsub("\n", "\\n") if value # convert newlines to \n
|
25
27
|
out += "#{key} = #{value}\n"
|
26
28
|
end
|
27
29
|
# escape unicode characters
|
@@ -29,6 +31,21 @@ module Translatomatic::ResourceFile
|
|
29
31
|
target.write(out)
|
30
32
|
end
|
31
33
|
|
34
|
+
# (see Translatomatic::ResourceFile::Base#supports_variable_interpolation?)
|
35
|
+
def supports_variable_interpolation?
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
# (see Translatomatic::ResourceFile::Base#create_variable)
|
40
|
+
def create_variable(name)
|
41
|
+
return "{#{name}}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# (see Translatomatic::ResourceFile::Base#variable_regex)
|
45
|
+
def variable_regex
|
46
|
+
/\{.*?\}/
|
47
|
+
end
|
48
|
+
|
32
49
|
private
|
33
50
|
|
34
51
|
def add_created_by
|
@@ -52,16 +69,17 @@ module Translatomatic::ResourceFile
|
|
52
69
|
line.strip!
|
53
70
|
next if line.length == 0
|
54
71
|
equal_idx = line.index("=")
|
72
|
+
colon_idx = line.index(":")
|
55
73
|
|
56
74
|
if line[0] == ?! || line[0] == ?#
|
57
75
|
# comment
|
58
76
|
# TODO: translate comments or keep originals?
|
59
77
|
next
|
60
|
-
elsif equal_idx.nil?
|
78
|
+
elsif equal_idx.nil? && colon_idx.nil?
|
61
79
|
@valid = false
|
62
80
|
return {}
|
63
81
|
end
|
64
|
-
name, value = line.split(/\s
|
82
|
+
name, value = line.split(/\s*[=:]\s*/, 2)
|
65
83
|
value = value.gsub("\\n", "\n") # convert \n to newlines
|
66
84
|
result[name] = value
|
67
85
|
end
|
@@ -1,8 +1,26 @@
|
|
1
1
|
module Translatomatic::ResourceFile
|
2
2
|
|
3
|
-
#
|
3
|
+
# @!visibility private
|
4
|
+
module XCodeStringsLocalePath
|
5
|
+
|
6
|
+
# (see Translatomatic::ResourceFile::Base#locale_path)
|
7
|
+
# @note localization files in XCode use the following file name
|
8
|
+
# convention: Project/locale.lproj/filename
|
9
|
+
def locale_path(locale)
|
10
|
+
if path.to_s.match(/\/([-\w]+).lproj\/.+$/)
|
11
|
+
# xcode style
|
12
|
+
filename = path.basename
|
13
|
+
path.parent.parent + (locale.to_s + ".lproj") + filename
|
14
|
+
else
|
15
|
+
super(locale)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# XCode strings resource file
|
4
21
|
# @see https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html
|
5
22
|
class XCodeStrings < Base
|
23
|
+
include Translatomatic::ResourceFile::XCodeStringsLocalePath
|
6
24
|
|
7
25
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
8
26
|
def self.extensions
|
@@ -16,19 +34,6 @@ module Translatomatic::ResourceFile
|
|
16
34
|
@properties = @path.exist? ? read(@path) : {}
|
17
35
|
end
|
18
36
|
|
19
|
-
# (see Translatomatic::ResourceFile::Base#locale_path)
|
20
|
-
# @note localization files in XCode use the following file name
|
21
|
-
# convention: Project/locale.lproj/filename
|
22
|
-
def locale_path(locale)
|
23
|
-
if path.to_s.match(/\/([-\w]+).lproj\/.+.strings$/)
|
24
|
-
# xcode style
|
25
|
-
filename = path.basename
|
26
|
-
path.parent.parent + (locale.to_s + ".lproj") + filename
|
27
|
-
else
|
28
|
-
super(locale)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
37
|
# (see Translatomatic::ResourceFile::Base#save)
|
33
38
|
def save(target = path, options = {})
|
34
39
|
out = ""
|
@@ -56,6 +61,10 @@ module Translatomatic::ResourceFile
|
|
56
61
|
key, value = entry
|
57
62
|
result[unescape(key)] = unescape(value)
|
58
63
|
end
|
64
|
+
|
65
|
+
if uncommented.strip.length > 0 && key_values.length == 0
|
66
|
+
@valid = false
|
67
|
+
end
|
59
68
|
result
|
60
69
|
end
|
61
70
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Translatomatic::ResourceFile
|
2
|
+
# XML resource file
|
2
3
|
class XML < Base
|
3
4
|
|
4
5
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
@@ -9,7 +10,8 @@ module Translatomatic::ResourceFile
|
|
9
10
|
# (see Translatomatic::ResourceFile::Base#initialize)
|
10
11
|
def initialize(path, locale = nil)
|
11
12
|
super(path, locale)
|
12
|
-
@valid = true
|
13
|
+
@valid = true
|
14
|
+
@nodemap = {}
|
13
15
|
@properties = @path.exist? ? read(@path) : {}
|
14
16
|
end
|
15
17
|
|
@@ -20,26 +22,36 @@ module Translatomatic::ResourceFile
|
|
20
22
|
end
|
21
23
|
|
22
24
|
# (see Translatomatic::ResourceFile::Base#save)
|
23
|
-
def save(target = path, options = {})
|
24
|
-
if @doc
|
25
|
+
def save(target = path, options = {})
|
26
|
+
if @doc
|
25
27
|
add_created_by unless options[:no_created_by]
|
26
|
-
target.write(@doc.to_xml)
|
28
|
+
target.write(@doc.to_xml)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
private
|
31
|
-
|
32
|
-
def comment(text)
|
33
|
-
@doc.create_comment(text)
|
32
|
+
private
|
33
|
+
|
34
|
+
def comment(text)
|
35
|
+
@doc.create_comment(text)
|
34
36
|
end
|
37
|
+
|
38
|
+
def add_created_by
|
39
|
+
@created_by ||= @doc.root.add_previous_sibling(comment(created_by))
|
40
|
+
end
|
35
41
|
|
36
42
|
# initialize nodemap from nokogiri document
|
37
43
|
# returns property hash
|
38
|
-
def init_nodemap(doc)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
44
|
+
def init_nodemap(doc)
|
45
|
+
if !doc.errors.empty?
|
46
|
+
log.error(doc.errors)
|
47
|
+
@valid = false
|
48
|
+
{}
|
49
|
+
else
|
50
|
+
# map of key1 => node, key2 => node, ...
|
51
|
+
@nodemap = create_nodemap(doc)
|
52
|
+
# map of key => node content
|
53
|
+
@nodemap.transform_values { |v| v.content }
|
54
|
+
end
|
43
55
|
end
|
44
56
|
|
45
57
|
# parse xml
|
@@ -47,9 +59,9 @@ module Translatomatic::ResourceFile
|
|
47
59
|
begin
|
48
60
|
# parse xml with nokogiri
|
49
61
|
@doc = read_doc(path)
|
50
|
-
init_nodemap(@doc)
|
62
|
+
init_nodemap(@doc)
|
51
63
|
rescue Exception => e
|
52
|
-
log.error(e.message)
|
64
|
+
log.error t("resource.error", message: e.message)
|
53
65
|
@valid = false
|
54
66
|
{}
|
55
67
|
end
|
@@ -63,11 +75,11 @@ module Translatomatic::ResourceFile
|
|
63
75
|
|
64
76
|
def create_nodemap(doc)
|
65
77
|
result = {}
|
66
|
-
text_nodes = doc.search(text_nodes_xpath)
|
78
|
+
text_nodes = doc.search(text_nodes_xpath)
|
67
79
|
idx = 1
|
68
|
-
text_nodes.each do |node|
|
80
|
+
text_nodes.each do |node|
|
69
81
|
next if whitespace?(node.content)
|
70
|
-
result["key#{idx}"] = node
|
82
|
+
result["key#{idx}"] = node
|
71
83
|
idx += 1
|
72
84
|
end
|
73
85
|
result
|
@@ -75,10 +87,10 @@ module Translatomatic::ResourceFile
|
|
75
87
|
|
76
88
|
def text_nodes_xpath
|
77
89
|
'//text()'
|
78
|
-
end
|
79
|
-
|
80
|
-
def whitespace?(text)
|
81
|
-
text == nil || text.strip.length == 0
|
90
|
+
end
|
91
|
+
|
92
|
+
def whitespace?(text)
|
93
|
+
text == nil || text.strip.length == 0
|
82
94
|
end
|
83
95
|
end # class
|
84
96
|
end # module
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
3
|
module Translatomatic::ResourceFile
|
4
|
+
# YAML resource file
|
5
|
+
# @see http://www.yaml.org/
|
4
6
|
class YAML < Base
|
5
7
|
|
6
8
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
@@ -34,7 +36,7 @@ module Translatomatic::ResourceFile
|
|
34
36
|
super(key, value)
|
35
37
|
|
36
38
|
hash = @data
|
37
|
-
path = key.split(/\./)
|
39
|
+
path = key.to_s.split(/\./)
|
38
40
|
last_key = path.pop
|
39
41
|
path.each { |i| hash = (hash[i] ||= {}) }
|
40
42
|
hash[last_key] = value
|
@@ -42,19 +44,51 @@ module Translatomatic::ResourceFile
|
|
42
44
|
|
43
45
|
# (see Translatomatic::ResourceFile::Base#save)
|
44
46
|
def save(target = path, options = {})
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
if @data
|
48
|
+
data = @data
|
49
|
+
data = data.transform_keys { locale.language } if ruby_i18n?
|
50
|
+
out = data.to_yaml
|
51
|
+
out.sub!(/^---\n/m, '')
|
52
|
+
out = comment(created_by) + "\n" + out unless options[:no_created_by]
|
53
|
+
target.write(out)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# (see Translatomatic::ResourceFile::Base#supports_variable_interpolation?)
|
58
|
+
def supports_variable_interpolation?
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
# (see Translatomatic::ResourceFile::Base#create_variable)
|
63
|
+
def create_variable(name)
|
64
|
+
return "%{#{name}}"
|
65
|
+
end
|
66
|
+
|
67
|
+
# (see Translatomatic::ResourceFile::Base#variable_regex)
|
68
|
+
def variable_regex
|
69
|
+
/\%\s*\{.*?\}/
|
48
70
|
end
|
49
71
|
|
50
72
|
private
|
51
73
|
|
74
|
+
# true if this resource file looks like a ruby i18n data file.
|
75
|
+
def ruby_i18n?
|
76
|
+
if @data && @data.length == 1
|
77
|
+
lang = @data.keys[0]
|
78
|
+
Translatomatic::Locale.new(lang).valid?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def comment(text)
|
83
|
+
"# #{text}\n"
|
84
|
+
end
|
85
|
+
|
52
86
|
def read
|
53
87
|
begin
|
54
88
|
@data = ::YAML.load_file(@path) || {}
|
55
89
|
flatten_data(@data)
|
56
90
|
rescue Exception => e
|
57
|
-
log.error(e.message)
|
91
|
+
log.error t("resource.error", message: e.message)
|
58
92
|
@valid = false
|
59
93
|
{}
|
60
94
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
module Translatomatic
|
3
|
+
# Provides methods to create resource files of various types.
|
3
4
|
module ResourceFile
|
4
5
|
class << self
|
5
6
|
include Translatomatic::Util
|
@@ -8,8 +9,8 @@ module Translatomatic
|
|
8
9
|
# Load a resource file. If locale is not specified, the locale of the
|
9
10
|
# file will be determined from the filename, or else the current default
|
10
11
|
# locale will be used.
|
11
|
-
# @param [String]
|
12
|
-
# @param [String]
|
12
|
+
# @param path [String] Path to the resource file
|
13
|
+
# @param locale [String] Locale of the resource file
|
13
14
|
# @return [Translatomatic::ResourceFile::Base] The resource file, or nil
|
14
15
|
# if the file type is unsupported.
|
15
16
|
def self.load(path, locale = nil)
|
@@ -17,7 +18,8 @@ module Translatomatic
|
|
17
18
|
modules.each do |mod|
|
18
19
|
# match on entire filename to support extensions containing locales
|
19
20
|
if extension_match(mod, path)
|
20
|
-
log.debug("
|
21
|
+
log.debug(t("resource.loading", file: path,
|
22
|
+
name: mod.name.demodulize))
|
21
23
|
file = mod.new(path, locale)
|
22
24
|
return file if file.valid?
|
23
25
|
end
|
@@ -26,7 +28,7 @@ module Translatomatic
|
|
26
28
|
end
|
27
29
|
|
28
30
|
# Find all resource files under the given directory. Follows symlinks.
|
29
|
-
# @param [String, Pathname]
|
31
|
+
# @param path [String, Pathname] The path to search from
|
30
32
|
# @return [Array<Translatomatic::ResourceFile>] Resource files found
|
31
33
|
def self.find(path, options = {})
|
32
34
|
files = []
|
@@ -71,6 +73,6 @@ require 'translatomatic/resource_file/text'
|
|
71
73
|
require 'translatomatic/resource_file/xml'
|
72
74
|
require 'translatomatic/resource_file/html'
|
73
75
|
require 'translatomatic/resource_file/markdown'
|
76
|
+
require 'translatomatic/resource_file/xcode_strings'
|
74
77
|
require 'translatomatic/resource_file/plist'
|
75
78
|
require 'translatomatic/resource_file/resw'
|
76
|
-
require 'translatomatic/resource_file/xcode_strings'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Translatomatic
|
2
|
+
# A string object with an associated locale.
|
2
3
|
class String
|
3
4
|
|
4
5
|
# @return [String] The string
|
@@ -16,7 +17,7 @@ module Translatomatic
|
|
16
17
|
attr_reader :offset
|
17
18
|
|
18
19
|
def initialize(value, locale, options = {})
|
19
|
-
@value = value || ''
|
20
|
+
@value = value.to_s || ''
|
20
21
|
@locale = Translatomatic::Locale.parse(locale)
|
21
22
|
@offset = options[:offset] || 0
|
22
23
|
@parent = options[:parent]
|
@@ -27,16 +28,21 @@ module Translatomatic
|
|
27
28
|
@value
|
28
29
|
end
|
29
30
|
|
31
|
+
# @return [Number] The length of the string
|
30
32
|
def length
|
31
33
|
@value.length
|
32
34
|
end
|
33
35
|
|
36
|
+
# @return [boolean] True if the string is empty
|
34
37
|
def empty?
|
35
38
|
@value.empty?
|
36
39
|
end
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
# Invokes value.match
|
42
|
+
# @param pattern [Regexp,String] The regex pattern to match
|
43
|
+
# @return [MatchData] Object describing the match, or nil if no match
|
44
|
+
def match(pattern)
|
45
|
+
@value.match(pattern)
|
40
46
|
end
|
41
47
|
|
42
48
|
# @return [boolean] true if this string is a substring of another string
|
@@ -58,38 +64,49 @@ module Translatomatic
|
|
58
64
|
# Find all sentences in the string
|
59
65
|
# @return [Array<Translatomatic::String] List of sentences
|
60
66
|
def sentences
|
61
|
-
|
67
|
+
substrings(sentence_regex)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Find all substrings matching the given regex
|
71
|
+
# @return [Array<Translatomatic::String] List of substrings
|
72
|
+
def substrings(regex)
|
73
|
+
matches = matches(@value, regex)
|
62
74
|
strings = []
|
63
|
-
|
64
|
-
|
75
|
+
matches.each do |match|
|
76
|
+
substring = match.to_s
|
65
77
|
# find leading and trailing whitespace
|
66
|
-
next if
|
78
|
+
next if substring.length == 0
|
67
79
|
|
68
|
-
parts =
|
80
|
+
parts = substring.match(/\A(\s*)(.*?)(\s*)\z/m).to_a
|
69
81
|
value = parts[2]
|
82
|
+
offset = match.offset(0)[0]
|
70
83
|
offset += parts[1].length # leading whitespace
|
71
84
|
strings << self.class.new(value, locale, offset: offset, parent: self)
|
72
|
-
offset += value.length + parts[3].length
|
73
85
|
end
|
74
86
|
|
75
|
-
# return [self] if there's only one
|
87
|
+
# return [self] if there's only one substring and it's equal to self
|
76
88
|
strings.length == 1 && strings[0].eql?(self) ? [self] : strings
|
77
89
|
end
|
78
90
|
|
91
|
+
# @return [boolean] true if other is a {Translatomatic::String} with
|
92
|
+
# the same value and locale.
|
79
93
|
def eql?(other)
|
80
94
|
other.kind_of?(Translatomatic::String) && other.hash == hash
|
81
95
|
end
|
82
96
|
|
97
|
+
# (see #eql?)
|
83
98
|
def ==(other)
|
84
99
|
eql?(other)
|
85
100
|
end
|
86
101
|
|
102
|
+
# @!visibility private
|
87
103
|
def hash
|
88
104
|
[value, locale].hash
|
89
105
|
end
|
90
106
|
|
91
107
|
private
|
92
108
|
|
109
|
+
# @!visibility private
|
93
110
|
class Script
|
94
111
|
attr_reader :language
|
95
112
|
attr_reader :delimiter # sentence delimiter
|
@@ -141,13 +158,24 @@ module Translatomatic
|
|
141
158
|
@script_data = script_data
|
142
159
|
end
|
143
160
|
|
161
|
+
def matches(s, re)
|
162
|
+
start_at = 0
|
163
|
+
matches = []
|
164
|
+
while(m = s.match(re, start_at))
|
165
|
+
break if m.to_s.empty?
|
166
|
+
matches.push(m)
|
167
|
+
start_at = m.end(0)
|
168
|
+
end
|
169
|
+
matches
|
170
|
+
end
|
171
|
+
|
144
172
|
def sentence_regex
|
145
173
|
script = script_data
|
146
174
|
if script.trailing_space
|
147
|
-
regex = /.*?(?:#{script.delimiter}\s
|
175
|
+
regex = /.*?(?:#{script.delimiter}\s+|\z)/m
|
148
176
|
else
|
149
177
|
# no trailing space after delimiter
|
150
|
-
regex = /.*?(?:#{script.delimiter}
|
178
|
+
regex = /.*?(?:#{script.delimiter}|\z)/m
|
151
179
|
end
|
152
180
|
end
|
153
181
|
|
@@ -3,14 +3,13 @@ module Translatomatic::TMX
|
|
3
3
|
class Document
|
4
4
|
|
5
5
|
# Create a new instance
|
6
|
-
# @param [Array<TranslationUnit>] A list of translation units
|
7
|
-
# @param [Locale] Source locale
|
8
|
-
# @return
|
9
|
-
def initialize(units, source_locale
|
6
|
+
# @param units [Array<TranslationUnit>] A list of translation units
|
7
|
+
# @param source_locale [Locale] Source locale
|
8
|
+
# @return [Translatomatic::TMX::Document] a new TMX object
|
9
|
+
def initialize(units, source_locale)
|
10
10
|
units = [units] unless units.kind_of?(Array)
|
11
11
|
@units = units
|
12
12
|
@source_locale = source_locale
|
13
|
-
@origin = origin
|
14
13
|
end
|
15
14
|
|
16
15
|
# @return [String] An XML string
|
@@ -25,7 +24,7 @@ module Translatomatic::TMX
|
|
25
24
|
segtype: "phrase", # default segtype
|
26
25
|
adminlang: @source_locale.to_s,
|
27
26
|
srclang: @source_locale.to_s,
|
28
|
-
"o-
|
27
|
+
"o-tmf": DEFAULT_OTMF
|
29
28
|
)
|
30
29
|
xml.body { tmx_body(xml) }
|
31
30
|
end
|
@@ -34,20 +33,18 @@ module Translatomatic::TMX
|
|
34
33
|
end
|
35
34
|
|
36
35
|
# Create a TMX document from the given converter
|
37
|
-
# @param [Array<Translatomatic::Model::Text>] List of texts
|
36
|
+
# @param texts [Array<Translatomatic::Model::Text>] List of texts
|
38
37
|
# @return [Translatomatic::TMX::Document] TMX document
|
39
38
|
def self.from_texts(texts)
|
40
39
|
# group texts by from_text_id to create units
|
41
40
|
# source_locale: use from_text.locale
|
42
41
|
# origin: use text.translator
|
43
|
-
origins = texts.collect { |i| i.translator }.compact.uniq
|
44
|
-
raise "Multiple origins in texts" if origins.length > 1
|
45
42
|
sources = texts.select { |i| i.from_text.nil? }
|
46
43
|
source_locales = sources.collect { |i| i.locale }.uniq
|
47
|
-
raise "
|
44
|
+
raise t("tmx.multiple_locales") if source_locales.length > 1
|
48
45
|
units = units_from_texts(texts)
|
49
46
|
|
50
|
-
return new(units, source_locales[0]
|
47
|
+
return new(units, source_locales[0])
|
51
48
|
end
|
52
49
|
|
53
50
|
def self.valid?(xml)
|
@@ -63,6 +60,7 @@ module Translatomatic::TMX
|
|
63
60
|
end
|
64
61
|
|
65
62
|
TMX_DTD = "http://www.ttt.org/oscarstandards/tmx/tmx14.dtd"
|
63
|
+
DEFAULT_OTMF = "Translatomatic"
|
66
64
|
|
67
65
|
def tmx_body(xml)
|
68
66
|
@units.each do |unit|
|
@@ -88,7 +86,8 @@ module Translatomatic::TMX
|
|
88
86
|
|
89
87
|
# create list of Translation Units
|
90
88
|
texts_by_from_id.values.collect do |list|
|
91
|
-
|
89
|
+
strings = list.uniq.collect { |i| string(i.value, i.locale) }
|
90
|
+
tmx_unit(strings)
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
@@ -1,10 +1,14 @@
|
|
1
1
|
module Translatomatic::TMX
|
2
|
+
# A TMX Translation Unit.
|
3
|
+
# A translation unit contains a list of strings, and is part of a TMX
|
4
|
+
# document.
|
5
|
+
# @see Translatomatic::TMX::Document
|
2
6
|
class TranslationUnit
|
3
7
|
|
4
8
|
# @return [Array<Translatomatic::String>] Strings in this translation unit
|
5
9
|
attr_reader :strings
|
6
10
|
|
7
|
-
# @param [Array<Translatomatic::String>]
|
11
|
+
# @param strings [Array<Translatomatic::String>] List of strings
|
8
12
|
def initialize(strings)
|
9
13
|
@strings = strings || []
|
10
14
|
end
|
data/lib/translatomatic/tmx.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Translatomatic
|
2
|
+
# Data object describing a text translation
|
3
|
+
class Translation
|
4
|
+
# @return [Translatomatic::String] original string
|
5
|
+
attr_reader :original
|
6
|
+
|
7
|
+
# @return [Translatomatic::String] translated string
|
8
|
+
attr_accessor :result
|
9
|
+
|
10
|
+
# @return [Symbol] The name of the translator
|
11
|
+
attr_reader :translator
|
12
|
+
|
13
|
+
# @return [boolean] True if this translation came from the database
|
14
|
+
attr_reader :from_database
|
15
|
+
|
16
|
+
def initialize(original, result, translator = nil, from_database = false)
|
17
|
+
@original = original
|
18
|
+
@result = result
|
19
|
+
@translator = translator
|
20
|
+
@from_database = from_database
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def string(string)
|
26
|
+
string.kind_of?(Translatomatic::String) ? string : Translatomatic::String.new(string)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|