diff --git a/gui/rpk-gui/public/locales/DE/common.json b/gui/rpk-gui/public/locales/DE/common.json
new file mode 100644
index 0000000..dc4cb0f
--- /dev/null
+++ b/gui/rpk-gui/public/locales/DE/common.json
@@ -0,0 +1,164 @@
+{
+ "pages": {
+ "login": {
+ "title": "Melden Sie sich bei Ihrem Konto an",
+ "signin": "Einloggen",
+ "signup": "Anmelden",
+ "divider": "oder",
+ "fields": {
+ "email": "Email",
+ "password": "Passwort"
+ },
+ "oauth": {
+ "google": "Einloggen mit Google",
+ "discord": "Einloggen mit Discord"
+ },
+ "errors": {
+ "validEmail": "Ungültige E-Mail-Adresse",
+ "requiredEmail": "E-Mail ist erforderlich",
+ "requiredPassword": "Passwort wird benötigt"
+ },
+ "buttons": {
+ "submit": "Anmeldung",
+ "forgotPassword": "Passwort vergessen?",
+ "noAccount": "Sie haben kein Konto?",
+ "rememberMe": "Erinnere dich an mich"
+ }
+ },
+ "forgotPassword": {
+ "title": "Haben Sie Ihr Passwort vergessen?",
+ "fields": {
+ "email": "Email"
+ },
+ "errors": {
+ "validEmail": "Ungültige E-Mail-Adresse",
+ "requiredEmail": "E-Mail ist erforderlich"
+ },
+ "buttons": {
+ "submit": "Anweisungen zum Zurücksetzen senden"
+ }
+ },
+ "register": {
+ "title": "Registrieren Sie sich für Ihr Konto",
+ "fields": {
+ "email": "Email",
+ "password": "Passwort"
+ },
+ "errors": {
+ "validEmail": "Ungültige E-Mail-Adresse",
+ "requiredEmail": "E-Mail ist erforderlich",
+ "requiredPassword": "Passwort wird benötigt"
+ },
+ "buttons": {
+ "submit": "Registrieren",
+ "haveAccount": "Ein Konto haben?"
+ }
+ },
+ "updatePassword": {
+ "title": "Kennwort aktualisieren",
+ "fields": {
+ "password": "Neues Passwort",
+ "confirmPassword": "Bestätige neues Passwort"
+ },
+ "errors": {
+ "confirmPasswordNotMatch": "Passwörter stimmen nicht überein",
+ "requiredPassword": "Passwort wird benötigt",
+ "requiredConfirmPassword": "Das Feld „Passwort bestätigen“ ist erforderlich"
+ },
+ "buttons": {
+ "submit": "Aktualisieren"
+ }
+ },
+ "error": {
+ "info": "Sie haben vergessen, {{action}} component zu {{resource}} hinzufügen.",
+ "404": "Leider existiert diese Seite nicht.",
+ "resource404": "Haben Sie die {{resource}} resource erstellt?",
+ "backHome": "Zurück"
+ }
+ },
+ "actions": {
+ "list": "Aufführen",
+ "create": "Erstellen",
+ "edit": "Bearbeiten",
+ "show": "Zeigen"
+ },
+ "buttons": {
+ "create": "Erstellen",
+ "save": "Speichern",
+ "logout": "Abmelden",
+ "delete": "Löschen",
+ "edit": "Bearbeiten",
+ "cancel": "Abbrechen",
+ "confirm": "Sicher?",
+ "filter": "Filter",
+ "clear": "Löschen",
+ "refresh": "Erneuern",
+ "show": "Zeigen",
+ "undo": "Undo",
+ "import": "Importieren",
+ "clone": "Klon",
+ "notAccessTitle": "Sie haben keine zugriffsberechtigung"
+ },
+ "warnWhenUnsavedChanges": "Nicht gespeicherte Änderungen werden nicht übernommen.",
+ "notifications": {
+ "success": "Erfolg",
+ "error": "Fehler (status code: {{statusCode}})",
+ "undoable": "Sie haben {{seconds}} Sekunden Zeit für Undo.",
+ "createSuccess": "{{resource}} erfolgreich erstellt.",
+ "createError": "Fehler beim Erstellen {{resource}} (status code: {{statusCode}})",
+ "deleteSuccess": "{{resource}} erfolgreich gelöscht.",
+ "deleteError": "Fehler beim Löschen {{resource}} (status code: {{statusCode}})",
+ "editSuccess": "{{resource}} erfolgreich bearbeitet.",
+ "editError": "Fehler beim Bearbeiten {{resource}} (status code: {{statusCode}})",
+ "importProgress": "{{processed}}/{{total}} importiert"
+ },
+ "loading": "Wird geladen",
+ "tags": {
+ "clone": "Klon"
+ },
+ "dashboard": {
+ "title": "Dashboard"
+ },
+ "posts": {
+ "posts": "Einträge",
+ "fields": {
+ "id": "Id",
+ "title": "Titel",
+ "category": "Kategorie",
+ "status": {
+ "title": "Status",
+ "published": "Veröffentlicht",
+ "draft": "Draft",
+ "rejected": "Abgelehnt"
+ },
+ "content": "Inhalh",
+ "createdAt": "Erstellt am"
+ },
+ "titles": {
+ "create": "Erstellen",
+ "edit": "Bearbeiten",
+ "list": "Einträge",
+ "show": "Eintrag zeigen"
+ }
+ },
+ "table": {
+ "actions": "Aktionen"
+ },
+ "documentTitle": {
+ "default": "refine",
+ "suffix": " | Refine",
+ "post": {
+ "list": "Beiträge | Refine",
+ "show": "#{{id}} Beitrag anzeigen | Refine",
+ "edit": "#{{id}} Beitrag bearbeiten | Refine",
+ "create": "Neuen Beitrag erstellen | Refine",
+ "clone": "#{{id}} Beitrag klonen | Refine"
+ }
+ },
+ "autoSave": {
+ "success": "gespeichert",
+ "error": "fehler beim automatischen speichern",
+ "loading": "speichern...",
+ "idle": "warten auf anderungen"
+ }
+}
diff --git a/gui/rpk-gui/public/locales/EN/common.json b/gui/rpk-gui/public/locales/EN/common.json
new file mode 100644
index 0000000..6ad95a6
--- /dev/null
+++ b/gui/rpk-gui/public/locales/EN/common.json
@@ -0,0 +1,164 @@
+{
+ "pages": {
+ "login": {
+ "title": "Sign in to your account",
+ "signin": "Sign in",
+ "signup": "Sign up",
+ "divider": "or",
+ "fields": {
+ "email": "Email",
+ "password": "Password"
+ },
+ "oauth": {
+ "google": "Sign in with Google",
+ "discord": "Sign in with Discord"
+ },
+ "errors": {
+ "validEmail": "Invalid email address",
+ "requiredEmail": "Email is required",
+ "requiredPassword": "Password is required"
+ },
+ "buttons": {
+ "submit": "Login",
+ "forgotPassword": "Forgot password?",
+ "noAccount": "Don’t have an account?",
+ "rememberMe": "Remember me"
+ }
+ },
+ "forgotPassword": {
+ "title": "Forgot your password?",
+ "fields": {
+ "email": "Email"
+ },
+ "errors": {
+ "validEmail": "Invalid email address",
+ "requiredEmail": "Email is required"
+ },
+ "buttons": {
+ "submit": "Send reset instructions"
+ }
+ },
+ "register": {
+ "title": "Sign up for your account",
+ "fields": {
+ "email": "Email",
+ "password": "Password"
+ },
+ "errors": {
+ "validEmail": "Invalid email address",
+ "requiredEmail": "Email is required",
+ "requiredPassword": "Password is required"
+ },
+ "buttons": {
+ "submit": "Register",
+ "haveAccount": "Have an account?"
+ }
+ },
+ "updatePassword": {
+ "title": "Update password",
+ "fields": {
+ "password": "New Password",
+ "confirmPassword": "Confirm new password"
+ },
+ "errors": {
+ "confirmPasswordNotMatch": "Passwords do not match",
+ "requiredPassword": "Password required",
+ "requiredConfirmPassword": "Confirm password is required"
+ },
+ "buttons": {
+ "submit": "Update"
+ }
+ },
+ "error": {
+ "info": "You may have forgotten to add the {{action}} component to {{resource}} resource.",
+ "404": "Sorry, the page you visited does not exist.",
+ "resource404": "Are you sure you have created the {{resource}} resource.",
+ "backHome": "Back Home"
+ }
+ },
+ "actions": {
+ "list": "List",
+ "create": "Create",
+ "edit": "Edit",
+ "show": "Show"
+ },
+ "buttons": {
+ "create": "Create",
+ "save": "Save",
+ "logout": "Logout",
+ "delete": "Delete",
+ "edit": "Edit",
+ "cancel": "Cancel",
+ "confirm": "Are you sure?",
+ "filter": "Filter",
+ "clear": "Clear",
+ "refresh": "Refresh",
+ "show": "Show",
+ "undo": "Undo",
+ "import": "Import",
+ "clone": "Clone",
+ "notAccessTitle": "You don't have permission to access"
+ },
+ "warnWhenUnsavedChanges": "Are you sure you want to leave? You have unsaved changes.",
+ "notifications": {
+ "success": "Successful",
+ "error": "Error (status code: {{statusCode}})",
+ "undoable": "You have {{seconds}} seconds to undo",
+ "createSuccess": "Successfully created {{resource}}",
+ "createError": "There was an error creating {{resource}} (status code: {{statusCode}})",
+ "deleteSuccess": "Successfully deleted {{resource}}",
+ "deleteError": "Error when deleting {{resource}} (status code: {{statusCode}})",
+ "editSuccess": "Successfully edited {{resource}}",
+ "editError": "Error when editing {{resource}} (status code: {{statusCode}})",
+ "importProgress": "Importing: {{processed}}/{{total}}"
+ },
+ "loading": "Loading",
+ "tags": {
+ "clone": "Clone"
+ },
+ "dashboard": {
+ "title": "Dashboard"
+ },
+ "posts": {
+ "posts": "Posts",
+ "fields": {
+ "id": "Id",
+ "title": "Title",
+ "category": "Category",
+ "status": {
+ "title": "Status",
+ "published": "Published",
+ "draft": "Draft",
+ "rejected": "Rejected"
+ },
+ "content": "Content",
+ "createdAt": "Created At"
+ },
+ "titles": {
+ "create": "Create Post",
+ "edit": "Edit Post",
+ "list": "Posts",
+ "show": "Show Post"
+ }
+ },
+ "table": {
+ "actions": "Actions"
+ },
+ "documentTitle": {
+ "default": "refine",
+ "suffix": " | Refine",
+ "post": {
+ "list": "Posts | Refine",
+ "show": "#{{id}} Show Post | Refine",
+ "edit": "#{{id}} Edit Post | Refine",
+ "create": "Create new Post | Refine",
+ "clone": "#{{id}} Clone Post | Refine"
+ }
+ },
+ "autoSave": {
+ "success": "saved",
+ "error": "auto save failure",
+ "loading": "saving...",
+ "idle": "waiting for changes"
+ }
+}
diff --git a/gui/rpk-gui/public/locales/FR/common.json b/gui/rpk-gui/public/locales/FR/common.json
new file mode 100644
index 0000000..4897684
--- /dev/null
+++ b/gui/rpk-gui/public/locales/FR/common.json
@@ -0,0 +1,164 @@
+{
+ "pages": {
+ "login": {
+ "title": "Authentification",
+ "signin": "S'authentifier",
+ "signup": "Créer un compte",
+ "divider": "ou",
+ "fields": {
+ "email": "Email",
+ "password": "Mot de passe"
+ },
+ "oauth": {
+ "google": "S'authentifier avec Google",
+ "discord": "S'authentifier avec Discord"
+ },
+ "errors": {
+ "validEmail": "Email invalide",
+ "requiredEmail": "l'Email est obligatoire",
+ "requiredPassword": "Le mot de passe est obligatoire"
+ },
+ "buttons": {
+ "submit": "S'authentifier",
+ "forgotPassword": "Mot de passe oublié?",
+ "noAccount": "Vous n'avec pas de compte?",
+ "rememberMe": "Se souvenir de moi"
+ }
+ },
+ "forgotPassword": {
+ "title": "Mot de passe oublié?",
+ "fields": {
+ "email": "Email"
+ },
+ "errors": {
+ "validEmail": "mail invalide",
+ "requiredEmail": "l'Email est obligatoire"
+ },
+ "buttons": {
+ "submit": "Envoyer les instructions de récupération"
+ }
+ },
+ "register": {
+ "title": "Création de compte",
+ "fields": {
+ "email": "Email",
+ "password": "Mot de passe"
+ },
+ "errors": {
+ "validEmail": "Email invalide",
+ "requiredEmail": "l'Email est obligatoire",
+ "requiredPassword": "Le mot de passe est obligatoire"
+ },
+ "buttons": {
+ "submit": "Créer un compte",
+ "haveAccount": "Vous avez déjà un compte?"
+ }
+ },
+ "updatePassword": {
+ "title": "Mise à jour du mot de passe",
+ "fields": {
+ "password": "Nouveau mot de passe",
+ "confirmPassword": "Confirmation"
+ },
+ "errors": {
+ "confirmPasswordNotMatch": "Les mots de passe ne correspondent pas",
+ "requiredPassword": "Le mot de passe est obligatoire",
+ "requiredConfirmPassword": "Vous devez confirmer votre mot de passe"
+ },
+ "buttons": {
+ "submit": "Mettre à jour"
+ }
+ },
+ "error": {
+ "info": "Il manque l'action {{action}} component à la ressource {{resource}} .",
+ "404": "Cette page n'existe pas.",
+ "resource404": "Cette page n'existe pas.",
+ "backHome": "Retour à l'accueil"
+ }
+ },
+ "actions": {
+ "list": "Liste",
+ "create": "Création",
+ "edit": "Édtion",
+ "show": "Voir"
+ },
+ "buttons": {
+ "create": "Créer",
+ "save": "Sauvegarder",
+ "logout": "Se déconnecter",
+ "delete": "Supprimer",
+ "edit": "Modifier",
+ "cancel": "Annuler",
+ "confirm": "Êtes vous sur?",
+ "filter": "Filtrer",
+ "clear": "Effacer",
+ "refresh": "Rafraîchir",
+ "show": "Voir",
+ "undo": "Annuler",
+ "import": "Importer",
+ "clone": "Cloner",
+ "notAccessTitle": "Vous n'avez pas la permission d'accéder à cette ressource"
+ },
+ "warnWhenUnsavedChanges": "Êtes vous sur de vouloir quitter la page? Vous avez des modification non sauvegardées.",
+ "notifications": {
+ "success": "Succès",
+ "error": "Erreur (Code de statut: {{statusCode}})",
+ "undoable": "Vous avez {{seconds}} secondes à annuler",
+ "createSuccess": "Création de {{resource}} réussie",
+ "createError": "Erreur pendant la création de {{resource}} (Code de statut: {{statusCode}})",
+ "deleteSuccess": "Suppression de {{resource}} réussie",
+ "deleteError": "Erreur pendant la suppression de {{resource}} (Code de statut: {{statusCode}})",
+ "editSuccess": "Modification de {{resource}} réussie",
+ "editError": "Erreur pendant la modification de {{resource}} (Code de statut: {{statusCode}})",
+ "importProgress": "Importation de: {{processed}}/{{total}}"
+ },
+ "loading": "Chargement",
+ "tags": {
+ "clone": "Clone"
+ },
+ "dashboard": {
+ "title": "Tableau de bord"
+ },
+ "posts": {
+ "posts": "Posts",
+ "fields": {
+ "id": "Id",
+ "title": "Title",
+ "category": "Category",
+ "status": {
+ "title": "Status",
+ "published": "Published",
+ "draft": "Draft",
+ "rejected": "Rejected"
+ },
+ "content": "Content",
+ "createdAt": "Created At"
+ },
+ "titles": {
+ "create": "Create Post",
+ "edit": "Edit Post",
+ "list": "Posts",
+ "show": "Show Post"
+ }
+ },
+ "table": {
+ "actions": "Actions"
+ },
+ "documentTitle": {
+ "default": "refine",
+ "suffix": " | Refine",
+ "post": {
+ "list": "Posts | Refine",
+ "show": "#{{id}} Show Post | Refine",
+ "edit": "#{{id}} Edit Post | Refine",
+ "create": "Create new Post | Refine",
+ "clone": "#{{id}} Clone Post | Refine"
+ }
+ },
+ "autoSave": {
+ "success": "Sauvegardé",
+ "error": "Sauvegarde automatique ratée",
+ "loading": "Sauvegarde...",
+ "idle": "En attente de modification"
+ }
+}
diff --git a/gui/rpk-gui/public/locales/en/common.json b/gui/rpk-gui/public/locales/en/common.json
deleted file mode 100644
index 1e19716..0000000
--- a/gui/rpk-gui/public/locales/en/common.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "pages": {
- "login": {
- "title": "Sign in to your account"
- }
- }
-}
diff --git a/gui/rpk-gui/public/locales/fr/common.json b/gui/rpk-gui/public/locales/fr/common.json
deleted file mode 100644
index 5756149..0000000
--- a/gui/rpk-gui/public/locales/fr/common.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "pages": {
- "login": {
- "title": "S'authentifier"
- }
- }
-}
diff --git a/gui/rpk-gui/src/components/auth/Login.tsx b/gui/rpk-gui/src/components/auth/Login.tsx
index a3942d2..0b9dbab 100644
--- a/gui/rpk-gui/src/components/auth/Login.tsx
+++ b/gui/rpk-gui/src/components/auth/Login.tsx
@@ -8,8 +8,10 @@ import * as React from "react";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
+import { useTranslation } from "@refinedev/core";
export const Login = () => {
+ const { translate } = useTranslation();
const [searchParams] = useSearchParams();
if (searchParams.get("oauth") == "success") {
const redirect_to = localStorage.getItem("redirect_after_login")
@@ -24,12 +26,12 @@ export const Login = () => {
rememberMe={false}
providers={[{
name: "google",
- label: "Sign in with Google",
+ label: translate("pages.login.oauth.google"),
icon: (),
},
{
name: "discord",
- label: "Sign in with Discord",
+ label: translate("pages.login.oauth.discord"),
icon: (),
},
]}
@@ -50,7 +52,7 @@ export const Login = () => {
underline="none"
to="/auth/forgot-password"
>
- Forgot password?
+ {translate("pages.login.buttons.forgotPassword")}
}
@@ -69,7 +71,7 @@ export const Login = () => {
component="span"
fontSize="12px"
>
- Don’t have an account?
+ {translate("pages.login.buttons.noAccount")}
{
to="/auth/register"
fontWeight="bold"
>
- Sign up
+ {translate("pages.login.signup")}
}
diff --git a/gui/rpk-gui/src/components/auth/Register.tsx b/gui/rpk-gui/src/components/auth/Register.tsx
index cb022c7..a979d96 100644
--- a/gui/rpk-gui/src/components/auth/Register.tsx
+++ b/gui/rpk-gui/src/components/auth/Register.tsx
@@ -1,5 +1,51 @@
import { AuthPage } from "@refinedev/mui";
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+import MuiLink from "@mui/material/Link";
+import * as React from "react";
+import { useTranslation } from "@refinedev/core";
+import { Link } from "react-router";
export const Register = () => {
- return ;
+ const { translate } = useTranslation();
+ const loginLink = (
+
+
+ {translate(
+ "pages.register.buttons.haveAccount",
+ translate(
+ "pages.login.buttons.haveAccount",
+ "Have an account?",
+ ),
+ )}
+
+
+ {translate(
+ "pages.register.signin",
+ translate("pages.login.signin", "Sign in"),
+ )}
+
+
+ )
+
+ return ;
};
diff --git a/gui/rpk-gui/src/components/header/I18nPicker.tsx b/gui/rpk-gui/src/components/header/I18nPicker.tsx
new file mode 100644
index 0000000..39f5f2c
--- /dev/null
+++ b/gui/rpk-gui/src/components/header/I18nPicker.tsx
@@ -0,0 +1,41 @@
+import Autocomplete from "@mui/material/Autocomplete";
+import TextField from "@mui/material/TextField";
+import Box from "@mui/material/Box";
+import React from "react";
+import { useTranslation } from "react-i18next";
+import { useTranslation as useRefineTranslation } from "@refinedev/core";
+
+const I18nPicker = () => {
+ const { i18n } = useTranslation();
+ const { getLocale, changeLocale } = useRefineTranslation();
+ const currentLocale = getLocale();
+
+ return (
+ {
+ return
+ }}
+ renderOption={(props, option) => {
+ const { key, ...optionProps } = props;
+ return (
+ img': { mr: 2, flexShrink: 0 } }}
+ {...optionProps}
+ >
+ { option }
+
+ );
+ }}
+ onChange={(event, value) => {
+ changeLocale(value);
+ }}
+ />
+ )
+}
+
+export default I18nPicker;
diff --git a/gui/rpk-gui/src/components/header/index.tsx b/gui/rpk-gui/src/components/header/index.tsx
index bf0e285..aa9125a 100644
--- a/gui/rpk-gui/src/components/header/index.tsx
+++ b/gui/rpk-gui/src/components/header/index.tsx
@@ -18,17 +18,11 @@ import { FirmContext } from "../../contexts/FirmContext";
import { Logout } from "../auth/Logout";
import { IUser } from "../../interfaces";
import MuiLink from "@mui/material/Link";
-import { useTranslation } from "react-i18next";
-import { useTranslation as useTranslationR } from "@refinedev/core";
-import { useSetLocale } from "@refinedev/core";
+import I18nPicker from "./I18nPicker";
export const Header: React.FC = ({
sticky = true,
}) => {
- const { i18n } = useTranslation();
- const { getLocale, changeLocale } = useTranslationR();
- const currentLocale = getLocale();
-
const collapsed = false;
const { mode, setMode } = useContext(ColorModeContext);
const { currentFirm } = useContext(FirmContext);
@@ -44,16 +38,6 @@ export const Header: React.FC = ({
setAnchorEl(null);
};
- const [anchorIn, setAnchorIn] = React.useState(null);
- const openI18nMenu = Boolean(anchorEl);
- const handleOpenI18nMenu = (event: React.MouseEvent) => {
- setAnchorIn(event.currentTarget);
- }
- const handleCloseI18nMenu = () => {
- setAnchorIn(null);
- };
-
-
return (
@@ -149,43 +133,7 @@ export const Header: React.FC = ({
{!user && (
)}
-
-
+
diff --git a/gui/rpk-gui/src/i18n.tsx b/gui/rpk-gui/src/i18n.tsx
index e6f6b51..5e280bb 100644
--- a/gui/rpk-gui/src/i18n.tsx
+++ b/gui/rpk-gui/src/i18n.tsx
@@ -8,13 +8,13 @@ i18n
.use(detector)
.use(initReactI18next)
.init({
- supportedLngs: ["en", "fr"],
+ supportedLngs: ["EN", "FR"],
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json", // locale files path
},
ns: ["common"],
defaultNS: "common",
- fallbackLng: ["en", "fr"],
+ fallbackLng: ["EN", "FR"],
});
export default i18n;