# Portabilitaet: UNIVERSAL
# Zuletzt validiert: 2026-03-08 (Claude/BACH wiki-author)
# Naechste Pruefung: 2027-03-08
# Quellen: Unicode CLDR, GNU gettext Manual, MDN Web Docs (Intl API), W3C i18n Best Practices

INTERNATIONALISIERUNG (i18n) UND LOKALISIERUNG (l10n)
======================================================

Stand: 2026-03-08
Sprache: DE


WAS IST i18n?
--------------
i18n ist die Abkuerzung fuer "internationalization" (i + 18 Buchstaben + n).
Es bedeutet: Software so zu entwickeln, dass sie mehrere Sprachen und
Regionen unterstuetzen kann, ohne den Quellcode aendern zu muessen.

Der verwandte Begriff l10n steht fuer "localization" (l + 10 Buchstaben + n)
und bezeichnet die tatsaechliche Uebersetzung und Anpassung fuer eine
konkrete Sprache oder Region.

  i18n = Vorbereitung (Architektur)
  l10n = Umsetzung (Inhalte)


WARUM i18n?
------------
  - Globale Reichweite: 75% der Internetnutzer sprechen kein Englisch
  - Rechtliche Anforderungen: EU-Vorschriften, Barrierefreiheit
  - Benutzererfahrung: Menschen bevorzugen Software in ihrer Sprache
  - Markterschliessung: Neue Maerkte ohne Code-Aenderungen


WAS WIRD INTERNATIONALISIERT?
-------------------------------

  Bereich           i18n (Vorbereitung)         l10n (Umsetzung)
  -----------------------------------------------------------------------
  Texte             Strings externalisieren     Uebersetzen (DE, FR, ES...)
  Zahlen            Format-System einbauen      1,000.00 vs 1.000,00
  Datum/Uhrzeit     Locale-aware Formatter      03/08/2026 vs 08.03.2026
  Waehrung          Dynamisches Symbol          $, EUR, ¥
  Sortierung        Locale-aware Collation      ae vs ä Reihenfolge
  Pluralformen      Plural-Regeln einbauen      1 Datei vs 2 Dateien
  Textrichtung      RTL-Support vorbereiten     Arabisch, Hebraeisch
  Bilder/Icons      Kulturell neutrale Assets   Lokale Anpassungen
  Masseinheiten     Einheiten-System            Metrisch vs Imperial


TECHNISCHE UMSETZUNG
----------------------

  1. Strings externalisieren
  --------------------------
  NIEMALS Texte hardcoden. Alle sichtbaren Strings in separate Dateien
  auslagern.

    Schlecht:
      print("Datei gespeichert")

    Gut:
      print(_("Datei gespeichert"))

  2. Locale-Kennung (BCP 47 / IETF)
  -----------------------------------
    de          Deutsch (allgemein)
    de-DE       Deutsch (Deutschland)
    de-AT       Deutsch (Oesterreich)
    de-CH       Deutsch (Schweiz)
    en-US       Englisch (USA)
    en-GB       Englisch (Grossbritannien)
    zh-Hans     Chinesisch (vereinfacht)
    zh-Hant     Chinesisch (traditionell)

  3. Unicode und Encoding
  ------------------------
    - IMMER UTF-8 verwenden (Standard seit HTML5)
    - Datenbank, Dateien, API-Responses: alles UTF-8
    - Python: PYTHONIOENCODING=utf-8 (besonders auf Windows)


UEBERSETZUNGS-DATEIFORMATE
----------------------------

  Format       Einsatzgebiet                 Beispiel
  ------------------------------------------------------------------
  .po/.mo      gettext (Python, C, PHP)      GNU-Standard
  .json        Web-Apps (React, Vue)         i18next, vue-i18n
  .xliff       Enterprise, iOS               XML-basiert, Tool-kompatibel
  .arb         Flutter/Dart                  JSON-Variante
  .strings     iOS/macOS (nativ)             Apple-Format
  .xml         Android                       res/values-de/strings.xml
  .resx        .NET/C#                       XML-basiert
  .properties  Java                          key=value
  .ts          Qt/PySide6                    Qt Linguist


i18n IN PYTHON (gettext)
--------------------------

  Setup:

    import gettext
    import locale

    # Locale setzen
    locale.setlocale(locale.LC_ALL, '')

    # Uebersetzungen laden
    lang = gettext.translation('myapp', localedir='locales', languages=['de'])
    lang.install()
    _ = lang.gettext

    # Verwendung
    print(_("File saved"))           # -> "Datei gespeichert"
    print(_("Welcome, %s") % name)   # -> "Willkommen, Max"

  Verzeichnisstruktur:

    locales/
    ├── de/LC_MESSAGES/
    │   ├── myapp.po                 # Quelldatei (editierbar)
    │   └── myapp.mo                 # Kompiliert (fuer Laufzeit)
    ├── fr/LC_MESSAGES/
    │   ├── myapp.po
    │   └── myapp.mo
    └── pot/
        └── myapp.pot                # Template (Basis fuer alle)

  Workflow:
    1. xgettext --language=Python -o myapp.pot *.py    Strings extrahieren
    2. msginit -l de -o de.po -i myapp.pot             PO-Datei erstellen
    3. Uebersetzen (manuell oder mit Tool)
    4. msgfmt -o myapp.mo de.po                        Kompilieren


i18n IN JAVASCRIPT/WEB
------------------------

  i18next (beliebtes Framework):

    // Initialisierung
    import i18next from 'i18next';

    i18next.init({
      lng: 'de',
      resources: {
        de: {
          translation: {
            "welcome": "Willkommen, {{name}}!",
            "items": "{{count}} Artikel",
            "items_plural": "{{count}} Artikel"
          }
        },
        en: {
          translation: {
            "welcome": "Welcome, {{name}}!",
            "items": "{{count}} item",
            "items_plural": "{{count}} items"
          }
        }
      }
    });

    i18next.t('welcome', { name: 'Max' });  // "Willkommen, Max!"

  Browser Intl API (nativ):

    // Zahlen
    new Intl.NumberFormat('de-DE').format(1234.5)    // "1.234,5"
    new Intl.NumberFormat('en-US').format(1234.5)    // "1,234.5"

    // Datum
    new Intl.DateTimeFormat('de-DE').format(date)    // "08.03.2026"
    new Intl.DateTimeFormat('en-US').format(date)    // "3/8/2026"

    // Waehrung
    new Intl.NumberFormat('de-DE', {
      style: 'currency', currency: 'EUR'
    }).format(42.5)                                  // "42,50 EUR"


i18n IN PYSIDE6/QT
--------------------

  Qt Linguist Workflow:

    # Im Code: tr() verwenden
    from PySide6.QtWidgets import QLabel
    label = QLabel(self.tr("File saved"))

    # Strings extrahieren
    pyside6-lupdate main.py -ts translations/app_de.ts

    # In Qt Linguist uebersetzen
    pyside6-linguist translations/app_de.ts

    # Kompilieren
    pyside6-lrelease translations/app_de.ts

    # Laden
    from PySide6.QtCore import QTranslator
    translator = QTranslator()
    translator.load("translations/app_de.qm")
    app.installTranslator(translator)


BEST PRACTICES
---------------
  - Frueh beginnen: i18n nachtraeglich einzubauen ist teuer
  - Keine String-Konkatenation fuer Saetze (Wortstellung variiert!)
  - Pluralformen beruecksichtigen (Russisch hat 3, Arabisch hat 6)
  - Platz einplanen: Deutsche Texte sind ~30% laenger als englische
  - Kontext mitliefern: "Open" kann "Oeffnen" oder "Offen" bedeuten
  - Bilder mit Text vermeiden (muessen pro Sprache erstellt werden)
  - RTL-Layout testen wenn relevant
  - Professionelle Uebersetzer einsetzen (nicht nur Google Translate)
  - Uebersetzungs-Management-Tools nutzen (Crowdin, Transifex, Weblate)


BACH-KONTEXT
-------------
BACH nutzt ein eigenes i18n-System mit Datenbank-Tabellen:

  languages_config        Konfigurierte Sprachen und Fallbacks
  languages_translations  Alle uebersetzten Strings (key -> locale -> text)

Handler: bach language list, bach language set <code>

BACH-Agenten und -Skills enthalten Strings in DE (primaer) und EN.
Der Commit-Stil "i18n:" wird fuer Uebersetzungs-Aenderungen verwendet.


SIEHE AUCH
-----------
  wiki/informatik/softwareentwicklung/i18n_en.txt   i18n (English)
  wiki/informatik/softwareentwicklung/README.txt    Softwareentwicklung
  wiki/informatik/web_entwicklung/                  Web-Entwicklung
