Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Locked segments #1127

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/org/omegat/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,8 @@ MW_PROGRESS_TOOLTIP_PERCENTAGE=File: unique translated % (unique left) \

MW_JUMPING_LAST_ENTRY=Jumping to last edited segment...

MW_SEGMENT_LOCKED=Locked segment ({0})

# NOTE: segment start is assumed to end with "0000" string to overwrite
# with entry number. If zeros not detected, entry number will not be
# displayed
Expand Down Expand Up @@ -1801,6 +1803,7 @@ WG_SAVE_ORIGIN=Save origin of &translation
WG_INITIAL_SEGMENT_LOAD_COUNT=Initial number of loaded segments:
WG_INITIAL_SEGMENT_LOAD_COUNT_TOOLTIP=When a single file has more segments than this, additional segments will be loaded on-demand as you scroll.
WG_PARA_MARK=Paragraph delimiter:
WG_SUPPORT_LOCKED_SEGMENTS=Support for locked segments
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Allow segment locking" would be better for this one, if I understand the intent correctly.


# org.omegat.gui.preferences.view.TMMatchesPreferencesPanel.java
EXT_TMX_DESCRIPTION=Settings for tags originating from non-OmegaT TMX files:
Expand Down Expand Up @@ -2509,7 +2512,8 @@ COLOR_MARK_COMES_FROM_TM_MT=From MT memory
COLOR_MARK_COMES_FROM_TM_XICE=From ICE memory
COLOR_MARK_COMES_FROM_TM_X100PC=From 100% memory
COLOR_MARK_COMES_FROM_TM_XAUTO=From auto memory
COLOR_MARK_COMES_FROM_TM_XENFORCED=From enforced memory
# COLOR_MARK_COMES_FROM_TM_XENFORCED=From enforced memory
COLOR_LOCKED_SEGMENT=Locked segment
COLOR_PARAGRAPH_START=Paragraph delimitation
COLOR_REPLACE=Replace
COLOR_LANGUAGE_TOOLS=Language checker
Expand Down
5 changes: 5 additions & 0 deletions src/org/omegat/filters3/xml/xliff/XLIFFFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ public void tagStart(String path, Attributes atts) {
if ("/xliff/file/header".equals(path)) {
ignored = true;
}
if (path.endsWith("/target")) {
if ("final".equals(atts.getValue("state"))) {
addProperty("LOCKED", "xliff final");
}
}
text.setLength(0);
}

Expand Down
16 changes: 13 additions & 3 deletions src/org/omegat/filters4/xml/xliff/AbstractXliffFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public boolean isBilingual() {
protected List<XMLEvent> source = new LinkedList<>();
protected List<XMLEvent> target = null;
protected List<XMLEvent> note = new LinkedList<>();
protected boolean isFinalState;

protected void cleanBuffers() {
source.clear();
Expand Down Expand Up @@ -144,7 +145,7 @@ protected boolean isToIgnore(String src, String tra) {

/** Add one unit to OmegaT, or more in case of <mrk mtype="seg"> **/
protected void registerCurrentTransUnit(String entryId, List<XMLEvent> unitSource,
List<XMLEvent> unitTarget, String notePattern) {
List<XMLEvent> unitTarget, String notePattern, boolean isFinalState) {
String src = buildTags(unitSource, false);
String tra = null;
if (unitTarget != null && !unitTarget.isEmpty()) {
Expand Down Expand Up @@ -180,8 +181,17 @@ protected void registerCurrentTransUnit(String entryId, List<XMLEvent> unitSourc
}
noteStr = subNoteBuf;
}
entryParseCallback.addEntry(entryId, src, tra, false,
noteStr == null ? null : noteStr.toString(), path, this, buildProtectedParts(src));
if (isFinalState) {
entryParseCallback.addEntryWithProperties(entryId, src, tra, false,
noteStr == null ? new String[] { "LOCKED", "xliff final" }
: new String[] { "LOCKED", "xliff final", org.omegat.core.data.SegmentProperties.COMMENT, noteStr.toString() },
path, this, buildProtectedParts(src));

} else {
entryParseCallback.addEntryWithProperties(entryId, src, tra, false,
noteStr == null ? null : new String[] { org.omegat.core.data.SegmentProperties.COMMENT, noteStr.toString() },
path, this, buildProtectedParts(src));
}
}
if (entryAlignCallback != null) {
entryAlignCallback.addTranslation(entryId, src, tra, false, path, this);
Expand Down
21 changes: 18 additions & 3 deletions src/org/omegat/filters4/xml/xliff/Xliff1Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ protected boolean processStartElement(StartElement startElement, XMLStreamWriter
throw new XMLStreamException(
OStrings.getString("XLIFF_MANDATORY_ORIGINAL_MISSING", "id", "trans-unit"));
}
isFinalState = false;
try {
isFinalState = "final".equals(startElement.getAttributeByName(new QName("state")).getValue());
} catch (Exception e) {
// non mandatory (and indeed should only accidentally be at this level)
}
flushedUnit = false;
targetStartEvent = null;
updateIgnoreScope(startElement);
Expand All @@ -176,6 +182,11 @@ protected boolean processStartElement(StartElement startElement, XMLStreamWriter
currentBuffer = target;
inTarget = true;
targetStartEvent = startElement;
try {
isFinalState = "final".equals(startElement.getAttributeByName(new QName("state")).getValue());
} catch (Exception e) {
// non mandatory, but in good place
}
break;
case "note":
currentBuffer = note;
Expand Down Expand Up @@ -235,11 +246,11 @@ protected boolean processEndElement(EndElement endElement, XMLStreamWriter write
}
if (ignoreScope == null || ignoreScope.startsWith("!")) { // registerCurrentTransUnit(unitId);
if (subSegments.isEmpty()) {
registerCurrentTransUnit(unitId, source, target, ".*");
registerCurrentTransUnit(unitId, source, target, ".*", isFinalState);
} else {
for (Map.Entry<String, List<XMLEvent>> me : subSegments.entrySet()) {
registerCurrentTransUnit(unitId + "/" + me.getKey(), me.getValue(),
findSubsegment(target, me.getKey()), "\\[(\\d+)\\](.*)\\[\\1\\]");
findSubsegment(target, me.getKey()), "\\[(\\d+)\\](.*)\\[\\1\\]", isFinalState);
}
}
}
Expand Down Expand Up @@ -540,7 +551,11 @@ protected final void generateTargetStartElement(XMLStreamWriter writer) throws X
}
if (isTranslated) {
writer.writeStartElement(namespace, "target");
writer.writeAttribute("state", "translated");
if (isFinalState) { // if segment is final it should be also final in the result
writer.writeAttribute("state", "final");
} else { // add status translated, which was not before
writer.writeAttribute("state", "translated");
}
if (targetStartEvent != null) {
for (java.util.Iterator<Attribute> iter = targetStartEvent.getAttributes(); iter.hasNext();) {
Attribute next = iter.next();
Expand Down
8 changes: 7 additions & 1 deletion src/org/omegat/filters4/xml/xliff/Xliff2Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ protected boolean processStartElement(StartElement startElement, XMLStreamWriter
segId = "1";
}
flushedSegment = false;
isFinalState = false;
try {
isFinalState = "final".equals(startElement.getAttributeByName(new QName("state")).getValue());
} catch (Exception e) {
// non mandatory
}
break;
case "source":
currentBuffer = source;
Expand Down Expand Up @@ -185,7 +191,7 @@ protected boolean processEndElement(EndElement endElement, XMLStreamWriter write
flushTranslations(writer); // if there was no <target> at all
}
if (ignoreScope == null || ignoreScope.startsWith("!")) {
registerCurrentTransUnit(segId, source, target, ".*");
registerCurrentTransUnit(segId, source, target, ".*", isFinalState);
}
segId = null;
cleanBuffers();
Expand Down
7 changes: 6 additions & 1 deletion src/org/omegat/gui/editor/EditorController.java
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ public void activateEntry(CaretPosition pos) {
// clear undo history.
((NotesTextArea) notes).clearHistory();
}

// then add new marks
markerController.reprocessImmediately(builder);

Expand Down Expand Up @@ -2253,4 +2253,9 @@ protected Map<Integer, Point> getViewableSegmentLocations() {
public IAutoCompleter getAutoCompleter() {
return editor.autoCompleter;
}

public void unlockSegment() {
editor.unlockSegment();
}

}
56 changes: 56 additions & 0 deletions src/org/omegat/gui/editor/EditorTextArea3.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
2013 Zoltan Bartko
2014 Aaron Madlon-Kay
2015 Yu Tang
2023-2024 Thomas Cordonnier
Home page: https://www.omegat.org/
Support center: https://omegat.org/support

Expand Down Expand Up @@ -65,9 +66,12 @@
import org.omegat.core.CoreEvents;
import org.omegat.core.data.ProtectedPart;
import org.omegat.core.data.SourceTextEntry;
import org.omegat.core.data.TMXEntry;
import org.omegat.core.events.IEntryEventListener;
import org.omegat.gui.editor.autocompleter.AutoCompleter;
import org.omegat.gui.shortcuts.PropertiesShortcuts;
import org.omegat.util.OStrings;
import org.omegat.util.Preferences;
import org.omegat.util.StringUtil;
import org.omegat.util.gui.Styles;
import org.omegat.util.gui.UIDesignManager;
Expand Down Expand Up @@ -163,6 +167,7 @@ protected void createInputAttributes(Element element, MutableAttributeSet set) {
});

addMouseListener(mouseListener);
CoreEvents.registerEntryEventListener(lockListener);

// Custom caret for overtype mode
OvertypeCaret c = new OvertypeCaret();
Expand Down Expand Up @@ -322,6 +327,39 @@ protected void registerPopupMenuConstructors(int priority, IPopupMenuConstructor
Collections.sort(popupConstructors, (o1, o2) -> o1.priority - o2.priority);
}
}

/**
* On new entry, check if we are in a locked segment, in which case we lock the editor
* Using this method ensures that isLocked is set here and only here
**/
protected final class LockListener implements IEntryEventListener {
private String isLocked = null;

public void onEntryActivated(SourceTextEntry newEntry) {
isLocked = null;
SourceTextEntry entry = controller.getCurrentEntry();
String[] props = entry.getRawProperties();
for (int i = 0; i < props.length; i++) {
if (props[i].equals("LOCKED")) {
isLocked = props[i + 1];
// Entries populated via a filter are always with context, as alternative
controller.setAlternateTranslationForCurrentEntry(true);
}
}
if (isLocked == null) {
TMXEntry tmx = Core.getProject().getTranslationInfo(entry);
isLocked = (tmx.linked == TMXEntry.ExternalLinked.xENFORCED) ? "tm/enforce" : null;
}
}

public void onNewFile(String activeFileName) {
}
};
private final transient LockListener lockListener = new LockListener();

public void unlockSegment() {
lockListener.isLocked = null;
}

/**
* Redefine some keys behavior. We can't use key listeners, because we have
Expand Down Expand Up @@ -364,6 +402,9 @@ protected void processKeyEvent(KeyEvent e) {
if (controller.settings.isUseTabForAdvance()) {
controller.nextEntry();
processed = true;
} else if (lockListener.isLocked != null) {
// We should not accept any character, including TAB
processed = Preferences.isPreferenceDefault(Preferences.SUPPORT_LOCKED_SEGMENTS, true);
}
} else if (s.equals(KEYSTROKE_PREV)) {
// Go back when 'Use TAB to advance'
Expand Down Expand Up @@ -475,6 +516,15 @@ protected void processKeyEvent(KeyEvent e) {
checkAndFixCaret(true);
}
}
// Treat the case of enforced translations which should be locked - this case does not seem to be treated via replaceSelection
if (lockListener.isLocked != null) {
if ((e.getKeyCode() == KeyEvent.VK_BACK_SPACE) || (e.getKeyCode() == KeyEvent.VK_DELETE)) {
Core.getMainWindow().showStatusMessageRB("MW_SEGMENT_LOCKED", lockListener.isLocked);
if (Preferences.isPreferenceDefault(Preferences.SUPPORT_LOCKED_SEGMENTS, true)) {
return;
}
}
}
super.processKeyEvent(e);
// note that the translation start/end position are not updated yet. This has been updated when
// then keyreleased event occurs.
Expand Down Expand Up @@ -828,6 +878,12 @@ private static class PopupMenuConstructorInfo {

@Override
public void replaceSelection(String content) {
if (lockListener.isLocked != null) {
Core.getMainWindow().showStatusMessageRB("MW_SEGMENT_LOCKED", lockListener.isLocked);
if (Preferences.isPreferenceDefault(Preferences.SUPPORT_LOCKED_SEGMENTS, true)) {
return;
}
}
// Overwrite current selection, and if at the end of the segment, allow
// inserting new text.
if (isEditable() && overtypeMode && getSelectionStart() == getSelectionEnd()
Expand Down
3 changes: 3 additions & 0 deletions src/org/omegat/gui/editor/IEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,7 @@ default boolean isOrientationAllLtr() {
default CaretPosition getCurrentPositionInEntryTranslationInEditor() {
return CaretPosition.startOfEntry();
}

/** Enable to edit a segment which was locked **/
void unlockSegment();
}
9 changes: 5 additions & 4 deletions src/org/omegat/gui/editor/mark/ComesFromAutoTMMarker.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class ComesFromAutoTMMarker implements IMarker {
private final HighlightPainter painterXice;
private final HighlightPainter painterX100Pc;
private final HighlightPainter painterXauto;
private final HighlightPainter painterXenforced;
private final HighlightPainter painterLocked;

public ComesFromAutoTMMarker() {
painterXice = new TransparentHighlightPainter(
Expand All @@ -54,8 +54,8 @@ public ComesFromAutoTMMarker() {
Styles.EditorColor.COLOR_MARK_COMES_FROM_TM_X100PC.getColor(), 0.5F);
painterXauto = new TransparentHighlightPainter(
Styles.EditorColor.COLOR_MARK_COMES_FROM_TM_XAUTO.getColor(), 0.5F);
painterXenforced = new TransparentHighlightPainter(
Styles.EditorColor.COLOR_MARK_COMES_FROM_TM_XENFORCED.getColor(), 0.5F);
painterLocked = new TransparentHighlightPainter(
Styles.EditorColor.COLOR_LOCKED_SEGMENT.getColor(), 0.5F);
}

@Override
Expand All @@ -64,6 +64,7 @@ public synchronized List<Mark> getMarksForEntry(SourceTextEntry ste, String sour
if (!Core.getEditor().getSettings().isMarkAutoPopulated()) {
return null;
}
boolean isLocked = false;
TMXEntry e = Core.getProject().getTranslationInfo(ste);
if (e == null || e.linked == null) {
return null;
Expand All @@ -80,7 +81,7 @@ public synchronized List<Mark> getMarksForEntry(SourceTextEntry ste, String sour
m.painter = painterXauto;
break;
case xENFORCED:
m.painter = painterXenforced;
m.painter = painterLocked;
}
return Collections.singletonList(m);
}
Expand Down
1 change: 1 addition & 0 deletions src/org/omegat/gui/main/MainWindowMenuHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ public void editMultipleDefaultActionPerformed() {

public void editMultipleAlternateActionPerformed() {
Core.getEditor().setAlternateTranslationForCurrentEntry(true);
Core.getEditor().unlockSegment();
}

public void editRegisterUntranslatedMenuItemActionPerformed() {
Expand Down
1 change: 1 addition & 0 deletions src/org/omegat/gui/multtrans/MultipleTransPane.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public void actionPerformed(ActionEvent e) {
miMultiple.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Core.getEditor().setAlternateTranslationForCurrentEntry(true);
Core.getEditor().unlockSegment();
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ protected void initFromPrefs() {
Preferences.EDITOR_INITIAL_SEGMENT_LOAD_COUNT, Preferences.EDITOR_INITIAL_SEGMENT_LOAD_COUNT_DEFAULT));
panel.paraMarkText.setText(Preferences.getPreferenceDefault(
Preferences.MARK_PARA_TEXT, Preferences.MARK_PARA_TEXT_DEFAULT));
panel.cbSupportLockedSegments.setSelected(Preferences.isPreferenceDefault(Preferences.SUPPORT_LOCKED_SEGMENTS, true));
updateEnabledness();
}

Expand All @@ -120,6 +121,7 @@ public void restoreDefaults() {
panel.tagValidateOnLeave.setSelected(false);
panel.cbSaveAutoStatus.setSelected(false);
panel.cbSaveOrigin.setSelected(false);
panel.cbSupportLockedSegments.setSelected(true);
panel.initialSegCountSpinner.setValue(Preferences.EDITOR_INITIAL_SEGMENT_LOAD_COUNT_DEFAULT);
panel.paraMarkText.setText(Preferences.MARK_PARA_TEXT_DEFAULT);

Expand Down Expand Up @@ -154,6 +156,7 @@ public void persist() {
Preferences.setPreference(Preferences.TAG_VALIDATE_ON_LEAVE, panel.tagValidateOnLeave.isSelected());
Preferences.setPreference(Preferences.SAVE_AUTO_STATUS, panel.cbSaveAutoStatus.isSelected());
Preferences.setPreference(Preferences.SAVE_ORIGIN, panel.cbSaveOrigin.isSelected());
Preferences.setPreference(Preferences.SUPPORT_LOCKED_SEGMENTS, panel.cbSupportLockedSegments.isSelected());

int segCount = Math.max(0, (Integer) panel.initialSegCountSpinner.getValue());
Preferences.setPreference(Preferences.EDITOR_INITIAL_SEGMENT_LOAD_COUNT, segCount);
Expand Down
15 changes: 15 additions & 0 deletions src/org/omegat/gui/preferences/view/EditingBehaviorPanel.form
Original file line number Diff line number Diff line change
Expand Up @@ -375,5 +375,20 @@
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="cbSupportLockedSegments">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/omegat/Bundle.properties" key="WG_SUPPORT_LOCKED_SEGMENTS" replaceFormat="OStrings.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="16" gridWidth="0" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="5" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Form>
Loading
Loading