Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS will be completely phased out by mid-2025. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit 2637f399 authored by Joze RIHTARSIC's avatar Joze RIHTARSIC
Browse files

[EDELIVERY-12747] add configuration options for update/create user alerts and...

[EDELIVERY-12747] add configuration options for update/create user alerts and fix language loading from filesystem
parent 3baeee14
No related branches found
No related tags found
No related merge requests found
Pipeline #201340 failed
Showing
with 573 additions and 1137 deletions
{
"column.selection.link.all": "Tot",
"column.selection.link.none": "Nimic",
"column.selection.link.show": "Toate coloanele",
"column.selection.link.hide": "Ascunde coloanele",
"cancel.dialog.text": "Doriti sa anulati toate modificarile care nu au fost inca salvate?",
"cancel.dialog.title": "Modificari in Curs",
"certificate.dialog.button.close": "Inchide",
"certificate.dialog.title": "Detalii Certificat",
"confirmation.dialog.button.no": "Nu",
"confirmation.dialog.button.yes": "Da",
"credentials.dialog.button.close": "Inchide",
"credentials.dialog.button.copy.access.token": "Copiaza valoarea Tokenului de access",
"credentials.dialog.button.import": "Importa",
"credentials.dialog.button.generate.access.token": "Genereaza un Token de access",
"credentials.dialog.button.save.certificate": "Salveaza Certificatul",
"credentials.dialog.error.read.certificate": "O eroare a fost detectata la citirea Certificatului. Verificati daca fisierul incarcat este un Certificat valid",
"credentials.dialog.error.upload.certificate": "O eroare a fost detectata la incarcarea Certificatului [{{fileName}}]. {{errorDescription}}",
"credentials.dialog.success.generate.token": "Tokenul cu identificatorul: \"{{responseIdentifier}}\" si valoarea: \"{{responseValue}}\" a fost generat!<br /><br />Copiati valoarea Tokenului de access si salvati-o intr-un loc sigur.<br /><br />Nu veti mai putea sa obtineti valoarea Tokenului de access o data ce apasati pe <b>Inchide</b>.",
"credentials.dialog.label.active": "Activ",
"credentials.dialog.label.certificate.validity.period": "Perioada de valabilitate a Certificatului",
"credentials.dialog.label.description": "Descriere",
"credentials.dialog.label.subject.name": "Subiect",
"credentials.dialog.label.smp.certificate.id": " Identificator certificat SMP",
"credentials.dialog.label.invalid.from": "Data \"Activ de la\" invalida",
"credentials.dialog.label.invalid.expire.on": "Data \"Expira la\" invalida",
"credentials.dialog.label.issuer.name": "Nume emitent",
"credentials.dialog.label.serial.number": "Numar de serie",
"credentials.dialog.label.validity": "Periada de valabilitate",
"credentials.dialog.placeholder.end.date": "Data finala",
"credentials.dialog.placeholder.expire.on": "Expira la",
"credentials.dialog.placeholder.start.date": "Date initiala",
"credentials.dialog.placeholder.valid.from": "Valabil de la",
"dialog.button.close": "Inchide",
"dialog.button.no": "Nu",
"dialog.button.ok": "OK",
"dialog.button.yes": "Da",
"document.property.dialog.button.ok": "OK",
"document.property.dialog.button.cancel": "Anuleaza",
"document.property.dialog.error.property.already.exists": "Proprietatea exista deja!",
"document.property.dialog.label.close": "Inchide",
"document.property.dialog.label.property.description": "Descrierea proprietatii:",
"document.property.dialog.label.property.name": "Numele proprietatii:",
"document.property.dialog.label.property.type": "Tipul proprietatii:",
"document.property.dialog.label.property.value": "Valoarea proprietatii:",
"document.property.dialog.title.new.mode": "Creeaza Propietatea Document",
"document.property.dialog.title.edit.mode": "Schimbati Proprietatea Document",
"expired.password.dialog.text": "Parola dumneavoastra este mai veche de trei luni. Va rugam sa o schimbati cat mai repede posibil!",
"expired.password.dialog.title": "Parola pe cale sa expire",
"manage.members.dialog.button.close": "Inchide",
"manage.members.dialog.title.invite.mode": "Invita Membru {{membershipType}}",
"manage.members.dialog.title.edit.mode": "Modifica Membru {{membershipType}}",
"member.dialog.button.close": "Inchide",
"member.dialog.button.save": "Salveaza",
"member.dialog.hint.choose.role": "Alege rolul membrului",
"member.dialog.hint.type.username": "Introduceti numele utilizatorului sau numele complet necesar localizarii utilizatorului si alegeti utilizatorul dorit din lista de rezultate",
"member.dialog.label.choose.user": "Alegeti Utilizatorul de invitat",
"member.dialog.label.invite.members": "Sunteti pe cale sa invitati membrii la {{target}}.",
"member.dialog.placeholder.role.type": "Rolul membrului",
"manage.dialog.title.invite.mode": "Invita membrul {{membershipType}}",
"manage.dialog.title.edit.mode": "Schimbati membrul {{membershipType}}",
"member.dialog.tooltip.role.type": "Tipul rolului detinut de membru.",
"object.properties.dialog.button.close": "Inchide",
"object.properties.dialog.header.key": "Cheie",
"object.properties.dialog.header.value": "Valoare",
"password.change.dialog.button.confirm": "Seteaza/modificati parola",
"password.change.dialog.button.close": "Inchide",
"password.change.dialog.error.old.password.reused": "Noua parola nu trebuie sa fie egala cu vechea parola actuala!",
"password.change.dialog.error.passwords.mismatch": "Confirmare parolei noi nu se potriveste cu noua parola!",
"password.change.dialog.label.confirm.new.password": "Confirmarea parolei noi",
"password.change.dialog.label.username": "Schimbati parola pentru Utilizator",
"password.change.dialog.label.new.password": "Parola noua",
"password.change.dialog.label.password.admin": "Parola de administrator pentru [{{username}}]",
"password.change.dialog.label.password.user": "Parola actuala",
"password.change.dialog.legend.required.fields": "* campuri obligatorii",
"password.change.dialog.title": "Seteaza/Schimba Parola",
"password.change.dialog.success.password.change.admin": "Parola a fost setata/schimbata cu success.",
"password.change.dialog.success.password.change.user": "Parola a fost setata/schimbata cu success. Conectati-va din nou la aplicatie folosind noua parola!",
"property.details.dialog.button.ok": "OK",
"property.details.dialog.button.cancel": "Anuleaza",
"property.details.dialog.error.invalid.property": "Proprietate invalida",
"property.details.dialog.error.validation": "A aparut o eroare la Validarea proprietatii",
"property.details.dialog.label.use.system.default.value": "Utilizati valoarea implicata a Sistemului",
"property.details.dialog.label.property.value": "Valoarea Proprietatii:",
"property.details.dialog.legend.description": "Descriere:",
"property.details.dialog.title.edit.mode": "Modificaarea Proprietatii {{type}}",
"property.details.dialog.title.new.mode": "Proprietate Noua {{type}}",
"session.expiration.dialog.button.expire": "Extinde",
"session.expiration.dialog.button.logout": "Deconectare",
"session.expiration.dialog.title": "Extindeti sesiunea",
"session.expiration.dialog.label.session.about.to.expire": "Sesiunea dvs. este pe cale sa expire in <b>{{timeLeft}}</b> secunde!<br />Doriti sa va deconectati acum sau sa o prelungiti pentru inca <b>{{timeout}}</b> secunde?",
"alert.panel.title": "Alerte",
"alert.panel.user.title": "{{value}} (E-mail: '{{mailTo}}')",
"certificate.panel.title": "Datele certificatului selectat",
"certificate.panel.label.alias": "Alias",
"certificate.panel.label.crl": "Adresa URL a listei de revocare a certificatelor",
"certificate.panel.label.issuer": "Emitent",
"certificate.panel.label.public.key.type": "Tipul cheii publice",
"certificate.panel.label.serial.number": "Numar de serie",
"certificate.panel.label.smp.certificate.id": "Identificator certificat SMP",
"certificate.panel.label.subject.name": "Numele subiectului",
"certificate.panel.label.valid.from": "Valabil de la",
"certificate.panel.label.valid.to": "Valabil pana la",
"certificate.panel.placeholder.alias": "Alias",
"certificate.panel.placeholder.crl": "Certificate revocation list URL",
"certificate.panel.placeholder.issuer": "Emitent",
"certificate.panel.placeholder.public.key.type": "Tipul cheii publice",
"certificate.panel.placeholder.smp.certificate.id": "Identificator certificat SMP",
"certificate.panel.placeholder.serial.number": "Numar de serie",
"certificate.panel.placeholder.subject.name": "Numele subiectului",
"certificate.panel.placeholder.valid.from": "Valabil pana la data",
"certificate.panel.placeholder.valid.to": "Valabil pana la data",
"document.properties.panel.label.filter": "Filtru",
"document.properties.panel.label.property": "Proprietate",
"document.properties.panel.label.value": "Valoare",
"document.properties.panel.label.no.properties.found": "Nu s-au gasit proprietati ale Documentului",
"document.properties.panel.label.select.page": "Selectati pagina cu proprietati",
"document.properties.panel.label.expand.collapse": "Extinde/Restrange",
"document.properties.panel.tooltip.expand.collapse": "Extinde/Restrange panoul cu proprietati",
"document.properties.panel.label.create": "Creeaza",
"document.properties.panel.label.delete.remove": "Sterge",
"document.properties.panel.label.edit": "Schimba",
"document.properties.panel.label.reset": "Reseteaza modificarile",
"document.properties.panel.tooltip.create": "Creeaza proprietate noua",
"document.properties.panel.tooltip.edit": "Schimba proprietate",
"document.properties.panel.tooltip.delete.remove": "Sterge proprietatea selectata",
"document.properties.panel.tooltip.reset": "Reseteaza modificarile",
"membership.panel.button.invite.member": "Invita membru",
"membership.panel.button.edit.membership": "Schimba",
"membership.panel.button.delete.membership": "Sterge",
"membership.panel.delete.confirmation.dialog.title": "Sterge membru",
"membership.panel.delete.confirmation.dialog.description": "Actiunea va sterge membrul [\"{{username}}\"]!<br/><br/>Doriti sa continuati?",
"membership.panel.label.filter": "Filtru membri",
"membership.panel.label.full.name": "Numele complet",
"membership.panel.label.member.of": "Membru al",
"membership.panel.label.no.filter.results": "Niciun membru direct care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"membership.panel.label.no.data.found": "Fara membri directi pentru domeniu",
"membership.panel.label.role.type": "Tipul rolului",
"membership.panel.label.username": "Nume de utilizator",
"membership.panel.placeholder.filter": "Filtru membri",
"membership.panel.title.domain": "Membrii directi de Domeniu {{value}}",
"membership.panel.title.group": "Membrii directi de Grup {{value}}",
"membership.panel.title.resource": "Membrii directi de Resursa",
"membership.panel.tooltip.invite.member": "Invita membru nou",
"membership.panel.tooltip.edit.membership": "Schimba calitatea de membru a utilizatorului selectat",
"membership.panel.tooltip.delete.membership": "Sterge calitatea de membru selectata",
"user.profile.panel.button.reset": "Reseteaza",
"user.profile.panel.button.save": "Salveaza",
"user.profile.panel.button.update.password": "Setati/modificati parola",
"user.profile.panel.hint.choose.member.role": "Alegeti rolul membrului",
"user.profile.panel.error.email": "Adresa de e-mail este invalida!",
"user.profile.panel.label.active": "Activ",
"user.profile.panel.label.application.role": "Rolul in aplicatie",
"user.profile.panel.label.email": "Adresa de e-mail",
"user.profile.panel.label.example": "Exemplu de data/ora",
"user.profile.panel.label.full.name": "Nume complet (nume si prenume)",
"user.profile.panel.label.language.bg": "Bulgara",
"user.profile.panel.label.language.cs": "Ceha",
"user.profile.panel.label.language.da": "Daneza",
"user.profile.panel.label.language.de": "Germana",
"user.profile.panel.label.language.el": "Greaca",
"user.profile.panel.label.language.en": "Engleza",
"user.profile.panel.label.language.es": "Spaniola",
"user.profile.panel.label.language.et": "Estoniana",
"user.profile.panel.label.language.fi": "Finlandeza",
"user.profile.panel.label.language.fr": "Franceza",
"user.profile.panel.label.language.hr": "Croata",
"user.profile.panel.label.language.hu": "Maghiara",
"user.profile.panel.label.language.it": "Italiana",
"user.profile.panel.label.language.lt": "Lituaniana",
"user.profile.panel.label.language.lv": "Letona",
"user.profile.panel.label.language.mt": "Malteza",
"user.profile.panel.label.language.nl": "Olandeza",
"user.profile.panel.label.language.pl": "Poloneza",
"user.profile.panel.label.language.pt": "Portugheza",
"user.profile.panel.label.language.ro": "Romana",
"user.profile.panel.label.language.sk": "Slovaca",
"user.profile.panel.label.language.sl": "Slovena",
"user.profile.panel.label.language.sv": "Suedeza",
"user.profile.panel.label.last.set": "Modificat ultima data la",
"user.profile.panel.label.locale": "Local (fomatare data/ora)",
"user.profile.panel.label.login.failed.attempts": "Incercari esuate",
"user.profile.panel.label.login.last.failed.attempt": "Ultima incercare esuata",
"user.profile.panel.label.new.user": "Va rugam sa completati detaliile utilizatorului si sa dati click pe \"Salveaza\" pentru a crea un nou utilizator",
"user.profile.panel.label.username": "Nume utilizator",
"user.profile.panel.label.password.expiration.date": "Parola expira la",
"user.profile.panel.label.suspended.until.date": "Dezactivat pana la",
"user.profile.panel.label.theme": "Tema",
"user.profile.panel.placeholder.choose.date": "Alegeti o data",
"user.profile.panel.placeholder.password.expiration.date": "Valid pana la",
"user.profile.panel.placeholder.login.failed.attempts": "Incercari esuate",
"user.profile.panel.text.account": "Date cont",
"user.profile.panel.text.credentials": "Resetati numele de utilizator si parola acestuia pentru autentificarea in aplicatie",
"user.profile.panel.text.user.profile": "Datele si setarile profilului utilizatorului",
"user.profile.panel.title.account": "Cont",
"user.profile.panel.title.credentials": "Nume de utilizator/parola",
"user.profile.panel.title.user.profile": "Profil utilizator",
"user.profile.panel.tooltip.application.role": "Rolul in aplicatie al utilizatorului",
"user.profile.panel.tooltip.password.expiration.date": "Parola implicita setata de Administratorul Sistemului! Utilizatorul trebuie sa isi schimbe parola imediat!",
"user.profile.panel.value.password.expiration.date": "Parola implicita sau nula",
"row.limiter.placeholder": "Randuri",
"search.table.button.cancel": "Anuleaza",
"search.table.button.delete": "Sterge",
"search.table.button.edit": "Modifica",
"search.table.button.new": "Nou rand",
"search.table.button.save": "Salveaza",
"search.table.button.search": "Cauta",
"search.table.dirty.confirmation.dialog.title": "Datele nu sunt inca salvate",
"search.table.dirty.confirmation.dialog.description": "Actiunea va reimprospata toate datele, iar datele care nu sunt salvate se vor pierde.<br/><br/>Doriti să continuati?",
"search.table.error.delete": "Eroare la stergere",
"search.table.error.update": "Operatia 'actualizare' nu a fost finalizata cu succes.",
"search.table.tooltip.edit": "Modifica",
"search.table.tooltip.delete": "Sterge",
"search.table.success.update": "Operatia 'actualizare' a fost finalizata cu succes",
"group.dialog.button.close": "Inchide",
"group.dialog.button.save": "Salveaza",
"group.dialog.description": "Pentru a crea un grup nou, introduceti un nume unic de grup corespunzator domeniului si dati clic pe Salvare.",
"group.dialog.hint.group.name": "Nume unic de grup corespunzator domeniului",
"group.dialog.hint.group.visibility": "Alegeti vizibilitatea grupului",
"group.dialog.label.group.name": "Numele grupului",
"group.dialog.label.group.description": "Descriere grupului",
"group.dialog.label.group.visibility": "Vizibilitatea grupului",
"group.dialog.placeholder.group.visibility": "Vizibilitatea grupului",
"group.dialog.tooltip.group.visibility": "Vizibilitatea grupului.",
"domain.group.button.create": "Creeaza",
"domain.group.button.delete": "Sterge",
"domain.group.button.edit": "Modifica datele",
"domain.group.button.group.members": "Membrii grupului",
"domain.group.delete.confirmation.dialog.title": "Sterge Grupul {{groupName}} din DomiSMP",
"domain.group.delete.confirmation.dialog.description": "Actiunea va sterge definitiv grupul!<br/><br/>Doriti sa continuati?",
"domain.group.error.delete": "Nu se poate sterge grupul din cauza datelor de domeniu nevalide. Este selectat grupul?",
"domain.group.group.details.dialog.title": "Detaliile Grupului",
"domain.group.label.filter": "Filtru membri",
"domain.group.label.group.name": "Numele grupului",
"domain.group.label.group.description": "Descriere",
"domain.group.label.group.visibility": "Vizibilitate",
"domain.group.label.no.filter.results": "Niciun grup care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"domain.group.label.no.data.found": "Domeniul nu are grupuri",
"domain.group.label.select.pages": "Selectati paginile",
"domain.group.manage.members.dialog.title": "Gestionarea Membrilor Resursei",
"domain.group.success.delete": "Grupul de domeniu [{{groupName}}] sters",
"domain.group.title.domains.groups": "Grupuri de domeniu",
"domain.group.title.domains.groups.for.domain.code": "Grupurile de domeniu pentru [{{domainCode}}]",
"domain.group.tooltip.create": "Creeaza un grup nou",
"domain.group.tooltip.delete": "Stergeti grupul selectat",
"domain.group.tooltip.edit": "Modificati grupul selectat",
"domain.group.tooltip.filter": "Filtru membri",
"domain.group.tooltip.group.members": "Membrii grup",
"edit.domain.label.configuration": "Configurare",
"edit.domain.label.domain.code": "Cod de domeniu",
"edit.domain.label.domain.members": "Membrii domeniu",
"edit.domain.label.filter": "Filtru coduri de domeniu",
"edit.domain.label.group": "Grup",
"edit.domain.label.no.filter.results": "Nu exista date care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"edit.domain.label.user.not.administrator": "Utilizatorul nu este Administrator al niciunui domeniu",
"edit.domain.placeholder.domain.code": "Cod de domeniu",
"edit.domain.text": "Panoul de administrare a domeniilor este un instrument pentru Administratorii de domenii cu care acestia pot gestiona membrii si grupurile acestor domenii",
"edit.domain.title": "Modifica Domenii",
"resource.dialog.button.close": "Inchide",
"resource.dialog.button.save": "Salveaza",
"resource.dialog.description": "Pentru a crea a noua resursa introduceti identificatorul unic si schema dupa care dati click pe Salveaza.",
"resource.dialog.label.resource.type": "Tipul de resursa selectat",
"resource.dialog.label.resource.id": "Identificatorul resursei",
"resource.dialog.label.resource.id.mandatory": "Identificator participantului nu trebuie sa fie gol si trebuie sa contina pana la 255 de caractere.",
"resource.dialog.label.resource.id.already.exists": "Identificator participantului pentru schema data este deja definit in baza de date!",
"resource.dialog.label.resource.scheme": "Schema resursei",
"resource.dialog.label.resource.scheme.mandatory": "Schema participantului nu poate fi goala.",
"resource.dialog.label.resource.visibility": "Vizibilitatea resursei",
"resource.dialog.placeholder.resource.type": "Selectati tipul resursei",
"resource.dialog.placeholder.resource.visibility": "Vizibilitatea resursei",
"resource.dialog.tooltip.resource.type": "Selectati tipul resursei.",
"resource.dialog.tooltip.resource.visibility": "Vizibilitatea resursei.",
"group.resource.panel.button.create": "Creeaza",
"group.resource.panel.button.delete": "Sterge",
"group.resource.panel.button.edit": "Modifica",
"group.resource.panel.button.members": "Membrii resursei",
"group.resource.panel.delete.confirmation.dialog.title": "Stergeti resursa cu schema din DomiSMP",
"group.resource.panel.delete.confirmation.dialog.description": "Actiunea va sterge definitiv resursa [{{identifierScheme}}] cu identificatorul: [{{identifierValue}}]!<br/><br/>Doriti sa continuati?",
"group.resource.panel.label.filter": "Filtru resurse",
"group.resource.panel.label.identifier.scheme": "Schema",
"group.resource.panel.label.identifier.value": "Identificator",
"group.resource.panel.label.no.filter.results": "Nicio resursa care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"group.resource.panel.label.no.data.found": "Grupul nu are resurse",
"group.resource.panel.label.select.pages": "Selectati pagina",
"group.resource.panel.manage.members.dialog.title": "Gestionarea Membrilor Resursei",
"group.resource.panel.placeholder.filter": "Filtru resurse",
"group.resource.panel.resource.details.dialog.title": "Detaliile Resursei",
"group.resource.panel.error.delete.group": "Nu se poate sterge grupul din cauza datelor de domeniu nevalide. Este selectat grupul?",
"group.resource.panel.error.delete.resource": "Nu se poate sterge resursa din cauza datelor nevalide despre resursa. Este resursa selectata?",
"group.resource.panel.success.delete": "Resursa [{{identifierScheme}}] cu identificatorul [{{identifierValue}}] a fost stearsa.",
"group.resource.panel.title": "Resursele grupului {{groupName}}",
"group.resource.panel.tooltip.create": "Creeaza",
"group.resource.panel.tooltip.delete": "Sterge resursa selectata",
"group.resource.panel.tooltip.edit": "Modifica datele",
"group.resource.panel.tooltip.members": "Membrii grupului",
"edit.group.label.resources": "Resurse",
"edit.group.label.members": "Membrii",
"edit.group.label.user.not.administrator": "Utilizatorul nu este Administrator al niciunui grup",
"edit.group.label.select.domain": "Grup selectat",
"edit.group.label.select.group": "Grupul selectat",
"edit.group.placeholder.select.domain": "Selecteaza domeniu",
"edit.group.placeholder.select.group": "Selecteaza grup",
"edit.group.text": "Panoul de administrare a grupurilor este un instrument pentru Administratorilor de grupuri cu care acestia pot gestiona membrii grupurilor si resursele",
"edit.group.title": "Modifica Grup",
"edit.group.tooltip.select.domain": "Domeniu selectat.",
"edit.group.tooltip.select.group": "Grup selectat.",
"document.wizard.dialog.button.cancel": "Anuleaza",
"document.wizard.dialog.button.ok": "OK",
"document.wizard.dialog.title": "Expert Extensie Resursa",
"resource.details.panel.label.resource.id": "Identificator resursa",
"resource.details.panel.label.resource.name": "Modifica documentul resursei",
"resource.details.panel.label.resource.scheme": "Schema resursa",
"resource.details.panel.label.resource.type": "Tip resursa",
"resource.details.panel.label.resource.visibility": "Vizibilitate resursa",
"resource.details.panel.label.resource.visibility.private": "Resursa privata este accesibila doar membrilor resursei!",
"resource.details.panel.label.resource.visibility.private.group": "Resursa apartine grupului privat. Doar membrii grupului si membrii grupului resursei o pot accesa!",
"resource.details.panel.label.resource.visibility.private.domain": "Resursa apartine domeniului privat. Doar membrii domeniului, membrii grupului domeniului si membrii grupului resursei o pot accesa!",
"resource.details.panel.label.resource.visibility.public": "Resursa este publica in grupul public si in domeniul public. Datele resursei sunt accesibile tuturor utilizatorilor.",
"resource.details.panel.button.edit": "Modifica documentul",
"resource.details.panel.placeholder.resource.type": "Tipul resursei pentru resursa",
"resource.details.panel.tooltip.resource.type": "Selectati tipul pentru resursa.",
"resource.details.panel.tooltip.resource.visibility": "Vizibilitatea resursei.",
"resource.details.panel.tooltip.show.resource": "Afisati resursa",
"resource.details.panel.title": "Resurse",
"resource.document.panel.button.back": "Inapoi",
"resource.document.panel.button.cancel": "Anuleaza",
"resource.document.panel.button.document.wizard": "Expert document",
"resource.document.panel.button.generate": "Genereaza",
"resource.document.panel.button.validate": "Valideaza",
"resource.document.panel.button.save": "Salveaza",
"resource.document.panel.cancel.confirmation.dialog.description": "Doriti sa anulati toate modificarile din document?",
"resource.document.panel.cancel.confirmation.dialog.title": "Anulati modificarile",
"resource.document.panel.document.wizard.dialog.title": "Expert resursa",
"resource.document.panel.label.created.on": "Creat la:",
"resource.document.panel.label.show.version": "Afisati versiunea:",
"resource.document.panel.placeholder.version": "Toate versiunile documentului",
"resource.document.panel.success.save": "Documentul este salvat cu versiunea curenta [{{currentResourceVersion}}].",
"resource.document.panel.success.generate": "Documentul este generat.",
"resource.document.panel.success.valid": "Documentul este valid.",
"resource.document.panel.title": "Resurse",
"resource.document.panel.tooltip.document.wizard": "Afiseaza dialogul expert document",
"resource.document.panel.tooltip.generate": "Genereaza resursa",
"resource.document.panel.tooltip.save": "Salveaza resursa",
"resource.document.panel.tooltip.validate": "Valideaza resursa",
"resource.document.panel.tooltip.version": "Selecteaza versiunea de afisat.",
"subresource.document.panel.button.back": "Inapoi",
"subresource.document.panel.button.cancel": "Anuleaza",
"subresource.document.panel.button.document.wizard": "Expert document",
"subresource.document.panel.button.generate": "Genereaza",
"subresource.document.panel.button.validate": "Valideaza",
"subresource.document.panel.button.save": "Salveaza",
"subresource.document.panel.cancel.confirmation.dialog.description": "Doriti sa anulati toate modificarile din document?",
"subresource.document.panel.cancel.confirmation.dialog.title": "Anulati modificarile",
"subresource.document.panel.label.created.on": "Creat la:",
"subresource.document.panel.label.show.version": "Afisati versiunea:",
"subresource.document.panel.placeholder.show.version": "Toate versiunile documentului",
"subresource.document.panel.success.generate": "Documentul este generat.",
"subresource.document.panel.success.save": "Documentul este salvat cu versiunea curenta [{{currentResourceVersion}}].",
"subresource.document.panel.success.valid": "Documentul este valid.",
"subresource.document.panel.tooltip.document.wizard": "Afiseaza dialogul expert document",
"subresource.document.panel.tooltip.generate": "Genereaza resursa",
"subresource.document.panel.tooltip.save": "Salveaza resursa",
"subresource.document.panel.tooltip.show.version": "Selecteaza versiunea de afisat.",
"subresource.document.panel.tooltip.validate": "Valideaza resursa",
"subresource.document.wizard.button.cancel": "Anuleaza",
"subresource.document.wizard.button.ok": "OK",
"subresource.document.wizard.error.read": "A aparut o eroare la citirea certificatului. Verificati daca fisierul incarcat are un tip de certificat valid",
"subresource.document.wizard.error.upload": "A aparut o eroare la incarcarea fisierului certificat [{{fileName}}] {{errorDescription}}",
"subresource.document.wizard.button.upload.certificate": "Incarca certificat",
"subresource.document.wizard.label.access.point": "Adresa URL a punctului de acces",
"subresource.document.wizard.label.access.point.mandatory": "Adresa URL a punctului de acces este obligatorie!",
"subresource.document.wizard.label.process.id": "Identificator de proces",
"subresource.document.wizard.label.process.id.mandatory": "Identificatorul de proces este obligatoriu!",
"subresource.document.wizard.label.process.scheme": "Schema proces",
"subresource.document.wizard.label.service.description": "Descriere serviciu",
"subresource.document.wizard.label.technical.contact.url": "Adresa URL de contact tehnic",
"subresource.document.wizard.label.transport.profile": "Profil transport",
"subresource.document.wizard.label.transport.profile.mandatory": "Profilul de transport (de ex: 'bdxr-transport-ebms3-as4-v1p0') este obligatoriu!",
"subresource.document.wizard.label.upload.certificate.mandatory": "Un certificatul x509 valid este obligatoriu!",
"subresource.document.wizard.legend.required.fields": "* campuri obligatorii",
"subresource.document.wizard.placeholder.upload.certificate": "Incarcati un certificat sau inserati valoarea in camp",
"subresource.document.wizard.title": "Expert subresursa",
"subresource.document.wizard.tooltip.access.point": "Adresa unui punct final, ca URL.",
"subresource.document.wizard.tooltip.process.id": "Partea de valoare a identificatorului procesului.",
"subresource.document.wizard.tooltip.process.scheme": "Partea schema a identificatorului procesului.",
"subresource.document.wizard.tooltip.service.description": "Descrierea serviciului",
"subresource.document.wizard.tooltip.technical.contact.url": "Contactul tehnic pentru serviciu",
"subresource.document.wizard.tooltip.transport.profile": "Indica tipul de metoda de transport utilizata intre punctele de acces pentru a schimba mesaje. Consulati specificatiile tehnice ale retelei de schimb de mesaje pentru valorile corecte.",
"subresource.dialog.button.close": "Inchide",
"subresource.dialog.button.create": "Creeaza",
"subresource.dialog.description": "Pentru a crea o subresursa noua introduceti identificatorul unic si schema dupa care dati click pe Salveaza.",
"subresource.dialog.label.resource.type": "Tip resursa selectata",
"subresource.dialog.label.subresource.id": "Identificator subresursa",
"subresource.dialog.label.subresource.scheme": "Schema subresursa",
"subresource.dialog.placeholder.resource.type": "Tipul selecta al subresursei",
"subresource.dialog.tooltip.resource.type": "Selectati tipul subresursei.",
"subresource.panel.button.create": "Creaza",
"subresource.panel.button.delete": "Sterge",
"subresource.panel.button.edit": "Modifica",
"subresource.panel.error.delete.resource.data": "Nu se poate sterge subresursa din cauza datelor nevalide despre resursa. Este resursa selectata?",
"subresource.panel.error.delete.subresource.data": "Nu se poate sterge subresursa din cauza datelor nevalide despre subresursa. Este subresursa selectata?",
"subresource.panel.delete.confirmation.dialog.description": "Actiunea va sterge definiti subresursa [{{identifierScheme}}] si identificatorul: [{{identifierValue}}]!<br/><br/>Doriti sa continuati?",
"subresource.panel.delete.confirmation.dialog.title": "Sterge resursa cu schema din DomiSMP",
"subresource.panel.label.filter": "Filtru resursa",
"subresource.panel.label.identifier.scheme": "Schema",
"subresource.panel.label.identifier.value": "Identificator",
"subresource.panel.label.no.filter.results": "Nicio resursa care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"subresource.panel.label.no.data.found": "Resursa nu are subresurse",
"subresource.panel.label.subresource.name": "Modifica documentul subresursei",
"subresource.panel.label.select.pages": "Selectati pagina",
"subresource.panel.subresource.dialog.title": "Creaza Subresursa",
"subresource.panel.placeholder.filter": "Filtru resurse",
"subresource.panel.success.delete": "Subresursa [{{identifierScheme}}] si identificatorul: [{{identifierValue}}] sters.",
"subresource.panel.title": "Subresurse",
"subresource.panel.tooltip.create": "Creaza",
"subresource.panel.tooltip.delete": "Sterge resursa selectata",
"subresource.panel.tooltip.edit": "Modifica",
"edit.resource.label.filter": "Filtru resurse",
"edit.resource.label.identifier.scheme": "Schema",
"edit.resource.label.identifier.value": "Identificator",
"edit.resource.label.members": "Membri",
"edit.resource.label.no.filter.results": "Nicio resursa care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"edit.resource.label.no.filter.results.admin": "Nicio resursa care sa se potriveasca cu filtrul",
"edit.resource.label.no.data.found": "Grupul nu are resurse",
"edit.resource.label.resource.details": "Detalii resursa",
"edit.resource.label.select.pages": "Selectati pagina",
"edit.resource.label.selected.domain": "Domeniul selectat",
"edit.resource.label.selected.group": "Grupul selectat",
"edit.resource.label.subresources": "Subresursa",
"edit.resource.label.user.not.administrator": "Utilizatorul nu este Administrator al niciunei resurse",
"edit.resource.placeholder.filter": "Filtru resurse",
"edit.resource.placeholder.selected.domain": "Domeniul selectat",
"edit.resource.placeholder.selected.group": "Grupul selectat",
"edit.resource.text": "Panoul de administrare a resurselor este un instrument pentru Administratorii de resurse cu care acestia pot gestiona resurse",
"edit.resource.title": "Modifica resursa",
"edit.resource.tooltip.selected.domain": "Domeniul selectat.",
"edit.resource.tooltip.selected.group": "Grupul selectat.",
"login.button.login": "Autentifica",
"login.button.password.reset": "Solicitati resetarea parolei",
"login.button.sso.login": "SSO Autentifica",
"login.dialog.password.expiration.dialog.description": "Parola dvs. este pe cale sa expire la {{expirationDate}}! Va rugam sa va schimbati parola inainte de data expirarii!",
"login.dialog.password.expiration.dialog.title": "Avertizare! Parola dvs. este pe cale sa expire",
"login.error.generic.error": "A aparut o eroare generica ({{errorStatus}}) in timpul conectarii.",
"login.error.inactive.user": "Utilizatorul este inactiv. Va rugam sa contactati Administratorul.",
"login.error.invalid.credentials": "{{errorStatus}} Combinatia nume de utilizator/parola pe care ati furnizat-o nu este valida. Incercati din nou sau contactati Administratorul.",
"login.error.invalid.username": "Va rugam sa introduceti un nume de utilizator valid.",
"login.error.invalid.username.or.password": "Va rugam sa introduceti un nume de utilizator si o parola valide.",
"login.error.smp.not.running": "Nu se poate autentifica. SMP nu ruleaza.",
"login.label.login": "Autentificare",
"login.label.logout": "Deconectare",
"login.label.password": "Parola",
"login.label.password.reset": "Solicitati resetarea parolei",
"login.label.sso.login": "Autentificare SSO",
"login.label.login.username": "Nume utilizator",
"login.label.password.reset.username": "Nume utilizator",
"login.title.smp.login": "Autentificare SMP",
"login.title.sso.login": "Autentificare SSO:",
"login.success.confirmation.email.sent": "A fost trimis un e-mail de confirmare la adresa dvs. de e-mail inregistrata pentru utilizatorul [{{userId}}]. Va rugam sa urmati instructiunel din e-mail pentru a finaliza procedul de resetare a contului. Daca nu ati primit acest e-mail, incercati mai tarziu sau contactati Administratorul",
"resource.search.button.clear.all": "Goleste tot",
"resource.search.error.fetch.resource.metadata": "A aparut o eroare la preluarea metadatelor resurselor",
"resource.search.label.document.type": "Tip document",
"resource.search.label.domain": "Domeniu",
"resource.search.label.no.subresources": "Nicio subresursa",
"resource.search.label.open.url": "Deschide adresa URL",
"resource.search.label.resource.id": "Identificator resursa",
"resource.search.label.resource.scheme": "Schema resursa",
"resource.search.label.column.document.type": "Tip document",
"resource.search.label.column.domain": "Domeniu",
"resource.search.label.column.resource.id": "Identificator resursa",
"resource.search.label.column.resource.scheme": "Schema resursa",
"resource.search.label.column.resource.url": "Adresa URL resursa",
"resource.search.label.column.subresource.count": "Numar Subr.",
"resource.search.label.subresource.id": "Identificator Subresursa",
"resource.search.label.subresource.id.scheme": "Schema identificatoro subresursa",
"resource.search.placeholder.document.type": "Tip document",
"resource.search.placeholder.domain": "Domeniu",
"resource.search.title": "Cautare",
"resource.search.tooltip.document.type": "Tip document",
"resource.search.tooltip.domain": "Domeniu",
"default.password.dialog.button.ok": "OK",
"default.password.dialog.title": "Folositi parola implicita pentru acest utilizator. Va recomandam sa o schimbati folosind consola utilizatorului.",
"reset.credentials.button.cancel": "Anuleaza",
"reset.credentials.button.update.password": "Seteaza/schimba parola",
"reset.credentials.error.passwords.mismatch": "Confirmare parolei noi nu se potriveste cu noua parola!",
"reset.credentials.error.old.password.reused": "Noua parola nu trebuie sa fie egala cu vechea parola actuala!",
"reset.credentials.label.username": "Introduceti Nume utilizator",
"reset.credentials.label.new.password": "Parola noua",
"reset.credentials.label.new.password.confirmation": "Confirmati Parola noua",
"reset.credentials.legend.required.fields": "* campuri obligatorii",
"reset.credentials.success.password.reset": "Parola a fost resetata cu succes. Conectati-va din nou la aplicatie folosind noua parola",
"domain.panel.button.reset": "Reseteaza",
"domain.panel.button.save": "Salveaza",
"domain.panel.label.domain": "Cod de Domeniu [{{value}}]",
"domain.panel.label.domain.already.exists": "Codul de Domeniu exista deja!",
"domain.panel.label.domain.default.resource.type": "Tipul de resursa implicit pentru domeniu",
"domain.panel.label.domain.mandatory": "Codul de domeniu trebuie sa fie constituit doar din caractere si din numere si trebuie sa contina pana la 63 de caractere.",
"domain.panel.label.domain.visibility": "Vizibilitatea domeniului",
"domain.panel.label.signature.cert.alias": "Certificatul semnaturii de raspuns (Semnatura CertAlias)",
"domain.panel.text": "Introduceti datele si dati click pe 'Salveaza' pentru a crea un domeniu nou",
"domain.panel.title": "Detalii Domeniu",
"domain.panel.hint.domain": "Pentru integrarea cu API-ul serviciu web: proprietatea de Domeniu",
"domain.panel.hint.domain.visibility": "Vizibilitatea domeniului. In cazul unui utilizator Intern, acesta trebuie sa fie autentificat pentru a putea citi resursele domeniului",
"domain.panel.hint.signature.cert.alias": "O valoare goala va face ca raspunsurile Resursa sa nu fie semnate de SMP!",
"domain.panel.tooltip.domain": "Codul de domeniu al SMP. Codul trebuie sa fie unic si este folosit in antetul HTTP 'Domain' sau in portiunea de URL atunci cand se preia/creeaza resursa folosind API-ul serviciu web",
"domain.panel.tooltip.domain.default.resource.type": "Tipul de resursa implicit pentru domeniu.",
"domain.panel.tooltip.domain.visibility": "Vizibilitatea domeniului.",
"domain.panel.tooltip.signature.cert.alias": "Certificatul este folosit la semnarea raspunsurilor REST pentru domeniu.",
"domain.panel.warning.domain.configuration.option.admin.member": "<li>adaugati un membru de domeniu cu rolul 'ADMIN' din fila Membri!</li>",
"domain.panel.warning.domain.configuration.option.resource.type": "<li>selectati cel putin un tip de resursa din fila Tipuri de Resursa</li>",
"domain.panel.warning.domain.configuration.option.signature.key": "<li>selectati cheia care va fi folosita pentru semnarea raspunsurilor domeniului!</li>",
"domain.panel.warning.domain.configuration.prefix": "Pentru a finaliza configurarea domeniului, va rugam: <ul>",
"domain.properties.button.reset": "Reseteaza",
"domain.properties.button.save": "Salveaza",
"domain.properties.label.domain.property": "Proprietatea Domeniului",
"domain.properties.label.domain.value": "Valoarea Domeniului",
"domain.properties.label.system.default": "Implicita Sistem",
"domain.properties.label.no.properties.found": "Nu s-au gasit proprietati ale Domeniului",
"domain.properties.panel.title": "Proprietati ale Domeniului",
"domain.resource.type.panel.button.reset": "Reseteaza",
"domain.resource.type.panel.button.save": "Salveaza",
"domain.resource.type.label.domain.resource.type.configuration": "Configurarea tipului resursei de domeniu",
"domain.sml.integration.panel.button.register": "Inregistreaza",
"domain.sml.integration.panel.button.reset": "Reseteaza",
"domain.sml.integration.panel.button.save": "Salveaza",
"domain.sml.integration.panel.button.unregister": "Anulati inregistrarea",
"domain.sml.integration.panel.hint.sml.domain": "Componenta specifica domeniului a zonei SML DNS (de ex. 'mydomain' in cazul 'mydomain.sml.dns.zone').",
"domain.sml.integration.panel.hint.smp.id": "Identificatorul SMP folosit pentru SML",
"domain.sml.integration.panel.label.smp.id": "Identificatorul SML SMP",
"domain.sml.integration.panel.label.smp.id.already.exists": "Identificatorul SML SMP exista deja!",
"domain.sml.integration.panel.label.smp.id.mandatory": "Identificatorul SML SMP trebuie sa contina pana la 63 de caractere, trebuie sa fie constituit doar din caractere alfanumerice si cratime, nu trebuie sa inceapa cu o cifra sau o cratima si nu trebuie sa se termine cu o cratima.",
"domain.sml.integration.panel.label.smp.client.certificate.alias": "Alias-ul Certificatului Client SML",
"domain.sml.integration.panel.label.sml.client.certificate.toggle": "Folositi antetul HTTP 'ClientCert' la autentificare.",
"domain.sml.integration.panel.label.sml.domain": "Domeniu SML",
"domain.sml.integration.panel.label.sml.domain.already.exists": "Domeniul cu subdomeniu gol SML exista deja!",
"domain.sml.integration.panel.label.sml.domain.mandatory": "Domeniul SML trebuie sa contina pana la 63 characters, trebuie sa contina doar caractere alfanumerice si cratime, nu trebuie sa inceapa cu o cifra sau cratima si nu trebuie sa se termine cu o cratima.",
"domain.sml.integration.panel.label.sml.subdomain.already.exists": "Subdomeniul SML este deja definit!",
"domain.sml.integration.panel.register.confirmation.dialog.description": "Actiunea va inregistra domeniul: [{{domainCode}}] si toate resursele acestuia in SML.<br/><br/>Doriti sa continuati?",
"domain.sml.integration.panel.register.confirmation.dialog.title": "Inregistrarea domeniului in SML",
"domain.sml.integration.panel.error.register": "A aparut o eroare la inregistrarea domeniului: {{domainCode}}",
"domain.sml.integration.panel.error.register.unknown.error": "Eroare necunoscuta. Verificati log-urile aplicatiei.",
"domain.sml.integration.panel.error.unregister": "A aparut o eroare la anularea inregistratii domeniului: {{domainCode}}",
"domain.sml.integration.panel.error.unregister.unknown.error": "Eroare necunoscuta. Verificati log-urile aplicatiei.",
"domain.sml.integration.panel.success.register": "Domeniul [{{domainCode}}] inregistrat in SML!",
"domain.sml.integration.panel.success.unregister": "Inregistrarea domeniul [{{domainCode}}] anulata din SML!",
"domain.sml.integration.panel.text": "Domeniul este inregistrat in SML!</p>Domeniul inregistrat nu poate fi sters si nici nu poate sa i se modifice identificatorul SMP SML",
"domain.sml.integration.panel.title": "Datele de integrare SML",
"domain.sml.integration.panel.tooltip.sml.domain": "Componenta specifica domeniului a zonei SML DNS (de ex. 'mydomain' in cazul 'mydomain.sml.dns.zone' sau lasati necompletat pentru valoare implicita a sml.dns.zone). Nota: are doar valoare informativa, zona SML DNS utilizata pentru publicare se bazeaza pe configuratia SML.",
"domain.sml.integration.panel.tooltip.smp.client.certificate.alias": "Certificatul Client folosit pentru autentificarea SML. Antetul HTTP 'Client-Cert' al SML este generat de asemenea din certificat",
"domain.sml.integration.panel.tooltip.smp.client.certificate.alias.default.option": "Alegeti certificatul pentru semnarea raspunsurilor SOAP",
"domain.sml.integration.panel.unregister.confirmation.dialog.description": "Actiunea va anula inregistrarea domeniului: [{{domainCode}}] si a tuturor resurselor acestuia din SML.<br/><br/>Doriti sa continuati?",
"domain.sml.integration.panel.unregister.confirmation.dialog.title": "Anulari Inregistrarea Domeniului din SML",
"admin.domain.button.create": "Creeaza Domeniu",
"admin.domain.button.delete": "Sterge Selectia",
"admin.domain.label.configuration": "Configurare",
"admin.domain.label.domain.data": "Date de domeniu",
"admin.domain.label.domain.code": "Codul de domeniu",
"admin.domain.label.filter": "Filtru coduri de domenii",
"admin.domain.label.no.filter.results": "Nu exista date care sa se potriveasca cu filtrul {{filterValue}}",
"admin.domain.label.no.data.found": "Nu exista date",
"admin.domain.label.members": "Membrii",
"admin.domain.label.select.page": "Selectati pagina",
"admin.domain.label.no.domains.selected": "Niciun domeniu selectat.",
"admin.domain.label.resource.type": "Tipul Resursei",
"admin.domain.label.sml.integration": "Integrare SML",
"admin.domain.error": "Eroare: {{actionMessage}}",
"admin.domain.success.create": "Domeniul: [{{domainCode}}] a fost creat!",
"admin.domain.success.remove": "Domeniul: [{{domainCode}}] este eliminat!",
"admin.domain.text": "Panoul de administrare a domeniilor este un instrument cu care se pot crea si sterge domenii in DomiSMP",
"admin.domain.title": "Administrarea Domeniilor",
"extension.panel.extension.description": "Descriere",
"extension.panel.label.description": "Descriere",
"extension.panel.label.extension.name": "Numele extensiei",
"extension.panel.label.extension.version": "Versiunea extensiei",
"extension.panel.label.resource.definitions": "Definitiile resursei",
"extension.panel.label.name": "Nume",
"extension.panel.label.id": "Identificator",
"extension.panel.label.url.segment": "Segment adresa URL",
"extension.panel.label.mime.type": "Tipul MIME",
"extension.panel.label.select.page": "Selectati pagina",
"extension.panel.label.show.selected.resources": "Afisati resursa selectata",
"extension.panel.placeholder.extension.name": "Numele extensiei",
"extension.panel.placeholder.extension.version": "Versiunea",
"extension.panel.title": "Datele Extensiei",
"resource.details.dialog.button.cancel": "Anuleaza",
"resource.details.dialog.resource.description": "Selectati datele de definire a resursei",
"resource.details.dialog.subresources.description": "Definitia Subresursei",
"resource.details.dialog.extension.description": "Descriere",
"resource.details.dialog.label.name": "Numele",
"resource.details.dialog.label.id": "Identificator",
"resource.details.dialog.label.url.segment": "Segment adresa URL",
"resource.details.dialog.label.mime.type": "Tipul MIME",
"resource.details.dialog.label.description": "Descriere",
"resource.details.dialog.label.resource.id": "Identificator resursa",
"resource.details.dialog.label.resource.name": "Numele resursei",
"resource.details.dialog.label.resource.mime.type": "Tipul MIME al resursei",
"resource.details.dialog.label.select.page": "Selectati pagina",
"resource.details.dialog.label.url": "Segment adreasa URL/antet HTTP",
"resource.details.dialog.placeholder.resource.id": "Identificator resursa",
"resource.details.dialog.placeholder.resource.name": "Nume resursa",
"resource.details.dialog.placeholder.resource.mime.type": "Tip MIME resursa",
"resource.details.dialog.placeholder.url": "Segment adreasa URL/antet HTTP",
"resource.details.dialog.title": "Detalii de Definire ale Resursei",
"extensions.label.filter": "Filtru nume extensii",
"extensions.label.no.filter.results": "Nu exista date care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"extensions.label.no.data.found": "Nu exista date",
"extensions.label.name": "Nume",
"extensions.label.version": "Versiune",
"extensions.label.select.page": "Selectati pagina",
"extensions.label.no.extension.selected": "Nicio extensie selectata.",
"extensions.text": "Extensii inregistrate in DomiSMP.<br />DomiSMP accepta tipuri de documente prin extensie personalizata. Extensiile implementeaza instrumente pentru validarea si generarea resurselor si subresurselor.<br /> Extensiile pot implementa, de asemenea, logica personalizata pentru scanarea atasamentelor (de ex. detectii de virusi).",
"extensions.title": "Extensii",
"keystore.import.dialog.button.import": "Importa",
"keystore.import.dialog.button.cancel": "Anuleaza",
"keystore.import.dialog.error.import": "A aparut o eroare la importul keystore: {{fileName}}",
"keystore.import.dialog.error.upload": "A aparut o eroare la incarcarea fisierului keystore {{fileName}}",
"keystore.import.dialog.error.generic": "A aparut o eroare la citirea keystore.",
"keystore.import.dialog.error.generic.message": "Verificati daca fisierul incarcat este un tip de keystore valid.",
"keystore.import.dialog.hint.password": "Cheile si keystore-ul trebuie sa utilizeze aceeasi parola!",
"keystore.import.dialog.label.choose": "Alegeti keystore-ul",
"keystore.import.dialog.label.keystore.file.name": "Alegeti un fisier - keystore!",
"keystore.import.dialog.label.keystore.type.mandatory": "Keystore type is required!",
"keystore.import.dialog.label.password.mandatory": "Parola este obligatorie! (Cheile si keystore-ul trebuie sa utilizeze aceeasi parola!)",
"keystore.import.dialog.legend.required.fields": "* campuri obligatorii",
"keystore.import.dialog.placeholder.keystore.file.name": "Numele fisierului keystore",
"keystore.import.dialog.placeholder.keystore.type": "Tipul keystore-ului",
"keystore.import.dialog.placeholder.keystore.type.jks": "Keystore Java (JKS)",
"keystore.import.dialog.placeholder.keystore.type.pkcs12": "PKCS #12 (PKCS12)",
"keystore.import.dialog.placeholder.password": "Parola",
"keystore.import.dialog.title": "Importare Keystore",
"keystore.import.dialog.warning.ignored.aliases": "Urmatoarele alias-uri au fost ignorate deoarece erau deja prezente in keystore-ul curent: {{ignoredAliases}}",
"admin.keystore.button.import.keystore": "Importa keystore",
"admin.keystore.button.delete.key": "Sterge cheia selectata",
"admin.keystore.label.alias": "Alias",
"admin.keystore.label.certificate": "Certificat",
"admin.keystore.label.key.pair": "Pereche de chei",
"admin.keystore.label.type": "Tip",
"admin.keystore.label.no.certificate.selected": "Niciun certificat selectat.",
"admin.keystore.label.invalid.certificate": "Certificat nevalid: {{reason}}",
"admin.keystore.label.filter": "Filtru alias-uri certificate/chei",
"admin.keystore.label.no.filter.results": "Nu exista date care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"admin.keystore.label.no.data.found": "Nu exista date",
"admin.keystore.label.select.page": "Selectati pagina",
"admin.keystore.delete.confirmation.dialog.description": "Actiunea va sterge definitiv cheia din keystore!<br/><br/>Doriti sa continuati?",
"admin.keystore.delete.confirmation.dialog.title": "Sterge cheia [{{alias}}] din keystore",
"admin.keystore.success.certificates.added": "Certificate adaugate [{{aliases}}]",
"admin.keystore.success.certificates.deleted": "Certificate sterse [{{aliases}}]",
"admin.keystore.success.errors.detected": "Erori detectate [{{errors}}]",
"admin.keystore.placeholder.filter": "alias",
"admin.keystore.text": "Keystore-ul contine chei pentru semnarea raspunsurilor si chei client pentru integrarea cu SML.",
"admin.keystore.title": "Administrare Keystore",
"property.label.column.property": "Proprietate",
"property.label.column.value": "Valoare",
"property.label.column.title.property": "Cheia de proprietate.",
"property.label.column.title.value": "Valoare proprietatii.",
"property.label.filter": "Filtru nume proprietati",
"property.label.new.value": "Noua valoare: '{{value}}'.",
"property.label.server.restart.needed": "Este necesara repornirea serverului!",
"property.label.server.restart.time": "Timp de actualizare programat la: {{date}}",
"property.title": "Proprietati",
"property.tooltip.filter": "Filtru dupa numele proprietatilor",
"admin.truststore.button.add.certificate": "Adauga certificat",
"admin.truststore.button.delete.certificate": "Sterge selectia",
"admin.truststore.error": "Eroare: {{actionMessage}}",
"admin.truststore.delete.confirmation.dialog.description": "Actiunea va sterge definitiv certificatul din truststore!<br/><br/>Doriti sa continuati?",
"admin.truststore.delete.confirmation.dialog.title": "Sterge certificatul {{alias}} din truststore",
"admin.truststore.label.alias": "Alias",
"admin.truststore.label.certificate.trustiness": "Cand truststore este gol, increderea in certificat nu este validata!",
"admin.truststore.label.filter": "Filtru alias-uri certificate",
"admin.truststore.label.invalid.certificate": "Certificat nevalid: {{reason}}",
"admin.truststore.label.no.filter.results": "Nu exista date care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"admin.truststore.label.no.data.found": "Nu exista date",
"admin.truststore.label.no.certificates.selected": "Niciun certificat selectat.",
"admin.truststore.label.select.page": "Selectati pagina",
"admin.truststore.placeholder.filter": "Alias",
"admin.truststore.success.import": "Certificatul: [{{certificateId}}] avand alias [{{alias}}] este importat!",
"admin.truststore.success.remove": "Certificatul: [{{certificateId}}] avand alias [{{alias}}] este sters!",
"admin.truststore.text": "Truststore contine certificatele in care exista incredere.<br />Certificatele folosite pentru autentificare trebuie sa fie continute in truststore.",
"admin.truststore.title": "Administrare Truststore",
"admin.user.button.create": "Creaza utilizator",
"admin.user.button.delete": "Sterge selectia",
"admin.user.delete.confirmation.dialog.description": "Actiunea va sterge definitiv utilizatorul!<br/><br/>Doriti sa continuati?",
"admin.user.delete.confirmation.dialog.title": "Sterge utilizatorul {{username}} din DomiSMP",
"admin.user.label.filter": "Filtru utilizatori",
"admin.user.label.full.name": "Nume complet",
"admin.user.label.username": "Nume utilizator",
"admin.user.label.no.filter.results": "Nu exista utilizatori care sa se potriveasca cu filtrul \"{{filterValue}}\"",
"admin.user.label.no.data.found": "Nu exista date",
"admin.user.label.select.page": "Selectati pagina",
"admin.user.label.no.user.selected": "Niciun utilizator selectat.",
"admin.user.placeholder.filter": "Nume utilizator sau nume complet",
"admin.user.success.create": "Utilizatorul [{{username}}] a fost creat!",
"admin.user.success.delete": "Utilizatorul [{{username}}] a fost sters!",
"admin.user.success.password.updated": "Parola utilizatorului actualizata!",
"admin.user.success.update": "Utilizatorul [{{username}}] actualizat!",
"admin.user.text": "Panoul de administrarea a utilizatorilor este un instrument cu care se pot crea si sterge utilizatori din DomiSMP",
"admin.user.title": "Administrarea Utilizatorilor",
"dns.query.panel.label.dns.query": "Interogarea DNS nu a functionat",
"dns.query.panel.label.resolved.dns.entries": "Intrari DNS rezolvate",
"dns.query.panel.title": "Domeniu DNS",
"dns.tools.button.generate.lookup.query": "Genereaza interogare",
"dns.tools.label.resource.id": "Identificator resursa",
"dns.tools.label.resource.scheme": "Schema resursa",
"dns.tools.label.resource.top.domain": "Domeniu de top",
"dns.tools.description": "Introduceti datele DNS-ului pentru a crea o interogare DNS",
"dns.tools.title": "Interogare DNS",
"access.token.panel.button.delete": "Sterge",
"access.token.panel.button.save": "Salveaza",
"access.token.panel.error.invalid.end.date": "Data expira la nevalida",
"access.token.panel.error.invalid.start.date": "Data activ de la nevalida",
"access.token.panel.label.active": "Activ",
"access.token.panel.label.description": "Descriere",
"access.token.panel.label.login.failed.attempts": "Incercari esuate",
"access.token.panel.label.login.last.failed.attempt": "Ultima incercare esuata",
"access.token.panel.label.token.expired": "Token-ul de acces a expirat",
"access.token.panel.label.suspended.until": "Dezactivat pana la",
"access.token.panel.label.validity.dates": "Introduceti un interval valid de date",
"access.token.panel.placeholder.end.date": "Data de incheiere",
"access.token.panel.placeholder.start.date": "Data de inceput",
"user.access.tokens.button.create": "Creaza Token de acces",
"user.access.tokens.label.access.tokens": "Token-uri de access",
"user.access.tokens.label.select.page": "Selectati pagina",
"user.access.tokens.text": "Puteti genera un Token de acces pentru fiecare aplicatie care are nevoie de acces la API-ul DomiSMP.",
"user.access.tokens.title": "Token de Access",
"user.access.tokens.credentials.dialog.title": "Nou Token de access creat",
"user.access.tokens.delete.confirmation.dialog.description": "Actiunea va sterge Token-ul de acces: \"{{credentialName}}\"!<br /><br />Doriti sa continuati?",
"user.access.tokens.delete.confirmation.dialog.title": "Sterge Token-ul de access",
"user.access.tokens.update.confirmation.dialog.description": "Actiunea va actualiza Token-ul de acces: \"{{credentialName}}\"!<br /><br />Doriti sa continuati?",
"user.access.tokens.update.confirmation.dialog.title": "Actualizeaza Token-ul de acces",
"user.access.tokens.tooltip.create": "Creaza Token de access nou",
"user.certificate.panel.button.delete": "Sterge",
"user.certificate.panel.button.show.details": "Arata detaliile",
"user.certificate.panel.button.save": "Salveaza",
"user.certificate.panel.label.active": "Activ",
"user.certificate.panel.label.certificate.id": "Identificator certificat",
"user.certificate.panel.label.description": "Descriere",
"user.certificate.panel.label.invalid.end.date": "Data expira la nevalida",
"user.certificate.panel.label.invalid.certificate": "Certificate nevalid: {{reason}}",
"user.certificate.panel.label.invalid.start.date": "Data activ de la nevalida",
"user.certificate.panel.label.validity.dates": "Perioada de valabilitate a certificatului",
"user.certificate.panel.placeholder.end.date": "Data de incheiere",
"user.certificate.panel.placeholder.start.date": "Data de inceput",
"user.certificates.button.import": "Importa certificat nou",
"user.certificates.label.user.certificate": "Certificate utilizatori",
"user.certificates.label.select.page": "Selectati pagina",
"user.certificates.credentials.dialog.title": "Importa Certificat",
"user.certificates.delete.confirmation.dialog.description": "Actiunea va sterge certificatul: \"{{credentialName}}\"!<br /><br />Doriti sa continuati?",
"user.certificates.delete.confirmation.dialog.title": "Sterge Certificat",
"user.certificates.update.confirmation.dialog.description": "Actiunea va actualiza datele certificatului:<br />{{credentialName}}!<br /><br />Doriti sa continuati?",
"user.certificates.update.confirmation.dialog.title": "Actualizeaza Certificat",
"user.certificates.text": "Inregistreaza un certificat de utilizator X509 pentru a avea acces la API-ul DomiSMP API utilizand autentificarea TLS reciproca.",
"user.certificates.title": "Certificate de utilizator X509",
"user.certificates.tooltip.import": "Importa certificat nou",
"toolbar.component.button.change.password": "Modifica parola",
"toolbar.component.button.logout": "Deconectare",
"toolbar.component.button.not.logged.in": "Neconectat",
"toolbar.component.button.open.cas.profile": "Deschideti datele CAS ale utilizatorului",
"toolbar.component.label.system.administrator.role": "Administrator de sistem",
"toolbar.component.label.user.role": "Utilizator SMP",
"app.component.button.collapse": "Restrangeti bara laterala",
"app.component.tooltip.collapse": "Retrangeti",
"app.component.tooltip.expand": "Extindeti",
"navigation.label.home": "Pagina de start",
"navigation.label.search": "Cautare",
"navigation.label.search.resources": "Resurse",
"navigation.label.search.dns.tools": "Instrumente DNS",
"navigation.label.login": "Authentificare",
"navigation.label.reset.token": "Resetare Token",
"navigation.label.edit": "Administrare",
"navigation.label.edit.domains": "Editare Domenii",
"navigation.label.edit.groups": "Editare Grupuri",
"navigation.label.edit.resources": "Editare Resurse",
"navigation.label.edit.resource.document": "Editare Documentul Resursei",
"navigation.label.edit.subresource.document": "Editare Documentul Subresursei",
"navigation.label.system.settings": "Setari de Sistem",
"navigation.label.system.settings.alerts": "Alerte",
"navigation.label.system.settings.domains": "Domenii",
"navigation.label.system.settings.extensions": "Extensii",
"navigation.label.system.settings.keystores": "Keystore",
"navigation.label.system.settings.properties": "Proprietati",
"navigation.label.system.settings.truststores": "Truststore",
"navigation.label.system.settings.users": "Utilizatori",
"navigation.label.user.settings": "Setari Utilizator",
"navigation.label.user.settings.profile": "Profil",
"navigation.label.user.settings.access.tokens": "Token-uri de Acces",
"navigation.label.user.settings.certificates": "Certificate",
"navigation.label.user.settings.alerts": "Alertele mele",
"navigation.label.user.settings.membership": "Calitate de Membru",
"navigation.tooltip.search.resources": "Cauta resurse inregistrate",
"navigation.tooltip.search.tools": "Cauta resurse inregistrate",
"navigation.tooltip.search.dns.tools": "Instrumente de cautare DNS"
}
......@@ -314,6 +314,31 @@ public enum SMPPropertyEnum {
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, STRING,
"^(.{0,255})$", "Subject must have less than 256 character"),
ALERT_USER_CREATED_ENABLED("smp.alert.user.created.enabled",
"true", "Enable/disable the user creation alert",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, BOOLEAN),
ALERT_USER_CREATED_LEVEL("smp.alert.user.created.level",
"HIGH", "User creation alert level. Values: {LOW, MEDIUM, HIGH}",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, STRING,
"^(LOW|MEDIUM|HIGH)$", "Allowed values are: LOW, MEDIUM, HIGH"),
ALERT_USER_CREATED_MAIL_SUBJECT("smp.alert.user.created.mail.subject",
"New DomiSMP User created", "User creation mail subject.",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, STRING,
"^(.{0,255})$", "Subject must have less than 256 character"),
ALERT_USER_UPDATED_ENABLED("smp.alert.user.updated.enabled",
"true", "Enable/disable the user creation alert",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, BOOLEAN),
ALERT_USER_UPDATED_LEVEL("smp.alert.user.updated.level",
"HIGH", "User creation alert level. Values: {LOW, MEDIUM, HIGH}",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, STRING,
"^(LOW|MEDIUM|HIGH)$", "Allowed values are: LOW, MEDIUM, HIGH"),
ALERT_USER_UPDATED_MAIL_SUBJECT("smp.alert.user.updated.mail.subject",
"DomiSMP User was updated by administrator", "User update mail subject.",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, STRING,
"^(.{0,255})$", "Subject must have less than 256 character"),
ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_ENABLED("smp.alert.accessToken.imminent_expiration.enabled",
"true", "Enable/disable the imminent accessToken expiration alert",
OPTIONAL, NOT_ENCRYPTED, NO_RESTART_NEEDED, BOOLEAN),
......
......@@ -2,8 +2,7 @@ package eu.europa.ec.edelivery.smp.config.init;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.services.ConfigurationService;
import eu.europa.ec.edelivery.smp.services.SMPLocaleService;
import eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
......@@ -14,16 +13,15 @@ import javax.annotation.PostConstruct;
*
* @since 5.1
* @author Sebastian-Ion TINCU
* @see eu.europa.ec.edelivery.smp.i18n.SMPLocale
*/
@Component
public class SMPLocaleFileSystemInitializer {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPLocaleFileSystemInitializer.class);
private final SMPLocaleService smpLocaleService;
private final SMPLanguageResourceService smpLocaleService;
public SMPLocaleFileSystemInitializer(SMPLocaleService smpLocaleService) {
public SMPLocaleFileSystemInitializer(SMPLanguageResourceService smpLocaleService) {
this.smpLocaleService = smpLocaleService;
}
......
package eu.europa.ec.edelivery.smp.i18n;
import org.apache.commons.lang3.StringUtils;
import java.util.EnumSet;
/**
* Locale enumeration for which DomiSMP is providing existing translations.
*
* @since 5.1
* @author Sebastian-Ion TINCU
*/
public enum SMPLocale {
/**
* The default English locale
*/
EN_US ("en", "English"),
/**
* The Romanian locale
*/
RO_RO ("ro", "Romanian");
private final String code;
private final String language;
SMPLocale(String code, String language) {
this.code = code;
this.language = language;
}
public String getCode() {
return code;
}
public String getLanguage() {
return language;
}
public static SMPLocale fromCodeDefaultingToEnglish(String code) {
return EnumSet.allOf(SMPLocale.class).stream()
.filter(locale -> StringUtils.equalsIgnoreCase(locale.getCode(), code))
.findAny()
.orElse(EN_US);
}
}
......@@ -447,6 +447,36 @@ public class ConfigurationService {
return configurationDAO.getCachedPropertyValue(ALERT_USER_LOGIN_FAILURE_MAIL_SUBJECT);
}
//-----------------------
// user Created
public Boolean getAlertUserCreatedEnabled() {
return configurationDAO.getCachedPropertyValue(ALERT_USER_CREATED_ENABLED);
}
public AlertLevelEnum getAlertUserCreatedLevel() {
String level = configurationDAO.getCachedPropertyValue(ALERT_USER_CREATED_LEVEL);
return AlertLevelEnum.valueOf(level);
}
public String getAlertUserCreatedSubject() {
return configurationDAO.getCachedPropertyValue(ALERT_USER_CREATED_MAIL_SUBJECT);
}
//-----------------------
// user updated
public Boolean getAlertUserUpdatedEnabled() {
return configurationDAO.getCachedPropertyValue(ALERT_USER_UPDATED_ENABLED);
}
public AlertLevelEnum getAlertUserUpdatedLevel() {
String level = configurationDAO.getCachedPropertyValue(ALERT_USER_UPDATED_LEVEL);
return AlertLevelEnum.valueOf(level);
}
public String getAlertUserUpdatedSubject() {
return configurationDAO.getCachedPropertyValue(ALERT_USER_UPDATED_MAIL_SUBJECT);
}
//-----------------------
// user suspended
public Boolean getAlertUserSuspendedEnabled() {
......
......@@ -311,9 +311,14 @@ public class CredentialsAlertService {
*/
public void alertUserCreated(DBUser user) {
boolean userCreatedAlertEnabled = configurationService.getAlertUserCreatedEnabled();
if (!userCreatedAlertEnabled) {
LOG.debug("Suppress alert: Alert user created is disabled!");
return;
}
String mailTo = user.getEmailAddress();
String mailSubject = "New user created";
AlertLevelEnum alertLevel = AlertLevelEnum.HIGH;
String mailSubject = configurationService.getAlertUserCreatedSubject();
AlertLevelEnum alertLevel = configurationService.getAlertUserCreatedLevel();
AlertTypeEnum alertType = AlertTypeEnum.USER_CREATED;
DBAlert alert = createAlert(user.getUsername(), mailSubject, mailTo, alertLevel, alertType);
......@@ -335,9 +340,14 @@ public class CredentialsAlertService {
*/
public void alertUserUpdated(DBUser user) {
boolean userCreatedAlertEnabled = configurationService.getAlertUserUpdatedEnabled();
if (!userCreatedAlertEnabled) {
LOG.debug("Suppress alert: Alert user updated is disabled!");
return;
}
String mailTo = user.getEmailAddress();
String mailSubject = "User data updated";
AlertLevelEnum alertLevel = AlertLevelEnum.HIGH;
String mailSubject = configurationService.getAlertUserUpdatedSubject();
AlertLevelEnum alertLevel = configurationService.getAlertUserUpdatedLevel();
AlertTypeEnum alertType = AlertTypeEnum.USER_UPDATED;
DBAlert alert = createAlert(user.getUsername(), mailSubject, mailTo, alertLevel, alertType);
......
package eu.europa.ec.edelivery.smp.services;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import eu.europa.ec.edelivery.smp.config.enums.SMPEnvPropertyEnum;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.commons.lang3.StringUtils.lowerCase;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;
/**
* Service providing operations for managing language resources (e.g. updating language files on the disk).
*
* @author Sebastian-Ion TINCU
* @since 5.1
*/
@Service
public class SMPLanguageResourceService {
public static final String LANGUAGE_FILENAME_UI_PREFIX = "ui_";
public static final String LANGUAGE_RESOURCE_UI_FOLDER = "/META-INF/resources/ui/assets/i18n/";
public static final String LANGUAGE_RESOURCE_UI_DEFAULT = LANGUAGE_RESOURCE_UI_FOLDER + "en.json";
public static final String LANGUAGE_FILENAME_MAIL_PREFIX = "mail-messages_";
public static final String LANGUAGE_RESOURCE_MAIL_FOLDER = "/mail-messages/";
public static final String LANGUAGE_RESOURCE_MAIL_DEFAULT = LANGUAGE_RESOURCE_MAIL_FOLDER + "en.json";
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPLanguageResourceService.class);
private final ConfigurationService configurationService;
private final ResourcePatternResolver resourceResolver;
public SMPLanguageResourceService(ConfigurationService configurationService,
ResourcePatternResolver resourceResolver) {
this.configurationService = configurationService;
this.resourceResolver = resourceResolver;
}
/**
* Method for getting the language file for a specific ISO 639 language code.
*
* @param langCode the ISO 639 language code (e.g. "en" for English, "fr" for French,
* "de" for German, etc.) or null for the default language
* @param filenamePrefix the prefix of the language file (e.g. "ui_" for "ui_en.json")
* @return the path to the language file
*/
public Path getLanguageFile(String filenamePrefix, String langCode) {
File localeFolder = configurationService.getLocaleFolder();
String languageFileName = getLanguageFilename(filenamePrefix, langCode);
if (localeFolder != null && !localeFolder.exists() && !localeFolder.mkdirs()) {
LOG.error("Failed to create locale folder [{}]", localeFolder);
return null;
}
return new File(localeFolder, languageFileName).toPath().toAbsolutePath();
}
@Cacheable("mail-templates-translations")
public Properties getMailProperties(String langCode) {
Resource langRes = getTranslationResourceFile(LANGUAGE_FILENAME_MAIL_PREFIX, langCode, LANGUAGE_RESOURCE_MAIL_DEFAULT);
ObjectMapper mapper = jsonObjectMapper();
try (InputStream target = langRes.getInputStream()) {
// Read JSON nodes from input streams
JsonNode jsonTranslation = mapper.readTree(target);
Properties properties = new Properties();
jsonTranslation.fieldNames().forEachRemaining(fieldName ->
properties.setProperty(fieldName, jsonTranslation.get(fieldName).asText());
);
return properties;
} catch (IOException e) {
LOG.error("Error occurred while merging the translation files", e);
return new Properties();
}
}
public Resource getTranslationResourceFile(String prefix, String code, String defaultResourceFile) {
Path langResourcePath = getLanguageFile(prefix, code);
if (langResourcePath != null && langResourcePath.toFile().exists()) {
LOG.debug("Returning local mail translation file [{}]", langResourcePath.toAbsolutePath());
return new FileSystemResource(langResourcePath);
} else {
LOG.warn("Local translation file [{}] does not exist. Return default translation [{}]!", code, defaultResourceFile);
ClassPathResource defResource = new ClassPathResource(defaultResourceFile);
if (defResource.exists()) {
return defResource;
} else {
LOG.error("Default locale file [{}] does not exist in classpath!", defaultResourceFile);
return null;
}
}
}
/**
* Method for updating the language files on the disk. The method will copy the language files from the classpath
* to the locale folder. If the locale folder does not exist, the method will try to create it.
* The method will not overwrite existing properties in the translation files. If a property is missing in the
* existing translation file, the method will add it from the classpath translation file.
*/
public void updateLocalesOnDisk() {
updateLocalesOnDisk(LANGUAGE_FILENAME_UI_PREFIX, LANGUAGE_RESOURCE_UI_FOLDER + "*.json");
updateLocalesOnDisk(LANGUAGE_FILENAME_MAIL_PREFIX, LANGUAGE_RESOURCE_MAIL_FOLDER + "*.json");
}
public void updateLocalesOnDisk(String filenamePrefix, String resourcePathPattern) {
// Get all the language files from the classpath
Resource[] resources;
try {
resources = resourceResolver.getResources("classpath:" + resourcePathPattern);
} catch (IOException e) {
LOG.error("An error occurred while reading the language files from the classpath", e);
return;
}
// Copy the language files to the locale folder
for (Resource resource : resources) {
String filename = resource.getFilename();
if (filename == null) {
LOG.warn("Resource [{}] does not have a filename!", resource);
continue;
}
String langCode = filename.substring(0, filename.indexOf('.'));
Path localeFile = getLanguageFile(filenamePrefix, langCode);
if (localeFile == null) {
LOG.warn("Can not generate 'locale/language' file [{}]! Check if local folder defined in property [{}] " +
"has writing permissions and the folder exists", localeFile, SMPEnvPropertyEnum.LOCALE_FOLDER.getProperty());
continue;
}
copyOrUpdateTranslation(localeFile, resource);
}
}
/**
* Method for copying a resource to a locale folder. If the IOException occurs, the method will silently log an error.
* The error can be caused by the lack of writing permissions or the absence of the locale folder or if the file already exists.
*
* @param resource the resource to copy
* @param localeFile the path to the locale file
*/
protected static void copyResourceToLocaleFolder(Resource resource, Path localeFile) {
try (InputStream inputStream = resource.getInputStream()) {
Files.copy(inputStream, localeFile);
} catch (IOException e) {
LOG.error("An error occurred while updating locale file [{}]", localeFile, e);
}
}
/**
* Method creates the language filename for a specific ISO 639 language code
* and a prefix. If the prefix is null, it will be ignored. The prefix and the language code
* will be normalized (lower case and trimmed).
*
* @param langCode the ISO 639 language code
* @return the filename for the language file
*/
private String getLanguageFilename(String prefix, String langCode) {
return normalize(prefix) + normalize(langCode) + ".json";
}
/**
* Method returns normalized token (lower case and trimmed).
*
* @param token token to normalize
* @return normalized token
*/
private String normalize(String token) {
return trimToEmpty(lowerCase(token));
}
/**
* The method will merge the existing translation file with the classpath translation file. The merge will add
* missing properties from the classpath translation file into the existing translation file, but it will not
* overwrite existing properties.
*
* @param localFilePath the path to the local translation file
* @param resourceTranslation
*/
public static void copyOrUpdateTranslation(Path localFilePath, Resource resourceTranslation) {
File localFile = localFilePath.toFile();
LOG.info("Updating translation file [{}]", localFile);
if (!localFile.exists()) {
LOG.debug("The local translation file [{}] does not exist!", localFile);
copyResourceToLocaleFolder(resourceTranslation, localFilePath);
return;
}
// update file
ObjectMapper mapper = jsonObjectMapper();
JsonNode mergedJson = null;
boolean changed = false;
try (InputStream target = new FileInputStream(localFilePath.toFile());
InputStream classpathTranslation = resourceTranslation.getInputStream()) {
// Read JSON nodes from input streams
JsonNode jsonReference = mapper.readTree(classpathTranslation);
mergedJson = mapper.readTree(target);
// Merge the JSON nodes
changed = mergeTranslationJson(mergedJson, jsonReference);
} catch (IOException e) {
LOG.error("Error occurred while merging the translation files", e);
return;
}
if (!changed) {
LOG.info("No changes were made to the translation file [{}]", localFile);
return;
}
// Write the merged JSON to the output file
try (OutputStream os = new FileOutputStream(localFilePath.toFile())) {
// Write the merged JSON to the output file
mapper.writerWithDefaultPrettyPrinter().writeValue(os, mergedJson);
} catch (IOException e) {
LOG.error("Error occurred while writing the merged translation file", e);
}
}
/**
* Merge two JSON nodes recursively. Method will add missing properties from
* the reference node into the target node, but it will not overwrite existing
* properties. If any changes were made to the target node, the method returns
* true else false.
* <p>
* The merge is used to add new translations to the existing language
* files.
*
* @param targetNode the main node to be updates
* @param referenceNode the reference node
* @return true if any changes were made to the target node else false.
*/
protected static boolean mergeTranslationJson(JsonNode targetNode, JsonNode referenceNode) {
AtomicBoolean changed = new AtomicBoolean(false);
referenceNode.fieldNames().forEachRemaining(fieldName -> {
JsonNode jsonNode = targetNode.get(fieldName);
// If the node is an object, recursively merge
boolean mergeChanged = changed.get();
if (jsonNode != null && jsonNode.isObject()) {
mergeChanged |= mergeTranslationJson(jsonNode, referenceNode.get(fieldName));
} else if (jsonNode == null && targetNode instanceof ObjectNode) {
// add new field
((ObjectNode) targetNode).set(fieldName, referenceNode.get(fieldName));
mergeChanged = true;
}
changed.set(mergeChanged);
});
return changed.get();
}
/**
* Method for creating a new instance of the {@link ObjectMapper} with the default configuration.
*
* @return the new instance of the {@link ObjectMapper}
*/
public static ObjectMapper jsonObjectMapper() {
ObjectMapper objectMapper = JsonMapper.builder()
.findAndAddModules()
.build();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
dateFormat.setTimeZone(TimeZone.getDefault());
objectMapper.setDateFormat(dateFormat);
return objectMapper;
}
}
package eu.europa.ec.edelivery.smp.services;
import eu.europa.ec.edelivery.smp.config.enums.SMPEnvPropertyEnum;
import eu.europa.ec.edelivery.smp.i18n.SMPLocale;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.EnumSet;
/**
* Service providing operations for managing locales (e.g. updating locales on the disk).
*
* @since 5.1
* @author Sebastian-Ion TINCU
*/
@Service
public class SMPLocaleService {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPLocaleService.class);
private final ConfigurationService configurationService;
public SMPLocaleService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
public Path getLocaleFile(SMPLocale locale) {
File localeFolder = configurationService.getLocaleFolder();
if (!localeFolder.exists() && !localeFolder.mkdirs()) {
LOG.error("Failed to create locale folder [{}]", localeFolder);
return null;
}
return new File(localeFolder, locale.getCode() + ".json").toPath().toAbsolutePath();
}
public Resource getLocaleResource(SMPLocale locale) {
return new ClassPathResource("META-INF/resources/ui/assets/i18n/" + locale.getCode() + ".json");
}
public void updateLocalesOnDisk() {
EnumSet.allOf(SMPLocale.class).forEach(this::updateLocaleOnDisk);
}
private void updateLocaleOnDisk(SMPLocale locale) {
Resource resource = getLocaleResource(locale);
if (resource.exists()) {
Path localeFile = getLocaleFile(locale);
if (localeFile == null) {
LOG.warn("Can not generate 'locale/language' file [{}]! Check if local folder defined in property [{}] " +
"has writing permissions and the folder exists", localeFile, SMPEnvPropertyEnum.LOCALE_FOLDER.getProperty());
return;
}
if (Files.exists(localeFile)) {
LOG.warn("Language file [{}] already exists, and it will be replaced with up-to-date translations", localeFile);
}
try(InputStream inputStream = resource.getInputStream()) {
Files.copy(inputStream, localeFile, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
LOG.error("An error occurred while updating locale file [{}]", localeFile, e);
}
}
}
}
......@@ -20,11 +20,11 @@ package eu.europa.ec.edelivery.smp.services.mail;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService;
import eu.europa.ec.edelivery.smp.utils.StringNamedSubstitutor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
......@@ -39,16 +39,21 @@ import java.util.Properties;
* @author Joze Rihtarsic
* @since 5.1
*/
@Component
@Service
public class MailTemplateService {
private static final String DEFAULT_LANGUAGE = "en";
private static final String MAIL_TEMPLATE = "/mail-messages/mail-template.htm";
private static final String MAIL_TEMPLATE_CHARSET= "UTF-8";
private static final String MAIL_TEMPLATE_CHARSET = "UTF-8";
private static final String MAIL_HEADER = "MAIL_HEADER";
private static final String MAIL_FOOTER = "MAIL_FOOTER";
private static final String MAIL_TITLE = "MAIL_TITLE";
private static final String MAIL_CONTENT = "MAIL_CONTENT";
SMPLanguageResourceService smpLanguageResourceService;
public MailTemplateService(SMPLanguageResourceService smpLanguageResourceService) {
this.smpLanguageResourceService = smpLanguageResourceService;
}
public String getMailHtmlContent(MailDataModel model) {
InputStream templateIS = MailTemplateService.class.getResourceAsStream(MAIL_TEMPLATE);
......@@ -82,34 +87,8 @@ public class MailTemplateService {
public String getMailData(MailDataModel model, String key) {
Properties translations = getMessageTranslations(model.getLanguage());
Properties translations = smpLanguageResourceService.getMailProperties(model.getLanguage());
String dataTemplate = translations.getProperty(key);
return StringUtils.isBlank(dataTemplate) ? dataTemplate : StringNamedSubstitutor.resolve(dataTemplate, model.getModel());
}
@Cacheable("mail-templates-translations")
public Properties getMessageTranslations(String language) {
Properties translations = loadTranslations(language);
if (translations != null) {
return translations;
}
return loadTranslations(DEFAULT_LANGUAGE);
}
protected Properties loadTranslations(String language) {
String langResource = "/mail-messages/mail-messages_" + language + ".properties";
InputStream isLanguage = MailTemplateService.class.getResourceAsStream(langResource);
if (isLanguage != null) {
try {
Properties translations = new Properties();
translations.load(isLanguage);
return translations;
} catch (IOException e) {
throw new SMPRuntimeException(ErrorCode.INTERNAL_ERROR, "Error reading mail template", ExceptionUtils.getRootCauseMessage(e));
}
}
return new Properties();
}
}
{
"mail.credential_changed.content" : "You're receiving this e-mail because your credential type: ${CREDENTIAL_TYPE} changed on DomiSMP ${SMP_INSTANCE_NAME}! <p>If you did not update your credential, please inform DomiSMP administrator immediately.</p><br>If you are having trouble accessing your account, reset your password. ",
"mail.credential_changed.title" : "Credential type: ${CREDENTIAL_TYPE} on DomiSMP ${SMP_INSTANCE_NAME} changed!",
"mail.credential_expired.content" : "<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p> <p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p> <p><strong>Expiration date-time: </strong> ${EXPIRATION_DATETIME}</p> <p><strong>Reporting date-time:</strong> ${REPORTING_DATETIME}</p> <p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> <p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>.",
"mail.credential_expired.title" : "Credential type: ${CREDENTIAL_TYPE} is expired",
"mail.credential_imminent_expiration.content" : "<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p><p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p><p><strong>Expiration date-time: </strong> ${EXPIRATION_DATETIME}</p><p><strong>Reporting date-time:</strong> ${REPORTING_DATETIME}</p><p><strong>Alert level:</strong> ${ALERT_LEVEL}</p><p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>",
"mail.credential_imminent_expiration.title" : "Credential type: ${CREDENTIAL_TYPE} imminent expiration",
"mail.credential_request_reset.content" : "You're receiving this e-mail because you requested a credential type: ${CREDENTIAL_TYPE} reset on DomiSMP ${SMP_INSTANCE_NAME} for your user account. <br/> Please go to the following page and choose a new password: <br/> <br/> <a href=\"${RESET_URL}\">${RESET_URL}</a> <br/> <br/> The link is valid for a short period of time. If the link has expired, please request a new one.",
"mail.credential_request_reset.title" : "Request for reset of the Credential type: ${CREDENTIAL_TYPE} on DomiSMP ${SMP_INSTANCE_NAME}",
"mail.credential_suspended.content" : "<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p> <p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p> <p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p> <p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p> <p><strong>Suspended util</strong> ${SUSPENDED_UNTIL_DATETIME}</p> <p><strong>Reporting time:</strong> ${REPORTING_DATETIME}</p> <p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> <p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>",
"mail.credential_suspended.title" : "Credential type: ${CREDENTIAL_TYPE} is temporarily suspended",
"mail.credential_verification_failed.content" : "<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p> <p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p> <p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p> <p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p> <p><strong>Reporting time:</strong> ${REPORTING_DATETIME}</p> <p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> <p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>",
"mail.credential_verification_failed.title" : "Credential type: ${CREDENTIAL_TYPE} verification failed!",
"mail.footer" : "DomiSMP instance: ${SMP_INSTANCE_NAME} (${SERVER_NAME}), ${CURRENT_DATETIME}",
"mail.header" : "eDelivery DomiSMP sample: ${SMP_INSTANCE_NAME}",
"mail.test_mail.content" : "This is a test mail from DomiSMP instance: ${SMP_INSTANCE_NAME} for your user account.",
"mail.test_mail.title" : "Test mail: ${CREDENTIAL_TYPE} on DomiSMP ${SMP_INSTANCE_NAME}",
"mail.user_created.content" : "You're receiving this e-mail because new user was created with :<br/><b>Username:</b>${USERNAME}<br /> <b>Name:</b>${FULL_NAME}<br /> <b>Email Address:</b>${EMAIL}<br /><b>Activated:</b>${ACTIVATED}<br /> Note: If user account is not yet activated please wait for activation mail, before first login. <br/>If you did not request this account, please inform DomiSMP administrator immediately.",
"mail.user_created.title" : "New user created on DomiSMP ${SMP_INSTANCE_NAME}",
"mail.user_updated.content" : "You're receiving this e-mail because user was updated with :<br/><b>Username:</b>${USERNAME}<br /> <b>Name:</b>${FULL_NAME}<br /> <b>Email Address:</b>${EMAIL}<br /><b>Activated:</b>${ACTIVATED}<br /><br/>If you did not request update account, please inform DomiSMP administrator immediately.",
"mail.user_updated.title" : "User update on DomiSMP ${SMP_INSTANCE_NAME}"
}
\ No newline at end of file
###
# #START_LICENSE#
# smp-server-library
# %%
# Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
# %%
# Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the Licence.
# You may obtain a copy of the Licence at:
#
# [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
#
# Unless required by applicable law or agreed to in writing, software distributed under the Licence is
# distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the Licence for the specific language governing permissions and limitations under the Licence.
# #END_LICENSE#
###
# Email translations. Each email has a header, title, content and footer. The texts are can be HTML formatted.
# The header and footer are common for all emails and should describe instance and purpose of the application.
# The title and content are specific for each email type.
mail.header=eDelivery DomiSMP sample: ${SMP_INSTANCE_NAME}
mail.footer=DomiSMP instance: ${SMP_INSTANCE_NAME} (${SERVER_NAME}), ${CURRENT_DATETIME}
# Email texts for password reset
mail.test_mail.title=Test mail: ${CREDENTIAL_TYPE} on DomiSMP ${SMP_INSTANCE_NAME}
mail.test_mail.content=This is a test mail from DomiSMP instance: ${SMP_INSTANCE_NAME} for your user account.
mail.user_created.title=New user created on DomiSMP ${SMP_INSTANCE_NAME}
mail.user_created.content=You're receiving this e-mail because new user was created with :<br/>\
<b>Username:</b>${USERNAME}<br /> \
<b>Name:</b>${FULL_NAME}<br /> \
<b>Email Address:</b>${EMAIL}<br />\
<b>Activated:</b>${ACTIVATED}<br /> \
Note: If user account is not yet activated please wait for activation mail, before first login. \
<br/>If you did not request this account, please inform DomiSMP administrator immediately.
mail.user_updated.title=User update on DomiSMP ${SMP_INSTANCE_NAME}
mail.user_updated.content=You're receiving this e-mail because user was updated with :<br/>\
<b>Username:</b>${USERNAME}<br /> \
<b>Name:</b>${FULL_NAME}<br /> \
<b>Email Address:</b>${EMAIL}<br />\
<b>Activated:</b>${ACTIVATED}<br />\
<br/>If you did not request update account, please inform DomiSMP administrator immediately.
# Email texts for password reset
mail.credential_request_reset.title=Request for reset of the Credential type: ${CREDENTIAL_TYPE} on DomiSMP ${SMP_INSTANCE_NAME}
mail.credential_request_reset.content=You're receiving this e-mail because you requested a credential type: ${CREDENTIAL_TYPE} \
reset on DomiSMP ${SMP_INSTANCE_NAME} for your user account. <br/> Please go to the following page and choose a new password: \
<br/> <br/> <a href="${RESET_URL}">${RESET_URL}</a> <br/> <br/> The link is valid for a short period of time. If the \
link has expired, please request a new one.
mail.credential_changed.title=Credential type: ${CREDENTIAL_TYPE} on DomiSMP ${SMP_INSTANCE_NAME} changed!
mail.credential_changed.content=You're receiving this e-mail because your credential type: ${CREDENTIAL_TYPE} changed \
on DomiSMP ${SMP_INSTANCE_NAME}! <p>If you did not update your credential, please inform DomiSMP administrator \
immediately.</p><br>If you are having trouble accessing your account, reset your password.
# Email texts for credential expired
mail.credential_expired.title=Credential type: ${CREDENTIAL_TYPE} is expired
mail.credential_expired.content=<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p> \
<p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p> \
<p><strong>Expiration date-time: </strong> ${EXPIRATION_DATETIME}</p> \
<p><strong>Reporting date-time:</strong> ${REPORTING_DATETIME}</p> \
<p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> \
<p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>.
# Email texts for credential imminent expiration}
mail.credential_imminent_expiration.title=Credential type: ${CREDENTIAL_TYPE} imminent expiration
mail.credential_imminent_expiration.content=<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p>\
<p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p>\
<p><strong>Expiration date-time: </strong> ${EXPIRATION_DATETIME}</p>\
<p><strong>Reporting date-time:</strong> ${REPORTING_DATETIME}</p>\
<p><strong>Alert level:</strong> ${ALERT_LEVEL}</p>\
<p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>
# Email texts for credential suspended
mail.credential_suspended.title=Credential type: ${CREDENTIAL_TYPE} is temporarily suspended
mail.credential_suspended.content=<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p> \
<p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p> \
<p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p> \
<p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p> \
<p><strong>Suspended util</strong> ${SUSPENDED_UNTIL_DATETIME}</p> \
<p><strong>Reporting time:</strong> ${REPORTING_DATETIME}</p> \
<p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> \
<p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>
# Email texts for credential verification failed
mail.credential_verification_failed.title=Credential type: ${CREDENTIAL_TYPE} verification failed!
mail.credential_verification_failed.content=<p><strong>Credential type:</strong> ${CREDENTIAL_TYPE}</p> \
<p><strong>Credential identifier:</strong> ${CREDENTIAL_ID}</p> \
<p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p> \
<p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p> \
<p><strong>Reporting time:</strong> ${REPORTING_DATETIME}</p> \
<p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> \
<p><strong>SMP instance name:</strong> ${SMP_INSTANCE_NAME}</p>
package eu.europa.ec.edelivery.smp.services;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import static eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* @since 5.1
* @author Joze RIHTARSIC
*/
class SMPLanguageResourceServiceTest {
File localeFolder = new File("target/locales");
ConfigurationService configurationService = Mockito.mock(ConfigurationService.class);
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
SMPLanguageResourceService testInstance = new SMPLanguageResourceService(configurationService, resourcePatternResolver);
@BeforeEach
void setUp() throws IOException {
// clean the folder
if (localeFolder.exists() ) {
// first delete all files and then empty folders
Files.walk(localeFolder.toPath())
.map( Path::toFile )
.sorted( Comparator.comparing( File::isDirectory ) )
.forEach( File::delete );
}
Mockito.when(configurationService.getLocaleFolder()).thenReturn(localeFolder);
}
@Test
void testMergeAddMissingProperty() {
// given
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode targetNode = objectMapper.createObjectNode();
targetNode.put("key1", "value1");
targetNode.put("key2", "value2");
ObjectNode referenceNode = objectMapper.createObjectNode();
referenceNode.put("key1", "value-001");
referenceNode.put("key2", "value-002");
referenceNode.put("key3", "value-003");
// when
boolean result = mergeTranslationJson(targetNode, referenceNode);
// then
assertTrue(result);
assertEquals("value1", targetNode.get("key1").asText());
assertEquals("value2", targetNode.get("key2").asText());
assertEquals("value-003", targetNode.get("key3").asText());
}
@Test
void testMergeAddMissingProperty2() {
// given
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode targetNode = objectMapper.createObjectNode();
targetNode.put("key1", "value1");
targetNode.put("key2", "");
ObjectNode referenceNode = objectMapper.createObjectNode();
referenceNode.put("key1", "value-001");
referenceNode.put("key2", "value-002");
// when
boolean result = mergeTranslationJson(targetNode, referenceNode);
// then
assertFalse(result);
assertEquals("value1", targetNode.get("key1").asText());
assertEquals("", targetNode.get("key2").asText());
assertFalse(targetNode.has("key3"));
}
@Test
void updateLocalesOnDiskCleanFolder() {
// given
assertFalse(localeFolder.exists());
// when
testInstance.updateLocalesOnDisk();
// then
assertTrue(localeFolder.exists());
File[] files = localeFolder.listFiles();
assertNotNull(files);
assertEquals(2, files.length);
assertEquals(LANGUAGE_FILENAME_UI_PREFIX + "en.json", files[0].getName());
assertEquals(LANGUAGE_FILENAME_MAIL_PREFIX + "en.json", files[1].getName());
}
@Test
void updateLocalesOnDiskOverwrite() throws IOException {
// given
ObjectMapper objectMapper = new ObjectMapper();
localeFolder.mkdirs();
String testText = "This must NOT be overwritten";
String testKey = "column.selection.link.all";
Path pathToFile = Paths.get(localeFolder.getAbsolutePath(), LANGUAGE_FILENAME_UI_PREFIX + "en.json");
assertFalse(pathToFile.toFile().exists());
// add one property
ObjectNode testNode = objectMapper.createObjectNode();
testNode.put(testKey, testText);
objectMapper.writeValue(pathToFile.toFile(), testNode);
assertTrue(pathToFile.toFile().exists());
// when
testInstance.updateLocalesOnDisk();
// then
assertTrue(localeFolder.exists());
File[] files = localeFolder.listFiles();
assertNotNull(files);
assertEquals(2, files.length);
assertEquals(LANGUAGE_FILENAME_UI_PREFIX + "en.json", files[0].getName());
assertEquals(LANGUAGE_FILENAME_MAIL_PREFIX + "en.json", files[1].getName());
JsonNode result = objectMapper.readTree(pathToFile.toFile());
assertEquals(testText, result.get(testKey).asText());
// 3 properties are added by the updateLocalesOnDisk method
// from the classpath resource META-INF/resources/ui/assets/i18n/en.json
assertEquals(4, result.size());
}
}
......@@ -19,9 +19,20 @@
package eu.europa.ec.edelivery.smp.services.mail;
import eu.europa.ec.edelivery.smp.data.ui.enums.AlertTypeEnum;
import eu.europa.ec.edelivery.smp.services.ConfigurationService;
import eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService;
import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialsExpirationProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
......@@ -30,8 +41,25 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
class MailTemplateTest {
File localeFolder = new File("target/locales");
ConfigurationService configurationService = Mockito.mock(ConfigurationService.class);
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
SMPLanguageResourceService smpLanguageResourceService = new SMPLanguageResourceService(configurationService, resourcePatternResolver);
MailTemplateService testInstance = new MailTemplateService();
MailTemplateService testInstance = new MailTemplateService(smpLanguageResourceService);
@BeforeEach
void setUp() throws IOException {
// clean the folder
if (localeFolder.exists() ) {
// first delete all files and then empty folders
Files.walk(localeFolder.toPath())
.map( Path::toFile )
.sorted( Comparator.comparing( File::isDirectory ) )
.forEach( File::delete );
}
Mockito.when(configurationService.getLocaleFolder()).thenReturn(localeFolder);
}
@Test
void getMailContent() {
......@@ -51,6 +79,5 @@ class MailTemplateTest {
assertTrue(result.contains("alert level"));
assertTrue(result.contains("credential id"));
assertTrue(result.contains("credential name"));
}
}
{
"column.selection.link.all": "All",
"column.selection.link.none": "None",
"column.selection.link.show": "Show columns",
"column.selection.link.hide": "Hide columns"
}
package eu.europa.ec.edelivery.smp.ui.external;
import eu.europa.ec.edelivery.smp.i18n.SMPLocale;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.services.SMPLocaleService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService;
import org.springframework.core.io.Resource;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.*;
import java.nio.file.Path;
import static eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService.LANGUAGE_FILENAME_UI_PREFIX;
import static eu.europa.ec.edelivery.smp.services.SMPLanguageResourceService.LANGUAGE_RESOURCE_UI_DEFAULT;
import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_LOCALE;
/**
......@@ -24,29 +21,16 @@ import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLI
@RequestMapping(value = CONTEXT_PATH_PUBLIC_LOCALE)
public class LocaleController {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(LocaleController.class);
private static final String DEFAULT_LOCALE_RESOURCE = "/META-INF/resources/ui/assets/i18n/en.json";
private final SMPLocaleService smpLocaleService;
public LocaleController(SMPLocaleService smpLocaleService) {
private final SMPLanguageResourceService smpLocaleService;
public LocaleController(SMPLanguageResourceService smpLocaleService) {
this.smpLocaleService = smpLocaleService;
}
@GetMapping(value = "/{code}", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
@ResponseBody
public Resource getLocale(@PathVariable("code") String code) {
Path langResourcePath = smpLocaleService.getLocaleFile(SMPLocale.fromCodeDefaultingToEnglish(code));
if (langResourcePath != null && langResourcePath.toFile().exists()) {
LOG.debug("Returning locale file [{}]", langResourcePath.toAbsolutePath());
return new FileSystemResource(langResourcePath);
} else {
LOG.warn("Locale file [{}] does not exist. Return default translation!", langResourcePath.toAbsolutePath());
ClassPathResource defResource = new ClassPathResource(DEFAULT_LOCALE_RESOURCE);
if (defResource.exists()) {
return defResource;
} else {
LOG.error("Default locale file [{}] does not exist in classpath!", DEFAULT_LOCALE_RESOURCE);
return null;
}
}
public Resource getLanguage(@PathVariable("code") String code) {
LOG.debug("Requesting locale file for code: [{}]", code);
return smpLocaleService.getTranslationResourceFile(LANGUAGE_FILENAME_UI_PREFIX, code, LANGUAGE_RESOURCE_UI_DEFAULT);
}
}
......@@ -172,6 +172,7 @@ public class UserAdminController {
}
DBUser user = uiUserService.updateUserPassword(authorizedUserId, changeUserId, newPassword.getCurrentPassword(), newPassword.getNewPassword(),!currentUser.isCasAuthenticated());
return authorizationService.sanitize(uiUserService.convertToRo(user));
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment