lara-sdk 1.0.9 → 1.2.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.
- checksums.yaml +4 -4
- data/lib/lara/client.rb +8 -2
- data/lib/lara/models/text.rb +166 -3
- data/lib/lara/styleguides.rb +25 -0
- data/lib/lara/translator.rb +58 -4
- data/lib/lara/version.rb +1 -1
- data/lib/lara.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a959c719f2393f4626f029c7116d426f1402889baeaea48a16800fbb58cd229
|
|
4
|
+
data.tar.gz: 54b9f604df73458c8abebb16ecce4389dcf4486f255d53187e3ad8dd7d2145c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0d29539cdb0b1fe5add2b2f3200b812666d1edd1c0ebac1d77604f9c696f1f791cac76a791a0fedf7d75d6c263086090b57116705c477f1d9455ae27bb2e4c67
|
|
7
|
+
data.tar.gz: 29de437c146d524cca9b29a198ebbdb3426e8bf258a073d72e9740efedcd84edb83d01156870f3a461b1d62fcb144cb52b27c178bb51a8d7b7b521593d60ecff
|
data/lib/lara/client.rb
CHANGED
|
@@ -226,8 +226,14 @@ module Lara
|
|
|
226
226
|
end
|
|
227
227
|
|
|
228
228
|
def parse_json(body)
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
return {} if body.nil? || body.empty?
|
|
230
|
+
|
|
231
|
+
parsed = JSON.parse(body)
|
|
232
|
+
if parsed.is_a?(Hash) && parsed.key?("content")
|
|
233
|
+
inner = parsed["content"]
|
|
234
|
+
return inner if inner.is_a?(Hash) || inner.is_a?(Array)
|
|
235
|
+
end
|
|
236
|
+
parsed
|
|
231
237
|
end
|
|
232
238
|
|
|
233
239
|
def parse_stream_response(body, &block)
|
data/lib/lara/models/text.rb
CHANGED
|
@@ -39,6 +39,99 @@ module Lara
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
class DetectedProfanity < Base
|
|
43
|
+
attr_reader :text, :start_char_index, :end_char_index, :score
|
|
44
|
+
|
|
45
|
+
def initialize(text:, start_char_index:, end_char_index:, score:)
|
|
46
|
+
super()
|
|
47
|
+
@text = text
|
|
48
|
+
@start_char_index = start_char_index
|
|
49
|
+
@end_char_index = end_char_index
|
|
50
|
+
@score = score
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class ProfanityDetectResult < Base
|
|
55
|
+
attr_reader :masked_text, :profanities, :error
|
|
56
|
+
|
|
57
|
+
def initialize(masked_text:, profanities: [], error: nil)
|
|
58
|
+
super()
|
|
59
|
+
@masked_text = masked_text
|
|
60
|
+
@profanities = profanities.map do |p|
|
|
61
|
+
DetectedProfanity.new(
|
|
62
|
+
text: p["text"] || p[:text],
|
|
63
|
+
start_char_index: p["start_char_index"] || p[:start_char_index],
|
|
64
|
+
end_char_index: p["end_char_index"] || p[:end_char_index],
|
|
65
|
+
score: p["score"] || p[:score]
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
@error = error
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Wraps profanity detection results for both target and (optionally) source text.
|
|
73
|
+
# Returned in TextResult#profanities when profanities_detect is set.
|
|
74
|
+
class ProfanitiesResult < Base
|
|
75
|
+
# @return [ProfanityDetectResult, Array<ProfanityDetectResult, nil>, nil]
|
|
76
|
+
attr_reader :target
|
|
77
|
+
# @return [ProfanityDetectResult, Array<ProfanityDetectResult, nil>, nil]
|
|
78
|
+
attr_reader :source
|
|
79
|
+
|
|
80
|
+
def initialize(target: nil, source: nil)
|
|
81
|
+
super()
|
|
82
|
+
@target = target
|
|
83
|
+
@source = source
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class StyleguideChange < Base
|
|
88
|
+
attr_reader :id, :original_translation, :refined_translation, :explanation
|
|
89
|
+
|
|
90
|
+
def initialize(id:, original_translation:, refined_translation:, explanation:)
|
|
91
|
+
super()
|
|
92
|
+
@id = id
|
|
93
|
+
@original_translation = original_translation
|
|
94
|
+
@refined_translation = refined_translation
|
|
95
|
+
@explanation = explanation
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def to_s
|
|
99
|
+
"StyleguideChange{id='#{id}', explanation='#{explanation}'}"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
class StyleguideResults < Base
|
|
104
|
+
attr_reader :original_translation, :changes
|
|
105
|
+
|
|
106
|
+
def initialize(original_translation:, changes: [])
|
|
107
|
+
super()
|
|
108
|
+
@original_translation = original_translation
|
|
109
|
+
@changes = changes
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def to_s
|
|
113
|
+
"StyleguideResults{changes=#{changes&.size || 0}}"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
class Styleguide < Base
|
|
118
|
+
attr_reader :id, :name, :content, :owner_id, :created_at, :updated_at
|
|
119
|
+
|
|
120
|
+
def initialize(id:, name:, content: nil, owner_id: nil, created_at: nil, updated_at: nil, **_kwargs)
|
|
121
|
+
super()
|
|
122
|
+
@id = id
|
|
123
|
+
@name = name
|
|
124
|
+
@content = content
|
|
125
|
+
@owner_id = owner_id
|
|
126
|
+
@created_at = Base.parse_time(created_at)
|
|
127
|
+
@updated_at = Base.parse_time(updated_at)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def to_s
|
|
131
|
+
"Styleguide{id='#{id}', name='#{name}'}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
42
135
|
class DetectPrediction < Base
|
|
43
136
|
attr_reader :language, :confidence
|
|
44
137
|
|
|
@@ -60,10 +153,20 @@ module Lara
|
|
|
60
153
|
end
|
|
61
154
|
end
|
|
62
155
|
|
|
156
|
+
class QualityEstimationResult < Base
|
|
157
|
+
attr_reader :score
|
|
158
|
+
|
|
159
|
+
def initialize(score:)
|
|
160
|
+
super()
|
|
161
|
+
@score = score
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
63
165
|
class TextResult < Base
|
|
64
166
|
attr_reader :content_type, :source_language, :translation,
|
|
65
167
|
:adapted_to, :glossaries,
|
|
66
|
-
:adapted_to_matches, :glossaries_matches
|
|
168
|
+
:adapted_to_matches, :glossaries_matches,
|
|
169
|
+
:profanities, :styleguide_results
|
|
67
170
|
|
|
68
171
|
def self.from_hash(hash)
|
|
69
172
|
return nil unless hash.is_a?(Hash)
|
|
@@ -78,6 +181,8 @@ module Lara
|
|
|
78
181
|
|
|
79
182
|
adapted_to_matches = convert_matches(hash["adapted_to_matches"], NGMemoryMatch)
|
|
80
183
|
glossaries_matches = convert_matches(hash["glossaries_matches"], NGGlossaryMatch)
|
|
184
|
+
profanities = convert_profanities(hash["profanities"])
|
|
185
|
+
styleguide_results = convert_styleguide_results(hash["styleguide_results"])
|
|
81
186
|
|
|
82
187
|
new(
|
|
83
188
|
content_type: hash["content_type"],
|
|
@@ -86,12 +191,15 @@ module Lara
|
|
|
86
191
|
adapted_to: hash["adapted_to"],
|
|
87
192
|
glossaries: hash["glossaries"],
|
|
88
193
|
adapted_to_matches: adapted_to_matches,
|
|
89
|
-
glossaries_matches: glossaries_matches
|
|
194
|
+
glossaries_matches: glossaries_matches,
|
|
195
|
+
profanities: profanities,
|
|
196
|
+
styleguide_results: styleguide_results
|
|
90
197
|
)
|
|
91
198
|
end
|
|
92
199
|
|
|
93
200
|
def initialize(content_type:, source_language:, translation:, adapted_to: nil, glossaries: nil,
|
|
94
|
-
adapted_to_matches: nil, glossaries_matches: nil
|
|
201
|
+
adapted_to_matches: nil, glossaries_matches: nil, profanities: nil,
|
|
202
|
+
styleguide_results: nil)
|
|
95
203
|
super()
|
|
96
204
|
@content_type = content_type
|
|
97
205
|
@source_language = source_language
|
|
@@ -100,6 +208,8 @@ module Lara
|
|
|
100
208
|
@glossaries = glossaries
|
|
101
209
|
@adapted_to_matches = adapted_to_matches
|
|
102
210
|
@glossaries_matches = glossaries_matches
|
|
211
|
+
@profanities = profanities
|
|
212
|
+
@styleguide_results = styleguide_results
|
|
103
213
|
end
|
|
104
214
|
|
|
105
215
|
class << self
|
|
@@ -119,6 +229,59 @@ module Lara
|
|
|
119
229
|
end
|
|
120
230
|
end
|
|
121
231
|
|
|
232
|
+
def convert_profanities(value)
|
|
233
|
+
return nil if value.nil?
|
|
234
|
+
return nil unless value.is_a?(Hash)
|
|
235
|
+
return nil unless value.key?("target") || value.key?("source")
|
|
236
|
+
|
|
237
|
+
ProfanitiesResult.new(
|
|
238
|
+
target: parse_profanity_value(value["target"]),
|
|
239
|
+
source: parse_profanity_value(value["source"])
|
|
240
|
+
)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def parse_profanity_value(value)
|
|
244
|
+
return nil if value.nil?
|
|
245
|
+
|
|
246
|
+
if value.is_a?(Hash)
|
|
247
|
+
ProfanityDetectResult.new(
|
|
248
|
+
masked_text: value["masked_text"],
|
|
249
|
+
profanities: value["profanities"] || [],
|
|
250
|
+
error: value["error"]
|
|
251
|
+
)
|
|
252
|
+
elsif value.is_a?(Array)
|
|
253
|
+
value.map do |v|
|
|
254
|
+
next nil if v.nil?
|
|
255
|
+
|
|
256
|
+
ProfanityDetectResult.new(
|
|
257
|
+
masked_text: v["masked_text"],
|
|
258
|
+
profanities: v["profanities"] || [],
|
|
259
|
+
error: v["error"]
|
|
260
|
+
)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def convert_styleguide_results(value)
|
|
266
|
+
return nil if value.nil?
|
|
267
|
+
return nil unless value.is_a?(Hash)
|
|
268
|
+
|
|
269
|
+
original_translation = value["original_translation"]
|
|
270
|
+
changes = (value["changes"] || []).map do |c|
|
|
271
|
+
StyleguideChange.new(
|
|
272
|
+
id: c["id"],
|
|
273
|
+
original_translation: c["original_translation"],
|
|
274
|
+
refined_translation: c["refined_translation"],
|
|
275
|
+
explanation: c["explanation"]
|
|
276
|
+
)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
StyleguideResults.new(
|
|
280
|
+
original_translation: original_translation,
|
|
281
|
+
changes: changes
|
|
282
|
+
)
|
|
283
|
+
end
|
|
284
|
+
|
|
122
285
|
def build_match(klass, h)
|
|
123
286
|
case klass.name.split("::").last
|
|
124
287
|
when "NGMemoryMatch"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lara
|
|
4
|
+
class Styleguides
|
|
5
|
+
def initialize(client)
|
|
6
|
+
@client = client
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# @return [Array<Lara::Models::Styleguide>]
|
|
10
|
+
def list
|
|
11
|
+
(@client.get("/v2/styleguides") || []).map do |h|
|
|
12
|
+
Lara::Models::Styleguide.new(**h.transform_keys(&:to_sym))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @return [Lara::Models::Styleguide,nil]
|
|
17
|
+
def get(id)
|
|
18
|
+
Lara::Models::Styleguide.new(**@client.get("/v2/styleguides/#{id}").transform_keys(&:to_sym))
|
|
19
|
+
rescue Lara::LaraApiError => e
|
|
20
|
+
return nil if e.status_code == 404
|
|
21
|
+
|
|
22
|
+
raise
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/lara/translator.rb
CHANGED
|
@@ -28,12 +28,13 @@ module Lara
|
|
|
28
28
|
connection_timeout: connection_timeout, read_timeout: read_timeout)
|
|
29
29
|
@memories = Memories.new(@client)
|
|
30
30
|
@glossaries = Glossaries.new(@client)
|
|
31
|
+
@styleguides = Styleguides.new(@client)
|
|
31
32
|
@documents = Documents.new(@client)
|
|
32
33
|
@images = Images.new(@client)
|
|
33
34
|
@audio = AudioTranslator.new(@client)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
attr_reader :client, :memories, :glossaries, :documents, :images, :audio
|
|
37
|
+
attr_reader :client, :memories, :glossaries, :styleguides, :documents, :images, :audio
|
|
37
38
|
|
|
38
39
|
# Translates text with optional tuning parameters.
|
|
39
40
|
# @param text [String, Array<String>, Array<Lara::Models::TextBlock>]
|
|
@@ -55,12 +56,17 @@ module Lara
|
|
|
55
56
|
# @param reasoning [Boolean] When true with a block, yields partial results during reasoning
|
|
56
57
|
# @param headers [Hash,nil]
|
|
57
58
|
# @param metadata [String, Hash, nil]
|
|
59
|
+
# @param profanities_detect [String,nil] One of "target", "source_target"
|
|
60
|
+
# @param profanities_handling [String,nil] One of "detect", "avoid", "hide" (default: "hide" when profanities_detect is set)
|
|
58
61
|
# @yield [Lara::Models::TextResult] Partial translation result (only when reasoning is true)
|
|
59
62
|
# @return [Lara::Models::TextResult] Final translation result
|
|
60
63
|
def translate(text, target:, source: nil, source_hint: nil, adapt_to: nil, glossaries: nil,
|
|
61
64
|
instructions: nil, content_type: nil, multiline: true, timeout_ms: nil,
|
|
62
65
|
priority: nil, use_cache: nil, cache_ttl_s: nil, no_trace: false, verbose: false,
|
|
63
|
-
style: nil, reasoning: false, headers: nil, metadata: nil,
|
|
66
|
+
style: nil, reasoning: false, headers: nil, metadata: nil,
|
|
67
|
+
profanities_detect: nil, profanities_handling: nil,
|
|
68
|
+
styleguide_id: nil, styleguide_reasoning: nil,
|
|
69
|
+
styleguide_explanation_language: nil, &callback)
|
|
64
70
|
q = normalize_text_input(text)
|
|
65
71
|
|
|
66
72
|
use_cache_value = case use_cache
|
|
@@ -86,7 +92,12 @@ module Lara
|
|
|
86
92
|
verbose: verbose,
|
|
87
93
|
style: style,
|
|
88
94
|
reasoning: reasoning,
|
|
89
|
-
metadata: metadata
|
|
95
|
+
metadata: metadata,
|
|
96
|
+
profanities_detect: profanities_detect,
|
|
97
|
+
profanities_handling: profanities_handling,
|
|
98
|
+
styleguide_id: styleguide_id,
|
|
99
|
+
styleguide_reasoning: styleguide_reasoning,
|
|
100
|
+
styleguide_explanation_language: styleguide_explanation_language
|
|
90
101
|
}.compact
|
|
91
102
|
|
|
92
103
|
request_headers = {}
|
|
@@ -112,7 +123,7 @@ module Lara
|
|
|
112
123
|
body[:passlist] = passlist if passlist&.any?
|
|
113
124
|
body = body.compact
|
|
114
125
|
|
|
115
|
-
result = @client.post("/v2/detect", body: body)
|
|
126
|
+
result = @client.post("/v2/detect/language", body: body)
|
|
116
127
|
Lara::Models::DetectResult.new(
|
|
117
128
|
language: result["language"],
|
|
118
129
|
content_type: result["content_type"],
|
|
@@ -120,6 +131,49 @@ module Lara
|
|
|
120
131
|
)
|
|
121
132
|
end
|
|
122
133
|
|
|
134
|
+
VALID_CONTENT_TYPES = %w[text/plain text/html text/xml application/xliff+xml].freeze
|
|
135
|
+
|
|
136
|
+
# Detects profanities in the given text.
|
|
137
|
+
# @param text [String] Text to check for profanities
|
|
138
|
+
# @param language [String] Language code (e.g. "en")
|
|
139
|
+
# @param content_type [String] One of "text/plain", "text/html", "text/xml", "application/xliff+xml"
|
|
140
|
+
# @return [Lara::Models::ProfanityDetectResult]
|
|
141
|
+
def detect_profanities(text, language:, content_type: "text/plain")
|
|
142
|
+
unless VALID_CONTENT_TYPES.include?(content_type)
|
|
143
|
+
raise ArgumentError, "Invalid content_type '#{content_type}'. Must be one of: #{VALID_CONTENT_TYPES.join(', ')}"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
body = { text: text, language: language, content_type: content_type }
|
|
147
|
+
result = @client.post("/v2/detect/profanities", body: body)
|
|
148
|
+
Lara::Models::ProfanityDetectResult.new(
|
|
149
|
+
masked_text: result["masked_text"],
|
|
150
|
+
profanities: result["profanities"] || [],
|
|
151
|
+
error: result["error"]
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Estimates translation quality for a sentence pair (or batch of pairs).
|
|
156
|
+
# @param source [String]
|
|
157
|
+
# @param target [String]
|
|
158
|
+
# @param sentence [String, Array<String>]
|
|
159
|
+
# @param translation [String, Array<String>]
|
|
160
|
+
# @return [Lara::Models::QualityEstimationResult, Array<Lara::Models::QualityEstimationResult>]
|
|
161
|
+
def quality_estimation(source:, target:, sentence:, translation:)
|
|
162
|
+
body = {
|
|
163
|
+
source: source,
|
|
164
|
+
target: target,
|
|
165
|
+
sentence: sentence,
|
|
166
|
+
translation: translation
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
result = @client.post("/v2/detect/quality-estimation", body: body)
|
|
170
|
+
if result.is_a?(Array)
|
|
171
|
+
result.map { |r| Lara::Models::QualityEstimationResult.new(score: r["score"] || r[:score]) }
|
|
172
|
+
else
|
|
173
|
+
Lara::Models::QualityEstimationResult.new(score: result["score"] || result[:score])
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
123
177
|
# Lists supported language codes.
|
|
124
178
|
def get_languages
|
|
125
179
|
@client.get("/v2/languages")
|
data/lib/lara/version.rb
CHANGED
data/lib/lara.rb
CHANGED
|
@@ -8,6 +8,7 @@ require_relative "lara/client"
|
|
|
8
8
|
require_relative "lara/translator"
|
|
9
9
|
require_relative "lara/memories"
|
|
10
10
|
require_relative "lara/glossaries"
|
|
11
|
+
require_relative "lara/styleguides"
|
|
11
12
|
require_relative "lara/s3_client"
|
|
12
13
|
require_relative "lara/documents"
|
|
13
14
|
require_relative "lara/images"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lara-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Translated
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -167,6 +167,7 @@ files:
|
|
|
167
167
|
- lib/lara/models/memories.rb
|
|
168
168
|
- lib/lara/models/text.rb
|
|
169
169
|
- lib/lara/s3_client.rb
|
|
170
|
+
- lib/lara/styleguides.rb
|
|
170
171
|
- lib/lara/translator.rb
|
|
171
172
|
- lib/lara/version.rb
|
|
172
173
|
homepage: https://laratranslate.com
|