diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index f4c2a420..55c640c2 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -76,7 +76,7 @@ export const EVENT_TYPES = [ 'UserPasswordReset', 'Test', ] -export const LANGUAGES = ['DE', 'EN', 'ZH']; +export const LANGUAGES = ['DE', 'EN', 'ZH', 'KO']; export const TOKEN_ALGS = [ 'RS256', 'RS384', diff --git a/src/api_types/src/generic.rs b/src/api_types/src/generic.rs index 01e17772..0f9095fe 100644 --- a/src/api_types/src/generic.rs +++ b/src/api_types/src/generic.rs @@ -34,6 +34,7 @@ pub enum Language { En, De, ZhHans, + Ko, } #[derive(Debug, Deserialize, Validate, ToSchema, IntoParams)] diff --git a/src/models/src/entity/well_known.rs b/src/models/src/entity/well_known.rs index b1894213..fcbc4d2b 100644 --- a/src/models/src/entity/well_known.rs +++ b/src/models/src/entity/well_known.rs @@ -147,7 +147,12 @@ impl WellKnown { ]; let service_documentation = "https://sebadob.github.io/rauthy/".to_string(); - let ui_locales_supported = vec!["de".to_string(), "en".to_string(), "zh-hans".to_string()]; + let ui_locales_supported = vec![ + "de".to_string(), + "en".to_string(), + "zh-hans".to_string(), + "ko".to_string(), + ]; WellKnown { issuer: String::from(issuer), diff --git a/src/models/src/i18n/account.rs b/src/models/src/i18n/account.rs index a6276ce9..92990008 100644 --- a/src/models/src/i18n/account.rs +++ b/src/models/src/i18n/account.rs @@ -87,6 +87,7 @@ impl SsrJson for I18nAccount<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -378,6 +379,96 @@ WebID被一些网络用于去中心化登陆。如果您不知道这是什么, zip: "邮政编码", } } + + fn build_ko() -> Self { + Self { + account: "사용자 계정", + acc_type: "계정 종류", + acc_type_passkey_text_1: r#"이 계정은 현재 패스키 전용 계정입니다. +즉, 비밀번호가 필요하지 않으므로, 비밀번호가 전혀 없다는 뜻입니다."#, + acc_type_passkey_text_2: r#"계정을 전환하고 비밀번호를 추가할 수 있습니다. +다만, 이렇게 하면 새 기기를 인증할 때마다 추가적으로 비밀번호 인증을 해야 한다는 것을 명심해 주세요. +한 번도 비밀번호를 입력한 적이 없는 기기에서는 바로 로그인할 수 없습니다."#, + acc_type_passkey_text_3: "계정을 전환하고 비밀번호를 추가하겠습니까?", + access_exp: "접근 만료", + access_renew: "접근 갱신 기한", + access_renew_delete: "갱신할 가능성을 제거", + birthdate: "생년월일", + cancel: "취소", + city: "도시", + change_password: "비밀번호 변경", + convert_account: "계정 전환", + convert_account_p_1: r#"계정을 패스키 전용 계정으로 전환할 수 있습니다. +이 전환은 비밀번호를 삭제하며, 등록된 패스키를 사용해서만 로그인할 수 있습니다. +추가적인 사용자 인증이 가능한 패스키만 허용된다는 점을 명심해 주세요. +패스키가 지원한다면, 'MFA' 페이지에서 키 이름 뒤에 작은 표시가 있는 것을 찾을 수 있을 겁니다."#, + country: "국가", + device_id: "아이디", + device_name: "이름", + devices: "기기", + devices_desc: "이 계정에 연결된 기기", + email: "이메일", + email_update_confirm: r#"아직 이메일 주소가 변경되지 않았습니다. 새 주소로 메시지가 전송되었습니다. +내부에 있는 승인 링크를 클릭해야 합니다. 승인되면 이메일 주소가 새 주소로 변경될 겁니다."#, + email_verified: "이메일 인증 여부", + family_name: "성", + federated_convert_password_1: r#"페더레이션 계정을 가지고 있습니다. 즉, 외부 인증 제공자를 사용하여 +로그인한다는 것을 의미합니다. 현재 제공자는 다음과 같습니다:"#, + federated_convert_password_2: r#"이메일을 통해 비밀번호 초기화를 요청할 수 있습니다. 완료하면 내부적인 +비밀번호가 계정에 추가될 겁니다. 그러면 외부 제공자 또는 내부적인 비밀번호를 통하여 로그인할 수 있습니다. 초기화를 요청하겠습니까?"#, + generate_random: "무작위로 생성", + given_name: "이름", + groups: "그룹", + invalid_input: "유효하지 않은 입력입니다.", + key: "키", + key_unique: "키는 고유해야 합니다.", + last_login: "마지막 로그인 일", + mfa: I18nAccountMfa::build_ko(), + mfa_activated: "MFA 활성화 여부", + nav_info: "정보", + nav_edit: "수정", + nav_mfa: "MFA", + nav_password: "비밀번호", + nav_logout: "로그아웃", + never: "무기한", + optional_values: "선택 항목", + password_confirm: "비밀번호 확인", + password_curr: "현재 비밀번호", + password_curr_req: "현재 비밀번호가 필요합니다.", + password_new: "새 비밀번호", + password_new_req: "새 비밀번호가 필요합니다.", + password_no_match: "비밀번호 확인이 필요합니다.", + password_expiry: "비밀번호 만료일", + password_policy: I18nPasswordPolicy::build_ko(), + password_policy_follow: "비밀번호 정책을 준수해야 합니다.", + password_reset: "비밀번호 초기화", + phone: "전화번호", + provider_link: "페더레이션 계정", + provider_link_desc: r#"이 계정은 다음 중 하나의 로그인 제공자에 연결할 수 있습니다. +이 기능을 활성화하면, 선택한 것의 로그인 페이지로 리다이렉트될 겁니다. 성공적으로 로그인하고 이메일이 일치하면, 계정이 연결될 겁니다."#, + provider_unlink: "페더레이션 해제", + provider_unlink_desc: r#"이 계정에 최소 하나의 비밀번호 또는 패스키를 설정하면, 상위 제공자로부터 연결을 해제할 수 있습니다."#, + reg_date: "가입일", + reg_ip: "IP에서 가입", + roles: "역할", + save: "저장", + street: "주소", + user: "사용자", + user_created: "사용자 생성일", + user_enabled: "사용자 활성화 여부", + user_expiry: "사용자 만료", + user_verified_tooltip: "지문 또는 PIN을 통해 보호", + valid_email: "유효하지 않은 이메일 형식입니다.", + valid_given_name: "이름은 특수문자를 제외한 1자에서 32자이어야 합니다.", + valid_family_name: "성은 특수문자를 제외한 1자에서 32자이어야 합니다.", + web_id_desc: r#"WebID와 함께 노출할 항목을 설정할 수 있습니다. +이 기능은 몇몇 탈중앙화된 로그인 네트워크에서 사용됩니다. 이것이 무엇인지 모르면, 대체로 필요하지 않을 것입니다."#, + web_id_desc_data: + "WebID에서 유효한 FOAF 어휘를 사용자 지정 데이터 항목에 추가할 수 있습니다", + web_id_expert_mode: "전문가 모드 활성화", + zip: "우편번호", + } + } } #[derive(Debug, Default, Serialize)] @@ -408,6 +499,7 @@ impl SsrJson for I18nAccountMfa<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -488,4 +580,27 @@ impl I18nAccountMfa<'_> { test_success: "测试成功!", } } + + pub(crate) fn build_ko() -> Self { + Self { + p_1: "윈도우와 안드로이드와 같은 여러 시스템에서 MFA 키를 사용하려면, 안드로이드에서 등록해야 합니다.", + p_2: "안드로이드는 비밀번호 없이 인증하는 기술을 가장 적게 지원하는 플랫폼 중 하나입니다. \ + 안드로이드에서 등록한 키는 다른 곳에서도 작동합니다. 그러나, 그 반대로는 적용되지 않습니다.", + + delete: "삭제", + error_reg: "가입 절차 시작 중 오류가 발생했습니다.", + invalid_key_used: "유효하지 않은 키가 사용되었습니다.", + last_used: "마지막 사용", + no_key: "이 슬롯에 등록된 보안 키가 없습니다.", + register: "등록", + register_new: "새 키 등록", + registerd: "등록되었습니다.", + registerd_keys: "등록된 키", + passkey_name: "패스키 이름", + passkey_name_err: "특수문자를 제외한 2자에서 32자이어야 합니다.", + test: "테스트", + test_error: "테스트 시작 중에 오류가 발생했습니다.", + test_success: "테스트 성공", + } + } } diff --git a/src/models/src/i18n/authorize.rs b/src/models/src/i18n/authorize.rs index 0365cab4..a40dcb0e 100644 --- a/src/models/src/i18n/authorize.rs +++ b/src/models/src/i18n/authorize.rs @@ -30,6 +30,7 @@ impl SsrJson for I18nAuthorize<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -108,4 +109,27 @@ hinzufügen."#, sign_up: "用户注册", } } + + fn build_ko() -> Self { + Self { + client_force_mfa: r#"이 로그인은 더 높은 수준의 보안을 위해서 MFA를 강제합니다. +접근하려면, 계정에 로그인하고 최소 하나 이상의 패스키를 추가해야 합니다."#, + email: "이메일", + email_bad_format: "잘못된 이메일 형식입니다.", + email_required: "이메일이 필요합니다.", + email_sent_msg: "이메일이 존재하면, 요청이 전송되었을 것입니다.", + http_429: "유효하지 않은 입력이 너무 많습니다. 다음 시간 전까지 비활성화합니다:", + invalid_credentials: "유효하지 않은 인증 정보입니다.", + invalid_key_used: "유효하지 않은 키입니다.", + login: "로그인", + mfa_ack: "확인되었습니다.", + password: "비밀번호", + password_forgotten: "비밀번호를 잊으셨나요?", + password_request: "요청", + password_required: "비밀번호는 필요합니다.", + provide_mfa: "MFA 기기를 통해 로그인해 주세요.", + request_expires: "요청 만료일", + sign_up: "사용자 가입", + } + } } diff --git a/src/models/src/i18n/device.rs b/src/models/src/i18n/device.rs index 78c97ace..565f669a 100644 --- a/src/models/src/i18n/device.rs +++ b/src/models/src/i18n/device.rs @@ -28,6 +28,7 @@ impl SsrJson for I18nDevice<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -96,4 +97,24 @@ impl I18nDevice<'_> { wrong_or_expired: "代码错误或已过期", } } + + fn build_ko() -> Self { + Self { + accept: "수락", + auto_redirect_account: "지금 계정으로 리다이렉트될 예정입니다.", + close_window: "이제 창을 닫아도 됩니다.", + decline: "거절", + desc: "기기에서 {{count}}자의 사용자 코드를 입력해 주세요.", + desc_scopes: "다음 기기가 접근을 요청합니다:", + err_too_short: "입력이 너무 짧습니다.", + err_too_long: "입력이 너무 깁니다.", + invalid_input: "유효하지 않은 입력입니다.", + is_accepted: "요청이 수락되었습니다.", + is_declined: "요청이 거절되었습니다.", + submit: "제출", + title: "기기 인증", + user_code: "사용자 코드", + wrong_or_expired: "잘못되거나 만료된 코드입니다.", + } + } } diff --git a/src/models/src/i18n/email_change_info_new.rs b/src/models/src/i18n/email_change_info_new.rs index 819d0827..d30809bb 100644 --- a/src/models/src/i18n/email_change_info_new.rs +++ b/src/models/src/i18n/email_change_info_new.rs @@ -18,6 +18,7 @@ impl SsrJson for I18nEmailChangeInfoNew<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -60,4 +61,15 @@ impl I18nEmailChangeInfoNew<'_> { button_text: "确认电子邮件地址", } } + + fn build_ko() -> Self { + Self { + subject: "이메일 변경 요청", + header: "이메일 변경 요청:", + click_link: "이메일 주소를 승인하려면 아래에 있는 링크를 클릭해 주세요.", + validity: "이 링크는 보안상의 이유로 짧은 시간 동안에만 유효합니다.", + expires: "링크 만료일:", + button_text: "이메일 승인", + } + } } diff --git a/src/models/src/i18n/email_change_info_old.rs b/src/models/src/i18n/email_change_info_old.rs index b96444c8..ed4855c4 100644 --- a/src/models/src/i18n/email_change_info_old.rs +++ b/src/models/src/i18n/email_change_info_old.rs @@ -19,6 +19,7 @@ impl SsrJson for I18nEmailChangeInfoOld<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -63,4 +64,16 @@ impl I18nEmailChangeInfoOld<'_> { button_text: "阻止地址更改", } } + + fn build_ko() -> Self { + Self { + subject: "이메일 변경 요청", + header: "이메일 변경 요청:", + change_info: "이메일 주소 변경 요청이 있습니다. 새로운 주소:", + click_link: "만약 이 변경을 요청한 적 없으면, 아래의 링크를 클릭해 주세요.", + validity: "이 링크는 보안상의 이유로 짧은 시간 동안에만 유효합니다.", + expires: "링크 만료일:", + button_text: "주소 변경 차단", + } + } } diff --git a/src/models/src/i18n/email_confirm_change.rs b/src/models/src/i18n/email_confirm_change.rs index 1334be79..6d5fafc1 100644 --- a/src/models/src/i18n/email_confirm_change.rs +++ b/src/models/src/i18n/email_confirm_change.rs @@ -15,6 +15,7 @@ impl SsrJson for I18nEmailConfirmChange<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -47,4 +48,12 @@ impl I18nEmailConfirmChange<'_> { msg_from_admin: "此操作由管理员完成。", } } + + fn build_ko() -> Self { + Self { + subject: "이메일 변경이 승인되었습니다:", + msg: "이메일 주소가 다음 주소로 성공적으로 변경되었습니다:", + msg_from_admin: "이 작업은 관리자가 수행했습니다.", + } + } } diff --git a/src/models/src/i18n/email_confirm_change_html.rs b/src/models/src/i18n/email_confirm_change_html.rs index 699ab219..04dfc059 100644 --- a/src/models/src/i18n/email_confirm_change_html.rs +++ b/src/models/src/i18n/email_confirm_change_html.rs @@ -16,6 +16,7 @@ impl SsrJson for I18nEmailConfirmChangeHtml<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -51,4 +52,13 @@ impl I18nEmailConfirmChangeHtml<'_> { to: "更新为", } } + + fn build_ko() -> Self { + Self { + title: "이메일 변경이 승인되었습니다.", + text_changed: "이메일 주소가 다음으로부터 변경되었습니다", + text_login: "이제 새로운 주소로 로그인할 수 있습니다.", + to: "에서", + } + } } diff --git a/src/models/src/i18n/email_password_new.rs b/src/models/src/i18n/email_password_new.rs index 1e2d0fb9..d11200f7 100644 --- a/src/models/src/i18n/email_password_new.rs +++ b/src/models/src/i18n/email_password_new.rs @@ -55,6 +55,23 @@ static TPL_ZH_HANS_PASSWORD_NEW_BUTTON: Lazy> = static TPL_ZH_HANS_PASSWORD_NEW_FOOTER: Lazy> = Lazy::new(|| env::var("TPL_ZH_HANS_PASSWORD_NEW_FOOTER").ok()); +static TPL_KO_PASSWORD_NEW_SUBJECT: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_SUBJECT").ok()); +static TPL_KO_PASSWORD_NEW_HEADER: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_HEADER").ok()); +static TPL_KO_PASSWORD_NEW_TEXT: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_TEXT").ok()); +static TPL_KO_PASSWORD_NEW_CLICK_LINK: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_CLICK_LINK").ok()); +static TPL_KO_PASSWORD_NEW_VALIDITY: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_VALIDITY").ok()); +static TPL_KO_PASSWORD_NEW_EXPIRES: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_EXPIRES").ok()); +static TPL_KO_PASSWORD_NEW_BUTTON: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_BUTTON").ok()); +static TPL_KO_PASSWORD_NEW_FOOTER: Lazy> = + Lazy::new(|| env::var("TPL_KO_PASSWORD_NEW_FOOTER").ok()); + #[derive(Debug, Serialize)] pub struct I18nEmailPasswordNew<'a> { pub subject: &'a str, @@ -73,6 +90,7 @@ impl SsrJson for I18nEmailPasswordNew<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -156,4 +174,29 @@ impl I18nEmailPasswordNew<'_> { footer: TPL_ZH_HANS_PASSWORD_NEW_FOOTER.as_deref(), } } + + fn build_ko() -> Self { + Self { + subject: TPL_KO_PASSWORD_NEW_SUBJECT + .as_deref() + .unwrap_or("새 비밀번호"), + header: TPL_KO_PASSWORD_NEW_HEADER + .as_deref() + .unwrap_or("새 비밀번호를 설정해 주세요:"), + text: TPL_KO_PASSWORD_NEW_TEXT.as_deref(), + click_link: TPL_KO_PASSWORD_NEW_CLICK_LINK + .as_deref() + .unwrap_or("비밀번호 입력창으로 이동하려면, 아래의 링크를 클릭해 주세요."), + validity: TPL_KO_PASSWORD_NEW_VALIDITY + .as_deref() + .unwrap_or("이 링크는 보안상의 이유로 짧은 시간 동안에만 유효합니다."), + expires: TPL_KO_PASSWORD_NEW_EXPIRES + .as_deref() + .unwrap_or("링크 만료일:"), + button_text: TPL_KO_PASSWORD_NEW_BUTTON + .as_deref() + .unwrap_or("비밀번호 설정"), + footer: TPL_KO_PASSWORD_NEW_FOOTER.as_deref(), + } + } } diff --git a/src/models/src/i18n/email_reset.rs b/src/models/src/i18n/email_reset.rs index cdb6e7d2..8039b39c 100644 --- a/src/models/src/i18n/email_reset.rs +++ b/src/models/src/i18n/email_reset.rs @@ -53,6 +53,22 @@ static TPL_ZH_HANS_RESET_BUTTON: Lazy> = static TPL_ZH_HANS_RESET_FOOTER: Lazy> = Lazy::new(|| env::var("TPL_ZH_HANS_RESET_FOOTER").ok()); +static TPL_KO_RESET_SUBJECT: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_SUBJECT").ok()); +static TPL_KO_RESET_HEADER: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_HEADER").ok()); +static TPL_KO_RESET_TEXT: Lazy> = Lazy::new(|| env::var("TPL_KO_RESET_TEXT").ok()); +static TPL_KO_RESET_CLICK_LINK: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_CLICK_LINK").ok()); +static TPL_KO_RESET_VALIDITY: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_VALIDITY").ok()); +static TPL_KO_RESET_EXPIRES: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_EXPIRES").ok()); +static TPL_KO_RESET_BUTTON: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_BUTTON").ok()); +static TPL_KO_RESET_FOOTER: Lazy> = + Lazy::new(|| env::var("TPL_KO_RESET_FOOTER").ok()); + #[derive(Debug, Serialize)] pub struct I18nEmailReset<'a> { pub subject: &'a str, @@ -71,6 +87,7 @@ impl SsrJson for I18nEmailReset<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -148,4 +165,25 @@ impl I18nEmailReset<'_> { footer: TPL_ZH_HANS_RESET_FOOTER.as_deref(), } } + + fn build_ko() -> Self { + Self { + subject: TPL_KO_RESET_SUBJECT + .as_deref() + .unwrap_or("비밀번호 초기화 요청"), + header: TPL_KO_RESET_HEADER + .as_deref() + .unwrap_or("비밀번호 초기화 요청:"), + text: TPL_KO_RESET_TEXT.as_deref(), + click_link: TPL_KO_RESET_CLICK_LINK + .as_deref() + .unwrap_or("비밀번호 초기화 요청 창으로 이동하려면, 아래의 링크를 클릭해 주세요."), + validity: TPL_KO_RESET_VALIDITY + .as_deref() + .unwrap_or("이 링크는 보안상의 이유로 짧은 시간 동안에만 유효합니다."), + expires: TPL_KO_RESET_EXPIRES.as_deref().unwrap_or("링크 만료일:"), + button_text: TPL_KO_RESET_BUTTON.as_deref().unwrap_or("비밀번호 초기화"), + footer: TPL_KO_RESET_FOOTER.as_deref(), + } + } } diff --git a/src/models/src/i18n/email_reset_info.rs b/src/models/src/i18n/email_reset_info.rs index 0a7f1929..adaa6fef 100644 --- a/src/models/src/i18n/email_reset_info.rs +++ b/src/models/src/i18n/email_reset_info.rs @@ -17,6 +17,7 @@ impl SsrJson for I18nEmailResetInfo<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -55,4 +56,14 @@ impl I18nEmailResetInfo<'_> { button_text: "更新密码", } } + + fn build_ko() -> Self { + Self { + subject: "비밀번호가 곧 만료됩니다.", + expires_1: "", + expires_2: "의 비밀번호가 곧 만료됩니다:", + update: "다음에서 변경할 수 있습니다:", + button_text: "비밀번호 변경", + } + } } diff --git a/src/models/src/i18n/error.rs b/src/models/src/i18n/error.rs index 65002f0f..495d2259 100644 --- a/src/models/src/i18n/error.rs +++ b/src/models/src/i18n/error.rs @@ -22,6 +22,7 @@ impl I18nError<'_> { Language::En => Self::build_en(status_code, details_text.map(|t| t.into())), Language::De => Self::build_de(status_code, details_text.map(|t| t.into())), Language::ZhHans => Self::build_zh_hans(status_code, details_text.map(|t| t.into())), + Language::Ko => Self::build_ko(status_code, details_text.map(|t| t.into())), } } } @@ -32,6 +33,7 @@ impl SsrJson for I18nError<'_> { Language::En => Self::build_en(StatusCode::NOT_FOUND, None), Language::De => Self::build_de(StatusCode::NOT_FOUND, None), Language::ZhHans => Self::build_zh_hans(StatusCode::NOT_FOUND, None), + Language::Ko => Self::build_ko(StatusCode::NOT_FOUND, None), } } @@ -92,4 +94,24 @@ impl I18nError<'_> { details_text, } } + + fn build_ko(status_code: StatusCode, details_text: Option>) -> Self { + let error_text = match status_code { + StatusCode::BAD_REQUEST => { + "요청이 손상되었거나 잘못되었습니다. 자세한 정보를 참고해 주세요." + } + StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => { + "접근 거부 - 이 리소스를 사용하거나 접근할 수 없습니다." + } + StatusCode::INTERNAL_SERVER_ERROR => "내부적인 서버 오류", + _ => "요청 정보를 찾을 수 없습니다.", + }; + + Self { + error: status_code.to_string(), + error_text, + details: "자세한 정보 표시", + details_text, + } + } } diff --git a/src/models/src/i18n/index.rs b/src/models/src/i18n/index.rs index ee927a42..4254f3f1 100644 --- a/src/models/src/i18n/index.rs +++ b/src/models/src/i18n/index.rs @@ -16,6 +16,7 @@ impl SsrJson for I18nIndex<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -48,4 +49,12 @@ impl I18nIndex<'_> { admin_login: "管理", } } + + fn build_ko() -> Self { + Self { + register: "가입", + account_login: "계정", + admin_login: "관리", + } + } } diff --git a/src/models/src/i18n/logout.rs b/src/models/src/i18n/logout.rs index b60d8a12..28364ff3 100644 --- a/src/models/src/i18n/logout.rs +++ b/src/models/src/i18n/logout.rs @@ -16,6 +16,7 @@ impl SsrJson for I18nLogout<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -49,4 +50,12 @@ impl I18nLogout<'_> { cancel: "取消", } } + + fn build_ko() -> Self { + Self { + logout: "로그아웃", + confirm_msg: "정말로 로그아웃하고 세션을 종료하겠습니까?", + cancel: "취소", + } + } } diff --git a/src/models/src/i18n/password_policy.rs b/src/models/src/i18n/password_policy.rs index 8a17776a..f2608eb6 100644 --- a/src/models/src/i18n/password_policy.rs +++ b/src/models/src/i18n/password_policy.rs @@ -52,4 +52,17 @@ impl I18nPasswordPolicy<'_> { not_recent: "不是最近使用过的密码之一", } } + + pub fn build_ko() -> Self { + Self { + password_policy: "비밀번호 정책", + length_min: "최소 자수", + length_max: "최대 자수", + lowercase_min: "최소 소문자 자수", + uppercase_min: "최소 대문자 자수", + digits_min: "최소 숫자 자수", + special_min: "최소 특수문자 자수", + not_recent: "최근 사용한 비밀번호 중 하나가 아닌 것", + } + } } diff --git a/src/models/src/i18n/password_reset.rs b/src/models/src/i18n/password_reset.rs index b5cb2d21..c346fdf3 100644 --- a/src/models/src/i18n/password_reset.rs +++ b/src/models/src/i18n/password_reset.rs @@ -37,6 +37,7 @@ impl SsrJson for I18nPasswordReset<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -145,4 +146,34 @@ Reset via E-Mail nutzen für den Fall, dass der derzeitige Passkey abhanden komm 对于仅密钥登陆的账户,在丢失您当前的密钥时,您无法通过电子邮件进行密码重置。"#, } } + + pub fn build_ko() -> Self { + Self { + password_policy: I18nPasswordPolicy::build_ko(), + + account_login: "계정 로그인", + bad_format: "잘못된 형식", + fido_link: "https://fidoalliance.org/fido2/?lang=ko", + generate: "생성", + mfa: I18nAccountMfa::build_ko(), + new_acc_desc_1: "계정 종류는 비밀번호가 없는 계정 또는 기존의 비밀번호가 있는 계정 중 하나를 선택할 수 있습니다.", + new_acc_desc_2: r#"비밀번호가 없는 계정은 더 강력한 보안 방법을 제공하기 때문에 항상 선호됩니다. +이러한 계정을 생성하려면 최소 하나의 패스키(Yubikey, Apple Touch ID, Windows Hello, ...)가 필요합니다. 기기가 FIDO2 표준을 지원해야 합니다. +더 자세한 사항은 다음 링크를 참고해 주세요: "#, + new_account: "새 계정", + password_reset: "비밀번호 초기화", + password: "비밀번호", + passwordless: "FIDO 패스키", + password_confirm: "비밀번호 확인", + password_no_match: "비밀번호가 일치하지 않습니다.", + required: "필수", + save: "저장", + success_1: "비밀번호가 성공적으로 변경되었습니다.", + success_2: "곧 리다이렉트됩니다.", + success_3: "만약 리다이렉트가 되지 않으면, 여기를 클릭해 주세요:", + success_passkey_1: "새로운 패스키가 성공적으로 등록되었습니다.", + success_passkey_2: r#"계정에 로그인하여 가능한 한 빨리 두 번째 백업 키를 등록해 주세요. +패스키 전용 계정은 현재 패스키를 잃어버리면, 이메일을 통하여 비밀번호 초기화할 수 없습니다."#, + } + } } diff --git a/src/models/src/i18n/register.rs b/src/models/src/i18n/register.rs index 89551822..a61f39c6 100644 --- a/src/models/src/i18n/register.rs +++ b/src/models/src/i18n/register.rs @@ -26,6 +26,7 @@ impl SsrJson for I18nRegister<'_> { Language::En => Self::build_en(), Language::De => Self::build_de(), Language::ZhHans => Self::build_zh_hans(), + Language::Ko => Self::build_ko(), } } @@ -88,4 +89,22 @@ impl I18nRegister<'_> { user_reg: "用户注册", } } + + fn build_ko() -> Self { + Self { + domain_allowed: "허용된 도메인:", + domain_err: "허용되지 않은 이메일의 도메인입니다.", + domain_restricted: "이메일의 도메인이 제한되어 있습니다.", + email: "이메일", + email_bad_format: "잘못된 이메일 형식입니다.", + email_check: "이메일 보관함을 확인해 주세요.", + family_name: "성", + given_name: "이름", + regex_name: "이름은 특수문자를 제외한 2자에서 32자이어야 합니다.", + register: "가입", + required: "필수 항목입니다.", + success: "성공적으로 가입되었습니다.", + user_reg: "사용자 가입", + } + } } diff --git a/src/models/src/language.rs b/src/models/src/language.rs index 6155a923..d5c51f9d 100644 --- a/src/models/src/language.rs +++ b/src/models/src/language.rs @@ -16,11 +16,12 @@ pub enum Language { En, De, ZhHans, + Ko, } impl Language { - fn all_available<'a>() -> [&'a str; 6] { - ["en", "en-US", "de", "de-DE", "zh", "zh-Hans"] + fn all_available<'a>() -> [&'a str; 7] { + ["en", "en-US", "de", "de-DE", "zh", "zh-Hans", "ko"] } pub fn as_str(&self) -> &str { @@ -28,6 +29,7 @@ impl Language { Language::En => "en", Language::De => "de", Language::ZhHans => "zh-Hans", + Language::Ko => "ko", } } } @@ -62,6 +64,7 @@ impl From<&str> for Language { "de" | "de-DE" => Self::De, "en" | "en-US" => Self::En, "zh" | "zh-hans" | "zh-Hans" => Self::ZhHans, + "ko" | "ko-KR" => Self::Ko, _ => Self::default(), } } @@ -101,6 +104,7 @@ impl From for Language { rauthy_api_types::generic::Language::En => Self::En, rauthy_api_types::generic::Language::De => Self::De, rauthy_api_types::generic::Language::ZhHans => Self::ZhHans, + rauthy_api_types::generic::Language::Ko => Self::Ko, } } } @@ -111,6 +115,7 @@ impl From for rauthy_api_types::generic::Language { Language::En => Self::En, Language::De => Self::De, Language::ZhHans => Self::ZhHans, + Language::Ko => Self::Ko, } } }