"""Fix ALL remaining untranslated labels in ERPNext.""" import sys, io, json, requests sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') URL = "http://localhost:8080" s = requests.Session() s.post(f"{URL}/api/method/login", data={"usr": "Administrator", "pwd": "admin"}) print("Logged in") T = { # ── Payment Entry ── "Party Name": "Nume Client", "Nume partid": "Nume Client", "Party": "Client", "Partener": "Client", "Party Type": "Tip Client", "Tip de partid": "Tip Client", "Party Balance": "Sold Client", "Balanța Party": "Sold Client", "Paid From": "Platit Din", "Contul plătit De la": "Platit Din", "Paid To": "Platit Catre", "Contul Plătite": "Platit Catre", "Account Balance (From)": "Sold Cont (Sursa)", "Account Balance (To)": "Sold Cont (Destinatie)", "Account Currency (From)": "Moneda Cont (Sursa)", "Account Currency (To)": "Moneda Cont (Destinatie)", "Paid Amount": "Suma Platita", "Paid Amount After Tax (RON)": "Suma Platita dupa Taxe (RON)", "Received Amount": "Suma Primita", "Received Amount After Tax (RON)": "Suma Primita dupa Taxe (RON)", "Suma primită (RON)": "Suma Primita (RON)", "Sumă Primită (RON)": "Suma Primita (RON)", "Reference No": "Nr. Referinta", "Cecul / de referință nr": "Nr. Referinta Plata", "Reference Date": "Data Referinta", "Cec/Dată de Referință": "Data Referinta Plata", "Payment References": "Referinte Plata", "Referințe de plată": "Referinte Plata", "Allocated": "Alocat", "Unallocated Amount": "Suma Nealocata", "Suma nealocată (RON)": "Suma Nealocata (RON)", "Total Allocated Amount": "Total Alocat", "Suma totală alocată (RON)": "Total Alocat (RON)", "Difference Amount": "Diferenta", "Diferența Sumă (RON)": "Diferenta (RON)", "Outstanding": "Restant", "remarcabil (RON)": "Restant (RON)", "outstanding (RON)": "Restant (RON)", "remarkable (RON)": "Restant (RON)", "Payment Type": "Tip Plata", "Tipul de plată": "Tip Plata", "Plata De la / la": "Plata De la / Catre", "Contact Person": "Persoana de Contact", "Persoana de Contact": "Persoana de Contact", "Transaction ID": "ID Tranzactie", "ID-ul de tranzacție": "ID Tranzactie", "Cheque/Reference No": "Nr. Referinta Plata", "Cheque/Reference Date": "Data Referinta Plata", "Source Exchange Rate": "Curs Valutar Sursa", "Target Exchange Rate": "Curs Valutar Destinatie", "Connections": "Legaturi", "Account Dimensions": "Dimensiuni Contabile", "Dimensiuni contabile": "Dimensiuni Contabile", "More Information": "Mai Multe Informatii", "Mai multe informatii": "Mai Multe Informatii", "Remarks": "Observatii", "Remarci": "Observatii", "In Words (Company Currency)": "In Litere (Moneda Companie)", "În cuvinte (Compania valutar)": "In Litere (Moneda Companie)", "In Words": "In Litere", "În cuvinte": "In Litere", "In Words (RON)": "In Litere (RON)", "În cuvinte (RON)": "In Litere (RON)", "Taxes and Charges": "Taxe si Impozite", "Impozite și Taxe": "Taxe si Impozite", "Total Taxes and Charges": "Total Taxe", "Total Impozite și Taxe (RON)": "Total Taxe (RON)", "Tax Withholding": "Retinere Taxe", "Descărcarea de impozite": "Retinere Taxe", "Deductions or Losses": "Deduceri sau Pierderi", "Deduceri sau Pierderi": "Deduceri sau Pierderi", "Naming Series": "Serie Numerotare", "Serii": "Serie Numerotare", "Account Holder": "Titular Cont", "Titularul Contului": "Titular Cont", "Section Subscriptions": "Sectiunea Abonamente", "Secțiunea de abonamente": "Sectiunea Abonamente", "Is Opening": "Este Deschidere", "Se deschide": "Este Deschidere", "Deschiderea este de intrare": "Inregistrare de Deschidere", "Tax Rate": "Cota Impozit", "Cota de impozitare": "Cota Impozit", "Statistics": "Statistici", "Statistici": "Statistici", "Graph": "Grafic", # ── Sales Invoice ── "Additional Info": "Informatii Suplimentare", "Billing Address": "Adresa de Facturare", "Adresa De Facturare": "Adresa de Facturare", "Shipping Address": "Adresa de Livrare", "Adresa de livrare": "Adresa de Livrare", "Company Address": "Adresa Companie", "Adresă Companie": "Adresa Companie", "Rounding Adjustment": "Ajustare Rotunjire", "Ajustare Rotunjire (RON)": "Ajustare Rotunjire (RON)", "Rotunjire ajustare (RON)": "Ajustare Rotunjire (RON)", "Write Off Amount": "Suma Casare", "Anulați suma (RON)": "Suma Casare (RON)", "Scrie Off Suma (RON)": "Suma Casare (RON)", "Apply Additional Discount On": "Aplica Discount Suplimentar Pe", "Aplicați Discount suplimentare La": "Aplica Discount Suplimentar Pe", "Items": "Articole", "Articole": "Articole", "Total Quantity": "Cantitate Totala", "Cantitatea totala": "Cantitate Totala", "Commission": "Comision", "Comision": "Comision", "Company Tax ID": "CUI Companie", "Due Date": "Data Scadenta", "Data scadentă de plată": "Data Scadenta", "Base Change Amount (RON)": "Suma Modificare Baza (RON)", "De schimbare a bazei Suma (RON)": "Suma Modificare Baza (RON)", "Debit To": "Cont Debit", "Debit Pentru": "Cont Debit", "Accounting Details": "Detalii Contabilitate", "Detalii Contabilitate": "Detalii Contabilitate", "Customer PO Details": "Detalii Comanda Client", "Detalii PO pentru clienți": "Detalii Comanda Client", "Additional Discount": "Discount Suplimentar", "Discount suplimentar": "Discount Suplimentar", "Additional Discount Amount": "Suma Discount Suplimentar", "Discount suplimentar Suma (RON)": "Suma Discount Suplimentar (RON)", "Additional Discount Percentage": "Procent Discount Suplimentar", "Procent de reducere suplimentară": "Procent Discount Suplimentar", "Suma de reducere suplimentară (RON)": "Suma Discount Suplimentar (RON)", "Sales Team": "Echipa Vanzari", "Echipa de vânzări": "Echipa Vanzari", "Taxes and Charges Calculation": "Calcul Taxe", "Impozite și Taxe Calcul": "Calcul Taxe", "Print Language": "Limba Tiparire", "Limba de imprimare": "Limba Tiparire", "Price List": "Lista de Preturi", "Lista Prețuri": "Lista de Preturi", "Packing List": "Lista de Ambalare", "Lista de ambalare": "Lista de Ambalare", "Price List Currency": "Moneda Lista Preturi", "Lista de pret Valuta": "Moneda Lista Preturi", "Price List Exchange Rate": "Curs Valutar Lista Preturi", "Lista de schimb valutar": "Curs Valutar Lista Preturi", "Time Sheet List": "Lista Pontaj", "Listă de timp Sheet": "Lista Pontaj", "Net Total": "Total Net", "Net total (RON)": "Total Net (RON)", "Customer Name": "Nume Client", "Company Name": "Nume Companie", "Nume Companie": "Nume Companie", "Write Off": "Casare Creante", "Pierderi din Creante": "Casare Creante", "Advance Payments": "Plati in Avans", "Plățile în avans": "Plati in Avans", "Payments": "Plati", "Plăți": "Plati", "Posting Time": "Ora Inregistrare", "PostingTime": "Ora Inregistrare", "Postarea de timp": "Ora Inregistrare", "Pricing Rules": "Reguli de Pret", "Reguli privind prețurile": "Reguli de Pret", "Rounded Total": "Total Rotunjit", "Rotunjite total (RON)": "Total Rotunjit (RON)", "Redeem Loyalty Points": "Rascumparare Puncte Loialitate", "Răscumpărarea punctelor de loialitate": "Rascumparare Puncte Loialitate", "Exchange Rate": "Curs Valutar", "Rata de schimb": "Curs Valutar", "Print Settings": "Setari Tiparire", "Setări de imprimare": "Setari Tiparire", "Outstanding Amount": "Suma Restanta", "Suma Restanta (RON)": "Suma Restanta (RON)", "Payment Terms": "Termeni Plata", "Termeni de plată": "Termeni Plata", "Terms and Conditions": "Termeni si Conditii", "Termeni si conditii": "Termeni si Conditii", "Total Advance": "Total Avans", "Total de Advance (RON)": "Total Avans (RON)", "Totals": "Totaluri", "Totaluri": "Totaluri", "Currency and Price List": "Moneda si Lista de Preturi", "Valută și lista de prețuri": "Moneda si Lista de Preturi", "Subscription": "Abonament", "Changes": "Modificari", # ── Customer ── "Primary Customer Address": "Adresa Principala Client", "Adresa primară a clientului": "Adresa Principala Client", "Address and Contact": "Adresa si Contact", "Adresa și Contact": "Adresa si Contact", "Tax Category": "Categorie Fiscala", "Categoria fiscală": "Categorie Fiscala", "Primary Customer Contact": "Contact Principal Client", "Contact primar client": "Contact Principal Client", "Default Accounts": "Conturi Implicite", "Conturi implicite": "Conturi Implicite", "Defaults": "Valori Implicite", "Implicite": "Valori Implicite", "Internal Customer": "Client Intern", "Credit Limit and Payment Terms": "Limita Credit si Termeni Plata", "Limita de credit și termenii de plată": "Limita Credit si Termeni Plata", "Primary Address and Contact": "Adresa si Contact Principal", "Loyalty Points": "Puncte Loialitate", "Puncte de loialitate": "Puncte Loialitate", "Default Payment Terms Template": "Sablon Termeni Plata Standard", "Șablonul Termenii de plată standard": "Sablon Termeni Plata Standard", "Tax ID": "Cod Fiscal (CUI)", "ID impozit": "Cod Fiscal (CUI)", "Email ID": "Adresa Email", "ID-ul de e-mail": "Adresa Email", # ── Lead ── "Lead Name": "Nume Lead", "Email Address": "Adresa Email", "Lead Source": "Sursa Lead", "Campaign Name": "Nume Campanie", # ── Common / Navigation ── "Activity": "Activitate", "Activitate": "Activitate", "Assigned To": "Atribuit Pentru", "Atribuit pentru": "Atribuit Pentru", "Attachments": "Atasamente", "Ataşamente": "Atasamente", "Tags": "Etichete", "Etichete": "Etichete", "Action": "Actiune", "Acțiune": "Actiune", "Follow": "Urmareste", "Urma": "Urmareste", "Comment": "Comentariu", "Comentarii": "Comentarii", "Comments": "Comentarii", "New Email": "Email Nou", "Email nou": "Email Nou", "Type a reply / comment": "Scrie un raspuns / comentariu", "No new notifications": "Nicio notificare noua", "Help Dropdown": "Meniu Ajutor", "Meniul drop-down Ajutor": "Meniu Ajutor", "User Menu": "Meniu Utilizator", "Toggle Sidebar": "Comuta Bara Laterala", "Comutați bara laterală": "Comuta Bara Laterala", "You last edited this": "Ultima editare", "You created this": "Creat de tine", "You submitted this document": "Document confirmat de tine", "yesterday": "ieri", "Bank Transaction": "Tranzactie Bancara", "Tranzacție bancară": "Tranzactie Bancara", "Settle": "Achita", "Achita": "Achita", "General Ledger": "Registru Contabil", "Registru Contabil": "Registru Contabil", } created = 0 skipped = 0 for source, translated in T.items(): check = s.get(f"{URL}/api/resource/Translation", params={ "filters": json.dumps([["language", "=", "ro"], ["source_text", "=", source]]), "fields": json.dumps(["name", "translated_text"]), "limit_page_length": 1, }) existing = check.json().get("data", []) if existing: # Update if different if existing[0].get("translated_text") != translated: s.put(f"{URL}/api/resource/Translation/{existing[0]['name']}", json={"translated_text": translated}) created += 1 else: skipped += 1 continue r = s.post(f"{URL}/api/resource/Translation", json={ "language": "ro", "source_text": source, "translated_text": translated, }) if r.status_code in (200, 201): created += 1 else: skipped += 1 print(f"Created/Updated: {created}, Skipped: {skipped}") # Clear cache s.post(f"{URL}/api/method/frappe.client.clear_cache") print("Cache cleared. Ctrl+Shift+R in browser.")