Name shortcut zu mailadler
This commit is contained in:
580
CSV_AUTO_EXPORT_IMPORT.md
Normal file
580
CSV_AUTO_EXPORT_IMPORT.md
Normal file
@@ -0,0 +1,580 @@
|
||||
# CSV Auto-Export/Import - Easiest Way
|
||||
|
||||
## 1. CSV Auto-Generieren (aus .ts)
|
||||
|
||||
### Problem
|
||||
```
|
||||
Du willst CSV mit:
|
||||
- Spalte 1: Alle Deutsch-Wörter (aus mail-adler_de.ts)
|
||||
- Spalte 2: Leer für neue Sprache
|
||||
- Mit Kommas korrekt formatiert
|
||||
|
||||
Statt manuell alle Wörter zu kopieren
|
||||
```
|
||||
|
||||
### Lösung: Export-Script
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# scripts/export_to_csv.py
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
import csv
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
def ts_to_csv(ts_file: str, csv_output: str, language_name: str = "Neue Sprache"):
|
||||
"""
|
||||
Exportiere alle Deutsch-Strings aus .ts zu CSV
|
||||
|
||||
Output:
|
||||
Deutsch,Neue Sprache
|
||||
Eingang,
|
||||
Gesendet,
|
||||
...
|
||||
"""
|
||||
|
||||
tree = ET.parse(ts_file)
|
||||
root = tree.getroot()
|
||||
ns = {'ts': 'http://trolltech.com/TS'}
|
||||
|
||||
# Sammle alle Deutsch-Strings
|
||||
german_strings = []
|
||||
|
||||
for message in root.findall('.//message', ns):
|
||||
source_elem = message.find('source', ns)
|
||||
if source_elem is not None and source_elem.text:
|
||||
german_strings.append(source_elem.text.strip())
|
||||
|
||||
# Dedupliziere (falls gleiche Wörter mehrmals vorkommen)
|
||||
german_strings = list(dict.fromkeys(german_strings))
|
||||
german_strings.sort()
|
||||
|
||||
# Schreibe CSV
|
||||
with open(csv_output, 'w', newline='', encoding='utf-8') as f:
|
||||
writer = csv.writer(f)
|
||||
# Header
|
||||
writer.writerow(['Deutsch', language_name])
|
||||
# Alle Strings
|
||||
for word in german_strings:
|
||||
writer.writerow([word, '']) # Zweite Spalte leer
|
||||
|
||||
print(f"✅ Export fertig!")
|
||||
print(f" Datei: {csv_output}")
|
||||
print(f" Strings: {len(german_strings)}")
|
||||
print(f"")
|
||||
print(f"Nächster Schritt:")
|
||||
print(f"1. Öffne {csv_output} in Excel")
|
||||
print(f"2. Fülle die '{language_name}'-Spalte mit Übersetzungen")
|
||||
print(f"3. Speichern")
|
||||
print(f"4. Führe import_csv.py aus")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Export .ts zu CSV')
|
||||
parser.add_argument('--source', required=True, help='mail-adler_de.ts')
|
||||
parser.add_argument('--output', required=True, help='output.csv')
|
||||
parser.add_argument('--language', default='English', help='Sprachen-Name')
|
||||
|
||||
args = parser.parse_args()
|
||||
ts_to_csv(args.source, args.output, args.language)
|
||||
```
|
||||
|
||||
### Verwendung:
|
||||
|
||||
```bash
|
||||
# Exportiere für Niederländisch
|
||||
python3 scripts/export_to_csv.py \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/glossary_nl.csv \
|
||||
--language Niederländisch
|
||||
|
||||
# Output: glossary_nl.csv erstellt
|
||||
# CSV hat:
|
||||
# - Spalte 1: "Deutsch" (alle Strings)
|
||||
# - Spalte 2: "Niederländisch" (leer)
|
||||
```
|
||||
|
||||
**glossary_nl.csv sieht so aus:**
|
||||
```csv
|
||||
Deutsch,Niederländisch
|
||||
Abbrechen,
|
||||
Anmeldedaten,
|
||||
Antworten,
|
||||
Ansicht,
|
||||
Archive,
|
||||
Archiv,
|
||||
Bearbeiten,
|
||||
Beenden,
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. In Excel bearbeiten
|
||||
|
||||
### Schritt 1: CSV öffnen
|
||||
|
||||
```
|
||||
1. Windows: Rechts-Klick auf glossary_nl.csv
|
||||
→ "Öffnen mit" → Excel
|
||||
|
||||
2. Oder: Excel → Datei → Öffnen → glossary_nl.csv
|
||||
```
|
||||
|
||||
### Schritt 2: Niederländisch-Spalte ausfüllen
|
||||
|
||||
```
|
||||
Excel-Tabelle:
|
||||
┌─────────────────┬──────────────────┐
|
||||
│ Deutsch │ Niederländisch │
|
||||
├─────────────────┼──────────────────┤
|
||||
│ Abbrechen │ Annuleren │
|
||||
│ Anmeldedaten │ Inloggegevens │
|
||||
│ Antworten │ Antwoorden │
|
||||
│ Ansicht │ Weergave │
|
||||
│ ... │ ... │
|
||||
└─────────────────┴──────────────────┘
|
||||
```
|
||||
|
||||
### Schritt 3: Speichern (als CSV!)
|
||||
|
||||
```
|
||||
Excel:
|
||||
1. Datei → Speichern unter
|
||||
2. Format: "CSV UTF-8 (Kommagetrennt)"
|
||||
(WICHTIG: UTF-8, nicht Standart-CSV)
|
||||
3. Speichern
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Import zurück zu .ts
|
||||
|
||||
### Import-Script
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# scripts/import_csv_to_ts.py
|
||||
|
||||
import csv
|
||||
import xml.etree.ElementTree as ET
|
||||
import argparse
|
||||
|
||||
def csv_to_ts(csv_file: str, ts_source: str, ts_output: str, language_column: str = 1):
|
||||
"""
|
||||
Importiere CSV-Übersetzungen zurück zu .ts
|
||||
|
||||
CSV-Format:
|
||||
Deutsch,English (oder Französisch, Niederländisch, etc.)
|
||||
Eingang,Inbox
|
||||
...
|
||||
"""
|
||||
|
||||
# 1. Lese CSV
|
||||
translations = {}
|
||||
|
||||
with open(csv_file, 'r', encoding='utf-8') as f:
|
||||
reader = csv.reader(f)
|
||||
header = next(reader) # Überspringe Header
|
||||
|
||||
for row in reader:
|
||||
if len(row) >= 2:
|
||||
deutsch = row[0].strip()
|
||||
übersetzt = row[1].strip()
|
||||
|
||||
if deutsch and übersetzt: # Nur wenn beide gefüllt
|
||||
translations[deutsch] = übersetzt
|
||||
|
||||
print(f"✅ CSV geladen: {len(translations)} Übersetzungen gefunden")
|
||||
|
||||
# 2. Parse .ts Datei
|
||||
tree = ET.parse(ts_source)
|
||||
root = tree.getroot()
|
||||
ns = {'ts': 'http://trolltech.com/TS'}
|
||||
ET.register_namespace('', 'http://trolltech.com/TS')
|
||||
|
||||
# 3. Update Übersetzungen
|
||||
updated = 0
|
||||
missing = 0
|
||||
|
||||
for message in root.findall('.//message', ns):
|
||||
source_elem = message.find('source', ns)
|
||||
trans_elem = message.find('translation', ns)
|
||||
|
||||
if source_elem is None or trans_elem is None:
|
||||
continue
|
||||
|
||||
deutsch_text = source_elem.text
|
||||
|
||||
if deutsch_text in translations:
|
||||
trans_elem.text = translations[deutsch_text]
|
||||
trans_elem.set('type', 'finished')
|
||||
updated += 1
|
||||
print(f" ✓ {deutsch_text:30} → {translations[deutsch_text]}")
|
||||
else:
|
||||
missing += 1
|
||||
|
||||
# 4. Speichern
|
||||
tree.write(ts_output, encoding='UTF-8', xml_declaration=True)
|
||||
|
||||
print(f"\n✅ FERTIG!")
|
||||
print(f" Aktualisiert: {updated}")
|
||||
print(f" Fehlend (nicht in CSV): {missing}")
|
||||
print(f" Ausgabedatei: {ts_output}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Import CSV zu .ts')
|
||||
parser.add_argument('--csv', required=True, help='glossary_nl.csv')
|
||||
parser.add_argument('--source', required=True, help='mail-adler_de.ts')
|
||||
parser.add_argument('--output', required=True, help='mail-adler_nl.ts')
|
||||
|
||||
args = parser.parse_args()
|
||||
csv_to_ts(args.csv, args.source, args.output)
|
||||
```
|
||||
|
||||
### Verwendung:
|
||||
|
||||
```bash
|
||||
# Importiere CSV zurück zu .ts
|
||||
python3 scripts/import_csv_to_ts.py \
|
||||
--csv translations/glossary_nl.csv \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/mail-adler_nl.ts
|
||||
|
||||
# Output:
|
||||
# ✅ CSV geladen: 247 Übersetzungen gefunden
|
||||
# ✓ Abbrechen → Annuleren
|
||||
# ✓ Anmeldedaten → Inloggegevens
|
||||
# ...
|
||||
# ✅ FERTIG!
|
||||
# Aktualisiert: 247
|
||||
# Fehlend: 0
|
||||
# Ausgabedatei: translations/mail-adler_nl.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Kompletter Workflow für neue Sprache
|
||||
|
||||
```bash
|
||||
# 1️⃣ EXPORT: Alle Deutsch-Strings → CSV
|
||||
python3 scripts/export_to_csv.py \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/glossary_nl.csv \
|
||||
--language Niederländisch
|
||||
|
||||
# Output: glossary_nl.csv erstellt (250 leere Zeilen)
|
||||
|
||||
# 2️⃣ BEARBEITEN: In Excel ausfüllen
|
||||
# → Öffne glossary_nl.csv in Excel
|
||||
# → Fülle Niederländisch-Spalte
|
||||
# → Speichern (als CSV UTF-8!)
|
||||
|
||||
# 3️⃣ IMPORT: CSV → .ts
|
||||
python3 scripts/import_csv_to_ts.py \
|
||||
--csv translations/glossary_nl.csv \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/mail-adler_nl.ts
|
||||
|
||||
# 4️⃣ KOMPILIEREN
|
||||
lrelease translations/mail-adler_nl.ts
|
||||
|
||||
# 5️⃣ GIT & RELEASE
|
||||
git add translations/glossary_nl.csv translations/mail-adler_nl.ts
|
||||
git commit -m "Add Dutch translation"
|
||||
./scripts/release_with_translation.sh nl_NL
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Mit LM Studio (Copy-Paste aus Excel)
|
||||
|
||||
### Schneller Workflow:
|
||||
|
||||
```
|
||||
1. Export: glossary_nl.csv erstellen
|
||||
python3 scripts/export_to_csv.py ...
|
||||
|
||||
2. Excel: glossary_nl.csv öffnen
|
||||
Links: Deutsch, Rechts: Niederländisch (leer)
|
||||
|
||||
3. LM Studio offen (http://localhost:1234)
|
||||
|
||||
4. Copy-Paste Loop:
|
||||
- Excel: "Abbrechen" kopieren
|
||||
- LM Studio: "Übersetze ins Niederländische: Abbrechen"
|
||||
- LM Studio antwortet: "Annuleren"
|
||||
- Excel: "Annuleren" einfügen
|
||||
- Nächst Wort...
|
||||
|
||||
5. Nach alle Wörter:
|
||||
Import: glossary_nl.csv → mail-adler_nl.ts
|
||||
python3 scripts/import_csv_to_ts.py ...
|
||||
|
||||
6. Fertig!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Mehrere Sprachen gleichzeitig (in einer Datei)
|
||||
|
||||
### Super praktisch: Ein CSV für alle Sprachen
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# scripts/export_to_csv_multilang.py
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
import csv
|
||||
import argparse
|
||||
|
||||
def ts_to_csv_multilang(ts_file: str, csv_output: str, languages: list):
|
||||
"""
|
||||
Exportiere zu CSV mit mehreren Sprach-Spalten
|
||||
|
||||
languages = ["English", "Français", "Español", "Niederländisch"]
|
||||
|
||||
Output:
|
||||
Deutsch,English,Français,Español,Niederländisch
|
||||
Eingang,Inbox,Boîte de réception,Bandeja de entrada,Postvak IN
|
||||
...
|
||||
"""
|
||||
|
||||
tree = ET.parse(ts_file)
|
||||
root = tree.getroot()
|
||||
ns = {'ts': 'http://trolltech.com/TS'}
|
||||
|
||||
# Sammle Deutsch-Strings
|
||||
german_strings = []
|
||||
for message in root.findall('.//message', ns):
|
||||
source_elem = message.find('source', ns)
|
||||
if source_elem is not None and source_elem.text:
|
||||
german_strings.append(source_elem.text.strip())
|
||||
|
||||
german_strings = list(dict.fromkeys(german_strings))
|
||||
german_strings.sort()
|
||||
|
||||
# Schreibe CSV mit mehreren Sprachen
|
||||
with open(csv_output, 'w', newline='', encoding='utf-8') as f:
|
||||
writer = csv.writer(f)
|
||||
# Header
|
||||
writer.writerow(['Deutsch'] + languages)
|
||||
# Alle Strings (nur erste Spalte gefüllt)
|
||||
for word in german_strings:
|
||||
row = [word] + ([''] * len(languages))
|
||||
writer.writerow(row)
|
||||
|
||||
print(f"✅ Multi-Language CSV erstellt!")
|
||||
print(f" Datei: {csv_output}")
|
||||
print(f" Strings: {len(german_strings)}")
|
||||
print(f" Sprachen: {', '.join(languages)}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--source', required=True, help='mail-adler_de.ts')
|
||||
parser.add_argument('--output', required=True, help='output.csv')
|
||||
parser.add_argument('--languages', required=True,
|
||||
help='Comma-separated: "English,Français,Español,Niederländisch"')
|
||||
|
||||
args = parser.parse_args()
|
||||
langs = [l.strip() for l in args.languages.split(',')]
|
||||
ts_to_csv_multilang(args.source, args.output, langs)
|
||||
```
|
||||
|
||||
### Verwendung:
|
||||
|
||||
```bash
|
||||
python3 scripts/export_to_csv_multilang.py \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/glossary_all.csv \
|
||||
--languages "English,Français,Español,Niederländisch,Portugiesisch,Italienisch"
|
||||
|
||||
# Output: glossary_all.csv mit 6 leeren Sprach-Spalten
|
||||
```
|
||||
|
||||
**Ergebnis (in Excel):**
|
||||
```csv
|
||||
Deutsch,English,Français,Español,Niederländisch,Portugiesisch,Italienisch
|
||||
Abbrechen,Cancel,Annuler,Cancelar,Annuleren,Cancelar,Annulla
|
||||
Anmeldedaten,Credentials,Identifiants,Credenciales,Inloggegevens,Credenciais,Credenziali
|
||||
...
|
||||
```
|
||||
|
||||
**Jetzt kannst du alle Sprachen in EINER Datei übersetzen!**
|
||||
|
||||
---
|
||||
|
||||
## 7. Import für jede einzelne Spalte
|
||||
|
||||
```bash
|
||||
# Nach du alle Spalten in Excel gefüllt hast:
|
||||
|
||||
# Englisch extrahieren & importieren
|
||||
python3 scripts/import_csv_column_to_ts.py \
|
||||
--csv translations/glossary_all.csv \
|
||||
--column English \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/mail-adler_en.ts
|
||||
|
||||
# Französisch
|
||||
python3 scripts/import_csv_column_to_ts.py \
|
||||
--csv translations/glossary_all.csv \
|
||||
--column Français \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/mail-adler_fr.ts
|
||||
|
||||
# Niederländisch
|
||||
python3 scripts/import_csv_column_to_ts.py \
|
||||
--csv translations/glossary_all.csv \
|
||||
--column Niederländisch \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/mail-adler_nl.ts
|
||||
|
||||
# ... für alle Sprachen
|
||||
```
|
||||
|
||||
**Script dafür:**
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# scripts/import_csv_column_to_ts.py
|
||||
|
||||
import csv
|
||||
import xml.etree.ElementTree as ET
|
||||
import argparse
|
||||
|
||||
def csv_column_to_ts(csv_file: str, column_name: str, ts_source: str, ts_output: str):
|
||||
"""
|
||||
Importiere eine bestimmte Spalte aus CSV zu .ts
|
||||
"""
|
||||
|
||||
# Lese CSV & finde Spalte
|
||||
translations = {}
|
||||
|
||||
with open(csv_file, 'r', encoding='utf-8') as f:
|
||||
reader = csv.DictReader(f) # Nutzt Header als Keys
|
||||
|
||||
for row in reader:
|
||||
deutsch = row['Deutsch'].strip()
|
||||
übersetzt = row.get(column_name, '').strip()
|
||||
|
||||
if deutsch and übersetzt:
|
||||
translations[deutsch] = übersetzt
|
||||
|
||||
print(f"✅ Spalte '{column_name}' geladen: {len(translations)} Übersetzungen")
|
||||
|
||||
# Update .ts
|
||||
tree = ET.parse(ts_source)
|
||||
root = tree.getroot()
|
||||
ns = {'ts': 'http://trolltech.com/TS'}
|
||||
ET.register_namespace('', 'http://trolltech.com/TS')
|
||||
|
||||
updated = 0
|
||||
for message in root.findall('.//message', ns):
|
||||
source_elem = message.find('source', ns)
|
||||
trans_elem = message.find('translation', ns)
|
||||
|
||||
if source_elem is not None and trans_elem is not None:
|
||||
deutsch_text = source_elem.text
|
||||
if deutsch_text in translations:
|
||||
trans_elem.text = translations[deutsch_text]
|
||||
trans_elem.set('type', 'finished')
|
||||
updated += 1
|
||||
|
||||
tree.write(ts_output, encoding='UTF-8', xml_declaration=True)
|
||||
|
||||
print(f"✅ {updated} Strings aktualisiert → {ts_output}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--csv', required=True)
|
||||
parser.add_argument('--column', required=True, help='Spalten-Name')
|
||||
parser.add_argument('--source', required=True)
|
||||
parser.add_argument('--output', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
csv_column_to_ts(args.csv, args.column, args.source, args.output)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Batch-Script für alle Sprachen
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/batch_import_all_languages.sh
|
||||
|
||||
CSV="translations/glossary_all.csv"
|
||||
SOURCE="translations/mail-adler_de.ts"
|
||||
LANGUAGES=("English" "Français" "Español" "Niederländisch" "Portugiesisch" "Italienisch")
|
||||
LANG_CODES=("en" "fr" "es" "nl" "pt" "it")
|
||||
|
||||
for i in "${!LANGUAGES[@]}"; do
|
||||
LANG="${LANGUAGES[$i]}"
|
||||
CODE="${LANG_CODES[$i]}"
|
||||
|
||||
echo "🌍 Importiere $LANG..."
|
||||
|
||||
python3 scripts/import_csv_column_to_ts.py \
|
||||
--csv "$CSV" \
|
||||
--column "$LANG" \
|
||||
--source "$SOURCE" \
|
||||
--output "translations/mail-adler_${CODE}.ts"
|
||||
|
||||
lrelease "translations/mail-adler_${CODE}.ts"
|
||||
done
|
||||
|
||||
echo "✅ Alle Sprachen importiert & kompiliert!"
|
||||
```
|
||||
|
||||
### Verwendung:
|
||||
|
||||
```bash
|
||||
chmod +x scripts/batch_import_all_languages.sh
|
||||
./scripts/batch_import_all_languages.sh
|
||||
|
||||
# Output:
|
||||
# 🌍 Importiere English...
|
||||
# ✅ 247 Strings aktualisiert → translations/mail-adler_en.ts
|
||||
# 🌍 Importiere Français...
|
||||
# ✅ 247 Strings aktualisiert → translations/mail-adler_fr.ts
|
||||
# ...
|
||||
# ✅ Alle Sprachen importiert & kompiliert!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Zusammenfassung: Der EASIEST Workflow
|
||||
|
||||
### Super Einfach (für dich perfekt):
|
||||
|
||||
**Schritt 1: EXPORT (Auto)**
|
||||
```bash
|
||||
python3 scripts/export_to_csv_multilang.py \
|
||||
--source translations/mail-adler_de.ts \
|
||||
--output translations/glossary_all.csv \
|
||||
--languages "English,Français,Español,Niederländisch,Portugiesisch,Italienisch"
|
||||
```
|
||||
|
||||
**Schritt 2: BEARBEITEN (Excel)**
|
||||
```
|
||||
Öffne glossary_all.csv in Excel
|
||||
Fülle alle Spalten mit Übersetzungen
|
||||
(oder nutze LM Studio: Copy-Paste jedes Wort)
|
||||
Speichern (Format: CSV UTF-8!)
|
||||
```
|
||||
|
||||
**Schritt 3: IMPORT (Auto)**
|
||||
```bash
|
||||
./scripts/batch_import_all_languages.sh
|
||||
```
|
||||
|
||||
**Schritt 4: RELEASE (Auto)**
|
||||
```bash
|
||||
git add translations/
|
||||
git commit -m "Add all translations"
|
||||
git push
|
||||
# GitHub Action macht den Rest
|
||||
```
|
||||
|
||||
**Fertig! Keine .ts-Bearbeitung, keine komplexe Formate, nur Excel!**
|
||||
Reference in New Issue
Block a user