From fd32e737a374dbd5bfa5b81f2e397618bdc0c9be Mon Sep 17 00:00:00 2001 From: Stavros Date: Wed, 19 Mar 2025 19:36:48 +0200 Subject: [PATCH] feat: add i18n --- internal/api/api.go | 12 ++++++ site/bun.lockb | Bin 100781 -> 103724 bytes site/package.json | 4 ++ site/src/components/auth/login-forn.tsx | 8 ++-- site/src/lib/i18n/i18n.ts | 20 ++++++++++ site/src/lib/i18n/locales/af-ZA.json | 15 ++++++++ site/src/lib/i18n/locales/ar-SA.json | 15 ++++++++ site/src/lib/i18n/locales/ca-ES.json | 15 ++++++++ site/src/lib/i18n/locales/cs-CZ.json | 15 ++++++++ site/src/lib/i18n/locales/da-DK.json | 15 ++++++++ site/src/lib/i18n/locales/de-DE.json | 15 ++++++++ site/src/lib/i18n/locales/el-GR.json | 15 ++++++++ site/src/lib/i18n/locales/en-US.json | 15 ++++++++ site/src/lib/i18n/locales/en.json | 45 +++++++++++++++++++++++ site/src/lib/i18n/locales/es-ES.json | 15 ++++++++ site/src/lib/i18n/locales/fi-FI.json | 15 ++++++++ site/src/lib/i18n/locales/fr-FR.json | 15 ++++++++ site/src/lib/i18n/locales/he-IL.json | 15 ++++++++ site/src/lib/i18n/locales/hu-HU.json | 15 ++++++++ site/src/lib/i18n/locales/it-IT.json | 15 ++++++++ site/src/lib/i18n/locales/ja-JP.json | 15 ++++++++ site/src/lib/i18n/locales/ko-KR.json | 15 ++++++++ site/src/lib/i18n/locales/nl-NL.json | 15 ++++++++ site/src/lib/i18n/locales/no-NO.json | 15 ++++++++ site/src/lib/i18n/locales/pl-PL.json | 15 ++++++++ site/src/lib/i18n/locales/pt-BR.json | 15 ++++++++ site/src/lib/i18n/locales/pt-PT.json | 15 ++++++++ site/src/lib/i18n/locales/ro-RO.json | 15 ++++++++ site/src/lib/i18n/locales/ru-RU.json | 15 ++++++++ site/src/lib/i18n/locales/sr-SP.json | 15 ++++++++ site/src/lib/i18n/locales/sv-SE.json | 15 ++++++++ site/src/lib/i18n/locales/tr-TR.json | 15 ++++++++ site/src/lib/i18n/locales/uk-UA.json | 15 ++++++++ site/src/lib/i18n/locales/vi-VN.json | 15 ++++++++ site/src/lib/i18n/locales/zh-CN.json | 15 ++++++++ site/src/lib/i18n/locales/zh-TW.json | 15 ++++++++ site/src/main.tsx | 1 + site/src/pages/continue-page.tsx | 34 +++++++++-------- site/src/pages/internal-server-error.tsx | 11 +++--- site/src/pages/login-page.tsx | 22 ++++++----- site/src/pages/logout-page.tsx | 39 +++++++++++++++----- site/src/pages/not-found-page.tsx | 8 ++-- site/src/pages/totp-page.tsx | 12 +++--- site/src/pages/unauthorized-page.tsx | 27 ++++++++++---- 44 files changed, 633 insertions(+), 60 deletions(-) create mode 100644 site/src/lib/i18n/i18n.ts create mode 100644 site/src/lib/i18n/locales/af-ZA.json create mode 100644 site/src/lib/i18n/locales/ar-SA.json create mode 100644 site/src/lib/i18n/locales/ca-ES.json create mode 100644 site/src/lib/i18n/locales/cs-CZ.json create mode 100644 site/src/lib/i18n/locales/da-DK.json create mode 100644 site/src/lib/i18n/locales/de-DE.json create mode 100644 site/src/lib/i18n/locales/el-GR.json create mode 100644 site/src/lib/i18n/locales/en-US.json create mode 100644 site/src/lib/i18n/locales/en.json create mode 100644 site/src/lib/i18n/locales/es-ES.json create mode 100644 site/src/lib/i18n/locales/fi-FI.json create mode 100644 site/src/lib/i18n/locales/fr-FR.json create mode 100644 site/src/lib/i18n/locales/he-IL.json create mode 100644 site/src/lib/i18n/locales/hu-HU.json create mode 100644 site/src/lib/i18n/locales/it-IT.json create mode 100644 site/src/lib/i18n/locales/ja-JP.json create mode 100644 site/src/lib/i18n/locales/ko-KR.json create mode 100644 site/src/lib/i18n/locales/nl-NL.json create mode 100644 site/src/lib/i18n/locales/no-NO.json create mode 100644 site/src/lib/i18n/locales/pl-PL.json create mode 100644 site/src/lib/i18n/locales/pt-BR.json create mode 100644 site/src/lib/i18n/locales/pt-PT.json create mode 100644 site/src/lib/i18n/locales/ro-RO.json create mode 100644 site/src/lib/i18n/locales/ru-RU.json create mode 100644 site/src/lib/i18n/locales/sr-SP.json create mode 100644 site/src/lib/i18n/locales/sv-SE.json create mode 100644 site/src/lib/i18n/locales/tr-TR.json create mode 100644 site/src/lib/i18n/locales/uk-UA.json create mode 100644 site/src/lib/i18n/locales/vi-VN.json create mode 100644 site/src/lib/i18n/locales/zh-CN.json create mode 100644 site/src/lib/i18n/locales/zh-TW.json diff --git a/internal/api/api.go b/internal/api/api.go index 7d861f3..ba3e4c3 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -4,6 +4,7 @@ import ( "fmt" "io/fs" "net/http" + "os" "strings" "time" "tinyauth/internal/assets" @@ -69,7 +70,18 @@ func (api *API) Init() { router.Use(func(c *gin.Context) { // If not an API request, serve the UI if !strings.HasPrefix(c.Request.URL.Path, "/api") { + // Check if the file exists + _, err := fs.Stat(dist, strings.TrimPrefix(c.Request.URL.Path, "/")) + + // If the file doesn't exist, serve the index.html + if os.IsNotExist(err) { + c.Request.URL.Path = "/" + } + + // Serve the file fileServer.ServeHTTP(c.Writer, c.Request) + + // Stop further processing c.Abort() } }) diff --git a/site/bun.lockb b/site/bun.lockb index fafe5b495f57bacbc84ef5ce322ca1d9864305e1..c4037f6ad9fa14b7b193bbafb6cdcccb8ab4dce3 100755 GIT binary patch delta 18947 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 diff --git a/site/package.json b/site/package.json index 8bbe81e..2e44296 100644 --- a/site/package.json +++ b/site/package.json @@ -16,8 +16,12 @@ "@mantine/notifications": "^7.16.0", "@tanstack/react-query": "4", "axios": "^1.7.9", + "i18next": "^24.2.3", + "i18next-browser-languagedetector": "^8.0.4", + "i18next-resources-to-backend": "^1.2.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-i18next": "^15.4.1", "react-router": "^7.1.3", "zod": "^3.24.1" }, diff --git a/site/src/components/auth/login-forn.tsx b/site/src/components/auth/login-forn.tsx index 8b76e2d..6dbf4eb 100644 --- a/site/src/components/auth/login-forn.tsx +++ b/site/src/components/auth/login-forn.tsx @@ -1,6 +1,7 @@ import { TextInput, PasswordInput, Button } from "@mantine/core"; import { useForm, zodResolver } from "@mantine/form"; import { LoginFormValues, loginSchema } from "../../schemas/login-schema"; +import { useTranslation } from "react-i18next"; interface LoginFormProps { isLoading: boolean; @@ -9,6 +10,7 @@ interface LoginFormProps { export const LoginForm = (props: LoginFormProps) => { const { isLoading, onSubmit } = props; + const { t } = useTranslation(); const form = useForm({ mode: "uncontrolled", @@ -22,7 +24,7 @@ export const LoginForm = (props: LoginFormProps) => { return (
{ {...form.getInputProps("username")} /> { {...form.getInputProps("password")} /> ); diff --git a/site/src/lib/i18n/i18n.ts b/site/src/lib/i18n/i18n.ts new file mode 100644 index 0000000..5408974 --- /dev/null +++ b/site/src/lib/i18n/i18n.ts @@ -0,0 +1,20 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; +import resourcesToBackend from 'i18next-resources-to-backend'; + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .use(resourcesToBackend((language: string) => import(`./locales/${language}.json`))) + .init({ + fallbackLng: 'en', + debug: import.meta.env.MODE === 'development', + + interpolation: { + escapeValue: false, + } + }); + + +export default i18n; \ No newline at end of file diff --git a/site/src/lib/i18n/locales/af-ZA.json b/site/src/lib/i18n/locales/af-ZA.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/af-ZA.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/ar-SA.json b/site/src/lib/i18n/locales/ar-SA.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/ar-SA.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/ca-ES.json b/site/src/lib/i18n/locales/ca-ES.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/ca-ES.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/cs-CZ.json b/site/src/lib/i18n/locales/cs-CZ.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/cs-CZ.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/da-DK.json b/site/src/lib/i18n/locales/da-DK.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/da-DK.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/de-DE.json b/site/src/lib/i18n/locales/de-DE.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/de-DE.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/el-GR.json b/site/src/lib/i18n/locales/el-GR.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/el-GR.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/en-US.json b/site/src/lib/i18n/locales/en-US.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/en-US.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/en.json b/site/src/lib/i18n/locales/en.json new file mode 100644 index 0000000..38ccec3 --- /dev/null +++ b/site/src/lib/i18n/locales/en.json @@ -0,0 +1,45 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider", + "continueRedirectingTitle": "Redirecting...", + "continueRedirectingSubtitle": "You should be redirected to the app soon", + "continueInvalidRedirectTitle": "Invalid redirect", + "continueInvalidRedirectSubtitle": "The redirect URL is invalid", + "continueInsecureRedirectTitle": "Insecure redirect", + "continueInsecureRedirectSubtitle": "You are trying to redirect from https to http, are you sure you want to continue?", + "continueTitle": "Continue", + "continueSubtitle": "Click the button to continue to your app.", + "internalErrorTitle": "Internal Server Error", + "internalErrorSubtitle": "An error occured on the server and it currently cannot serve your request.", + "internalErrorButton": "Try again", + "logoutFailTitle": "Failed to logout", + "logoutFailSubtitle": "Please try again", + "logoutSuccessTitle": "Logged out", + "logoutSuccessSubtitle": "You have been logged out", + "logoutTitle": "Logout", + "logoutUsernameSubtitle": "You are currently logged in as {{username}}, click the button below to logout.", + "logoutOauthSubtitle": "You are currently logged in as {{username}} using the {{provider}} OAuth provider, click the button below to logout.", + "notFoundTitle": "Page not found", + "notFoundSubtitle": "The page you are looking for does not exist.", + "notFoundButton": "Go home", + "totpFailTitle": "Failed to verify code", + "totpFailSubtitle": "Please check your code and try again", + "totpSuccessTitle": "Verified", + "totpSuccessSubtitle": "Redirecting to your app", + "totpTitle": "Enter your TOTP code", + "unauthorizedTitle": "Unauthorized", + "unauthorizedResourceSubtitle": "The user with username {{username}} is not authorized to access the resource {{resource}}.", + "unaothorizedLoginSubtitle": "The user with username {{username}} is not authorized to login.", + "unauthorizedButton": "Try again" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/es-ES.json b/site/src/lib/i18n/locales/es-ES.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/es-ES.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/fi-FI.json b/site/src/lib/i18n/locales/fi-FI.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/fi-FI.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/fr-FR.json b/site/src/lib/i18n/locales/fr-FR.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/fr-FR.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/he-IL.json b/site/src/lib/i18n/locales/he-IL.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/he-IL.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/hu-HU.json b/site/src/lib/i18n/locales/hu-HU.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/hu-HU.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/it-IT.json b/site/src/lib/i18n/locales/it-IT.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/it-IT.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/ja-JP.json b/site/src/lib/i18n/locales/ja-JP.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/ja-JP.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/ko-KR.json b/site/src/lib/i18n/locales/ko-KR.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/ko-KR.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/nl-NL.json b/site/src/lib/i18n/locales/nl-NL.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/nl-NL.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/no-NO.json b/site/src/lib/i18n/locales/no-NO.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/no-NO.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/pl-PL.json b/site/src/lib/i18n/locales/pl-PL.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/pl-PL.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/pt-BR.json b/site/src/lib/i18n/locales/pt-BR.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/pt-BR.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/pt-PT.json b/site/src/lib/i18n/locales/pt-PT.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/pt-PT.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/ro-RO.json b/site/src/lib/i18n/locales/ro-RO.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/ro-RO.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/ru-RU.json b/site/src/lib/i18n/locales/ru-RU.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/ru-RU.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/sr-SP.json b/site/src/lib/i18n/locales/sr-SP.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/sr-SP.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/sv-SE.json b/site/src/lib/i18n/locales/sv-SE.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/sv-SE.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/tr-TR.json b/site/src/lib/i18n/locales/tr-TR.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/tr-TR.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/uk-UA.json b/site/src/lib/i18n/locales/uk-UA.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/uk-UA.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/vi-VN.json b/site/src/lib/i18n/locales/vi-VN.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/vi-VN.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/zh-CN.json b/site/src/lib/i18n/locales/zh-CN.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/zh-CN.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/lib/i18n/locales/zh-TW.json b/site/src/lib/i18n/locales/zh-TW.json new file mode 100644 index 0000000..ccfb76c --- /dev/null +++ b/site/src/lib/i18n/locales/zh-TW.json @@ -0,0 +1,15 @@ +{ + "loginTitle": "Welcome back, login with", + "loginDivider": "Or continue with password", + "loginUsername": "Username", + "loginPassword": "Password", + "loginSubmit": "Login", + "loginFailTitle": "Failed to login", + "loginFailSubtitle": "Please check your username and password", + "loginSuccessTitle": "Logged in", + "loginSuccessSubtitle": "Welcome back!", + "loginOauthFailTitle": "Internal error", + "loginOauthFailSubtitle": "Failed to get OAuth URL", + "loginOauthSuccessTitle": "Redirecting", + "loginOauthSuccessSubtitle": "Redirecting to your OAuth provider" +} \ No newline at end of file diff --git a/site/src/main.tsx b/site/src/main.tsx index 270ee05..ac776a2 100644 --- a/site/src/main.tsx +++ b/site/src/main.tsx @@ -17,6 +17,7 @@ import { UnauthorizedPage } from "./pages/unauthorized-page.tsx"; import { InternalServerError } from "./pages/internal-server-error.tsx"; import { TotpPage } from "./pages/totp-page.tsx"; import { AppContextProvider } from "./context/app-context.tsx"; +import "./lib/i18n/i18n.ts"; const queryClient = new QueryClient({ defaultOptions: { diff --git a/site/src/pages/continue-page.tsx b/site/src/pages/continue-page.tsx index 54b601e..41582b3 100644 --- a/site/src/pages/continue-page.tsx +++ b/site/src/pages/continue-page.tsx @@ -6,6 +6,7 @@ import { Layout } from "../components/layouts/layout"; import { ReactNode } from "react"; import { isQueryValid } from "../utils/utils"; import { useAppContext } from "../context/app-context"; +import { Trans, useTranslation } from "react-i18next"; export const ContinuePage = () => { const queryString = window.location.search; @@ -14,6 +15,7 @@ export const ContinuePage = () => { const { isLoggedIn } = useUserContext(); const { disableContinue } = useAppContext(); + const { t } = useTranslation(); if (!isLoggedIn) { return ; @@ -25,8 +27,8 @@ export const ContinuePage = () => { const redirect = () => { notifications.show({ - title: "Redirecting", - message: "You should be redirected to the app soon", + title: t("continueRedirectingTitle"), + message: t("continueRedirectingSubtitle"), color: "blue", }); setTimeout(() => { @@ -42,12 +44,9 @@ export const ContinuePage = () => { return ( - Invalid Redirect - - - The redirect URL is invalid, please contact the app owner to fix the - issue. + {t("Invalid redirect")} + {t("The redirect URL is invalid")} ); } @@ -57,9 +56,9 @@ export const ContinuePage = () => { return ( - Redirecting + {t("continueRedirectingTitle")} - You should be redirected to your app soon. + {t("continueRedirectingSubtitle")} ); } @@ -68,14 +67,17 @@ export const ContinuePage = () => { return ( - Insecure Redirect + {t("continueInsecureRedirectTitle")} - Your are trying to redirect from https to{" "} - http, are you sure you want to continue? + }} + /> ); @@ -84,11 +86,11 @@ export const ContinuePage = () => { return ( - Continue + {t("continueTitle")} - Click the button to continue to your app. + {t("continueSubtitle")} ); diff --git a/site/src/pages/internal-server-error.tsx b/site/src/pages/internal-server-error.tsx index b841409..7f1bca9 100644 --- a/site/src/pages/internal-server-error.tsx +++ b/site/src/pages/internal-server-error.tsx @@ -1,19 +1,18 @@ import { Button, Paper, Text } from "@mantine/core"; import { Layout } from "../components/layouts/layout"; +import { useTranslation } from "react-i18next"; export const InternalServerError = () => { + const { t } = useTranslation(); return ( - Internal Server Error - - - An error occured on the server and it currently cannot serve your - request. + {t("internalErrorTitle")} + {t("internalErrorSubtitle")} diff --git a/site/src/pages/login-page.tsx b/site/src/pages/login-page.tsx index 5f6bd16..35f6609 100644 --- a/site/src/pages/login-page.tsx +++ b/site/src/pages/login-page.tsx @@ -10,6 +10,7 @@ import { LoginFormValues } from "../schemas/login-schema"; import { LoginForm } from "../components/auth/login-forn"; import { isQueryValid } from "../utils/utils"; import { useAppContext } from "../context/app-context"; +import { useTranslation } from "react-i18next"; export const LoginPage = () => { const queryString = window.location.search; @@ -18,6 +19,7 @@ export const LoginPage = () => { const { isLoggedIn } = useUserContext(); const { configuredProviders, title, genericName } = useAppContext(); + const { t } = useTranslation(); const oauthProviders = configuredProviders.filter( (value) => value !== "username", @@ -33,8 +35,8 @@ export const LoginPage = () => { }, onError: () => { notifications.show({ - title: "Failed to login", - message: "Check your username and password", + title: t("loginFailTitle"), + message: t("loginFailSubtitle"), color: "red", }); }, @@ -45,8 +47,8 @@ export const LoginPage = () => { } notifications.show({ - title: "Logged in", - message: "Welcome back!", + title: t("loginSuccessTitle"), + message: t("loginSuccessSubtitle"), color: "green", }); @@ -69,15 +71,15 @@ export const LoginPage = () => { }, onError: () => { notifications.show({ - title: "Internal error", - message: "Failed to get OAuth URL", + title: t("loginOauthFailTitle"), + message: t("loginOauthFailSubtitle"), color: "red", }); }, onSuccess: (data) => { notifications.show({ - title: "Redirecting", - message: "Redirecting to your OAuth provider", + title: t("loginOauthSuccessTitle"), + message: t("loginOauthSuccessSubtitle"), color: "blue", }); setTimeout(() => { @@ -97,7 +99,7 @@ export const LoginPage = () => { {oauthProviders.length > 0 && ( <> - Welcome back, login with + {t("loginTitle")} { /> {configuredProviders.includes("username") && ( diff --git a/site/src/pages/logout-page.tsx b/site/src/pages/logout-page.tsx index 7ae98de..edc597d 100644 --- a/site/src/pages/logout-page.tsx +++ b/site/src/pages/logout-page.tsx @@ -7,10 +7,12 @@ import { Navigate } from "react-router"; import { Layout } from "../components/layouts/layout"; import { capitalize } from "../utils/utils"; import { useAppContext } from "../context/app-context"; +import { Trans, useTranslation } from "react-i18next"; export const LogoutPage = () => { const { isLoggedIn, username, oauth, provider } = useUserContext(); const { genericName } = useAppContext(); + const { t } = useTranslation(); if (!isLoggedIn) { return ; @@ -22,15 +24,15 @@ export const LogoutPage = () => { }, onError: () => { notifications.show({ - title: "Failed to logout", - message: "Please try again", + title: t("logoutFailTitle"), + message: t("logoutFailSubtitle"), color: "red", }); }, onSuccess: () => { notifications.show({ - title: "Logged out", - message: "Goodbye!", + title: t("logoutSuccessTitle"), + message: t("logoutSuccessSubtitle"), color: "green", }); setTimeout(() => { @@ -43,13 +45,30 @@ export const LogoutPage = () => { - Logout + {t("logoutTitle")} - You are currently logged in as {username} - {oauth && - ` using ${capitalize(provider === "generic" ? genericName : provider)} OAuth`} - . Click the button below to log out. + {oauth ? ( + }} + values={{ + provider: + provider === "generic" ? genericName : capitalize(provider), + username: username, + }} + /> + ) : ( + }} + values={{ + username: username, + }} + /> + )} diff --git a/site/src/pages/not-found-page.tsx b/site/src/pages/not-found-page.tsx index 30f2587..ab3d3fd 100644 --- a/site/src/pages/not-found-page.tsx +++ b/site/src/pages/not-found-page.tsx @@ -1,16 +1,18 @@ import { Button, Paper, Text } from "@mantine/core"; import { Layout } from "../components/layouts/layout"; +import { useTranslation } from "react-i18next"; export const NotFoundPage = () => { + const { t } = useTranslation(); return ( - Not found + {t("notFoundTitle")} - The page you are looking for does not exist. + {t("notFoundSubtitle")} diff --git a/site/src/pages/totp-page.tsx b/site/src/pages/totp-page.tsx index d97708c..1724535 100644 --- a/site/src/pages/totp-page.tsx +++ b/site/src/pages/totp-page.tsx @@ -7,6 +7,7 @@ import { useMutation } from "@tanstack/react-query"; import axios from "axios"; import { notifications } from "@mantine/notifications"; import { useAppContext } from "../context/app-context"; +import { useTranslation } from "react-i18next"; export const TotpPage = () => { const queryString = window.location.search; @@ -15,6 +16,7 @@ export const TotpPage = () => { const { totpPending, isLoggedIn } = useUserContext(); const { title } = useAppContext(); + const { t } = useTranslation(); if (isLoggedIn) { return ; @@ -30,15 +32,15 @@ export const TotpPage = () => { }, onError: () => { notifications.show({ - title: "Failed to verify code", - message: "Please try again", + title: t("totpFailTitle"), + message: t("totpFailSubtitle"), color: "red", }); }, onSuccess: () => { notifications.show({ - title: "Verified", - message: "Redirecting to your app", + title: t("totpSuccessTitle"), + message: t("totpSuccessSubtitle"), color: "green", }); setTimeout(() => { @@ -52,7 +54,7 @@ export const TotpPage = () => { {title} - Enter your TOTP code + {t("totpTitle")} { const queryString = window.location.search; @@ -9,6 +10,8 @@ export const UnauthorizedPage = () => { const username = params.get("username") ?? ""; const resource = params.get("resource") ?? ""; + const { t } = useTranslation(); + if (!isQueryValid(username)) { return ; } @@ -17,16 +20,26 @@ export const UnauthorizedPage = () => { - Unauthorized + {t("Unauthorized")} - The user with username {username} is not authorized to{" "} {isQueryValid(resource) ? ( - - access the {resource} resource. - + + }} + values={{ resource, username }} + /> + ) : ( - "login." + + + )}