mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(console,phrases): optimize onboarding process (#4214)
This commit is contained in:
parent
36b5958935
commit
ae4f85bf10
25 changed files with 163 additions and 481 deletions
|
@ -9,7 +9,7 @@ type Props = {
|
|||
children: ReactNode;
|
||||
};
|
||||
|
||||
const totalSteps = 3;
|
||||
const totalSteps = 2;
|
||||
|
||||
function ActionBar({ step, children }: Props) {
|
||||
return (
|
||||
|
|
|
@ -19,7 +19,6 @@ import { gtagAwTrackingId, gtagSignUpConversionId, logtoProductionHostname } fro
|
|||
import AppContent from './containers/AppContent';
|
||||
import useUserOnboardingData from './hooks/use-user-onboarding-data';
|
||||
import * as styles from './index.module.scss';
|
||||
import About from './pages/About';
|
||||
import Congrats from './pages/Congrats';
|
||||
import SignInExperience from './pages/SignInExperience';
|
||||
import Welcome from './pages/Welcome';
|
||||
|
@ -110,7 +109,6 @@ export function OnboardingRoutes() {
|
|||
<Route path={OnboardingRoute.Onboarding} element={<AppContent />}>
|
||||
<Route index element={<Navigate replace to={OnboardingPage.Welcome} />} />
|
||||
<Route path={OnboardingPage.Welcome} element={<Welcome />} />
|
||||
<Route path={OnboardingPage.AboutUser} element={<About />} />
|
||||
<Route path={OnboardingPage.SignInExperience} element={<SignInExperience />} />
|
||||
<Route path={OnboardingPage.Congrats} element={<Congrats />} />
|
||||
</Route>
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.title {
|
||||
font: var(--font-title-1);
|
||||
margin-top: _.unit(6);
|
||||
}
|
||||
|
||||
.description {
|
||||
font: var(--font-body-2);
|
||||
margin-top: _.unit(3);
|
||||
}
|
||||
|
||||
.form {
|
||||
width: 100%;
|
||||
margin-top: _.unit(6);
|
||||
|
||||
.titleSelector {
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.option {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.cardFieldHeadline {
|
||||
margin-bottom: _.unit(2);
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
import { withAppInsights } from '@logto/app-insights/react';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import { useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Case from '@/assets/icons/case.svg';
|
||||
import PageMeta from '@/components/PageMeta';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import OverlayScrollbar from '@/ds-components/OverlayScrollbar';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import useUserOnboardingData from '@/onboarding/hooks/use-user-onboarding-data';
|
||||
import * as pageLayout from '@/onboarding/scss/layout.module.scss';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
|
||||
import ActionBar from '../../components/ActionBar';
|
||||
import { CardSelector, MultiCardSelector } from '../../components/CardSelector';
|
||||
import type { Questionnaire } from '../../types';
|
||||
import { OnboardingPage } from '../../types';
|
||||
import { getOnboardingPage } from '../../utils';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
import { titleOptions, companySizeOptions, reasonOptions } from './options';
|
||||
|
||||
function About() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { navigate } = useTenantPathname();
|
||||
|
||||
const {
|
||||
data: { questionnaire },
|
||||
isBusinessPlan,
|
||||
update,
|
||||
} = useUserOnboardingData();
|
||||
|
||||
const { control, register, handleSubmit, reset } = useForm<Questionnaire>({
|
||||
mode: 'onChange',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
reset(questionnaire);
|
||||
}, [questionnaire, reset]);
|
||||
|
||||
const onSubmit = handleSubmit(
|
||||
trySubmitSafe(async (formData) => {
|
||||
await update({ questionnaire: formData });
|
||||
})
|
||||
);
|
||||
|
||||
const onNext = async () => {
|
||||
await onSubmit();
|
||||
navigate(getOnboardingPage(OnboardingPage.SignInExperience));
|
||||
};
|
||||
|
||||
const onBack = async () => {
|
||||
navigate(getOnboardingPage(OnboardingPage.Welcome));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={pageLayout.page}>
|
||||
<PageMeta titleKey={['cloud.about.page_title', 'cloud.general.onboarding']} />
|
||||
<OverlayScrollbar className={pageLayout.contentContainer}>
|
||||
<div className={pageLayout.content}>
|
||||
<Case />
|
||||
<div className={styles.title}>{t('cloud.about.title')}</div>
|
||||
<div className={styles.description}>{t('cloud.about.description')}</div>
|
||||
<form className={styles.form}>
|
||||
{isBusinessPlan && (
|
||||
<>
|
||||
<FormField
|
||||
isMultiple
|
||||
title="cloud.about.title_field"
|
||||
headlineClassName={styles.cardFieldHeadline}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="titles"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<MultiCardSelector
|
||||
className={styles.titleSelector}
|
||||
optionClassName={styles.option}
|
||||
value={value ?? []}
|
||||
options={titleOptions}
|
||||
onChange={(value) => {
|
||||
onChange(value.length === 0 ? undefined : value);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="cloud.about.company_name_field">
|
||||
<TextInput
|
||||
placeholder={t('cloud.about.company_name_placeholder')}
|
||||
{...register('companyName')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
title="cloud.about.company_size_field"
|
||||
headlineClassName={styles.cardFieldHeadline}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="companySize"
|
||||
render={({ field: { onChange, value, name } }) => (
|
||||
<CardSelector
|
||||
name={name}
|
||||
value={value ?? ''}
|
||||
options={companySizeOptions}
|
||||
optionClassName={styles.option}
|
||||
onChange={(value) => {
|
||||
onChange(conditional(value && value));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
</>
|
||||
)}
|
||||
<FormField
|
||||
isMultiple
|
||||
title="cloud.about.reason_field"
|
||||
headlineClassName={styles.cardFieldHeadline}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="reasons"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<MultiCardSelector
|
||||
value={value ?? []}
|
||||
options={reasonOptions}
|
||||
onChange={(value) => {
|
||||
onChange(value.length === 0 ? undefined : value);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
</form>
|
||||
</div>
|
||||
</OverlayScrollbar>
|
||||
<ActionBar step={2}>
|
||||
<Button title="general.next" type="primary" onClick={onNext} />
|
||||
<Button title="general.back" onClick={onBack} />
|
||||
</ActionBar>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default withAppInsights(About);
|
|
@ -1,32 +0,0 @@
|
|||
import type {
|
||||
CardSelectorOption,
|
||||
MultiCardSelectorOption,
|
||||
} from '@/onboarding/components/CardSelector';
|
||||
|
||||
import { CompanySize, Reason, Title } from '../../types';
|
||||
|
||||
export const titleOptions: MultiCardSelectorOption[] = [
|
||||
{ title: 'cloud.about.title_options.developer', value: Title.Developer },
|
||||
{ title: 'cloud.about.title_options.team_lead', value: Title.TeamLead },
|
||||
{ title: 'cloud.about.title_options.ceo', value: Title.Ceo },
|
||||
{ title: 'cloud.about.title_options.cto', value: Title.Cto },
|
||||
{ title: 'cloud.about.title_options.product', value: Title.Product },
|
||||
{ title: 'cloud.about.title_options.others', value: Title.Others },
|
||||
];
|
||||
|
||||
export const companySizeOptions: CardSelectorOption[] = [
|
||||
{ title: 'cloud.about.company_options.size_1', value: CompanySize.Scale1 },
|
||||
{ title: 'cloud.about.company_options.size_2_49', value: CompanySize.Scale2 },
|
||||
{ title: 'cloud.about.company_options.size_50_199', value: CompanySize.Scale3 },
|
||||
{ title: 'cloud.about.company_options.size_200_999', value: CompanySize.Scale4 },
|
||||
{ title: 'cloud.about.company_options.size_1000_plus', value: CompanySize.Scale5 },
|
||||
];
|
||||
|
||||
export const reasonOptions: MultiCardSelectorOption[] = [
|
||||
{ title: 'cloud.about.reason_options.passwordless', value: Reason.Passwordless },
|
||||
{ title: 'cloud.about.reason_options.efficiency', value: Reason.Efficiency },
|
||||
{ title: 'cloud.about.reason_options.access_control', value: Reason.AccessControl },
|
||||
{ title: 'cloud.about.reason_options.multi_tenancy', value: Reason.MultiTenancy },
|
||||
{ title: 'cloud.about.reason_options.enterprise', value: Reason.Enterprise },
|
||||
{ title: 'cloud.about.reason_options.others', value: Reason.Others },
|
||||
];
|
|
@ -218,7 +218,7 @@ function SignInExperience() {
|
|||
/>
|
||||
</div>
|
||||
</OverlayScrollbar>
|
||||
<ActionBar step={3}>
|
||||
<ActionBar step={2}>
|
||||
<div className={styles.continueActions}>
|
||||
<Button
|
||||
type="outline"
|
||||
|
@ -249,7 +249,7 @@ function SignInExperience() {
|
|||
title="general.back"
|
||||
disabled={isSubmitting}
|
||||
onClick={() => {
|
||||
navigate(getOnboardingPage(OnboardingPage.AboutUser));
|
||||
navigate(getOnboardingPage(OnboardingPage.Welcome));
|
||||
}}
|
||||
/>
|
||||
</ActionBar>
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.content {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.congrats {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: _.unit(6);
|
||||
font: var(--font-title-1);
|
||||
text-align: center;
|
||||
margin-top: _.unit(6);
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: _.unit(3);
|
||||
text-align: center;
|
||||
font: var(--font-body-2);
|
||||
margin-top: _.unit(3);
|
||||
}
|
||||
|
||||
.form {
|
||||
width: 100%;
|
||||
margin-top: _.unit(6);
|
||||
|
||||
.titleSelector {
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.option {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.cardFieldHeadline {
|
||||
margin-bottom: _.unit(2);
|
||||
}
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
import { withAppInsights } from '@logto/app-insights/react';
|
||||
import classNames from 'classnames';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import { useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import WelcomeImage from '@/assets/images/sign-in-experience-welcome.svg';
|
||||
import Case from '@/assets/icons/case.svg';
|
||||
import PageMeta from '@/components/PageMeta';
|
||||
import Button from '@/ds-components/Button';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
import OverlayScrollbar from '@/ds-components/OverlayScrollbar';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
import useTenantPathname from '@/hooks/use-tenant-pathname';
|
||||
import ActionBar from '@/onboarding/components/ActionBar';
|
||||
import { CardSelector } from '@/onboarding/components/CardSelector';
|
||||
import useUserOnboardingData from '@/onboarding/hooks/use-user-onboarding-data';
|
||||
import * as pageLayout from '@/onboarding/scss/layout.module.scss';
|
||||
import { trySubmitSafe } from '@/utils/form';
|
||||
|
||||
import ActionBar from '../../components/ActionBar';
|
||||
import { CardSelector, MultiCardSelector } from '../../components/CardSelector';
|
||||
import type { Questionnaire } from '../../types';
|
||||
import { OnboardingPage } from '../../types';
|
||||
import { OnboardingPage, Project } from '../../types';
|
||||
import { getOnboardingPage } from '../../utils';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
import { deploymentTypeOptions, projectOptions } from './options';
|
||||
import { titleOptions, companySizeOptions, reasonOptions, projectOptions } from './options';
|
||||
|
||||
function Welcome() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
@ -32,12 +33,9 @@ function Welcome() {
|
|||
update,
|
||||
} = useUserOnboardingData();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting, isValid },
|
||||
reset,
|
||||
} = useForm<Questionnaire>({ defaultValues: questionnaire, mode: 'onChange' });
|
||||
const { control, register, handleSubmit, reset, watch } = useForm<Questionnaire>({
|
||||
mode: 'onChange',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
reset(questionnaire);
|
||||
|
@ -51,15 +49,15 @@ function Welcome() {
|
|||
|
||||
const onNext = async () => {
|
||||
await onSubmit();
|
||||
navigate(getOnboardingPage(OnboardingPage.AboutUser));
|
||||
navigate(getOnboardingPage(OnboardingPage.SignInExperience));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={pageLayout.page}>
|
||||
<PageMeta titleKey={['cloud.welcome.page_title', 'cloud.general.onboarding']} />
|
||||
<OverlayScrollbar className={pageLayout.contentContainer}>
|
||||
<div className={classNames(pageLayout.content, styles.content)}>
|
||||
<WelcomeImage className={styles.congrats} />
|
||||
<div className={pageLayout.content}>
|
||||
<Case />
|
||||
<div className={styles.title}>{t('cloud.welcome.title')}</div>
|
||||
<div className={styles.description}>{t('cloud.welcome.description')}</div>
|
||||
<form className={styles.form}>
|
||||
|
@ -81,20 +79,73 @@ function Welcome() {
|
|||
)}
|
||||
/>
|
||||
</FormField>
|
||||
{/* Check whether it is a business use case */}
|
||||
{watch('project') === Project.Company && (
|
||||
<>
|
||||
<FormField
|
||||
isMultiple
|
||||
title="cloud.welcome.title_field"
|
||||
headlineClassName={styles.cardFieldHeadline}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="titles"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<MultiCardSelector
|
||||
className={styles.titleSelector}
|
||||
optionClassName={styles.option}
|
||||
value={value ?? []}
|
||||
options={titleOptions}
|
||||
onChange={(value) => {
|
||||
onChange(value.length === 0 ? undefined : value);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="cloud.welcome.company_name_field">
|
||||
<TextInput
|
||||
placeholder={t('cloud.welcome.company_name_placeholder')}
|
||||
{...register('companyName')}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
title="cloud.welcome.company_size_field"
|
||||
headlineClassName={styles.cardFieldHeadline}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="companySize"
|
||||
render={({ field: { onChange, value, name } }) => (
|
||||
<CardSelector
|
||||
name={name}
|
||||
value={value ?? ''}
|
||||
options={companySizeOptions}
|
||||
optionClassName={styles.option}
|
||||
onChange={(value) => {
|
||||
onChange(conditional(value && value));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
</>
|
||||
)}
|
||||
<FormField
|
||||
title="cloud.welcome.deployment_type_field"
|
||||
isMultiple
|
||||
title="cloud.welcome.reason_field"
|
||||
headlineClassName={styles.cardFieldHeadline}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="deploymentType"
|
||||
rules={{ required: true }}
|
||||
render={({ field: { onChange, value, name } }) => (
|
||||
<CardSelector
|
||||
name={name}
|
||||
value={value}
|
||||
options={deploymentTypeOptions}
|
||||
onChange={onChange}
|
||||
name="reasons"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<MultiCardSelector
|
||||
value={value ?? []}
|
||||
options={reasonOptions}
|
||||
onChange={(value) => {
|
||||
onChange(value.length === 0 ? undefined : value);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
@ -103,12 +154,7 @@ function Welcome() {
|
|||
</div>
|
||||
</OverlayScrollbar>
|
||||
<ActionBar step={1}>
|
||||
<Button
|
||||
title="general.next"
|
||||
type="primary"
|
||||
disabled={isSubmitting || !isValid}
|
||||
onClick={onNext}
|
||||
/>
|
||||
<Button title="general.next" type="primary" onClick={onNext} />
|
||||
</ActionBar>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import Building from '@/assets/icons/building.svg';
|
||||
import Cloud from '@/assets/icons/cloud.svg';
|
||||
import Database from '@/assets/icons/database.svg';
|
||||
import Pizza from '@/assets/icons/pizza.svg';
|
||||
import type { CardSelectorOption } from '@/onboarding/components/CardSelector';
|
||||
import type {
|
||||
CardSelectorOption,
|
||||
MultiCardSelectorOption,
|
||||
} from '@/onboarding/components/CardSelector';
|
||||
|
||||
import { DeploymentType, Project } from '../../types';
|
||||
import { Project, CompanySize, Reason, Title } from '../../types';
|
||||
|
||||
export const projectOptions: CardSelectorOption[] = [
|
||||
{
|
||||
|
@ -19,15 +20,28 @@ export const projectOptions: CardSelectorOption[] = [
|
|||
},
|
||||
];
|
||||
|
||||
export const deploymentTypeOptions: CardSelectorOption[] = [
|
||||
{
|
||||
icon: <Database />,
|
||||
title: 'cloud.welcome.deployment_type_options.open_source',
|
||||
value: DeploymentType.OpenSource,
|
||||
},
|
||||
{
|
||||
icon: <Cloud />,
|
||||
title: 'cloud.welcome.deployment_type_options.cloud',
|
||||
value: DeploymentType.Cloud,
|
||||
},
|
||||
export const titleOptions: MultiCardSelectorOption[] = [
|
||||
{ title: 'cloud.welcome.title_options.developer', value: Title.Developer },
|
||||
{ title: 'cloud.welcome.title_options.team_lead', value: Title.TeamLead },
|
||||
{ title: 'cloud.welcome.title_options.ceo', value: Title.Ceo },
|
||||
{ title: 'cloud.welcome.title_options.cto', value: Title.Cto },
|
||||
{ title: 'cloud.welcome.title_options.product', value: Title.Product },
|
||||
{ title: 'cloud.welcome.title_options.others', value: Title.Others },
|
||||
];
|
||||
|
||||
export const companySizeOptions: CardSelectorOption[] = [
|
||||
{ title: 'cloud.welcome.company_options.size_1', value: CompanySize.Scale1 },
|
||||
{ title: 'cloud.welcome.company_options.size_2_49', value: CompanySize.Scale2 },
|
||||
{ title: 'cloud.welcome.company_options.size_50_199', value: CompanySize.Scale3 },
|
||||
{ title: 'cloud.welcome.company_options.size_200_999', value: CompanySize.Scale4 },
|
||||
{ title: 'cloud.welcome.company_options.size_1000_plus', value: CompanySize.Scale5 },
|
||||
];
|
||||
|
||||
export const reasonOptions: MultiCardSelectorOption[] = [
|
||||
{ title: 'cloud.welcome.reason_options.passwordless', value: Reason.Passwordless },
|
||||
{ title: 'cloud.welcome.reason_options.efficiency', value: Reason.Efficiency },
|
||||
{ title: 'cloud.welcome.reason_options.access_control', value: Reason.AccessControl },
|
||||
{ title: 'cloud.welcome.reason_options.multi_tenancy', value: Reason.MultiTenancy },
|
||||
{ title: 'cloud.welcome.reason_options.enterprise', value: Reason.Enterprise },
|
||||
{ title: 'cloud.welcome.reason_options.others', value: Reason.Others },
|
||||
];
|
||||
|
|
|
@ -7,6 +7,7 @@ export enum OnboardingRoute {
|
|||
|
||||
export enum OnboardingPage {
|
||||
Welcome = 'welcome',
|
||||
/** @deprecated Merged `about-user` to `welcome` page. */
|
||||
AboutUser = 'about-user',
|
||||
SignInExperience = 'sign-in-experience',
|
||||
Congrats = 'congrats',
|
||||
|
@ -17,7 +18,8 @@ export enum Project {
|
|||
Company = 'company',
|
||||
}
|
||||
|
||||
export enum DeploymentType {
|
||||
/** @deprecated Open-source options was for cloud preview use, no longer needed. Use default `Cloud` value for placeholder. */
|
||||
enum DeploymentType {
|
||||
OpenSource = 'open-source',
|
||||
Cloud = 'cloud',
|
||||
}
|
||||
|
@ -50,7 +52,8 @@ export enum Reason {
|
|||
|
||||
const questionnaireGuard = z.object({
|
||||
project: z.nativeEnum(Project),
|
||||
deploymentType: z.nativeEnum(DeploymentType),
|
||||
/** @deprecated Open-source options was for cloud preview use, no longer needed. Use default `Cloud` value for placeholder. */
|
||||
deploymentType: z.nativeEnum(DeploymentType).optional().default(DeploymentType.Cloud),
|
||||
titles: z.array(z.nativeEnum(Title)).optional(),
|
||||
companyName: z.string().optional(),
|
||||
companySize: z.nativeEnum(CompanySize).optional(),
|
||||
|
|
|
@ -4,25 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: 'Willkommen',
|
||||
title: 'Willkommen, lass uns deine eigene Logto Cloud Preview erstellen',
|
||||
title: 'Willkommen bei Logto Cloud! Wir möchten gerne ein bisschen mehr über Sie erfahren.',
|
||||
description:
|
||||
'Egal, ob Sie ein Open-Source- oder Cloud-Benutzer sind, machen Sie eine Tour durch die Showcase und erleben Sie den vollen Wert von Logto. Die Cloud-Vorschau dient auch als vorläufige Version von Logto Cloud.',
|
||||
'Machen Sie Ihre Logto-Erfahrung einzigartig, indem Sie uns besser kennenlernen. Ihre Informationen sind bei uns sicher.',
|
||||
project_field: 'Ich verwende Logto für',
|
||||
project_options: {
|
||||
personal: 'Persönliches Projekt',
|
||||
company: 'Unternehmensprojekt',
|
||||
},
|
||||
deployment_type_field: 'Bevorzugst du Open-Source oder Cloud?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Open-Source',
|
||||
cloud: 'Cloud',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Ein bisschen über Sie',
|
||||
title: 'Ein wenig über Sie',
|
||||
description:
|
||||
'Machen Sie Ihre Logto-Erfahrung einzigartig, indem Sie uns besser kennenlernen. Ihre Informationen sind bei uns sicher.',
|
||||
title_field: 'Ihr Titel',
|
||||
title_options: {
|
||||
developer: 'Entwickler',
|
||||
|
|
|
@ -4,25 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: 'Welcome',
|
||||
title: 'Welcome and let’s create your own Logto Cloud Preview',
|
||||
title: "Welcome to Logto Cloud! We'd love to learn a bit about you.",
|
||||
description:
|
||||
'Whether you’re an open-source or cloud user, take a tour of the showcase and experience the full value of Logto. Cloud preview also serves as a preliminary version of Logto Cloud.',
|
||||
'Let‘s make your Logto experience unique to you by getting to know you better. Your information is safe with us.',
|
||||
project_field: 'I’m using Logto for',
|
||||
project_options: {
|
||||
personal: 'Personal project',
|
||||
company: 'Company project',
|
||||
},
|
||||
deployment_type_field: 'Prefer open-source or cloud?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Open-Source',
|
||||
cloud: 'Cloud',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'A bit about you',
|
||||
title: 'A little bit about you',
|
||||
description:
|
||||
'Let‘s make your Logto experience unique to you by getting to know you better. Your information is safe with us.',
|
||||
title_field: 'Your title',
|
||||
title_options: {
|
||||
developer: 'Developer',
|
||||
|
|
|
@ -3,26 +3,15 @@ const cloud = {
|
|||
onboarding: 'Integración',
|
||||
},
|
||||
welcome: {
|
||||
page_title: 'Bienvenido',
|
||||
title: 'Bienvenido y creemos su propia vista previa de Logto Cloud',
|
||||
page_title: 'Bienvenida',
|
||||
title: '¡Bienvenido a Logto Cloud! Nos encantaría saber un poco más sobre ti.',
|
||||
description:
|
||||
'Ya sea que sea un usuario de código abierto o en la nube, realice un recorrido por la vitrina y experimente el valor completo de Logto. La vista previa en la nube también sirve como una versión preliminar de Logto Cloud.',
|
||||
'Hagamos que su experiencia de Logto sea única para usted al conocerlo mejor. Su información está segura con nosotros.',
|
||||
project_field: 'Estoy usando Logto para:',
|
||||
project_options: {
|
||||
personal: 'Proyecto personal',
|
||||
company: 'Proyecto empresarial',
|
||||
},
|
||||
deployment_type_field: '¿Prefiere el código abierto o la nube?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Código abierto',
|
||||
cloud: 'Nube',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Un poco sobre ti',
|
||||
title: 'Un poco sobre ti',
|
||||
description:
|
||||
'Hagamos que su experiencia de Logto sea única para usted al conocerlo mejor. Su información está segura con nosotros.',
|
||||
title_field: 'Tu título',
|
||||
title_options: {
|
||||
developer: 'Desarrollador',
|
||||
|
|
|
@ -3,26 +3,15 @@ const cloud = {
|
|||
onboarding: 'Intégration',
|
||||
},
|
||||
welcome: {
|
||||
page_title: 'Bienvenue',
|
||||
title: 'Bienvenue et créons votre propre aperçu cloud de Logto',
|
||||
page_title: 'Welcome',
|
||||
title: 'Bienvenue dans Logto Cloud ! Nous aimerions en savoir un peu plus sur vous.',
|
||||
description:
|
||||
'Que vous soyez un utilisateur open-source ou cloud, faites une visite de la vitrine et découvrez la valeur totale de Logto. Le Cloud Preview sert également de version préliminaire de Logto Cloud.',
|
||||
'Personnalisons votre expérience Logto en vous connaissant mieux. Vos informations sont en sécurité avec nous.',
|
||||
project_field: "J'utilise Logto pour",
|
||||
project_options: {
|
||||
personal: 'Projet personnel',
|
||||
company: "Projet d'entreprise",
|
||||
},
|
||||
deployment_type_field: 'Vous préférez open-source ou cloud?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Open-Source',
|
||||
cloud: 'Cloud',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Un peu à propos de vous',
|
||||
title: 'Un peu à propos de vous',
|
||||
description:
|
||||
'Personnalisons votre expérience Logto en vous connaissant mieux. Vos informations sont en sécurité avec nous.',
|
||||
title_field: 'Votre titre',
|
||||
title_options: {
|
||||
developer: 'Développeur',
|
||||
|
|
|
@ -4,25 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: 'Benvenuto',
|
||||
title: 'Benvenuto e creiamo insieme la tua anteprima di Logto Cloud',
|
||||
title: "Benvenuto in Logto Cloud! Ci piacerebbe conoscere un po' di te.",
|
||||
description:
|
||||
'Che tu sia un utente open-source o cloud, fai un tour della vetrina e scopri il valore completo di Logto. Cloud preview serve anche come versione preliminare di Logto Cloud.',
|
||||
'Facciamo diventare la tua esperienza Logto unica conoscendoti meglio. Le tue informazioni sono al sicuro con noi.',
|
||||
project_field: 'Sto usando Logto per',
|
||||
project_options: {
|
||||
personal: 'Progetto personale',
|
||||
company: 'Progetto aziendale',
|
||||
},
|
||||
deployment_type_field: 'Preferisci open-source o cloud?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Open-Source',
|
||||
cloud: 'Cloud',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: "Un po' di te",
|
||||
title: "Un po' di te per rendere unica la tua esperienza Logto",
|
||||
description:
|
||||
'Facciamo diventare la tua esperienza Logto unica conoscendoti meglio. Le tue informazioni sono al sicuro con noi.',
|
||||
title_field: 'La tua posizione',
|
||||
title_options: {
|
||||
developer: 'Sviluppatore',
|
||||
|
|
|
@ -4,25 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: 'ようこそ',
|
||||
title: 'ようこそ、あなたのLogto Cloud Previewを作成しましょう',
|
||||
title: 'Logto Cloud へようこそ!あなたについて少し学びたいです。',
|
||||
description:
|
||||
'オープンソースユーザーでもクラウドユーザーでも、ショーケースを見て、Logtoのすべての価値を体験してください。Cloud PreviewはLogto Cloudの予備バージョンでもあります。',
|
||||
'あなたの情報を知ることで、あなたにユニークなLogtoエクスペリエンスを提供します。あなたの情報は安全に保管されます。',
|
||||
project_field: 'ログトを使用しています',
|
||||
project_options: {
|
||||
personal: '個人プロジェクト',
|
||||
company: '会社プロジェクト',
|
||||
},
|
||||
deployment_type_field: 'オープンソースまたはクラウドを希望しますか?',
|
||||
deployment_type_options: {
|
||||
open_source: 'オープンソース',
|
||||
cloud: 'クラウド',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'あなたについて',
|
||||
title: 'あなたについて少し教えてください',
|
||||
description:
|
||||
'あなたの情報を知ることで、あなたにユニークなLogtoエクスペリエンスを提供します。あなたの情報は安全に保管されます。',
|
||||
title_field: 'あなたのタイトル',
|
||||
title_options: {
|
||||
developer: '開発者',
|
||||
|
|
|
@ -4,25 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: '환영합니다',
|
||||
title: '환영합니다. 당신 만의 Logto Cloud Preview를 만들어 보세요',
|
||||
title: 'Logto Cloud 에 오신 것을 환영합니다! 조금 더 알고 싶어요.',
|
||||
description:
|
||||
'오픈 소스 사용자든 클라우드 사용자든, 쇼케이스를 둘러보고 Logto의 모든 가치를 경험해 보세요. 클라우드 미리 보기는 Logto Cloud의 미리 보기 버전으로도 제공돼요.',
|
||||
project_field: 'Logto를 아래의 목적으로 사용해요',
|
||||
'당신에 대해 더 잘 파악하여 Logto 경험을 특별하게 만들어 드릴게요. 정보는 저희가 안전하게 관리해요.',
|
||||
project_field: 'Logto 를 아래의 목적으로 사용해요',
|
||||
project_options: {
|
||||
personal: '개인 프로젝트',
|
||||
company: '기업 프로젝트',
|
||||
},
|
||||
deployment_type_field: '오픈 소스와 클라우드 중 어느 쪽을 선호하시나요?',
|
||||
deployment_type_options: {
|
||||
open_source: '오픈 소스',
|
||||
cloud: '클라우드',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: '본인에 대해 간략히 소개하기',
|
||||
title: '당신에 관하여',
|
||||
description:
|
||||
'당신에 대해 더 잘 파악하여 Logto 경험을 특별하게 만들어 드릴게요. 정보는 저희가 안전하게 관리해요.',
|
||||
title_field: '당신의 직함',
|
||||
title_options: {
|
||||
developer: '개발자',
|
||||
|
|
|
@ -3,26 +3,15 @@ const cloud = {
|
|||
onboarding: 'Wdrażanie',
|
||||
},
|
||||
welcome: {
|
||||
page_title: 'Witaj',
|
||||
title: 'Witaj i stwórz własny podgląd chmury Logto',
|
||||
page_title: 'Witamy',
|
||||
title: 'Witaj w chmurze Logto! Chcielibyśmy dowiedzieć się trochę o Tobie.',
|
||||
description:
|
||||
'Nie ważne czy jesteś użytkownikiem open-source czy chmury, przejdź przez prezentacje i doświadcz pełnej wartości Logto. Podgląd chmury serwuje również jako wstępna wersja chmury Logto.',
|
||||
'Stwórz indywidualne wrażenia z Logto dzięki naszej wiedzy na temat Ciebie. Twoje informacje są bezpieczne u nas.',
|
||||
project_field: 'Używam Logto do',
|
||||
project_options: {
|
||||
personal: 'Projektu osobistego',
|
||||
company: 'Projektu firmowego',
|
||||
},
|
||||
deployment_type_field: 'Wolisz open-source czy chmurę?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Open-Source',
|
||||
cloud: 'Chmura',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Trochę o Tobie',
|
||||
title: 'Trochę o Tobie',
|
||||
description:
|
||||
'Stwórz indywidualne wrażenia z Logto dzięki naszej wiedzy na temat Ciebie. Twoje informacje są bezpieczne u nas.',
|
||||
title_field: 'Twój tytuł',
|
||||
title_options: {
|
||||
developer: 'Developer',
|
||||
|
|
|
@ -3,26 +3,15 @@ const cloud = {
|
|||
onboarding: 'Integração',
|
||||
},
|
||||
welcome: {
|
||||
page_title: 'Boas-vindas',
|
||||
title: 'Boas-vindas e vamos criar sua própria visualização de nuvem Logto',
|
||||
page_title: 'Bem-vindo',
|
||||
title: 'Bem-vindo ao Logto Cloud! Gostaríamos de conhecer um pouco sobre você.',
|
||||
description:
|
||||
'Se você é um usuário de código aberto ou de nuvem, faça um passeio pela vitrine e experimente o valor completo do Logto. A visualização da nuvem também serve como uma versão preliminar da nuvem Logto.',
|
||||
'Vamos tornar sua experiência Logto única, conhecendo você melhor. Suas informações estão seguras conosco.',
|
||||
project_field: 'Estou usando o Logto para',
|
||||
project_options: {
|
||||
personal: 'Projeto pessoal',
|
||||
company: 'Projeto da empresa',
|
||||
},
|
||||
deployment_type_field: 'Preferencialmente de código aberto ou na nuvem?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Código aberto',
|
||||
cloud: 'Nuvem',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Um pouco sobre você',
|
||||
title: 'Um pouco sobre você',
|
||||
description:
|
||||
'Vamos tornar sua experiência Logto única, conhecendo você melhor. Suas informações estão seguras conosco.',
|
||||
title_field: 'O seu título',
|
||||
title_options: {
|
||||
developer: 'Desenvolvedor',
|
||||
|
|
|
@ -4,25 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: 'Bem-vindo',
|
||||
title: 'Bem-vindo e vamos criar a sua própria visualização da Logto Cloud',
|
||||
title: 'Bem-vindo ao Logto Cloud! Gostaríamos de aprender um pouco sobre você.',
|
||||
description:
|
||||
'Seja um usuário de código aberto ou de nuvem, faça um passeio pela demonstração e experimente o valor total da Logto. A pré-visualização da nuvem também serve como uma versão preliminar da Logto Cloud.',
|
||||
'Vamos tornar a experiência da Logto única para você conhecendo você melhor. Suas informações estão seguras conosco.',
|
||||
project_field: 'Estou usando a Logto para',
|
||||
project_options: {
|
||||
personal: 'Projeto pessoal',
|
||||
company: 'Projeto da empresa',
|
||||
},
|
||||
deployment_type_field: 'Prefere código aberto ou nuvem?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Código aberto',
|
||||
cloud: 'Nuvem',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Um pouco sobre você',
|
||||
title: 'Um pouco sobre você',
|
||||
description:
|
||||
'Vamos tornar a experiência da Logto única para você conhecendo você melhor. Suas informações estão seguras conosco.',
|
||||
title_field: 'O seu título',
|
||||
title_options: {
|
||||
developer: 'Desenvolvedor/a',
|
||||
|
@ -119,7 +108,7 @@ const cloud = {
|
|||
'Você entrou com sucesso usando sua conta social. Para garantir uma integração perfeita e acesso a todos os recursos do Logto, recomendamos que você prossiga para configurar seu próprio conector social.',
|
||||
},
|
||||
tenant: {
|
||||
create_tenant: 'Create tenant',
|
||||
create_tenant: 'Criar novo inquilino',
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -4,26 +4,14 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: 'Добро пожаловать',
|
||||
title:
|
||||
'Добро пожаловать, и давайте создадим свой собственный предварительный просмотр облака Logto',
|
||||
title: 'Добро пожаловать в облако Logto! Мы хотели бы узнать вас получше.',
|
||||
description:
|
||||
'Независимо от того, являетесь ли вы пользователем открытого исходного кода или облачным пользователем, ознакомьтесь с витриной и ощутите полную ценность Logto. Предварительный просмотр облака также служит предварительной версией облака Logto.',
|
||||
'Сделайте свой опыт работы с Logto уникальным для вас, узнав вас получше. Ваша информация надежно защищена.',
|
||||
project_field: 'Я использую Logto для',
|
||||
project_options: {
|
||||
personal: 'Личного проекта',
|
||||
company: 'Компании',
|
||||
},
|
||||
deployment_type_field: 'Предпочитаете открытый исходный код или облако?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Открытый Исходный Код',
|
||||
cloud: 'Облачный',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Немного о вас',
|
||||
title: 'Немного о вас',
|
||||
description:
|
||||
'Сделайте свой опыт работы с Logto уникальным для вас, узнав вас получше. Ваша информация надежно защищена.',
|
||||
title_field: 'Твоя должность',
|
||||
title_options: {
|
||||
developer: 'Разработчик',
|
||||
|
|
|
@ -3,26 +3,15 @@ const cloud = {
|
|||
onboarding: 'Başlatma',
|
||||
},
|
||||
welcome: {
|
||||
page_title: 'Hoşgeldiniz',
|
||||
title: 'Hoşgeldiniz ve kendi Logto Cloud Önizlemenizi oluşturalım',
|
||||
page_title: 'Hoş geldiniz',
|
||||
title: "Logto Cloud'a hoş geldiniz! Sizi biraz tanımak istiyoruz.",
|
||||
description:
|
||||
"Açık kaynak veya bulut kullanıcısı olsanız da, sergi turuna çıkın ve Logto'nun tam değerini deneyimleyin. Cloud önizlemesi ayrıca Logto Cloud'un ön sürümü olarak da hizmet verir.",
|
||||
'Sizi daha iyi tanıyarak Logto deneyiminizi size özel hale getirelim. Bilgileriniz bizimle güvende.',
|
||||
project_field: "Logto'yu kullanıyorum çünkü",
|
||||
project_options: {
|
||||
personal: 'Kişisel proje',
|
||||
company: 'Şirket projesi',
|
||||
},
|
||||
deployment_type_field: 'Açık kaynak veya bulut tercih eder misiniz?',
|
||||
deployment_type_options: {
|
||||
open_source: 'Açık Kaynak',
|
||||
cloud: 'Bulut',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: 'Biraz sen hakkında',
|
||||
title: 'Senin hakkında biraz bilgi',
|
||||
description:
|
||||
'Sizi daha iyi tanıyarak Logto deneyiminizi size özel hale getirelim. Bilgileriniz bizimle güvende.',
|
||||
title_field: 'Unvanın',
|
||||
title_options: {
|
||||
developer: 'Geliştirici',
|
||||
|
|
|
@ -4,24 +4,13 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: '欢迎',
|
||||
title: '欢迎来到 Logto Cloud(预览版),让我们一起创建独属于你的体验',
|
||||
description:
|
||||
'无论你是开源用户还是云用户,都可以在展示中了解 Logto 的全部价值。Cloud 预览版也是 Logto Cloud 的初步版本。',
|
||||
title: '欢迎来到 Logto Cloud!我们很想了解你。',
|
||||
description: '通过更好地了解你,我们可以使你的 Logto 体验更加个性化。你的信息是安全的。',
|
||||
project_field: '我使用 Logto 是为了',
|
||||
project_options: {
|
||||
personal: '个人项目',
|
||||
company: '公司项目',
|
||||
},
|
||||
deployment_type_field: '你偏爱开源还是云?',
|
||||
deployment_type_options: {
|
||||
open_source: '开源',
|
||||
cloud: '云',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: '关于你',
|
||||
title: '关于你的一些信息',
|
||||
description: '通过更好地了解你,我们可以使你的 Logto 体验更加个性化。你的信息是安全的。',
|
||||
title_field: '你的头衔',
|
||||
title_options: {
|
||||
developer: '开发人员',
|
||||
|
|
|
@ -4,24 +4,13 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: '歡迎',
|
||||
title: '歡迎來到 Logto Cloud(預覽版),讓我們一起創建獨屬於你的體驗',
|
||||
description:
|
||||
'無論你是開源用戶還是雲用戶,都可以在展示中了解 Logto 的全部價值。Cloud 預覽版也是 Logto Cloud 的初步版本。',
|
||||
title: '歡迎來到 Logto Cloud!我們很想了解你的一些信息。',
|
||||
description: '通過更好地了解你,我們可以使你的 Logto 體驗更加個性化。你的信息是安全的。',
|
||||
project_field: '我使用 Logto 是為了',
|
||||
project_options: {
|
||||
personal: '個人專案',
|
||||
company: '公司專案',
|
||||
},
|
||||
deployment_type_field: '你偏愛開源還是雲?',
|
||||
deployment_type_options: {
|
||||
open_source: '開源',
|
||||
cloud: '雲',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: '關於你',
|
||||
title: '關於你的一些信息',
|
||||
description: '通過更好地了解你,我們可以使你的 Logto 體驗更加個性化。你的信息是安全的。',
|
||||
title_field: '你的頭銜',
|
||||
title_options: {
|
||||
developer: '開發人員',
|
||||
|
|
|
@ -4,24 +4,13 @@ const cloud = {
|
|||
},
|
||||
welcome: {
|
||||
page_title: '歡迎',
|
||||
title: '歡迎來到 Logto Cloud(預覽版),讓我們一起創建獨屬於你的體驗',
|
||||
description:
|
||||
'無論你是開源用戶還是雲用戶,都可以在展示中了解 Logto 的全部價值。Cloud 預覽版也是 Logto Cloud 的初步版本。',
|
||||
title: '歡迎來到 Logto Cloud!我們很想了解一些關於你的資訊。',
|
||||
description: '通過更好地了解你,我們可以使你的 Logto 體驗更加個性化。你的信息是安全的。',
|
||||
project_field: '我使用 Logto 是為了',
|
||||
project_options: {
|
||||
personal: '個人專案',
|
||||
company: '公司專案',
|
||||
},
|
||||
deployment_type_field: '你偏愛開源還是雲?',
|
||||
deployment_type_options: {
|
||||
open_source: '開源',
|
||||
cloud: '雲',
|
||||
},
|
||||
},
|
||||
about: {
|
||||
page_title: '關於你',
|
||||
title: '關於你的一些信息',
|
||||
description: '通過更好地了解你,我們可以使你的 Logto 體驗更加個性化。你的信息是安全的。',
|
||||
title_field: '你的頭銜',
|
||||
title_options: {
|
||||
developer: '開發人員',
|
||||
|
|
Loading…
Reference in a new issue