From b978e09327deb08cfd49ebb21ae11d0a0fbd79c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Padez?=
Date: Sun, 23 Aug 2026 05:15:22 +0000
Subject: [PATCH] authentication and calendar-sync passwords keyed (214 -> 163)
Authentication reaches zero -- sign-in, bootstrap, forgot and reset password. These
are the first words a new account reads, which is why the brief ranked them above
the larger screens.
DavAppPasswords had the third toLocaleDateString(undefined, ...) in the shell; it now
uses useFormat().date like the other two.
DebugPanel's three labels are keyed too. Worth knowing rather than acting on: that
panel is rendered behind showDebug, which Background.tsx hardcodes to false, so it
never appears. Keyed rather than deleted because removing it is not my call.
---
.../ForgotPassword/ForgotPassword.tsx | 16 +++---
.../ForgotPassword/ResetPassword.tsx | 22 +++----
.../ForgotPassword/useResetPassword.ts | 4 +-
.../Authentication/LandingPage/Bootstrap.tsx | 26 +++++----
.../Authentication/LandingPage/Login.tsx | 16 +++---
.../Layout/DuckAvatar/DebugPanel.tsx | 9 ++-
.../IntegrationsSettings/DavAppPasswords.tsx | 57 +++++++++++--------
src/apps/officer-web/locales/en-GB.json | 51 +++++++++++++++++
src/apps/officer-web/locales/pt-PT.json | 51 +++++++++++++++++
9 files changed, 189 insertions(+), 63 deletions(-)
diff --git a/src/apps/officer-web/Screens/Authentication/ForgotPassword/ForgotPassword.tsx b/src/apps/officer-web/Screens/Authentication/ForgotPassword/ForgotPassword.tsx
index d7dc1d2e..f959e3e0 100644
--- a/src/apps/officer-web/Screens/Authentication/ForgotPassword/ForgotPassword.tsx
+++ b/src/apps/officer-web/Screens/Authentication/ForgotPassword/ForgotPassword.tsx
@@ -7,8 +7,10 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/Card';
+import { useTranslation } from '@/lib/i18n';
export function ForgotPassword() {
+ const { t } = useTranslation();
const client = useClient('/api/auth');
const [isSubmitting, setIsSubmitting] = useState(false);
const [done, setDone] = useState(false);
@@ -34,29 +36,29 @@ export function ForgotPassword() {
{done ? (
-
Check your email
+
{t('auth.checkEmail')}
A password reset link has been sent to {state.email}.
-
Click it to reset your password.
+
{t('auth.checkEmailHint')}
) : (
<>
-
Forgot Password
-
Enter your email to receive a reset link
+
{t('auth.forgotTitle')}
+
{t('auth.forgotSubtitle')}
*/}
- Forgot password?
+ {t('auth.forgotPassword')}
diff --git a/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DebugPanel.tsx b/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DebugPanel.tsx
index 2430b179..03ff7e67 100644
--- a/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DebugPanel.tsx
+++ b/src/apps/officer-web/Screens/Authentication/Layout/DuckAvatar/DebugPanel.tsx
@@ -1,3 +1,5 @@
+import { useTranslation } from '@/lib/i18n';
+
type DebugPanelProps = {
fullControlMode: boolean;
cameraInfo: {
@@ -13,9 +15,10 @@ type DebugPanelProps = {
};
export function DebugPanel({ fullControlMode, cameraInfo, modelInfo }: DebugPanelProps) {
+ const { t } = useTranslation();
return (
{!revoked && (
- revoke(entry.id)} title="Revoke">
+ revoke(entry.id)} title={t('settings.dav.revoke')}>
)}
@@ -200,7 +211,7 @@ export const DavAppPasswords = () => {
variant="ghost"
size="sm"
onClick={() => remove(entry.id)}
- title="Delete"
+ title={t('settings.dav.delete')}
className="hover:text-red-500"
>
diff --git a/src/apps/officer-web/locales/en-GB.json b/src/apps/officer-web/locales/en-GB.json
index dde73743..745f08e1 100644
--- a/src/apps/officer-web/locales/en-GB.json
+++ b/src/apps/officer-web/locales/en-GB.json
@@ -360,6 +360,21 @@
"resetTitle": "Reset the password for {{email}}?",
"resetBody": "A new password is generated and shown to you once — it is not stored anywhere and cannot be looked up afterwards. Their existing password stops working immediately, and they are signed out everywhere.",
"resetLinuxNote": "Their Linux account ({{osUser}}) is not affected: it has no password, and SSH keys are unchanged."
+ },
+ "dav": {
+ "newDevice": "New device",
+ "create": "Create",
+ "none": "No devices yet.",
+ "placeholder": "Pixel 9, iPad, Thunderbird…",
+ "revoke": "Revoke",
+ "delete": "Delete",
+ "copyFailed": "Could not copy — select and copy manually",
+ "createFailed": "Could not create the app password",
+ "revoked": "Revoked — that device will stop syncing",
+ "revokeFailed": "Could not revoke",
+ "deleteFailed": "Could not delete",
+ "copyField": "Copy {{field}}",
+ "copied": "{{what}} copied"
}
},
"header": {
@@ -484,5 +499,41 @@
"submitted": "Bug report submitted",
"failed": "Failed to submit bug report",
"submit": "Submit"
+ },
+ "auth": {
+ "signInTitle": "Welcome Back",
+ "signInSubtitle": "Sign in to your account",
+ "emailOrUsername": "Email or username",
+ "password": "Password",
+ "forgotPassword": "Forgot password?",
+ "emailPlaceholder": "you@example.com",
+ "passwordPlaceholder": "Your password",
+ "forgotTitle": "Forgot Password",
+ "forgotSubtitle": "Enter your email to receive a reset link",
+ "email": "Email",
+ "backToLogin": "Back to login",
+ "checkEmail": "Check your email",
+ "checkEmailHint": "Click it to reset your password.",
+ "resetOk": "Password reset successfully. Please sign in.",
+ "verifying": "Verifying…",
+ "invalidLink": "Invalid Link",
+ "invalidLinkHint": "This reset link is invalid or has expired.",
+ "resetTitle": "Reset Password",
+ "resetSubtitle": "Enter your new password",
+ "confirmPassword": "Confirm Password",
+ "minChars": "Min 12 characters",
+ "confirmPlaceholder": "Confirm your password",
+ "bootstrapTitle": "Welcome, Admin",
+ "bootstrapSubtitle": "Create your administrator account",
+ "name": "Name",
+ "username": "Username",
+ "namePlaceholder": "Your name",
+ "adminEmailPlaceholder": "admin@example.com",
+ "bootstrapOk": "Administrator account created. Please sign in.",
+ "debug": {
+ "controls": "Controls:",
+ "camera": "Camera:",
+ "model": "Model:"
+ }
}
}
diff --git a/src/apps/officer-web/locales/pt-PT.json b/src/apps/officer-web/locales/pt-PT.json
index ca40b7e7..8bc171f8 100644
--- a/src/apps/officer-web/locales/pt-PT.json
+++ b/src/apps/officer-web/locales/pt-PT.json
@@ -360,6 +360,21 @@
"resetTitle": "Redefinir a palavra-passe de {{email}}?",
"resetBody": "É gerada uma nova palavra-passe e mostrada uma única vez — não é guardada em nenhum lugar e não pode ser consultada depois. A palavra-passe atual deixa de funcionar imediatamente, e a sessão é terminada em todo o lado.",
"resetLinuxNote": "A conta Linux ({{osUser}}) não é afetada: não tem palavra-passe, e as chaves SSH ficam inalteradas."
+ },
+ "dav": {
+ "newDevice": "Novo dispositivo",
+ "create": "Criar",
+ "none": "Ainda não há dispositivos.",
+ "placeholder": "Pixel 9, iPad, Thunderbird…",
+ "revoke": "Revogar",
+ "delete": "Eliminar",
+ "copyFailed": "Não foi possível copiar — selecione e copie manualmente",
+ "createFailed": "Não foi possível criar a palavra-passe de aplicação",
+ "revoked": "Revogada — esse dispositivo deixa de sincronizar",
+ "revokeFailed": "Não foi possível revogar",
+ "deleteFailed": "Não foi possível eliminar",
+ "copyField": "Copiar {{field}}",
+ "copied": "{{what}} copiado"
}
},
"header": {
@@ -484,5 +499,41 @@
"submitted": "Comunicação de erro enviada",
"failed": "Falha ao enviar a comunicação de erro",
"submit": "Enviar"
+ },
+ "auth": {
+ "signInTitle": "Bem-vindo de volta",
+ "signInSubtitle": "Inicie sessão na sua conta",
+ "emailOrUsername": "Email ou nome de utilizador",
+ "password": "Palavra-passe",
+ "forgotPassword": "Esqueceu-se da palavra-passe?",
+ "emailPlaceholder": "utilizador@exemplo.com",
+ "passwordPlaceholder": "A sua palavra-passe",
+ "forgotTitle": "Recuperar palavra-passe",
+ "forgotSubtitle": "Introduza o seu email para receber um link de recuperação",
+ "email": "Email",
+ "backToLogin": "Voltar ao início de sessão",
+ "checkEmail": "Verifique o seu email",
+ "checkEmailHint": "Clique nele para redefinir a palavra-passe.",
+ "resetOk": "Palavra-passe redefinida com sucesso. Inicie sessão.",
+ "verifying": "A verificar…",
+ "invalidLink": "Link inválido",
+ "invalidLinkHint": "Este link de recuperação é inválido ou expirou.",
+ "resetTitle": "Redefinir palavra-passe",
+ "resetSubtitle": "Introduza a sua nova palavra-passe",
+ "confirmPassword": "Confirmar palavra-passe",
+ "minChars": "Mínimo 12 caracteres",
+ "confirmPlaceholder": "Confirme a sua palavra-passe",
+ "bootstrapTitle": "Bem-vindo, Administrador",
+ "bootstrapSubtitle": "Crie a sua conta de administrador",
+ "name": "Nome",
+ "username": "Nome de utilizador",
+ "namePlaceholder": "O seu nome",
+ "adminEmailPlaceholder": "admin@exemplo.com",
+ "bootstrapOk": "Conta de administrador criada. Inicie sessão.",
+ "debug": {
+ "controls": "Controlos:",
+ "camera": "Câmara:",
+ "model": "Modelo:"
+ }
}
}