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 fafe5b4..c4037f6 100755 Binary files a/site/bun.lockb and b/site/bun.lockb differ 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." + + + )}