From 7f63901067af0bcb154e0417b4fa1df1ca15161b Mon Sep 17 00:00:00 2001 From: GuillM Date: Fri, 29 Dec 2023 20:17:20 +0100 Subject: [PATCH 1/9] add french translations, extend translation implementation, tweak language config --- public/locales/en/translation.json | 10 +- public/locales/fr/translation.json | 285 ++++++++++++++++++ src/i18n.ts | 19 +- .../organizations/components/domain-stat.tsx | 4 +- .../organizations/components/members-stat.tsx | 4 +- src/pages/organizations/detail.tsx | 12 +- src/pages/organizations/domains/add.tsx | 12 +- src/pages/organizations/index.tsx | 21 +- .../components/internationalization.tsx | 15 +- src/pages/profile/components/profile.tsx | 4 +- 10 files changed, 357 insertions(+), 29 deletions(-) create mode 100644 public/locales/fr/translation.json diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 59cb85a..c5428f1 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -272,5 +272,13 @@ "welcomeMessage": "Welcome to keycloak account management", "writeDeleteToConfirm": "Write delete to confirm", "youAreTheSameUserAsThisUser": "This is your account! This is you!", - "youLackTheManageRolesRole": "You lack the manage roles role" + "youLackTheManageRolesRole": "You lack the manage roles role", + "searchOrganizations": "Search Organizations", + "newDomainPlaceholder": "www.your-domain.com", + "error-domain-invalid": "Domain is not valid", + "error-domain-already-present": "${domain} is already present for this org.", + "pending": "pending", + "org-details-stat-sso-active": "active SSO connections", + "view-roles": "view roles", + "manage-roles": "manage roles" } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json new file mode 100644 index 0000000..aeb88f1 --- /dev/null +++ b/public/locales/fr/translation.json @@ -0,0 +1,285 @@ +{ + "accept": "Accepter", + "accessGrantedOn": "Accès accordé le", + "accountSecurity": "Sécurité du compte", + "accountUpdatedError": "Impossible de mettre à jour le compte en raison d'erreurs de validation", + "accountUpdatedMessage": "Votre compte a été mis à jour.", + "add": "Ajouter", + "addANewDomainToThisOrganization": "Ajouter un nouveau domaine à cette organisation", + "addAnSsoProvider": "Ajouter un fournisseur SSO", + "addDomain": "Ajouter un domaine", + "addNewDomain": "Ajouter un nouveau domaine", + "admin": "Admin", + "all": "Tout", + "allApplication": "Toutes les applications", + "allManage": "Tout gérer", + "allView": "Tout voir", + "anyChangesYouMakeWillHaveImmediateEffect": "Tout changement que vous effectuez aura un effet immédiat", + "application": "Application", + "applicationDetails": "Détails de l'application", + "applications": "Applications", + "applicationsIntroMessage": "Suivez et gérez les permissions de votre application pour accéder à votre compte", + "applicationType": "Type d'application", + "authenticatorApplication": "Application d'authentification", + "avatar": "Avatar", + "backToOrg": "Retour à l'organisation", + "backToSettings": "Retour aux paramètres", + "basic-authentication": "Authentification basique", + "basicAuthentication": "Authentification basique", + "cancel": "Annuler", + "choose": "Choisir...", + "client": "Client", + "clientNotFoundMessage": "*Client non trouvé.", + "client_account": "*Compte", + "client_account-console": "*Console du compte", + "client_admin-cli": "*CLI d'administration", + "client_broker": "*Broker", + "client_realm-management": "*Gestion du domaine", + "client_security-admin-console": "*Console d'administration", + "clients": "Clients", + "close": "Fermer", + "configureWaysToSignIn": "Configurer les méthodes de connexion", + "confirm": "Confirmer", + "confirmProfileDelete": "Confirmer la suppression du profil", + "copied": "Copié", + "copy": "Copier", + "createATxtRecordInYourDnsConfigurationForTheFollowingHostname": "Créez un enregistrement txt dans votre configuration DNS pour le nom d'hôte suivant", + "created": "Créé", + "credentialCreatedAt": "<0>Créé {{date}}.", + "credentialsRemovingError": "Erreur lors de la suppression de {{0}}. Veuillez réessayer.", + "credentialsSuccessfullyRemoved": "{{0}} supprimé", + "currentRegisteredDomains": "Domaines actuellement enregistrés", + "currentSession": "Session actuelle", + "dark": "Sombre", + "deleteYourProfile": "Supprimer votre compte", + "description": "Description", + "device-activity": "Activité de l'appareil", + "deviceActivity": "Activité de l'appareil", + "directMembership": "Membre direct", + "displayName": "Nom affiché", + "doCancel": "Annuler", + "doDeny": "Refuser", + "domainName": "Nom de domaine", + "domains": "Domaines", + "done": "Fait", + "doSave": "Sauvegarder", + "doSignOut": "Se déconnecter", + "edit": "Modifier", + "editRoles": "Modifier les rôles", + "editTheResource": "Partager la ressource - {{0}}", + "email": "Email", + "enterAVerificationCodeFromAuthenticatorApplication": "Entrez un code de vérification de l'application d'authentification", + "error-empty": "Veuillez spécifier la valeur de '{{0}}'.", + "error-invalid-blank": "Veuillez spécifier la valeur de '{{0}}'.", + "error-invalid-date": "'{{0}}' est une date invalide.", + "error-invalid-email": "Adresse e-mail invalide.", + "error-invalid-length-too-long": "'{{0}}' doit avoir une longueur maximale de {{2}}.", + "error-invalid-length-too-short": "'{{0}}' doit avoir une longueur minimale de {{1}}.", + "error-invalid-length": "'{{0}}' doit avoir une longueur entre {{1}} et {{2}}.", + "error-invalid-number": "'{{0}}' est un nombre invalide", + "error-invalid-uri-fragment": "'{{0}}' est un fragment d'URL invalide.", + "error-invalid-uri-scheme": "'{{0}}' a un schéma d'URL invalide.", + "error-invalid-uri": "'{{0}}' est une URL invalide.", + "error-invalid-value": "'{{0}}' a une valeur invalide.", + "error-number-out-of-range-too-big": "'{{0}}' doit avoir une valeur maximale de {{2}}.", + "error-number-out-of-range-too-small": "'{{0}}' doit avoir une valeur minimale de {{1}}.", + "error-number-out-of-range": "'{{0}}' mdoit être un nombre entre {{1}} et {{2}}.", + "error-pattern-no-match": "'{{0}}' ne correspond pas au format requis.", + "error-person-name-invalid-character": "'{{0}}' contient un caractère invalide.", + "error-user-attribute-required": "Veuillez spécifier '{{0}}'.", + "error-username-invalid-character": "'{{0}}' contains invalid character.", + "errorRemovedMessage": "Impossible de supprimer {{userLabel}} en raison de : {{error}}", + "errorSignOutMessage": "Impossible de se déconnecter : {{error}}", + "expires": "Expiration", + "failedToCopy": "Échec de la copie", + "filterByName": "Filtrer par nom...", + "firstName": "Prénom", + "fullName": "{{givenName}} {{familyName}}", + "general": "Général", + "groupDescriptionLabel": "Voir les groupes auxquels vous êtes associé", + "groupLabel": "Groupes", + "groups": "Groupes", + "id": "ID", + "infoMessage": "En cliquant sur Retirer l'accès, vous retirerez les permissions accordées à cette application. Cette application n'utilisera plus vos informations.", + "insufficientPermissionsToViewOrganization": "Permissions insuffisantes pour voir l'organisation", + "internalApp": "Interne", + "inUse": "En cours d'utilisation", + "invitationInstructionsDescription": "Ajoutez un nouveau membre à l'organisation en entrant son mail et en lui attribuant un rôle au sein de l'organisation. Un mail leur sera envoyé avec des instructions pour rejoindre.", + "invitationTitle": "Invitez un nouveau membre à {{0}}", + "inviteNewMembers": "Inviter de nouveaux membres", + "inviteNewMembersOrRemoveMembersFromTheOrganization": "Inviter de nouveaux membres ou retirer des membres de l'organisation", + "ipAddress": "Adresse IP", + "label": "Étiquette", + "lastAccessed": "Dernier accès", + "lastAccessedOn": "Dernièrement accédé", + "lastName": "Nom de famille", + "light": "Clair", + "link": "Lier le compte", + "linkAccount": "Lier le compte", + "linkedAccounts": "Comptes liés", + "linkedAccountsIntroMessage": "Gérer les connexions via des comptes tiers.", + "linkedAccountsTitle": "Comptes liés", + "linkedEmpty": "Aucun fournisseur lié", + "linkedLoginProviders": "Fournisseurs de connexion liés", + "linkError": "Impossible de lier en raison de : {{error}}", + "localeUpdatedSuccessfully": "Localisation mise à jour avec succès", + "localeUpdateFailed": "Erreur lors de la mise à jour de la localisation.", + "localization": "Localisation", + "logo": "Logo", + "logOut": "Se déconnecter", + "manageAccount": "Gérer le compte", + "manageLoginsThroughThirdPartyAccounts": "Gérer les connexions via des comptes tiers", + "manageYourUserProfileInformation": "Gérer vos informations personnelles.", + "members": "Membres", + "myResources": "Mes Ressources", + "name": "Nom", + "noGroups": "Aucun groupe", + "noGroupsText": "Vous n'êtes inscrit dans aucun groupe", + "none": "Aucun", + "notInUse": "Pas en utilisation", + "notSetUp": "{{0}} n'est pas configuré.", + "offlineAccess": "Accès hors ligne", + "options": "Options", + "organization": "Organisation", + "organizations": "Organisations", + "otp-display-name": "Application d'authentification", + "otp-help-text": "Saisissze le code de vérification de l'application d'authentification.", + "password-display-name": "Mot de passe", + "password-help-text": "Connectez-vous en saisissant votre mot de passe.", + "password-less-title": "Connexion avec clé de sécurité", + "password": "Mon mot de passe", + "passwordless": "Sans mot de passe", + "path": "Chemin", + "permanentlyRemoveYourProfileAndAllOfItsContentsThisActionIsNotReversibleSoPleaseContinueWithCaution": "Supprimez définitivement votre compte et tout son contenu, cette action n'est pas réversible, veuillez donc continuer avec prudence.", + "permissionRequest": "Demandes de permission - {{0}}", + "permissionRequests": "Demandes de permission", + "permissions": "Permissions", + "personalInfo": "Informations personnelles", + "personalInfoDescription": "Gérez vos informations", + "personalInformation": "Informations personnelles", + "privacyPolicy": "Politique de confidentialité", + "profile": "Profil", + "provider": "Fournisseur", + "refreshPage": "Rafraîchir la page", + "remove": "Retirer", + "removeButton": "Retirer l'accès", + "removeConsentError": "Impossible de retirer le consentement en raison de: {{error}}", + "removeConsentSuccess": "Consentement retiré avec succès", + "removeCred": "Retirer {{0}}", + "removeCredAriaLabel": "Retirer les informations d'identification", + "removeDomain": "Retirer", + "removeDomainError": "{{0}} n'a pas été retiré de cette organisation. ({{1}})", + "removeDomainQuestion": "Retirer ce domaine de l'organisation ne peut pas être annulé et nécessitera de l'ajouter manuellement à nouveau.", + "removeDomainSuccess": "{{0}} a été retiré avec succès de cette organisation.", + "removeDomainTitle": "Retirer {{0}} de cette organisation.", + "removeModalMessage": "Cela retirera la permission d'accès actuellement accordée pour {{0}}. Vous devrez accorder à nouveau l'accès si vous souhaitez utiliser cette application.", + "removeModalTitle": "Retirer l'accès", + "requestor": "Demandeur", + "required": "Requis", + "reset": "Réinitialiser", + "resourceAlreadyShared": "La ressource est déjà partagée avec cet utilisateur.", + "resourceIntroMessage": "Partagez vos ressources parmi les membres de l'équipe", + "resourceName": "Nom de la ressource", + "resources": "Ressources", + "resourceSharedWith_one": "La ressource est partagée avec <0>{{username}}", + "resourceSharedWith_other": "La ressource est partagée avec <0>{{username}} et <1>{{other}} autres utilisateurs", + "resourceSharedWith_zero": "Cette ressource n'est pas partagée.", + "returnToHomepage": "Retourner à la page d'accueil", + "save": "Sauvegarder", + "searchMembers": "Chercher des membres", + "securityKey": "Clé de sécurité", + "selectLocale": "Sélectionner la langue", + "selectOne": "Sélectionner une option", + "sendInvitation": "Envoyer une invitation", + "settings": "Paramètres", + "setupAssociatedDomainsAndVerifyThemToEnsureFullSecurity": "Configurer les domaines associés et les vérifier pour assurer une sécurité complète", + "setUpAuthenticator": "Configurer l'authentificateur", + "setupDomains": "Configurer les domaines", + "setUpNew": "Configurer {{0}}", + "setUpSecurityKey": "Configurer la clé de sécurité", + "setupSso": "Configurer SSO", + "setupSsoConnectionsAsNecessaryForThisOrganization": "Configurer les connexions SSO selon les besoins pour cette organisation", + "share": "Partager", + "sharedWithMe": "Partagé avec moi", + "shareError": "Impossible de partager la ressource en raison de : {{error}}", + "shareSuccess": "Ressource partagée avec succès.", + "shareTheResource": "Partager la ressource - {{0}}", + "shareUser": "Ajoutez des utilisateurs pour partager votre ressource", + "shareWith": "Partager avec ", + "signedInDevices": "Appareils connectés", + "signedInDevicesExplanation": "Déconnectez-vous de tout appareil inconnu.", + "signedOutSession": "Déconnecté {{0}}/{{1}}", + "signInByEnteringYourPassword": "Connexion avec un mot de passe", + "signingIn": "Connexion", + "signingInDescription": "Configurer les méthodes de connexion.", + "signOut": "Se déconnecter", + "signOutAllDevices": "Déconnecter tous les appareils", + "signOutAllDevicesWarning": "Cette action déconnectera tous les appareils qui se sont connectés à votre compte, y compris l'appareil que vous utilisez actuellement.", + "signOutOfAnyUnfamiliarDevices": "Déconnectez-vous de tout appareil inconnu", + "signOutSession": "Déconnecter la session", + "signOutThisSessionQuestion": "Veuillez confirmer que vous souhaitez vous déconnecter de la session sur l'autre appareil.", + "signOutWarning": "Déconnecter la session ?", + "socialLogin": "Social login", + "somethingWentWrong": "Quelque chose s'est mal passé", + "somethingWentWrongDescription": "Désolé, une erreur inattendue s'est produite.", + "speakToAnAdminInOrderToBeGrantedThisRole": "Parlez à un administrateur pour obtenir ce rôle", + "sso": "SSO", + "started": "Commencé", + "status": "Statut", + "stopUsingCred": "Arrêter d'utiliser {{0}}?", + "successRemovedMessage": "{{userLabel}} a été retiré.", + "system": "Système", + "systemDefined": "Défini par le système", + "termsOfService": "Conditions de service", + "theme": "Thème", + "thirdPartyApp": "Tiers", + "thisActionWillSignOutAllTheDevicesThatHaveSignedInToYourAccountIncludingTheCurrentDeviceYouAreUsing": "Cette action déconnectera tous les appareils qui se sont connectés à votre compte, y compris l'appareil que vous utilisez actuellement.", + "tryAgain": "Réessayer", + "two-factor": "Authentification à deux facteurs", + "twoFactorAuthentication": "Authentification à deux facteurs", + "unknownOperatingSystem": "Système d'exploitation inconnu", + "unknownUser": "Anonyme", + "unLink": "Dissocier le compte", + "unlinkAccount": "Dissocier le compte", + "unlinkedEmpty": "Pas de fournisseurs dissociés", + "unlinkedLoginProviders": "Fournisseurs de connexion dissociés", + "unLinkError": "Impossible de dissocier en raison de : {{error}}", + "unLinkSuccess": "Compte dissocié avec succès", + "unShare": "Ne plus partager l'ensemble", + "unShareError": "Impossible de ne plus partager la ressource en raison de : {{error}}", + "unShareSuccess": "Partage supprimé avec succès.", + "update": "Mettre à jour", + "updateCredAriaLabel": "Mettre à jour les informations d'identification", + "updateError": "Impossible de mettre à jour la ressource en raison de : {{error}}", + "updateLocale": "Modifier", + "updateOrganization": "Mettre à jour l'organisation", + "updateSuccess": "Ressource mise à jour avec succès.", + "user": "Utilisateur", + "username": "Nom d'utilisateur", + "usernamePlaceholder": "Nom d'utilisateur ou mail.", + "usernameEmailSame": "Le nom d'utilisateur est identique au mail.", + "useTheFollowingDetailsToVerifyYourDomain": "Utilisez les détails suivants pour vérifier votre domaine", + "useThisCodeForTheValueOfTheTxtRecord": "Utilisez ce code pour la valeur de l'enregistrement TXT", + "useYourSecurityKeyForPasswordlessSignIn": "Utilisez votre clé de sécurité pour une connexion sans mot de passe", + "useYourSecurityKeyToSignIn": "UUtilisez votre clé de sécurité pour vous connecter", + "validated": "Validé", + "verificationPending": "Vérification en attente", + "verified": "Vérifié", + "verify": "Vérifier", + "verifyDomain": "Vérifier le domaine", + "viewLinkedDomainsAndVerifyDnsEntries": "Voir les domaines liés et vérifier les entrées DNS", + "viewOrganizationInformationChangeDisplayName": "Voir les informations de l'organisation", + "welcomeMessage": "Bienvenue dans la gestion de compte keycloak", + "writeDeleteToConfirm": "Écrire supprimer pour confirmer", + "youAreTheSameUserAsThisUser": "C'est votre compte ! C'est vous !", + "youLackTheManageRolesRole": "Vous manquez le rôle de gestion des rôles", + "searchOrganizations": "Chercher des Organisations", + "newDomainPlaceholder": "www.mon-domaine.com", + "error-domain-invalid": "Domaine invalide.", + "error-domain-already-present": "${domain} existe déjà pour cette organisation.", + "success-domain-added": "${domain} has been added to organization. Please verify domain.", + "pending": "En attente", + "org-details-stat-sso-active": "Connexion SSO actives", + "view-roles": "rôle de lecture", + "manage-roles": "rôle d'écriture" +} diff --git a/src/i18n.ts b/src/i18n.ts index 1f8009c..f6ad6f6 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -3,7 +3,8 @@ import HttpBackend from "i18next-http-backend"; import { initReactI18next } from "react-i18next"; import { joinPath } from "services/join-path"; -const DEFAULT_LOCALE = "en"; +const ENGLISH_LOCALE = "en"; +const FRENCH_LOCAL = "fr" const DEFAULT_NAMESPACE = "translation"; i18n @@ -12,7 +13,7 @@ i18n .init({ returnNull: false, defaultNS: DEFAULT_NAMESPACE, - fallbackLng: DEFAULT_LOCALE, + fallbackLng: [ENGLISH_LOCALE, FRENCH_LOCAL], ns: [DEFAULT_NAMESPACE], interpolation: { escapeValue: false, @@ -22,4 +23,18 @@ i18n }, }); +// use localStorage to avoid losing language on page reload +if(localStorage.getItem("lng") != undefined) { + i18n.changeLanguage(localStorage.getItem("lng")!); +} else { + localStorage.setItem('lng', ENGLISH_LOCALE) +} + +export const setLanguage = (lang: string) => { + i18n.changeLanguage(lang).then(() => { + i18n.options.lng = lang; + }) + localStorage.setItem('lng', lang); +} + export default i18n; diff --git a/src/pages/organizations/components/domain-stat.tsx b/src/pages/organizations/components/domain-stat.tsx index 90e5e72..0994391 100644 --- a/src/pages/organizations/components/domain-stat.tsx +++ b/src/pages/organizations/components/domain-stat.tsx @@ -3,6 +3,7 @@ import { OrganizationRepresentation, useGetOrganizationDomainsQuery, } from "store/apis/orgs"; +import {useTranslation} from "react-i18next"; type Props = { org: OrganizationRepresentation; @@ -10,6 +11,7 @@ type Props = { }; const DomainStat: React.FC = ({ org, realm }) => { + const { t } = useTranslation(); const { data: domains = [] } = useGetOrganizationDomainsQuery({ realm, orgId: org.id!, @@ -25,7 +27,7 @@ const DomainStat: React.FC = ({ org, realm }) => { percent={verifiedPercentage} hoverPercentText="Percentage of domains verified" value={org.domains?.length || "0"} - label="domains" + label={t("domains")} /> ); }; diff --git a/src/pages/organizations/components/members-stat.tsx b/src/pages/organizations/components/members-stat.tsx index f9e132e..1cf1311 100644 --- a/src/pages/organizations/components/members-stat.tsx +++ b/src/pages/organizations/components/members-stat.tsx @@ -3,6 +3,7 @@ import { OrganizationRepresentation, useGetOrganizationMembershipsQuery, } from "store/apis/orgs"; +import {useTranslation} from "react-i18next"; type Props = { org: OrganizationRepresentation; @@ -10,6 +11,7 @@ type Props = { }; const MembersStat: React.FC = ({ org, realm }) => { + const { t } = useTranslation(); const { data: members = [] } = useGetOrganizationMembershipsQuery({ realm: realm, orgId: org.id!, @@ -17,7 +19,7 @@ const MembersStat: React.FC = ({ org, realm }) => { const totalMembers = members.length === 0 ? 0 : members.length - 1; - return ; + return ; }; export default MembersStat; diff --git a/src/pages/organizations/detail.tsx b/src/pages/organizations/detail.tsx index 9e995f1..640e7cf 100644 --- a/src/pages/organizations/detail.tsx +++ b/src/pages/organizations/detail.tsx @@ -118,7 +118,7 @@ export default function OrganizationDetail() { collapseOnMobile={true} leftAreaItems={ } rightAreaItems={ @@ -142,8 +142,8 @@ export default function OrganizationDetail() { - - + +
{t("inviteNewMembersOrRemoveMembersFromTheOrganization")} @@ -177,7 +177,7 @@ export default function OrganizationDetail() { @@ -203,8 +203,8 @@ export default function OrganizationDetail() { - - + +
{t("setupAssociatedDomainsAndVerifyThemToEnsureFullSecurity")} diff --git a/src/pages/organizations/domains/add.tsx b/src/pages/organizations/domains/add.tsx index 4a383e5..db9e609 100644 --- a/src/pages/organizations/domains/add.tsx +++ b/src/pages/organizations/domains/add.tsx @@ -57,17 +57,17 @@ const DomainsAdd = () => { if (org.domains?.includes(domain)) { P2Toast({ error: true, - title: `${domain} is already present for this org.`, + title: `${t("error-domain-already-present")}`, }); } else if (!isValidDomain(domain)) { setError( "domain", - { message: "Domain is not valid" }, + { message: `${t("error-domain-invalid")}`}, { shouldFocus: true } ); P2Toast({ error: true, - title: `${domain} is not valid.`, + title: `${t("error-domain-invalid")}`, }); } else { const orgCopy = { ...org }; @@ -87,7 +87,7 @@ const DomainsAdd = () => { reset(); P2Toast({ success: true, - title: `${domain} has been added to organization. Please verify domain.`, + title: `${t("success-domain-added")}`, }); refetchDomains(); return navigate(`/organizations/${orgId}/settings`); @@ -128,7 +128,7 @@ const DomainsAdd = () => { {org.domains && org.domains?.length > 0 && (
- Current registered domains + {t("currentRegisteredDomains")}
{org.domains.map((domain) => ( @@ -156,7 +156,7 @@ const DomainsAdd = () => { error={errors.domain} inputArgs={{ type: "text", - placeholder: "www.your-domain.com", + placeholder: `${t("newDomainPlaceholder")}`, required: true, disabled: !hasManageOrganizationRole, }} diff --git a/src/pages/organizations/index.tsx b/src/pages/organizations/index.tsx index 8947176..79d3d3c 100644 --- a/src/pages/organizations/index.tsx +++ b/src/pages/organizations/index.tsx @@ -15,10 +15,14 @@ import DomainStat from "./components/domain-stat"; import MembersStat from "./components/members-stat"; import useUser from "components/utils/useUser"; import Fuse from "fuse.js"; +import {useTranslation} from "react-i18next"; +import {useGetAccountQuery} from "../../store/apis/profile"; +import {setLanguage} from "../../i18n"; -const { realm } = config.env; +const { realm, supportedLocales } = config.env; export default function Organizations() { + const { t, i18n} = useTranslation(); const { user } = useUser(); const [viewType, setViewType] = useState( ViewLayoutOptions.GRID @@ -33,11 +37,22 @@ export default function Organizations() { { skip: !user?.id } ); + // localization not loaded on login, need to load it from locale attribute + const { data: account, isLoading: isLoadingAccount } = useGetAccountQuery({ + userProfileMetadata: true, + realm, + }); + const hasLocale = (locale: string): boolean => locale in supportedLocales; + const fuse = new Fuse(userOrgs, { keys: ["displayName", "name", "domains"], }); useEffect(() => { + // load language on homepage (after login) + if (account?.attributes?.locale && hasLocale(account?.attributes?.locale[0])) { + setLanguage(account?.attributes?.locale[0]); + } fuse.setCollection(userOrgs); }, [userOrgs]); @@ -49,13 +64,13 @@ export default function Organizations() { return ( <> setSearchString(e.target.value), }} className="w-full md:w-auto" diff --git a/src/pages/profile/components/internationalization.tsx b/src/pages/profile/components/internationalization.tsx index c924948..0ad3b7f 100644 --- a/src/pages/profile/components/internationalization.tsx +++ b/src/pages/profile/components/internationalization.tsx @@ -10,11 +10,12 @@ import { useTranslation } from "react-i18next"; import P2Toast from "components/utils/toast"; import Dropdown from "components/elements/forms/dropdown/hui-dropdown"; import { first } from "lodash"; +import {setLanguage} from "../../../i18n"; const { realm, supportedLocales } = config.env; const Internationalization = () => { - const { t } = useTranslation(); + const { t, i18n } = useTranslation(); const noSelection = { id: "none", name: t("selectLocale"), disabled: true }; const localeOptions = [ @@ -29,6 +30,7 @@ const Internationalization = () => { id: string; name: string; }>(localeOptions[0]); + const { data: account, isLoading: isLoadingAccount } = useGetAccountQuery({ userProfileMetadata: true, realm, @@ -39,13 +41,12 @@ const Internationalization = () => { (l) => l.id === first(account?.attributes?.locale) ); if (hasLocale) { - setSelectedLocale( - localeOptions[ + const locale = localeOptions[ localeOptions.findIndex( - (l) => l.id === first(account?.attributes?.locale) - ) - ] - ); + (l) => l.id === first(account?.attributes?.locale))] + + setSelectedLocale(locale); + setLanguage(locale.id); } }, [account]); diff --git a/src/pages/profile/components/profile.tsx b/src/pages/profile/components/profile.tsx index 8824de6..dd66f52 100644 --- a/src/pages/profile/components/profile.tsx +++ b/src/pages/profile/components/profile.tsx @@ -74,8 +74,8 @@ const ProfileData = () => { <>
From 9f6607fe6c747df1bfdd2b63e7ae09577040772a Mon Sep 17 00:00:00 2001 From: pnzrr Date: Thu, 11 Jan 2024 21:38:02 -0700 Subject: [PATCH 2/9] fix function call syntax --- src/pages/organizations/domains/add.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/pages/organizations/domains/add.tsx b/src/pages/organizations/domains/add.tsx index db9e609..fefd9da 100644 --- a/src/pages/organizations/domains/add.tsx +++ b/src/pages/organizations/domains/add.tsx @@ -35,11 +35,10 @@ const DomainsAdd = () => { orgId: orgId!, realm, }); - const { refetch: refetchDomains } = - useGetOrganizationDomainsQuery({ - realm, - orgId: orgId!, - }); + const { refetch: refetchDomains } = useGetOrganizationDomainsQuery({ + realm, + orgId: orgId!, + }); const hasManageOrganizationRole = hasManageOrganizationRoleCheck(orgId); const [updateOrg] = useUpdateOrganizationMutation(); @@ -57,17 +56,17 @@ const DomainsAdd = () => { if (org.domains?.includes(domain)) { P2Toast({ error: true, - title: `${t("error-domain-already-present")}`, + title: t("error-domain-already-present"), }); } else if (!isValidDomain(domain)) { setError( "domain", - { message: `${t("error-domain-invalid")}`}, + { message: t("error-domain-invalid") }, { shouldFocus: true } ); P2Toast({ error: true, - title: `${t("error-domain-invalid")}`, + title: t("error-domain-invalid"), }); } else { const orgCopy = { ...org }; @@ -87,7 +86,7 @@ const DomainsAdd = () => { reset(); P2Toast({ success: true, - title: `${t("success-domain-added")}`, + title: t("success-domain-added"), }); refetchDomains(); return navigate(`/organizations/${orgId}/settings`); @@ -156,7 +155,7 @@ const DomainsAdd = () => { error={errors.domain} inputArgs={{ type: "text", - placeholder: `${t("newDomainPlaceholder")}`, + placeholder: t("newDomainPlaceholder"), required: true, disabled: !hasManageOrganizationRole, }} From 03e2f053e9381c2add09f8b519c00e209ae0a2c7 Mon Sep 17 00:00:00 2001 From: pnzrr Date: Thu, 11 Jan 2024 22:10:12 -0700 Subject: [PATCH 3/9] formatting cleanup --- src/i18n.ts | 12 ++++++------ src/pages/organizations/detail.tsx | 2 +- src/pages/organizations/index.tsx | 15 +++++++++------ .../profile/components/internationalization.tsx | 11 +++++++---- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/i18n.ts b/src/i18n.ts index f6ad6f6..5d816d1 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -4,7 +4,7 @@ import { initReactI18next } from "react-i18next"; import { joinPath } from "services/join-path"; const ENGLISH_LOCALE = "en"; -const FRENCH_LOCAL = "fr" +const FRENCH_LOCAL = "fr"; const DEFAULT_NAMESPACE = "translation"; i18n @@ -24,17 +24,17 @@ i18n }); // use localStorage to avoid losing language on page reload -if(localStorage.getItem("lng") != undefined) { +if (localStorage.getItem("lng") != undefined) { i18n.changeLanguage(localStorage.getItem("lng")!); } else { - localStorage.setItem('lng', ENGLISH_LOCALE) + localStorage.setItem("lng", ENGLISH_LOCALE); } export const setLanguage = (lang: string) => { i18n.changeLanguage(lang).then(() => { i18n.options.lng = lang; - }) - localStorage.setItem('lng', lang); -} + }); + localStorage.setItem("lng", lang); +}; export default i18n; diff --git a/src/pages/organizations/detail.tsx b/src/pages/organizations/detail.tsx index 640e7cf..314417a 100644 --- a/src/pages/organizations/detail.tsx +++ b/src/pages/organizations/detail.tsx @@ -118,7 +118,7 @@ export default function OrganizationDetail() { collapseOnMobile={true} leftAreaItems={ } rightAreaItems={ diff --git a/src/pages/organizations/index.tsx b/src/pages/organizations/index.tsx index 79d3d3c..74d48e4 100644 --- a/src/pages/organizations/index.tsx +++ b/src/pages/organizations/index.tsx @@ -15,14 +15,14 @@ import DomainStat from "./components/domain-stat"; import MembersStat from "./components/members-stat"; import useUser from "components/utils/useUser"; import Fuse from "fuse.js"; -import {useTranslation} from "react-i18next"; -import {useGetAccountQuery} from "../../store/apis/profile"; -import {setLanguage} from "../../i18n"; +import { useTranslation } from "react-i18next"; +import { useGetAccountQuery } from "../../store/apis/profile"; +import { setLanguage } from "../../i18n"; const { realm, supportedLocales } = config.env; export default function Organizations() { - const { t, i18n} = useTranslation(); + const { t } = useTranslation(); const { user } = useUser(); const [viewType, setViewType] = useState( ViewLayoutOptions.GRID @@ -50,7 +50,10 @@ export default function Organizations() { useEffect(() => { // load language on homepage (after login) - if (account?.attributes?.locale && hasLocale(account?.attributes?.locale[0])) { + if ( + account?.attributes?.locale && + hasLocale(account?.attributes?.locale[0]) + ) { setLanguage(account?.attributes?.locale[0]); } fuse.setCollection(userOrgs); @@ -70,7 +73,7 @@ export default function Organizations() { <> setSearchString(e.target.value), }} className="w-full md:w-auto" diff --git a/src/pages/profile/components/internationalization.tsx b/src/pages/profile/components/internationalization.tsx index 0ad3b7f..c7ba81c 100644 --- a/src/pages/profile/components/internationalization.tsx +++ b/src/pages/profile/components/internationalization.tsx @@ -10,12 +10,12 @@ import { useTranslation } from "react-i18next"; import P2Toast from "components/utils/toast"; import Dropdown from "components/elements/forms/dropdown/hui-dropdown"; import { first } from "lodash"; -import {setLanguage} from "../../../i18n"; +import { setLanguage } from "../../../i18n"; const { realm, supportedLocales } = config.env; const Internationalization = () => { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const noSelection = { id: "none", name: t("selectLocale"), disabled: true }; const localeOptions = [ @@ -41,9 +41,12 @@ const Internationalization = () => { (l) => l.id === first(account?.attributes?.locale) ); if (hasLocale) { - const locale = localeOptions[ + const locale = + localeOptions[ localeOptions.findIndex( - (l) => l.id === first(account?.attributes?.locale))] + (l) => l.id === first(account?.attributes?.locale) + ) + ]; setSelectedLocale(locale); setLanguage(locale.id); From 7b0e7691e4e4b840f6e68f35909242d95d9623c6 Mon Sep 17 00:00:00 2001 From: pnzrr Date: Thu, 11 Jan 2024 22:10:23 -0700 Subject: [PATCH 4/9] adjust regex --- src/pages/organizations/domains/add.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/organizations/domains/add.tsx b/src/pages/organizations/domains/add.tsx index fefd9da..199733c 100644 --- a/src/pages/organizations/domains/add.tsx +++ b/src/pages/organizations/domains/add.tsx @@ -150,7 +150,7 @@ const DomainsAdd = () => { register={register} registerArgs={{ pattern: - /^(?!-)[A-Za-z0-9-]+([\-\.]{1}[a-z0-9]+)*\.[A-Za-z]{2,6}$/, + /^(?!-)(?:[a-zA-Z\d-]{0,62}[a-zA-Z\d]\.)+(?:[a-zA-Z]{2,})$/, }} error={errors.domain} inputArgs={{ From d42019090af2f11a56ee7396a792e51dfec627aa Mon Sep 17 00:00:00 2001 From: pnzrr Date: Thu, 11 Jan 2024 22:25:37 -0700 Subject: [PATCH 5/9] move the initial load into the App level to avoid any issues with specific routes --- src/App.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/App.tsx b/src/App.tsx index 2a8b430..c3f465b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,29 @@ import Layout from "components/layouts/layout"; +import { setLanguage } from "i18n"; import { Outlet } from "react-router-dom"; +import { useGetAccountQuery } from "store/apis/profile"; +import { config } from "config"; +import { useEffect } from "react"; + +const { supportedLocales, realm } = config.env; function App() { + const hasLocale = (locale: string): boolean => locale in supportedLocales; + + const { data: account } = useGetAccountQuery({ + userProfileMetadata: true, + realm, + }); + useEffect(() => { + // load language (after login) + if ( + account?.attributes?.locale && + hasLocale(account?.attributes?.locale[0]) + ) { + setLanguage(account?.attributes?.locale[0]); + } + }, [account]); + return ( From a948cf414e7be9c3d9adcc7bf36ee4db4774227d Mon Sep 17 00:00:00 2001 From: pnzrr Date: Thu, 11 Jan 2024 22:26:05 -0700 Subject: [PATCH 6/9] auto load the intial language from localstorage if there --- src/i18n.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/i18n.ts b/src/i18n.ts index 5d816d1..0eec725 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -7,10 +7,17 @@ const ENGLISH_LOCALE = "en"; const FRENCH_LOCAL = "fr"; const DEFAULT_NAMESPACE = "translation"; +// use localStorage to avoid losing language on page reload +const locale = localStorage.getItem("locale"); +if (!locale) { + localStorage.setItem("locale", ENGLISH_LOCALE); +} + i18n .use(HttpBackend) .use(initReactI18next) .init({ + lng: locale || ENGLISH_LOCALE, returnNull: false, defaultNS: DEFAULT_NAMESPACE, fallbackLng: [ENGLISH_LOCALE, FRENCH_LOCAL], @@ -23,18 +30,11 @@ i18n }, }); -// use localStorage to avoid losing language on page reload -if (localStorage.getItem("lng") != undefined) { - i18n.changeLanguage(localStorage.getItem("lng")!); -} else { - localStorage.setItem("lng", ENGLISH_LOCALE); -} - export const setLanguage = (lang: string) => { i18n.changeLanguage(lang).then(() => { i18n.options.lng = lang; }); - localStorage.setItem("lng", lang); + localStorage.setItem("locale", lang); }; export default i18n; From 12c6c96d3f9f05cb049fc77084fc092b49ae8ed8 Mon Sep 17 00:00:00 2001 From: pnzrr Date: Thu, 11 Jan 2024 22:26:22 -0700 Subject: [PATCH 7/9] this was moved to the App level rather than only the organizations page --- src/pages/organizations/index.tsx | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/pages/organizations/index.tsx b/src/pages/organizations/index.tsx index 74d48e4..a8c55f1 100644 --- a/src/pages/organizations/index.tsx +++ b/src/pages/organizations/index.tsx @@ -16,10 +16,8 @@ import MembersStat from "./components/members-stat"; import useUser from "components/utils/useUser"; import Fuse from "fuse.js"; import { useTranslation } from "react-i18next"; -import { useGetAccountQuery } from "../../store/apis/profile"; -import { setLanguage } from "../../i18n"; -const { realm, supportedLocales } = config.env; +const { realm } = config.env; export default function Organizations() { const { t } = useTranslation(); @@ -37,25 +35,11 @@ export default function Organizations() { { skip: !user?.id } ); - // localization not loaded on login, need to load it from locale attribute - const { data: account, isLoading: isLoadingAccount } = useGetAccountQuery({ - userProfileMetadata: true, - realm, - }); - const hasLocale = (locale: string): boolean => locale in supportedLocales; - const fuse = new Fuse(userOrgs, { keys: ["displayName", "name", "domains"], }); useEffect(() => { - // load language on homepage (after login) - if ( - account?.attributes?.locale && - hasLocale(account?.attributes?.locale[0]) - ) { - setLanguage(account?.attributes?.locale[0]); - } fuse.setCollection(userOrgs); }, [userOrgs]); From 600a9a08af703dd27d09316d61e15b595d44d596 Mon Sep 17 00:00:00 2001 From: MGLL Date: Fri, 12 Jan 2024 14:38:21 +0100 Subject: [PATCH 8/9] add missing translations for toasts --- public/locales/en/translation.json | 33 ++++++- public/locales/fr/translation.json | 99 ++++++++++++------- src/pages/invitation/new.tsx | 16 +-- src/pages/member/roles.tsx | 28 +++--- src/pages/organizations/domains/add.tsx | 4 +- src/pages/organizations/domains/verify.tsx | 2 +- src/pages/profile-delete/index.tsx | 8 +- .../components/internationalization.tsx | 2 +- src/pages/profile/components/profile.tsx | 10 +- 9 files changed, 124 insertions(+), 78 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index c5428f1..233fade 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -104,8 +104,6 @@ "insufficientPermissionsToViewOrganization": "Insufficient permissions to view organization", "internalApp": "Internal", "inUse": "In use", - "invitationInstructionsDescription": "Add a new member to the organization by entering their email and assigning them a role within the organization. An email will be sent to them with instructions on how to join.", - "invitationTitle": "Invite new member to {{0}}", "inviteNewMembers": "Invite new members", "inviteNewMembersOrRemoveMembersFromTheOrganization": "Invite new members or remove members from the organization", "ipAddress": "IP address", @@ -270,7 +268,7 @@ "viewLinkedDomainsAndVerifyDnsEntries": "View linked domains and verify dns entries", "viewOrganizationInformationChangeDisplayName": "View organization information change display name", "welcomeMessage": "Welcome to keycloak account management", - "writeDeleteToConfirm": "Write delete to confirm", + "writeDeleteToConfirm": "Write 'delete' to confirm", "youAreTheSameUserAsThisUser": "This is your account! This is you!", "youLackTheManageRolesRole": "You lack the manage roles role", "searchOrganizations": "Search Organizations", @@ -279,6 +277,31 @@ "error-domain-already-present": "${domain} is already present for this org.", "pending": "pending", "org-details-stat-sso-active": "active SSO connections", - "view-roles": "view roles", - "manage-roles": "manage roles" + "invitation-email-placeholder": "for example, Thomas, thomas@domain.com", + "invitation-instructions-description": "Add a new member to the organization by entering their email and assigning them a role within the organization. An email will be sent to them with instructions on how to join.", + "invitation-missing-permission-title": "You lack the 'manage-invitations' role.", + "invitation-missing-permission-body": "Speak to an admin in order to be granted this role.", + "invitation-title": "Invite new member to {{0}}", + "invitation-toast-submit": "{{data.email}} is being sent an invitation.", + "invitation-toast-submit-success": "{{data.email}} has been sent an invitation.", + "member-roles-missing-permission-title": "You lack the 'manage-roles' role.", + "member-roles-missing-permission-body": "Speak to an admin in order to be granted this role.", + "insufficient-permissions": "Insufficient permissions to perform action.", + "profile-email-placeholder": "your@email.com", + "profile-localization-description": "Manage your localization (language).", + "profile-toast-success": "Profile updated successfully.", + "profile-toast-error": "Error during Profile update.", + "role-toast-granted": "Granted {{roleName}} role to user.", + "role-toast-granted-error": "Error granting role {{roleName}} to user. Please try again.", + "role-toast-granted-all": "Granted all roles to user.", + "role-toast-granted-all-error": "Error granting all roles to user. Please try again.", + "role-toast-revoked": "Revoked {{roleName}} role from user.", + "role-toast-revoked-error": "Error revoking {{roleName}} role from user. Please try again.", + "role-toast-revoked-all": "Revoked all roles for user.", + "role-toast-revoked-all-error": "Error revoking all roles for user. Please try again.", + "role-toast-granted-filter": "Granted roles to user:", + "role-set": "Set roles:", + "role-section-header-title": "Edit roles of", + "manage": "manage", + "view": "view" } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index aeb88f1..ddd0fb6 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -5,8 +5,8 @@ "accountUpdatedError": "Impossible de mettre à jour le compte en raison d'erreurs de validation", "accountUpdatedMessage": "Votre compte a été mis à jour.", "add": "Ajouter", - "addANewDomainToThisOrganization": "Ajouter un nouveau domaine à cette organisation", - "addAnSsoProvider": "Ajouter un fournisseur SSO", + "addANewDomainToThisOrganization": "Ajouter un nouveau domaine à l'organisation", + "addAnSsoProvider": "Gestion des fournisseurs SSO.", "addDomain": "Ajouter un domaine", "addNewDomain": "Ajouter un nouveau domaine", "admin": "Admin", @@ -40,10 +40,10 @@ "close": "Fermer", "configureWaysToSignIn": "Configurer les méthodes de connexion", "confirm": "Confirmer", - "confirmProfileDelete": "Confirmer la suppression du profil", + "confirmProfileDelete": "Confirmer la suppression du compte", "copied": "Copié", "copy": "Copier", - "createATxtRecordInYourDnsConfigurationForTheFollowingHostname": "Créez un enregistrement txt dans votre configuration DNS pour le nom d'hôte suivant", + "createATxtRecordInYourDnsConfigurationForTheFollowingHostname": "Créez un enregistrement TXT dans votre configuration DNS avec le nom d'hôte suivant", "created": "Créé", "credentialCreatedAt": "<0>Créé {{date}}.", "credentialsRemovingError": "Erreur lors de la suppression de {{0}}. Veuillez réessayer.", @@ -59,7 +59,7 @@ "displayName": "Nom affiché", "doCancel": "Annuler", "doDeny": "Refuser", - "domainName": "Nom de domaine", + "domainName": "Nom du domaine", "domains": "Domaines", "done": "Fait", "doSave": "Sauvegarder", @@ -68,7 +68,7 @@ "editRoles": "Modifier les rôles", "editTheResource": "Partager la ressource - {{0}}", "email": "Email", - "enterAVerificationCodeFromAuthenticatorApplication": "Entrez un code de vérification de l'application d'authentification", + "enterAVerificationCodeFromAuthenticatorApplication": "Entrez un code de vérification de l'application d'authentification.", "error-empty": "Veuillez spécifier la valeur de '{{0}}'.", "error-invalid-blank": "Veuillez spécifier la valeur de '{{0}}'.", "error-invalid-date": "'{{0}}' est une date invalide.", @@ -104,23 +104,21 @@ "insufficientPermissionsToViewOrganization": "Permissions insuffisantes pour voir l'organisation", "internalApp": "Interne", "inUse": "En cours d'utilisation", - "invitationInstructionsDescription": "Ajoutez un nouveau membre à l'organisation en entrant son mail et en lui attribuant un rôle au sein de l'organisation. Un mail leur sera envoyé avec des instructions pour rejoindre.", - "invitationTitle": "Invitez un nouveau membre à {{0}}", - "inviteNewMembers": "Inviter de nouveaux membres", - "inviteNewMembersOrRemoveMembersFromTheOrganization": "Inviter de nouveaux membres ou retirer des membres de l'organisation", + "inviteNewMembers": "Inviter des nouveaux membres", + "inviteNewMembersOrRemoveMembersFromTheOrganization": "Inviter de nouveaux membres ou retirer des membres de l'organisation.", "ipAddress": "Adresse IP", "label": "Étiquette", "lastAccessed": "Dernier accès", "lastAccessedOn": "Dernièrement accédé", - "lastName": "Nom de famille", + "lastName": "Nom", "light": "Clair", "link": "Lier le compte", "linkAccount": "Lier le compte", - "linkedAccounts": "Comptes liés", + "linkedAccounts": "Comptes tiers liés", "linkedAccountsIntroMessage": "Gérer les connexions via des comptes tiers.", "linkedAccountsTitle": "Comptes liés", - "linkedEmpty": "Aucun fournisseur lié", - "linkedLoginProviders": "Fournisseurs de connexion liés", + "linkedEmpty": "Aucun compte lié", + "linkedLoginProviders": "Comptes liés", "linkError": "Impossible de lier en raison de : {{error}}", "localeUpdatedSuccessfully": "Localisation mise à jour avec succès", "localeUpdateFailed": "Erreur lors de la mise à jour de la localisation.", @@ -150,7 +148,7 @@ "password": "Mon mot de passe", "passwordless": "Sans mot de passe", "path": "Chemin", - "permanentlyRemoveYourProfileAndAllOfItsContentsThisActionIsNotReversibleSoPleaseContinueWithCaution": "Supprimez définitivement votre compte et tout son contenu, cette action n'est pas réversible, veuillez donc continuer avec prudence.", + "permanentlyRemoveYourProfileAndAllOfItsContentsThisActionIsNotReversibleSoPleaseContinueWithCaution": "Supprimez définitivement votre compte et tout son contenu, cette action est irréversible, veuillez donc continuer avec prudence.", "permissionRequest": "Demandes de permission - {{0}}", "permissionRequests": "Demandes de permission", "permissions": "Permissions", @@ -168,10 +166,10 @@ "removeCred": "Retirer {{0}}", "removeCredAriaLabel": "Retirer les informations d'identification", "removeDomain": "Retirer", - "removeDomainError": "{{0}} n'a pas été retiré de cette organisation. ({{1}})", - "removeDomainQuestion": "Retirer ce domaine de l'organisation ne peut pas être annulé et nécessitera de l'ajouter manuellement à nouveau.", - "removeDomainSuccess": "{{0}} a été retiré avec succès de cette organisation.", - "removeDomainTitle": "Retirer {{0}} de cette organisation.", + "removeDomainError": "{{0}} n'a pas été retiré de l'organisation. ({{1}})", + "removeDomainQuestion": "Retirer ce domaine de l'organisation est irréversible et nécessitera de l'ajouter à nouveau manuellement.", + "removeDomainSuccess": "{{0}} a été retiré avec succès de l'organisation.", + "removeDomainTitle": "Retirer {{0}} de l'organisation.", "removeModalMessage": "Cela retirera la permission d'accès actuellement accordée pour {{0}}. Vous devrez accorder à nouveau l'accès si vous souhaitez utiliser cette application.", "removeModalTitle": "Retirer l'accès", "requestor": "Demandeur", @@ -192,13 +190,13 @@ "selectOne": "Sélectionner une option", "sendInvitation": "Envoyer une invitation", "settings": "Paramètres", - "setupAssociatedDomainsAndVerifyThemToEnsureFullSecurity": "Configurer les domaines associés et les vérifier pour assurer une sécurité complète", + "setupAssociatedDomainsAndVerifyThemToEnsureFullSecurity": "Configurer et vérifier les domaines associés pour assurer une sécurité complète.", "setUpAuthenticator": "Configurer l'authentificateur", - "setupDomains": "Configurer les domaines", + "setupDomains": "Configurer des domaines", "setUpNew": "Configurer {{0}}", "setUpSecurityKey": "Configurer la clé de sécurité", - "setupSso": "Configurer SSO", - "setupSsoConnectionsAsNecessaryForThisOrganization": "Configurer les connexions SSO selon les besoins pour cette organisation", + "setupSso": "Configurer un fournisseur SSO", + "setupSsoConnectionsAsNecessaryForThisOrganization": "Configurer les fournisseurs SSO de l'organisation.", "share": "Partager", "sharedWithMe": "Partagé avec moi", "shareError": "Impossible de partager la ressource en raison de : {{error}}", @@ -222,7 +220,7 @@ "socialLogin": "Social login", "somethingWentWrong": "Quelque chose s'est mal passé", "somethingWentWrongDescription": "Désolé, une erreur inattendue s'est produite.", - "speakToAnAdminInOrderToBeGrantedThisRole": "Parlez à un administrateur pour obtenir ce rôle", + "speakToAnAdminInOrderToBeGrantedThisRole": "Contactez un administrateur pour obtenir ce rôle.", "sso": "SSO", "started": "Commencé", "status": "Statut", @@ -241,8 +239,8 @@ "unknownUser": "Anonyme", "unLink": "Dissocier le compte", "unlinkAccount": "Dissocier le compte", - "unlinkedEmpty": "Pas de fournisseurs dissociés", - "unlinkedLoginProviders": "Fournisseurs de connexion dissociés", + "unlinkedEmpty": "Pas de compte dissocié", + "unlinkedLoginProviders": "Comptes dissociés", "unLinkError": "Impossible de dissocier en raison de : {{error}}", "unLinkSuccess": "Compte dissocié avec succès", "unShare": "Ne plus partager l'ensemble", @@ -252,34 +250,59 @@ "updateCredAriaLabel": "Mettre à jour les informations d'identification", "updateError": "Impossible de mettre à jour la ressource en raison de : {{error}}", "updateLocale": "Modifier", - "updateOrganization": "Mettre à jour l'organisation", + "updateOrganization": "Modifier l'organisation", "updateSuccess": "Ressource mise à jour avec succès.", "user": "Utilisateur", "username": "Nom d'utilisateur", "usernamePlaceholder": "Nom d'utilisateur ou mail.", - "usernameEmailSame": "Le nom d'utilisateur est identique au mail.", - "useTheFollowingDetailsToVerifyYourDomain": "Utilisez les détails suivants pour vérifier votre domaine", + "usernameEmailSame": "Le nom d'utilisateur est identique à l'email.", + "useTheFollowingDetailsToVerifyYourDomain": "Utilisez les informations suivantes pour vérifier votre domaine.", "useThisCodeForTheValueOfTheTxtRecord": "Utilisez ce code pour la valeur de l'enregistrement TXT", - "useYourSecurityKeyForPasswordlessSignIn": "Utilisez votre clé de sécurité pour une connexion sans mot de passe", + "useYourSecurityKeyForPasswordlessSignIn": "Utilisez votre clé de sécurité pour une connexion sans mot de passe.", "useYourSecurityKeyToSignIn": "UUtilisez votre clé de sécurité pour vous connecter", "validated": "Validé", "verificationPending": "Vérification en attente", "verified": "Vérifié", "verify": "Vérifier", "verifyDomain": "Vérifier le domaine", - "viewLinkedDomainsAndVerifyDnsEntries": "Voir les domaines liés et vérifier les entrées DNS", - "viewOrganizationInformationChangeDisplayName": "Voir les informations de l'organisation", + "viewLinkedDomainsAndVerifyDnsEntries": "Domaines liés et entrées DNS.", + "viewOrganizationInformationChangeDisplayName": "Détails de l'organisation.", "welcomeMessage": "Bienvenue dans la gestion de compte keycloak", - "writeDeleteToConfirm": "Écrire supprimer pour confirmer", + "writeDeleteToConfirm": "Écrivez 'supprimer' pour confirmer", "youAreTheSameUserAsThisUser": "C'est votre compte ! C'est vous !", "youLackTheManageRolesRole": "Vous manquez le rôle de gestion des rôles", "searchOrganizations": "Chercher des Organisations", "newDomainPlaceholder": "www.mon-domaine.com", "error-domain-invalid": "Domaine invalide.", - "error-domain-already-present": "${domain} existe déjà pour cette organisation.", - "success-domain-added": "${domain} has been added to organization. Please verify domain.", + "error-domain-already-present": "existe déjà pour l'organisation.", + "success-domain-added": "a été ajouté à l'organization. Vous devez vérifier le domaine.", "pending": "En attente", - "org-details-stat-sso-active": "Connexion SSO actives", - "view-roles": "rôle de lecture", - "manage-roles": "rôle d'écriture" + "org-details-stat-sso-active": "SSO actifs", + "invitation-email-placeholder": "par exemple, Thomas, thomas@domaine.com", + "invitation-instructions-description": "Ajoutez un nouveau membre à l'organisation en entrant son email et en lui attribuant un rôle au sein de l'organisation. Un email leur sera envoyé avec des instructions pour rejoindre.", + "invitation-missing-permission-title": "Vous ne pouvez pas gérer les invitations.", + "invitation-missing-permission-body": "Contactez un administrateur pour obtenir les droits nécessaires.", + "invitation-title": "Inviter un nouveau membre à {{0}}", + "invitation-toast-submit": "Une invitation est envoyée à {{data.email}}.", + "invitation-toast-submit-success": "Une invitation a été envoyée à {{data.email}}.", + "member-roles-missing-permission-title": "Vous ne pouvez pas gérer les roles.", + "member-roles-missing-permission-body": "Contactez un administrateur pour obtenir les droits nécessaires.", + "insufficient-permissions": "Permissions insuffisante pour réaliser cette action.", + "profile-email-placeholder": "votre@email.com", + "profile-localization-description": "Gérer votre localisation (langue).", + "profile-toast-success": "Compte modifié avec succès.", + "profile-toast-error": "Un problème est survenu.", + "role-toast-granted": "Rôle {{roleName}} accordé à l'utilisateur.", + "role-toast-granted-error": "Une erreur est survenue lors de l'assignation du rôle {{roleName}}, Veuillez réessayer.", + "role-toast-granted-all": "Tous les rôles ont été assignés à l'utilisateur.", + "role-toast-granted-all-error": "Une erreur est survenue lors de l'assignation de tous les rôles. Veuillez réessayer.", + "role-toast-revoked": "Rôle {{roleName}} retiré à l'utilisateur.", + "role-toast-revoked-error": "Une erreur est survenue lors de la dissociation du rôle {{roleName}}, Veuillez réessayer.", + "role-toast-revoked-all": "Tous les rôles ont été retirés à l'utilisateur.", + "role-toast-revoked-all-error": "Une erreur est survenue lors de la dissociation de tous les rôles, Veuillez réessayer.", + "role-toast-granted-filter": "Roles assignés à l'utilisateur:", + "role-set": "Assigner les rôles:", + "role-section-header-title": "Modifier les rôles de", + "manage": "gestion", + "view": "lecture" } diff --git a/src/pages/invitation/new.tsx b/src/pages/invitation/new.tsx index b01fdae..d81ca6f 100644 --- a/src/pages/invitation/new.tsx +++ b/src/pages/invitation/new.tsx @@ -57,7 +57,7 @@ const NewInvitation = () => { const onSubmit = async (data) => { if (data.email) { P2Toast({ - title: `${data.email} is being sent an invitation.`, + title: t("invitation-toast-submit", { data }), information: true, }); await addOrganizationInvitation({ @@ -74,7 +74,7 @@ const NewInvitation = () => { .then(() => { P2Toast({ success: true, - title: `${data.email} has been sent an invitation.`, + title: t("invitation-toast-submit-success", { data }), }); reset(); return navigate(`/organizations/${orgId}/details`); @@ -84,7 +84,7 @@ const NewInvitation = () => { error: true, title: e.status === 401 - ? "Insufficient roles to perform action." + ? t("insufficient-permissions") : e.data.error, }); }); @@ -98,8 +98,8 @@ const NewInvitation = () => { return (
{ {!hasManageInvitationsRole && (
@@ -133,7 +133,7 @@ const NewInvitation = () => { error={errors.email} inputArgs={{ type: "email", - placeholder: "you@email.com", + placeholder: t('invitation-email-placeholder'), required: true, disabled: !hasManageInvitationsRole, }} diff --git a/src/pages/member/roles.tsx b/src/pages/member/roles.tsx index 8ea3980..a919773 100644 --- a/src/pages/member/roles.tsx +++ b/src/pages/member/roles.tsx @@ -85,13 +85,13 @@ const Roles = () => { refetchRoles(); P2Toast({ success: true, - title: `Granted ${roleName} role to user.`, + title: t("role-toast-granted", { roleName }), }); }) .catch(() => P2Toast({ error: true, - title: `Error granting ${roleName} role to user. Please try again.`, + title: t("role-toast-granted-error", { roleName }), }) ) .finally(() => { @@ -109,13 +109,13 @@ const Roles = () => { refetchRoles(); P2Toast({ success: true, - title: `Revoked ${roleName} role user.`, + title: t("role-toast-revoked", { roleName }), }); }) .catch(() => P2Toast({ error: true, - title: `Error revoking ${roleName} role to user. Please try again.`, + title: t("role-toast-revoked-error", { roleName }), }) ) .finally(() => { @@ -140,13 +140,13 @@ const Roles = () => { .then(() => { P2Toast({ success: true, - title: `Granted all roles to user.`, + title: t("role-toast-granted-all"), }); }) .catch(() => { P2Toast({ error: true, - title: `Error granting all roles to user. Please try again.`, + title: t("role-toast-granted-all-error"), }); }) .finally(() => { @@ -171,13 +171,13 @@ const Roles = () => { .then(() => { P2Toast({ success: true, - title: `Revoked all roles for user.`, + title: t("role-toast-revoked-all"), }); }) .catch(() => { P2Toast({ error: true, - title: `Error revoking all roles for user. Please try again.`, + title: t("role-toast-revoked-all-error"), }); }) .finally(() => { @@ -205,13 +205,13 @@ const Roles = () => { .then(() => { P2Toast({ success: true, - title: `Granted ${filter} roles to user.`, + title: `${t("role-toast-granted-filter")} ${t(filter)}.`, }); }) .catch(() => { P2Toast({ error: true, - title: `Error granting ${filter} roles to user. Please try again.`, + title: t("role-toast-granted-error"), }); }) .finally(() => { @@ -228,7 +228,7 @@ const Roles = () => { return (
{ {!hasManageRolesRole && (
)}
-
Set roles:
+
{t('role-set')}
diff --git a/src/pages/profile/components/internationalization.tsx b/src/pages/profile/components/internationalization.tsx index c7ba81c..5030705 100644 --- a/src/pages/profile/components/internationalization.tsx +++ b/src/pages/profile/components/internationalization.tsx @@ -97,7 +97,7 @@ const Internationalization = () => {
diff --git a/src/pages/profile/components/profile.tsx b/src/pages/profile/components/profile.tsx index dd66f52..7ed9c1f 100644 --- a/src/pages/profile/components/profile.tsx +++ b/src/pages/profile/components/profile.tsx @@ -59,13 +59,13 @@ const ProfileData = () => { .then(() => { P2Toast({ success: true, - title: `Profile updated successfully.`, + title: t('profile-toast-success'), }); }) .catch((err) => { return P2Toast({ error: true, - title: `Error during Profile update. ${err.data.error}`, + title: `${t('profile-toast-error')} ${err.data.error}`, }); }); }; @@ -92,9 +92,9 @@ const ProfileData = () => { }} inputArgs={{ disabled: isLoadingAccount || !featureFlags.editUsernameAllowed, - placeholder: "your@email.com", + placeholder: t('profile-email-placeholder'), type: "email", - title: "Username is the same as email.", + title: t("usernameEmailSame"), }} error={errors.username} helpText={t("usernameEmailSame")} @@ -128,7 +128,7 @@ const ProfileData = () => { inputArgs={{ disabled: isLoadingAccount || !featureFlags.updateEmailFeatureEnabled, - placeholder: "your@email.com", + placeholder: t('profile-email-placeholder'), type: "email", }} error={errors.email} From d2a8a03cab376561d1b9cd9d2bdc9dfbdacabf47 Mon Sep 17 00:00:00 2001 From: MGLL Date: Fri, 12 Jan 2024 15:19:54 +0100 Subject: [PATCH 9/9] fix format, order translations --- public/locales/en/translation.json | 77 +++++++++---------- public/locales/fr/translation.json | 78 ++++++++++---------- src/pages/invitation/new.tsx | 6 +- src/pages/member/roles.tsx | 4 +- src/pages/organizations/domains/add.tsx | 4 +- src/pages/organizations/domains/verify.tsx | 2 +- src/pages/organizations/settings/domains.tsx | 2 +- src/pages/profile-delete/index.tsx | 6 +- src/pages/profile/components/delete.tsx | 4 +- src/pages/profile/components/profile.tsx | 8 +- 10 files changed, 96 insertions(+), 95 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 233fade..60d71ca 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -40,7 +40,6 @@ "close": "Close", "configureWaysToSignIn": "Configure ways to sign in", "confirm": "Confirm", - "confirmProfileDelete": "Confirm profile delete", "copied": "Copied", "copy": "Copy", "createATxtRecordInYourDnsConfigurationForTheFollowingHostname": "Create a txt record in your dns configuration for the following hostname", @@ -51,7 +50,6 @@ "currentRegisteredDomains": "Current registered domains", "currentSession": "Current session", "dark": "Dark", - "deleteYourProfile": "Delete your profile", "description": "Description", "device-activity": "Device activity", "deviceActivity": "Device activity", @@ -61,6 +59,9 @@ "doDeny": "Deny", "domainName": "Domain name", "domains": "Domains", + "domains-add-placeholder": "www.your-domain.com", + "domains-add-success": "{{domain}} has been added to organization. Please verify domain.", + "domains-verify": "Verify domain", "done": "Done", "doSave": "Save", "doSignOut": "Sign out", @@ -69,6 +70,8 @@ "editTheResource": "Share the resource - {{0}}", "email": "Email", "enterAVerificationCodeFromAuthenticatorApplication": "Enter a verification code from authenticator application", + "error-domain-invalid": "Domain is not valid", + "error-domain-already-present": "${domain} is already present for this org.", "error-empty": "Please specify value of '{{0}}'.", "error-invalid-blank": "Please specify value of '{{0}}'.", "error-invalid-date": "'{{0}}' is invalid date.", @@ -104,6 +107,14 @@ "insufficientPermissionsToViewOrganization": "Insufficient permissions to view organization", "internalApp": "Internal", "inUse": "In use", + "insufficient-permissions": "Insufficient permissions to perform action.", + "invitation-email-placeholder": "for example, Thomas, thomas@domain.com", + "invitation-instructions-description": "Add a new member to the organization by entering their email and assigning them a role within the organization. An email will be sent to them with instructions on how to join.", + "invitation-missing-permission-title": "You lack the 'manage-invitations' role.", + "invitation-missing-permission-body": "Speak to an admin in order to be granted this role.", + "invitation-title": "Invite new member to {{0}}", + "invitation-toast-submit": "{{data.email}} is being sent an invitation.", + "invitation-toast-submit-success": "{{data.email}} has been sent an invitation.", "inviteNewMembers": "Invite new members", "inviteNewMembersOrRemoveMembersFromTheOrganization": "Invite new members or remove members from the organization", "ipAddress": "IP address", @@ -125,9 +136,12 @@ "localization": "Localization", "logo": "Logo", "logOut": "Log out", + "manage": "manage", "manageAccount": "Manage account", "manageLoginsThroughThirdPartyAccounts": "Manage logins through third party accounts", "manageYourUserProfileInformation": "Manage your user profile information", + "member-roles-missing-permission-title": "You lack the 'manage-roles' role.", + "member-roles-missing-permission-body": "Speak to an admin in order to be granted this role.", "members": "Members", "myResources": "My Resources", "name": "Name", @@ -138,6 +152,7 @@ "notSetUp": "{{0}} is not set up.", "offlineAccess": "Offline access", "options": "Options", + "org-details-stat-sso-active": "active SSO connections", "organization": "Organization", "organizations": "Organizations", "otp-display-name": "Authenticator application", @@ -148,6 +163,7 @@ "password": "My password", "passwordless": "no password", "path": "Path", + "pending": "pending", "permanentlyRemoveYourProfileAndAllOfItsContentsThisActionIsNotReversibleSoPleaseContinueWithCaution": "Permanently remove your profile and all of its contents this action is not reversible so please continue with caution", "permissionRequest": "Permission requests - {{0}}", "permissionRequests": "Permission requests", @@ -157,6 +173,13 @@ "personalInformation": "Personal information", "privacyPolicy": "Privacy policy", "profile": "Profile", + "profile-delete-title": "Delete your profile", + "profile-delete-confirm": "Confirm profile delete", + "profile-delete-write-to-confirm": "Write 'delete' to confirm.", + "profile-email-placeholder": "your@email.com", + "profile-localization-description": "Manage your localization (language).", + "profile-toast-success": "Profile updated successfully.", + "profile-toast-error": "Error during Profile update.", "provider": "Provider", "refreshPage": "Refresh the page", "remove": "Remove", @@ -183,8 +206,20 @@ "resourceSharedWith_other": "Resource is shared with <0>{{username}} and <1>{{other}} other users", "resourceSharedWith_zero": "This resource is not shared.", "returnToHomepage": "Return to homepage", + "role-toast-granted": "Granted {{roleName}} role to user.", + "role-toast-granted-error": "Error granting role {{roleName}} to user. Please try again.", + "role-toast-granted-all": "Granted all roles to user.", + "role-toast-granted-all-error": "Error granting all roles to user. Please try again.", + "role-toast-revoked": "Revoked {{roleName}} role from user.", + "role-toast-revoked-error": "Error revoking {{roleName}} role from user. Please try again.", + "role-toast-revoked-all": "Revoked all roles for user.", + "role-toast-revoked-all-error": "Error revoking all roles for user. Please try again.", + "role-toast-granted-filter": "Granted roles to user:", + "role-set": "Set roles:", + "role-section-header-title": "Edit roles of", "save": "Save", "searchMembers": "Search members", + "searchOrganizations": "Search Organizations", "securityKey": "Security key", "selectLocale": "Select Locale", "selectOne": "Select an option", @@ -264,44 +299,10 @@ "verificationPending": "Verification pending", "verified": "Verified", "verify": "Verify", - "verifyDomain": "Verify domain", + "view": "view", "viewLinkedDomainsAndVerifyDnsEntries": "View linked domains and verify dns entries", "viewOrganizationInformationChangeDisplayName": "View organization information change display name", "welcomeMessage": "Welcome to keycloak account management", - "writeDeleteToConfirm": "Write 'delete' to confirm", "youAreTheSameUserAsThisUser": "This is your account! This is you!", - "youLackTheManageRolesRole": "You lack the manage roles role", - "searchOrganizations": "Search Organizations", - "newDomainPlaceholder": "www.your-domain.com", - "error-domain-invalid": "Domain is not valid", - "error-domain-already-present": "${domain} is already present for this org.", - "pending": "pending", - "org-details-stat-sso-active": "active SSO connections", - "invitation-email-placeholder": "for example, Thomas, thomas@domain.com", - "invitation-instructions-description": "Add a new member to the organization by entering their email and assigning them a role within the organization. An email will be sent to them with instructions on how to join.", - "invitation-missing-permission-title": "You lack the 'manage-invitations' role.", - "invitation-missing-permission-body": "Speak to an admin in order to be granted this role.", - "invitation-title": "Invite new member to {{0}}", - "invitation-toast-submit": "{{data.email}} is being sent an invitation.", - "invitation-toast-submit-success": "{{data.email}} has been sent an invitation.", - "member-roles-missing-permission-title": "You lack the 'manage-roles' role.", - "member-roles-missing-permission-body": "Speak to an admin in order to be granted this role.", - "insufficient-permissions": "Insufficient permissions to perform action.", - "profile-email-placeholder": "your@email.com", - "profile-localization-description": "Manage your localization (language).", - "profile-toast-success": "Profile updated successfully.", - "profile-toast-error": "Error during Profile update.", - "role-toast-granted": "Granted {{roleName}} role to user.", - "role-toast-granted-error": "Error granting role {{roleName}} to user. Please try again.", - "role-toast-granted-all": "Granted all roles to user.", - "role-toast-granted-all-error": "Error granting all roles to user. Please try again.", - "role-toast-revoked": "Revoked {{roleName}} role from user.", - "role-toast-revoked-error": "Error revoking {{roleName}} role from user. Please try again.", - "role-toast-revoked-all": "Revoked all roles for user.", - "role-toast-revoked-all-error": "Error revoking all roles for user. Please try again.", - "role-toast-granted-filter": "Granted roles to user:", - "role-set": "Set roles:", - "role-section-header-title": "Edit roles of", - "manage": "manage", - "view": "view" + "youLackTheManageRolesRole": "You lack the manage roles role" } diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index ddd0fb6..c6779c3 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -40,7 +40,6 @@ "close": "Fermer", "configureWaysToSignIn": "Configurer les méthodes de connexion", "confirm": "Confirmer", - "confirmProfileDelete": "Confirmer la suppression du compte", "copied": "Copié", "copy": "Copier", "createATxtRecordInYourDnsConfigurationForTheFollowingHostname": "Créez un enregistrement TXT dans votre configuration DNS avec le nom d'hôte suivant", @@ -51,7 +50,6 @@ "currentRegisteredDomains": "Domaines actuellement enregistrés", "currentSession": "Session actuelle", "dark": "Sombre", - "deleteYourProfile": "Supprimer votre compte", "description": "Description", "device-activity": "Activité de l'appareil", "deviceActivity": "Activité de l'appareil", @@ -61,6 +59,9 @@ "doDeny": "Refuser", "domainName": "Nom du domaine", "domains": "Domaines", + "domains-add-placeholder": "www.mon-domaine.com", + "domains-add-success": "{{domain}} a été ajouté à l'organization. Vous devez vérifier le domaine.", + "domains-verify": "Vérifier le domaine", "done": "Fait", "doSave": "Sauvegarder", "doSignOut": "Se déconnecter", @@ -69,6 +70,8 @@ "editTheResource": "Partager la ressource - {{0}}", "email": "Email", "enterAVerificationCodeFromAuthenticatorApplication": "Entrez un code de vérification de l'application d'authentification.", + "error-domain-invalid": "Domaine invalide.", + "error-domain-already-present": "existe déjà pour l'organisation.", "error-empty": "Veuillez spécifier la valeur de '{{0}}'.", "error-invalid-blank": "Veuillez spécifier la valeur de '{{0}}'.", "error-invalid-date": "'{{0}}' est une date invalide.", @@ -104,6 +107,14 @@ "insufficientPermissionsToViewOrganization": "Permissions insuffisantes pour voir l'organisation", "internalApp": "Interne", "inUse": "En cours d'utilisation", + "insufficient-permissions": "Permissions insuffisante pour réaliser cette action.", + "invitation-email-placeholder": "par exemple, Thomas, thomas@domaine.com", + "invitation-instructions-description": "Ajoutez un nouveau membre à l'organisation en entrant son email et en lui attribuant un rôle au sein de l'organisation. Un email leur sera envoyé avec des instructions pour rejoindre.", + "invitation-missing-permission-title": "Vous ne pouvez pas gérer les invitations.", + "invitation-missing-permission-body": "Contactez un administrateur pour obtenir les droits nécessaires.", + "invitation-title": "Inviter un nouveau membre à {{0}}", + "invitation-toast-submit": "Une invitation est envoyée à {{data.email}}.", + "invitation-toast-submit-success": "Une invitation a été envoyée à {{data.email}}.", "inviteNewMembers": "Inviter des nouveaux membres", "inviteNewMembersOrRemoveMembersFromTheOrganization": "Inviter de nouveaux membres ou retirer des membres de l'organisation.", "ipAddress": "Adresse IP", @@ -125,9 +136,12 @@ "localization": "Localisation", "logo": "Logo", "logOut": "Se déconnecter", + "manage": "gestion", "manageAccount": "Gérer le compte", "manageLoginsThroughThirdPartyAccounts": "Gérer les connexions via des comptes tiers", "manageYourUserProfileInformation": "Gérer vos informations personnelles.", + "member-roles-missing-permission-title": "Vous ne pouvez pas gérer les roles.", + "member-roles-missing-permission-body": "Contactez un administrateur pour obtenir les droits nécessaires.", "members": "Membres", "myResources": "Mes Ressources", "name": "Nom", @@ -138,6 +152,7 @@ "notSetUp": "{{0}} n'est pas configuré.", "offlineAccess": "Accès hors ligne", "options": "Options", + "org-details-stat-sso-active": "SSO actifs", "organization": "Organisation", "organizations": "Organisations", "otp-display-name": "Application d'authentification", @@ -148,6 +163,7 @@ "password": "Mon mot de passe", "passwordless": "Sans mot de passe", "path": "Chemin", + "pending": "En attente", "permanentlyRemoveYourProfileAndAllOfItsContentsThisActionIsNotReversibleSoPleaseContinueWithCaution": "Supprimez définitivement votre compte et tout son contenu, cette action est irréversible, veuillez donc continuer avec prudence.", "permissionRequest": "Demandes de permission - {{0}}", "permissionRequests": "Demandes de permission", @@ -157,6 +173,13 @@ "personalInformation": "Informations personnelles", "privacyPolicy": "Politique de confidentialité", "profile": "Profil", + "profile-email-placeholder": "votre@email.com", + "profile-localization-description": "Gérer votre localisation (langue).", + "profile-toast-success": "Compte modifié avec succès.", + "profile-toast-error": "Un problème est survenu.", + "profile-delete-title": "Supprimer votre compte", + "profile-delete-confirm": "Confirmer la suppression du compte", + "profile-delete-write-to-confirm": "Écrivez 'supprimer' pour confirmer.", "provider": "Fournisseur", "refreshPage": "Rafraîchir la page", "remove": "Retirer", @@ -183,8 +206,20 @@ "resourceSharedWith_other": "La ressource est partagée avec <0>{{username}} et <1>{{other}} autres utilisateurs", "resourceSharedWith_zero": "Cette ressource n'est pas partagée.", "returnToHomepage": "Retourner à la page d'accueil", + "role-toast-granted": "Rôle {{roleName}} accordé à l'utilisateur.", + "role-toast-granted-error": "Une erreur est survenue lors de l'assignation du rôle {{roleName}}, Veuillez réessayer.", + "role-toast-granted-all": "Tous les rôles ont été assignés à l'utilisateur.", + "role-toast-granted-all-error": "Une erreur est survenue lors de l'assignation de tous les rôles. Veuillez réessayer.", + "role-toast-revoked": "Rôle {{roleName}} retiré à l'utilisateur.", + "role-toast-revoked-error": "Une erreur est survenue lors de la dissociation du rôle {{roleName}}, Veuillez réessayer.", + "role-toast-revoked-all": "Tous les rôles ont été retirés à l'utilisateur.", + "role-toast-revoked-all-error": "Une erreur est survenue lors de la dissociation de tous les rôles, Veuillez réessayer.", + "role-toast-granted-filter": "Roles assignés à l'utilisateur:", + "role-set": "Assigner les rôles:", + "role-section-header-title": "Modifier les rôles de", "save": "Sauvegarder", "searchMembers": "Chercher des membres", + "searchOrganizations": "Chercher des Organisations", "securityKey": "Clé de sécurité", "selectLocale": "Sélectionner la langue", "selectOne": "Sélectionner une option", @@ -264,45 +299,10 @@ "verificationPending": "Vérification en attente", "verified": "Vérifié", "verify": "Vérifier", - "verifyDomain": "Vérifier le domaine", + "view": "lecture", "viewLinkedDomainsAndVerifyDnsEntries": "Domaines liés et entrées DNS.", "viewOrganizationInformationChangeDisplayName": "Détails de l'organisation.", "welcomeMessage": "Bienvenue dans la gestion de compte keycloak", - "writeDeleteToConfirm": "Écrivez 'supprimer' pour confirmer", "youAreTheSameUserAsThisUser": "C'est votre compte ! C'est vous !", - "youLackTheManageRolesRole": "Vous manquez le rôle de gestion des rôles", - "searchOrganizations": "Chercher des Organisations", - "newDomainPlaceholder": "www.mon-domaine.com", - "error-domain-invalid": "Domaine invalide.", - "error-domain-already-present": "existe déjà pour l'organisation.", - "success-domain-added": "a été ajouté à l'organization. Vous devez vérifier le domaine.", - "pending": "En attente", - "org-details-stat-sso-active": "SSO actifs", - "invitation-email-placeholder": "par exemple, Thomas, thomas@domaine.com", - "invitation-instructions-description": "Ajoutez un nouveau membre à l'organisation en entrant son email et en lui attribuant un rôle au sein de l'organisation. Un email leur sera envoyé avec des instructions pour rejoindre.", - "invitation-missing-permission-title": "Vous ne pouvez pas gérer les invitations.", - "invitation-missing-permission-body": "Contactez un administrateur pour obtenir les droits nécessaires.", - "invitation-title": "Inviter un nouveau membre à {{0}}", - "invitation-toast-submit": "Une invitation est envoyée à {{data.email}}.", - "invitation-toast-submit-success": "Une invitation a été envoyée à {{data.email}}.", - "member-roles-missing-permission-title": "Vous ne pouvez pas gérer les roles.", - "member-roles-missing-permission-body": "Contactez un administrateur pour obtenir les droits nécessaires.", - "insufficient-permissions": "Permissions insuffisante pour réaliser cette action.", - "profile-email-placeholder": "votre@email.com", - "profile-localization-description": "Gérer votre localisation (langue).", - "profile-toast-success": "Compte modifié avec succès.", - "profile-toast-error": "Un problème est survenu.", - "role-toast-granted": "Rôle {{roleName}} accordé à l'utilisateur.", - "role-toast-granted-error": "Une erreur est survenue lors de l'assignation du rôle {{roleName}}, Veuillez réessayer.", - "role-toast-granted-all": "Tous les rôles ont été assignés à l'utilisateur.", - "role-toast-granted-all-error": "Une erreur est survenue lors de l'assignation de tous les rôles. Veuillez réessayer.", - "role-toast-revoked": "Rôle {{roleName}} retiré à l'utilisateur.", - "role-toast-revoked-error": "Une erreur est survenue lors de la dissociation du rôle {{roleName}}, Veuillez réessayer.", - "role-toast-revoked-all": "Tous les rôles ont été retirés à l'utilisateur.", - "role-toast-revoked-all-error": "Une erreur est survenue lors de la dissociation de tous les rôles, Veuillez réessayer.", - "role-toast-granted-filter": "Roles assignés à l'utilisateur:", - "role-set": "Assigner les rôles:", - "role-section-header-title": "Modifier les rôles de", - "manage": "gestion", - "view": "lecture" + "youLackTheManageRolesRole": "Vous manquez le rôle de gestion des rôles" } diff --git a/src/pages/invitation/new.tsx b/src/pages/invitation/new.tsx index d81ca6f..d6d0636 100644 --- a/src/pages/invitation/new.tsx +++ b/src/pages/invitation/new.tsx @@ -113,8 +113,8 @@ const NewInvitation = () => { {!hasManageInvitationsRole && (
@@ -133,7 +133,7 @@ const NewInvitation = () => { error={errors.email} inputArgs={{ type: "email", - placeholder: t('invitation-email-placeholder'), + placeholder: t("invitation-email-placeholder"), required: true, disabled: !hasManageInvitationsRole, }} diff --git a/src/pages/member/roles.tsx b/src/pages/member/roles.tsx index a919773..d4d927c 100644 --- a/src/pages/member/roles.tsx +++ b/src/pages/member/roles.tsx @@ -228,7 +228,7 @@ const Roles = () => { return (
{
)}
-
{t('role-set')}
+
{t("role-set")}
+ ); const removeDomainBtn = ( diff --git a/src/pages/profile-delete/index.tsx b/src/pages/profile-delete/index.tsx index 600a754..b773ed4 100644 --- a/src/pages/profile-delete/index.tsx +++ b/src/pages/profile-delete/index.tsx @@ -39,7 +39,7 @@ const ProfileDelete = () => {
{
{ }} />
diff --git a/src/pages/profile/components/delete.tsx b/src/pages/profile/components/delete.tsx index 3247199..14b36cf 100644 --- a/src/pages/profile/components/delete.tsx +++ b/src/pages/profile/components/delete.tsx @@ -11,14 +11,14 @@ const DeleteProfile = () => {
- +
diff --git a/src/pages/profile/components/profile.tsx b/src/pages/profile/components/profile.tsx index 7ed9c1f..0e6ca63 100644 --- a/src/pages/profile/components/profile.tsx +++ b/src/pages/profile/components/profile.tsx @@ -59,13 +59,13 @@ const ProfileData = () => { .then(() => { P2Toast({ success: true, - title: t('profile-toast-success'), + title: t("profile-toast-success"), }); }) .catch((err) => { return P2Toast({ error: true, - title: `${t('profile-toast-error')} ${err.data.error}`, + title: `${t("profile-toast-error")} ${err.data.error}`, }); }); }; @@ -92,7 +92,7 @@ const ProfileData = () => { }} inputArgs={{ disabled: isLoadingAccount || !featureFlags.editUsernameAllowed, - placeholder: t('profile-email-placeholder'), + placeholder: t("profile-email-placeholder"), type: "email", title: t("usernameEmailSame"), }} @@ -128,7 +128,7 @@ const ProfileData = () => { inputArgs={{ disabled: isLoadingAccount || !featureFlags.updateEmailFeatureEnabled, - placeholder: t('profile-email-placeholder'), + placeholder: t("profile-email-placeholder"), type: "email", }} error={errors.email}