diff --git a/backend/internal/handler/auth_handler.go b/backend/internal/handler/auth_handler.go index 019b1656..dae3e471 100644 --- a/backend/internal/handler/auth_handler.go +++ b/backend/internal/handler/auth_handler.go @@ -4144,7 +4144,17 @@ func (h *AuthHandler) ProcessPasswordResetToken(c *fiber.Ctx) error { ale.LoginIDs["loginId_normalized"] = loginID userfrontURL := h.resolveUserfrontURL(c) - redirectBase, parseErr := url.Parse(userfrontURL + "/reset-password") + locale := "ko" + acceptLang := c.Get("Accept-Language") + if acceptLang != "" { + // Accept-Language 헤더는 선호도가 가장 높은 순서대로 쉼표로 구분되어 나열됩니다. (예: ko-KR,ko;q=0.9,en-US;q=0.8) + // 따라서 첫 번째 쉼표 이전의 가장 첫 번째 세그먼트가 사용자가 최우선으로 선호하는 언어입니다. + firstLang := strings.Split(acceptLang, ",")[0] + if strings.Contains(strings.ToLower(firstLang), "en") { + locale = "en" + } + } + redirectBase, parseErr := url.Parse(fmt.Sprintf("%s/%s/reset-password", strings.TrimRight(userfrontURL, "/"), locale)) if parseErr != nil { ale.Status = fiber.StatusInternalServerError ale.LatencyMs = time.Since(startTime) diff --git a/locales/en.toml b/locales/en.toml index 9990de93..b6a4e8e2 100644 --- a/locales/en.toml +++ b/locales/en.toml @@ -283,6 +283,9 @@ no_users_found = "No Users Found" protected_relation = "This relation is protected and cannot be changed here." super_admin_description = "Grant or revoke system super administrator access." super_admin_grant_success = "Super administrator access granted." +super_admin_grant_queue_empty = "Add users to grant from the search results on the left." +super_admin_grant_users_required = "Please add one or more users to grant." +super_admin_search_empty = "Please enter a search term." super_admin_revoke_success = "Super administrator access revoked." super_admin_users_required = "Select at least one user." target_tenant_picker_desc = "Choose the tenant scope for this permission." @@ -1500,6 +1503,12 @@ target_org_picker = "Select organization" target_queue_empty = "No targets selected" target_queue_remove = "Remove target" target_tenant_picker_title = "Select tenant" +search_results = "results" +super_admin_grant_queue_add = "Add to targets" +super_admin_grant_queue_remove = "Remove from targets" +super_admin_grant_targets = "Grant Targets" +super_admin_search = "Search User" +super_admin_search_placeholder = "Search UUID, name, email, phone number" target_tenant_required_option = "Target tenant required" user_list = "User List" diff --git a/locales/ko.toml b/locales/ko.toml index be4ba144..c4f282e3 100644 --- a/locales/ko.toml +++ b/locales/ko.toml @@ -283,6 +283,9 @@ no_users_found = "등록된 사용자가 없습니다." protected_relation = "보호된 관계라 이 화면에서 변경할 수 없습니다." super_admin_description = "시스템 Super Admin 권한을 부여하거나 회수합니다." super_admin_grant_success = "Super Admin 권한을 부여했습니다." +super_admin_grant_queue_empty = "부여할 사용자를 왼쪽 검색 결과에서 추가하세요." +super_admin_grant_users_required = "부여할 사용자를 하나 이상 추가하세요." +super_admin_search_empty = "검색어를 입력하세요." super_admin_revoke_success = "Super Admin 권한을 회수했습니다." super_admin_users_required = "사용자를 한 명 이상 선택해 주세요." target_tenant_picker_desc = "이 권한에 적용할 테넌트 범위를 선택합니다." @@ -1500,6 +1503,12 @@ target_org_picker = "조직 선택" target_queue_empty = "선택된 대상이 없습니다." target_queue_remove = "대상 제거" target_tenant_picker_title = "테넌트 선택" +search_results = "건" +super_admin_grant_queue_add = "부여 대상 추가" +super_admin_grant_queue_remove = "부여 대상 제거" +super_admin_grant_targets = "부여 대상자" +super_admin_search = "사용자 검색" +super_admin_search_placeholder = "UUID, 이름, 이메일, 전화번호 검색" target_tenant_required_option = "대상 테넌트 필수" user_list = "대상 사용자" diff --git a/locales/template.toml b/locales/template.toml index 73c0cfe1..9c47a53c 100644 --- a/locales/template.toml +++ b/locales/template.toml @@ -283,6 +283,9 @@ no_users_found = "" protected_relation = "" super_admin_description = "" super_admin_grant_success = "" +super_admin_grant_queue_empty = "" +super_admin_grant_users_required = "" +super_admin_search_empty = "" super_admin_revoke_success = "" super_admin_users_required = "" target_tenant_picker_desc = "" @@ -1500,6 +1503,12 @@ target_org_picker = "" target_queue_empty = "" target_queue_remove = "" target_tenant_picker_title = "" +search_results = "" +super_admin_grant_queue_add = "" +super_admin_grant_queue_remove = "" +super_admin_grant_targets = "" +super_admin_search = "" +super_admin_search_placeholder = "" target_tenant_required_option = "" user_list = "" diff --git a/userfront/lib/features/auth/presentation/forgot_password_screen.dart b/userfront/lib/features/auth/presentation/forgot_password_screen.dart index 8c01e4cd..9b72a485 100644 --- a/userfront/lib/features/auth/presentation/forgot_password_screen.dart +++ b/userfront/lib/features/auth/presentation/forgot_password_screen.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import '../../../core/i18n/locale_utils.dart'; +import '../../../core/services/auth_token_store.dart'; import '../../../core/services/auth_proxy_service.dart'; import '../../../core/ui/toast_service.dart'; import 'package:userfront/i18n.dart'; @@ -48,7 +51,17 @@ class _ForgotPasswordScreenState extends State { ); if (mounted) { ToastService.success(tr('msg.userfront.forgot.sent')); - Navigator.of(context).pop(); + if (context.canPop()) { + context.pop(); + } else { + final isLoggedIn = AuthTokenStore.hasToken(); + final localeCode = extractLocaleFromPath(Uri.base) ?? resolvePreferredLocaleCode(); + if (isLoggedIn) { + context.go('/$localeCode/profile'); + } else { + context.go('/$localeCode/signin'); + } + } } } catch (e) { if (mounted) { diff --git a/userfront/lib/features/profile/presentation/pages/profile_page.dart b/userfront/lib/features/profile/presentation/pages/profile_page.dart index 4ed3e63b..d023365c 100644 --- a/userfront/lib/features/profile/presentation/pages/profile_page.dart +++ b/userfront/lib/features/profile/presentation/pages/profile_page.dart @@ -1097,11 +1097,6 @@ class _ProfilePageState extends ConsumerState { ) : Text(tr('ui.userfront.profile.password.change')), ), - const SizedBox(width: 12), - TextButton( - onPressed: () => context.go('/recovery'), - child: Text(tr('ui.userfront.profile.password.forgot')), - ), ], ), ],