1 package com.acumenvelocity.ath.steps;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import com.acumenvelocity.ath.common.Const;
7 import com.acumenvelocity.ath.common.ControllerUtil;
8 import com.acumenvelocity.ath.common.Log;
9 import com.acumenvelocity.ath.common.OkapiUtil;
10 import com.acumenvelocity.ath.gct.v3.AthTranslation;
11
12 import net.sf.okapi.common.Event;
13 import net.sf.okapi.common.IParameters;
14 import net.sf.okapi.common.IResource;
15 import net.sf.okapi.common.MimeTypeMapper;
16 import net.sf.okapi.common.Util;
17 import net.sf.okapi.common.annotation.AltTranslationsAnnotation;
18 import net.sf.okapi.common.query.MatchType;
19 import net.sf.okapi.common.resource.ISegments;
20 import net.sf.okapi.common.resource.ITextUnit;
21 import net.sf.okapi.common.resource.Segment;
22 import net.sf.okapi.common.resource.TextContainer;
23 import net.sf.okapi.common.resource.TextFragment;
24 import net.sf.okapi.common.resource.TextFragmentUtil;
25 import net.sf.okapi.lib.translation.QueryUtil;
26
27 public class BatchMtStep extends BaseTuBatchProcessingStep {
28
29 private BatchMtParameters params = new BatchMtParameters();
30 private final List<String> sourceSegments = new ArrayList<>();
31 private final List<SegmentInfo> segmentInfos = new ArrayList<>();
32 private final QueryUtil qutil = new QueryUtil();
33
34 @Override
35 public String getName() {
36 return "Batch Google Cloud Translation v3";
37 }
38
39 @Override
40 public String getDescription() {
41 return "Translates a batch of collected TU segments with the "
42 + "Google Cloud Translate v3 service";
43 }
44
45 @Override
46 public BatchMtParameters getParameters() {
47 return params;
48 }
49
50 @Override
51 public void setParameters(IParameters params) {
52 this.params = (BatchMtParameters) params;
53 }
54
55 @Override
56 protected void clear() {
57 sourceSegments.clear();
58 segmentInfos.clear();
59 }
60
61
62
63
64 private void preProcessTextUnit(ITextUnit tu) {
65 TextContainer source = tu.getSource();
66
67 if (source == null) {
68 Log.error(getClass(), "Source of TU '{}' is null", tu.getId());
69 return;
70 }
71
72 TextContainer target = tu.getTarget(getTargetLocale());
73 ISegments targetSegments = target == null ? null : target.getSegments();
74
75
76 for (Segment segment : source.getSegments()) {
77 TextFragment content = segment.getContent();
78
79
80 if (content == null || content.isEmpty()) {
81 Log.trace(getClass(), "Skipping empty segment in TU '{}'", tu.getId());
82 continue;
83 }
84
85 if (targetSegments != null) {
86 Segment tseg = targetSegments.get(segment.getId());
87
88 if (tseg != null && tseg.getContent() != null && !tseg.getContent().isEmpty()) {
89
90 continue;
91 }
92 }
93
94 String sourceText = null;
95
96 if (params.isMtSendPlainText()) {
97 sourceText = content.getText();
98 params.setMimeType(MimeTypeMapper.PLAIN_TEXT_MIME_TYPE);
99
100 } else {
101 sourceText = qutil.toCodedHTML(content);
102 params.setMimeType(MimeTypeMapper.HTML_MIME_TYPE);
103 }
104
105 sourceSegments.add(sourceText);
106
107
108 segmentInfos.add(new SegmentInfo(tu, segment.getId()));
109
110 Log.trace(getClass(), "Collected segment [{}]: '{}'",
111 sourceSegments.size() - 1, sourceText);
112 }
113
114 }
115
116
117
118
119 private void postProcessTextUnits(List<String> targetSegments) {
120 if (Util.isEmpty(targetSegments)) {
121 Log.warn(getClass(), "No evaluation results available");
122 return;
123 }
124
125 if (targetSegments.size() != segmentInfos.size()) {
126 Log.error(getClass(), "Mismatch: {} target segments, but {} segment infos",
127 targetSegments.size(), segmentInfos.size());
128
129 return;
130 }
131
132
133 for (int i = 0; i < targetSegments.size(); i++) {
134 String targetText = targetSegments.get(i);
135 SegmentInfo segInfo = segmentInfos.get(i);
136
137 ITextUnit tu = segInfo.textUnit;
138 TextContainer source = tu.getSource();
139 String segmentId = segInfo.segmentId;
140
141
142 TextContainer target = tu.getTarget(getTargetLocale());
143
144 if (target == null) {
145 target = tu.createTarget(getTargetLocale(), false, IResource.COPY_SEGMENTATION);
146 Log.trace(getClass(), "Created target container for TU '{}'", tu.getId());
147 }
148
149
150 Segment sseg = source.getSegments().get(segmentId);
151 Segment tseg = target.getSegments().get(segmentId);
152
153 if (tseg == null) {
154 tseg = new Segment(segmentId);
155 target.append(tseg);
156
157 Log.trace(getClass(), "Created target segment '{}' in TU '{}'", segmentId, tu.getId());
158 }
159
160 TextFragment targetTf;
161
162 if (params.isMtSendPlainText()) {
163 targetTf = new TextFragment(targetText);
164
165 } else {
166 targetTf = qutil.fromCodedHTMLToFragment(targetText, null);
167 }
168
169 TextFragment segSource = sseg.getContent();
170
171 OkapiUtil.removeExtraCodes(segSource.getCodes(), targetTf);
172
173
174 TextFragmentUtil.alignAndCopyCodeMetadata(segSource, targetTf, true, true);
175
176
177 OkapiUtil.rearrangeCodes(segSource.getCodes(), targetTf);
178
179 tseg.setContent(targetTf);
180
181
182 AltTranslationsAnnotation ata = new AltTranslationsAnnotation();
183
184 ata.add(getSourceLocale(), getTargetLocale(), sseg.getContent(), sseg.getContent(), targetTf,
185 MatchType.MT, 95, Const.MT_PROVIDER_GOOGLE_MT_V3, 95, 95);
186
187 tseg.setAnnotation(ata);
188 }
189
190 }
191
192 @Override
193 protected void processTuEvents(List<Event> tuEvents) {
194 for (Event tue : tuEvents) {
195 ITextUnit tu = tue.getTextUnit();
196 preProcessTextUnit(tu);
197 }
198
199 Log.info(getClass(), "Collected {} source segments from {} text units",
200 sourceSegments.size(), tuEvents.size());
201
202 List<String> targetSegments = AthTranslation.translateBatch(
203 sourceSegments,
204 getSourceLocale().toString(),
205 getTargetLocale().toString(),
206
207 params.isMtSendPlainText()
208 ? MimeTypeMapper.PLAIN_TEXT_MIME_TYPE
209 : MimeTypeMapper.HTML_MIME_TYPE,
210
211 ControllerUtil.getProjectId(),
212 params.getProjectLocation(),
213 params.getModelId(),
214 params.getGlossaryId());
215
216
217
218
219
220
221
222 postProcessTextUnits(targetSegments);
223 }
224
225 }