1
0
forked from baron/baron-sso

i18n 누락 정리 및 하드코딩 텍스트 치환

This commit is contained in:
2026-05-06 16:31:40 +09:00
parent 9a87af93f1
commit 64cdef81a6
6 changed files with 154 additions and 81 deletions

View File

@@ -1,14 +1,15 @@
const Map<String, String> internalErrorWhitelistMessages = {
'settings_disabled': '현재 계정 설정 화면은 준비 중입니다.',
'invalid_session': '세션이 만료되었습니다. 다시 로그인해 주세요.',
'verification_required': '추가 인증이 필요합니다. 안내에 따라 진행해 주세요.',
'recovery_expired': '재설정 링크가 만료되었습니다. 다시 요청해 주세요.',
'recovery_invalid': '재설정 링크가 유효하지 않습니다.',
'rate_limited': '요청이 많습니다. 잠시 후 다시 시도해 주세요.',
'not_found': '요청한 페이지를 찾을 수 없습니다.',
'bad_request': '입력값을 확인해 주세요.',
'password_or_email_mismatch': '이메일 혹은 비밀번호가 일치하지 않습니다.',
'tenant_not_allowed': '허용되지 않은 테넌트입니다.',
const Map<String, String> internalErrorWhitelistMessageKeys = {
'settings_disabled': 'msg.userfront.error.whitelist.settings_disabled',
'invalid_session': 'msg.userfront.error.whitelist.invalid_session',
'verification_required': 'msg.userfront.error.whitelist.verification_required',
'recovery_expired': 'msg.userfront.error.whitelist.recovery_expired',
'recovery_invalid': 'msg.userfront.error.whitelist.recovery_invalid',
'rate_limited': 'msg.userfront.error.whitelist.rate_limited',
'not_found': 'msg.userfront.error.whitelist.not_found',
'bad_request': 'msg.userfront.error.whitelist.bad_request',
'password_or_email_mismatch':
'msg.userfront.error.whitelist.password_or_email_mismatch',
'tenant_not_allowed': 'msg.userfront.error.whitelist.tenant_not_allowed',
};
const Set<String> oryBypassErrorCodes = {

View File

@@ -65,7 +65,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.password_policy_fetch',
'비밀번호 정책을 불러오지 못했습니다.',
'Failed to load the password policy.',
);
}
}
@@ -84,7 +84,7 @@ class AuthProxyService {
}
throw _error(
'err.userfront.auth_proxy.profile_load',
'프로필을 불러오지 못했습니다: {{error}}',
'Failed to load the profile: {{error}}',
detail: response.body,
);
} finally {
@@ -110,7 +110,7 @@ class AuthProxyService {
}
throw _error(
'err.userfront.auth_proxy.profile_load',
'프로필을 불러오지 못했습니다: {{error}}',
'Failed to load the profile: {{error}}',
detail: response.body,
);
} finally {
@@ -144,7 +144,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.tenant_info_fetch',
'테넌트 정보를 불러오지 못했습니다.',
'Failed to load tenant information.',
);
}
}
@@ -180,7 +180,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.login_init',
'로그인 초기화에 실패했습니다: {{error}}',
'Failed to initialize login: {{error}}',
detail: response.body,
);
}
@@ -205,7 +205,7 @@ class AuthProxyService {
}
throw _error(
'err.userfront.auth_proxy.login_poll',
'로그인 상태 확인에 실패했습니다: {{error}}',
'Failed to check login status: {{error}}',
detail: response.body,
);
}
@@ -227,7 +227,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.verify_failed',
'검증에 실패했습니다: {{error}}',
'Verification failed: {{error}}',
detail: response.body,
);
}
@@ -261,7 +261,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.verify_failed',
'검증에 실패했습니다: {{error}}',
'Verification failed: {{error}}',
detail: response.body,
);
}
@@ -281,7 +281,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.dashboard.sessions.revoke',
'세션 종료에 실패했습니다: {{error}}',
'Failed to revoke the session: {{error}}',
detail: response.body,
);
}
@@ -304,7 +304,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.dashboard.sessions.load',
'활성 세션을 불러오지 못했습니다: {{error}}',
'Failed to load the active sessions: {{error}}',
detail: response.body,
);
}
@@ -342,7 +342,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.verify_failed',
'검증에 실패했습니다: {{error}}',
'Verification failed: {{error}}',
detail: response.body,
);
}
@@ -568,7 +568,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.sms_send',
'SMS 전송에 실패했습니다: {{error}}',
'Failed to send SMS: {{error}}',
detail: response.body,
);
}
@@ -591,7 +591,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.code_verify',
'인증 코드 확인에 실패했습니다: {{error}}',
'Failed to verify the code: {{error}}',
detail: response.body,
);
}
@@ -609,7 +609,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.qr_init',
'QR 로그인을 시작하지 못했습니다: {{error}}',
'Failed to start QR login: {{error}}',
detail: response.body,
);
}
@@ -631,7 +631,7 @@ class AuthProxyService {
}
throw _error(
'err.userfront.auth_proxy.qr_poll',
'QR 상태 확인에 실패했습니다: {{error}}',
'Failed to check QR status: {{error}}',
detail: response.body,
);
}
@@ -669,7 +669,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.qr_approve',
'QR 승인에 실패했습니다: {{error}}',
'Failed to approve QR login: {{error}}',
detail: response.body,
);
}
@@ -720,7 +720,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.user_create',
'사용자 생성에 실패했습니다: {{error}}',
'Failed to create the user: {{error}}',
detail: response.body,
);
}
@@ -749,7 +749,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.user_list',
'사용자 목록 조회에 실패했습니다: {{error}}',
'Failed to load the user list: {{error}}',
detail: response.body,
);
}
@@ -770,7 +770,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.user_delete',
'사용자 삭제에 실패했습니다: {{error}}',
'Failed to delete the user: {{error}}',
detail: response.body,
);
}
@@ -796,7 +796,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.user_status_update',
'상태 업데이트에 실패했습니다: {{error}}',
'Failed to update the user status: {{error}}',
detail: response.body,
);
}
@@ -829,7 +829,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.user_update',
'사용자 수정에 실패했습니다: {{error}}',
'Failed to update the user: {{error}}',
detail: response.body,
);
}
@@ -855,7 +855,7 @@ class AuthProxyService {
} else {
throw _error(
'err.userfront.auth_proxy.linked_apps_load',
'연동된 앱 목록을 불러오지 못했습니다.',
'Failed to load linked applications.',
);
}
} finally {
@@ -1043,7 +1043,7 @@ class AuthProxyService {
if (response.statusCode != 200) {
throw _error(
'err.userfront.auth_proxy.phone_code_send',
'인증 코드 전송에 실패했습니다: {{error}}',
'Failed to send the verification code: {{error}}',
detail: response.body,
);
}

View File

@@ -282,9 +282,9 @@ class _ErrorScreenState extends State<ErrorScreen> {
final isProd = widget.isProdOverride ?? AuthProxyService.isProdEnv;
final normalizedCode = (widget.errorCode ?? '').trim();
final hasCode = normalizedCode.isNotEmpty;
final internalWhitelistFallback =
internalErrorWhitelistMessages[normalizedCode];
final isInternalWhitelisted = internalWhitelistFallback != null;
final internalWhitelistKey =
internalErrorWhitelistMessageKeys[normalizedCode];
final isInternalWhitelisted = internalWhitelistKey != null;
final isOryBypass = hasCode && oryBypassErrorCodes.contains(normalizedCode);
final isKnownProdCode = hasCode && (isInternalWhitelisted || isOryBypass);
final isTenantAccessBlocked = normalizedCode == 'tenant_not_allowed';
@@ -294,7 +294,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
final title = isTenantAccessBlocked
? tr(
'msg.userfront.error.tenant.page_title',
fallback: '애플리케이션 접근이 제한되었습니다',
fallback: 'Application access is restricted',
)
: isProd
? tr('msg.userfront.error.title')
@@ -335,14 +335,11 @@ class _ErrorScreenState extends State<ErrorScreen> {
final detail = isTenantAccessBlocked
? tr(
'msg.userfront.error.tenant.detail',
fallback: '현재 로그인된 계정은 이 애플리케이션에 접근할 수 없습니다.',
fallback: 'The current signed-in account cannot access this application.',
)
: isProd
? (isInternalWhitelisted
? tr(
'msg.userfront.error.whitelist.$normalizedCode',
fallback: internalWhitelistFallback,
)
? tr(internalWhitelistKey!)
: (isOryBypass
? tr(
'msg.userfront.error.ory.$normalizedCode',
@@ -422,7 +419,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
Text(
tr(
'msg.userfront.error.tenant.title',
fallback: '접근 제한 정보',
fallback: 'Access restriction details',
),
style: theme.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w700,
@@ -447,7 +444,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
child: Text(
tr(
'msg.userfront.error.tenant.loading',
fallback: '현재 계정 정보를 불러오는 중입니다.',
fallback: 'Loading the current account details.',
),
style: theme.textTheme.bodySmall
?.copyWith(
@@ -462,39 +459,39 @@ class _ErrorScreenState extends State<ErrorScreen> {
_InfoRow(
label: tr(
'msg.userfront.error.tenant.account',
fallback: '계정',
fallback: 'Account',
),
value: emailLabel.isNotEmpty
? emailLabel
: tr(
'msg.userfront.error.tenant.account_unknown',
fallback: '알 수 없음',
fallback: 'Unknown',
),
),
const SizedBox(height: 8),
_InfoRow(
label: tr(
'msg.userfront.error.tenant.primary_tenant',
fallback: '대표 소속 테넌트',
fallback: 'Primary affiliated tenant',
),
value: tenantLabel.isNotEmpty
? tenantLabel
: tr(
'msg.userfront.error.tenant.tenant_unknown',
fallback: '알 수 없음',
fallback: 'Unknown',
),
),
const SizedBox(height: 8),
_InfoRow(
label: tr(
'msg.userfront.error.tenant.affiliated_tenants',
fallback: '전체 소속 테넌트',
fallback: 'All affiliated tenants',
),
value: affiliatedTenantLabels.isNotEmpty
? affiliatedTenantLabels.join(', ')
: tr(
'msg.userfront.error.tenant.tenant_unknown',
fallback: '알 수 없음',
fallback: 'Unknown',
),
),
if (showTenantLookupFallback) ...[
@@ -503,7 +500,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
tr(
'msg.userfront.error.tenant.lookup_fallback',
fallback:
'표시 정보가 충분하지 않아 일부 항목은 확인되지 않을 수 있습니다.',
'Some fields may be unavailable because there is not enough profile information to display.',
),
style: theme.textTheme.bodySmall
?.copyWith(
@@ -518,7 +515,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
tr(
'msg.userfront.error.tenant.load_failed',
fallback:
'계정 정보를 확인하지 못했습니다. 다시 시도해 주세요.',
'Failed to load account details. Please try again.',
),
style: theme.textTheme.bodySmall
?.copyWith(
@@ -548,7 +545,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
Text(
tr(
'msg.userfront.error.tenant.allowed_box_title',
fallback: '접속 가능 테넌트',
fallback: 'Allowed tenants',
),
style: theme.textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.w700,
@@ -559,7 +556,7 @@ class _ErrorScreenState extends State<ErrorScreen> {
_InfoRow(
label: tr(
'msg.userfront.error.tenant.allowed_tenants',
fallback: '접속 가능 테넌트',
fallback: 'Allowed tenants',
),
value: allowedTenantLabels.join(', '),
),
@@ -567,11 +564,11 @@ class _ErrorScreenState extends State<ErrorScreen> {
_InfoRow(
label: tr(
'msg.userfront.error.tenant.allowed_tenants',
fallback: '접속 가능 테넌트',
fallback: 'Allowed tenants',
),
value: tr(
'msg.userfront.error.tenant.tenant_unknown',
fallback: '알 수 없음',
fallback: 'Unknown',
),
),
],

View File

@@ -34,9 +34,41 @@ const Map<String, String> koStrings = {
"err.userfront.auth_proxy.consent_reject": "동의 거부에 실패했습니다.",
"err.userfront.auth_proxy.linked_app_revoke": "연동 해지에 실패했습니다.",
"err.userfront.auth_proxy.login_failed": "로그인에 실패했습니다.",
"err.userfront.auth_proxy.login_init": "로그인 초기화에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.login_poll":
"로그인 상태 확인에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.oidc_accept": "OIDC 로그인 승인에 실패했습니다.",
"err.userfront.auth_proxy.password_reset_complete": "비밀번호 재설정에 실패했습니다.",
"err.userfront.auth_proxy.password_policy_fetch":
"비밀번호 정책을 불러오지 못했습니다.",
"err.userfront.auth_proxy.password_reset_init": "비밀번호 재설정을 시작하지 못했습니다.",
"err.userfront.auth_proxy.profile_load":
"프로필을 불러오지 못했습니다: {{error}}",
"err.userfront.auth_proxy.tenant_info_fetch":
"테넌트 정보를 불러오지 못했습니다.",
"err.userfront.auth_proxy.verify_failed": "검증에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.sms_send": "SMS 전송에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.code_verify":
"인증 코드 확인에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.qr_init":
"QR 로그인을 시작하지 못했습니다: {{error}}",
"err.userfront.auth_proxy.qr_poll":
"QR 상태 확인에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.qr_approve": "QR 승인에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.user_create":
"사용자 생성에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.user_list":
"사용자 목록 조회에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.user_delete":
"사용자 삭제에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.user_status_update":
"상태 업데이트에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.user_update":
"사용자 수정에 실패했습니다: {{error}}",
"err.userfront.auth_proxy.linked_apps_load":
"연동된 앱 목록을 불러오지 못했습니다.",
"err.userfront.auth_proxy.phone_code_send":
"인증 코드 전송에 실패했습니다: {{error}}",
"err.userfront.profile.load_failed": "프로필을 불러오지 못했습니다: {{error}}",
"err.userfront.profile.password_change_failed": "비밀번호 변경에 실패했습니다: {{error}}",
"err.userfront.profile.send_code_failed": "인증번호 전송 실패: {{error}}",
@@ -589,6 +621,8 @@ const Map<String, String> koStrings = {
"재설정 링크가 만료되었습니다. 다시 요청해 주세요.",
"msg.userfront.error.whitelist.recovery_invalid": "재설정 링크가 유효하지 않습니다.",
"msg.userfront.error.whitelist.settings_disabled": "현재 계정 설정 화면은 준비 중입니다.",
"msg.userfront.error.whitelist.tenant_not_allowed":
"허용되지 않은 테넌트입니다.",
"msg.userfront.error.whitelist.verification_required":
"추가 인증이 필요합니다. 안내에 따라 진행해 주세요.",
"msg.userfront.forgot.description":
@@ -2010,11 +2044,46 @@ const Map<String, String> enStrings = {
"err.userfront.auth_proxy.linked_app_revoke":
"Failed to revoke the linked application.",
"err.userfront.auth_proxy.login_failed": "Login failed.",
"err.userfront.auth_proxy.login_init":
"Failed to initialize login: {{error}}",
"err.userfront.auth_proxy.login_poll":
"Failed to check login status: {{error}}",
"err.userfront.auth_proxy.oidc_accept": "OIDC Accept",
"err.userfront.auth_proxy.password_reset_complete":
"Failed to complete the password reset.",
"err.userfront.auth_proxy.password_policy_fetch":
"Failed to load the password policy.",
"err.userfront.auth_proxy.password_reset_init":
"Failed to start the password reset.",
"err.userfront.auth_proxy.profile_load":
"Failed to load the profile: {{error}}",
"err.userfront.auth_proxy.tenant_info_fetch":
"Failed to load tenant information.",
"err.userfront.auth_proxy.verify_failed":
"Verification failed: {{error}}",
"err.userfront.auth_proxy.sms_send": "Failed to send SMS: {{error}}",
"err.userfront.auth_proxy.code_verify":
"Failed to verify the code: {{error}}",
"err.userfront.auth_proxy.qr_init":
"Failed to start QR login: {{error}}",
"err.userfront.auth_proxy.qr_poll":
"Failed to check QR status: {{error}}",
"err.userfront.auth_proxy.qr_approve":
"Failed to approve QR login: {{error}}",
"err.userfront.auth_proxy.user_create":
"Failed to create the user: {{error}}",
"err.userfront.auth_proxy.user_list":
"Failed to load the user list: {{error}}",
"err.userfront.auth_proxy.user_delete":
"Failed to delete the user: {{error}}",
"err.userfront.auth_proxy.user_status_update":
"Failed to update the user status: {{error}}",
"err.userfront.auth_proxy.user_update":
"Failed to update the user: {{error}}",
"err.userfront.auth_proxy.linked_apps_load":
"Failed to load linked applications.",
"err.userfront.auth_proxy.phone_code_send":
"Failed to send the verification code: {{error}}",
"err.userfront.profile.load_failed": "Failed to load the profile.",
"err.userfront.profile.password_change_failed": "Password Change Failed",
"err.userfront.profile.send_code_failed":
@@ -2669,6 +2738,8 @@ const Map<String, String> enStrings = {
"The recovery link is invalid.",
"msg.userfront.error.whitelist.settings_disabled":
"Account settings are currently unavailable.",
"msg.userfront.error.whitelist.tenant_not_allowed":
"This tenant is not allowed.",
"msg.userfront.error.whitelist.verification_required":
"Additional verification is required. Please follow the instructions.",
"msg.userfront.forgot.description":