translatomatic 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +19 -0
  3. data/.gitignore +0 -0
  4. data/.travis.yml +7 -7
  5. data/.yardopts +9 -0
  6. data/Gemfile +4 -4
  7. data/Guardfile +0 -0
  8. data/README.de.md +61 -16
  9. data/README.es.md +60 -15
  10. data/README.fr.md +61 -16
  11. data/README.it.md +60 -15
  12. data/README.ja.md +59 -14
  13. data/README.ko.md +137 -0
  14. data/README.md +58 -13
  15. data/README.ms.md +137 -0
  16. data/README.pt.md +137 -0
  17. data/README.ru.md +137 -0
  18. data/README.sv.md +137 -0
  19. data/README.zh.md +137 -0
  20. data/bin/setup +8 -8
  21. data/bin/translatomatic +6 -6
  22. data/bin/travis +1 -1
  23. data/config/locales/translatomatic/de.yml +104 -0
  24. data/config/locales/translatomatic/en.yml +101 -0
  25. data/config/locales/translatomatic/es.yml +105 -0
  26. data/config/locales/translatomatic/fr.yml +105 -0
  27. data/config/locales/translatomatic/it.yml +103 -0
  28. data/config/locales/translatomatic/ja.yml +102 -0
  29. data/config/locales/translatomatic/ko.yml +101 -0
  30. data/config/locales/translatomatic/ms.yml +103 -0
  31. data/config/locales/translatomatic/pt.yml +105 -0
  32. data/config/locales/translatomatic/ru.yml +103 -0
  33. data/config/locales/translatomatic/sv.yml +103 -0
  34. data/config/locales/translatomatic/zh.yml +102 -0
  35. data/db/migrate/201712170000_initial.rb +2 -1
  36. data/lib/translatomatic/cli/base.rb +73 -0
  37. data/lib/translatomatic/cli/common_options.rb +14 -0
  38. data/lib/translatomatic/cli/config.rb +81 -0
  39. data/lib/translatomatic/cli/database.rb +29 -0
  40. data/lib/translatomatic/cli/main.rb +112 -0
  41. data/lib/translatomatic/cli/translate.rb +146 -0
  42. data/lib/translatomatic/cli.rb +8 -216
  43. data/lib/translatomatic/config.rb +143 -0
  44. data/lib/translatomatic/converter.rb +196 -149
  45. data/lib/translatomatic/converter_stats.rb +18 -14
  46. data/lib/translatomatic/database.rb +35 -37
  47. data/lib/translatomatic/escaped_unicode.rb +1 -1
  48. data/lib/translatomatic/extractor/base.rb +2 -0
  49. data/lib/translatomatic/extractor/ruby.rb +1 -0
  50. data/lib/translatomatic/extractor.rb +1 -0
  51. data/lib/translatomatic/http_request.rb +43 -14
  52. data/lib/translatomatic/locale.rb +28 -4
  53. data/lib/translatomatic/logger.rb +21 -13
  54. data/lib/translatomatic/model/locale.rb +5 -1
  55. data/lib/translatomatic/model/text.rb +2 -0
  56. data/lib/translatomatic/model.rb +1 -0
  57. data/lib/translatomatic/option.rb +75 -10
  58. data/lib/translatomatic/progress_updater.rb +7 -3
  59. data/lib/translatomatic/resource_file/base.rb +41 -18
  60. data/lib/translatomatic/resource_file/html.rb +11 -14
  61. data/lib/translatomatic/resource_file/markdown.rb +13 -12
  62. data/lib/translatomatic/resource_file/plist.rb +3 -14
  63. data/lib/translatomatic/resource_file/properties.rb +21 -3
  64. data/lib/translatomatic/resource_file/resw.rb +1 -0
  65. data/lib/translatomatic/resource_file/text.rb +1 -0
  66. data/lib/translatomatic/resource_file/xcode_strings.rb +23 -14
  67. data/lib/translatomatic/resource_file/xml.rb +34 -22
  68. data/lib/translatomatic/resource_file/yaml.rb +39 -5
  69. data/lib/translatomatic/resource_file.rb +7 -5
  70. data/lib/translatomatic/string.rb +40 -12
  71. data/lib/translatomatic/tmx/document.rb +11 -12
  72. data/lib/translatomatic/tmx/translation_unit.rb +5 -1
  73. data/lib/translatomatic/tmx.rb +2 -0
  74. data/lib/translatomatic/translation.rb +30 -0
  75. data/lib/translatomatic/translation_result.rb +45 -45
  76. data/lib/translatomatic/translator/base.rb +128 -83
  77. data/lib/translatomatic/translator/frengly.rb +62 -57
  78. data/lib/translatomatic/translator/google.rb +35 -31
  79. data/lib/translatomatic/translator/microsoft.rb +41 -33
  80. data/lib/translatomatic/translator/my_memory.rb +68 -64
  81. data/lib/translatomatic/translator/yandex.rb +56 -39
  82. data/lib/translatomatic/translator.rb +99 -63
  83. data/lib/translatomatic/util.rb +31 -1
  84. data/lib/translatomatic/version.rb +4 -1
  85. data/lib/translatomatic.rb +17 -0
  86. data/translatomatic.gemspec +5 -4
  87. 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*=\s*/, 2)
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,4 +1,5 @@
1
1
  module Translatomatic::ResourceFile
2
+ # Windows resources file (XML)
2
3
  class RESW < XML
3
4
 
4
5
  # (see Translatomatic::ResourceFile::Base.extensions)
@@ -1,4 +1,5 @@
1
1
  module Translatomatic::ResourceFile
2
+ # Text resource file
2
3
  class Text < Base
3
4
 
4
5
  # (see Translatomatic::ResourceFile::Base.extensions)
@@ -1,8 +1,26 @@
1
1
  module Translatomatic::ResourceFile
2
2
 
3
- # XCode strings file
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
- # map of key1 => node, key2 => node, ...
40
- @nodemap = create_nodemap(doc)
41
- # map of key => node content
42
- @nodemap.transform_values { |v| v.content }
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
- out = @data.to_yaml
46
- out.sub!(/^---\n/m, '')
47
- target.write(out)
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] path Path to the resource file
12
- # @param [String] locale Locale of the resource file
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("attempting to load #{path.to_s} using #{mod.name.demodulize}")
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] path The path to search from
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
- def match(regex)
39
- @value.match(regex)
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
- sentences = @value.scan(sentence_regex)
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
- offset = 0
64
- sentences.each do |sentence|
75
+ matches.each do |match|
76
+ substring = match.to_s
65
77
  # find leading and trailing whitespace
66
- next if sentence.length == 0
78
+ next if substring.length == 0
67
79
 
68
- parts = sentence.match(/^(\s*)(.*?)(\s*)$/).to_a
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 sentence and it's equal to self
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 A new TMX object
9
- def initialize(units, source_locale, origin)
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-tmx": @origin
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 "Multiple source locales in texts" if source_locales.length > 1
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], origins[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
- tmx_unit(list.uniq.collect { |i| string(i.value, i.locale) })
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>] list of strings
11
+ # @param strings [Array<Translatomatic::String>] List of strings
8
12
  def initialize(strings)
9
13
  @strings = strings || []
10
14
  end
@@ -1,3 +1,5 @@
1
+ # Translation Memory Exchange
2
+ # @see https://en.wikipedia.org/wiki/Translation_Memory_eXchange
1
3
  module Translatomatic::TMX; end
2
4
 
3
5
  require 'translatomatic/tmx/translation_unit'
@@ -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