ADR: Segment Sorting in the Editor¶
Status¶
Proposed (Date: 2026-07-23)
Pull Requests:
Sorting hook (
IEditorSorter): https://github.com/omegat-org/omegat/pull/2161Collapsible bar UI base: https://github.com/omegat-org/omegat/pull/2162
Sort bar and sorter model: https://github.com/omegat-org/omegat/pull/2163
Numeral parsing foundation: https://github.com/omegat-org/omegat/pull/2154
Context¶
Feature request #1094 asks for a way to sort the segments displayed in the editor, for example alphabetically by source text, so that translators can group similar segments and translate them in one pass.
Historically the editor displays segments strictly in their natural project order (the order in which the file filters produced them from the source files). There was no extension point for reordering the display.
Implementing sorting on top of an existing editor extension point was considered and
rejected. In particular, IEditorFilter is a hook for batch processing of the
segments, not a display-order mechanism: attaching ordering to it would have forced
every existing and future implementation to also deal with ordering, and plugins and
scripts could not have reordered the editor without replacing an active
IEditorFilter. Which segments the editor displays and in which order it displays
them are orthogonal concerns, so ordering gets its own dedicated hook and the two
mechanisms stay independent of each other.
In addition, parts of the entry navigation assumed that displayed segments appear in ascending entry-number order (positional lookups), an assumption that any custom order breaks.
Decision¶
Sorting is provided through a dedicated, minimal core hook, with the sorter model and its UI kept outside the core.
1. The IEditorSorter interface¶
org.omegat.gui.editor.IEditorSorter decides in which order the editor displays the
segments of the currently displayed file, without any influence on which segments
are displayed. It exposes a single method:
getComparator()returns aComparator<SegmentBuilder>used to order the displayed list of segments. Implementations must define a stable, total order and should fall back to the natural project order (by entry number) for otherwise-equal segments, so that the result is fully deterministic.
The comparator is applied in EditorController.loadDocument() to the segments being
displayed. When no sorter is set, the loading code path is unchanged and the
document order is identical to previous releases.
2. API on IEditor¶
IEditor gains setSort, getSort and removeSort. ConsoleBindings implements
the new methods, so scripts running in console mode keep working. Plugins and
scripts can therefore reorder the editor display without touching any other editor
mechanism.
3. Scope: per-file ordering¶
The editor loads one source file at a time, so the comparator only reorders the segments within the currently displayed file. It does not establish a project-wide order across files; navigation still moves from file to file in natural project order.
5. Sorter model and UI outside the core hook¶
The core only knows the IEditorSorter hook. The concrete sorter model and its UI
are delivered separately:
The sort bar UI and the multi-key sorter model (
org.omegat.gui.editor.sort:SortBar,SortKey,MultiKeySorter,TextKeyComparator,NumericValueComparator,CachingCollatorComparator).The collapsible bar component (
CollapsibleBar) that hosts the sort bar without taking up editor space when unused.Numeric ordering of textual numbers builds on the numeral parsing foundation (
NumeralValueParser).
Consequences¶
With no sorter set, the editor behaves exactly as before; the default code path is unaffected.
Sorting is independent of the editor’s other extension points; in particular it neither uses nor restricts the
IEditorFilterbatch-processing API, and both can be active at the same time.Plugins and scripts get a supported way to reorder the editor display.
Entry navigation is robust under any permutation of the displayed segments.
Ordering is limited to the currently displayed file; a project-wide order across files is out of scope for this design.
The core commitment is a single small interface; sorting criteria and UI can evolve (or be replaced by plugins) without further core changes.
References¶
Feature request: #1094 “Sorting segments”
Pull requests: #2161 (hook), #2162 (collapsible bar), #2163 (sort bar and model), #2154 (numeral parsing foundation)