ADR: OmegaT CLI Modernization with PicoCLI

Status

Accepted - Implementation in progress

Context

The existing OmegaT command line interface suffered from several architectural and usability issues:

Problems with Legacy CLI

  • Complex nested options: Deep nesting made the CLI difficult to use and document

  • Monolithic architecture: All CLI logic was centralized in the CLIParameters class and Main class

  • Poor documentation: Help text was stored as a single large message in Bundle.properties, causing translation and maintenance issues

  • Limited extensibility: No mechanism for plugins to add custom CLI commands

  • Inconsistent syntax: Mixed patterns that didn’t follow modern CLI conventions

User Experience Issues

  • PDF manual became unreadable due to excessive indentation from nested options

  • Help system was monolithic and difficult to navigate

  • No hierarchical help structure (e.g., --help <command>)

  • Inconsistent command patterns across different operations

Decision

We decided to modernize the OmegaT CLI by adopting PicoCLI as the command-line parsing library and restructuring the entire CLI architecture.

Key Architectural Changes

1. PicoCLI Integration

  • Replace custom CLIParameters class with PicoCLI-based command structure

  • Implement standard command-line patterns with proper sub-command support

  • Leverage PicoCLI’s automatic help generation and validation

2. Modular Command Architecture

  • Create dedicated command classes in org.omegat.cli package

  • Each command becomes a self-contained class with its own logic and parameters

  • Each command shares mixin class Parameters for common options.

  • Help messages are i18n-ed with Prameters.properties resource bundles.

3. New Command Structure

OmegaT [COMMAND] [SUB-COMMAND] [OPTIONS] [ARGUMENTS]

Supported Commands:

  • start - Launch OmegaT GUI (default when no command specified)

  • team - Team project management utilities

  • stats - Statistics generation

  • translate - Console translation mode

  • align - Document alignment utilities(CLI/GUI)

  • pseudo - Pseudo TMX generation

4. Help example

$ ./OmegaT --help
Usage: omegat [-hV] [--disable-location-save] [--disable-project-locking]
              [--no-team] [--alignDir=<path>] [--config-dir=<path>]
              [--config-file=<path>] [--mode=<console-mode-name>]
              [--output-file=<stats-output-file>] [--pseudotranslatetmx=<path>]
              [--pseudotranslatetype=<equal_or_empty>]
              [--resource-bundle=<bundle>] [--source-pattern=<sourcePattern>]
              [--stats-type=<xml_or_text_or_json>] [-D=<String=String>]...
              [<project>] [COMMAND]
OmegaT free translation memory application.
      [<project>]
      --alignDir=<path>      The folder containing the translated files.
      --config-dir=<path>    The folder used to read or write OmegaT
                               configuration files.
      --config-file=<path>   A Java .properties file from which to load default
                               settings.
  -D=<String=String>
      --disable-location-save
                             Do not remember the last folder opened in the file
                               picker.
      --disable-project-locking
                             Do not attempt to lock the omegat.project file.
  -h, --help                 Show this help message and exit.
      --mode=<console-mode-name>
                             Console mode name: console-translate,
                               console-createpseudotranslatetmx, console-align,
                               or console-stats
      --no-team              Disable team project functionality.
      --output-file=<stats-output-file>
                             Prints to the specified file, or to standard
                               output
                             if no file is given or the option is not used.
      --pseudotranslatetmx=<path>
                             The output pseudotranslated TMX file.
      --pseudotranslatetype=<equal_or_empty>
                             What to put in the pseudotranslated TMX.
      --resource-bundle=<bundle>
                             A Java .properties file to use for the interface
                               text.
      --source-pattern=<sourcePattern>
                             A regex whitelist of source files to process.
      --stats-type=<xml_or_text_or_json>
                             Specifies the output format.
                             If --stats-type is not specified, the format is
                             detected from the file extension.
                             Defaults to xml.
  -V, --version              Print version information and exit.
Commands:
  start      Start OmegaT GUI.
  align      Launch Align Tool.
  translate  Console translate command.
  stats      Show translation statistics.
  team       Team admin utility.
  help       Display help information about the specified command.
miurahr@miurahr-dragon:~/IdeaProjects/omegat/build/install/OmegaT$ ./OmegaT team init --help
Missing required parameters: '<source>', '<target>'
Usage: omegat team init <source> <target>
Team project tool.
Initialize a minimal team project with the specified languages.
If invoked in a git working tree or svn checkout, the results
will be staged/added.
      <source>   Source language
      <target>   Target langauge
$ ./OmegaT team --help
Usage: omegat team [-h] [COMMAND]
Team admin utility.
  -h, --help   Show this help message and exit.
Commands:
  init  Team project tool.
        Initialize a minimal team project with the specified languages.
        If invoked in a git working tree or svn checkout, the results
        will be staged/added.
miurahr@miurahr-dragon:~/IdeaProjects/omegat/build/install/OmegaT$ ./OmegaT team 
Usage: team [-h] [COMMAND]
  -h, --help   Show this help message and exit.
Commands:
  init
$ ./OmegaT start  --help
Usage: omegat start [-h] [--quiet] [--[no-]team] [--verbose]
                    [--ITokenizer=<tokenizerSource>]
                    [--ITokenizerTarget=<tokenizerTarget>] [--script=<path>]
                    [--tag-validation=<tagValidation>] <project>
Start OmegaT GUI.
      <project>         Project directory
  -h, --help            Show this help message and exit.
      --ITokenizer=<tokenizerSource>
                        source-language tokenizer to use (overrides project
                          settings). See OmegaT.jar/META-INF/MANIFEST.MF for
                          valid values.
      --ITokenizerTarget=<tokenizerTarget>
                        target-language tokenizer to use (overrides project
                          settings). See OmegaT.jar/META-INF/MANIFEST.MF for
                          valid values.
      --quiet           Reduce output to command line stdout.
      --script=<path>   A script file to execute on project events.
      --tag-validation=<tagValidation>
                        Validate tags. Abort: Exit with an error if tags are
                          invalid. Warn: Report invalid tags to stdout.
      --[no-]team       Enable team project functionality[Default: ON].
      --verbose         Verbose output of command log messages.

Implementation Details

Package Structure

org.omegat.cli/
├── LegacyParameters.java   # Main CLI legacy parameters
├── Parameters.java         # Sub command common parameters
├── Common.java             # Common operations among sub commands
├── AlignCommand.java       # Alignment operations
├── PseudoTranslationCommand.java # Pseudo Translation operations
├── StartCommand.java       # GUI startup
├── StatsCommand.java       # Statistics generation
└── TeamCommand.java        # Team project operations
├── TranslateCommand.java   # Console translation

Core Changes

Removed Components

  • CLIParameters class (replaced by PicoCLI structure)

  • Legacy CLI parsing logic in Main class

  • Monolithic help text in Bundle.properties

  • Deprecated CLI-related test classes

Added Components

  • PicoCLI dependency integration

  • Modular command classes with dedicated responsibilities

  • Runtime preferences for CLI-specific parameters

  • Enhanced help system with command-specific documentation

Modified Components

  • Main class: Streamlined to delegate to PicoCLI

  • Core class: Removed CLI parameter dependencies

  • ProjectPropertiesDialog: Cleaned up CLI-related code

  • Test suites: Updated to reflect new CLI structure

Command Implementation Pattern

Each command follows a consistent pattern:

@Command(name = "commandname", description = "Command description")
public class ExampleCommand implements Callable<Integer> {
    @Parameters(description = "Command parameters")
    private List<String> parameters;
    
    @Option(names = {"-o", "--option"}, description = "Option description")
    private String option;
    
    @Override
    public int call() {
        // Command implementation
        return 0;
    }
}

Runtime Integration

  • Preferences: New CLI parameters stored in RuntimePreferences

  • Lifecycle: Commands handle their own execution lifecycle

  • Error Handling: PicoCLI provides standardized error reporting

  • Validation: Built-in parameter validation and type conversion

Benefits

For Users

  • Intuitive syntax: Follows modern CLI conventions (similar to Git)

  • Better help system: Hierarchical help with --help and --help <command>

  • Consistent patterns: Uniform command structure across all operations

  • Improved documentation: Clear, modular help text

For Developers

  • Modular architecture: Commands are self-contained and testable

  • Plugin extensibility: Framework ready for plugin-based command extensions

  • Maintainable code: Separation of concerns between commands

  • Standard library: Leverages proven PicoCLI patterns and features

For Translators

  • Granular messages: Help text split into manageable, translatable units

  • Context preservation: Command-specific help maintains proper context

  • Reduced complexity: Smaller, focused translation units

Migration Strategy

Backward Compatibility

  • Legacy command syntax continues to work during transition period

  • Gradual deprecation of old patterns with clear migration guidance

  • Existing scripts and integrations remain functional

Rollout Plan

  1. Phase 1: Core PicoCLI integration with basic commands

  2. Phase 2: Advanced command features and plugin framework

  3. Phase 3: Legacy CLI deprecation and removal

Testing Strategy

Test Coverage

  • Unit tests: Individual command classes with focused test cases

  • Regression tests: Ensure backward compatibility during transition

Quality Assurance

  • Command parameter validation testing

  • Error handling and user feedback verification

  • Performance testing for large project operations

  • Cross-platform CLI behavior validation

Risks and Mitigations

Dependencies

  • Risk: Adding PicoCLI dependency increases application size

  • Mitigation: PicoCLI is lightweight and provides significant value

Complexity

  • Risk: New architecture might introduce learning curve

  • Mitigation: Comprehensive documentation and examples provided

Migration

  • Risk: Breaking changes for existing CLI users

  • Mitigation: Backward compatibility maintained during transition

Future Considerations

Plugin System Integration

The new CLI architecture provides foundation for:

  • Plugin-contributed commands

  • Dynamic command registration

  • Extensible parameter handling

Advanced Features

  • Command completion support

  • Configuration file integration

  • Enhanced scripting capabilities

References


Date: 2024-01-30
Authors: Hiroshi Miura, Thomas Cordonnier, Jean-Christophe Helary
Reviewers: OmegaT Development Team
Status: Implementation in Progress