deepl-rb 3.8.0 → 3.9.0

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +1 -1
  3. data/CHANGELOG.md +23 -1
  4. data/README.md +213 -4
  5. data/VERSION +1 -1
  6. data/deepl-rb.gemspec +34 -6
  7. data/lib/deepl/document_api.rb +11 -1
  8. data/lib/deepl/requests/base.rb +55 -3
  9. data/lib/deepl/requests/document/upload.rb +50 -1
  10. data/lib/deepl/requests/translate.rb +4 -1
  11. data/lib/deepl/requests/translation_memory/base.rb +47 -0
  12. data/lib/deepl/requests/translation_memory/create_export.rb +41 -0
  13. data/lib/deepl/requests/translation_memory/create_import.rb +53 -0
  14. data/lib/deepl/requests/translation_memory/destroy.rb +37 -0
  15. data/lib/deepl/requests/translation_memory/download_export.rb +35 -0
  16. data/lib/deepl/requests/translation_memory/find.rb +38 -0
  17. data/lib/deepl/requests/translation_memory/find_job.rb +38 -0
  18. data/lib/deepl/requests/translation_memory/list.rb +5 -18
  19. data/lib/deepl/requests/translation_memory/segments.rb +46 -0
  20. data/lib/deepl/requests/translation_memory/storage_base.rb +47 -0
  21. data/lib/deepl/requests/translation_memory/upload_file.rb +47 -0
  22. data/lib/deepl/resources/translation_memory.rb +4 -1
  23. data/lib/deepl/resources/translation_memory_export.rb +37 -0
  24. data/lib/deepl/resources/translation_memory_import.rb +29 -0
  25. data/lib/deepl/resources/translation_memory_job.rb +142 -0
  26. data/lib/deepl/resources/translation_memory_segments.rb +78 -0
  27. data/lib/deepl/translation_memory_api.rb +293 -1
  28. data/lib/deepl/utils/time_parser.rb +26 -0
  29. data/lib/deepl.rb +31 -0
  30. data/lib/version.rb +1 -1
  31. data/spec/integration_tests/document_api_spec.rb +47 -0
  32. data/spec/integration_tests/integration_test_utils.rb +8 -0
  33. data/spec/integration_tests/translate_api_spec.rb +19 -0
  34. data/spec/integration_tests/translation_memory_api_spec.rb +192 -2
  35. data/spec/integration_tests/translation_memory_error_paths_spec.rb +68 -0
  36. data/spec/requests/document/upload_spec.rb +130 -0
  37. data/spec/requests/translate_spec.rb +55 -0
  38. data/spec/requests/translation_memory/create_export_spec.rb +37 -0
  39. data/spec/requests/translation_memory/create_import_spec.rb +61 -0
  40. data/spec/requests/translation_memory/destroy_spec.rb +36 -0
  41. data/spec/requests/translation_memory/download_export_spec.rb +54 -0
  42. data/spec/requests/translation_memory/find_job_spec.rb +37 -0
  43. data/spec/requests/translation_memory/find_spec.rb +36 -0
  44. data/spec/requests/translation_memory/segments_spec.rb +58 -0
  45. data/spec/requests/translation_memory/upload_file_spec.rb +55 -0
  46. data/spec/resources/translation_memory_export_spec.rb +38 -0
  47. data/spec/resources/translation_memory_import_spec.rb +30 -0
  48. data/spec/resources/translation_memory_job_spec.rb +109 -0
  49. data/spec/resources/translation_memory_segments_spec.rb +78 -0
  50. data/spec/resources/translation_memory_spec.rb +18 -1
  51. data/spec/support/managed_glossary.rb +48 -0
  52. data/spec/support/managed_translation_memory.rb +48 -0
  53. metadata +34 -3
@@ -0,0 +1,41 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class CreateExport < Base
10
+ attr_reader :translation_memory_id
11
+
12
+ def initialize(api, translation_memory_id, options = {})
13
+ super(api, options)
14
+ @translation_memory_id = translation_memory_id
15
+ end
16
+
17
+ def request
18
+ build_translation_memory_export(*execute_request_with_retries(post_request({})))
19
+ end
20
+
21
+ def to_s
22
+ "POST #{uri.request_uri}"
23
+ end
24
+
25
+ private
26
+
27
+ def build_translation_memory_export(request, response)
28
+ data = JSON.parse(response.body)
29
+ # The API answers 200 when it reused a previously completed export, and 202 when it
30
+ # started a new one.
31
+ reused_existing = response.code.to_i == 200
32
+ Resources::TranslationMemoryExport.new(data, reused_existing, request, response)
33
+ end
34
+
35
+ def path
36
+ "translation_memories/#{translation_memory_id}/export"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class CreateImport < Base
10
+ attr_reader :file_name, :content_length
11
+
12
+ def initialize(api, file_name, content_length, options = {}, additional_headers = {})
13
+ super(api, options, additional_headers)
14
+ @file_name = file_name
15
+ @content_length = content_length
16
+ @content_type = delete_option(:content_type)
17
+ @display_name = delete_option(:display_name)
18
+ end
19
+
20
+ def request
21
+ build_translation_memory_import(*execute_request_with_retries(post_request(payload)))
22
+ end
23
+
24
+ def details
25
+ "HTTP Headers: #{headers}\nPayload #{payload}"
26
+ end
27
+
28
+ def to_s
29
+ "POST #{uri.request_uri}"
30
+ end
31
+
32
+ private
33
+
34
+ def payload
35
+ source_file = { file_name: file_name, content_length: content_length }
36
+ source_file[:content_type] = @content_type if @content_type
37
+ payload = { source_file: source_file }
38
+ payload[:parameters] = { display_name: @display_name } if @display_name
39
+ payload
40
+ end
41
+
42
+ def build_translation_memory_import(request, response)
43
+ data = JSON.parse(response.body)
44
+ Resources::TranslationMemoryImport.new(data, request, response)
45
+ end
46
+
47
+ def path
48
+ 'translation_memories/import'
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class Destroy < Base
10
+ attr_reader :translation_memory_id
11
+
12
+ def initialize(api, translation_memory_id, options = {})
13
+ super(api, options)
14
+ @translation_memory_id = translation_memory_id
15
+ end
16
+
17
+ def request
18
+ build_response(*execute_request_with_retries(delete_request))
19
+ end
20
+
21
+ def to_s
22
+ "DELETE #{uri.request_uri}"
23
+ end
24
+
25
+ private
26
+
27
+ def build_response(_, _)
28
+ translation_memory_id
29
+ end
30
+
31
+ def path
32
+ "translation_memories/#{translation_memory_id}"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class DownloadExport < StorageBase
10
+ def initialize(api, download_url, output_file)
11
+ super(api, download_url)
12
+ @output_file = output_file
13
+ end
14
+
15
+ def request
16
+ extract_file(*execute_request_with_retries(get_request))
17
+ end
18
+
19
+ def to_s
20
+ "GET #{uri.request_uri}"
21
+ end
22
+
23
+ private
24
+
25
+ def get_request # rubocop:disable Naming/AccessorMethodName
26
+ Net::HTTP::Get.new(uri.request_uri, headers)
27
+ end
28
+
29
+ def extract_file(_request, response)
30
+ File.binwrite(@output_file, response.body)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class Find < Base
10
+ attr_reader :translation_memory_id
11
+
12
+ def initialize(api, translation_memory_id, options = {})
13
+ super(api, options)
14
+ @translation_memory_id = translation_memory_id
15
+ end
16
+
17
+ def request
18
+ build_translation_memory(*execute_request_with_retries(get_request))
19
+ end
20
+
21
+ def to_s
22
+ "GET #{uri.request_uri}"
23
+ end
24
+
25
+ private
26
+
27
+ def build_translation_memory(request, response)
28
+ data = JSON.parse(response.body)
29
+ Resources::TranslationMemory.new(data, request, response)
30
+ end
31
+
32
+ def path
33
+ "translation_memories/#{translation_memory_id}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class FindJob < Base
10
+ attr_reader :job_id
11
+
12
+ def initialize(api, job_id, options = {})
13
+ super(api, options)
14
+ @job_id = job_id
15
+ end
16
+
17
+ def request
18
+ build_job(*execute_request_with_retries(get_request))
19
+ end
20
+
21
+ def to_s
22
+ "GET #{uri.request_uri}"
23
+ end
24
+
25
+ private
26
+
27
+ def build_job(request, response)
28
+ data = JSON.parse(response.body)
29
+ Resources::TranslationMemoryJob.new(data, request, response)
30
+ end
31
+
32
+ def path
33
+ "translation_memories/jobs/#{job_id}"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -7,6 +7,8 @@ module DeepL
7
7
  module Requests
8
8
  module TranslationMemory
9
9
  class List < Base
10
+ SUPPORTED_OPTIONS = %w[page page_size].freeze
11
+
10
12
  def initialize(api, options = {})
11
13
  super
12
14
  end
@@ -21,11 +23,6 @@ module DeepL
21
23
 
22
24
  private
23
25
 
24
- def get_request # rubocop:disable Naming/AccessorMethodName
25
- http_headers = add_json_content_type(headers)
26
- Net::HTTP::Get.new(uri.request_uri, http_headers)
27
- end
28
-
29
26
  def build_translation_memory_list(request, response)
30
27
  data = JSON.parse(response.body)
31
28
  data['translation_memories'].map do |tm|
@@ -33,22 +30,12 @@ module DeepL
33
30
  end
34
31
  end
35
32
 
36
- def uri
37
- @uri ||= begin
38
- base_uri = URI("#{host}/v3/#{path}")
39
- query_string = build_query_string
40
- base_uri.query = query_string unless query_string.empty?
41
- base_uri
33
+ def query_params
34
+ SUPPORTED_OPTIONS.each_with_object({}) do |option_name, params|
35
+ params[option_name] = option(option_name).to_s if option?(option_name)
42
36
  end
43
37
  end
44
38
 
45
- def build_query_string
46
- params = {}
47
- params['page'] = option(:page).to_s if option?(:page)
48
- params['page_size'] = option(:page_size).to_s if option?(:page_size)
49
- URI.encode_www_form(params)
50
- end
51
-
52
39
  def path
53
40
  'translation_memories'
54
41
  end
@@ -0,0 +1,46 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class Segments < Base
10
+ SUPPORTED_OPTIONS = %w[page_size page_cursor filter_text filter_case_sensitive].freeze
11
+
12
+ attr_reader :translation_memory_id
13
+
14
+ def initialize(api, translation_memory_id, options = {})
15
+ super(api, options)
16
+ @translation_memory_id = translation_memory_id
17
+ end
18
+
19
+ def request
20
+ build_segments(*execute_request_with_retries(get_request))
21
+ end
22
+
23
+ def to_s
24
+ "GET #{uri.request_uri}"
25
+ end
26
+
27
+ private
28
+
29
+ def build_segments(request, response)
30
+ data = JSON.parse(response.body)
31
+ Resources::TranslationMemorySegments.new(data, request, response)
32
+ end
33
+
34
+ def query_params
35
+ SUPPORTED_OPTIONS.each_with_object({}) do |option_name, params|
36
+ params[option_name] = option(option_name).to_s if option?(option_name)
37
+ end
38
+ end
39
+
40
+ def path
41
+ "translation_memories/#{translation_memory_id}/segments"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ ##
10
+ # Common behaviour of the requests to a pre-signed storage URL handed out by the API, such
11
+ # as a translation memory upload or download URL. Those URLs point outside of the DeepL
12
+ # API, so they are requested over their own connection and the DeepL `Authorization` header
13
+ # is deliberately not sent.
14
+
15
+ class StorageBase < DeepL::Requests::Base
16
+ attr_reader :storage_url
17
+
18
+ def initialize(api, storage_url, options = {}, additional_headers = {})
19
+ super(api, options, additional_headers)
20
+ if storage_url.nil? || storage_url.empty?
21
+ raise Exceptions::Error, 'Storage URL must not be empty'
22
+ end
23
+
24
+ @storage_url = storage_url
25
+ end
26
+
27
+ private
28
+
29
+ def http_client
30
+ @http_client ||= begin
31
+ client = Net::HTTP.new(uri.host, uri.port)
32
+ client.use_ssl = uri.scheme == 'https'
33
+ client
34
+ end
35
+ end
36
+
37
+ def uri
38
+ @uri ||= URI(storage_url)
39
+ end
40
+
41
+ def headers
42
+ { 'User-Agent' => api.configuration.user_agent }.merge(@additional_headers)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Requests
8
+ module TranslationMemory
9
+ class UploadFile < StorageBase
10
+ DEFAULT_CONTENT_TYPE = 'application/xml'
11
+
12
+ attr_reader :file_content, :content_type
13
+
14
+ def initialize(api, upload_url, file_content, content_type = DEFAULT_CONTENT_TYPE)
15
+ super(api, upload_url)
16
+ @file_content = file_content
17
+ @content_type = content_type || DEFAULT_CONTENT_TYPE
18
+ end
19
+
20
+ def request
21
+ build_response(*execute_request_with_retries(put_request))
22
+ end
23
+
24
+ def details
25
+ "HTTP Headers: #{headers}\nPayload #{file_content.bytesize} byte(s)"
26
+ end
27
+
28
+ def to_s
29
+ "PUT #{uri.request_uri}"
30
+ end
31
+
32
+ private
33
+
34
+ def put_request
35
+ put_req = Net::HTTP::Put.new(uri.request_uri,
36
+ headers.merge('Content-Type' => content_type))
37
+ put_req.body = file_content
38
+ put_req
39
+ end
40
+
41
+ def build_response(_, _)
42
+ nil
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -6,7 +6,8 @@
6
6
  module DeepL
7
7
  module Resources
8
8
  class TranslationMemory < Base
9
- attr_reader :translation_memory_id, :name, :source_language, :target_languages, :segment_count
9
+ attr_reader :translation_memory_id, :name, :source_language, :target_languages,
10
+ :segment_count, :creation_time, :updated_time
10
11
 
11
12
  def initialize(translation_memory, *args)
12
13
  super(*args)
@@ -15,6 +16,8 @@ module DeepL
15
16
  @source_language = translation_memory['source_language']
16
17
  @target_languages = translation_memory['target_languages'] || []
17
18
  @segment_count = translation_memory['segment_count'] || 0
19
+ @creation_time = Utils::TimeParser.parse_optional_time(translation_memory['creation_time'])
20
+ @updated_time = Utils::TimeParser.parse_optional_time(translation_memory['updated_time'])
18
21
  end
19
22
 
20
23
  def to_s
@@ -0,0 +1,37 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Resources
8
+ ##
9
+ # A translation memory export job. Poll the job until it is finished to obtain the download
10
+ # URL of the exported TMX file.
11
+
12
+ class TranslationMemoryExport < Base
13
+ attr_reader :job_id, :translation_memory_id
14
+
15
+ def initialize(translation_memory_export, reused_existing, *args)
16
+ super(*args)
17
+ parameters = translation_memory_export['parameters'] || {}
18
+ @job_id = translation_memory_export['job_id']
19
+ @translation_memory_id = parameters['translation_memory_id']
20
+ @reused_existing = reused_existing
21
+ end
22
+
23
+ ##
24
+ # Checks if the API reused a previously completed export instead of starting a new one.
25
+ #
26
+ # @return [true] if so
27
+
28
+ def reused_existing?
29
+ @reused_existing
30
+ end
31
+
32
+ def to_s
33
+ "TranslationMemoryExport: ID: #{job_id}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Resources
8
+ ##
9
+ # A newly created translation memory import job. The TMX file must be uploaded to
10
+ # `upload_url` before `expires_at`, processing starts once the upload is detected.
11
+
12
+ class TranslationMemoryImport < Base
13
+ attr_reader :job_id, :upload_url, :expires_at
14
+
15
+ def initialize(translation_memory_import, *args)
16
+ super(*args)
17
+ @job_id = translation_memory_import['job_id']
18
+ @upload_url = translation_memory_import['upload_url']
19
+ @expires_at = Utils::TimeParser.parse_optional_time(
20
+ translation_memory_import['expires_at']
21
+ )
22
+ end
23
+
24
+ def to_s
25
+ "TranslationMemoryImport: ID: #{job_id}"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,142 @@
1
+ # Copyright 2026 DeepL SE (https://www.deepl.com)
2
+ # Use of this source code is governed by an MIT
3
+ # license that can be found in the LICENSE.md file.
4
+ # frozen_string_literal: true
5
+
6
+ module DeepL
7
+ module Resources
8
+ ##
9
+ # The outcome of a translation memory import or export job.
10
+
11
+ class TranslationMemoryJobResult
12
+ STATUS_AWAITING_INPUT = 'awaiting_input'
13
+ STATUS_PROCESSING = 'processing'
14
+ STATUS_COMPLETED = 'completed'
15
+ STATUS_DOWNLOADED = 'downloaded'
16
+ STATUS_FAILED = 'failed'
17
+ STATUS_EXPIRED = 'expired'
18
+
19
+ attr_reader :status, :required_action, :download_url, :expires_at, :error_message,
20
+ :translation_memory_id, :skipped_segment_count
21
+
22
+ def initialize(result)
23
+ status_metadata = result['status_metadata'] || {}
24
+ error = result['error'] || {}
25
+
26
+ @status = result['status']
27
+ @required_action = status_metadata['required_action']
28
+ @download_url = result['download_url']
29
+ @expires_at = Utils::TimeParser.parse_optional_time(result['expires_at'])
30
+ @error_message = error['message']
31
+ @translation_memory_id = result['translation_memory_id']
32
+ @skipped_segment_count = result['skipped_segment_count']
33
+ end
34
+
35
+ ##
36
+ # Checks if the job terminated. Note that this could be due to an error as well, but means
37
+ # no further waiting is necessary.
38
+ #
39
+ # @return [true] if so
40
+
41
+ def finished?
42
+ [STATUS_COMPLETED, STATUS_DOWNLOADED, STATUS_FAILED, STATUS_EXPIRED].include?(status)
43
+ end
44
+
45
+ ##
46
+ # Checks if the job is still waiting for the TMX file to be uploaded. Note that the API
47
+ # detects an upload asynchronously, so a job keeps reporting this status for a while after
48
+ # its file has been uploaded.
49
+ #
50
+ # @return [true] if so
51
+
52
+ def awaiting_input?
53
+ status == STATUS_AWAITING_INPUT
54
+ end
55
+
56
+ ##
57
+ # Checks if there was an error during the job, including it having expired.
58
+ #
59
+ # @return [true] if so
60
+
61
+ def error?
62
+ [STATUS_FAILED, STATUS_EXPIRED].include?(status)
63
+ end
64
+
65
+ def to_s
66
+ "TranslationMemoryJobResult: Status: #{status} - Error message: #{error_message}"
67
+ end
68
+ end
69
+
70
+ ##
71
+ # Status of a translation memory import or export job. The API returns exactly one result.
72
+
73
+ class TranslationMemoryJob < Base
74
+ OPERATION_IMPORT = 'import'
75
+ OPERATION_EXPORT = 'export'
76
+
77
+ attr_reader :job_id, :product, :operation, :creation_time, :updated_time, :results,
78
+ :translation_memory_id, :display_name, :source_content_type,
79
+ :source_content_length
80
+
81
+ def initialize(job, *args)
82
+ super(*args)
83
+ extract_basic_fields(job)
84
+ extract_parameters(job)
85
+ @results = (job['results'] || []).map { |result| TranslationMemoryJobResult.new(result) }
86
+ end
87
+
88
+ ##
89
+ # The single result of the job, or nil if the API returned none.
90
+ #
91
+ # @return [DeepL::Resources::TranslationMemoryJobResult, nil]
92
+
93
+ def result
94
+ results.first
95
+ end
96
+
97
+ def status
98
+ result&.status
99
+ end
100
+
101
+ def finished?
102
+ result ? result.finished? : false
103
+ end
104
+
105
+ def awaiting_input?
106
+ result ? result.awaiting_input? : false
107
+ end
108
+
109
+ def error?
110
+ result ? result.error? : false
111
+ end
112
+
113
+ def error_message
114
+ result&.error_message
115
+ end
116
+
117
+ def to_s
118
+ "TranslationMemoryJob: #{operation} - ID: #{job_id} - Status: #{status}"
119
+ end
120
+
121
+ private
122
+
123
+ def extract_basic_fields(job)
124
+ @job_id = job['job_id']
125
+ @product = job['product']
126
+ @operation = job['operation']
127
+ @creation_time = Utils::TimeParser.parse_optional_time(job['creation_time'])
128
+ @updated_time = Utils::TimeParser.parse_optional_time(job['updated_time'])
129
+ end
130
+
131
+ def extract_parameters(job)
132
+ parameters = job['parameters'] || {}
133
+ source_file = job['source_file'] || {}
134
+
135
+ @translation_memory_id = parameters['translation_memory_id']
136
+ @display_name = parameters['display_name']
137
+ @source_content_type = source_file['content_type']
138
+ @source_content_length = source_file['content_length']
139
+ end
140
+ end
141
+ end
142
+ end