translatomatic 0.1.1 → 0.1.2

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.
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