Email conf. vs ref

This commit is contained in:
lewis
2025-12-29 18:08:12 +02:00
parent c302d2aea1
commit 5aceed2ab3
17 changed files with 818 additions and 608 deletions
-2
View File
@@ -279,12 +279,10 @@ export const api = {
async requestEmailUpdate(
token: string,
email: string,
): Promise<{ tokenRequired: boolean }> {
return xrpc("com.atproto.server.requestEmailUpdate", {
method: "POST",
token,
body: { email },
});
},
+14 -1
View File
@@ -234,6 +234,7 @@
"deleting": "Deleting...",
"messages": {
"emailCodeSent": "Verification code sent to your notification channel",
"emailCodeSentToCurrent": "Verification code sent to your current email address",
"emailUpdated": "Email updated successfully",
"emailUpdateFailed": "Failed to update email",
"handleUpdated": "Handle updated successfully",
@@ -659,6 +660,7 @@
"codeResent": "Verification code resent!",
"codeResentDetail": "Verification code sent! Check your inbox.",
"backToLogin": "Back to Login",
"backToSettings": "Back to Settings",
"verifyingAccount": "Verifying account: @{handle}",
"startOver": "Start over with a different account",
"noPending": "No pending verification found.",
@@ -671,7 +673,18 @@
"continue": "Continue",
"identifierLabel": "Email or Identifier",
"identifierPlaceholder": "you@example.com",
"identifierHelp": "The email address or identifier the code was sent to"
"identifierHelp": "The email address or identifier the code was sent to",
"emailUpdateTitle": "Update Email Address",
"emailUpdateSubtitle": "Enter your new email address and the verification code sent to your current email.",
"emailUpdateRequiresAuth": "You must be signed in to update your email address.",
"emailUpdateFailed": "Failed to update email address",
"emailUpdateCodeHelp": "The code was sent to your current email address",
"newEmailLabel": "New Email Address",
"newEmailPlaceholder": "new@example.com",
"updateEmail": "Update Email",
"updating": "Updating...",
"emailUpdated": "Your email has been updated successfully.",
"emailUpdatedInfo": "You may need to verify your new email address."
},
"resetPassword": {
"title": "Reset Password",
+14 -17
View File
@@ -234,6 +234,7 @@
"deleting": "Poistetaan...",
"messages": {
"emailCodeSent": "Vahvistuskoodi lähetetty ilmoituskanavallesi",
"emailCodeSentToCurrent": "Vahvistuskoodi lähetetty nykyiseen sähköpostiosoitteeseesi",
"emailUpdated": "Sähköposti päivitetty",
"emailUpdateFailed": "Sähköpostin päivitys epäonnistui",
"handleUpdated": "Käyttäjänimi päivitetty",
@@ -671,7 +672,19 @@
"noPending": "Odottavaa vahvistusta ei löytynyt.",
"noPendingInfo": "Jos loit tilin äskettäin ja sinun on vahvistettava se, sinun on ehkä luotava uusi tili. Jos olet jo vahvistanut tilisi, voit kirjautua sisään.",
"createAccount": "Luo tili",
"signIn": "Kirjaudu sisään"
"signIn": "Kirjaudu sisään",
"backToSettings": "Takaisin asetuksiin",
"emailUpdateCodeHelp": "Koodi lähetettiin nykyiseen sähköpostiosoitteeseesi",
"emailUpdateFailed": "Sähköpostiosoitteen päivitys epäonnistui",
"emailUpdateRequiresAuth": "Sinun on kirjauduttava sisään päivittääksesi sähköpostiosoitteesi.",
"emailUpdateSubtitle": "Syötä uusi sähköpostiosoitteesi ja nykyiseen sähköpostiisi lähetetty vahvistuskoodi.",
"emailUpdateTitle": "Päivitä sähköpostiosoite",
"emailUpdated": "Sähköpostiosoitteesi on päivitetty.",
"emailUpdatedInfo": "Sinun on ehkä vahvistettava uusi sähköpostiosoitteesi.",
"newEmailLabel": "Uusi sähköpostiosoite",
"newEmailPlaceholder": "uusi@esimerkki.fi",
"updateEmail": "Päivitä sähköposti",
"updating": "Päivitetään..."
},
"resetPassword": {
"title": "Palauta salasana",
@@ -754,26 +767,10 @@
"verificationMethod": "Vahvistusmenetelmä",
"email": "Sähköpostiosoite",
"emailPlaceholder": "sinä@esimerkki.fi",
"discord": "Discord",
"discordId": "Discord-käyttäjätunnus",
"discordIdPlaceholder": "Discord-käyttäjätunnuksesi",
"discordIdHint": "Numeerinen Discord-käyttäjätunnuksesi (ota Kehittäjätila käyttöön löytääksesi sen)",
"telegram": "Telegram",
"telegramUsername": "Telegram-käyttäjänimi",
"telegramUsernamePlaceholder": "@käyttäjänimesi",
"signal": "Signal",
"signalNumber": "Signal-puhelinnumero",
"signalNumberPlaceholder": "+358401234567",
"signalNumberHint": "Sisällytä maakoodi (esim. +358 Suomelle)",
"inviteCode": "Kutsukoodi",
"inviteCodePlaceholder": "Syötä kutsukoodisi",
"inviteCodeRequired": "vaaditaan",
"didWebDescription": "Käytä DID-identiteettiä, jota isännöidään omalla verkkotunnuksellasi.",
"didWebToggle": "Käytä ulkoista did:web",
"externalDid": "Sinun did:web",
"externalDidPlaceholder": "did:web:verkkotunnuksesi.fi",
"dnsVerificationInstructions": "Vahvistaaksesi verkkotunnuksesi, lisää tämä TXT-tietue:",
"copyDid": "Kopioi DID",
"createButton": "Luo tili",
"creating": "Luodaan...",
"alreadyHaveAccount": "Onko sinulla jo tili?",
+16 -41
View File
@@ -234,6 +234,7 @@
"deleting": "削除中...",
"messages": {
"emailCodeSent": "通知チャンネルに確認コードを送信しました",
"emailCodeSentToCurrent": "現在のメールアドレスに確認コードを送信しました",
"emailUpdated": "メールを更新しました",
"emailUpdateFailed": "メールの更新に失敗しました",
"handleUpdated": "ハンドルを更新しました",
@@ -671,7 +672,19 @@
"noPending": "保留中の確認が見つかりません。",
"noPendingInfo": "最近アカウントを作成して確認が必要な場合は、新しいアカウントを作成する必要があります。すでにアカウントを確認した場合は、サインインできます。",
"createAccount": "アカウントを作成",
"signIn": "サインイン"
"signIn": "サインイン",
"backToSettings": "設定に戻る",
"emailUpdateCodeHelp": "コードは現在のメールアドレスに送信されました",
"emailUpdateFailed": "メールアドレスの更新に失敗しました",
"emailUpdateRequiresAuth": "メールアドレスを更新するにはサインインが必要です。",
"emailUpdateSubtitle": "新しいメールアドレスと、現在のメールに送信された確認コードを入力してください。",
"emailUpdateTitle": "メールアドレスの更新",
"emailUpdated": "メールアドレスが正常に更新されました。",
"emailUpdatedInfo": "新しいメールアドレスの確認が必要な場合があります。",
"newEmailLabel": "新しいメールアドレス",
"newEmailPlaceholder": "new@example.com",
"updateEmail": "メールを更新",
"updating": "更新中..."
},
"resetPassword": {
"title": "パスワードリセット",
@@ -754,26 +767,10 @@
"verificationMethod": "確認方法",
"email": "メールアドレス",
"emailPlaceholder": "you@example.com",
"discord": "Discord",
"discordId": "Discord ユーザー ID",
"discordIdPlaceholder": "Discord ユーザー ID",
"discordIdHint": "数値の Discord ユーザー ID(開発者モードを有効にして確認)",
"telegram": "Telegram",
"telegramUsername": "Telegram ユーザー名",
"telegramUsernamePlaceholder": "@yourusername",
"signal": "Signal",
"signalNumber": "Signal 電話番号",
"signalNumberPlaceholder": "+81XXXXXXXXXX",
"signalNumberHint": "国番号を含めてください(例: 日本は +81)",
"inviteCode": "招待コード",
"inviteCodePlaceholder": "招待コードを入力",
"inviteCodeRequired": "必須",
"didWebDescription": "独自ドメインでホストされる DID アイデンティティを使用します。",
"didWebToggle": "外部 did:web を使用",
"externalDid": "あなたの did:web",
"externalDidPlaceholder": "did:web:yourdomain.com",
"dnsVerificationInstructions": "ドメインを確認するには、この TXT レコードを追加してください:",
"copyDid": "DID をコピー",
"createButton": "アカウントを作成",
"creating": "作成中...",
"alreadyHaveAccount": "すでにアカウントをお持ちですか?",
@@ -896,32 +893,15 @@
"delegation": {
"title": "アカウント委任",
"controllers": "コントローラー",
"controllersDescription": "コントローラーはあなたのアカウントの管理者として行動できます。あなたが許可した操作を実行し、あなたの代わりに投稿を作成し、リポジトリを変更できます。",
"controlledAccounts": "管理アカウント",
"controlledAccountsDescription": "これらはあなたがコントローラーとして追加されているアカウントです。これらのアカウントで許可されたアクションを実行できます。",
"noControllers": "コントローラーはまだいません",
"noControlledAccounts": "管理アカウントはありません",
"addController": "コントローラーを追加",
"revokeAccess": "アクセスを取り消す",
"revokeConfirm": "このコントローラーのアクセスを取り消しますか?あなたのアカウントで操作できなくなります。",
"handle": "ハンドル",
"handlePlaceholder": "@user.bsky.social",
"did": "DID",
"didPlaceholder": "did:plc:...",
"scopes": "権限レベル",
"scopeOwner": "オーナー",
"scopeOwnerDesc": "完全な管理(すべてのアクションを実行可能)",
"scopeAdmin": "管理者",
"scopeAdminDesc": "投稿、アプリパスワード、設定の管理",
"scopeEditor": "編集者",
"scopeEditorDesc": "投稿、いいね、フォローの作成・管理",
"scopeViewer": "閲覧者",
"scopeViewerDesc": "リポジトリと設定の読み取り専用アクセス",
"scopeCustom": "カスタム",
"scopeCustomDesc": "個別の権限を選択",
"grantedAt": "許可日時",
"expiresAt": "有効期限",
"noExpiration": "無期限",
"actAs": "として行動",
"auditLog": "監査ログ",
"auditLogTitle": "委任監査ログ",
@@ -944,13 +924,7 @@
"showing": "{start}{end} / {total}件",
"refresh": "更新",
"failedToLoadAuditLog": "監査ログの読み込みに失敗しました",
"addControllerTitle": "コントローラーを追加",
"addControllerDescription": "このアカウントに対して指定した権限で操作できるユーザーを追加します。",
"controllerIdentifier": "コントローラーのハンドルまたはDID",
"selectScopes": "権限レベルを選択",
"add": "追加",
"adding": "追加中...",
"cancel": "キャンセル",
"accessLevel": "アクセスレベル",
"addControllerButton": "+ コントローラーを追加",
"auditLogDesc": "すべての委任アクティビティを表示",
@@ -974,7 +948,8 @@
"remove": "削除",
"removeConfirm": "このコントローラーを削除しますか?",
"viewAuditLog": "監査ログを表示",
"yourAccessLevel": "あなたのアクセスレベル"
"yourAccessLevel": "あなたのアクセスレベル",
"accountCreated": "委任アカウントを作成しました: {handle}"
},
"actAs": {
"title": "として行動",
+16 -41
View File
@@ -234,6 +234,7 @@
"deleting": "삭제 중...",
"messages": {
"emailCodeSent": "알림 채널로 인증 코드를 보냈습니다",
"emailCodeSentToCurrent": "현재 이메일 주소로 인증 코드를 보냈습니다",
"emailUpdated": "이메일이 업데이트되었습니다",
"emailUpdateFailed": "이메일 업데이트에 실패했습니다",
"handleUpdated": "핸들이 업데이트되었습니다",
@@ -671,7 +672,19 @@
"noPending": "보류 중인 인증이 없습니다.",
"noPendingInfo": "최근에 계정을 만들고 인증이 필요한 경우 새 계정을 만들어야 합니다. 이미 계정을 인증한 경우 로그인할 수 있습니다.",
"createAccount": "계정 만들기",
"signIn": "로그인"
"signIn": "로그인",
"backToSettings": "설정으로 돌아가기",
"emailUpdateCodeHelp": "코드가 현재 이메일 주소로 전송되었습니다",
"emailUpdateFailed": "이메일 주소 업데이트 실패",
"emailUpdateRequiresAuth": "이메일 주소를 업데이트하려면 로그인해야 합니다.",
"emailUpdateSubtitle": "새 이메일 주소와 현재 이메일로 전송된 인증 코드를 입력하세요.",
"emailUpdateTitle": "이메일 주소 업데이트",
"emailUpdated": "이메일 주소가 성공적으로 업데이트되었습니다.",
"emailUpdatedInfo": "새 이메일 주소를 인증해야 할 수 있습니다.",
"newEmailLabel": "새 이메일 주소",
"newEmailPlaceholder": "new@example.com",
"updateEmail": "이메일 업데이트",
"updating": "업데이트 중..."
},
"resetPassword": {
"title": "비밀번호 재설정",
@@ -754,26 +767,10 @@
"verificationMethod": "인증 방법",
"email": "이메일 주소",
"emailPlaceholder": "you@example.com",
"discord": "Discord",
"discordId": "Discord 사용자 ID",
"discordIdPlaceholder": "Discord 사용자 ID",
"discordIdHint": "숫자 Discord 사용자 ID (개발자 모드를 활성화하여 찾기)",
"telegram": "Telegram",
"telegramUsername": "Telegram 사용자 이름",
"telegramUsernamePlaceholder": "@yourusername",
"signal": "Signal",
"signalNumber": "Signal 전화번호",
"signalNumberPlaceholder": "+821012345678",
"signalNumberHint": "국가 코드 포함 (예: 한국 +82)",
"inviteCode": "초대 코드",
"inviteCodePlaceholder": "초대 코드 입력",
"inviteCodeRequired": "필수",
"didWebDescription": "자체 도메인에서 호스팅되는 DID 아이덴티티를 사용합니다.",
"didWebToggle": "외부 did:web 사용",
"externalDid": "귀하의 did:web",
"externalDidPlaceholder": "did:web:yourdomain.com",
"dnsVerificationInstructions": "도메인을 인증하려면 이 TXT 레코드를 추가하세요:",
"copyDid": "DID 복사",
"createButton": "계정 만들기",
"creating": "생성 중...",
"alreadyHaveAccount": "이미 계정이 있으신가요?",
@@ -896,32 +893,15 @@
"delegation": {
"title": "계정 위임",
"controllers": "컨트롤러",
"controllersDescription": "컨트롤러는 귀하의 계정 관리자로서 행동할 수 있습니다. 귀하가 허용한 작업을 수행하고, 귀하를 대신하여 게시물을 생성하고, 저장소를 수정할 수 있습니다.",
"controlledAccounts": "관리 계정",
"controlledAccountsDescription": "귀하가 컨트롤러로 추가된 계정들입니다. 이 계정들에서 허용된 작업을 수행할 수 있습니다.",
"noControllers": "아직 컨트롤러가 없습니다",
"noControlledAccounts": "관리 계정이 없습니다",
"addController": "컨트롤러 추가",
"revokeAccess": "액세스 취소",
"revokeConfirm": "이 컨트롤러의 액세스를 취소하시겠습니까? 귀하의 계정에서 더 이상 작업을 수행할 수 없습니다.",
"handle": "핸들",
"handlePlaceholder": "@user.bsky.social",
"did": "DID",
"didPlaceholder": "did:plc:...",
"scopes": "권한 수준",
"scopeOwner": "소유자",
"scopeOwnerDesc": "전체 관리(모든 작업 수행 가능)",
"scopeAdmin": "관리자",
"scopeAdminDesc": "게시물, 앱 비밀번호, 설정 관리",
"scopeEditor": "편집자",
"scopeEditorDesc": "게시물, 좋아요, 팔로우 생성 및 관리",
"scopeViewer": "뷰어",
"scopeViewerDesc": "저장소 및 설정 읽기 전용 액세스",
"scopeCustom": "사용자 정의",
"scopeCustomDesc": "개별 권한 선택",
"grantedAt": "허용 일시",
"expiresAt": "만료",
"noExpiration": "무기한",
"actAs": "로 활동",
"auditLog": "감사 로그",
"auditLogTitle": "위임 감사 로그",
@@ -944,13 +924,7 @@
"showing": "{start}~{end} / {total}개",
"refresh": "새로고침",
"failedToLoadAuditLog": "감사 로그를 불러오지 못했습니다",
"addControllerTitle": "컨트롤러 추가",
"addControllerDescription": "이 계정에서 지정된 권한으로 작업할 수 있는 사용자를 추가합니다.",
"controllerIdentifier": "컨트롤러 핸들 또는 DID",
"selectScopes": "권한 수준 선택",
"add": "추가",
"adding": "추가 중...",
"cancel": "취소",
"accessLevel": "액세스 수준",
"addControllerButton": "+ 컨트롤러 추가",
"auditLogDesc": "모든 위임 활동 보기",
@@ -974,7 +948,8 @@
"remove": "제거",
"removeConfirm": "이 컨트롤러를 제거하시겠습니까?",
"viewAuditLog": "감사 로그 보기",
"yourAccessLevel": "귀하의 액세스 수준"
"yourAccessLevel": "귀하의 액세스 수준",
"accountCreated": "위임 계정이 생성되었습니다: {handle}"
},
"actAs": {
"title": "로 활동",
+16 -41
View File
@@ -234,6 +234,7 @@
"deleting": "Raderar...",
"messages": {
"emailCodeSent": "Verifieringskod skickad till din meddelandekanal",
"emailCodeSentToCurrent": "Verifieringskod skickad till din nuvarande e-postadress",
"emailUpdated": "E-post uppdaterad",
"emailUpdateFailed": "Kunde inte uppdatera e-post",
"handleUpdated": "Användarnamn uppdaterat",
@@ -671,7 +672,19 @@
"noPending": "Ingen väntande verifiering hittades.",
"noPendingInfo": "Om du nyligen skapade ett konto och behöver verifiera det kan du behöva skapa ett nytt konto. Om du redan verifierat ditt konto kan du logga in.",
"createAccount": "Skapa konto",
"signIn": "Logga in"
"signIn": "Logga in",
"backToSettings": "Tillbaka till inställningar",
"emailUpdateCodeHelp": "Koden skickades till din nuvarande e-postadress",
"emailUpdateFailed": "Kunde inte uppdatera e-postadress",
"emailUpdateRequiresAuth": "Du måste vara inloggad för att uppdatera din e-postadress.",
"emailUpdateSubtitle": "Ange din nya e-postadress och verifieringskoden som skickades till din nuvarande e-post.",
"emailUpdateTitle": "Uppdatera e-postadress",
"emailUpdated": "Din e-postadress har uppdaterats.",
"emailUpdatedInfo": "Du kan behöva verifiera din nya e-postadress.",
"newEmailLabel": "Ny e-postadress",
"newEmailPlaceholder": "ny@exempel.se",
"updateEmail": "Uppdatera e-post",
"updating": "Uppdaterar..."
},
"resetPassword": {
"title": "Återställ lösenord",
@@ -754,26 +767,10 @@
"verificationMethod": "Verifieringsmetod",
"email": "E-postadress",
"emailPlaceholder": "du@exempel.se",
"discord": "Discord",
"discordId": "Discord användar-ID",
"discordIdPlaceholder": "Ditt Discord användar-ID",
"discordIdHint": "Ditt numeriska Discord användar-ID (aktivera Utvecklarläge för att hitta det)",
"telegram": "Telegram",
"telegramUsername": "Telegram-användarnamn",
"telegramUsernamePlaceholder": "@dittanvändarnamn",
"signal": "Signal",
"signalNumber": "Signal-telefonnummer",
"signalNumberPlaceholder": "+46701234567",
"signalNumberHint": "Inkludera landskod (t.ex. +46 för Sverige)",
"inviteCode": "Inbjudningskod",
"inviteCodePlaceholder": "Ange din inbjudningskod",
"inviteCodeRequired": "krävs",
"didWebDescription": "Använd en DID-identitet som är lagrad på din egen domän.",
"didWebToggle": "Använd extern did:web",
"externalDid": "Din did:web",
"externalDidPlaceholder": "did:web:dindomän.se",
"dnsVerificationInstructions": "För att verifiera din domän, lägg till denna TXT-post:",
"copyDid": "Kopiera DID",
"createButton": "Skapa konto",
"creating": "Skapar...",
"alreadyHaveAccount": "Har du redan ett konto?",
@@ -896,32 +893,15 @@
"delegation": {
"title": "Kontodelegering",
"controllers": "Kontrollanter",
"controllersDescription": "Kontrollanter kan agera som administratörer för ditt konto. De kan utföra åtgärder du tillåter, skapa inlägg för din räkning och modifiera din dataförvaring.",
"controlledAccounts": "Kontrollerade konton",
"controlledAccountsDescription": "Detta är konton där du har lagts till som kontrollant. Du kan utföra tillåtna åtgärder på dessa konton.",
"noControllers": "Inga kontrollanter ännu",
"noControlledAccounts": "Inga kontrollerade konton",
"addController": "Lägg till kontrollant",
"revokeAccess": "Återkalla åtkomst",
"revokeConfirm": "Återkalla denna kontrollants åtkomst? De kommer inte längre kunna utföra åtgärder på ditt konto.",
"handle": "Användarnamn",
"handlePlaceholder": "@user.bsky.social",
"did": "DID",
"didPlaceholder": "did:plc:...",
"scopes": "Behörighetsnivå",
"scopeOwner": "Ägare",
"scopeOwnerDesc": "Fullständig kontroll (kan utföra alla åtgärder)",
"scopeAdmin": "Administratör",
"scopeAdminDesc": "Hantera inlägg, applösenord, inställningar",
"scopeEditor": "Redaktör",
"scopeEditorDesc": "Skapa och hantera inlägg, gillningar, följningar",
"scopeViewer": "Läsare",
"scopeViewerDesc": "Endast läsåtkomst till dataförvaring och inställningar",
"scopeCustom": "Anpassad",
"scopeCustomDesc": "Välj individuella behörigheter",
"grantedAt": "Beviljad",
"expiresAt": "Upphör",
"noExpiration": "Ingen utgång",
"actAs": "Agera som",
"auditLog": "Granskningslogg",
"auditLogTitle": "Delegerings-granskningslogg",
@@ -944,13 +924,7 @@
"showing": "{start}{end} av {total}",
"refresh": "Uppdatera",
"failedToLoadAuditLog": "Kunde inte ladda granskningsloggen",
"addControllerTitle": "Lägg till kontrollant",
"addControllerDescription": "Lägg till en användare som kan utföra åtgärder på detta konto med specificerade behörigheter.",
"controllerIdentifier": "Kontrollantens användarnamn eller DID",
"selectScopes": "Välj behörighetsnivå",
"add": "Lägg till",
"adding": "Lägger till...",
"cancel": "Avbryt",
"accessLevel": "Åtkomstnivå",
"addControllerButton": "+ Lägg till kontrollant",
"auditLogDesc": "Visa all delegeringsaktivitet",
@@ -974,7 +948,8 @@
"remove": "Ta bort",
"removeConfirm": "Vill du ta bort denna kontrollant?",
"viewAuditLog": "Visa granskningslogg",
"yourAccessLevel": "Din åtkomstnivå"
"yourAccessLevel": "Din åtkomstnivå",
"accountCreated": "Skapade delegerat konto: {handle}"
},
"actAs": {
"title": "Agera som",
+16 -25
View File
@@ -234,6 +234,7 @@
"deleting": "删除中...",
"messages": {
"emailCodeSent": "验证码已发送到您的通知渠道",
"emailCodeSentToCurrent": "验证码已发送到您当前的邮箱地址",
"emailUpdated": "邮箱更新成功",
"emailUpdateFailed": "邮箱更新失败",
"handleUpdated": "用户名更新成功",
@@ -671,7 +672,19 @@
"continue": "继续",
"identifierLabel": "邮箱或标识符",
"identifierPlaceholder": "you@example.com",
"identifierHelp": "接收验证码的邮箱地址或标识符"
"identifierHelp": "接收验证码的邮箱地址或标识符",
"backToSettings": "返回设置",
"emailUpdateCodeHelp": "验证码已发送到您当前的邮箱地址",
"emailUpdateFailed": "更新邮箱地址失败",
"emailUpdateRequiresAuth": "您需要登录才能更新邮箱地址。",
"emailUpdateSubtitle": "输入您的新邮箱地址和发送到当前邮箱的验证码。",
"emailUpdateTitle": "更新邮箱地址",
"emailUpdated": "您的邮箱地址已成功更新。",
"emailUpdatedInfo": "您可能需要验证新的邮箱地址。",
"newEmailLabel": "新邮箱地址",
"newEmailPlaceholder": "new@example.com",
"updateEmail": "更新邮箱",
"updating": "更新中..."
},
"resetPassword": {
"title": "重置密码",
@@ -821,7 +834,8 @@
"passkeysNotSupported": "此浏览器不支持通行密钥。请使用其他浏览器或使用密码注册。",
"passkeyCancelled": "通行密钥创建已取消",
"passkeyFailed": "通行密钥注册失败"
}
},
"didWebWarning1Detail": "您的身份将是 {did}。"
},
"trustedDevices": {
"title": "受信任设备",
@@ -879,32 +893,15 @@
"delegation": {
"title": "账户委托",
"controllers": "控制者",
"controllersDescription": "控制者可以作为您账户的管理员。他们可以执行您允许的操作,代表您发布帖子,以及修改您的数据仓库。",
"controlledAccounts": "受控账户",
"controlledAccountsDescription": "这些是您被添加为控制者的账户。您可以在这些账户上执行允许的操作。",
"noControllers": "暂无控制者",
"noControlledAccounts": "无受控账户",
"addController": "添加控制者",
"revokeAccess": "撤销访问",
"revokeConfirm": "撤销此控制者的访问权限?他们将无法再在您的账户上执行操作。",
"handle": "用户名",
"handlePlaceholder": "@user.bsky.social",
"did": "DID",
"didPlaceholder": "did:plc:...",
"scopes": "权限级别",
"scopeOwner": "所有者",
"scopeOwnerDesc": "完全控制(可执行所有操作)",
"scopeAdmin": "管理员",
"scopeAdminDesc": "管理帖子、应用专用密码、设置",
"scopeEditor": "编辑者",
"scopeEditorDesc": "创建和管理帖子、点赞、关注",
"scopeViewer": "查看者",
"scopeViewerDesc": "只读访问数据仓库和设置",
"scopeCustom": "自定义",
"scopeCustomDesc": "选择单独的权限",
"grantedAt": "授权时间",
"expiresAt": "过期时间",
"noExpiration": "永不过期",
"actAs": "代理操作",
"auditLog": "审计日志",
"auditLogTitle": "委托审计日志",
@@ -928,13 +925,7 @@
"showing": "{start}{end} / 共{total}条",
"refresh": "刷新",
"failedToLoadAuditLog": "加载审计日志失败",
"addControllerTitle": "添加控制者",
"addControllerDescription": "添加一个可以在此账户上执行指定权限操作的用户。",
"controllerIdentifier": "控制者用户名或 DID",
"selectScopes": "选择权限级别",
"add": "添加",
"adding": "添加中...",
"cancel": "取消",
"accessLevel": "访问级别",
"addControllerButton": "+ 添加控制者",
"auditLogDesc": "查看所有委托活动",
+17 -23
View File
@@ -56,21 +56,17 @@
if (message?.text === text) message = null
}, 5000)
}
async function handleRequestEmailUpdate(e: Event) {
e.preventDefault()
if (!auth.session || !newEmail) return
async function handleRequestEmailUpdate() {
if (!auth.session) return
emailLoading = true
message = null
try {
const result = await api.requestEmailUpdate(auth.session.accessJwt, newEmail)
const result = await api.requestEmailUpdate(auth.session.accessJwt)
emailTokenRequired = result.tokenRequired
if (emailTokenRequired) {
showMessage('success', $_('settings.messages.emailCodeSent'))
showMessage('success', $_('settings.messages.emailCodeSentToCurrent'))
} else {
await api.updateEmail(auth.session.accessJwt, newEmail)
await refreshSession()
showMessage('success', $_('settings.messages.emailUpdated'))
newEmail = ''
emailTokenRequired = true
}
} catch (e) {
showMessage('error', e instanceof ApiError ? e.message : $_('settings.messages.emailUpdateFailed'))
@@ -244,17 +240,6 @@
required
/>
</div>
<div class="actions">
<button type="submit" disabled={emailLoading || !emailToken}>
{emailLoading ? $_('settings.updating') : $_('settings.confirmEmailChange')}
</button>
<button type="button" class="secondary" onclick={() => { emailTokenRequired = false; emailToken = '' }}>
{$_('common.cancel')}
</button>
</div>
</form>
{:else}
<form onsubmit={handleRequestEmailUpdate}>
<div class="field">
<label for="new-email">{$_('settings.newEmail')}</label>
<input
@@ -266,10 +251,19 @@
required
/>
</div>
<button type="submit" disabled={emailLoading || !newEmail}>
{emailLoading ? $_('settings.requesting') : $_('settings.changeEmailButton')}
</button>
<div class="actions">
<button type="submit" disabled={emailLoading || !emailToken || !newEmail}>
{emailLoading ? $_('settings.updating') : $_('settings.confirmEmailChange')}
</button>
<button type="button" class="secondary" onclick={() => { emailTokenRequired = false; emailToken = ''; newEmail = '' }}>
{$_('common.cancel')}
</button>
</div>
</form>
{:else}
<button onclick={handleRequestEmailUpdate} disabled={emailLoading}>
{emailLoading ? $_('settings.requesting') : $_('settings.changeEmailButton')}
</button>
{/if}
</section>
<section>
+94 -3
View File
@@ -13,9 +13,10 @@
channel: string
}
type VerificationMode = 'signup' | 'token'
type VerificationMode = 'signup' | 'token' | 'email-update'
let mode = $state<VerificationMode>('signup')
let newEmail = $state('')
let pendingVerification = $state<PendingVerification | null>(null)
let verificationCode = $state('')
let identifier = $state('')
@@ -50,7 +51,12 @@
onMount(async () => {
const params = parseQueryParams()
if (params.token) {
if (params.type === 'email-update') {
mode = 'email-update'
if (params.token) {
verificationCode = params.token
}
} else if (params.token) {
mode = 'token'
verificationCode = params.token
if (params.identifier) {
@@ -134,6 +140,33 @@
}
}
async function handleEmailUpdate() {
if (!verificationCode.trim() || !newEmail.trim()) return
if (!auth.session) {
error = $_('verify.emailUpdateRequiresAuth')
return
}
submitting = true
error = null
try {
await api.updateEmail(auth.session.accessJwt, newEmail.trim(), verificationCode.trim())
success = true
successPurpose = 'email-update'
successChannel = 'email'
} catch (e: any) {
if (e instanceof ApiError) {
error = e.message
} else {
error = $_('verify.emailUpdateFailed')
}
} finally {
submitting = false
}
}
async function handleResendCode() {
if (mode === 'signup') {
if (!pendingVerification || resendingCode) return
@@ -198,7 +231,13 @@
{:else if success}
<div class="success-container">
<h1>{$_('verify.verified')}</h1>
{#if successPurpose === 'migration' || successPurpose === 'signup'}
{#if successPurpose === 'email-update'}
<p class="subtitle">{$_('verify.emailUpdated')}</p>
<p class="info-text">{$_('verify.emailUpdatedInfo')}</p>
<div class="actions">
<a href="#/settings" class="btn">{$_('verify.backToSettings')}</a>
</div>
{:else if successPurpose === 'migration' || successPurpose === 'signup'}
<p class="subtitle">{$_('verify.channelVerified', { values: { channel: channelLabel(successChannel || '') } })}</p>
<p class="info-text">{$_('verify.canNowSignIn')}</p>
<div class="actions">
@@ -213,6 +252,58 @@
</div>
{/if}
</div>
{:else if mode === 'email-update'}
<h1>{$_('verify.emailUpdateTitle')}</h1>
<p class="subtitle">{$_('verify.emailUpdateSubtitle')}</p>
{#if !auth.session}
<div class="message warning">{$_('verify.emailUpdateRequiresAuth')}</div>
<div class="actions">
<a href="#/login" class="btn">{$_('verify.signIn')}</a>
</div>
{:else}
{#if error}
<div class="message error">{error}</div>
{/if}
<form onsubmit={(e) => { e.preventDefault(); handleEmailUpdate(); }}>
<div class="field">
<label for="new-email">{$_('verify.newEmailLabel')}</label>
<input
id="new-email"
type="email"
bind:value={newEmail}
placeholder={$_('verify.newEmailPlaceholder')}
disabled={submitting}
required
autocomplete="email"
/>
</div>
<div class="field">
<label for="verification-code">{$_('verify.codeLabel')}</label>
<input
id="verification-code"
type="text"
bind:value={verificationCode}
placeholder={$_('verify.codePlaceholder')}
disabled={submitting}
required
autocomplete="off"
class="token-input"
/>
<p class="field-help">{$_('verify.emailUpdateCodeHelp')}</p>
</div>
<button type="submit" disabled={submitting || !verificationCode.trim() || !newEmail.trim()}>
{submitting ? $_('verify.updating') : $_('verify.updateEmail')}
</button>
</form>
<p class="link-text">
<a href="#/settings">{$_('verify.backToSettings')}</a>
</p>
{/if}
{:else if mode === 'token'}
<h1>{$_('verify.tokenTitle')}</h1>
<p class="subtitle">{$_('verify.tokenSubtitle')}</p>