From 7aa51306288514151112a696d0fa9804ffba8c23 Mon Sep 17 00:00:00 2001
From: Alexander Schwartz
Date: Mon, 17 Mar 2025 15:18:02 +0100
Subject: [PATCH] Validate single quotes in themes
Closes #37930
Signed-off-by: Alexander Schwartz
---
docs/translation.md | 12 ++
.../account/messages/messages_ca.properties | 60 +++---
.../account/messages/messages_it.properties | 62 +++---
.../admin/messages/messages_ca.properties | 192 +++++++++---------
.../admin/messages/messages_fr.properties | 76 +++----
.../themeverifier/ThemeVerifierMojo.java | 8 +-
.../VerifyMessageProperties.java | 58 +++++-
.../VerifyMessagePropertiesTest.java | 19 ++
.../doubleSingleQuotes_en.properties | 17 ++
.../resources/singleQuotesEnd_en.properties | 17 ++
.../singleQuotesMiddle_en.properties | 17 ++
.../resources/singleQuotesStart_en.properties | 17 ++
.../admin/OrganizationInvitationLinkTest.java | 2 +-
themes/pom.xml | 3 +
.../account/messages/messages_ca.properties | 10 +-
.../account/messages/messages_ka.properties | 4 +-
.../account/messages/messages_nl.properties | 2 +-
.../admin/messages/messages_ca.properties | 2 +-
.../admin/messages/messages_it.properties | 20 +-
.../email/messages/messages_ca.properties | 4 +-
.../login/messages/messages_ca.properties | 20 +-
.../login/messages/messages_es.properties | 2 +-
.../login/messages/messages_ka.properties | 6 +-
.../login/messages/messages_nl.properties | 4 +-
.../login/messages/messages_ru.properties | 2 +-
.../account/messages/messages_en.properties | 2 +-
.../email/messages/messages_en.properties | 8 +-
.../login/messages/messages_en.properties | 4 +-
28 files changed, 406 insertions(+), 244 deletions(-)
create mode 100644 misc/theme-verifier/src/test/resources/doubleSingleQuotes_en.properties
create mode 100644 misc/theme-verifier/src/test/resources/singleQuotesEnd_en.properties
create mode 100644 misc/theme-verifier/src/test/resources/singleQuotesMiddle_en.properties
create mode 100644 misc/theme-verifier/src/test/resources/singleQuotesStart_en.properties
diff --git a/docs/translation.md b/docs/translation.md
index 4732852d76f..f8c3eb8fe77 100644
--- a/docs/translation.md
+++ b/docs/translation.md
@@ -27,6 +27,18 @@ To ensure consistency and quality across translations, please adhere to the foll
- Maintain consistency with existing translations.
- Translate text accurately, ensuring that the meaning is preserved.
+### Handling of single quotes (`'`)
+
+Whenever messages are formatted in the backend, Keycloak uses Java's MessageFormat to replace placeholders. This uses single quotes (`'`) as an escape mechanism.
+
+Therefore, use typographic quotes like `‘` and `’` where possible.
+
+To avoid problems, automatic checks ensure the following:
+
+* In all "base" themes, where message keys are evaluated in the backend, no single quote (`'`) must be used standalone as it would not print when used in Java's MessageFormat. For legacy messages, a double single quote (`''`) can be used to print a single quote.
+
+* In all UI themes, where message keys are evaluated in the frontend, a single quote (`'`) must only be used standalone, and a double single (`''`) must not be used.
+
### Spanish translations
- Use the formal "usted" form instead of the informal "vos or tu" (i.e., avoid tuteo), ensuring a more formal tone.
diff --git a/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_ca.properties b/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_ca.properties
index 6cfb27c8226..144efb56c3f 100644
--- a/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_ca.properties
+++ b/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_ca.properties
@@ -2,7 +2,7 @@
#Tue Jan 09 09:05:12 CET 2024
cancel=Cancel·la
backTo=Torna a {{app}}
-applicationType=Tipus d''aplicació
+applicationType=Tipus d'aplicació
noGroupsText=No us heu unit a cap grup
path=Camí
password=Contrasenya
@@ -11,29 +11,29 @@ lastAccessedOn=Últim accés
permissions=Permisos
credentialCreatedAt=<0>Creada0> el {{date}}.
error-username-invalid-character=«{{0}}» conté un caràcter no vàlid.
-infoMessage=Fent clic en «Elimina l''accés», eliminareu els permisos concedits a aquesta aplicació. Aquesta aplicació ja no podrà utilitzar la vostra informació.
+infoMessage=Fent clic en «Elimina l'accés», eliminareu els permisos concedits a aquesta aplicació. Aquesta aplicació ja no podrà utilitzar la vostra informació.
unknownOperatingSystem=Sistema operatiu desconegut
edit=Edita
-otp-display-name=aplicació d''autenticació
+otp-display-name=aplicació d'autenticació
linkedEmpty=No hi ha cap proveïdor enllaçat
directMembership=Pertinença directa
-error-invalid-length-too-short=L''atribut {0} ha de tindre una llargària mínima de {1}.
-error-number-out-of-range-too-big=L''atribut {0} ha de tindre valor màxim de {2}.
+error-invalid-length-too-short=L'atribut {0} ha de tindre una llargària mínima de {1}.
+error-number-out-of-range-too-big=L'atribut {0} ha de tindre valor màxim de {2}.
updateEmail=Actualitza el correu electrònic
two-factor=Autenticació de doble factor
signedInDevicesExplanation=Desconnecteu qualsevol dispositiu que no us siga familiar.
status=Estat
-error-number-out-of-range-too-small=L''atribut {0} ha de tindre valor mínim de {1}.
-removeModalMessage=Això eliminarà els permisos d''accés actualment concedits a {{name}}. Haureu de tornar a concedir accés si voleu utilitzar aquesta aplicació.
+error-number-out-of-range-too-small=L'atribut {0} ha de tindre valor mínim de {1}.
+removeModalMessage=Això eliminarà els permisos d'accés actualment concedits a {{name}}. Haureu de tornar a concedir accés si voleu utilitzar aquesta aplicació.
lastName=Cognoms
-invalidEmailMessage=«{{0}}»: l''adreça de correu electrònic no és vàlida.
+invalidEmailMessage=«{{0}}»: l'adreça de correu electrònic no és vàlida.
clients=Clients
filterByName=Filtra per nom…
refreshPage=Refresca la pàgina
-error-user-attribute-required=Especifiqueu l''atribut «{0}».
+error-user-attribute-required=Especifiqueu l'atribut «{0}».
currentSession=Sessió actual
error-empty=Especifiqueu el valor de «{{0}}».
-error-invalid-uri-fragment=«{{0}}» és un fragment d''URL invàlid.
+error-invalid-uri-fragment=«{{0}}» és un fragment d'URL invàlid.
error-invalid-blank=Especifiqueu el valor de «{{0}}».
missingFirstNameMessage=«{{0}}»: Indiqueu el nom.
signedOutSession=Desconnectat {{browser}}/{{os}}
@@ -42,24 +42,24 @@ close=Tanca
email=Correu electrònic
signOutWarning=Voleu sortir de la sessió?
signOutAllDevicesWarning=Aquesta acció desconnectarà tots els dispositius que han entrat al vostre compte, inclòs el dispositiu que esteu utilitzant ara mateix.
-unShareSuccess=S''ha deixat de compartir el recurs correctament.
+unShareSuccess=S'ha deixat de compartir el recurs correctament.
signingIn=Identificació
-stopUsingCred=Voleu deixar d''utilitzar {{name}}?
-error-number-out-of-range=L''atribut {0} ha de ser un número entre {1} i {2}.
+stopUsingCred=Voleu deixar d'utilitzar {{name}}?
+error-number-out-of-range=L'atribut {0} ha de ser un número entre {1} i {2}.
thirdPartyApp=De tercers
started=Iniciat
-updateSuccess=S''ha actualitzat el recurs correctament.
+updateSuccess=S'ha actualitzat el recurs correctament.
unShare=Deixa de compartir-ho tot
-removeAccess=Elimina l''accés
+removeAccess=Elimina l'accés
removeCred=Elimina {{name}}
signOutAllDevices=Desconnecta tots els dispositius
-error-invalid-email=L''adreça de correu electrònic no és vàlida.
+error-invalid-email=L'adreça de correu electrònic no és vàlida.
myResources=Els meus recursos
linkedAccountsIntroMessage=Gestiona les entrades a través de comptes de tercers.
groupDescriptionLabel=Visualitzeu els grups als quals esteu associat
resourceAlreadyShared=El recurs ja està compartit amb aquest usuari.
-error-invalid-length-too-long=L''atribut {0} ha de tindre una llargària màxima de {2}.
-accountUpdatedMessage=S''ha actualitzat el vostre compte.
+error-invalid-length-too-long=L'atribut {0} ha de tindre una llargària màxima de {2}.
+accountUpdatedMessage=S'ha actualitzat el vostre compte.
logo=Logotip
password-help-text=Entreu introduint la vostra contrasenya.
deleteAccount=Elimina el compte
@@ -87,24 +87,24 @@ description=Descripció
update=Actualitza
signedInDevices=Dispositius identificats
missingPasswordMessage=«{{0}}»: Indiqueu la contrasenya.
-otp-help-text=Introduïu el codi de verificació de l''aplicació d''autenticació.
-error-invalid-uri-scheme=«{{0}} té un esquema d''URL invàlid.
+otp-help-text=Introduïu el codi de verificació de l'aplicació d'autenticació.
+error-invalid-uri-scheme=«{{0}} té un esquema d'URL invàlid.
error-user-attribute-read-only=El camp {0} és només de lectura.
error-invalid-date=La data «{0}» no és vàlida.
missingEmailMessage=«{0}»: Indiqueu una adreça electrònica.
applicationsIntroMessage=Feu seguiment i gestioneu els permisos de les aplicacions per a accedir al vostre compte
-error-invalid-length=L''atribut {0} ha de tindre una llargària d''entre {1} i {2}.
+error-invalid-length=L'atribut {0} ha de tindre una llargària d'entre {1} i {2}.
missingLastNameMessage=«{0}»: Indiqueu els vostres cognoms.
-linkedLoginProviders=Proveïdors d''entrada enllaçats
+linkedLoginProviders=Proveïdors d'entrada enllaçats
inUse=En ús
client=Client
-error-invalid-uri=L''URL «{0}» no és vàlid.
+error-invalid-uri=L'URL «{0}» no és vàlid.
systemDefined=Definit pel sistema
internalApp=Internes
accessGrantedOn=Accés concedit el:
permissionRequests=Peticions de permís
-shareSuccess=S''ha compartit el recurs correctament.
-missingUsernameMessage=«{0}»: Indiqueu el vostre nom d''usuari.
+shareSuccess=S'ha compartit el recurs correctament.
+missingUsernameMessage=«{0}»: Indiqueu el vostre nom d'usuari.
fullName={{givenName}} {{familyName}}
resources=Recursos
resourceIntroMessage=Compartiu recursos entre membres del vostre equip
@@ -115,14 +115,14 @@ shareWith=Comparteix amb
updateCredAriaLabel=Actualitza la credencial
error-pattern-no-match=«{0}» no té el format requerit.
application=Aplicació
-unlinkedLoginProviders=Proveïdors d''entrada no enllaçats
-applicationDetails=Detalls de l''aplicació
-successRemovedMessage={{userLabel}} s''ha eliminat.
+unlinkedLoginProviders=Proveïdors d'entrada no enllaçats
+applicationDetails=Detalls de l'aplicació
+successRemovedMessage={{userLabel}} s'ha eliminat.
deleteAccountWarning=Això és irreversible. Totes les vostres dades es destruiran permanentment i no seran accessibles.
error-person-name-invalid-character=«{0}» conté un caràcter no vàlid.
user=Usuari
applications=Aplicacions
-username=Nom d''usuari
+username=Nom d'usuari
removeConsentSuccess=S'ha eliminat el consentiment amb èxit
required=Requerit
deviceActivity=Activitat dels aparells
@@ -215,5 +215,5 @@ errorSignOutMessage=No s'ha pogut sortir: {{error}}
errorRemovedMessage=No s'ha pogut suprimir {{userLabel}} a causa de: {{error}}
resourceSharedWith_other=El recurs està compartit amb <0>{{username}}0> i <1>{{other}}1> altres usuaris
shareUser=Afegeix usuaris amb qui compartir el recurs
-error-invalid-multivalued-size=L''atribut {{0}} ha de tenir almenys {{1}} i com a mot {{2}} valors.
+error-invalid-multivalued-size=L'atribut {{0}} ha de tenir almenys {{1}} i com a mot {{2}} valors.
termsAndConditionsDeclined=Cal que accepteu els Termes i Condicions per a continuar
diff --git a/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_it.properties b/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_it.properties
index c9b3d9fbc57..7cef00cc301 100644
--- a/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_it.properties
+++ b/js/apps/account-ui/maven-resources-community/theme/keycloak.v3/account/messages/messages_it.properties
@@ -10,8 +10,8 @@ setUpNew=Impostazione {{name}}
lastAccessedOn=Ultimo accesso
permissions=Permessi
credentialCreatedAt=<0>Creato0> {{date}}.
-error-username-invalid-character=''{0}'' contiene caratteri non validi.
-infoMessage=Cliccando su ''Rimuovi accesso'', rimuoverai le autorizzazioni concesse a questa applicazione. Questa applicazione non utilizzerà più le tue informazioni.
+error-username-invalid-character='{0}' contiene caratteri non validi.
+infoMessage=Cliccando su 'Rimuovi accesso', rimuoverai le autorizzazioni concesse a questa applicazione. Questa applicazione non utilizzerà più le tue informazioni.
unknownOperatingSystem=Sistema operativo sconosciuto
edit=Modifica
otp-display-name=Applicazione Authenticator (OTP)
@@ -20,35 +20,35 @@ signOut=Esci
linkedEmpty=Nessun provider collegato
directMembership=Membri diretti
accept=Accetta
-error-invalid-length-too-short=''{0}'' deve avere una lunghezza minima di {1}.
-error-number-out-of-range-too-big=''{0}'' deve avere un valore massimo di {2}.
+error-invalid-length-too-short='{0}' deve avere una lunghezza minima di {1}.
+error-number-out-of-range-too-big='{0}' deve avere un valore massimo di {2}.
updateEmail=Aggiorna email
two-factor=Autenticazione a due fattori
signedInDevicesExplanation=Uscire da tutti i dispositivi sconosciuti.
status=Stato
-error-number-out-of-range-too-small=''{0}'' deve avere un valore minimo di {1}.
-removeModalMessage=Questo rimuoverà l''autorizzazione di accesso attualmente concessa per {{name}}. Dovrai concedere nuovamente l''accesso se vuoi utilizzare questa applicazione.
+error-number-out-of-range-too-small='{0}' deve avere un valore minimo di {1}.
+removeModalMessage=Questo rimuoverà l’autorizzazione di accesso attualmente concessa per {{name}}. Dovrai concedere nuovamente l’accesso se vuoi utilizzare questa applicazione.
lastName=Cognome
invalidEmailMessage='{{0}}': indirizzo email non valido.
clients=Client
filterByName=Filtra per nome ...
refreshPage=Aggiornare la pagina
-error-user-attribute-required=Specificare ''{0}''.
+error-user-attribute-required=Specificare '{0}'.
currentSession=Sessione in corso
-error-empty=Specificare il valore di ''{0}''.
-error-invalid-uri-fragment=''{0}'' è un frammento URL non valido.
+error-empty=Specificare il valore di '{0}'.
+error-invalid-uri-fragment='{0}' è un frammento URL non valido.
signedOutSession=Disconnesso {{browser}}/{{os}}
missingFirstNameMessage='{{0}}': inserisci il nome.
-error-invalid-blank=Specificare il valore di ''{0}''.
+error-invalid-blank=Specificare il valore di '{0}'.
share=Condiviso
close=Chiudi
email=Email
signOutWarning=Chiudere la sessione?
-signOutAllDevicesWarning=Quest''azione disconnetterà tutti i dispositivi che hanno effettuato l''accesso al tuo utente, compreso il dispositivo attualmente in uso.
+signOutAllDevicesWarning=Quest'azione disconnetterà tutti i dispositivi che hanno effettuato l'accesso al tuo utente, compreso il dispositivo attualmente in uso.
unShareSuccess=La condivisione della risorsa è stata rimossa.
signingIn=Impostazioni di accesso
stopUsingCred=Smettere di usare {{name}}?
-error-number-out-of-range=''{0}'' deve essere un numero compreso tra {1} e {2}.
+error-number-out-of-range='{0}' deve essere un numero compreso tra {1} e {2}.
thirdPartyApp=Applicazioni di terze parti
started=Iniziato
updateSuccess=Risorsa aggiornata con successo.
@@ -61,13 +61,13 @@ myResources=Le mie risorse
linkedAccountsIntroMessage=Gestire gli accessi tramite utenze di terzi.
groupDescriptionLabel=Visualizza i gruppi con cui sei associato/a
resourceAlreadyShared=La risorsa è già condivisa con questo utente.
-error-invalid-length-too-long=''{0}'' deve avere una lunghezza massima di {2}.
+error-invalid-length-too-long='{0}' deve avere una lunghezza massima di {2}.
accountUpdatedMessage=Il tuo utente è stato aggiornato.
logo=Logo
password-help-text=Accedere inserendo la password.
deleteAccount=Elimina utente
add=Aggiungi
-error-invalid-value=''{0}'' ha un valore non valido.
+error-invalid-value='{0}' ha un valore non valido.
ipAddress=Indirizzo IP
resourceName=Nome della risorsa
unlinkedEmpty=Nessun provider scollegato
@@ -84,23 +84,23 @@ password-display-name=Password
expires=Scade
noGroups=Nessun gruppo
notSetUp={{name}} non è impostato.
-error-invalid-number=''{0}'' non è un numero valido.
+error-invalid-number='{0}' non è un numero valido.
link=Account collegato
description=Descrizione
update=Aggiorna
signedInDevices=Dispositivi registrati
missingPasswordMessage='{{0}}': inserisci la password.
-otp-help-text=Immettere un codice di verifica dall''applicazione Authenticator.
-error-invalid-uri-scheme=''{0}'' ha uno schema URL non valido.
-error-invalid-date=''{0}'' è una data non valida.
-missingEmailMessage='{{0}}': inserisci l''indirizzo email.
-applicationsIntroMessage=Traccia e gestisci i permessi delle applicazioni nell''accesso al tuo account
-error-invalid-length=''{0}'' deve avere una lunghezza compresa tra {1} e {2}.
+otp-help-text=Immettere un codice di verifica dall’applicazione Authenticator.
+error-invalid-uri-scheme='{0}' ha uno schema URL non valido.
+error-invalid-date='{0}' è una data non valida.
+missingEmailMessage='{{0}}': inserisci l’indirizzo email.
+applicationsIntroMessage=Traccia e gestisci i permessi delle applicazioni nell’accesso al tuo account
+error-invalid-length='{0}' deve avere una lunghezza compresa tra {1} e {2}.
missingLastNameMessage='{{0}}': inserisci il cognome.
linkedLoginProviders=Provider di accesso collegati
inUse=In uso
client=Client
-error-invalid-uri=''{0}'' è un URL non valido.
+error-invalid-uri='{0}' è un URL non valido.
systemDefined=SSistema definito
internalApp=Interna
accessGrantedOn=Accesso concesso il:
@@ -115,13 +115,13 @@ termsOfService=Termini di servizio
requestor=Richiedente
shareWith=Condividi con
updateCredAriaLabel=Aggiorna credenziali
-error-pattern-no-match=''{0}'' non corrisponde al formato richiesto.
+error-pattern-no-match='{0}' non corrisponde al formato richiesto.
application=Applicazione
unlinkedLoginProviders=Provider di accesso scollegati
-applicationDetails=Dettagli dell''applicazione
+applicationDetails=Dettagli dell’applicazione
successRemovedMessage={{userLabel}} è stato rimosso.
deleteAccountWarning=Questa operazione è irreversibile. Tutti i tuoi dati saranno distrutti in modo permanente e non potranno essere recuperati.
-error-person-name-invalid-character=''{0}'' contiene caratteri non validi.
+error-person-name-invalid-character='{0}' contiene caratteri non validi.
user=Utente
applications=Applicazioni
username=Nome utente
@@ -139,7 +139,7 @@ avatar=Avatar
personalInfoDescription=Gestisci le tue informazioni di base
personalInfo=Informazioni personali
flowTypeHelp=Che tipo di modulo è
-accountSecurity=Sicurezza dell''utente
+accountSecurity=Sicurezza dell'utente
manageAccount=Gestione utente
shareError=Non è possibile condividere la risorsa a causa di: {{error}}
somethingWentWrongDescription=Ci dispiace, si è verificato un errore imprevisto.
@@ -166,7 +166,7 @@ recovery-codes-generate-new-codes=Genera nuovi codici per assicurarti l'accesso
oid4vci=Credenziali verificabili
verifiableCredentialsTitle=Credenziali verificabili
verifiableCredentialsIssuerAlert=Non è stato possibile ottenere informazioni sull'emittente.
-verifiableCredentialsOfferAlert=Non è stato possibile ottenere un''offerta.
+verifiableCredentialsOfferAlert=Non è stato possibile ottenere un’offerta.
verifiableCredentialsSelectionDefault=Seleziona la configurazione di una credenziale.
phoneScopeConsentText=Numero di telefono
offlineAccessScopeConsentText=Accesso offline
@@ -201,19 +201,19 @@ addressScopeConsentText=Indirizzo
rolesScopeConsentText=Ruoli dell'utente
somethingWentWrong=Qualcosa è andato storto
emptyUserOrganizationsInstructions=Non sei ancora membro di alcuna organizzazione.
-searchOrganization=Cerca un''organizzazione
+searchOrganization=Cerca un’organizzazione
organizationList=Elenco delle organizzazioni
termsAndConditionsDeclined=Per poter continuare devi accettare i termini e le condizioni
permissionRequest=Richieste di permesso - {{name}}
general=Generale
-rolesScope=Se non è stata definita alcuna mappatura dell''ambito (scope) su un ruolo, ogni utente è autorizzato a utilizzare questo ambito client. Se sono state definite mappature dell''ambito su un ruolo, l''utente deve essere membro di almeno uno dei ruoli.
+rolesScope=Se non è stata definita alcuna mappatura dell'ambito (scope) su un ruolo, ogni utente è autorizzato a utilizzare questo ambito client. Se sono state definite mappature dell'ambito su un ruolo, l'utente deve essere membro di almeno uno dei ruoli.
unLinkError=Non è possibile togliere il collegamento: {{error}}
recovery-authn-code=I miei codici di recupero
signingInDescription=Configura le modalità di accesso.
removeConsentError=Non è possibile rimuovere il consenso a causa di: {{error}}
linkedAccounts=Utenze collegate
groupsListHeader=Intestazione lista gruppi
-scopeNameHelp=Nome dell''ambito client. Deve essere univoco nel realm. Il nome non deve contenere caratteri di spazio, poiché viene utilizzato come valore del parametro ambito
+scopeNameHelp=Nome dell'ambito client. Deve essere univoco nel realm. Il nome non deve contenere caratteri di spazio, poiché viene utilizzato come valore del parametro ambito
scopeDescriptionHelp=Descrizione dell'ambito del client
-selectOne=Seleziona un''opzione
+selectOne=Seleziona un’opzione
privacyPolicy=Politica sulla riservatezza
diff --git a/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_ca.properties b/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_ca.properties
index 25a8aa901e4..9f73e945d5a 100644
--- a/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_ca.properties
+++ b/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_ca.properties
@@ -1,121 +1,121 @@
storePassword=Contrasenya del magatzem
-logoutServiceRedirectBindingURLHelp=URL d''enllaç SAML de redirecció per a la desconnexió única del client. Pots deixar-ho en blanc si estàs fent servir un enllaç diferent.
+logoutServiceRedirectBindingURLHelp=URL d'enllaç SAML de redirecció per a la desconnexió única del client. Pots deixar-ho en blanc si estàs fent servir un enllaç diferent.
themes=Temes
password=Contrasenya
-clientType=''OpenID connect'' permet als clients verificar la identitat de l''usuari final basat en l''autenticació realitzada per un servidor d''autorització. ''SAML'' habilita l''autenticació i autorització d''escenaris basats en web incloent cross-domain i single sign-on (SSO) i utilitza tokens de seguretat que contenen afirmacions per passar informació.
+clientType='OpenID connect' permet als clients verificar la identitat de l'usuari final basat en l'autenticació realitzada per un servidor d'autorització. 'SAML' habilita l'autenticació i autorització d'escenaris basats en web incloent cross-domain i single sign-on (SSO) i utilitza tokens de seguretat que contenen afirmacions per passar informació.
composite=Compost
clientSignature=Signatura de Client requerida
-waitIncrementSecondsHelp=Quan s''ha arribat al llindar d''error, quant de temps ha d''estar un usuari bloquejat?
+waitIncrementSecondsHelp=Quan s'ha arribat al llindar d'error, quant de temps ha d'estar un usuari bloquejat?
nodeHost=Host del node
-mapperType=Tipus d''assignador
-quickLoginCheckMilliSeconds=Si ocorren errors de forma concurrent i molt ràpida, bloquejar a l''usuari.
+mapperType=Tipus d'assignador
+quickLoginCheckMilliSeconds=Si ocorren errors de forma concurrent i molt ràpida, bloquejar a l'usuari.
edit=Edita
unspecified=no especificat
-archiveFormat=Format d''Arxiu
+archiveFormat=Format d'Arxiu
validatorDialogColNames.colName=Nom de rol
associatedRolesText=Rols Associats
certificateHelp=Certificat de client per validar els JWT emesos per aquest client i signats amb la clau privada del client del teu magatzem de claus.
credentialType=Tipus
defaultLocale=Idioma per defecte
-clientIdHelp=L''identificador del client registrat amb el proveïdor d''identitat.
+clientIdHelp=L'identificador del client registrat amb el proveïdor d'identitat.
forcePostBindingHelp=Fes servir sempre POST per a les respostes.
-authorizationUrl=URL d''autorització
+authorizationUrl=URL d'autorització
roleName=Nom de rol
httpPostBindingAuthnRequestHelp=Indica si AuthnRequest ha de ser enviat usant HTTP-POST. Si no està activat es fa HTTP-REDIRECT.
securityDefences=Defenses de seguretat
-accessTokenLifespanHelp=Temps màxim abans que un token d''accés expiri. Es recomana que aquest valor sigui curt en relació al temps màxim de SSO.
-includeInAccessToken.tooltip=S''hauria d'afegir la identitat reclamada al token d''accés?
-redirectURIHelp=L''URI de redirecció usada per configurar el proveïdor d''identitat.
-idpInitiatedSsoRelayStateHelp=Estat de retransmissió que voleu enviar amb una petició SAML quan es vol fer servir un SSO iniciat per l''IDP.
+accessTokenLifespanHelp=Temps màxim abans que un token d'accés expiri. Es recomana que aquest valor sigui curt en relació al temps màxim de SSO.
+includeInAccessToken.tooltip=S'hauria d'afegir la identitat reclamada al token d'accés?
+redirectURIHelp=L'URI de redirecció usada per configurar el proveïdor d'identitat.
+idpInitiatedSsoRelayStateHelp=Estat de retransmissió que voleu enviar amb una petició SAML quan es vol fer servir un SSO iniciat per l'IDP.
attestationPreference.none=cap
revocation=Revocació
-clientDescriptionHelp=Indica la descripció del client. Per exemple ''My Client for TimeSheets''. També suporta claus per a valors localitzats. Per exemple: ${my_client_description}.
+clientDescriptionHelp=Indica la descripció del client. Per exemple 'My Client for TimeSheets'. També suporta claus per a valors localitzats. Per exemple: ${my_client_description}.
clientAuthenticator=Client autenticador
-useEntityDescriptor=Importar metadades des d''un descriptor d'entitat remot d''un IDP de SAML
-logoutServiceRedirectBindingURL=URL d''enllaç SAML de redirecció per a la desconnexió
-loginActionTimeout=Temps màxim d''acció en l''inici de sessió
-idpInitiatedSsoRelayState=Estat de retransmissió d''un SSO iniciat per l''IDP
+useEntityDescriptor=Importar metadades des d'un descriptor d'entitat remot d'un IDP de SAML
+logoutServiceRedirectBindingURL=URL d'enllaç SAML de redirecció per a la desconnexió
+loginActionTimeout=Temps màxim d'acció en l'inici de sessió
+idpInitiatedSsoRelayState=Estat de retransmissió d'un SSO iniciat per l'IDP
validatingX509Certs=Validant certificat X509
masterSamlProcessingUrl=URL principal de processament SAML
key=Clau
-validRedirectURIs=Patró d''URI vàlida per a la qual un navegador pot sol·licitar la redirecció després d''un inici o tancament de sessió completat. Es permeten comodins simples p.ex. ''http://example.com/*''. També es poden indicar rutes relatives p.ex. ''/my/relative/path/*''. Les rutes relatives generaran un URI de redirecció fent servir el host i port de la petició. Per SAML, s''han de fixar patrons d''URI vàlids si vols confiar en l''URL del servei del consumidor indicada en la petició d''inici de sessió.
-userInfoUrl=URL d''informació d''usuari
+validRedirectURIs=Patró d'URI vàlida per a la qual un navegador pot sol·licitar la redirecció després d'un inici o tancament de sessió completat. Es permeten comodins simples p.ex. 'http://example.com/*'. També es poden indicar rutes relatives p.ex. '/my/relative/path/*'. Les rutes relatives generaran un URI de redirecció fent servir el host i port de la petició. Per SAML, s'han de fixar patrons d'URI vàlids si vols confiar en l'URL del servei del consumidor indicada en la petició d'inici de sessió.
+userInfoUrl=URL d'informació d'usuari
assertionConsumerServicePostBindingURL=Assertion Consumer Service POST Binding URL
usermodel.clientRoleMapping.clientId.label=ID Client
-identityProviders=Proveïdors d''identitat
+identityProviders=Proveïdors d'identitat
clientId=ID Client
nameIdPolicyFormat=Format de política NameID
-idpInitiatedSsoUrlName=Nom del fragment de l''URL per referenciar al client quan vols un SSO iniciat per l''IDP. Deixant això buit desactiva els SSO iniciats per l''IDP. L''URL referenciada des del navegador serà\: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
+idpInitiatedSsoUrlName=Nom del fragment de l'URL per referenciar al client quan vols un SSO iniciat per l'IDP. Deixant això buit desactiva els SSO iniciats per l'IDP. L'URL referenciada des del navegador serà\: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
validatingX509CertsHelp=El certificat en format PEM que ha de fer-se servir per comprovar les signatures.
-importFile=Arxiu d''Importació
-clientLoginTimeoutHelp=Temps màxim que un client té per finalitzar el protocol d''obtenció del token d''accés. Hauria de ser normalment de l''ordre d''1 minut.
+importFile=Arxiu d'Importació
+clientLoginTimeoutHelp=Temps màxim que un client té per finalitzar el protocol d'obtenció del token d'accés. Hauria de ser normalment de l'ordre d'1 minut.
lastAccess=Últim Accés
ssoSessionIdle=Temps màxim que una sessió pot estar inactiva abans que expiri. Els tokens i sessions de navegador són invalidades quan la sessió expira.
xFrameOptions=X-Frame-Options
prompts.none=cap
-emailTheme=Tema d''email
+emailTheme=Tema d'email
times.minutes=Minuts
nameIdFormatHelp=El format de nom de l'ID que es farà servir per al títol.
forcePostBinding=Forçar enllaços POST
-discoveryEndpoint=Importa metadades des d''un descriptor d''un proveïdor d''identitat (IDP) remot.
+discoveryEndpoint=Importa metadades des d'un descriptor d'un proveïdor d'identitat (IDP) remot.
registerNodeManually=Registrar node manualment
redirectURI=URI de redirecció
signDocuments=Signar documents
tokenUrl=Token URL
consentRequired=Es requereix consentiment
notBefore=No abans de
-editUsername=Edita el nom d''usuari
+editUsername=Edita el nom d'usuari
lastRegistration=Últim registre
requireSsl=Sol·licitar SSL
-samlEntityDescriptor=Et permet carregar metadades d''un proveïdor d''identitat (IDP) extern d''un arxiu de coniguración o descarregar des d''una URL.
+samlEntityDescriptor=Et permet carregar metadades d'un proveïdor d'identitat (IDP) extern d'un arxiu de coniguración o descarregar des d'una URL.
wantAuthnRequestsSigned=Signar AuthnRequests
-usermodel.attr.tooltip=Nom de l''atribut d''usuari emmagatzemat que és el nom de l''atribut dins el map UserModel.attribute.
+usermodel.attr.tooltip=Nom de l'atribut d'usuari emmagatzemat que és el nom de l'atribut dins el map UserModel.attribute.
export=Exporta
generateNewKeys=Generar noves claus
offlineSessionIdle=Inactivitat de sessió sense connexió
backchannelLogout=Backchannel Logout
-userRegistrationHelpText=Habilitar/deshabilitar la pàgina de registre. Un enllaç per al registre es mostrarà també a la pàgina d''inici de sessió.
-revokeRefreshToken=Revocar el token d''actualització
+userRegistrationHelpText=Habilitar/deshabilitar la pàgina de registre. Un enllaç per al registre es mostrarà també a la pàgina d'inici de sessió.
+revokeRefreshToken=Revocar el token d'actualització
minimumQuickLoginWaitSeconds=Temps mínim entre errors de connexió ràpids
prompts.login=login
-offlineSessionIdleHelp=Temps màxim inactiu d''una sessió sense connexió abans que expiri. Necessites fer servi un token sense connexió per refrescar almenys una vegada dins d'aquest període, en un altre cas la sessió sense connexió expirarà.
-forceNameIdFormatHelp=Ignorar la petició de subjecte NameID i fer servir la configurada a la consola d''administració.
+offlineSessionIdleHelp=Temps màxim inactiu d'una sessió sense connexió abans que expiri. Necessites fer servi un token sense connexió per refrescar almenys una vegada dins d'aquest període, en un altre cas la sessió sense connexió expirarà.
+forceNameIdFormatHelp=Ignorar la petició de subjecte NameID i fer servir la configurada a la consola d'administració.
realmRoles=Rols de domini
port=Port
-adminThemeHelp=Selecciona el tema per a la consola d''administració.
+adminThemeHelp=Selecciona el tema per a la consola d'administració.
nameIdFormat=Format de NameID
validRedirectUri=URIs de redirecció vàlides
clientList=Clients
userSession.modelNote.label=Nota sessió usuari
-logoutServicePostBindingURL=URL d''enllaç SAML POST per a la desconnexió
+logoutServicePostBindingURL=URL d'enllaç SAML POST per a la desconnexió
singleLogoutServiceUrl=URL de servei de desconnexió únic
-userAttribute=Atribut d''usuari
+userAttribute=Atribut d'usuari
roles=Rols
description=Descripció
-validateSignatureHelp=Habilitar/deshabilitar la validació de signatures de proveïdors d''identitat (IDP) externs
+validateSignatureHelp=Habilitar/deshabilitar la validació de signatures de proveïdors d'identitat (IDP) externs
clientSignatureHelp=Signarà el client les seves peticions i respostes SAML? I haurien de ser validades?
title=Sessions
-keyPasswordHelp=Contrasenya per accedir a la clau privada continguda en l''arxiu
+keyPasswordHelp=Contrasenya per accedir a la clau privada continguda en l'arxiu
verifyEmail=Verificar email
frontchannelLogout=Desconnexió en primer pla (Front Channel)
formatOption=Format
-loginTheme=Tema d''inici de sessió
+loginTheme=Tema d'inici de sessió
provider=Proveïdor
providerId=ID
titleRoles=Rols de domini
-nodeReRegistrationTimeout=Temps d''espera de re-registre de node
+nodeReRegistrationTimeout=Temps d'espera de re-registre de node
loginTimeout=Temps màxim de desconnexió
-accessTokenLifespan=Durada del token d''accés
+accessTokenLifespan=Durada del token d'accés
setToNow=Fixar a ara
-signAssertionsHelp=Haurien de signar-se les assercions en documents SAML? Aquest ajust no és necessari si el document ja s''està signant.
+signAssertionsHelp=Haurien de signar-se les assercions en documents SAML? Aquest ajust no és necessari si el document ja s'està signant.
validateSignature=Validar signatures
headers=Capçaleres
fineGrainSamlEndpointConfig=Fine Grain SAML Endpoint Configuration
hours=Hores
encryptAssertions=Xifrar afirmacions
-keyAliasHelp=Àlies de l''arxiu de la teva clau privada i certificat.
-aliasHelp=L''àlies que identifica de forma única un proveïdor d''identitat, es far servir també per construir la URI de redirecció.
-tokenClaimName.tooltip=Nom del reclam a inserir en el testimoni. Pot ser un nom complet com ''address.street''. En aquest cas, es crearà un objecte JSON niat.
+keyAliasHelp=Àlies de l'arxiu de la teva clau privada i certificat.
+aliasHelp=L'àlies que identifica de forma única un proveïdor d'identitat, es far servir també per construir la URI de redirecció.
+tokenClaimName.tooltip=Nom del reclam a inserir en el testimoni. Pot ser un nom complet com 'address.street'. En aquest cas, es crearà un objecte JSON niat.
maxFailureWaitSeconds=Espera màxima
userName=Usuari
clientProfileDescription=Descripció
@@ -127,80 +127,80 @@ webOrigins=Orígens web
realm=Domini
prompt=Prompt
username=Usuari
-importConfig=Importa metadades des d''un descriptor d''un proveïdor d''identitat (IDP) descarregat.
-bruteForceDetection=Detecció d''atacs per força bruta
-archiveFormatHelp=Format d''arxiu Java keystore o PKCS12
+importConfig=Importa metadades des d'un descriptor d'un proveïdor d'identitat (IDP) descarregat.
+bruteForceDetection=Detecció d'atacs per força bruta
+archiveFormatHelp=Format d'arxiu Java keystore o PKCS12
keyAlias=Àlies de clau
-revokeRefreshTokenHelp=Si està activat els tokens d''actualització només poden usar-se una vegada. En un altre cas els tokens d''actualització no es revoquen quan s''utilitzen i poden ser usat múltiples vegades.
-storedTokensReadableHelp=Habilitar/deshabilitar si els nous usuaris poden llegir els tokens emmagatzemats. Això assigna el rol ''broker.read-token''.
+revokeRefreshTokenHelp=Si està activat els tokens d'actualització només poden usar-se una vegada. En un altre cas els tokens d'actualització no es revoquen quan s'utilitzen i poden ser usat múltiples vegades.
+storedTokensReadableHelp=Habilitar/deshabilitar si els nous usuaris poden llegir els tokens emmagatzemats. Això assigna el rol 'broker.read-token'.
none=cap
sslType.all=totes les peticions
type=Tipus
httpPostBindingResponse=HTTP-POST enllaç de resposta
issuer=Emissor
seconds=Segons
-editUsernameHelp=Si està habilitat, el nom d''usuari és editable, altrament és de només lectura.
+editUsernameHelp=Si està habilitat, el nom d'usuari és editable, altrament és de només lectura.
id=ID
-accountThemeHelp=Selecciona el tema per a les pàgines de gestió del compte d''usuari.
+accountThemeHelp=Selecciona el tema per a les pàgines de gestió del compte d'usuari.
fullScopeAllowedHelp=Permet deshabilitar totes les restriccions.
canonicalizationHelp=Mètode de canonicalització per a les signatures XML.
sessions=Sessions
includeAuthnStatement=Incloure AuthnStatement
jsonType.tooltip=El tipus de JSON que hauria de fer-se servir per omplir la petició de JSON en el token. long, int, boolean i String són valors vàlids.
-multivalued.tooltip=Indica si l''atribut suporta múltiples valors. Si està habilitat, la llista de tots els valors d''aquest atribut es fixarà com a reclamació. Si està deshabilitat, només el primer valor serà fixat com a reclamació.
+multivalued.tooltip=Indica si l'atribut suporta múltiples valors. Si està habilitat, la llista de tots els valors d'aquest atribut es fixarà com a reclamació. Si està deshabilitat, només el primer valor serà fixat com a reclamació.
enableStartTLS=Habilitar StartTLS
enableStartTls=Habilitar StartTLS
-addIdPMapper=Afegeix assignador de proveïdor d''identitat
-trustEmail=Confiar en l''email
+addIdPMapper=Afegeix assignador de proveïdor d'identitat
+trustEmail=Confiar en l'email
jsonType.label=Tipus JSON de reclamació
fullScopeAllowed=Permet tots els àmbits
push=Push
homeURL=URL inicial
-masterSamlProcessingUrlHelp=Si està configurada, aquesta URL es fara servir per a cada enllaç al proveïdor del servei del consumidor d''assercions i serveis de desconnexió únics. Pot ser sobreescrit de forma individual per a cada enllaç i servei en el punt final de configuració fina de SAML.
-usermodel.attr.label=Atribut d''usuari
+masterSamlProcessingUrlHelp=Si està configurada, aquesta URL es fara servir per a cada enllaç al proveïdor del servei del consumidor d'assercions i serveis de desconnexió únics. Pot ser sobreescrit de forma individual per a cada enllaç i servei en el punt final de configuració fina de SAML.
+usermodel.attr.label=Atribut d'usuari
claimJsonType=El tipus de JSON que hauria de fer-se servir per omplir la petició de JSON en el token. long, int, boolean i String són valors vàlids
-forceAuthenticationHelp=Indica si el proveïdor d''identitat ha d'autenticar en presentar directament les credencials en lloc de dependre d''un context de seguretat previ.
+forceAuthenticationHelp=Indica si el proveïdor d'identitat ha d'autenticar en presentar directament les credencials en lloc de dependre d'un context de seguretat previ.
testClusterAvailability=Provar disponibilitat del clúster
forceNameIdFormat=Forçar format NameID
-rememberMeHelpText=Mostra la casella de selecció en la pàgina d''inici de sessió per a permetre a l''usuari estar connectat entre reinicis del navegador fins que la sessió expiri.
+rememberMeHelpText=Mostra la casella de selecció en la pàgina d'inici de sessió per a permetre a l'usuari estar connectat entre reinicis del navegador fins que la sessió expiri.
sslType.external=peticions externes
-multiValued=Indica si l''atribut suporta múltiples valors. Si està habilitat, la llista de tots els valors d''aquest atribut es fixarà com a reclamació. Si està deshabilitat, només el primer valor serà fixat com a reclamació.
+multiValued=Indica si l'atribut suporta múltiples valors. Si està habilitat, la llista de tots els valors d'aquest atribut es fixarà com a reclamació. Si està deshabilitat, només el primer valor serà fixat com a reclamació.
addRole=Afegir rol
ssoServiceUrl=URL de servei de connexió únic (SSO)
clients=Clients
clientName=Nom
-userRegistration=Registre d''usuari
+userRegistration=Registre d'usuari
save=Desar
-wantAuthnRequestsSignedHelp=Indica si el proveïdor d''identitat espera rebre signades les AuthnRequest.
+wantAuthnRequestsSignedHelp=Indica si el proveïdor d'identitat espera rebre signades les AuthnRequest.
login=login
enabled=Habilitat
-maxDeltaTimeSeconds=Reinici del comptador d''errors
+maxDeltaTimeSeconds=Reinici del comptador d'errors
keyPassword=Contrasenya de la clau
backchannelLogoutHelp=Does the external IDP support backchannel logout?
SSOSessionIdle=Sessions SSO inactives
-ssoServiceUrlHelp=L''URL que s''ha de fer servir per enviar peticions d''autenticació (SAML AuthnRequest).
-trustEmailHelp=Si està habilitat, l''email rebut d''aquest proveïdor no es verificarà encara que la verificació estigui habilitada per al domini.
+ssoServiceUrlHelp=L'URL que s'ha de fer servir per enviar peticions d'autenticació (SAML AuthnRequest).
+trustEmailHelp=Si està habilitat, l'email rebut d'aquest proveïdor no es verificarà encara que la verificació estigui habilitada per al domini.
supportedLocales=Idiomes suportats
maxFailureWaitSecondsHelp=Temps màxim que un usuari queda bloquejat.
-issuerHelp=L''identificador de l''emissor per a l''emissor de la resposta. Si no s''indica, no es realitzarà cap validació.
+issuerHelp=L'identificador de l'emissor per a l'emissor de la resposta. Si no s'indica, no es realitzarà cap validació.
titleSessions=Sessions
-clientNameHelp=Indica el nom visible del client. Per exemple ''My Client''. També suporta claus per valors localitzats. Per exemple: ${my_client}
-maxDeltaTimeSecondsHelp=Quan s''ha de reiniciar el comptador d''errors?
-adminURLHelp=URL a la interfície d''administració del client. Fixa aquest valor si el client suporta l''adaptador de REST. Aquesta API REST permet al servidor d''autenticació enviar al client polítiques de revocació i altres tasques administratives. Normalment es fixa a l''URL base del client.
+clientNameHelp=Indica el nom visible del client. Per exemple 'My Client'. També suporta claus per valors localitzats. Per exemple: ${my_client}
+maxDeltaTimeSecondsHelp=Quan s'ha de reiniciar el comptador d'errors?
+adminURLHelp=URL a la interfície d'administració del client. Fixa aquest valor si el client suporta l'adaptador de REST. Aquesta API REST permet al servidor d'autenticació enviar al client polítiques de revocació i altres tasques administratives. Normalment es fixa a l'URL base del client.
contentSecurityPolicy=Content-Security-Policy
rootUrl=URL arrel
rootURL=URL arrel afegida a les URL relatives
-storePasswordHelp=Contrasenya per accedir a l''arxiu
+storePasswordHelp=Contrasenya per accedir a l'arxiu
frontchannelLogoutHelp=Quan està activat, la desconnexió requereix una redirecció del navegador cap al client. Quan no està activat, el servidor realitza una invovación de desconnexió en segon pla.
-clientLoginTimeout=Temps màxim d''autenticació
-nodeReRegistrationTimeoutHelp=Indica el màxim interval de temps perquè els nodes del clúster registrats es tornin a registrar. Si el node del clúster no envia una petició de re-registre a Keycloak dins d''aquest interval, serà desregistrat de Keycloak
-logoutServicePostBindingURLHelp=URL d''enllaç SAML POST per a la desconnexió única del client. Pots deixar-ho en blanc si estàs fent servir un enllaç diferent.
-registrationEmailAsUsername=Email com a nom d''usuari
+clientLoginTimeout=Temps màxim d'autenticació
+nodeReRegistrationTimeoutHelp=Indica el màxim interval de temps perquè els nodes del clúster registrats es tornin a registrar. Si el node del clúster no envia una petició de re-registre a Keycloak dins d'aquest interval, serà desregistrat de Keycloak
+logoutServicePostBindingURLHelp=URL d'enllaç SAML POST per a la desconnexió única del client. Pots deixar-ho en blanc si estàs fent servir un enllaç diferent.
+registrationEmailAsUsername=Email com a nom d'usuari
scopes=Àmbits
signDocumentsHelp=Hauria el domini de signar els documents SAML?
-requireSslHelp=És HTTP obligatori? ''cap'' significa que HTTPS no és obligatori per cap direcicón IP de client, ''peticions externes'' indica que localhost i les adreces IP privades poden accedir sense HTTPS, ''totes les peticions'' vol dir que HTTPS és obligatori per a totes les adreces IP.
-userInfoUrlHelp=L''URL d''informació d''usuari. Opcional.
-includeAuthnStatementHelp=Hauria d''incloure''s una declaració especificant el mètode i la marca de temps en la resposta d''inici de sessió?
+requireSslHelp=És HTTP obligatori? 'cap' significa que HTTPS no és obligatori per cap direcicón IP de client, 'peticions externes' indica que localhost i les adreces IP privades poden accedir sense HTTPS, 'totes les peticions' vol dir que HTTPS és obligatori per a totes les adreces IP.
+userInfoUrlHelp=L'URL d'informació d'usuari. Opcional.
+includeAuthnStatementHelp=Hauria d'incloure's una declaració especificant el mètode i la marca de temps en la resposta d'inici de sessió?
kc.realm.name=Domini
download=Descarrega
protocol=Protocol
@@ -210,26 +210,26 @@ create=Crea
clientSecret=Secret de Client
from=Des de
httpPostBindingAuthnRequest=HTTP-POST per AuthnRequest
-includeInAccessToken.label=Afegir al token d''accés
-adminURL=URL d''administració
+includeInAccessToken.label=Afegir al token d'accés
+adminURL=URL d'administració
settings=Ajustos
failureFactorHelp=Indica quants errors es permeten abans que es dispari una espera.
minutes=Minuts
-storeTokensHelp=Habilitar/deshabilitar si els tokens han de ser emmagatzemats després d''autenticar als usuaris.
-singleLogoutServiceUrlHelp=L''URL que ha de fer-se servir per enviar peticions de desconnexió.
-userSession.modelNote.tooltip=Nom de la nota emmagatzemada en la sessió d''usuari dins del mapa UserSessionModel.note
-clientsClientTypeHelp=''OpenID connect'' permet als clients verificar la identitat de l''usuari final basat en l''autenticació realitzada per un servidor d''autorització. ''SAML'' habilita l''autenticació i autorització d''escenaris basats en web incloent cross-domain i single sign-on (SSO) i utilitza tokens de seguretat que contenen afirmacions per passar informació.
+storeTokensHelp=Habilitar/deshabilitar si els tokens han de ser emmagatzemats després d'autenticar als usuaris.
+singleLogoutServiceUrlHelp=L'URL que ha de fer-se servir per enviar peticions de desconnexió.
+userSession.modelNote.tooltip=Nom de la nota emmagatzemada en la sessió d'usuari dins del mapa UserSessionModel.note
+clientsClientTypeHelp='OpenID connect' permet als clients verificar la identitat de l'usuari final basat en l'autenticació realitzada per un servidor d'autorització. 'SAML' habilita l'autenticació i autorització d'escenaris basats en web incloent cross-domain i single sign-on (SSO) i utilitza tokens de seguretat que contenen afirmacions per passar informació.
storeTokens=Emmagatzemar tokens
-includeInIdToken.label=Afegir al token d''ID
-webOriginsHelp=Orígens CORS permesos. Per permetre tots els orígens d''URIs de redirecció vàlides afegeix ''+''. Per permetre tots els orígens afegeix ''*''.
+includeInIdToken.label=Afegir al token d'ID
+webOriginsHelp=Orígens CORS permesos. Per permetre tots els orígens d'URIs de redirecció vàlides afegeix '+'. Per permetre tots els orígens afegeix '*'.
emailThemeHelp=Selecciona el tema per als correus electrònics que són enviats pel servidor.
logoutUrl=URL de desconnexió
canonicalization=Mètode de canonicalització
storedTokensReadable=Tokens emmagatzemats llegibles
SSOSessionMax=Temps màxim sessió SSO
-minimumQuickLoginWaitSecondsHelp=Quant de temps s''ha d''esperar després d''un error en un intent ràpid d''identificació
+minimumQuickLoginWaitSecondsHelp=Quant de temps s'ha d'esperar després d'un error en un intent ràpid d'identificació
mappers=Assignadors
-waitIncrementSeconds=Increment d''espera
+waitIncrementSeconds=Increment d'espera
usermodel.prop.label=Propietat
name-id-format=Format de NameID
addNode=Afegir Node
@@ -240,34 +240,34 @@ selectRole.label=Selecciona rol
prompts.consent=consentiment
enableSSL=Habilitar SSL
general=General
-failureFactor=Nombre màxim d''errors d''inici de sessió
+failureFactor=Nombre màxim d'errors d'inici de sessió
signAssertions=Signar assercions
-adminTheme=Tema de consola d''administració
+adminTheme=Tema de consola d'administració
alias=Àlies
tokens=Tokens
encryptAssertionsHelp=Haurien de xifrar-se les afirmacions SAML amb la clau pública del client fent servir AES?
-clientSecretHelp=El secret del client registrat amb el proveïdor d''identitat.
+clientSecretHelp=El secret del client registrat amb el proveïdor d'identitat.
validateSignatures=Habilitar/deshabilitar la validació de signatura en respostes SAML.
on=Activat
-descriptionHelp=Indica la descripció del client. Per exemple ''My Client for TimeSheets''. També suporta claus per a valors localitzats. Per exemple\: ${my_client_description}
-logoutUrlHelp=Punt de tancament de sessió per utilitzar en la desconnexió d''usuaris des d''un proveïdor d''identitat (IDP) extern.
+descriptionHelp=Indica la descripció del client. Per exemple 'My Client for TimeSheets'. També suporta claus per a valors localitzats. Per exemple\: ${my_client_description}
+logoutUrlHelp=Punt de tancament de sessió per utilitzar en la desconnexió d'usuaris des d'un proveïdor d'identitat (IDP) extern.
times.seconds=Segons
clear=Neteja
-serviceAccount=Permetre autenticar aquest client contra Keycloak i rebre un token d''accés dedicat per a aquest client.
+serviceAccount=Permetre autenticar aquest client contra Keycloak i rebre un token d'accés dedicat per a aquest client.
assertionConsumerServiceRedirectBindingURL=Assertion Consumer Service Redirect Binding URL
-loginThemeHelp=Selecciona el tema per a les pàgines d''inici de sessió, OTP, permisos, registre i recordatori de contrasenya.
-signatureAlgorithm=L''algorisme de signatura usat per signar els documents.
+loginThemeHelp=Selecciona el tema per a les pàgines d'inici de sessió, OTP, permisos, registre i recordatori de contrasenya.
+signatureAlgorithm=L'algorisme de signatura usat per signar els documents.
multivalued.label=Valors múltiples
accountTheme=Tema de compte
forceAuthentication=Forçar autenticació
clustering=Clustering
rememberMe=Mantenir connectat
category=Categoria
-usermodel.prop.tooltip=Nom del mètode de propietat en la interfície UserModel. Per exemple, un valor de ''email'' faria referència al mètode UserModel.getEmail().
+usermodel.prop.tooltip=Nom del mètode de propietat en la interfície UserModel. Per exemple, un valor de 'email' faria referència al mètode UserModel.getEmail().
times.days=Dies
user=Usuari
registeredClusterNodes=Registrar nodes de clúster
-selectRole.tooltip=Introdueix el rol a la caixa de text de l''esquerra, o fes clic a aquest botó per navegar i buscar el rol que vols.
+selectRole.tooltip=Introdueix el rol a la caixa de text de l'esquerra, o fes clic a aquest botó per navegar i buscar el rol que vols.
deleteConfirm_other=Esteu segur de voler suprimir aquests grups?
persistent=Persistent
cancel=Cancel·la
diff --git a/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_fr.properties b/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_fr.properties
index 6e64d536fb3..c0a5a83173a 100644
--- a/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_fr.properties
+++ b/js/apps/admin-ui/maven-resources-community/theme/keycloak.v2/admin/messages/messages_fr.properties
@@ -1,10 +1,10 @@
bruteForceDetection=Détection des attaques par force brute
sslType.all=Toutes les requêtes
themes=Thèmes
-editUsernameHelp=Si actif, le champ du nom de l''utilisateur est modifiable.
+editUsernameHelp=Si actif, le champ du nom de l'utilisateur est modifiable.
seconds=Secondes
password=Mot de passe
-waitIncrementSecondsHelp=Quand le seuil des erreurs est atteint, combien de temps l''utilisateur est-il bloqué ?
+waitIncrementSecondsHelp=Quand le seuil des erreurs est atteint, combien de temps l'utilisateur est-il bloqué ?
accountThemeHelp=Sélectionnez le thème pour la gestion des comptes.
events=Évènements
sessions=Sessions
@@ -14,65 +14,65 @@ enableStartTls=Activer StartTLS
push=Appuyer
defaultLocale=Locale par défaut
htmlDisplayName=Nom d'affichage HTML
-rememberMeHelpText=Affiche une case à cocher sur la page de connexion pour permettre aux utilisateurs de rester connectés entre deux redémarrages de leur navigateur, jusqu''à expiration de la session.
+rememberMeHelpText=Affiche une case à cocher sur la page de connexion pour permettre aux utilisateurs de rester connectés entre deux redémarrages de leur navigateur, jusqu'à expiration de la session.
sslType.external=Les requêtes externes
securityDefences=Mesures de sécurité
realmSettings=Configurations du domaine
duplicateEmailsHelpText=Autorise plusieurs utilisateurs à avoir la même adresse de courriel. Changer cette configuration va vider le cache. Il est recommandé de mettre à jour manuellement les contraintes sur le courriel dans la base de données après la désactivation du support des doublons.
clients=Clients
-accessTokenLifespanHelp=Durée maximale avant que le jeton d''accès n''expire. Cette valeur devrait être relativement plus petite que la durée d''inactivité (timeout) du SSO.
-userRegistration=Enregistrement d''utilisateur
+accessTokenLifespanHelp=Durée maximale avant que le jeton d'accès n'expire. Cette valeur devrait être relativement plus petite que la durée d'inactivité (timeout) du SSO.
+userRegistration=Enregistrement d'utilisateur
save=Sauver
enabled=Actif
revocation=Révocation
maxDeltaTimeSeconds=Durée de remise à zéro des erreurs
SSOSessionIdle=Sessions SSO inactives
-loginActionTimeout=Durée d''inactivité des actions de connexions
+loginActionTimeout=Durée d'inactivité des actions de connexions
endpoints=Endpoints
supportedLocales=Locales supportées
maxFailureWaitSecondsHelp=Durée maximale de blocage du compte utilisateur
-clientLoginTimeoutHelp=Durée maximale qu''a un client pour finir le protocole du jeton d''accès. Devrait être de l''ordre de la minute (1 min).
+clientLoginTimeoutHelp=Durée maximale qu'a un client pour finir le protocole du jeton d'accès. Devrait être de l'ordre de la minute (1 min).
titleSessions=Sessions
-ssoSessionIdle=Temps d''inactivité autorisé avant expiration de la session. Les jetons et les sessions navigateurs sont invalidées quand la session expire.
+ssoSessionIdle=Temps d'inactivité autorisé avant expiration de la session. Les jetons et les sessions navigateurs sont invalidées quand la session expire.
xFrameOptions=X-Frame-Options
maxDeltaTimeSecondsHelp=Quand les erreurs sont-elles remises à zéro ?
contentSecurityPolicy=Content-Security-Policy
-clientLoginTimeout=Durée d''inactivité de connexion (timeout)
+clientLoginTimeout=Durée d'inactivité de connexion (timeout)
userFederation=Regroupement Utilisateur
emailTheme=Thème pour le courriel
times.minutes=Minutes
-registrationEmailAsUsername=Courriel comme nom d''utilisateur
-requireSslHelp=Niveau d''exigence HTTPS \: ''aucun'' signifie que le HTTPS n''est requis pour aucune adresse IP cliente. ''les requêtes externes'' signifie que localhost et les adresses IP privées peuvent accéder sans HTTPS. ''toutes les requêtes'' signifie que le protocole HTTPS est obligatoire pour toutes les adresses IP.
+registrationEmailAsUsername=Courriel comme nom d'utilisateur
+requireSslHelp=Niveau d'exigence HTTPS \: 'aucun' signifie que le HTTPS n'est requis pour aucune adresse IP cliente. 'les requêtes externes' signifie que localhost et les adresses IP privées peuvent accéder sans HTTPS. 'toutes les requêtes' signifie que le protocole HTTPS est obligatoire pour toutes les adresses IP.
notBefore=Pas avant
-editUsername=Éditez le nom de l''utilisateur
+editUsername=Éditez le nom de l'utilisateur
titleEvents=Évènements
requireSsl=SSL requis
-impersonate=Usurper l''identité
+impersonate=Usurper l'identité
host=Hôte
from=De
add=Ajouter
-failureFactorHelp=Nombre d''erreurs avant de déclencher le temps d''attente.
+failureFactorHelp=Nombre d'erreurs avant de déclencher le temps d'attente.
minutes=Minutes
-userRegistrationHelpText=Activer/désactiver la page d''enregistrement. Un lien pour l''enregistrement sera visible sur la page de connexion.
-minimumQuickLoginWaitSeconds=Durée minimale d''attente entre deux connexions
+userRegistrationHelpText=Activer/désactiver la page d'enregistrement. Un lien pour l'enregistrement sera visible sur la page de connexion.
+minimumQuickLoginWaitSeconds=Durée minimale d'attente entre deux connexions
port=Port
-adminThemeHelp=Sélectionnez le thème de la UI d''administration.
+adminThemeHelp=Sélectionnez le thème de la UI d'administration.
emailThemeHelp=Sélectionnez le thème pour les courriels envoyées par le serveur.
clientList=Clients
SSOSessionMax=Maximum de sessions SSO
-minimumQuickLoginWaitSecondsHelp=Durée d''attente demandée après une erreur entre deux connexions.
-waitIncrementSeconds=Temps d''attente
+minimumQuickLoginWaitSecondsHelp=Durée d'attente demandée après une erreur entre deux connexions.
+waitIncrementSeconds=Temps d'attente
certificate=Certificat
title=Authentification
verifyEmail=Vérification du courriel
enableSSL=Activer SSL/TLS
general=Général
-failureFactor=Nombre maximal d''erreurs de connexion
+failureFactor=Nombre maximal d'erreurs de connexion
loginTheme=Thème de connexion
-adminTheme=Thème de la UI d''administration
-accessTokenLifespan=Durée de vie du jeton d''accès
-loginWithEmailHelpText=Autorise l''utilisateur à s''authentifier avec son adresse de courriel.
-loginTimeout=Durée d''inactivité de connexion
+adminTheme=Thème de la UI d'administration
+accessTokenLifespan=Durée de vie du jeton d'accès
+loginWithEmailHelpText=Autorise l'utilisateur à s'authentifier avec son adresse de courriel.
+loginTimeout=Durée d'inactivité de connexion
tokens=Jetons
setToNow=Mettre à maintenant
authentication=Authentification
@@ -80,34 +80,34 @@ times.seconds=Secondes
headers=En-têtes
hours=Heures
clear=Effacer
-maxFailureWaitSeconds=Durée maximale d''attente
+maxFailureWaitSeconds=Durée maximale d'attente
configure=Configurer
-userName=Nom de l''utilisateur
-loginThemeHelp=Sélectionnez le thème pour les pages de connexion, de mot de passe à usage unique basé sur le temps, des droits, de l''enregistrement, et du mot passe oublié.
+userName=Nom de l'utilisateur
+loginThemeHelp=Sélectionnez le thème pour les pages de connexion, de mot de passe à usage unique basé sur le temps, des droits, de l'enregistrement, et du mot passe oublié.
manage=Gérer
-ssoSessionMax=Durée maximale avant que la session n''expire. Les jetons et les sessions navigateurs sont invalidées quand la session expire.
+ssoSessionMax=Durée maximale avant que la session n'expire. Les jetons et les sessions navigateurs sont invalidées quand la session expire.
accountTheme=Thème du compte
times.hours=Heures
rememberMe=Se souvenir de moi
titleAuthentication=Authentification
times.days=Jours
-username=Nom de l''utilisateur
+username=Nom de l'utilisateur
passwordPoliciesHelp.regexPattern=Le mot de passe doit correspondre à une ou plusieurs des expressions régulières Java définies.
passwordPoliciesHelp.length=Le nombre minimum de caractères requis pour le mot de passe.
-passwordPoliciesHelp.passwordBlacklist=Empêche l''utilisation d''un mot de passe présent dans la liste noire.
+passwordPoliciesHelp.passwordBlacklist=Empêche l'utilisation d'un mot de passe présent dans la liste noire.
passwordPoliciesHelp.digits=Le nombre de caractères numériques requis dans le mot de passe.
-passwordPoliciesHelp.notUsername=Le mot de passe ne peut pas être identique au nom d''utilisateur.
-passwordPoliciesHelp.notContainsUsername=Le mot de passe ne peut pas contenir le nom d''utilisateur.
-passwordPoliciesHelp.passwordHistory=Empêche un mot de passe récent d''être réutilisé.
-passwordPoliciesHelp.notEmail=Le mot de passe ne peut pas être identique à l''adresse mail de l''utilisateur.
+passwordPoliciesHelp.notUsername=Le mot de passe ne peut pas être identique au nom d'utilisateur.
+passwordPoliciesHelp.notContainsUsername=Le mot de passe ne peut pas contenir le nom d'utilisateur.
+passwordPoliciesHelp.passwordHistory=Empêche un mot de passe récent d'être réutilisé.
+passwordPoliciesHelp.notEmail=Le mot de passe ne peut pas être identique à l'adresse mail de l'utilisateur.
passwordPoliciesHelp.maxLength=Le nombre maximum de caractères autorisés dans le mot de passe.
-passwordPoliciesHelp.maxAuthAge=L''âge maximum d''une authentification avec laquelle un mot de passe peut être modifié sans réauthentification.
+passwordPoliciesHelp.maxAuthAge=L'âge maximum d'une authentification avec laquelle un mot de passe peut être modifié sans réauthentification.
passwordPoliciesHelp.specialChars=Le nombre de caractères spéciaux requis dans le mot de passe.
passwordPoliciesHelp.lowerCase=Le nombre de lettres minuscules requises dans le mot de passe.
-passwordPoliciesHelp.forceExpiredPasswordChange=Le nombre de jours pendant lesquels le mot de passe est valide avant qu''un nouveau mot de passe ne soit requis.
+passwordPoliciesHelp.forceExpiredPasswordChange=Le nombre de jours pendant lesquels le mot de passe est valide avant qu'un nouveau mot de passe ne soit requis.
passwordPoliciesHelp.upperCase=Le nombre de lettres majuscules requises dans le mot de passe.
-passwordPoliciesHelp.hashIterations=Le nombre de fois qu''un mot de passe est haché avant stockage ou vérification. Le nombre de rondes par défaut selon l'algorithme est : -1 pour Argon2, 210 000 pour pbkdf2-sha512, 600 000 pour pbkdf2-sha256 et 1 300 000 pour pbkdf2.
-passwordPoliciesHelp.hashAlgorithm=Applique un algorithme de hachage aux mots de passe, afin qu''ils ne soient pas stockés en texte clair.
+passwordPoliciesHelp.hashIterations=Le nombre de fois qu'un mot de passe est haché avant stockage ou vérification. Le nombre de rondes par défaut selon l'algorithme est : -1 pour Argon2, 210 000 pour pbkdf2-sha512, 600 000 pour pbkdf2-sha256 et 1 300 000 pour pbkdf2.
+passwordPoliciesHelp.hashAlgorithm=Applique un algorithme de hachage aux mots de passe, afin qu'ils ne soient pas stockés en texte clair.
trusted-hosts.label=Hôtes de confiance
deletedSuccess=Fournisseur supprimé avec succès.
cancel=Annuler
diff --git a/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/ThemeVerifierMojo.java b/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/ThemeVerifierMojo.java
index 5779165ed1a..75ba00b2441 100644
--- a/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/ThemeVerifierMojo.java
+++ b/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/ThemeVerifierMojo.java
@@ -31,6 +31,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.stream.Collectors;
@Mojo(name = "verify-theme", defaultPhase = LifecyclePhase.INSTALL, threadSafe = true)
public class ThemeVerifierMojo extends AbstractMojo {
@@ -38,6 +39,9 @@ public class ThemeVerifierMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject mavenProject;
+ @Parameter(defaultValue = "false", readonly = true)
+ private boolean validateMessageFormatQuotes;
+
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
Iterator resources = mavenProject.getResources().iterator();
@@ -48,11 +52,11 @@ public class ThemeVerifierMojo extends AbstractMojo {
Iterator fileIterator = FileUtils.iterateFiles(dir, MessagePropertiesFilter.INSTANCE, DirectoryFileFilter.INSTANCE);
while (fileIterator.hasNext()) {
File file = fileIterator.next();
- messages.addAll(new VerifyMessageProperties(file).verify());
+ messages.addAll(new VerifyMessageProperties(file).withValidateMessageFormatQuotes(validateMessageFormatQuotes).verify());
}
}
if (!messages.isEmpty()) {
- throw new MojoFailureException("Validation errors: " + messages);
+ throw new MojoFailureException("Validation errors: " + messages.stream().collect(Collectors.joining(System.lineSeparator())));
}
}
}
diff --git a/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java b/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java
index 88d30090d30..22be7610a29 100644
--- a/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java
+++ b/misc/theme-verifier/src/main/java/org/keycloak/themeverifier/VerifyMessageProperties.java
@@ -38,6 +38,7 @@ public class VerifyMessageProperties {
private final File file;
private List messages;
+ private boolean validateMessageFormatQuotes;
public VerifyMessageProperties(File file) {
this.file = file;
@@ -50,12 +51,61 @@ public class VerifyMessageProperties {
verifyNoDuplicateKeys(contents);
verifySafeHtml();
verifyProblematicBlanks();
+ if (validateMessageFormatQuotes) {
+ verifyMessageFormatQuotes();
+ } else {
+ verifyNotMessageFormatQuotes();
+ }
} catch (IOException e) {
throw new MojoExecutionException("Can not read file " + file, e);
}
return messages;
}
+ private final static Pattern DOUBLE_SINGLE_QUOTES = Pattern.compile("''");
+
+ private void verifyNotMessageFormatQuotes() {
+ PropertyResourceBundle bundle;
+ try (FileInputStream fis = new FileInputStream(file)) {
+ bundle = new PropertyResourceBundle(fis);
+ } catch (IOException e) {
+ throw new RuntimeException("unable to read file " + file, e);
+ }
+
+ bundle.getKeys().asIterator().forEachRemaining(key -> {
+ String value = bundle.getString(key);
+
+ if (DOUBLE_SINGLE_QUOTES.matcher(value).find()) {
+ messages.add("Double single quotes are not allowed in message formats as they might be shown in frontends as-is in '" + key + "' for file " + file + ": " + value);
+ }
+
+ });
+ }
+
+ private static final Pattern SINGLE_QUOTE_MIDDLE = Pattern.compile("[^']'[^']");
+ private static final Pattern SINGLE_QUOTE_END = Pattern.compile("[^']'$");
+ private static final Pattern SINGLE_QUOTE_START = Pattern.compile("^'[^']");
+
+ private void verifyMessageFormatQuotes() {
+ PropertyResourceBundle bundle;
+ try (FileInputStream fis = new FileInputStream(file)) {
+ bundle = new PropertyResourceBundle(fis);
+ } catch (IOException e) {
+ throw new RuntimeException("unable to read file " + file, e);
+ }
+
+ bundle.getKeys().asIterator().forEachRemaining(key -> {
+ String value = bundle.getString(key);
+
+ if (SINGLE_QUOTE_START.matcher(value).find()
+ || SINGLE_QUOTE_MIDDLE.matcher(value).find()
+ || SINGLE_QUOTE_END.matcher(value).find()) {
+ messages.add("Single quotes are not allowed in message formats due to unexpected behaviors in '" + key + "' for file " + file + ": " + value);
+ }
+
+ });
+ }
+
PolicyFactory POLICY_SOME_HTML = new org.owasp.html.HtmlPolicyBuilder()
.allowElements(
"br", "p", "strong", "b"
@@ -135,7 +185,7 @@ public class VerifyMessageProperties {
String value = bundle.getString(key);
if (value.contains(" ")) {
- messages.add("Duplicate blanks in " + key + " for file " + file + ": '" + value);
+ messages.add("Duplicate blanks in '" + key + "' for file " + file + ": '" + value);
}
if (value.startsWith(" ")) {
@@ -224,4 +274,10 @@ public class VerifyMessageProperties {
messages.add("Duplicate keys in file '" + file.getAbsolutePath() + "': " + duplicateKeys);
}
}
+
+ public VerifyMessageProperties withValidateMessageFormatQuotes(boolean validateMessageFormatQuotes) {
+ this.validateMessageFormatQuotes = validateMessageFormatQuotes;
+ return this;
+ }
+
}
diff --git a/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java b/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java
index 09806921698..9bb2072b142 100644
--- a/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java
+++ b/misc/theme-verifier/src/test/java/org/keycloak/themeverifier/VerifyMessagePropertiesTest.java
@@ -51,6 +51,25 @@ class VerifyMessagePropertiesTest {
MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Didn't find anchor tag")));
}
+ @Test
+ void verifyNoSingleQuoteForMessageFormat() throws MojoExecutionException {
+ List verify = getFile("singleQuotesStart_en.properties").withValidateMessageFormatQuotes(true).verify();
+ MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Single quotes are not allowed")));
+
+ verify = getFile("singleQuotesMiddle_en.properties").withValidateMessageFormatQuotes(true).verify();
+ MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Single quotes are not allowed")));
+
+ verify = getFile("singleQuotesEnd_en.properties").withValidateMessageFormatQuotes(true).verify();
+ MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Single quotes are not allowed")));
+
+ }
+
+ @Test
+ void verifyNoDoubleQuoteForUIMessages() throws MojoExecutionException {
+ List verify = getFile("doubleSingleQuotes_en.properties").withValidateMessageFormatQuotes(false).verify();
+ MatcherAssert.assertThat(verify, Matchers.hasItem(Matchers.containsString("Double single quotes are not allowed")));
+ }
+
@Test
void verifyNoExtraBlanks() throws MojoExecutionException {
List verify = getFile("blanks_en.properties").verify();
diff --git a/misc/theme-verifier/src/test/resources/doubleSingleQuotes_en.properties b/misc/theme-verifier/src/test/resources/doubleSingleQuotes_en.properties
new file mode 100644
index 00000000000..e705a673c07
--- /dev/null
+++ b/misc/theme-verifier/src/test/resources/doubleSingleQuotes_en.properties
@@ -0,0 +1,17 @@
+#
+# Copyright 2025 Red Hat, Inc. and/or its affiliates
+# and other contributors as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+key=test''test
\ No newline at end of file
diff --git a/misc/theme-verifier/src/test/resources/singleQuotesEnd_en.properties b/misc/theme-verifier/src/test/resources/singleQuotesEnd_en.properties
new file mode 100644
index 00000000000..d466d32a886
--- /dev/null
+++ b/misc/theme-verifier/src/test/resources/singleQuotesEnd_en.properties
@@ -0,0 +1,17 @@
+#
+# Copyright 2025 Red Hat, Inc. and/or its affiliates
+# and other contributors as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+key='value
\ No newline at end of file
diff --git a/misc/theme-verifier/src/test/resources/singleQuotesMiddle_en.properties b/misc/theme-verifier/src/test/resources/singleQuotesMiddle_en.properties
new file mode 100644
index 00000000000..a1fb5efcaab
--- /dev/null
+++ b/misc/theme-verifier/src/test/resources/singleQuotesMiddle_en.properties
@@ -0,0 +1,17 @@
+#
+# Copyright 2025 Red Hat, Inc. and/or its affiliates
+# and other contributors as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+key=va'lue
\ No newline at end of file
diff --git a/misc/theme-verifier/src/test/resources/singleQuotesStart_en.properties b/misc/theme-verifier/src/test/resources/singleQuotesStart_en.properties
new file mode 100644
index 00000000000..d466d32a886
--- /dev/null
+++ b/misc/theme-verifier/src/test/resources/singleQuotesStart_en.properties
@@ -0,0 +1,17 @@
+#
+# Copyright 2025 Red Hat, Inc. and/or its affiliates
+# and other contributors as indicated by the @author tags.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+key='value
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/OrganizationInvitationLinkTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/OrganizationInvitationLinkTest.java
index 3928ab41c77..5936a53f85e 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/OrganizationInvitationLinkTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/OrganizationInvitationLinkTest.java
@@ -381,7 +381,7 @@ public class OrganizationInvitationLinkTest extends AbstractOrganizationTest {
assertThat(text, Matchers.containsString(("Link to join the organization
")));
assertThat(text, Matchers.containsString(("Link to join the organization")));
assertThat(text, Matchers.containsString(("This link will expire within 12 hours")));
- assertThat(text, Matchers.containsString(("If you dont want to join the organization, just ignore this message.
")));
+ assertThat(text, Matchers.containsString(("If you don't want to join the organization, just ignore this message.
")));
String orgToken = UriUtils.parseQueryParameters(link, false).values().stream().map(strings -> strings.get(0)).findFirst().orElse(null);
Assert.assertNotNull(orgToken);
diff --git a/themes/pom.xml b/themes/pom.xml
index 72062807452..0f7270fbd28 100755
--- a/themes/pom.xml
+++ b/themes/pom.xml
@@ -44,6 +44,9 @@
verify-theme
+
+ true
+
diff --git a/themes/src/main/resources-community/theme/base/account/messages/messages_ca.properties b/themes/src/main/resources-community/theme/base/account/messages/messages_ca.properties
index 617da8b8dd6..cd8b33e8372 100644
--- a/themes/src/main/resources-community/theme/base/account/messages/messages_ca.properties
+++ b/themes/src/main/resources-community/theme/base/account/messages/messages_ca.properties
@@ -61,13 +61,13 @@ gender=Gènere
birthday=Natalici
zoneinfo=Fus horari
gssDelegationCredential=Credencial de delegació GSS
-profileScopeConsentText=Perfil d'usuari
+profileScopeConsentText=Perfil d’usuari
emailScopeConsentText=Adreça de correu electrònic
addressScopeConsentText=Adreça
phoneScopeConsentText=Número de telèfon
offlineAccessScopeConsentText=Accés fora de línia
samlRoleListScopeConsentText=Els meus rols
-rolesScopeConsentText=Rols d'usuari
+rolesScopeConsentText=Rols d’usuari
role_admin=Administrador
role_realm-admin=Administrador del domini
role_create-realm=Crea un domini
@@ -354,6 +354,6 @@ error-user-attribute-read-only=El camp {0} és només de lectura.
error-username-invalid-character=El nom d''usuari conté un caràcter no vàlid.
error-person-name-invalid-character=El nom conté un caràcter no vàlid.
organizationScopeConsentText=Organització
-invalidPasswordNotContainsUsernameMessage=La contrasenya no és vàlida: no pot contenir el nom d'usuari.
-accountManagementBaseThemeCannotBeUsedDirectly=El tema de compte base només conté traduccions per a la consola de compte. Per a mostrar la consola de compte, heu d'establir el pare del vostre tema a un altre tema de compte, o proveir el vostre fitxer intdex.ftl.
-federatedIdentityBoundOrganization=No podeu suprimir l'enllaç a un proveïdor d'identitat sense una organització.
+invalidPasswordNotContainsUsernameMessage=La contrasenya no és vàlida: no pot contenir el nom d’usuari.
+accountManagementBaseThemeCannotBeUsedDirectly=El tema de compte base només conté traduccions per a la consola de compte. Per a mostrar la consola de compte, heu d’establir el pare del vostre tema a un altre tema de compte, o proveir el vostre fitxer intdex.ftl.
+federatedIdentityBoundOrganization=No podeu suprimir l’enllaç a un proveïdor d’identitat sense una organització.
diff --git a/themes/src/main/resources-community/theme/base/account/messages/messages_ka.properties b/themes/src/main/resources-community/theme/base/account/messages/messages_ka.properties
index 082216758ba..891a959c16d 100644
--- a/themes/src/main/resources-community/theme/base/account/messages/messages_ka.properties
+++ b/themes/src/main/resources-community/theme/base/account/messages/messages_ka.properties
@@ -204,7 +204,7 @@ backTo={0}-ზე დაბრუნება
backToApplication=« აპლიკაციაზე დაბრუნება
grantedPersonalInfo=მინიჭებული პირადი ინფორმაცია
totpStep1=დააყენეთ ერთ-ერთი ამ აპლიკაციათაგანი თქვენს მობილურზე:
-totpStep3=შეიყვანეთ ერთჯერადი კოდი, რომელიც აპლიკაციამ მოგაწოდათ და დააწკაპუნეთ ღილაკზე 'შენახვა', რომ მორგება დაასრულოთ.
+totpStep3=შეიყვანეთ ერთჯერადი კოდი, რომელიც აპლიკაციამ მოგაწოდათ და დააწკაპუნეთ ღილაკზე ''შენახვა'', რომ მორგება დაასრულოთ.
totpUnableToScan=ვერ დაასკანერეთ?
totpManualStep2=გახსენით აპლიკაცია და შეიყვანეთ კოდი:
irreversibleAction=ეს ქმედება შეუქცევადია
@@ -269,7 +269,7 @@ mobileSetupStep2=გახსენით აპლიკაცია და დ
#Authenticator - SMS Code setup
authenticatorSMSCodeSetupTitle=SMS კოდის მორგება
chooseYourCountry=აირჩიეთ თქვენი ქვეყანა
-mobileSetupStep3=შეიყვანეთ ერთჯერადი კოდი, რომელიც აპლიკაციამ მოგაწოდათ და დააწკაპუნეთ ღილაკზე 'შენახვა', რომ მორგება დაასრულოთ.
+mobileSetupStep3=შეიყვანეთ ერთჯერადი კოდი, რომელიც აპლიკაციამ მოგაწოდათ და დააწკაპუნეთ ღილაკზე ''შენახვა'', რომ მორგება დაასრულოთ.
scanBarCode=გნებავთ ბარკოდის დასკანირება?
enterBarCode=შეიყვანეთ ერთჯერადი კოდი
sendVerficationCode=გადამოწმების კოდის გაგზავნა
diff --git a/themes/src/main/resources-community/theme/base/account/messages/messages_nl.properties b/themes/src/main/resources-community/theme/base/account/messages/messages_nl.properties
index 0a06f9f017f..05dc215e87f 100644
--- a/themes/src/main/resources-community/theme/base/account/messages/messages_nl.properties
+++ b/themes/src/main/resources-community/theme/base/account/messages/messages_nl.properties
@@ -126,7 +126,7 @@ configureAuthenticators=Ingestelde authenticators
mobile=Mobiel
totpStep1=Installeer een van de volgende applicaties op je mobiele apparaat:
totpStep2=Open de applicatie en scan de barcode:
-totpStep3=Voer de eenmalige code in – gegenereerd door de applicatie – en tik op 'Opslaan' om de installatie te voltooien.
+totpStep3=Voer de eenmalige code in – gegenereerd door de applicatie – en tik op ''Opslaan'' om de installatie te voltooien.
totpStep3DeviceName=Geef je apparaat een naam om je OTP-apparaten overzichtelijk te houden.
totpManualStep2=Open de applicatie en voer de sleutel in:
totpManualStep3=Gebruik de volgende configuratiewaarden als de applicatie deze instellingen toestaat:
diff --git a/themes/src/main/resources-community/theme/base/admin/messages/messages_ca.properties b/themes/src/main/resources-community/theme/base/admin/messages/messages_ca.properties
index 9d89b3da1d8..c7134246edc 100644
--- a/themes/src/main/resources-community/theme/base/admin/messages/messages_ca.properties
+++ b/themes/src/main/resources-community/theme/base/admin/messages/messages_ca.properties
@@ -61,5 +61,5 @@ error-invalid-date=L''atribut {0} és una data invàlida.
error-user-attribute-read-only=L''atribut {0} és només de lectura.
error-username-invalid-character={0} conté un caràcter no vàlid.
error-person-name-invalid-character={0} conté un caràcter no vàlid.
-invalidPasswordNotContainsUsernameMessage=La contrasenya no és vàlida: no pot contenir el nom d'usuari.
+invalidPasswordNotContainsUsernameMessage=La contrasenya no és vàlida: no pot contenir el nom d''usuari.
error-invalid-multivalued-size=L''atribut {0} ha de tenir almenys {1} i com a molt {2} valor(s).
diff --git a/themes/src/main/resources-community/theme/base/admin/messages/messages_it.properties b/themes/src/main/resources-community/theme/base/admin/messages/messages_it.properties
index 0e985394747..450ad6a96af 100644
--- a/themes/src/main/resources-community/theme/base/admin/messages/messages_it.properties
+++ b/themes/src/main/resources-community/theme/base/admin/messages/messages_it.properties
@@ -11,17 +11,17 @@ ldapErrorEditModeMandatory=La modalità di modifica è obbligatoria
ldapErrorInvalidCustomFilter=Il filtro LDAP configurato non inizia con "(" o non finisce con ")".
ldapErrorConnectionTimeoutNotNumber=Il timeout della connessione deve essere un numero
ldapErrorReadTimeoutNotNumber=Il timeout della lettura deve essere un numero
-ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=Non è possibile preservare l'ereditarietà del gruppo e contemporaneamente utilizzare l'appartenenza UID.
+ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=Non è possibile preservare l''ereditarietà del gruppo e contemporaneamente utilizzare l''appartenenza UID.
ldapErrorCantWriteOnlyForReadOnlyLdap=Non è possibile impostare la sola scrittura quando la modalità del provider LDAP non è WRITABLE
ldapErrorCantWriteOnlyAndReadOnly=Non è possibile impostare contemporaneamente sola lettura e sola scrittura
ldapErrorCantEnableStartTlsAndConnectionPooling=Non è possibile abilitare sia StartTLS che il pooling delle connessioni.
-ldapErrorCantEnableUnsyncedAndImportOff=Non è possibile disattivare l'importazione degli utenti quando la modalità del provider LDAP è UNSYNCED
-clientRootURLIllegalSchemeError=L'URL di root usa un protocollo vietato
+ldapErrorCantEnableUnsyncedAndImportOff=Non è possibile disattivare l''importazione degli utenti quando la modalità del provider LDAP è UNSYNCED
+clientRootURLIllegalSchemeError=L''URL di root usa un protocollo vietato
clientRedirectURIsIllegalSchemeError=Un URI di redirect usa un protocollo vietato
-clientBaseURLInvalid=L'URL di base non è valido
-clientRootURLInvalid=L'URL di root non è valido
+clientBaseURLInvalid=L''URL di base non è valido
+clientRootURLInvalid=L''URL di root non è valido
clientRedirectURIsInvalid=Un URI di redirect non è valido
-backchannelLogoutUrlIsInvalid=L'URL di disconnessione non è valido
+backchannelLogoutUrlIsInvalid=L''URL di disconnessione non è valido
pairwiseMalformedClientRedirectURI=Il client contiene un URI di redirect non valido.
pairwiseClientRedirectURIsMissingHost=Gli URI di redirect del client devono contenere un host valido.
pairwiseClientRedirectURIsMultipleHosts=Senza un Sector Identifier URI, gli URI di reindirizzamento del client non devono contenere più host.
@@ -38,19 +38,19 @@ error-username-invalid-character={0} contiene caratteri non validi.
error-person-name-invalid-character={0} contiene caratteri non validi.
error-invalid-multivalued-size=Il campo {0} deve avere almeno {1} e al massimo {2} {2,choice,0#valori|1#valore|1Verifiqueu el vostre correu electrònic introdu
orgInviteBodyPersonalized=Hola, {5} {6}.\n\nHeu estat convidat a unir-vos a l''organització «{3}». Feu clic a l''enllaç següent per a unir-vos-hi.\n\n{0}\n\nAquest enllaç caducarà el {4}.\n\nSi no us voleu unir a l''organització, podeu ignorar aquest missatge.
-orgInviteBodyHtml=Heu estat convidat a unir-vos a l'organització «{3}». Feu clic a l'enllaç següent per a unir-vos-hi.
Enllaç per a unir-se a l'organització
Aquest enllaç caducarà el {4}.
Si no us voleu unir a l'organització, podeu ignorar aquest missatge.
+orgInviteBodyHtml=Heu estat convidat a unir-vos a l''organització «{3}». Feu clic a l''enllaç següent per a unir-vos-hi.
Enllaç per a unir-se a l''organització
Aquest enllaç caducarà el {4}.
Si no us voleu unir a l''organització, podeu ignorar aquest missatge.
orgInviteBody=Heu estat convidat a unir-vos a l''organització «{3}». Feu clic a l''enllaç següent per a unir-vos-hi.\n\n{0}\n\nAquest enllaç caducarà el {4}.\n\nSi no us voleu unir a l''organització, podeu ignorar aquest missatge.
orgInviteBodyPersonalizedHtml=Hola, {5} {6}
Heu estat convidat a unir-vos a l''organització «{3}». Feu clic a l''enllaç següent per a unir-vos-hi.
Enllaç per a unir-se a l''organització
Aquest enllaç caducarà el {4}.
Si no us voleu unir a l''organització, podeu ignorar aquest missatge.
orgInviteSubject=Invitació per a unir-vos a l''organització {0}
eventUpdateCredentialSubject=Actualització de la credencial
eventRemoveCredentialSubject=Supressió de la credencial
eventUserDisabledByTemporaryLockoutSubject=L''usuari és inhabilitat per un bloqueig temporal
-eventUserDisabledByPermanentLockoutSubject=L'usuari és inhabilitat per un bloqueig permanent
+eventUserDisabledByPermanentLockoutSubject=L''usuari és inhabilitat per un bloqueig permanent
eventUserDisabledByTemporaryLockoutBody=El vostre usuari ha estat inhabilitat temporalment per múltiples atempts fallits en {0}. Contacteu amb un administrador si ho necessiteu.
eventUpdateCredentialBody=S''han canviat les vostres credencials {0} el {1} des de {2}. Si no en sabeu res, contacteu amb l''administrador.
eventUserDisabledByTemporaryLockoutHtml=El vostre usuari ha estat inhabilitat temporalment per múltiples intents fallits en {0}. Contacteu amb un administrador si ho necessiteu.
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_ca.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_ca.properties
index ea957f3b76d..440a0587025 100644
--- a/themes/src/main/resources-community/theme/base/login/messages/messages_ca.properties
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_ca.properties
@@ -103,13 +103,13 @@ birthday=Natalici
zoneinfo=Fus horari
gssDelegationCredential=Credencial de delegació GSS
logoutOtherSessions=Surt d''altres dispositius
-profileScopeConsentText=Perfil d'usuari
+profileScopeConsentText=Perfil d''usuari
emailScopeConsentText=Adreça de correu electrònic
addressScopeConsentText=Adreça
phoneScopeConsentText=Número de telèfon
offlineAccessScopeConsentText=Accés fora de línia
samlRoleListScopeConsentText=Els meus rols
-rolesScopeConsentText=Rols d'usuari
+rolesScopeConsentText=Rols d''usuari
restartLoginTooltip=Torna a iniciar l''entrada
loginTotpIntro=Heu de configurar un generador de contrasenyes d''un sol ús per a accedir a aquest compte
loginTotpStep1=Instal·leu una de les aplicacions següents al vostre mòbil:
@@ -454,21 +454,21 @@ authenticateStrong=Es requereix autenticació forta per a continuar
deleteCredentialMessage=Voleu suprimir {0}?
showPassword=Mostra la contrasenya
organizationScopeConsentText=Organització
-confirmOverrideIdpContinue=Sí, sobreescriu l'enllaç amb el compte actual
+confirmOverrideIdpContinue=Sí, sobreescriu l''enllaç amb el compte actual
passkey-login-title=Entrada amb Passkey
passkey-available-authenticators=Passkeys disponibles
-passkey-unsupported-browser-text=Aquest navegador no implementa Passkey. Proveu-ho amb un altre, o contacteu amb l'administrador.
+passkey-unsupported-browser-text=Aquest navegador no implementa Passkey. Proveu-ho amb un altre, o contacteu amb l''administrador.
passkey-doAuthenticate=Entra amb Passkey
passkey-createdAt-label=Creada
passkey-autofill-select=Seleccioneu la vostra passkey
-organization.confirm-membership.title=Esteu a punt d'unir-vos a l'organització ${kc.org.name}
+organization.confirm-membership.title=Esteu a punt d''unir-vos a l''organització ${kc.org.name}
organization.member.register.title=Creeu un compte per a unir-vos a l''organització ${kc.org.name}
organization.select=Seleccioneu una organització per a continuar:
deleteCredentialTitle=Suprimeix {0}
-invalidPasswordNotContainsUsernameMessage=La contrasenya no és vàlida: no pot contenir el nom d'usuari.
-identityProviderMissingCodeOrErrorMessage=Manca el paràmetre o codi d'error a la resposta del proveïdor d'identitat.
+invalidPasswordNotContainsUsernameMessage=La contrasenya no és vàlida: no pot contenir el nom d''usuari.
+identityProviderMissingCodeOrErrorMessage=Manca el paràmetre o codi d''error a la resposta del proveïdor d''identitat.
hidePassword=Amaga la contrasenya
-identityProviderLogoutFailure=Error de sortida de l'IdP SAML
+identityProviderLogoutFailure=Error de sortida de l''IdP SAML
emailVerifiedAlreadyMessage=La vostra adreça de correu electrònic ja està verificada.
requiredAction.webauthn-register=Registre de WebAuthn
webauthn-registration-init-label-prompt=Inseriu l''etiqueta de la vostra passkey registrada
@@ -478,5 +478,5 @@ auth-x509-client-username-form-display-name=Certificat X509
webauthn-registration-init-label=Passkey (Etiqueta per defecte)
auth-x509-client-username-form-help-text=Entra amb un certificat de client X509.
error-invalid-multivalued-size=L''atribut {0} ha de tenir almenys {1} i com a molt {2} valor(s).
-confirmOverrideIdpTitle=L'enllaç de l'agent ja existeix
-notMemberOfOrganization=L'usuari no és membre de l'organització {0}
+confirmOverrideIdpTitle=L''enllaç de l''agent ja existeix
+notMemberOfOrganization=L''usuari no és membre de l''organització {0}
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_es.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_es.properties
index 6903216e889..d019a0bbea7 100644
--- a/themes/src/main/resources-community/theme/base/login/messages/messages_es.properties
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_es.properties
@@ -352,7 +352,7 @@ invalidPasswordGenericMessage=Contraseña no válida: la nueva contraseña no co
successLogout=Está desconectado
standardFlowDisabledMessage=El cliente no puede iniciar el inicio de sesión del navegador con el tipo de respuesta dado. El flujo estándar está deshabilitado para el cliente.
implicitFlowDisabledMessage=El cliente no puede iniciar el inicio de sesión del navegador con el tipo de respuesta dado. El flujo implícito está deshabilitado para el cliente.
-cookieNotFoundMessage=Cookie de reinicio de inicio de sesión no encontrado. Puede que haya expirado, que haya sido eliminado o que las cookies estén deshabilitadas en tu navegador. Si las cookies están deshabilitadas, habilítalas. Haz clic en 'Volver a la aplicación' para iniciar sesión nuevamente.
+cookieNotFoundMessage=Cookie de reinicio de inicio de sesión no encontrado. Puede que haya expirado, que haya sido eliminado o que las cookies estén deshabilitadas en tu navegador. Si las cookies están deshabilitadas, habilítalas. Haz clic en ''Volver a la aplicación'' para iniciar sesión nuevamente.
insufficientLevelOfAuthentication=El nivel de autenticación solicitado no se ha cumplido.
identityProviderMissingCodeOrErrorMessage=Código faltante o parámetro de error en respuesta del proveedor de identidad.
identityProviderInvalidSignatureMessage=Firma no válida en respuesta del proveedor de identidad.
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_ka.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_ka.properties
index aab085f66a5..e36fe0535c6 100644
--- a/themes/src/main/resources-community/theme/base/login/messages/messages_ka.properties
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_ka.properties
@@ -185,7 +185,7 @@ identity-provider-login-label=ან შედით მეთოდით
idp-username-password-form-help-text=მიაბით თქვენი ანგარიში სისტემაში შესვლით.
frontchannel-logout.message=მიმდინარეობს თქვენი გასვლა შემდეგი აპებიდან
logoutConfirmTitle=მიმდინარეობს გასვლა
-finalDeletionConfirmation=თუ თქვენს ანგარიშს წაშლით, მას ვეღარ აღადგენთ. ანგარიშის შესანარჩუნებლად დააწკაპუნეთ ღილაკზე 'გაუქმება'.
+finalDeletionConfirmation=თუ თქვენს ანგარიშს წაშლით, მას ვეღარ აღადგენთ. ანგარიშის შესანარჩუნებლად დააწკაპუნეთ ღილაკზე ''გაუქმება''.
deleteAccountConfirm=ანგარიშის ინფორმაციის წაშლა
loggingOutImmediately=დაუყოვნებლივ გაგდებას
userDeletedSuccessfully=მომხმარებელი წარმატებით წაიშალა
@@ -298,7 +298,7 @@ loginChooseAuthenticator=აირჩიეთ შესვლის მეთ
oauthGrantRequest=ანიჭებთ ამ წვდომის უფლებებს?
inResource=სად
oauth2DeviceVerificationTitle=მოწყობილობის შესვლა
-verifyOAuth2DeviceUserCode=შეიყვანეთ კოდი, რომელიც თქვენმა მოწყობილობამ მოგაწოდათ და დააწკაპუნეთ ღილაკზე 'გადაცემა'
+verifyOAuth2DeviceUserCode=შეიყვანეთ კოდი, რომელიც თქვენმა მოწყობილობამ მოგაწოდათ და დააწკაპუნეთ ღილაკზე ''გადაცემა''
oauth2DeviceInvalidUserCodeMessage=არასწორი კოდი. თავიდან სცადეთ.
oauth2DeviceVerificationCompleteHeader=მოწყობილობის შესვლა წარმატებულია
emailVerifyInstruction1=ელფოსტა ინსტრუქციებით, რომ გადავამოწმოთ თქვენი ელფოსტის მისამართი, გაიგზავნა მისამართზე {0}.
@@ -403,7 +403,7 @@ couldNotSendAuthenticationRequestMessage=ვერ გავაგზავნ
invalidAccessCodeMessage=არასწორი წვდომის კოდი.
sessionNotActiveMessage=სესია აქტიური არაა.
invalidCodeMessage=აღმოჩენილია შეცდომა. შედით თავიდან თქვენი აპლიკაციით.
-cookieNotFoundMessage=გადატვირთვის შესვლის ქუქი აღმოჩენილი არაა. შეიძლება, მისი ვადა ამოიწურა. ასევე, შეიძლება, ის წაშალეს, ან ბრაუზერში ქუქიები გათიშულია. თუ ქუქიები გათიშულია, ჩართეთ ისინი. დააწკაპუნეთ 'აპლიკაციაზე დაბრუნებაზე', რომ თავიდან შეხვიდეთ.
+cookieNotFoundMessage=გადატვირთვის შესვლის ქუქი აღმოჩენილი არაა. შეიძლება, მისი ვადა ამოიწურა. ასევე, შეიძლება, ის წაშალეს, ან ბრაუზერში ქუქიები გათიშულია. თუ ქუქიები გათიშულია, ჩართეთ ისინი. დააწკაპუნეთ ''აპლიკაციაზე დაბრუნებაზე'', რომ თავიდან შეხვიდეთ.
insufficientLevelOfAuthentication=ავთენტიკაციის მოთხოვნილი დონე არ დაკმაყოფილებულა.
identityProviderUnexpectedErrorMessage=მოულოდნელი შეცდომა იდენტიფიკატორის მომწოდებლით ავთენტიკაციისას
identityProviderMissingStateMessage=იდენტიფიკატორის მომწოდებლის პასუხში მდგომარეობის პარამეტრი მითითებული არაა.
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties
index 09177d508da..c798214cd05 100644
--- a/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_nl.properties
@@ -20,7 +20,7 @@ errorDeletingAccount=Onverwachte fout bij het verwijderen van account
deletingAccountForbidden=U heeft onvoldoende rechten om dit account te verwijderen, neem contact op met beheer.
kerberosNotConfigured=Kerberos is niet geconfigureerd
kerberosNotConfiguredTitle=Kerberos is niet geconfigureerd
-bypassKerberosDetail=U bent niet ingelogd via Kerberos of uw browser kan niet met Kerberos inloggen. Klik op 'doorgaan' om via een andere manier in te loggen
+bypassKerberosDetail=U bent niet ingelogd via Kerberos of uw browser kan niet met Kerberos inloggen. Klik op ''doorgaan'' om via een andere manier in te loggen
kerberosNotSetUp=Kerberos is onjuist geconfigureerd. U kunt niet inloggen.
registerTitle=Registreer
loginAccountTitle=Inloggen met uw account
@@ -89,7 +89,7 @@ rolesScopeConsentText=Gebruikersrollen
loginTotpIntro=U bent verplicht om tweefactor-authenticatie in te stellen om dit account te kunnen gebruiken
loginTotpStep1=Installeer een van de volgende applicaties op uw mobile telefoon:
loginTotpStep2=Open de applicatie en scan de barcode:
-loginTotpStep3=Voer de eenmalige code die door de applicatie is aangeleverd in en klik op 'Verzenden' om de setup te voltooien.
+loginTotpStep3=Voer de eenmalige code die door de applicatie is aangeleverd in en klik op ''Verzenden'' om de setup te voltooien.
loginTotpManualStep2=Open de applicatie en voer de sleutel in:
loginTotpManualStep3=Gebruik de volgende configuratiewaarden (als de applicatie dit ondersteund):
loginTotpUnableToScan=Lukt het scannen niet?
diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_ru.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_ru.properties
index bd9ca05eb21..49679c4caf7 100644
--- a/themes/src/main/resources-community/theme/base/login/messages/messages_ru.properties
+++ b/themes/src/main/resources-community/theme/base/login/messages/messages_ru.properties
@@ -13,7 +13,7 @@ doClickHere=Нажмите сюда
doImpersonate=Имперсонализироваться
kerberosNotConfigured=Kerberos не сконфигурирован
kerberosNotConfiguredTitle=Kerberos не сконфигурирован
-bypassKerberosDetail=Либо вы не вошли в систему с помощью Kerberos, либо ваш браузер не настроен для входа в систему Kerberos. Пожалуйста, нажмите кнопку 'Продолжить' для входа в с помощью других средств
+bypassKerberosDetail=Либо вы не вошли в систему с помощью Kerberos, либо ваш браузер не настроен для входа в систему Kerberos. Пожалуйста, нажмите кнопку ''Продолжить'' для входа в с помощью других средств
kerberosNotSetUp=Kerberos не настроен. Вы не можете войти.
registerWithTitle=Зарегистрироваться с {0}
registerWithTitleHtml={0}
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_en.properties b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
index bd4f3e66f75..357cfbbf925 100755
--- a/themes/src/main/resources/theme/base/account/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
@@ -267,7 +267,7 @@ permissionRequestion=Permission Requestion
permission=Permission
shares=share(s)
notBeingShared=This resource is not being shared.
-notHaveAnyResource=You don't have any resources
+notHaveAnyResource=You don’t have any resources
noResourcesSharedWithYou=There are no resources shared with you
havePermissionRequestsWaitingForApproval=You have {0} permission request(s) waiting for approval.
clickHereForDetails=Click here for details.
diff --git a/themes/src/main/resources/theme/base/email/messages/messages_en.properties b/themes/src/main/resources/theme/base/email/messages/messages_en.properties
index fcc134076ea..69ff11a545c 100755
--- a/themes/src/main/resources/theme/base/email/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/email/messages/messages_en.properties
@@ -2,10 +2,10 @@ emailVerificationSubject=Verify email
emailVerificationBody=Someone has created a {2} account with this email address. If this was you, click the link below to verify your email address\n\n{0}\n\nThis link will expire within {3}.\n\nIf you didn''t create this account, just ignore this message.
emailVerificationBodyHtml=Someone has created a {2} account with this email address. If this was you, click the link below to verify your email address
Link to e-mail address verification
This link will expire within {3}.
If you didn''t create this account, just ignore this message.
orgInviteSubject=Invitation to join the {0} organization
-orgInviteBody=You were invited to join the "{3}" organization. Click the link below to join.\n\n{0}\n\nThis link will expire within {4}.\n\nIf you don't want to join the organization, just ignore this message.
-orgInviteBodyHtml=You were invited to join the {3} organization. Click the link below to join.
Link to join the organization
This link will expire within {4}.
If you don't want to join the organization, just ignore this message.
-orgInviteBodyPersonalized=Hi, "{5}" "{6}".\n\n You were invited to join the "{3}" organization. Click the link below to join.\n\n{0}\n\nThis link will expire within {4}.\n\nIf you don't want to join the organization, just ignore this message.
-orgInviteBodyPersonalizedHtml=Hi, {5} {6}.
You were invited to join the {3} organization. Click the link below to join.
Link to join the organization
This link will expire within {4}.
If you don't want to join the organization, just ignore this message.
+orgInviteBody=You were invited to join the "{3}" organization. Click the link below to join.\n\n{0}\n\nThis link will expire within {4}.\n\nIf you don''t want to join the organization, just ignore this message.
+orgInviteBodyHtml=You were invited to join the {3} organization. Click the link below to join.
Link to join the organization
This link will expire within {4}.
If you don''t want to join the organization, just ignore this message.
+orgInviteBodyPersonalized=Hi, "{5}" "{6}".\n\n You were invited to join the "{3}" organization. Click the link below to join.\n\n{0}\n\nThis link will expire within {4}.\n\nIf you don''t want to join the organization, just ignore this message.
+orgInviteBodyPersonalizedHtml=Hi, {5} {6}.
You were invited to join the {3} organization. Click the link below to join.
Link to join the organization
This link will expire within {4}.
If you don''t want to join the organization, just ignore this message.
emailUpdateConfirmationSubject=Verify new email
emailUpdateConfirmationBody=To update your {2} account with email address {1}, click the link below\n\n{0}\n\nThis link will expire within {3}.\n\nIf you don''t want to proceed with this modification, just ignore this message.
emailUpdateConfirmationBodyHtml=To update your {2} account with email address {1}, click the link below
{0}
This link will expire within {3}.
If you don''t want to proceed with this modification, just ignore this message.
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_en.properties b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
index e1b68762073..4a934dbd3a8 100644
--- a/themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -176,7 +176,7 @@ emailLinkIdpTitle=Link {0}
emailLinkIdp1=An email with instructions to link {0} account {1} with your {2} account has been sent to you.
emailLinkIdp2=Haven''t received a verification code in your email?
emailLinkIdp3=to re-send the email.
-emailLinkIdp4=If you already verified the email in different browser
+emailLinkIdp4=If you already verified the email in a different browser
emailLinkIdp5=to continue.
backToLogin=« Back to Login
@@ -453,7 +453,7 @@ auth-recovery-code-prompt=Recovery code #{0}
auth-recovery-code-header=Login with a recovery authentication code
recovery-codes-error-invalid=Invalid recovery authentication code
recovery-code-config-header=Recovery Authentication Codes
-recovery-code-config-warning-title=These recovery codes won't appear again after leaving this page
+recovery-code-config-warning-title=These recovery codes won''t appear again after leaving this page
recovery-code-config-warning-message=Make sure to print, download, or copy them to a password manager and keep them save. Canceling this setup will remove these recovery codes from your account.
recovery-codes-print=Print
recovery-codes-download=Download