Skip to content

UX: Implement complete internationalization (i18n) with resource bundles #66

@sfloess

Description

@sfloess

Overview

Complete the i18n implementation by actually using the Messages infrastructure and resource bundles that already exist.

Current State

  • ✅ Messages.java infrastructure exists
  • ✅ Resource bundles for 4 languages (English, German, Spanish, French)
  • ❌ None of it is actually used (dead code)
  • ❌ All UI strings are hardcoded

UX Score Impact

Current: UX A (94/100)
With this: UX A+ (99/100)

Issue

Issue #51 documents the unused infrastructure - this issue is about COMPLETING it, not removing it.

Implementation Plan

Phase 1: Desktop CLI (Highest Priority)

Update JNexus.java to use Messages:

Before:

System.out.println("Listing components in repository: " + repository);

After:

System.out.println(Messages.format("cli.listing.components", repository));

Update all commands (list, delete, stats) to use Messages.get() and Messages.format().

Phase 2: Swing GUI

Update JNexusSwing.java:

Before:

JButton listButton = new JButton("List");
JButton refreshButton = new JButton("Refresh");

After:

JButton listButton = new JButton(Messages.get("button.list"));
JButton refreshButton = new JButton(Messages.get("button.refresh"));

Replace ~100 hardcoded strings.

Phase 3: AWT GUI and Terminal UI

Same approach as Swing - replace hardcoded strings with Messages.get().

Phase 4: Language Selector

Add language selection:

CLI:

jnexus --lang=de list my-repo
# Or via environment:
export JNEXUS_LANG=es

GUI:
Add "Language" menu or Settings panel:

String[] languages = {"English", "Deutsch", "Español", "Français"};
JComboBox<String> langSelector = new JComboBox<>(languages);
langSelector.addActionListener(e -> {
    String selected = (String) langSelector.getSelectedItem();
    Locale locale = getLocaleForLanguage(selected);
    Messages.setLocale(locale);
    refreshUI();  // Reload all labels
});

Phase 5: Android (Optional)

Android has built-in i18n via strings.xml:

<!-- res/values/strings.xml (English) -->
<string name="button_list">List</string>

<!-- res/values-de/strings.xml (German) -->
<string name="button_list">Liste</string>

<!-- res/values-es/strings.xml (Spanish) -->
<string name="button_list">Lista</string>

Use stringResource(R.string.button_list) in Compose.

Phase 6: iOS (Optional)

iOS has built-in i18n via Localizable.strings:

// en.lproj/Localizable.strings
"button.list" = "List";

// de.lproj/Localizable.strings
"button.list" = "Liste";

// In code:
Text(NSLocalizedString("button.list", comment: ""))

Existing Resource Bundles

Already created (7,000+ lines across 4 languages):

  • messages.properties (English)
  • messages_de.properties (German)
  • messages_es.properties (Spanish)
  • messages_fr.properties (French)

Testing

Add i18n tests:

@Test
void testGermanLocalization() {
    Messages.setLocale(Locale.GERMAN);
    assertEquals("Liste", Messages.get("button.list"));
}

@Test
void testAllKeysExistInAllBundles() {
    // Verify no missing translations
    Locale[] locales = {Locale.ENGLISH, Locale.GERMAN, 
                        new Locale("es"), Locale.FRENCH};
    Set<String> englishKeys = getKeys(Locale.ENGLISH);
    
    for (Locale locale : locales) {
        Set<String> localeKeys = getKeys(locale);
        assertEquals(englishKeys, localeKeys, 
            "Missing translations in " + locale);
    }
}

Configuration

Add to nexus.properties:

# Language/locale (auto-detect if not specified)
nexus.language=en
# Or: de, es, fr

Acceptance Criteria

  • All CLI output uses Messages.format()
  • All GUI labels use Messages.get()
  • Language selector in GUI
  • --lang flag in CLI
  • All 4 languages tested
  • No missing translation keys
  • Auto-detection of system locale
  • Documentation updated (README, RUNNING.md)

Benefits

  • Accessibility for non-English users
  • Professional appearance
  • Expands user base globally
  • Leverages existing infrastructure
  • Demonstrates attention to detail

Effort Estimate

  • CLI: 2-3 hours (50 strings)
  • Swing GUI: 4-6 hours (100+ strings)
  • AWT GUI: 3-4 hours (80 strings)
  • Terminal UI: 2-3 hours (60 strings)
  • Testing: 2 hours
  • Total: 15-20 hours

Priority

Medium - Infrastructure exists, just needs integration

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions