diff --git a/packages/console/src/assets/icons/factor-backup-code.svg b/packages/console/src/assets/icons/factor-backup-code.svg new file mode 100644 index 000000000..3f32f449e --- /dev/null +++ b/packages/console/src/assets/icons/factor-backup-code.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/console/src/assets/icons/factor-totp.svg b/packages/console/src/assets/icons/factor-totp.svg new file mode 100644 index 000000000..826eb5eaf --- /dev/null +++ b/packages/console/src/assets/icons/factor-totp.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/console/src/assets/icons/factor-webauthn.svg b/packages/console/src/assets/icons/factor-webauthn.svg new file mode 100644 index 000000000..8f9d92c1f --- /dev/null +++ b/packages/console/src/assets/icons/factor-webauthn.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/console/src/assets/icons/security-lock.svg b/packages/console/src/assets/icons/security-lock.svg new file mode 100644 index 000000000..be9137b46 --- /dev/null +++ b/packages/console/src/assets/icons/security-lock.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/console/src/consts/env.ts b/packages/console/src/consts/env.ts index 8ceda539e..147fa6d25 100644 --- a/packages/console/src/consts/env.ts +++ b/packages/console/src/consts/env.ts @@ -1,6 +1,5 @@ import { yes } from '@silverhand/essentials'; -// eslint-disable-next-line import/no-unused-modules export const isProduction = process.env.NODE_ENV === 'production'; export const isCloud = yes(process.env.IS_CLOUD); export const adminEndpoint = process.env.ADMIN_ENDPOINT; diff --git a/packages/console/src/containers/ConsoleContent/Sidebar/hook.tsx b/packages/console/src/containers/ConsoleContent/Sidebar/hook.tsx index daeec0002..5293a2bb8 100644 --- a/packages/console/src/containers/ConsoleContent/Sidebar/hook.tsx +++ b/packages/console/src/containers/ConsoleContent/Sidebar/hook.tsx @@ -12,6 +12,7 @@ import List from '@/assets/icons/list.svg'; import UserProfile from '@/assets/icons/profile.svg'; import ResourceIcon from '@/assets/icons/resource.svg'; import Role from '@/assets/icons/role.svg'; +import SecurityLock from '@/assets/icons/security-lock.svg'; import Web from '@/assets/icons/web.svg'; import { isCloud } from '@/consts/env'; import useUserPreferences from '@/hooks/use-user-preferences'; @@ -78,6 +79,10 @@ export const useSidebarMenuItems = (): { Icon: Web, title: 'sign_in_experience', }, + { + Icon: SecurityLock, + title: 'mfa', + }, { Icon: Connection, title: 'connectors', diff --git a/packages/console/src/containers/ConsoleContent/index.tsx b/packages/console/src/containers/ConsoleContent/index.tsx index fb780366a..46a71c78c 100644 --- a/packages/console/src/containers/ConsoleContent/index.tsx +++ b/packages/console/src/containers/ConsoleContent/index.tsx @@ -9,7 +9,7 @@ import { TenantSettingsTabs, ApplicationDetailsTabs, } from '@/consts'; -import { isCloud } from '@/consts/env'; +import { isCloud, isProduction } from '@/consts/env'; import OverlayScrollbar from '@/ds-components/OverlayScrollbar'; import useUserPreferences from '@/hooks/use-user-preferences'; import ApiResourceDetails from '@/pages/ApiResourceDetails'; @@ -24,6 +24,7 @@ import ConnectorDetails from '@/pages/ConnectorDetails'; import Connectors from '@/pages/Connectors'; import Dashboard from '@/pages/Dashboard'; import GetStarted from '@/pages/GetStarted'; +import Mfa from '@/pages/Mfa'; import NotFound from '@/pages/NotFound'; import Profile from '@/pages/Profile'; import ChangePasswordModal from '@/pages/Profile/containers/ChangePasswordModal'; @@ -97,6 +98,7 @@ function ConsoleContent() { } /> } /> + {!isProduction && } />} } /> } /> diff --git a/packages/console/src/ds-components/Switch/index.module.scss b/packages/console/src/ds-components/Switch/index.module.scss index 8fd171d4d..2605536d2 100644 --- a/packages/console/src/ds-components/Switch/index.module.scss +++ b/packages/console/src/ds-components/Switch/index.module.scss @@ -58,4 +58,12 @@ margin-right: _.unit(2); font: var(--font-body-2); } + + &.error { + border-color: var(--color-error); + + &:focus-within { + outline-color: var(--color-danger-focused); + } + } } diff --git a/packages/console/src/ds-components/Switch/index.tsx b/packages/console/src/ds-components/Switch/index.tsx index 094d6fdd8..4342e65ee 100644 --- a/packages/console/src/ds-components/Switch/index.tsx +++ b/packages/console/src/ds-components/Switch/index.tsx @@ -1,3 +1,4 @@ +import classNames from 'classnames'; import type { HTMLProps, ReactNode, Ref } from 'react'; import { forwardRef } from 'react'; @@ -5,11 +6,12 @@ import * as styles from './index.module.scss'; type Props = Omit, 'label'> & { label?: ReactNode; + hasError?: boolean; }; -function Switch({ label, ...rest }: Props, ref?: Ref) { +function Switch({ label, hasError, ...rest }: Props, ref?: Ref) { return ( - + {label} diff --git a/packages/console/src/pages/Mfa/MfaForm/FactorLabel/index.module.scss b/packages/console/src/pages/Mfa/MfaForm/FactorLabel/index.module.scss new file mode 100644 index 000000000..f5106c920 --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/FactorLabel/index.module.scss @@ -0,0 +1,20 @@ +@use '@/scss/underscore' as _; + +.factorLabel { + display: flex; + flex-direction: column; + gap: _.unit(1); + font: var(--font-body-2); + color: var(--color-text-secondary); +} + +.factorTitle { + display: flex; + align-items: center; + color: var(--color-text); + + .factorIcon { + color: var(--color-text-secondary); + margin-right: _.unit(3); + } +} diff --git a/packages/console/src/pages/Mfa/MfaForm/FactorLabel/index.tsx b/packages/console/src/pages/Mfa/MfaForm/FactorLabel/index.tsx new file mode 100644 index 000000000..c232c9ae5 --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/FactorLabel/index.tsx @@ -0,0 +1,28 @@ +import { type AdminConsoleKey } from '@logto/phrases'; +import { type ReactElement, cloneElement } from 'react'; + +import DynamicT from '@/ds-components/DynamicT'; + +import * as styles from './index.module.scss'; + +type Props = { + title: AdminConsoleKey; + description: AdminConsoleKey; + icon: ReactElement; +}; + +function FactorLabel({ title, description, icon }: Props) { + return ( + + + {cloneElement(icon, { className: styles.factorIcon })} + + + + + + + ); +} + +export default FactorLabel; diff --git a/packages/console/src/pages/Mfa/MfaForm/PolicyOptionTitle/index.module.scss b/packages/console/src/pages/Mfa/MfaForm/PolicyOptionTitle/index.module.scss new file mode 100644 index 000000000..8e801ef12 --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/PolicyOptionTitle/index.module.scss @@ -0,0 +1,12 @@ +@use '@/scss/underscore' as _; + +.policyLabel { + font: var(--font-body-2); + display: flex; + flex-direction: column; + gap: _.unit(1); +} + +.description { + color: var(--color-text-secondary); +} diff --git a/packages/console/src/pages/Mfa/MfaForm/PolicyOptionTitle/index.tsx b/packages/console/src/pages/Mfa/MfaForm/PolicyOptionTitle/index.tsx new file mode 100644 index 000000000..b270567f7 --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/PolicyOptionTitle/index.tsx @@ -0,0 +1,25 @@ +import { type AdminConsoleKey } from '@logto/phrases'; + +import DynamicT from '@/ds-components/DynamicT'; + +import * as styles from './index.module.scss'; + +export type Props = { + title: AdminConsoleKey; + description: AdminConsoleKey; +}; + +function PolicyOptionTitle({ title, description }: Props) { + return ( + + + + + + + + + ); +} + +export default PolicyOptionTitle; diff --git a/packages/console/src/pages/Mfa/MfaForm/constants.ts b/packages/console/src/pages/Mfa/MfaForm/constants.ts new file mode 100644 index 000000000..427ebb1cf --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/constants.ts @@ -0,0 +1,14 @@ +import { MfaPolicy } from '@logto/schemas'; + +import { type Props as PolicyOptionTitleProps } from './PolicyOptionTitle'; + +export const policyOptionTitlePropsMap: Record = { + [MfaPolicy.UserControlled]: { + title: 'mfa.user_controlled', + description: 'mfa.user_controlled_description', + }, + [MfaPolicy.Mandatory]: { + title: 'mfa.mandatory', + description: 'mfa.mandatory_description', + }, +}; diff --git a/packages/console/src/pages/Mfa/MfaForm/index.module.scss b/packages/console/src/pages/Mfa/MfaForm/index.module.scss new file mode 100644 index 000000000..0226d6c7a --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/index.module.scss @@ -0,0 +1,31 @@ +@use '@/scss/underscore' as _; + +.factorField { + display: flex; + flex-direction: column; + gap: _.unit(4); +} + +.fieldDescription { + font: var(--font-body-2); + color: var(--color-text-secondary); + margin-bottom: _.unit(2); +} + +.backupCodeField { + display: flex; + flex-direction: column; + gap: _.unit(2); + + .backupCodeDescription { + margin-bottom: unset; + } +} + +.policyRadio { + > div[class$='content'] { + > div[class$='indicator'] { + align-self: flex-start; + } + } +} diff --git a/packages/console/src/pages/Mfa/MfaForm/index.tsx b/packages/console/src/pages/Mfa/MfaForm/index.tsx new file mode 100644 index 000000000..e3527d146 --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/index.tsx @@ -0,0 +1,162 @@ +import { MfaPolicy, type SignInExperience } from '@logto/schemas'; +import classNames from 'classnames'; +import { useMemo } from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import { toast } from 'react-hot-toast'; +import { useTranslation } from 'react-i18next'; + +import FactorBackupCode from '@/assets/icons/factor-backup-code.svg'; +import FactorOtp from '@/assets/icons/factor-totp.svg'; +import FactorWebAuthn from '@/assets/icons/factor-webauthn.svg'; +import DetailsForm from '@/components/DetailsForm'; +import FormCard from '@/components/FormCard'; +import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal'; +import DynamicT from '@/ds-components/DynamicT'; +import FormField from '@/ds-components/FormField'; +import InlineNotification from '@/ds-components/InlineNotification'; +import RadioGroup, { Radio } from '@/ds-components/RadioGroup'; +import Switch from '@/ds-components/Switch'; +import useApi from '@/hooks/use-api'; +import { trySubmitSafe } from '@/utils/form'; + +import { type MfaConfigForm, type MfaConfig } from '../types'; + +import FactorLabel from './FactorLabel'; +import PolicyOptionTitle from './PolicyOptionTitle'; +import { policyOptionTitlePropsMap } from './constants'; +import * as styles from './index.module.scss'; +import { convertMfaFormToConfig, convertMfaConfigToForm, validateBackupCodeFactor } from './utils'; + +type Props = { + data: MfaConfig; + onMfaUpdated: (updatedData: MfaConfig) => void; +}; + +function MfaForm({ data, onMfaUpdated }: Props) { + const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); + const { + register, + reset, + formState: { isDirty, isSubmitting }, + handleSubmit, + control, + watch, + } = useForm({ defaultValues: convertMfaConfigToForm(data), mode: 'onChange' }); + const api = useApi(); + + const formValues = watch(); + + const isBackupCodeAllowed = useMemo(() => { + const { factors } = convertMfaFormToConfig(formValues); + return validateBackupCodeFactor(factors); + }, [formValues]); + + const onSubmit = handleSubmit( + trySubmitSafe(async (formData) => { + const mfaConfig = convertMfaFormToConfig(formData); + if (!validateBackupCodeFactor(mfaConfig.factors)) { + return; + } + + const { mfa: updatedMfaConfig } = await api + .patch('api/sign-in-exp', { + json: { mfa: mfaConfig }, + }) + .json(); + reset(convertMfaConfigToForm(updatedMfaConfig)); + toast.success(t('general.saved')); + onMfaUpdated(updatedMfaConfig); + }) + ); + + return ( + <> + + + + + + + + } + /> + } + {...register('totpEnabled')} + /> + } + /> + } + {...register('webAuthnEnabled')} + /> + + + + + } + /> + } + hasError={!isBackupCodeAllowed} + {...register('backupCodeEnabled')} + /> + {!isBackupCodeAllowed && ( + + + + )} + + + + + + + + + + ( + + {Object.values(MfaPolicy).map((policy) => { + const titleProps = policyOptionTitlePropsMap[policy]; + return ( + } + value={policy} + /> + ); + })} + + )} + /> + + + + + > + ); +} + +export default MfaForm; diff --git a/packages/console/src/pages/Mfa/MfaForm/utils.ts b/packages/console/src/pages/Mfa/MfaForm/utils.ts new file mode 100644 index 000000000..a78a97ac0 --- /dev/null +++ b/packages/console/src/pages/Mfa/MfaForm/utils.ts @@ -0,0 +1,31 @@ +import { MfaFactor } from '@logto/schemas'; +import { conditional } from '@silverhand/essentials'; + +import { type MfaConfig, type MfaConfigForm } from '../types'; + +export const convertMfaConfigToForm = ({ policy, factors }: MfaConfig): MfaConfigForm => ({ + policy, + totpEnabled: factors.includes(MfaFactor.TOTP), + webAuthnEnabled: factors.includes(MfaFactor.WebAuthn), + backupCodeEnabled: factors.includes(MfaFactor.BackupCode), +}); + +export const convertMfaFormToConfig = (mfaConfigForm: MfaConfigForm): MfaConfig => { + const { policy, totpEnabled, webAuthnEnabled, backupCodeEnabled } = mfaConfigForm; + + const factors = [ + conditional(totpEnabled && MfaFactor.TOTP), + conditional(webAuthnEnabled && MfaFactor.WebAuthn), + conditional(backupCodeEnabled && MfaFactor.BackupCode), + // eslint-disable-next-line unicorn/prefer-native-coercion-functions + ].filter((factor): factor is MfaFactor => Boolean(factor)); + + return { + policy, + factors, + }; +}; + +export const validateBackupCodeFactor = (factors: MfaFactor[]): boolean => { + return !(factors.length === 1 && factors.includes(MfaFactor.BackupCode)); +}; diff --git a/packages/console/src/pages/Mfa/PageWrapper/index.module.scss b/packages/console/src/pages/Mfa/PageWrapper/index.module.scss new file mode 100644 index 000000000..ec0e9bcea --- /dev/null +++ b/packages/console/src/pages/Mfa/PageWrapper/index.module.scss @@ -0,0 +1,12 @@ +@use '@/scss/underscore' as _; + +.container { + display: flex; + flex-direction: column; + min-height: 100%; + + .cardTitle { + flex-shrink: 0; + margin-bottom: _.unit(4); + } +} diff --git a/packages/console/src/pages/Mfa/PageWrapper/index.tsx b/packages/console/src/pages/Mfa/PageWrapper/index.tsx new file mode 100644 index 000000000..42d83ff4d --- /dev/null +++ b/packages/console/src/pages/Mfa/PageWrapper/index.tsx @@ -0,0 +1,22 @@ +import { type ReactNode } from 'react'; + +import PageMeta from '@/components/PageMeta'; +import CardTitle from '@/ds-components/CardTitle'; + +import * as styles from './index.module.scss'; + +type Props = { + children: ReactNode; +}; + +function PageWrapper({ children }: Props) { + return ( + + + + {children} + + ); +} + +export default PageWrapper; diff --git a/packages/console/src/pages/Mfa/Skeleton/index.module.scss b/packages/console/src/pages/Mfa/Skeleton/index.module.scss new file mode 100644 index 000000000..01b354dc2 --- /dev/null +++ b/packages/console/src/pages/Mfa/Skeleton/index.module.scss @@ -0,0 +1,7 @@ +@use '@/scss/underscore' as _; + +.container { + display: flex; + flex-direction: column; + gap: _.unit(4); +} diff --git a/packages/console/src/pages/Mfa/Skeleton/index.tsx b/packages/console/src/pages/Mfa/Skeleton/index.tsx new file mode 100644 index 000000000..3bb6647fe --- /dev/null +++ b/packages/console/src/pages/Mfa/Skeleton/index.tsx @@ -0,0 +1,14 @@ +import { FormCardSkeleton } from '@/components/FormCard'; + +import * as styles from './index.module.scss'; + +function Skeleton() { + return ( + + + + + ); +} + +export default Skeleton; diff --git a/packages/console/src/pages/Mfa/index.tsx b/packages/console/src/pages/Mfa/index.tsx new file mode 100644 index 000000000..45cc18c4c --- /dev/null +++ b/packages/console/src/pages/Mfa/index.tsx @@ -0,0 +1,47 @@ +import { withAppInsights } from '@logto/app-insights/react/AppInsightsReact'; +import { type SignInExperience } from '@logto/schemas'; +import useSWR from 'swr'; + +import RequestDataError from '@/components/RequestDataError'; +import { type RequestError } from '@/hooks/use-api'; + +import MfaForm from './MfaForm'; +import PageWrapper from './PageWrapper'; +import Skeleton from './Skeleton'; + +function Mfa() { + const { data, error, mutate, isLoading } = useSWR( + 'api/sign-in-exp' + ); + + if (isLoading) { + return ( + + + + ); + } + + if (error) { + return ( + + + + ); + } + + return ( + + {data && ( + { + void mutate({ ...data, mfa }); + }} + /> + )} + + ); +} + +export default withAppInsights(Mfa); diff --git a/packages/console/src/pages/Mfa/types.ts b/packages/console/src/pages/Mfa/types.ts new file mode 100644 index 000000000..fb0765d08 --- /dev/null +++ b/packages/console/src/pages/Mfa/types.ts @@ -0,0 +1,10 @@ +import { type MfaPolicy, type SignInExperience } from '@logto/schemas'; + +export type MfaConfig = SignInExperience['mfa']; + +export type MfaConfigForm = { + policy: MfaPolicy; + totpEnabled: boolean; + webAuthnEnabled: boolean; + backupCodeEnabled: boolean; +}; diff --git a/packages/integration-tests/src/tests/console/mfa/helpers.ts b/packages/integration-tests/src/tests/console/mfa/helpers.ts new file mode 100644 index 000000000..edf3e2a7d --- /dev/null +++ b/packages/integration-tests/src/tests/console/mfa/helpers.ts @@ -0,0 +1,15 @@ +import { type Page } from 'puppeteer'; + +export const expectToClickFactor = async (page: Page, inputName: string) => { + await expect(page).toClick(`form label[class$=switch]:has(input[name="${inputName}"])`); +}; + +export const expectToClickPolicyOption = async (page: Page, inputName: string) => { + await expect(page).toClick(`form div[role=radio]:has(input[name=policy][value=${inputName}])`); +}; + +export const expectBackupCodeSetupError = async (page: Page) => { + await expect(page).toMatchElement('form div[class*=inlineNotification] div[class$=content]', { + text: 'To use Backup code for MFA, other factors must be turned on to ensure your users successful sign-in.', + }); +}; diff --git a/packages/integration-tests/src/tests/console/mfa/index.test.ts b/packages/integration-tests/src/tests/console/mfa/index.test.ts new file mode 100644 index 000000000..4ff7cc58c --- /dev/null +++ b/packages/integration-tests/src/tests/console/mfa/index.test.ts @@ -0,0 +1,63 @@ +import { logtoConsoleUrl } from '#src/constants.js'; +import { + expectMainPageWithTitle, + expectToClickSidebarMenu, + expectToSaveChanges, + goToAdminConsole, + waitForToast, +} from '#src/ui-helpers/index.js'; + +import { + expectBackupCodeSetupError, + expectToClickFactor, + expectToClickPolicyOption, +} from './helpers.js'; + +await page.setViewport({ width: 1920, height: 1080 }); + +describe('multi-factor authentication', () => { + beforeAll(async () => { + await goToAdminConsole(); + }); + + it('navigate to multi-factor authentication page', async () => { + await expectToClickSidebarMenu(page, 'Multi-factor auth'); + await expectMainPageWithTitle(page, 'Multi-factor authentication'); + expect(page.url()).toBe(new URL(`console/mfa`, new URL(logtoConsoleUrl)).href); + }); + + it('should be able to update multi-factors', async () => { + // Cannot enable backup code alone + await expectToClickFactor(page, 'backupCodeEnabled'); + await expectBackupCodeSetupError(page); + + // Enable webAuthn + await expectToClickFactor(page, 'webAuthnEnabled'); + + // The backup code error should disappear + await expect(expectBackupCodeSetupError(page)).rejects.toThrow(); + await expectToSaveChanges(page); + await waitForToast(page, { text: 'Saved' }); + + // Enable totp + await expectToClickFactor(page, 'totpEnabled'); + await expectToSaveChanges(page); + await waitForToast(page, { text: 'Saved' }); + }); + + it('should be able to update policy', async () => { + await expect(page).toClick('form div[role=radio]:has(input[name=policy][value=Mandatory])'); + await expectToClickPolicyOption(page, 'Mandatory'); + await expectToSaveChanges(page); + await waitForToast(page, { text: 'Saved' }); + }); + + it('reset mfa settings', async () => { + await expectToClickFactor(page, 'backupCodeEnabled'); + await expectToClickFactor(page, 'webAuthnEnabled'); + await expectToClickFactor(page, 'totpEnabled'); + await expectToClickPolicyOption(page, 'UserControlled'); + await expectToSaveChanges(page); + await waitForToast(page, { text: 'Saved' }); + }); +}); diff --git a/packages/integration-tests/src/ui-helpers/index.ts b/packages/integration-tests/src/ui-helpers/index.ts index 32937d4eb..b6565ab76 100644 --- a/packages/integration-tests/src/ui-helpers/index.ts +++ b/packages/integration-tests/src/ui-helpers/index.ts @@ -131,11 +131,14 @@ export const expectToOpenNewPage = async (browser: Browser, url: string) => { }; export const expectMainPageWithTitle = async (page: Page, title: string) => { - await expect(page).toMatchElement( - 'div[class$=main] div[class$=headline] div[class$=titleEllipsis]', - { - text: title, - timeout: 2000, - } - ); + await expect(page).toMatchElement('div[class$=main] div[class$=titleEllipsis]', { + text: title, + timeout: 2000, + }); +}; + +export const expectToClickSidebarMenu = async (page: Page, menuText: string) => { + await expect(page).toClick('div[class$=sidebar] a div[class$=title]', { + text: menuText, + }); }; diff --git a/packages/phrases/src/locales/de/translation/admin-console/index.ts b/packages/phrases/src/locales/de/translation/admin-console/index.ts index c40df5942..278ad6a90 100644 --- a/packages/phrases/src/locales/de/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/de/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/de/translation/admin-console/mfa.ts b/packages/phrases/src/locales/de/translation/admin-console/mfa.ts new file mode 100644 index 000000000..b075e635d --- /dev/null +++ b/packages/phrases/src/locales/de/translation/admin-console/mfa.ts @@ -0,0 +1,35 @@ +const mfa = { + title: 'Multi-Faktor-Authentifizierung', + description: + 'Fügen Sie der Sicherheit Ihres Anmeldeerlebnisses die Multi-Faktor-Authentifizierung hinzu.', + factors: 'Faktoren', + multi_factors: 'Multi-Faktoren', + multi_factors_description: + 'Benutzer müssen einen der aktivierten Faktoren zur zweistufigen Authentifizierung überprüfen.', + totp: 'Authenticator-App OTP', + otp_description: 'Verknüpfen Sie Google Authenticator usw., um Einmalpasswörter zu überprüfen.', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthn verwendet den Passkey, um das Gerät des Benutzers zu überprüfen, einschließlich YubiKey.', + backup_code: 'Backup-Code', + backup_code_description: + 'Generieren Sie 10 eindeutige Codes, von denen jeder für eine einzige Authentifizierung verwendet werden kann.', + backup_code_setup_hint: + 'Der Backup-Authentifizierungsfaktor, der nicht alleine aktiviert werden kann:', + backup_code_error_hint: + 'Um den Backup-Code für MFA zu verwenden, müssen andere Faktoren aktiviert sein, um die erfolgreiche Anmeldung Ihrer Benutzer sicherzustellen.', + policy: 'Richtlinie', + two_step_sign_in_policy: 'Zwei-Schritt-Authentifizierungsrichtlinie bei der Anmeldung', + two_step_sign_in_policy_description: + 'Definieren Sie eine app-weite Anforderung für die zweistufige Authentifizierung bei der Anmeldung.', + user_controlled: 'Benutzerkontrolliert', + user_controlled_description: + 'Standardmäßig deaktiviert und nicht obligatorisch, aber Benutzer können es individuell aktivieren.', + mandatory: 'Obligatorisch', + mandatory_description: 'Erfordern Sie MFA für alle Ihre Benutzer bei jeder Anmeldung.', + unlock_reminder: + 'Entsperren Sie die MFA zur Sicherheitsüberprüfung durch ein Upgrade auf einen kostenpflichtigen Plan. Zögern Sie nicht, uns zu kontaktieren, wenn Sie Unterstützung benötigen.', + view_plans: 'Pläne anzeigen', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/de/translation/admin-console/tabs.ts b/packages/phrases/src/locales/de/translation/admin-console/tabs.ts index 96a9d9c80..799f50525 100644 --- a/packages/phrases/src/locales/de/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/de/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Rollen', docs: 'Dokumentation', tenant_settings: 'Einstellungen', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/en/translation/admin-console/index.ts b/packages/phrases/src/locales/en/translation/admin-console/index.ts index d8c90f87d..6884f5746 100644 --- a/packages/phrases/src/locales/en/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/en/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/en/translation/admin-console/mfa.ts b/packages/phrases/src/locales/en/translation/admin-console/mfa.ts new file mode 100644 index 000000000..3d669d3b1 --- /dev/null +++ b/packages/phrases/src/locales/en/translation/admin-console/mfa.ts @@ -0,0 +1,32 @@ +const mfa = { + title: 'Multi-factor authentication', + description: + 'Add multi-factor authentication to elevate the security of your sign-in experience.', + factors: 'Factors', + multi_factors: 'Multi-factors', + multi_factors_description: + 'Users need to verify one of the enabled factors for two-step authentication.', + totp: 'Authenticator app OTP', + otp_description: 'Link Google Authenticator, etc., to verify one-time passwords.', + webauthn: 'WebAuthn', + webauthn_description: 'WebAuthn uses the passkey to verify the user’s device including YubiKey.', + backup_code: 'Backup code', + backup_code_description: 'Generate 10 unique codes, each usable for a single authentication.', + backup_code_setup_hint: 'The backup authentication factor which can not be enabled alone:', + backup_code_error_hint: + 'To use Backup code for MFA, other factors must be turned on to ensure your users successful sign-in.', + policy: 'Policy', + two_step_sign_in_policy: 'Two-step authentication policy at sign-in', + two_step_sign_in_policy_description: + 'Define a app-wide 2-step authentication requirement for sign-in.', + user_controlled: 'User-controlled', + user_controlled_description: + 'Disabled by default and not mandatory, but users can enable it individually.', + mandatory: 'Mandatory', + mandatory_description: 'Require MFA for all your users at every sign-in.', + unlock_reminder: + 'Unlock MFA to verification security by upgrading to a paid plan. Don’t hesitate to contact us if you need any assistance.', + view_plans: 'View plans', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/en/translation/admin-console/tabs.ts b/packages/phrases/src/locales/en/translation/admin-console/tabs.ts index ff3d89ebc..d5206b6ec 100644 --- a/packages/phrases/src/locales/en/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/en/translation/admin-console/tabs.ts @@ -11,6 +11,7 @@ const tabs = { roles: 'Roles', docs: 'Docs', tenant_settings: 'Settings', + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/es/translation/admin-console/index.ts b/packages/phrases/src/locales/es/translation/admin-console/index.ts index 92723d3a8..dc836b089 100644 --- a/packages/phrases/src/locales/es/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/es/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/es/translation/admin-console/mfa.ts b/packages/phrases/src/locales/es/translation/admin-console/mfa.ts new file mode 100644 index 000000000..e52ee8acf --- /dev/null +++ b/packages/phrases/src/locales/es/translation/admin-console/mfa.ts @@ -0,0 +1,36 @@ +const mfa = { + title: 'Autenticación multifactor', + description: + 'Agrega autenticación multifactor para elevar la seguridad de tu experiencia de inicio de sesión.', + factors: 'Factores', + multi_factors: 'Multifactores', + multi_factors_description: + 'Los usuarios deben verificar uno de los factores habilitados para la autenticación de dos pasos.', + totp: 'OTP de la aplicación autenticadora', + otp_description: 'Vincula Google Authenticator, etc., para verificar contraseñas de un solo uso.', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthn utiliza la clave de paso para verificar el dispositivo del usuario, incluido YubiKey.', + backup_code: 'Código de respaldo', + backup_code_description: + 'Genera 10 códigos únicos, cada uno utilizable para una sola autenticación.', + backup_code_setup_hint: + 'El factor de autenticación de respaldo que no se puede habilitar por sí solo:', + backup_code_error_hint: + 'Para usar el código de respaldo para la autenticación multifactor, deben estar habilitados otros factores para garantizar el inicio de sesión exitoso de tus usuarios.', + policy: 'Política', + two_step_sign_in_policy: 'Política de autenticación de dos pasos al iniciar sesión', + two_step_sign_in_policy_description: + 'Define un requisito de autenticación de dos pasos en toda la aplicación al iniciar sesión.', + user_controlled: 'Controlado por el usuario', + user_controlled_description: + 'Desactivado por defecto y no obligatorio, pero los usuarios pueden habilitarlo individualmente.', + mandatory: 'Obligatorio', + mandatory_description: + 'Requiere autenticación multifactor para todos tus usuarios en cada inicio de sesión.', + unlock_reminder: + 'Desbloquea la autenticación multifactor para mejorar la seguridad mediante la actualización a un plan de pago. No dudes en contactarnos si necesitas ayuda.', + view_plans: 'Ver planes', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/es/translation/admin-console/tabs.ts b/packages/phrases/src/locales/es/translation/admin-console/tabs.ts index d62dd728d..ba685dba3 100644 --- a/packages/phrases/src/locales/es/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/es/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Roles', docs: 'Documentos', tenant_settings: 'Configuraciones', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/fr/translation/admin-console/index.ts b/packages/phrases/src/locales/fr/translation/admin-console/index.ts index d8c90f87d..6884f5746 100644 --- a/packages/phrases/src/locales/fr/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/fr/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/fr/translation/admin-console/mfa.ts b/packages/phrases/src/locales/fr/translation/admin-console/mfa.ts new file mode 100644 index 000000000..2baf67f0e --- /dev/null +++ b/packages/phrases/src/locales/fr/translation/admin-console/mfa.ts @@ -0,0 +1,37 @@ +const mfa = { + title: 'Authentification multi-facteurs', + description: + 'Ajoutez une authentification multi-facteurs pour renforcer la sécurité de votre expérience de connexion.', + factors: 'Facteurs', + multi_factors: 'Multi-facteurs', + multi_factors_description: + "Les utilisateurs doivent vérifier l'un des facteurs activés pour l'authentification à deux étapes.", + totp: "OTP de l'application Authenticator", + otp_description: + 'Liez Google Authenticator, etc., pour vérifier les mots de passe à usage unique.', + webauthn: 'WebAuthn', + webauthn_description: + "WebAuthn utilise la clé de passe pour vérifier le périphérique de l'utilisateur, y compris YubiKey.", + backup_code: 'Code de secours', + backup_code_description: + 'Générez 10 codes uniques, chacun utilisable pour une seule authentification.', + backup_code_setup_hint: + "Le facteur d'authentification de secours qui ne peut pas être activé seul :", + backup_code_error_hint: + "Pour utiliser le code de secours pour l'authentification multi-facteurs, d'autres facteurs doivent être activés pour garantir la réussite de la connexion de vos utilisateurs.", + policy: 'Politique', + two_step_sign_in_policy: "Politique d'authentification à deux étapes à la connexion", + two_step_sign_in_policy_description: + "Définissez une exigence d'authentification à deux étapes dans toute l'application lors de la connexion.", + user_controlled: "Contrôlé par l'utilisateur", + user_controlled_description: + "Désactivé par défaut et non obligatoire, mais les utilisateurs peuvent l'activer individuellement.", + mandatory: 'Obligatoire', + mandatory_description: + "Exigez l'authentification multi-facteurs pour tous vos utilisateurs à chaque connexion.", + unlock_reminder: + "Débloquez l'authentification multi-facteurs pour renforcer la sécurité en passant à un abonnement payant. N'hésitez pas à nous contacter si vous avez besoin d'aide.", + view_plans: 'Voir les plans', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/fr/translation/admin-console/tabs.ts b/packages/phrases/src/locales/fr/translation/admin-console/tabs.ts index 566c73b95..275f88e83 100644 --- a/packages/phrases/src/locales/fr/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/fr/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Roles', docs: 'Documentation', tenant_settings: 'Paramètres', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/it/translation/admin-console/index.ts b/packages/phrases/src/locales/it/translation/admin-console/index.ts index d8c90f87d..6884f5746 100644 --- a/packages/phrases/src/locales/it/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/it/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/it/translation/admin-console/mfa.ts b/packages/phrases/src/locales/it/translation/admin-console/mfa.ts new file mode 100644 index 000000000..379769045 --- /dev/null +++ b/packages/phrases/src/locales/it/translation/admin-console/mfa.ts @@ -0,0 +1,36 @@ +const mfa = { + title: 'Autenticazione multi-fattore', + description: + "Aggiungi l'autenticazione multi-fattore per aumentare la sicurezza della tua esperienza di accesso.", + factors: 'Fattori', + multi_factors: 'Multi-fattori', + multi_factors_description: + "Gli utenti devono verificare uno dei fattori abilitati per l'autenticazione a due passaggi.", + totp: "OTP dell'app Authenticator", + otp_description: 'Collega Google Authenticator, ecc., per verificare le password monouso.', + webauthn: 'WebAuthn', + webauthn_description: + "WebAuthn utilizza la chiave di passaggio per verificare il dispositivo dell'utente, inclusa YubiKey.", + backup_code: 'Codice di backup', + backup_code_description: + 'Genera 10 codici unici, ciascuno utilizzabile per una singola autenticazione.', + backup_code_setup_hint: + 'Il fattore di autenticazione di backup che non può essere attivato da solo:', + backup_code_error_hint: + "Per utilizzare il codice di backup per l'autenticazione multi-fattore, è necessario attivare altri fattori per garantire il successo dell'accesso dei tuoi utenti.", + policy: 'Politica', + two_step_sign_in_policy: "Politica di autenticazione a due passaggi all'accesso", + two_step_sign_in_policy_description: + "Definisci un requisito di autenticazione a due passaggi per l'applicazione al momento dell'accesso.", + user_controlled: "Controllato dall'utente", + user_controlled_description: + 'Disabilitato per impostazione predefinita e non obbligatorio, ma gli utenti possono attivarlo singolarmente.', + mandatory: 'Obbligatorio', + mandatory_description: + "Richiedi l'autenticazione multi-fattore per tutti i tuoi utenti ad ogni accesso.", + unlock_reminder: + "Sblocca l'autenticazione multi-fattore per verificare la sicurezza passando a un piano a pagamento. Non esitare a contattarci se hai bisogno di assistenza.", + view_plans: 'Visualizza i piani', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/it/translation/admin-console/tabs.ts b/packages/phrases/src/locales/it/translation/admin-console/tabs.ts index 68a1b5eca..2a7a122e8 100644 --- a/packages/phrases/src/locales/it/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/it/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Ruoli', docs: 'Documenti', tenant_settings: 'Impostazioni', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/ja/translation/admin-console/index.ts b/packages/phrases/src/locales/ja/translation/admin-console/index.ts index d8c90f87d..6884f5746 100644 --- a/packages/phrases/src/locales/ja/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/ja/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/ja/translation/admin-console/mfa.ts b/packages/phrases/src/locales/ja/translation/admin-console/mfa.ts new file mode 100644 index 000000000..ea66ffda0 --- /dev/null +++ b/packages/phrases/src/locales/ja/translation/admin-console/mfa.ts @@ -0,0 +1,32 @@ +const mfa = { + title: '多要素認証', + description: + 'サインインエクスペリエンスのセキュリティを向上させるために、多要素認証を追加します。', + factors: '要因', + multi_factors: 'マルチファクター', + multi_factors_description: + 'ユーザーは2段階認証のために有効になっている要因の1つを確認する必要があります。', + totp: 'AuthenticatorアプリOTP', + otp_description: 'Google Authenticatorなどをリンクしてワンタイムパスワードを確認します。', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthnはYubiKeyを含むユーザーのデバイスを確認するためにパスキーを使用します。', + backup_code: 'バックアップコード', + backup_code_description: '1回の認証に使用できる10個のユニークなコードを生成します。', + backup_code_setup_hint: '単独で有効化できないバックアップ認証要因:', + backup_code_error_hint: + 'MFAのバックアップコードを使用するには、他の要因を有効にする必要があり、ユーザーのサインインが成功することを確認します。', + policy: 'ポリシー', + two_step_sign_in_policy: 'サインイン時の2段階認証ポリシー', + two_step_sign_in_policy_description: 'サインイン時のアプリ全体の2段階認証要件を定義します。', + user_controlled: 'ユーザーがコントロール', + user_controlled_description: + 'デフォルトでは無効で、強制ではありませんが、ユーザーは個別に有効にできます。', + mandatory: '必須', + mandatory_description: 'すべてのユーザーに対してすべてのサインインでMFAが必要です。', + unlock_reminder: + 'セキュリティの確認のためにMFAをロック解除して有料プランにアップグレードします。サポートが必要な場合はお気軽にお問い合わせください。', + view_plans: 'プランを表示', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/ja/translation/admin-console/tabs.ts b/packages/phrases/src/locales/ja/translation/admin-console/tabs.ts index 24fadf271..00878cbc1 100644 --- a/packages/phrases/src/locales/ja/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/ja/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: '役割', docs: 'ドキュメント', tenant_settings: '設定', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/ko/translation/admin-console/index.ts b/packages/phrases/src/locales/ko/translation/admin-console/index.ts index fd7c6e799..2b9bb1730 100644 --- a/packages/phrases/src/locales/ko/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/ko/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/ko/translation/admin-console/mfa.ts b/packages/phrases/src/locales/ko/translation/admin-console/mfa.ts new file mode 100644 index 000000000..c6dde4a03 --- /dev/null +++ b/packages/phrases/src/locales/ko/translation/admin-console/mfa.ts @@ -0,0 +1,31 @@ +const mfa = { + title: '다중 인증', + description: '로그인 경험의 보안을 강화하기 위해 다중 인증을 추가하세요.', + factors: '요소', + multi_factors: '다중 요소', + multi_factors_description: + '사용자는 두 단계 인증을 위해 활성화된 요소 중 하나를 확인해야 합니다.', + totp: 'Authenticator 앱 OTP', + otp_description: 'Google Authenticator 등을 연결하여 일회용 암호를 확인합니다.', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthn은 YubiKey를 포함한 사용자 장치를 확인하기 위해 패스키를 사용합니다.', + backup_code: '백업 코드', + backup_code_description: '한 번의 인증에 사용할 수 있는 고유한 10개의 코드를 생성합니다.', + backup_code_setup_hint: '독립적으로 활성화할 수 없는 백업 인증 요소:', + backup_code_error_hint: + 'MFA에 백업 코드를 사용하려면 다른 요소도 활성화되어 있어야 하며 사용자의 로그인이 성공적으로 이루어지도록 합니다.', + policy: '정책', + two_step_sign_in_policy: '로그인 시 이중 인증 정책', + two_step_sign_in_policy_description: '로그인 시 앱 전체에서 이중 인증 요구 사항을 정의합니다.', + user_controlled: '사용자 제어', + user_controlled_description: + '기본적으로 비활성화되어 있으며 필수 사항은 아니지만 사용자는 개별적으로 활성화할 수 있습니다.', + mandatory: '필수', + mandatory_description: '모든 사용자에 대한 모든 로그인에서 MFA가 필요합니다.', + unlock_reminder: + '보안을 확인하려면 유료 플랜으로 업그레이드하여 MFA를 잠금 해제하십시오. 도움이 필요하면 언제든지 문의하십시오.', + view_plans: '플랜 보기', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/ko/translation/admin-console/tabs.ts b/packages/phrases/src/locales/ko/translation/admin-console/tabs.ts index a82c7f47a..49d95210d 100644 --- a/packages/phrases/src/locales/ko/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/ko/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: '역할', docs: '문서', tenant_settings: '설정', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/index.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/index.ts index fd7c6e799..2b9bb1730 100644 --- a/packages/phrases/src/locales/pl-pl/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/mfa.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/mfa.ts new file mode 100644 index 000000000..0e4397256 --- /dev/null +++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/mfa.ts @@ -0,0 +1,36 @@ +const mfa = { + title: 'Wieloczynnikowa autoryzacja', + description: + 'Dodaj wieloczynnikową autoryzację, aby podnieść bezpieczeństwo swojego doświadczenia z logowaniem.', + factors: 'Czynniki', + multi_factors: 'Wieloczynniki', + multi_factors_description: + 'Użytkownicy muszą zweryfikować jeden z włączonych czynników podczas autoryzacji dwuetapowej.', + totp: 'OTP z aplikacji Authenticator', + otp_description: 'Połącz Google Authenticator itp., aby zweryfikować jednorazowe hasła.', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthn używa klucza przechodzenia do weryfikacji urządzenia użytkownika, w tym YubiKey.', + backup_code: 'Kod zapasowy', + backup_code_description: + 'Generuj 10 unikalnych kodów, z których każdy można użyć do jednej autoryzacji.', + backup_code_setup_hint: + 'Czynnik autoryzacji zapasowej, który nie może być włączony samodzielnie:', + backup_code_error_hint: + 'Aby używać kodu zapasowego do autoryzacji wieloczynnikowej, inne czynniki muszą być włączone, aby zapewnić udane logowanie użytkowników.', + policy: 'Polityka', + two_step_sign_in_policy: 'Polityka autoryzacji dwuetapowej podczas logowania', + two_step_sign_in_policy_description: + 'Zdefiniuj wymaganie autoryzacji dwuetapowej na poziomie aplikacji podczas logowania.', + user_controlled: 'Kontrolowane przez użytkownika', + user_controlled_description: + 'Domyślnie wyłączone i nieobowiązkowe, ale użytkownicy mogą włączyć je indywidualnie.', + mandatory: 'Obowiązkowe', + mandatory_description: + 'Wymagaj autoryzacji wieloczynnikowej dla wszystkich użytkowników podczas każdego logowania.', + unlock_reminder: + 'Odblokuj autoryzację wieloczynnikową, aby zwiększyć bezpieczeństwo, przechodząc na płatny plan. Nie wahaj się skontaktować z nami, jeśli potrzebujesz pomocy.', + view_plans: 'Zobacz plany', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/pl-pl/translation/admin-console/tabs.ts b/packages/phrases/src/locales/pl-pl/translation/admin-console/tabs.ts index 235001482..216dd8bb3 100644 --- a/packages/phrases/src/locales/pl-pl/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/pl-pl/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Role', docs: 'Dokumentacja', tenant_settings: 'Ustawienia', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/index.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/index.ts index 87d021dc2..29ccc6842 100644 --- a/packages/phrases/src/locales/pt-br/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/pt-br/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/mfa.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/mfa.ts new file mode 100644 index 000000000..a2514b836 --- /dev/null +++ b/packages/phrases/src/locales/pt-br/translation/admin-console/mfa.ts @@ -0,0 +1,35 @@ +const mfa = { + title: 'Autenticação de vários fatores', + description: + 'Adicione autenticação de vários fatores para elevar a segurança da sua experiência de login.', + factors: 'Fatores', + multi_factors: 'Múltiplos fatores', + multi_factors_description: + 'Os usuários precisam verificar um dos fatores habilitados para autenticação de dois passos.', + totp: 'OTP do aplicativo Authenticator', + otp_description: 'Vincule o Google Authenticator, etc., para verificar senhas de uso único.', + webauthn: 'WebAuthn', + webauthn_description: + 'O WebAuthn usa a chave de passagem para verificar o dispositivo do usuário, incluindo o YubiKey.', + backup_code: 'Código de backup', + backup_code_description: + 'Gere 10 códigos exclusivos, cada um utilizável para uma única autenticação.', + backup_code_setup_hint: 'O fator de autenticação de backup que não pode ser ativado sozinho:', + backup_code_error_hint: + 'Para usar o código de backup para autenticação de vários fatores, outros fatores devem estar ativados para garantir o login bem-sucedido de seus usuários.', + policy: 'Política', + two_step_sign_in_policy: 'Política de autenticação de dois passos no login', + two_step_sign_in_policy_description: + 'Defina um requisito de autenticação de dois passos em toda a aplicação no momento do login.', + user_controlled: 'Controlado pelo usuário', + user_controlled_description: + 'Desativado por padrão e não obrigatório, mas os usuários podem ativá-lo individualmente.', + mandatory: 'Obrigatório', + mandatory_description: + 'Exija autenticação de vários fatores para todos os seus usuários em cada login.', + unlock_reminder: + 'Desbloqueie a autenticação de vários fatores para verificar a segurança, fazendo upgrade para um plano pago. Não hesite em entrar em contato conosco se precisar de assistência.', + view_plans: 'Ver planos', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/pt-br/translation/admin-console/tabs.ts b/packages/phrases/src/locales/pt-br/translation/admin-console/tabs.ts index 0fea5cacf..39291455c 100644 --- a/packages/phrases/src/locales/pt-br/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/pt-br/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Registros', docs: 'Documentação', tenant_settings: 'Configurações', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/index.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/index.ts index d97e19806..8aa363a57 100644 --- a/packages/phrases/src/locales/pt-pt/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/mfa.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/mfa.ts new file mode 100644 index 000000000..a2514b836 --- /dev/null +++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/mfa.ts @@ -0,0 +1,35 @@ +const mfa = { + title: 'Autenticação de vários fatores', + description: + 'Adicione autenticação de vários fatores para elevar a segurança da sua experiência de login.', + factors: 'Fatores', + multi_factors: 'Múltiplos fatores', + multi_factors_description: + 'Os usuários precisam verificar um dos fatores habilitados para autenticação de dois passos.', + totp: 'OTP do aplicativo Authenticator', + otp_description: 'Vincule o Google Authenticator, etc., para verificar senhas de uso único.', + webauthn: 'WebAuthn', + webauthn_description: + 'O WebAuthn usa a chave de passagem para verificar o dispositivo do usuário, incluindo o YubiKey.', + backup_code: 'Código de backup', + backup_code_description: + 'Gere 10 códigos exclusivos, cada um utilizável para uma única autenticação.', + backup_code_setup_hint: 'O fator de autenticação de backup que não pode ser ativado sozinho:', + backup_code_error_hint: + 'Para usar o código de backup para autenticação de vários fatores, outros fatores devem estar ativados para garantir o login bem-sucedido de seus usuários.', + policy: 'Política', + two_step_sign_in_policy: 'Política de autenticação de dois passos no login', + two_step_sign_in_policy_description: + 'Defina um requisito de autenticação de dois passos em toda a aplicação no momento do login.', + user_controlled: 'Controlado pelo usuário', + user_controlled_description: + 'Desativado por padrão e não obrigatório, mas os usuários podem ativá-lo individualmente.', + mandatory: 'Obrigatório', + mandatory_description: + 'Exija autenticação de vários fatores para todos os seus usuários em cada login.', + unlock_reminder: + 'Desbloqueie a autenticação de vários fatores para verificar a segurança, fazendo upgrade para um plano pago. Não hesite em entrar em contato conosco se precisar de assistência.', + view_plans: 'Ver planos', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/pt-pt/translation/admin-console/tabs.ts b/packages/phrases/src/locales/pt-pt/translation/admin-console/tabs.ts index f0197fd85..02bdd2e57 100644 --- a/packages/phrases/src/locales/pt-pt/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/pt-pt/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Papéis', docs: 'Documentação', tenant_settings: 'Definições', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/ru/translation/admin-console/index.ts b/packages/phrases/src/locales/ru/translation/admin-console/index.ts index d3117260f..ce054104a 100644 --- a/packages/phrases/src/locales/ru/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/ru/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/ru/translation/admin-console/mfa.ts b/packages/phrases/src/locales/ru/translation/admin-console/mfa.ts new file mode 100644 index 000000000..e13d0ac7a --- /dev/null +++ b/packages/phrases/src/locales/ru/translation/admin-console/mfa.ts @@ -0,0 +1,35 @@ +const mfa = { + title: 'Многофакторная аутентификация', + description: + 'Добавьте многофакторную аутентификацию для повышения безопасности вашего опыта входа.', + factors: 'Факторы', + multi_factors: 'Многофакторы', + multi_factors_description: + 'Пользователи должны проверить один из включенных факторов для двухэтапной аутентификации.', + totp: 'OTP из приложения Authenticator', + otp_description: 'Свяжите Google Authenticator и т. д., чтобы проверить одноразовые пароли.', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthn использует ключ прохода для проверки устройства пользователя, включая YubiKey.', + backup_code: 'Резервный код', + backup_code_description: + 'Генерируйте 10 уникальных кодов, каждый из которых можно использовать для одной аутентификации.', + backup_code_setup_hint: 'Фактор резервной аутентификации, который нельзя включить отдельно:', + backup_code_error_hint: + 'Чтобы использовать резервный код для многофакторной аутентификации, другие факторы должны быть включены для обеспечения успешного входа ваших пользователей.', + policy: 'Политика', + two_step_sign_in_policy: 'Политика двухэтапной аутентификации при входе', + two_step_sign_in_policy_description: + 'Задайте требование двухэтапной аутентификации для всего приложения при входе.', + user_controlled: 'Управление пользователем', + user_controlled_description: + 'По умолчанию отключено и не обязательно, но пользователи могут включить его по отдельности.', + mandatory: 'Обязательно', + mandatory_description: + 'Требуйте многофакторную аутентификацию для всех ваших пользователей при каждом входе.', + unlock_reminder: + 'Разблокируйте многофакторную аутентификацию для увеличения безопасности с помощью перехода на платный план. Не стесняйтесь связаться с нами, если вам нужна помощь.', + view_plans: 'Просмотреть планы', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/ru/translation/admin-console/tabs.ts b/packages/phrases/src/locales/ru/translation/admin-console/tabs.ts index 7783e8a78..ee14963b2 100644 --- a/packages/phrases/src/locales/ru/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/ru/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Роли', docs: 'Документация', tenant_settings: 'Настройки', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/index.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/index.ts index 658c9792a..ce90f0a02 100644 --- a/packages/phrases/src/locales/tr-tr/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/mfa.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/mfa.ts new file mode 100644 index 000000000..3964841a3 --- /dev/null +++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/mfa.ts @@ -0,0 +1,36 @@ +const mfa = { + title: 'Çoklu Faktör Kimlik Doğrulama', + description: + 'Giriş deneyiminizin güvenliğini artırmak için çoklu faktör kimlik doğrulamayı ekleyin.', + factors: 'Faktörler', + multi_factors: 'Çoklu faktörler', + multi_factors_description: + 'Kullanıcılar, iki aşamalı kimlik doğrulama için etkinleştirilen faktörlerden birini doğrulamalıdır.', + totp: 'Authenticator uygulama OTP', + otp_description: + 'Google Authenticator vb. bağlayarak tek kullanımlık şifreleri doğrulamak için kullanın.', + webauthn: 'WebAuthn', + webauthn_description: + 'WebAuthn, YubiKey dahil olmak üzere kullanıcının cihazını doğrulamak için geçiş anahtarını kullanır.', + backup_code: 'Yedek kod', + backup_code_description: + 'Tek kullanımlık bir kimlik doğrulama için kullanılabilen 10 benzersiz kod üretin.', + backup_code_setup_hint: 'Tek başına etkinleştirilemeyen yedek kimlik doğrulama faktörü:', + backup_code_error_hint: + 'Çoklu faktör kimlik doğrulamada yedek kodu kullanmak için kullanıcılarınızın başarılı giriş yapmalarını sağlamak için diğer faktörlerin etkinleştirilmiş olması gerekir.', + policy: 'Politika', + two_step_sign_in_policy: 'Giriş sırasında iki adımlı kimlik doğrulama politikası', + two_step_sign_in_policy_description: + 'Giriş sırasında tüm uygulama genelinde iki adımlı kimlik doğrulama gereksinimi tanımlayın.', + user_controlled: 'Kullanıcı tarafından kontrol edilen', + user_controlled_description: + 'Varsayılan olarak devre dışı bırakılmış ve zorunlu değildir, ancak kullanıcılar ayrı ayrı etkinleştirebilirler.', + mandatory: 'Zorunlu', + mandatory_description: + 'Her girişte tüm kullanıcılarınız için çoklu faktör kimlik doğrulamayı gerektirin.', + unlock_reminder: + 'Güvenliği doğrulamak için çoklu faktör kimlik doğrulamayı kilit açmak için bir ücretli plana yükselterek etkinleştirin. Yardıma ihtiyacınız varsa çekinmeden bizimle iletişime geçin.', + view_plans: 'Planları görüntüle', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/tr-tr/translation/admin-console/tabs.ts b/packages/phrases/src/locales/tr-tr/translation/admin-console/tabs.ts index bf564093b..9075c263e 100644 --- a/packages/phrases/src/locales/tr-tr/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/tr-tr/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: 'Roller', docs: 'Dökümanlar', tenant_settings: 'Ayarlar', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/index.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/index.ts index 950b04d4d..1a78db3a6 100644 --- a/packages/phrases/src/locales/zh-cn/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/mfa.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/mfa.ts new file mode 100644 index 000000000..bae17a41d --- /dev/null +++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/mfa.ts @@ -0,0 +1,27 @@ +const mfa = { + title: '多因素身份验证', + description: '添加多因素身份验证以提升您的登录体验的安全性。', + factors: '因素', + multi_factors: '多因素', + multi_factors_description: '用户需要验证启用的一个因素以进行两步验证。', + totp: 'Authenticator应用程序OTP', + otp_description: '链接Google Authenticator等来验证一次性密码。', + webauthn: 'WebAuthn', + webauthn_description: 'WebAuthn使用通行密钥验证用户设备,包括YubiKey。', + backup_code: '备用代码', + backup_code_description: '生成10个唯一的代码,每个代码可用于一次验证。', + backup_code_setup_hint: '不能单独启用的备用身份验证因素:', + backup_code_error_hint: '要使用备用代码进行多因素身份验证,必须启用其他因素以确保用户成功登录。', + policy: '策略', + two_step_sign_in_policy: '登录时的两步验证策略', + two_step_sign_in_policy_description: '为登录时的应用程序定义双重验证要求。', + user_controlled: '用户控制', + user_controlled_description: '默认情况下禁用且非强制,但用户可以单独启用它。', + mandatory: '强制', + mandatory_description: '要求所有用户在每次登录时进行多因素身份验证。', + unlock_reminder: + '解锁多因素身份验证以通过升级到付费计划验证安全性。如果需要帮助,请随时联系我们。', + view_plans: '查看计划', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/zh-cn/translation/admin-console/tabs.ts b/packages/phrases/src/locales/zh-cn/translation/admin-console/tabs.ts index c2670586f..12973e4ac 100644 --- a/packages/phrases/src/locales/zh-cn/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/zh-cn/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: '角色', docs: '文档', tenant_settings: '设置', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/index.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/index.ts index 48ea828aa..9ef581c33 100644 --- a/packages/phrases/src/locales/zh-hk/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/mfa.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/mfa.ts new file mode 100644 index 000000000..04ba5d97c --- /dev/null +++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/mfa.ts @@ -0,0 +1,27 @@ +const mfa = { + title: '多因子驗證', + description: '添加多因子驗證以提升您的登錄體驗的安全性。', + factors: '因素', + multi_factors: '多因素', + multi_factors_description: '用戶需要驗證啟用的一個因素以進行兩步驗證。', + totp: 'Authenticator應用程式OTP', + otp_description: '連接Google Authenticator等來驗證一次性密碼。', + webauthn: 'WebAuthn', + webauthn_description: 'WebAuthn使用通行密鑰驗證用戶設備,包括YubiKey。', + backup_code: '備用代碼', + backup_code_description: '生成10個唯一的代碼,每個代碼可用於一次驗證。', + backup_code_setup_hint: '不能單獨啟用的備用身份驗證因素:', + backup_code_error_hint: '要使用備用代碼進行多因子驗證,必須啟用其他因素以確保用戶成功登錄。', + policy: '策略', + two_step_sign_in_policy: '登錄時的雙重驗證策略', + two_step_sign_in_policy_description: '為登錄時的應用程序定義雙重驗證要求。', + user_controlled: '用戶控制', + user_controlled_description: '默認情況下禁用且非強制,但用戶可以單獨啟用它。', + mandatory: '強制', + mandatory_description: '要求所有用戶在每次登錄時進行多因子驗證。', + unlock_reminder: + '解鎖多因子驗證以通過升級到付費計劃驗證安全性。如果需要幫助,請隨時聯繫我們。', + view_plans: '查看計劃', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/zh-hk/translation/admin-console/tabs.ts b/packages/phrases/src/locales/zh-hk/translation/admin-console/tabs.ts index 7d0192e59..15e2971fa 100644 --- a/packages/phrases/src/locales/zh-hk/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/zh-hk/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: '角色', docs: '文檔', tenant_settings: '設置', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs); diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/index.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/index.ts index 48ea828aa..9ef581c33 100644 --- a/packages/phrases/src/locales/zh-tw/translation/admin-console/index.ts +++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/index.ts @@ -16,6 +16,7 @@ import guide from './guide.js'; import log_details from './log-details.js'; import logs from './logs.js'; import menu from './menu.js'; +import mfa from './mfa.js'; import permissions from './permissions.js'; import profile from './profile.js'; import role_details from './role-details.js'; @@ -73,6 +74,7 @@ const admin_console = { subscription, upsell, guide, + mfa, }; export default Object.freeze(admin_console); diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/mfa.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/mfa.ts new file mode 100644 index 000000000..31c098084 --- /dev/null +++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/mfa.ts @@ -0,0 +1,27 @@ +const mfa = { + title: '多因素驗證', + description: '添加多因素驗證以提升您的登錄體驗的安全性。', + factors: '因素', + multi_factors: '多因素', + multi_factors_description: '用戶需要驗證啟用的一個因素以進行兩步驗證。', + totp: 'Authenticator應用程式OTP', + otp_description: '連接Google Authenticator等來驗證一次性密碼。', + webauthn: 'WebAuthn', + webauthn_description: 'WebAuthn使用通行密鑰驗證用戶設備,包括YubiKey。', + backup_code: '備用代碼', + backup_code_description: '生成10個唯一的代碼,每個代碼可用於一次驗證。', + backup_code_setup_hint: '不能單獨啟用的備用身份驗證因素:', + backup_code_error_hint: '要使用備用代碼進行多因子驗證,必須啟用其他因素以確保用戶成功登錄。', + policy: '策略', + two_step_sign_in_policy: '登錄時的雙重驗證策略', + two_step_sign_in_policy_description: '為登錄時的應用程序定義雙重驗證要求。', + user_controlled: '用戶控制', + user_controlled_description: '默認情況下禁用且非強制,但用戶可以單獨啟用它。', + mandatory: '強制', + mandatory_description: '要求所有用戶在每次登錄時進行多因子驗證。', + unlock_reminder: + '解鎖多因子驗證以通過升級到付費計劃驗證安全性。如果需要幫助,請隨時聯繫我們。', + view_plans: '查看計劃', +}; + +export default Object.freeze(mfa); diff --git a/packages/phrases/src/locales/zh-tw/translation/admin-console/tabs.ts b/packages/phrases/src/locales/zh-tw/translation/admin-console/tabs.ts index 21cafd07c..1f2d71502 100644 --- a/packages/phrases/src/locales/zh-tw/translation/admin-console/tabs.ts +++ b/packages/phrases/src/locales/zh-tw/translation/admin-console/tabs.ts @@ -11,6 +11,8 @@ const tabs = { roles: '角色', docs: '文件', tenant_settings: '設定', + /** UNTRANSLATED */ + mfa: 'Multi-factor auth', }; export default Object.freeze(tabs);