""" Set ERPNext to Romanian + add custom translations for DiDi labels. Run: python setup-translations.py """ import requests import json import sys import io sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') URL = "http://localhost:8080" s = requests.Session() login = s.post(f"{URL}/api/method/login", data={"usr": "Administrator", "pwd": "admin"}) if login.status_code != 200: print("Login failed"); exit(1) print("Logged in as Administrator") # ── 1. Set system language to Romanian ── print("\n1. Setting system language to Romanian...") r = s.put(f"{URL}/api/resource/System%20Settings/System%20Settings", json={ "language": "ro", "date_format": "dd.mm.yyyy", "time_format": "HH:mm:ss", "number_format": "#.###,##", "country": "Romania", "first_day_of_the_week": "Monday", }) print(f" System Settings: {r.status_code}") # ── 2. Set Administrator language to RO ── print("\n2. Setting Administrator language...") r = s.put(f"{URL}/api/resource/User/Administrator", json={"language": "ro"}) print(f" Admin language: {r.status_code}") # Also API user r = s.put(f"{URL}/api/resource/User/website_api@didi-erp", json={"language": "ro"}) print(f" API user language: {r.status_code}") # ── 3. Custom translations for DiDi labels ── print("\n3. Adding custom translations...") TRANSLATIONS = { # DocType names "Sales Invoice": "Factura de Vanzare", "Customer": "Client", "Lead": "Lead", "Payment Log": "Jurnal Plati", "Payment Entry": "Incasare", "Service Agreement": "Acord Servicii", "Website Content": "Continut Website", "Analysis Report": "Raport Analiza", "Subscription Plan": "Plan Abonament", "Item": "Articol / Serviciu", "Item Group": "Grup Articole", "Supplier": "Furnizor", "Company": "Companie", "Account": "Cont Contabil", "Purchase Invoice": "Factura de Achizitie", "Email Template": "Sablon Email", "Sales Taxes and Charges Template": "Sablon Taxe (TVA)", "Lead Source": "Sursa Lead", "Sales Stage": "Etapa Vanzare", # Common fields "Customer Name": "Nume Client", "Customer Type": "Tip Client", "Customer Group": "Grup Clienti", "Territory": "Teritoriu", "Grand Total": "Total General", "Net Total": "Total Net", "Outstanding Amount": "Suma Restanta", "Posting Date": "Data Emiterii", "Due Date": "Data Scadenta", "Status": "Status", "Currency": "Moneda", "Paid": "Platita", "Unpaid": "Neplatita", "Overdue": "Restanta", "Cancelled": "Anulata", "Draft": "Ciorna", "Submitted": "Confirmata", "Amount": "Suma", "Rate": "Pret Unitar", "Quantity": "Cantitate", "Qty": "Cant.", "Description": "Descriere", "Total": "Total", "Tax": "Taxa", "Taxes": "Taxe", "Discount": "Reducere", "Payment Type": "Tip Plata", "Receive": "Incasare", # DiDi custom fields "Analysis Consumed": "Analiza Consumata", "Analysis Session ID": "ID Sesiune Analiza", "DiDi User ID": "ID Utilizator DiDi", "IAM Role": "Rol IAM", "Active Plan": "Plan Activ", "Plan Activation Date": "Data Activare Plan", "Source Form": "Formular Sursa", "Page Origin": "Pagina Origine", # Custom DocType fields "Acceptance Date": "Data Acceptarii", "Client IP": "IP Client", "Terms Version": "Versiune Termeni", "Agreement HTML": "Continut Acord", "Stripe Payment Intent ID": "ID Plata Stripe", "Stripe Session ID": "ID Sesiune Stripe", "Raw Webhook Data": "Date Brute Webhook", "Event Type": "Tip Eveniment", "Page Slug": "Slug Pagina", "Section Key": "Cheie Sectiune", "Display Order": "Ordine Afisare", "Is Active": "Activ", "Content RO": "Continut RO", "Content EN": "Continut EN", "Extra Data": "Date Extra", "Report Title": "Titlu Raport", "Generated At": "Generat La", "Result JSON": "Rezultat JSON", "PDF File": "Fisier PDF", "Media Type": "Tip Media", "Component": "Componenta", # Workspace & navigation "Home": "Acasa", "Settings": "Setari", "Search": "Cauta", "Help": "Ajutor", "Logout": "Deconectare", "Save": "Salveaza", "Submit": "Confirma", "Cancel": "Anuleaza", "Delete": "Sterge", "New": "Nou", "Edit": "Editeaza", "Print": "Tipareste", "Download": "Descarca", "Filter": "Filtreaza", "Sort By": "Sorteaza dupa", "Created By": "Creat de", "Modified By": "Modificat de", "Owner": "Proprietar", "Creation": "Data Creare", "Modified": "Data Modificare", "Actions": "Actiuni", "Add Row": "Adauga Rand", "Select All": "Selecteaza Tot", # Reports "Balance Sheet": "Bilant", "Profit and Loss Statement": "Cont Profit si Pierdere", "General Ledger": "Registru General", "Trial Balance": "Balanta de Verificare", "Accounts Receivable": "Debitori", "Accounts Payable": "Creditori", # CRM "Lead Name": "Nume Lead", "Email Address": "Adresa Email", "Phone": "Telefon", "Source": "Sursa", "Campaign": "Campanie", "Converted": "Convertit", "Do Not Contact": "Nu Contacta", "Replied": "Raspuns", "Interested": "Interesat", "Quotation": "Oferta", "Opportunity": "Oportunitate", # Subscription "Plan Name": "Nume Plan", "Billing Interval": "Interval Facturare", "Cost": "Cost", "Month": "Lunar", "Year": "Anual", # Common actions/buttons "Amend": "Modifica", "Duplicate": "Duplica", "Rename": "Redenumeste", "Reload": "Reincarca", "Close": "Inchide", "Yes": "Da", "No": "Nu", "Confirm": "Confirma", "Apply": "Aplica", "Clear": "Curata", "Refresh": "Actualizeaza", "Export": "Exporta", "Import": "Importa", # Misc "Romania": "Romania", "Commercial": "Comercial", "Individual": "Persoana Fizica", "Company": "Companie", "All Item Groups": "Toate Grupurile", "DiDi Services": "Servicii DiDi", "Succeeded": "Reusita", "Failed": "Esuata", "Refunded": "Rambursata", "Pending": "In Asteptare", "Completed": "Finalizat", "Accepted": "Acceptat", "Expired": "Expirat", } created = 0 skipped = 0 for source, translated in TRANSLATIONS.items(): # Check if translation exists check = s.get(f"{URL}/api/resource/Translation", params={ "filters": json.dumps([["language", "=", "ro"], ["source_text", "=", source]]), "fields": json.dumps(["name"]), "limit_page_length": 1, }) existing = check.json().get("data", []) if existing: 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: print(f" Error: {source} -> {r.status_code}") print(f" Created: {created}, Skipped (existing): {skipped}") # ── 4. Clear cache to apply translations ── print("\n4. Clearing cache...") r = s.post(f"{URL}/api/method/frappe.client.clear_cache") print(f" Cache cleared: {r.status_code}") print(f"\nDone! {created} traduceri noi adaugate.") print("Refresh ERPNext (Ctrl+Shift+R) pentru a vedea traducerile.")