old_to_translation.py

Wandelt Olivers alte Übersetzungen (match.json) ins Paketformat und vergleicht sie mit dem Englischen (Zahlen, Eigennamen, Absätze, Länge).

Ablage beim Arbeiten: tools/old_to_translation.py. Herunterladen: auf den Dateinamen über dem Code klicken.

old_to_translation.py
"""old_to_translation.py RAW JAHR -> translations/<JAHR>_alt.json + Pruefbericht
Wandelt Olivers alte edwiki-Uebersetzungen (aus match.json) ins Paketformat und vergleicht sie mit dem Englischen:
Zahlen, Eigennamen, Absatzzahl, Laenge. Auffaellige Meldungen landen im Bericht zur Durchsicht."""
import json, re, sys, csv
from pathlib import Path
R = Path(sys.argv[1]); year = int(sys.argv[2])
EN = {}
for f in (R / 'EN').glob('*.json'):
    if int(f.stem[:4]) - 1286 == year:
        for a in json.load(open(f, encoding='utf-8'))['articles']: EN[a['id']] = a
idx = [r for r in csv.DictReader(open(R / 'index.csv', encoding='utf-8'), delimiter=';') if int(r['date'][:4]) == year]
M = {o['fid']: o for o in json.load(open('match.json', encoding='utf-8')) if o.get('fid')}
 
def plain(t):
    out = []
    for line in t.split('\n'):
        line = line.rstrip()
        if re.fullmatch(r'>\s*', line): continue
        line = re.sub(r'^>\s?', '', line)
        line = re.sub(r'^\s+[*-]\s+', '• ', line)
        line = line.replace('**', '')
        line = re.sub(r'//(.+?)//', r'*\1*', line)
        line = re.sub(r'\\\\\s*$', '', line)
        if line.strip(): out.append(line.strip())
    return '\n'.join(out)
 
NUM = re.compile(r'\d[\d,.]*')
def nums(t): return {re.sub(r'[,.]', '', n).lstrip('0') for n in NUM.findall(t)} - {''}
def names(t):
    c = set(re.findall(r"\b([A-Z][a-z’'-]+(?: [A-Z][a-z’'-]+)+)", t))
    return {x for x in c if not x.split()[0] in ('The', 'A', 'An', 'In', 'This', 'Pilots', 'At', 'Some', 'Many', 'As', 'We', 'It', 'If')}
out, rep = {}, []
for i, r in enumerate(idx):
    e = EN[r['frontier_id']]; o = M.get(r['frontier_id'])
    if not o: rep.append(f'#{i} FEHLT (neu übersetzen): {e["title"]}'); continue
    de = plain(o['body']); out[r['frontier_id']] = dict(source='eigene', title=o['title'].strip(), body=de)
    flags = []
    mn = sorted(n for n in nums(e['body']) - nums(de) if len(n) > 1)
    if mn: flags.append('Zahlen fehlen: ' + ' '.join(mn))
    # Genitiv-s weg; Institutionen/Titel werden uebersetzt und zaehlen nicht
    INST = r'^(Federal|Imperial|Alliance|Galactic|Pleiades|Witch|Interstellar|Pilots|Advanced|Reactive|Military|Battle|Performance|New|Senate|Defence|Fleet|Civilian|Other|Although|While|Obviously|Prime|President|Councillor|Admiral|Emperor|Imperator|Commander|Senator|Lady|Mr|Ms|Agronomic|Onion|Cerberus|Alliance)\b'
    def core(n): return re.sub(r"[’']s?$", '', n)
    nm = sorted({core(n) for n in names(e['body'])} - {''})
    nm = [n for n in nm if not re.match(INST, n) and n not in de and n.split()[-1] not in de]
    if nm: flags.append('Namen fehlen: ' + '; '.join(nm))
    pe, pd = len([p for p in e['body'].split('\n') if p.strip()]), len(de.split('\n'))
    if abs(pe - pd) > 1: flags.append(f'Absätze EN {pe} / DE {pd}')
    q = len(de) / max(1, len(e['body']))
    if q < 0.95 or q > 1.6: flags.append(f'Länge DE/EN {q:.2f}')
    if flags: rep.append(f'#{i} {r["date"]} {e["title"]} | ' + ' | '.join(flags))
Path('translations').mkdir(exist_ok=True)
json.dump(out, open(f'translations/{year}_alt.json', 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
print(len(out), 'alte Übersetzungen;', len(rep), 'auffällig/fehlend')
print('\n'.join(rep))