feat: Add visitor mode in LoginPage component

This commit is contained in:
Peifan Li
2026-01-03 16:24:13 -05:00
parent b6fbf015a3
commit 44b24543d0
11 changed files with 238 additions and 138 deletions

View File

@@ -24,6 +24,7 @@ import AlertModal from '../components/AlertModal';
import ConfirmationModal from '../components/ConfirmationModal';
import { useAuth } from '../contexts/AuthContext';
import { useLanguage } from '../contexts/LanguageContext';
import { useVisitorMode } from '../contexts/VisitorModeContext';
import getTheme from '../theme';
import { getWebAuthnErrorTranslationKey } from '../utils/translations';
@@ -42,6 +43,7 @@ const LoginPage: React.FC = () => {
const [resetPasswordCooldown, setResetPasswordCooldown] = useState(0); // in milliseconds
const { t } = useLanguage();
const { login } = useAuth();
const { visitorMode } = useVisitorMode();
const queryClient = useQueryClient();
// Fetch website name and settings from settings
@@ -398,7 +400,12 @@ const LoginPage: React.FC = () => {
<Typography variant="h4" sx={{ fontWeight: 'bold', lineHeight: 1 }}>
{websiteName}
</Typography>
{websiteName !== 'MyTube' && (
{visitorMode && (
<Typography variant="caption" color="text.secondary" sx={{ fontSize: '0.75rem', lineHeight: 1.2, mt: 0.5 }}>
{t('visitorMode')}
</Typography>
)}
{websiteName !== 'MyTube' && !visitorMode && (
<Typography variant="caption" color="text.secondary" sx={{ fontSize: '0.65rem', lineHeight: 1.2, mt: 0.25 }}>
Powered by MyTube
</Typography>
@@ -453,7 +460,7 @@ const LoginPage: React.FC = () => {
>
{loginMutation.isPending ? (t('verifying') || 'Verifying...') : t('signIn')}
</Button>
{passkeysExist && (
{passkeysExist && !visitorMode && (
<>
<Divider sx={{ my: 2 }}>OR</Divider>
<Button
@@ -472,7 +479,7 @@ const LoginPage: React.FC = () => {
)}
</>
)}
{!passwordLoginAllowed && passkeysExist && (
{!passwordLoginAllowed && passkeysExist && !visitorMode && (
<Button
fullWidth
variant="contained"
@@ -486,7 +493,7 @@ const LoginPage: React.FC = () => {
: (t('loginWithPasskey') || 'Login with Passkey')}
</Button>
)}
{allowResetPassword && (
{allowResetPassword && !visitorMode && (
<Button
fullWidth
variant="outlined"

View File

@@ -53,9 +53,11 @@ export const ar = {
columnsCount: "{count} أعمدة",
enableLogin: "تفعيل حماية تسجيل الدخول",
allowPasswordLogin: "السماح بتسجيل الدخول بكلمة المرور",
allowPasswordLoginHelper: "عند التعطيل، لن يكون تسجيل الدخول بكلمة المرور متاحًا. يجب أن يكون لديك مفتاح وصول واحد على الأقل لتعطيل تسجيل الدخول بكلمة المرور.",
allowPasswordLoginHelper:
"عند التعطيل، لن يكون تسجيل الدخول بكلمة المرور متاحًا. يجب أن يكون لديك مفتاح وصول واحد على الأقل لتعطيل تسجيل الدخول بكلمة المرور.",
allowResetPassword: "السماح بإعادة تعيين كلمة المرور",
allowResetPasswordHelper: "عند التعطيل، لن يتم عرض زر إعادة تعيين كلمة المرور في صفحة تسجيل الدخول وستتم حظر واجهة برمجة تطبيقات إعادة تعيين كلمة المرور.",
allowResetPasswordHelper:
"عند التعطيل، لن يتم عرض زر إعادة تعيين كلمة المرور في صفحة تسجيل الدخول وستتم حظر واجهة برمجة تطبيقات إعادة تعيين كلمة المرور.",
password: "كلمة المرور",
enterPassword: "أدخل كلمة المرور",
togglePasswordVisibility: "تبديل رؤية كلمة المرور",
@@ -314,8 +316,10 @@ export const ar = {
resetPasswordConfirm: "إعادة التعيين",
resetPasswordSuccess:
"تم إعادة تعيين كلمة المرور. تحقق من سجلات الخادم للحصول على كلمة المرور الجديدة.",
resetPasswordDisabledInfo: "تم تعطيل إعادة تعيين كلمة المرور. لإعادة تعيين كلمة المرور، قم بتشغيل الأمر التالي في دليل الخادم:\n\nnpm run reset-password\n\nأو:\n\nts-node scripts/reset-password.ts\n\nسيؤدي هذا إلى إنشاء كلمة مرور عشوائية جديدة وتمكين تسجيل الدخول بكلمة المرور.",
resetPasswordScriptGuide: "لإعادة تعيين كلمة المرور يدوياً، قم بتشغيل الأمر التالي في دليل الخادم:\n\nnpm run reset-password\n\nأو:\n\nts-node scripts/reset-password.ts\n\nإذا لم يتم توفير كلمة مرور، سيتم إنشاء كلمة مرور عشوائية مكونة من 8 أحرف.",
resetPasswordDisabledInfo:
"تم تعطيل إعادة تعيين كلمة المرور. لإعادة تعيين كلمة المرور، قم بتشغيل الأمر التالي في دليل الخادم:\n\nnpm run reset-password\n\nأو:\n\nts-node scripts/reset-password.ts\n\nسيؤدي هذا إلى إنشاء كلمة مرور عشوائية جديدة وتمكين تسجيل الدخول بكلمة المرور.",
resetPasswordScriptGuide:
"لإعادة تعيين كلمة المرور يدوياً، قم بتشغيل الأمر التالي في دليل الخادم:\n\nnpm run reset-password\n\nأو:\n\nts-node scripts/reset-password.ts\n\nإذا لم يتم توفير كلمة مرور، سيتم إنشاء كلمة مرور عشوائية مكونة من 8 أحرف.",
waitTimeMessage: "يرجى الانتظار {time} قبل المحاولة مرة أخرى.",
tooManyAttempts: "محاولات فاشلة كثيرة جداً.",
// Passkeys
@@ -332,12 +336,15 @@ export const ar = {
loginWithPasskey: "تسجيل الدخول بمفتاح المرور",
authenticating: "جاري المصادقة...",
passkeyLoginFailed: "فشلت مصادقة مفتاح المرور. يرجى المحاولة مرة أخرى.",
passkeyErrorPermissionDenied: "لا يُسمح بالطلب من قبل وكيل المستخدم أو المنصة في السياق الحالي، ربما لأن المستخدم رفض الإذن.",
passkeyErrorPermissionDenied:
"لا يُسمح بالطلب من قبل وكيل المستخدم أو المنصة في السياق الحالي، ربما لأن المستخدم رفض الإذن.",
passkeyErrorAlreadyRegistered: "تم تسجيل المصادق مسبقاً.",
linkCopied: "تم نسخ الرابط إلى الحافظة",
copyFailed: "فشل نسخ الرابط",
passkeyRequiresHttps: "يتطلب WebAuthn استخدام HTTPS أو localhost. يرجى الدخول إلى التطبيق عبر HTTPS أو استخدام localhost بدلاً من عنوان IP.",
passkeyWebAuthnNotSupported: "WebAuthn غير مدعوم في هذا المتصفح. يرجى استخدام متصفح حديث يدعم WebAuthn.",
passkeyRequiresHttps:
"يتطلب WebAuthn استخدام HTTPS أو localhost. يرجى الدخول إلى التطبيق عبر HTTPS أو استخدام localhost بدلاً من عنوان IP.",
passkeyWebAuthnNotSupported:
"WebAuthn غير مدعوم في هذا المتصفح. يرجى استخدام متصفح حديث يدعم WebAuthn.",
// Collection Page
loadingCollection: "جاري تحميل المجموعة...",

View File

@@ -52,9 +52,11 @@ export const de = {
columnsCount: "{count} Spalten",
enableLogin: "Anmeldeschutz aktivieren",
allowPasswordLogin: "Passwort-Anmeldung zulassen",
allowPasswordLoginHelper: "Wenn deaktiviert, ist die Passwort-Anmeldung nicht verfügbar. Sie müssen mindestens einen Passkey haben, um die Passwort-Anmeldung zu deaktivieren.",
allowPasswordLoginHelper:
"Wenn deaktiviert, ist die Passwort-Anmeldung nicht verfügbar. Sie müssen mindestens einen Passkey haben, um die Passwort-Anmeldung zu deaktivieren.",
allowResetPassword: "Passwort zurücksetzen zulassen",
allowResetPasswordHelper: "Wenn deaktiviert, wird die Schaltfläche zum Zurücksetzen des Passworts auf der Anmeldeseite nicht angezeigt und die API zum Zurücksetzen des Passworts wird blockiert.",
allowResetPasswordHelper:
"Wenn deaktiviert, wird die Schaltfläche zum Zurücksetzen des Passworts auf der Anmeldeseite nicht angezeigt und die API zum Zurücksetzen des Passworts wird blockiert.",
password: "Passwort",
enterPassword: "Passwort eingeben",
togglePasswordVisibility: "Passwort sichtbar machen",
@@ -314,8 +316,10 @@ export const de = {
resetPasswordConfirm: "Zurücksetzen",
resetPasswordSuccess:
"Das Passwort wurde zurückgesetzt. Überprüfen Sie die Backend-Protokolle für das neue Passwort.",
resetPasswordDisabledInfo: "Die Passwort-Zurücksetzung ist deaktiviert. Um Ihr Passwort zurückzusetzen, führen Sie den folgenden Befehl im Backend-Verzeichnis aus:\n\nnpm run reset-password\n\nOder:\n\nts-node scripts/reset-password.ts\n\nDies generiert ein neues zufälliges Passwort und aktiviert die Passwort-Anmeldung.",
resetPasswordScriptGuide: "Um das Passwort manuell zurückzusetzen, führen Sie den folgenden Befehl im Backend-Verzeichnis aus:\n\nnpm run reset-password\n\nOder:\n\nts-node scripts/reset-password.ts\n\nWenn kein Passwort angegeben wird, wird ein zufälliges 8-stelliges Passwort generiert.",
resetPasswordDisabledInfo:
"Die Passwort-Zurücksetzung ist deaktiviert. Um Ihr Passwort zurückzusetzen, führen Sie den folgenden Befehl im Backend-Verzeichnis aus:\n\nnpm run reset-password\n\nOder:\n\nts-node scripts/reset-password.ts\n\nDies generiert ein neues zufälliges Passwort und aktiviert die Passwort-Anmeldung.",
resetPasswordScriptGuide:
"Um das Passwort manuell zurückzusetzen, führen Sie den folgenden Befehl im Backend-Verzeichnis aus:\n\nnpm run reset-password\n\nOder:\n\nts-node scripts/reset-password.ts\n\nWenn kein Passwort angegeben wird, wird ein zufälliges 8-stelliges Passwort generiert.",
waitTimeMessage: "Bitte warten Sie {time}, bevor Sie es erneut versuchen.",
tooManyAttempts: "Zu viele fehlgeschlagene Versuche.",
// Passkeys
@@ -335,12 +339,16 @@ export const de = {
authenticating: "Wird authentifiziert...",
passkeyLoginFailed:
"Passkey-Authentifizierung fehlgeschlagen. Bitte versuchen Sie es erneut.",
passkeyErrorPermissionDenied: "Die Anfrage wird vom Benutzer-Agenten oder der Plattform im aktuellen Kontext nicht zugelassen, möglicherweise weil der Benutzer die Berechtigung verweigert hat.",
passkeyErrorAlreadyRegistered: "Der Authentifikator wurde bereits zuvor registriert.",
passkeyErrorPermissionDenied:
"Die Anfrage wird vom Benutzer-Agenten oder der Plattform im aktuellen Kontext nicht zugelassen, möglicherweise weil der Benutzer die Berechtigung verweigert hat.",
passkeyErrorAlreadyRegistered:
"Der Authentifikator wurde bereits zuvor registriert.",
linkCopied: "Link in die Zwischenablage kopiert",
copyFailed: "Link konnte nicht kopiert werden",
passkeyRequiresHttps: "WebAuthn erfordert HTTPS oder localhost. Bitte greifen Sie über HTTPS auf die Anwendung zu oder verwenden Sie localhost anstelle einer IP-Adresse.",
passkeyWebAuthnNotSupported: "WebAuthn wird in diesem Browser nicht unterstützt. Bitte verwenden Sie einen modernen Browser, der WebAuthn unterstützt.",
passkeyRequiresHttps:
"WebAuthn erfordert HTTPS oder localhost. Bitte greifen Sie über HTTPS auf die Anwendung zu oder verwenden Sie localhost anstelle einer IP-Adresse.",
passkeyWebAuthnNotSupported:
"WebAuthn wird in diesem Browser nicht unterstützt. Bitte verwenden Sie einen modernen Browser, der WebAuthn unterstützt.",
loadingCollection: "Sammlung wird geladen...",
collectionNotFound: "Sammlung nicht gefunden",
noVideosInCollection: "Keine Videos in dieser Sammlung.",

View File

@@ -53,9 +53,11 @@ export const en = {
columnsCount: "{count} Columns",
enableLogin: "Enable Login Protection",
allowPasswordLogin: "Allow Password Login",
allowPasswordLoginHelper: "When disabled, password login is not available. You must have at least one passkey to disable password login.",
allowPasswordLoginHelper:
"When disabled, password login is not available. You must have at least one passkey to disable password login.",
allowResetPassword: "Allow Reset Password",
allowResetPasswordHelper: "When disabled, the reset password button will not be shown on the login page and the reset password API will be blocked.",
allowResetPasswordHelper:
"When disabled, the reset password button will not be shown on the login page and the reset password API will be blocked.",
password: "Password",
enterPassword: "Enter Password",
togglePasswordVisibility: "Toggle password visibility",
@@ -120,24 +122,28 @@ export const en = {
"This will permanently delete all .ytdl and .part files in the uploads directory. Make sure there are no active downloads before proceeding.",
// Task Hooks
taskHooks: 'Task Hooks',
taskHooksDescription: 'Execute custom shell commands at specific points in the task lifecycle. Available environment variables: MYTUBE_TASK_ID, MYTUBE_TASK_TITLE, MYTUBE_SOURCE_URL, MYTUBE_VIDEO_PATH.',
taskHooksWarning: 'Warning: Commands run with the server\'s permissions. Use with caution.',
hookTaskBeforeStart: 'Before Task Start',
hookTaskBeforeStartHelper: 'Executes before the download begins.',
hookTaskSuccess: 'Task Success',
hookTaskSuccessHelper: 'Executes after successful download, before cloud upload/deletion (awaits completion).',
hookTaskFail: 'Task Failed',
hookTaskFailHelper: 'Executes when a task fails.',
hookTaskCancel: 'Task Cancelled',
hookTaskCancelHelper: 'Executes when a task is manually cancelled.',
found: 'Found',
notFound: 'Not Set',
deleteHook: 'Delete Hook Script',
confirmDeleteHook: 'Are you sure you want to delete this hook script?',
uploadHook: 'Upload .sh',
enterPasswordToUploadHook: 'Please enter your password to upload this hook script.',
riskCommandDetected: 'Risk command detected: {command}. Upload rejected.',
taskHooks: "Task Hooks",
taskHooksDescription:
"Execute custom shell commands at specific points in the task lifecycle. Available environment variables: MYTUBE_TASK_ID, MYTUBE_TASK_TITLE, MYTUBE_SOURCE_URL, MYTUBE_VIDEO_PATH.",
taskHooksWarning:
"Warning: Commands run with the server's permissions. Use with caution.",
hookTaskBeforeStart: "Before Task Start",
hookTaskBeforeStartHelper: "Executes before the download begins.",
hookTaskSuccess: "Task Success",
hookTaskSuccessHelper:
"Executes after successful download, before cloud upload/deletion (awaits completion).",
hookTaskFail: "Task Failed",
hookTaskFailHelper: "Executes when a task fails.",
hookTaskCancel: "Task Cancelled",
hookTaskCancelHelper: "Executes when a task is manually cancelled.",
found: "Found",
notFound: "Not Set",
deleteHook: "Delete Hook Script",
confirmDeleteHook: "Are you sure you want to delete this hook script?",
uploadHook: "Upload .sh",
enterPasswordToUploadHook:
"Please enter your password to upload this hook script.",
riskCommandDetected: "Risk command detected: {command}. Upload rejected.",
cleanupTempFilesActiveDownloads:
"Cannot clean up temporary files while downloads are active. Please wait for all downloads to complete or cancel them first.",
formatFilenamesSuccess:
@@ -214,9 +220,11 @@ export const en = {
uploadingVideo: "Uploading: {title}",
clearThumbnailCache: "Clear Thumbnail Local Cache",
clearing: "Clearing...",
clearThumbnailCacheSuccess: "Thumbnail cache cleared successfully. Thumbnails will be regenerated when accessed next time.",
clearThumbnailCacheSuccess:
"Thumbnail cache cleared successfully. Thumbnails will be regenerated when accessed next time.",
clearThumbnailCacheError: "Failed to clear thumbnail cache",
clearThumbnailCacheConfirmMessage: "This will clear all locally cached thumbnails for cloud videos. Thumbnails will be regenerated from cloud storage when accessed next time. Continue?",
clearThumbnailCacheConfirmMessage:
"This will clear all locally cached thumbnails for cloud videos. Thumbnails will be regenerated from cloud storage when accessed next time. Continue?",
// Manage
manageContent: "Manage Content",
@@ -328,8 +336,10 @@ export const en = {
resetPasswordConfirm: "Reset",
resetPasswordSuccess:
"Password has been reset. Check backend logs for the new password.",
resetPasswordDisabledInfo: "Password reset is disabled. To reset your password, run the following command in the backend directory:\n\nnpm run reset-password\n\nOr:\n\nts-node scripts/reset-password.ts\n\nThis will generate a new random password and enable password login.",
resetPasswordScriptGuide: "To reset password manually, run the following command in the backend directory:\n\nnpm run reset-password\n\nOr:\n\nts-node scripts/reset-password.ts\n\nIf no password is provided, a random 8-character password will be generated.",
resetPasswordDisabledInfo:
"Password reset is disabled. To reset your password, run the following command in the backend directory:\n\nnpm run reset-password\n\nOr:\n\nts-node scripts/reset-password.ts\n\nThis will generate a new random password and enable password login.",
resetPasswordScriptGuide:
"To reset password manually, run the following command in the backend directory:\n\nnpm run reset-password\n\nOr:\n\nts-node scripts/reset-password.ts\n\nIf no password is provided, a random 8-character password will be generated.",
waitTimeMessage: "Please wait {time} before trying again.",
tooManyAttempts: "Too many failed attempts.",
// Passkeys
@@ -337,17 +347,21 @@ export const en = {
creatingPasskey: "Creating...",
passkeyCreated: "Passkey created successfully",
passkeyCreationFailed: "Failed to create passkey. Please try again.",
passkeyWebAuthnNotSupported: "WebAuthn is not supported in this browser. Please use a modern browser that supports WebAuthn.",
passkeyRequiresHttps: "WebAuthn requires HTTPS or localhost. Please access the application via HTTPS or use localhost instead of an IP address.",
passkeyWebAuthnNotSupported:
"WebAuthn is not supported in this browser. Please use a modern browser that supports WebAuthn.",
passkeyRequiresHttps:
"WebAuthn requires HTTPS or localhost. Please access the application via HTTPS or use localhost instead of an IP address.",
removePasskeys: "Remove All Passkeys",
removePasskeysTitle: "Remove All Passkeys",
removePasskeysMessage: "Are you sure you want to remove all passkeys? This action cannot be undone.",
removePasskeysMessage:
"Are you sure you want to remove all passkeys? This action cannot be undone.",
passkeysRemoved: "All passkeys have been removed",
passkeysRemoveFailed: "Failed to remove passkeys. Please try again.",
loginWithPasskey: "Login with Passkey",
authenticating: "Authenticating...",
passkeyLoginFailed: "Passkey authentication failed. Please try again.",
passkeyErrorPermissionDenied: "The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.",
passkeyErrorPermissionDenied:
"The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.",
passkeyErrorAlreadyRegistered: "The authenticator was previously registered.",
linkCopied: "Link copied to clipboard",
copyFailed: "Failed to copy link",
@@ -419,7 +433,8 @@ export const en = {
authorOrPlaylist: "Author / Playlist",
playlistDetected: "Playlist Detected",
playlistHasVideos: "This playlist has {count} videos.",
downloadPlaylistAndCreateCollection: "Download playlist videos and create a Collection for it?",
downloadPlaylistAndCreateCollection:
"Download playlist videos and create a Collection for it?",
playlistDownloadStarted: "Playlist download started",
collectionHasVideos: "This Bilibili collection has {count} videos.",
seriesHasVideos: "This Bilibili series has {count} videos.",
@@ -633,7 +648,8 @@ export const en = {
cloudflaredTunnel: "Cloudflare Tunnel",
enableCloudflaredTunnel: "Enable Cloudflare Tunnel",
cloudflaredToken: "Tunnel Token (Optional)",
cloudflaredTokenHelper: "Paste your tunnel token here, or leave empty to use a random Quick Tunnel.",
cloudflaredTokenHelper:
"Paste your tunnel token here, or leave empty to use a random Quick Tunnel.",
waitingForUrl: "Waiting for Quick Tunnel URL...",
running: "Running",
stopped: "Stopped",
@@ -641,8 +657,10 @@ export const en = {
accountTag: "Account Tag",
copied: "Copied!",
clickToCopy: "Click to copy",
quickTunnelWarning: "Quick Tunnel URLs change every time the tunnel restarts.",
managedInDashboard: "Public hostname is managed in your Cloudflare Zero Trust Dashboard.",
quickTunnelWarning:
"Quick Tunnel URLs change every time the tunnel restarts.",
managedInDashboard:
"Public hostname is managed in your Cloudflare Zero Trust Dashboard.",
// Database Export/Import
exportImportDatabase: "Export/Import Database",
@@ -673,5 +691,4 @@ export const en = {
noBackupAvailable: "No backup available",
failedToDownloadVideo: "Failed to download video. Please try again.",
failedToDownload: "Failed to download. Please try again.",
};

View File

@@ -63,9 +63,11 @@ export const es = {
columnsCount: "{count} Columnas",
enableLogin: "Habilitar Protección de Inicio de Sesión",
allowPasswordLogin: "Permitir Inicio de Sesión con Contraseña",
allowPasswordLoginHelper: "Cuando está deshabilitado, el inicio de sesión con contraseña no está disponible. Debe tener al menos una clave de acceso para deshabilitar el inicio de sesión con contraseña.",
allowPasswordLoginHelper:
"Cuando está deshabilitado, el inicio de sesión con contraseña no está disponible. Debe tener al menos una clave de acceso para deshabilitar el inicio de sesión con contraseña.",
allowResetPassword: "Permitir Restablecer Contraseña",
allowResetPasswordHelper: "Cuando está deshabilitado, el botón de restablecer contraseña no se mostrará en la página de inicio de sesión y la API de restablecer contraseña será bloqueada.",
allowResetPasswordHelper:
"Cuando está deshabilitado, el botón de restablecer contraseña no se mostrará en la página de inicio de sesión y la API de restablecer contraseña será bloqueada.",
password: "Contraseña",
enterPassword: "Introducir contraseña",
togglePasswordVisibility: "Alternar visibilidad de contraseña",
@@ -337,8 +339,10 @@ export const es = {
resetPasswordConfirm: "Restablecer",
resetPasswordSuccess:
"La contraseña ha sido restablecida. Consulte los registros del backend para obtener la nueva contraseña.",
resetPasswordDisabledInfo: "El restablecimiento de contraseña está deshabilitado. Para restablecer su contraseña, ejecute el siguiente comando en el directorio del backend:\n\nnpm run reset-password\n\nO:\n\nts-node scripts/reset-password.ts\n\nEsto generará una nueva contraseña aleatoria y habilitará el inicio de sesión con contraseña.",
resetPasswordScriptGuide: "Para restablecer la contraseña manualmente, ejecute el siguiente comando en el directorio del backend:\n\nnpm run reset-password\n\nO:\n\nts-node scripts/reset-password.ts\n\nSi no se proporciona una contraseña, se generará una contraseña aleatoria de 8 caracteres.",
resetPasswordDisabledInfo:
"El restablecimiento de contraseña está deshabilitado. Para restablecer su contraseña, ejecute el siguiente comando en el directorio del backend:\n\nnpm run reset-password\n\nO:\n\nts-node scripts/reset-password.ts\n\nEsto generará una nueva contraseña aleatoria y habilitará el inicio de sesión con contraseña.",
resetPasswordScriptGuide:
"Para restablecer la contraseña manualmente, ejecute el siguiente comando en el directorio del backend:\n\nnpm run reset-password\n\nO:\n\nts-node scripts/reset-password.ts\n\nSi no se proporciona una contraseña, se generará una contraseña aleatoria de 8 caracteres.",
waitTimeMessage: "Por favor espere {time} antes de intentar nuevamente.",
tooManyAttempts: "Demasiados intentos fallidos.",
// Passkeys
@@ -358,12 +362,16 @@ export const es = {
authenticating: "Autenticando...",
passkeyLoginFailed:
"Error en la autenticación con clave de acceso. Por favor, inténtelo de nuevo.",
passkeyErrorPermissionDenied: "La solicitud no está permitida por el agente de usuario o la plataforma en el contexto actual, posiblemente porque el usuario denegó el permiso.",
passkeyErrorAlreadyRegistered: "El autenticador ya estaba registrado previamente.",
passkeyErrorPermissionDenied:
"La solicitud no está permitida por el agente de usuario o la plataforma en el contexto actual, posiblemente porque el usuario denegó el permiso.",
passkeyErrorAlreadyRegistered:
"El autenticador ya estaba registrado previamente.",
linkCopied: "Enlace copiado al portapapeles",
copyFailed: "Error al copiar enlace",
passkeyRequiresHttps: "WebAuthn requiere HTTPS o localhost. Por favor, acceda a la aplicación a través de HTTPS o utilice localhost en lugar de una dirección IP.",
passkeyWebAuthnNotSupported: "WebAuthn no es compatible con este navegador. Por favor, utilice un navegador moderno que sea compatible con WebAuthn.",
passkeyRequiresHttps:
"WebAuthn requiere HTTPS o localhost. Por favor, acceda a la aplicación a través de HTTPS o utilice localhost en lugar de una dirección IP.",
passkeyWebAuthnNotSupported:
"WebAuthn no es compatible con este navegador. Por favor, utilice un navegador moderno que sea compatible con WebAuthn.",
// Collection Page: "Cargando colección...", collectionNotFound: "Colección no encontrada",
noVideosInCollection: "No hay videos en esta colección.",

View File

@@ -56,9 +56,11 @@ export const fr = {
columnsCount: "{count} Colonnes",
enableLogin: "Activer la protection par connexion",
allowPasswordLogin: "Autoriser la connexion par mot de passe",
allowPasswordLoginHelper: "Lorsqu'elle est désactivée, la connexion par mot de passe n'est pas disponible. Vous devez avoir au moins une clé d'accès pour désactiver la connexion par mot de passe.",
allowPasswordLoginHelper:
"Lorsqu'elle est désactivée, la connexion par mot de passe n'est pas disponible. Vous devez avoir au moins une clé d'accès pour désactiver la connexion par mot de passe.",
allowResetPassword: "Autoriser la réinitialisation du mot de passe",
allowResetPasswordHelper: "Lorsqu'elle est désactivée, le bouton de réinitialisation du mot de passe ne sera pas affiché sur la page de connexion et l'API de réinitialisation du mot de passe sera bloquée.",
allowResetPasswordHelper:
"Lorsqu'elle est désactivée, le bouton de réinitialisation du mot de passe ne sera pas affiché sur la page de connexion et l'API de réinitialisation du mot de passe sera bloquée.",
password: "Mot de passe",
enterPassword: "Entrez le mot de passe",
togglePasswordVisibility: "Afficher/Masquer le mot de passe",
@@ -337,8 +339,10 @@ export const fr = {
resetPasswordConfirm: "Réinitialiser",
resetPasswordSuccess:
"Le mot de passe a été réinitialisé. Consultez les journaux du backend pour le nouveau mot de passe.",
resetPasswordDisabledInfo: "La réinitialisation du mot de passe est désactivée. Pour réinitialiser votre mot de passe, exécutez la commande suivante dans le répertoire backend :\n\nnpm run reset-password\n\nOu :\n\nts-node scripts/reset-password.ts\n\nCela générera un nouveau mot de passe aléatoire et activera la connexion par mot de passe.",
resetPasswordScriptGuide: "Pour réinitialiser le mot de passe manuellement, exécutez la commande suivante dans le répertoire backend :\n\nnpm run reset-password\n\nOu :\n\nts-node scripts/reset-password.ts\n\nSi aucun mot de passe n'est fourni, un mot de passe aléatoire de 8 caractères sera généré.",
resetPasswordDisabledInfo:
"La réinitialisation du mot de passe est désactivée. Pour réinitialiser votre mot de passe, exécutez la commande suivante dans le répertoire backend :\n\nnpm run reset-password\n\nOu :\n\nts-node scripts/reset-password.ts\n\nCela générera un nouveau mot de passe aléatoire et activera la connexion par mot de passe.",
resetPasswordScriptGuide:
"Pour réinitialiser le mot de passe manuellement, exécutez la commande suivante dans le répertoire backend :\n\nnpm run reset-password\n\nOu :\n\nts-node scripts/reset-password.ts\n\nSi aucun mot de passe n'est fourni, un mot de passe aléatoire de 8 caractères sera généré.",
waitTimeMessage: "Veuillez attendre {time} avant de réessayer.",
tooManyAttempts: "Trop de tentatives échouées.",
// Passkeys
@@ -358,12 +362,16 @@ export const fr = {
authenticating: "Authentification en cours...",
passkeyLoginFailed:
"Échec de l'authentification par clé d'accès. Veuillez réessayer.",
passkeyErrorPermissionDenied: "La demande n'est pas autorisée par l'agent utilisateur ou la plateforme dans le contexte actuel, peut-être parce que l'utilisateur a refusé l'autorisation.",
passkeyErrorAlreadyRegistered: "L'authentificateur a déjà été enregistré précédemment.",
passkeyErrorPermissionDenied:
"La demande n'est pas autorisée par l'agent utilisateur ou la plateforme dans le contexte actuel, peut-être parce que l'utilisateur a refusé l'autorisation.",
passkeyErrorAlreadyRegistered:
"L'authentificateur a déjà été enregistré précédemment.",
linkCopied: "Lien copié dans le presse-papiers",
copyFailed: "Échec de la copie du lien",
passkeyRequiresHttps: "WebAuthn nécessite HTTPS ou localhost. Veuillez accéder à l'application via HTTPS ou utiliser localhost au lieu d'une adresse IP.",
passkeyWebAuthnNotSupported: "WebAuthn n'est pas supporté par ce navigateur. Veuillez utiliser un navigateur moderne qui supporte WebAuthn.",
passkeyRequiresHttps:
"WebAuthn nécessite HTTPS ou localhost. Veuillez accéder à l'application via HTTPS ou utiliser localhost au lieu d'une adresse IP.",
passkeyWebAuthnNotSupported:
"WebAuthn n'est pas supporté par ce navigateur. Veuillez utiliser un navigateur moderne qui supporte WebAuthn.",
// Collection Page
loadingCollection: "Chargement de la collection...",

View File

@@ -55,9 +55,11 @@ export const ja = {
columnsCount: "{count} 列",
enableLogin: "ログイン保護を有効にする",
allowPasswordLogin: "パスワードログインを許可",
allowPasswordLoginHelper: "無効にすると、パスワードログインは利用できません。パスワードログインを無効にするには、少なくとも1つのパスキーが必要です。",
allowPasswordLoginHelper:
"無効にすると、パスワードログインは利用できません。パスワードログインを無効にするには、少なくとも1つのパスキーが必要です。",
allowResetPassword: "パスワードリセットを許可",
allowResetPasswordHelper: "無効にすると、ログインページにパスワードリセットボタンが表示されず、パスワードリセットAPIがブロックされます。",
allowResetPasswordHelper:
"無効にすると、ログインページにパスワードリセットボタンが表示されず、パスワードリセットAPIがブロックされます。",
password: "パスワード",
enterPassword: "パスワードを入力",
togglePasswordVisibility: "パスワードの表示切り替え",
@@ -321,8 +323,10 @@ export const ja = {
resetPasswordConfirm: "リセット",
resetPasswordSuccess:
"パスワードがリセットされました。新しいパスワードについては、バックエンドログを確認してください。",
resetPasswordDisabledInfo: "パスワードリセットは無効になっています。パスワードをリセットするには、バックエンドディレクトリで次のコマンドを実行してください:\n\nnpm run reset-password\n\nまたは\n\nts-node scripts/reset-password.ts\n\nこれにより、新しいランダムパスワードが生成され、パスワードログインが有効になります。",
resetPasswordScriptGuide: "パスワードを手動でリセットするには、バックエンドディレクトリで次のコマンドを実行してください:\n\nnpm run reset-password\n\nまたは\n\nts-node scripts/reset-password.ts\n\nパスワードが提供されない場合、ランダムな8文字のパスワードが生成されます。",
resetPasswordDisabledInfo:
"パスワードリセットは無効になっています。パスワードをリセットするには、バックエンドディレクトリで次のコマンドを実行してください:\n\nnpm run reset-password\n\nまたは\n\nts-node scripts/reset-password.ts\n\nこれにより、新しいランダムパスワードが生成され、パスワードログインが有効になります。",
resetPasswordScriptGuide:
"パスワードを手動でリセットするには、バックエンドディレクトリで次のコマンドを実行してください:\n\nnpm run reset-password\n\nまたは\n\nts-node scripts/reset-password.ts\n\nパスワードが提供されない場合、ランダムな8文字のパスワードが生成されます。",
waitTimeMessage: "再試行する前に {time} お待ちください。",
tooManyAttempts: "失敗した試行が多すぎます。",
// Passkeys
@@ -341,12 +345,15 @@ export const ja = {
loginWithPasskey: "パスキーでログイン",
authenticating: "認証中...",
passkeyLoginFailed: "パスキー認証に失敗しました。もう一度お試しください。",
passkeyErrorPermissionDenied: "ユーザーエージェントまたはプラットフォームが現在のコンテキストでリクエストを許可していません。ユーザーが権限を拒否した可能性があります。",
passkeyErrorPermissionDenied:
"ユーザーエージェントまたはプラットフォームが現在のコンテキストでリクエストを許可していません。ユーザーが権限を拒否した可能性があります。",
passkeyErrorAlreadyRegistered: "認証器は以前に登録されています。",
linkCopied: "リンクをクリップボードにコピーしました",
copyFailed: "リンクのコピーに失敗しました",
passkeyRequiresHttps: "WebAuthnにはHTTPSまたはlocalhostが必要です。HTTPS経由でアプリケーションにアクセスするか、IPアドレスの代わりにlocalhostを使用してください。",
passkeyWebAuthnNotSupported: "このブラウザはWebAuthnをサポートしていません。WebAuthnをサポートする最新のブラウザを使用してください。",
passkeyRequiresHttps:
"WebAuthnにはHTTPSまたはlocalhostが必要です。HTTPS経由でアプリケーションにアクセスするか、IPアドレスの代わりにlocalhostを使用してください。",
passkeyWebAuthnNotSupported:
"このブラウザはWebAuthnをサポートしていません。WebAuthnをサポートする最新のブラウザを使用してください。",
// Collection Page
loadingCollection: "コレクションを読み込み中...",

View File

@@ -55,9 +55,11 @@ export const ko = {
columnsCount: "{count} 열",
enableLogin: "로그인 보호 활성화",
allowPasswordLogin: "비밀번호 로그인 허용",
allowPasswordLoginHelper: "비활성화되면 비밀번호 로그인을 사용할 수 없습니다. 비밀번호 로그인을 비활성화하려면 최소한 하나의 패스키가 있어야 합니다.",
allowPasswordLoginHelper:
"비활성화되면 비밀번호 로그인을 사용할 수 없습니다. 비밀번호 로그인을 비활성화하려면 최소한 하나의 패스키가 있어야 합니다.",
allowResetPassword: "비밀번호 재설정 허용",
allowResetPasswordHelper: "비활성화되면 로그인 페이지에 비밀번호 재설정 버튼이 표시되지 않고 비밀번호 재설정 API가 차단됩니다.",
allowResetPasswordHelper:
"비활성화되면 로그인 페이지에 비밀번호 재설정 버튼이 표시되지 않고 비밀번호 재설정 API가 차단됩니다.",
password: "비밀번호",
enterPassword: "비밀번호 입력",
togglePasswordVisibility: "비밀번호 표시 전환",
@@ -316,8 +318,10 @@ export const ko = {
resetPasswordConfirm: "재설정",
resetPasswordSuccess:
"비밀번호가 재설정되었습니다. 새 비밀번호는 백엔드 로그를 확인하세요.",
resetPasswordDisabledInfo: "비밀번호 재설정이 비활성화되어 있습니다. 비밀번호를 재설정하려면 백엔드 디렉토리에서 다음 명령을 실행하세요:\n\nnpm run reset-password\n\n또는:\n\nts-node scripts/reset-password.ts\n\n이렇게 하면 새로운 임의의 비밀번호가 생성되고 비밀번호 로그인이 활성화됩니다.",
resetPasswordScriptGuide: "비밀번호를 수동으로 재설정하려면 백엔드 디렉토리에서 다음 명령을 실행하세요:\n\nnpm run reset-password\n\n또는:\n\nts-node scripts/reset-password.ts\n\n비밀번호가 제공되지 않으면 임의의 8자 비밀번호가 생성됩니다.",
resetPasswordDisabledInfo:
"비밀번호 재설정이 비활성화되어 있습니다. 비밀번호를 재설정하려면 백엔드 디렉토리에서 다음 명령을 실행하세요:\n\nnpm run reset-password\n\n또는:\n\nts-node scripts/reset-password.ts\n\n이렇게 하면 새로운 임의의 비밀번호가 생성되고 비밀번호 로그인이 활성화됩니다.",
resetPasswordScriptGuide:
"비밀번호를 수동으로 재설정하려면 백엔드 디렉토리에서 다음 명령을 실행하세요:\n\nnpm run reset-password\n\n또는:\n\nts-node scripts/reset-password.ts\n\n비밀번호가 제공되지 않으면 임의의 8자 비밀번호가 생성됩니다.",
waitTimeMessage: "다시 시도하기 전에 {time} 기다려 주세요.",
tooManyAttempts: "실패한 시도가 너무 많습니다.",
// Passkeys
@@ -334,12 +338,15 @@ export const ko = {
loginWithPasskey: "패스키로 로그인",
authenticating: "인증 중...",
passkeyLoginFailed: "패스키 인증에 실패했습니다. 다시 시도해 주세요.",
passkeyErrorPermissionDenied: "사용자 에이전트 또는 플랫폼이 현재 컨텍스트에서 요청을 허용하지 않습니다. 사용자가 권한을 거부했을 수 있습니다.",
passkeyErrorPermissionDenied:
"사용자 에이전트 또는 플랫폼이 현재 컨텍스트에서 요청을 허용하지 않습니다. 사용자가 권한을 거부했을 수 있습니다.",
passkeyErrorAlreadyRegistered: "인증기가 이전에 등록되었습니다.",
linkCopied: "링크가 클립보드에 복사되었습니다",
copyFailed: "링크 복사 실패",
passkeyRequiresHttps: "WebAuthn은 HTTPS 또는 localhost가 필요합니다. HTTPS를 통해 애플리케이션에 액세스하거나 IP 주소 대신 localhost를 사용하십시오.",
passkeyWebAuthnNotSupported: "이 브라우저는 WebAuthn을 지원하지 않습니다. WebAuthn을 지원하는 최신 브라우저를 사용하십시오.",
passkeyRequiresHttps:
"WebAuthn은 HTTPS 또는 localhost가 필요합니다. HTTPS를 통해 애플리케이션에 액세스하거나 IP 주소 대신 localhost를 사용하십시오.",
passkeyWebAuthnNotSupported:
"이 브라우저는 WebAuthn을 지원하지 않습니다. WebAuthn을 지원하는 최신 브라우저를 사용하십시오.",
// Collection Page
loadingCollection: "컬렉션 로드 중...",

View File

@@ -56,9 +56,11 @@ export const pt = {
columnsCount: "{count} Colunas",
enableLogin: "Ativar Proteção de Login",
allowPasswordLogin: "Permitir Login com Senha",
allowPasswordLoginHelper: "Quando desabilitado, o login com senha não está disponível. Você deve ter pelo menos uma chave de acesso para desabilitar o login com senha.",
allowPasswordLoginHelper:
"Quando desabilitado, o login com senha não está disponível. Você deve ter pelo menos uma chave de acesso para desabilitar o login com senha.",
allowResetPassword: "Permitir Redefinir Senha",
allowResetPasswordHelper: "Quando desabilitado, o botão de redefinir senha não será exibido na página de login e a API de redefinir senha será bloqueada.",
allowResetPasswordHelper:
"Quando desabilitado, o botão de redefinir senha não será exibido na página de login e a API de redefinir senha será bloqueada.",
password: "Senha",
enterPassword: "Digite a senha",
togglePasswordVisibility: "Alternar visibilidade da senha",
@@ -332,8 +334,10 @@ export const pt = {
resetPasswordConfirm: "Redefinir",
resetPasswordSuccess:
"A senha foi redefinida. Verifique os logs do backend para a nova senha.",
resetPasswordDisabledInfo: "A redefinição de senha está desabilitada. Para redefinir sua senha, execute o seguinte comando no diretório do backend:\n\nnpm run reset-password\n\nOu:\n\nts-node scripts/reset-password.ts\n\nIsso gerará uma nova senha aleatória e habilitará o login com senha.",
resetPasswordScriptGuide: "Para redefinir a senha manualmente, execute o seguinte comando no diretório do backend:\n\nnpm run reset-password\n\nOu:\n\nts-node scripts/reset-password.ts\n\nSe nenhuma senha for fornecida, uma senha aleatória de 8 caracteres será gerada.",
resetPasswordDisabledInfo:
"A redefinição de senha está desabilitada. Para redefinir sua senha, execute o seguinte comando no diretório do backend:\n\nnpm run reset-password\n\nOu:\n\nts-node scripts/reset-password.ts\n\nIsso gerará uma nova senha aleatória e habilitará o login com senha.",
resetPasswordScriptGuide:
"Para redefinir a senha manualmente, execute o seguinte comando no diretório do backend:\n\nnpm run reset-password\n\nOu:\n\nts-node scripts/reset-password.ts\n\nSe nenhuma senha for fornecida, uma senha aleatória de 8 caracteres será gerada.",
waitTimeMessage: "Por favor, aguarde {time} antes de tentar novamente.",
tooManyAttempts: "Muitas tentativas falharam.",
// Passkeys
@@ -353,12 +357,16 @@ export const pt = {
authenticating: "Autenticando...",
passkeyLoginFailed:
"Falha na autenticação com chave de acesso. Por favor, tente novamente.",
passkeyErrorPermissionDenied: "A solicitação não é permitida pelo agente do usuário ou pela plataforma no contexto atual, possivelmente porque o usuário negou a permissão.",
passkeyErrorAlreadyRegistered: "O autenticador já foi registrado anteriormente.",
passkeyErrorPermissionDenied:
"A solicitação não é permitida pelo agente do usuário ou pela plataforma no contexto atual, possivelmente porque o usuário negou a permissão.",
passkeyErrorAlreadyRegistered:
"O autenticador já foi registrado anteriormente.",
linkCopied: "Link copiado para a área de transferência",
copyFailed: "Falha ao copiar link",
passkeyRequiresHttps: "WebAuthn requer HTTPS ou localhost. Por favor, acesse o aplicativo via HTTPS ou use localhost em vez de um endereço IP.",
passkeyWebAuthnNotSupported: "WebAuthn não é suportado neste navegador. Por favor, use um navegador moderno que suporte WebAuthn.",
passkeyRequiresHttps:
"WebAuthn requer HTTPS ou localhost. Por favor, acesse o aplicativo via HTTPS ou use localhost em vez de um endereço IP.",
passkeyWebAuthnNotSupported:
"WebAuthn não é suportado neste navegador. Por favor, use um navegador moderno que suporte WebAuthn.",
// Collection Page
loadingCollection: "Carregando coleção...",

View File

@@ -65,9 +65,11 @@ export const ru = {
columnsCount: "{count} колонок",
enableLogin: "Включить защиту входа",
allowPasswordLogin: "Разрешить вход по паролю",
allowPasswordLoginHelper: "При отключении вход по паролю недоступен. Для отключения входа по паролю необходимо иметь хотя бы один ключ доступа.",
allowPasswordLoginHelper:
"При отключении вход по паролю недоступен. Для отключения входа по паролю необходимо иметь хотя бы один ключ доступа.",
allowResetPassword: "Разрешить сброс пароля",
allowResetPasswordHelper: "При отключении кнопка сброса пароля не будет отображаться на странице входа, а API сброса пароля будет заблокирована.",
allowResetPasswordHelper:
"При отключении кнопка сброса пароля не будет отображаться на странице входа, а API сброса пароля будет заблокирована.",
password: "Пароль",
enterPassword: "Введите пароль",
togglePasswordVisibility: "Показать/скрыть пароль",
@@ -332,8 +334,10 @@ export const ru = {
resetPasswordConfirm: "Сбросить",
resetPasswordSuccess:
"Пароль был сброшен. Проверьте логи бэкенда для нового пароля.",
resetPasswordDisabledInfo: "Сброс пароля отключен. Чтобы сбросить пароль, выполните следующую команду в директории бэкенда:\n\nnpm run reset-password\n\nИли:\n\nts-node scripts/reset-password.ts\n\nЭто сгенерирует новый случайный пароль и включит вход по паролю.",
resetPasswordScriptGuide: "Чтобы вручную сбросить пароль, выполните следующую команду в директории бэкенда:\n\nnpm run reset-password\n\nИли:\n\nts-node scripts/reset-password.ts\n\nЕсли пароль не указан, будет сгенерирован случайный 8-символьный пароль.",
resetPasswordDisabledInfo:
"Сброс пароля отключен. Чтобы сбросить пароль, выполните следующую команду в директории бэкенда:\n\nnpm run reset-password\n\nИли:\n\nts-node scripts/reset-password.ts\n\nЭто сгенерирует новый случайный пароль и включит вход по паролю.",
resetPasswordScriptGuide:
"Чтобы вручную сбросить пароль, выполните следующую команду в директории бэкенда:\n\nnpm run reset-password\n\nИли:\n\nts-node scripts/reset-password.ts\n\nЕсли пароль не указан, будет сгенерирован случайный 8-символьный пароль.",
waitTimeMessage: "Пожалуйста, подождите {time} перед повторной попыткой.",
tooManyAttempts: "Слишком много неудачных попыток.",
// Passkeys
@@ -353,12 +357,15 @@ export const ru = {
authenticating: "Аутентификация...",
passkeyLoginFailed:
"Ошибка аутентификации с помощью ключа доступа. Пожалуйста, попробуйте снова.",
passkeyErrorPermissionDenied: "Запрос не разрешен пользовательским агентом или платформой в текущем контексте, возможно, потому что пользователь отклонил разрешение.",
passkeyErrorPermissionDenied:
"Запрос не разрешен пользовательским агентом или платформой в текущем контексте, возможно, потому что пользователь отклонил разрешение.",
passkeyErrorAlreadyRegistered: "Аутентификатор был ранее зарегистрирован.",
linkCopied: "Ссылка скопирована в буфер обмена",
copyFailed: "Не удалось скопировать ссылку",
passkeyRequiresHttps: "WebAuthn требует HTTPS или localhost. Пожалуйста, войдите в приложение через HTTPS или используйте localhost вместо IP-адреса.",
passkeyWebAuthnNotSupported: "WebAuthn не поддерживается в этом браузере. Пожалуйста, используйте современный браузер с поддержкой WebAuthn.",
passkeyRequiresHttps:
"WebAuthn требует HTTPS или localhost. Пожалуйста, войдите в приложение через HTTPS или используйте localhost вместо IP-адреса.",
passkeyWebAuthnNotSupported:
"WebAuthn не поддерживается в этом браузере. Пожалуйста, используйте современный браузер с поддержкой WebAuthn.",
// Collection Page
loadingCollection: "Загрузка коллекции...",

View File

@@ -1,28 +1,38 @@
import { ar } from './locales/ar';
import { de } from './locales/de';
import { en } from './locales/en';
import { es } from './locales/es';
import { fr } from './locales/fr';
import { ja } from './locales/ja';
import { ko } from './locales/ko';
import { pt } from './locales/pt';
import { ru } from './locales/ru';
import { zh } from './locales/zh';
import { ar } from "./locales/ar";
import { de } from "./locales/de";
import { en } from "./locales/en";
import { es } from "./locales/es";
import { fr } from "./locales/fr";
import { ja } from "./locales/ja";
import { ko } from "./locales/ko";
import { pt } from "./locales/pt";
import { ru } from "./locales/ru";
import { zh } from "./locales/zh";
export const translations = {
en,
zh,
es,
de,
ja,
fr,
ko,
ar,
pt,
ru
en,
zh,
es,
de,
ja,
fr,
ko,
ar,
pt,
ru,
};
export type Language = 'en' | 'zh' | 'es' | 'de' | 'ja' | 'fr' | 'ko' | 'ar' | 'pt' | 'ru';
export type Language =
| "en"
| "zh"
| "es"
| "de"
| "ja"
| "fr"
| "ko"
| "ar"
| "pt"
| "ru";
export type TranslationKey = keyof typeof translations.en;
/**
@@ -30,24 +40,30 @@ export type TranslationKey = keyof typeof translations.en;
* @param errorMessage The error message from WebAuthn API
* @returns Translation key if a match is found, null otherwise
*/
export function getWebAuthnErrorTranslationKey(errorMessage: string): TranslationKey | null {
if (!errorMessage) return null;
const lowerMessage = errorMessage.toLowerCase();
// Check for permission denied error
if (lowerMessage.includes('not allowed') ||
lowerMessage.includes('denied permission') ||
lowerMessage.includes('user denied')) {
return 'passkeyErrorPermissionDenied';
}
// Check for already registered error
if (lowerMessage.includes('previously registered') ||
lowerMessage.includes('already registered') ||
lowerMessage.includes('authenticator was previously')) {
return 'passkeyErrorAlreadyRegistered';
}
return null;
export function getWebAuthnErrorTranslationKey(
errorMessage: string
): TranslationKey | null {
if (!errorMessage) return null;
const lowerMessage = errorMessage.toLowerCase();
// Check for permission denied error
if (
lowerMessage.includes("not allowed") ||
lowerMessage.includes("denied permission") ||
lowerMessage.includes("user denied")
) {
return "passkeyErrorPermissionDenied";
}
// Check for already registered error
if (
lowerMessage.includes("previously registered") ||
lowerMessage.includes("already registered") ||
lowerMessage.includes("authenticator was previously")
) {
return "passkeyErrorAlreadyRegistered";
}
return null;
}