Merge branch 'onboarding-fixes' into 'main'
Onboarding fixes See merge request soapbox-pub/soapbox!3318
This commit is contained in:
commit
c84bddb466
|
@ -34,7 +34,7 @@ import {
|
||||||
MuteModal,
|
MuteModal,
|
||||||
NostrLoginModal,
|
NostrLoginModal,
|
||||||
NostrSignupModal,
|
NostrSignupModal,
|
||||||
OnboardingFlowModal,
|
OnboardingModal,
|
||||||
ReactionsModal,
|
ReactionsModal,
|
||||||
ReblogsModal,
|
ReblogsModal,
|
||||||
ReplyMentionsModal,
|
ReplyMentionsModal,
|
||||||
|
@ -87,7 +87,7 @@ const MODAL_COMPONENTS: Record<string, React.ExoticComponent<any>> = {
|
||||||
'MUTE': MuteModal,
|
'MUTE': MuteModal,
|
||||||
'NOSTR_LOGIN': NostrLoginModal,
|
'NOSTR_LOGIN': NostrLoginModal,
|
||||||
'NOSTR_SIGNUP': NostrSignupModal,
|
'NOSTR_SIGNUP': NostrSignupModal,
|
||||||
'ONBOARDING_FLOW': OnboardingFlowModal,
|
'ONBOARDING': OnboardingModal,
|
||||||
'REACTIONS': ReactionsModal,
|
'REACTIONS': ReactionsModal,
|
||||||
'REBLOGS': ReblogsModal,
|
'REBLOGS': ReblogsModal,
|
||||||
'REPLY_MENTIONS': ReplyMentionsModal,
|
'REPLY_MENTIONS': ReplyMentionsModal,
|
||||||
|
|
|
@ -12,15 +12,15 @@ import AvatarSelectionModal from './steps/avatar-step.tsx';
|
||||||
import BioStep from './steps/bio-step.tsx';
|
import BioStep from './steps/bio-step.tsx';
|
||||||
import CompletedModal from './steps/completed-step.tsx';
|
import CompletedModal from './steps/completed-step.tsx';
|
||||||
import CoverPhotoSelectionModal from './steps/cover-photo-selection-step.tsx';
|
import CoverPhotoSelectionModal from './steps/cover-photo-selection-step.tsx';
|
||||||
import DisplayUserNameStep from './steps/display-identity-step.tsx';
|
|
||||||
import DisplayNameStep from './steps/display-name-step.tsx';
|
import DisplayNameStep from './steps/display-name-step.tsx';
|
||||||
import SuggestedAccountsModal from './steps/suggested-accounts-step.tsx';
|
import SuggestedAccountsModal from './steps/suggested-accounts-step.tsx';
|
||||||
|
import UsernameStep from './steps/username-step.tsx';
|
||||||
|
|
||||||
interface IOnboardingFlowModal {
|
interface IOnboardingModal {
|
||||||
onClose(): void;
|
onClose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OnboardingFlowModal: React.FC<IOnboardingFlowModal> = ({ onClose }) => {
|
const OnboardingModal: React.FC<IOnboardingModal> = ({ onClose }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const [currentStep, setCurrentStep] = useState<number>(0);
|
const [currentStep, setCurrentStep] = useState<number>(0);
|
||||||
|
@ -49,7 +49,7 @@ const OnboardingFlowModal: React.FC<IOnboardingFlowModal> = ({ onClose }) => {
|
||||||
const steps = [
|
const steps = [
|
||||||
<AvatarSelectionModal onClose={handleComplete} onNext={handleNextStep} />,
|
<AvatarSelectionModal onClose={handleComplete} onNext={handleNextStep} />,
|
||||||
<DisplayNameStep onClose={handleComplete} onNext={handleNextStep} />,
|
<DisplayNameStep onClose={handleComplete} onNext={handleNextStep} />,
|
||||||
<DisplayUserNameStep onClose={handleComplete} onNext={handleNextStep} />,
|
<UsernameStep onClose={handleComplete} onNext={handleNextStep} />,
|
||||||
<BioStep onClose={handleComplete} onNext={handleNextStep} />,
|
<BioStep onClose={handleComplete} onNext={handleNextStep} />,
|
||||||
<CoverPhotoSelectionModal onClose={handleComplete} onNext={handleNextStep} />,
|
<CoverPhotoSelectionModal onClose={handleComplete} onNext={handleNextStep} />,
|
||||||
<SuggestedAccountsModal onClose={handleComplete} onNext={handleNextStep} />,
|
<SuggestedAccountsModal onClose={handleComplete} onNext={handleNextStep} />,
|
||||||
|
@ -78,9 +78,8 @@ const OnboardingFlowModal: React.FC<IOnboardingFlowModal> = ({ onClose }) => {
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={4} justifyContent='center' alignItems='center' className='relative w-full'>
|
<Stack space={5} justifyContent='center' alignItems='center' className='relative w-full'>
|
||||||
<Modal width='2xl' onClose={handleComplete} theme='transparent' >
|
<Modal width='2xl' onClose={handleComplete}>
|
||||||
<Stack space={4}>
|
|
||||||
<ReactSwipeableViews animateHeight index={currentStep} onChangeIndex={handleSwipe}>
|
<ReactSwipeableViews animateHeight index={currentStep} onChangeIndex={handleSwipe}>
|
||||||
{steps.map((step, i) => (
|
{steps.map((step, i) => (
|
||||||
<div key={i} className='w-full'>
|
<div key={i} className='w-full'>
|
||||||
|
@ -96,9 +95,9 @@ const OnboardingFlowModal: React.FC<IOnboardingFlowModal> = ({ onClose }) => {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</ReactSwipeableViews>
|
</ReactSwipeableViews>
|
||||||
</Stack>
|
</Modal>
|
||||||
<div className='relative flex w-full justify-center'>
|
|
||||||
<HStack space={3} alignItems='center' justifyContent='center' className='absolute h-10'>
|
<HStack space={3} alignItems='center' justifyContent='center' className='pointer-events-auto'>
|
||||||
{steps.map((_, i) => (
|
{steps.map((_, i) => (
|
||||||
<button
|
<button
|
||||||
key={i}
|
key={i}
|
||||||
|
@ -112,10 +111,8 @@ const OnboardingFlowModal: React.FC<IOnboardingFlowModal> = ({ onClose }) => {
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</HStack>
|
</HStack>
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OnboardingFlowModal;
|
export default OnboardingModal;
|
|
@ -11,7 +11,6 @@ import Input from 'soapbox/components/ui/input.tsx';
|
||||||
import Stack from 'soapbox/components/ui/stack.tsx';
|
import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||||
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
|
|
||||||
import toast from 'soapbox/toast.tsx';
|
import toast from 'soapbox/toast.tsx';
|
||||||
|
|
||||||
const closeIcon = xIcon;
|
const closeIcon = xIcon;
|
||||||
|
@ -30,14 +29,12 @@ const DisplayNameStep: React.FC<IDisplayNameStep> = ({ onClose, onNext }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const { account } = useOwnAccount();
|
const [value, setValue] = useState<string>('');
|
||||||
const [value, setValue] = useState<string>(account?.display_name || '');
|
|
||||||
const [isSubmitting, setSubmitting] = useState<boolean>(false);
|
const [isSubmitting, setSubmitting] = useState<boolean>(false);
|
||||||
const [errors, setErrors] = useState<string[]>([]);
|
const [errors, setErrors] = useState<string[]>([]);
|
||||||
|
|
||||||
const trimmedValue = value.trim();
|
const isValid = value.trim().length > 0;
|
||||||
const isValid = trimmedValue.length > 0;
|
const isDisabled = !isValid;
|
||||||
const isDisabled = !isValid || value.length > 30;
|
|
||||||
|
|
||||||
const hintText = useMemo(() => {
|
const hintText = useMemo(() => {
|
||||||
const charsLeft = 30 - value.length;
|
const charsLeft = 30 - value.length;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import helpSquare from '@tabler/icons/outline/help-square-rounded.svg';
|
|
||||||
import xIcon from '@tabler/icons/outline/x.svg';
|
import xIcon from '@tabler/icons/outline/x.svg';
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
@ -6,11 +5,8 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import Button from 'soapbox/components/ui/button.tsx';
|
import Button from 'soapbox/components/ui/button.tsx';
|
||||||
import FormGroup from 'soapbox/components/ui/form-group.tsx';
|
import FormGroup from 'soapbox/components/ui/form-group.tsx';
|
||||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
|
||||||
import IconButton from 'soapbox/components/ui/icon-button.tsx';
|
import IconButton from 'soapbox/components/ui/icon-button.tsx';
|
||||||
import Popover from 'soapbox/components/ui/popover.tsx';
|
|
||||||
import Stack from 'soapbox/components/ui/stack.tsx';
|
import Stack from 'soapbox/components/ui/stack.tsx';
|
||||||
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
|
|
||||||
import Text from 'soapbox/components/ui/text.tsx';
|
import Text from 'soapbox/components/ui/text.tsx';
|
||||||
import Textarea from 'soapbox/components/ui/textarea.tsx';
|
import Textarea from 'soapbox/components/ui/textarea.tsx';
|
||||||
import { UsernameInput } from 'soapbox/features/edit-identity/index.tsx';
|
import { UsernameInput } from 'soapbox/features/edit-identity/index.tsx';
|
||||||
|
@ -22,19 +18,16 @@ import toast from 'soapbox/toast.tsx';
|
||||||
const closeIcon = xIcon;
|
const closeIcon = xIcon;
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'onboarding.display_identity.title', defaultMessage: 'Choose an Identity' },
|
label: { id: 'onboarding.username.label', defaultMessage: 'Username' },
|
||||||
subtitle: { id: 'onboarding.display_identity.subtitle', defaultMessage: 'You can always edit this later.' },
|
placeholder: { id: 'onboarding.username.fields.reason_placeholder', defaultMessage: 'Why do you want to be part of the {siteTitle} community?' },
|
||||||
label: { id: 'onboarding.display_identity.label', defaultMessage: 'Identity' },
|
requested: { id: 'onboarding.username.request', defaultMessage: 'Username requested' },
|
||||||
helpText: { id: 'onboarding.display_identity.help_text', defaultMessage: 'This identifier is a unique username that represents you on the platform. This username can be used to personalize your experience and facilitate communication within the community.' },
|
|
||||||
placeholder: { id: 'onboarding.display_identity.fields.reason_placeholder', defaultMessage: 'Why do you want to be part of the {siteTitle} community?' },
|
|
||||||
requested: { id: 'onboarding.display_identity.request', defaultMessage: 'Username requested' },
|
|
||||||
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
|
error: { id: 'onboarding.error', defaultMessage: 'An unexpected error occurred. Please try again or skip this step.' },
|
||||||
saving: { id: 'onboarding.saving', defaultMessage: 'Saving…' },
|
saving: { id: 'onboarding.saving', defaultMessage: 'Saving…' },
|
||||||
next: { id: 'onboarding.next', defaultMessage: 'Next' },
|
next: { id: 'onboarding.next', defaultMessage: 'Next' },
|
||||||
skip: { id: 'onboarding.skip', defaultMessage: 'Skip for now' },
|
skip: { id: 'onboarding.skip', defaultMessage: 'Skip for now' },
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IDisplayUserNameStep {
|
interface IUsernameStep {
|
||||||
onClose?(): void;
|
onClose?(): void;
|
||||||
onNext: () => void;
|
onNext: () => void;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +45,7 @@ function useRequestName() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const DisplayUserNameStep: React.FC<IDisplayUserNameStep> = ({ onClose, onNext }) => {
|
const UsernameStep: React.FC<IUsernameStep> = ({ onClose, onNext }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { instance } = useInstance();
|
const { instance } = useInstance();
|
||||||
const { mutate } = useRequestName();
|
const { mutate } = useRequestName();
|
||||||
|
@ -61,9 +54,8 @@ const DisplayUserNameStep: React.FC<IDisplayUserNameStep> = ({ onClose, onNext }
|
||||||
const [username, setUsername] = useState<string>('');
|
const [username, setUsername] = useState<string>('');
|
||||||
const [reason, setReason] = useState<string>('');
|
const [reason, setReason] = useState<string>('');
|
||||||
|
|
||||||
const trimmedValue = username.trim();
|
const isValid = username.trim().length > 0;
|
||||||
const isValid = trimmedValue.length > 0;
|
const isDisabled = !isValid;
|
||||||
const isDisabled = !isValid || username.length > 30;
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
const name = `${username}@${instance.domain}`;
|
const name = `${username}@${instance.domain}`;
|
||||||
|
@ -72,6 +64,7 @@ const DisplayUserNameStep: React.FC<IDisplayUserNameStep> = ({ onClose, onNext }
|
||||||
|
|
||||||
mutate({ name, reason }, {
|
mutate({ name, reason }, {
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
|
onNext();
|
||||||
toast.success(intl.formatMessage(messages.requested));
|
toast.success(intl.formatMessage(messages.requested));
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ['names', 'pending'],
|
queryKey: ['names', 'pending'],
|
||||||
|
@ -85,43 +78,21 @@ const DisplayUserNameStep: React.FC<IDisplayUserNameStep> = ({ onClose, onNext }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack space={2} justifyContent='center' alignItems='center' className='relative w-full rounded-3xl bg-white px-4 py-8 text-gray-900 shadow-lg black:bg-black dark:bg-primary-900 dark:text-gray-100 dark:shadow-none sm:p-10'>
|
<Stack space={2} justifyContent='center' alignItems='center' className='relative w-full rounded-3xl bg-white px-4 py-8 text-gray-900 shadow-lg black:bg-black dark:bg-primary-900 dark:text-gray-100 dark:shadow-none sm:p-10'>
|
||||||
|
|
||||||
{/* <HeaderSteps onClose={onClose} title={intl.formatMessage(messages.title)} subtitle={intl.formatMessage(messages.subtitle)} /> */}
|
|
||||||
<div className='relative w-full'>
|
<div className='relative w-full'>
|
||||||
<IconButton src={closeIcon} onClick={onClose} className='absolute -right-2 -top-6 text-gray-500 hover:text-gray-700 dark:text-gray-300 dark:hover:text-gray-200 rtl:rotate-180' />
|
<IconButton src={closeIcon} onClick={onClose} className='absolute -right-2 -top-6 text-gray-500 hover:text-gray-700 dark:text-gray-300 dark:hover:text-gray-200 rtl:rotate-180' />
|
||||||
<Stack space={2} justifyContent='center' alignItems='center' className='-mx-4 mb-4 border-b border-solid pb-4 dark:border-gray-800 sm:-mx-10 sm:pb-10'>
|
<Stack space={2} justifyContent='center' alignItems='center' className='-mx-4 mb-4 border-b border-solid pb-4 dark:border-gray-800 sm:-mx-10 sm:pb-10'>
|
||||||
<Text size='2xl' align='center' weight='bold'>
|
<Text size='2xl' align='center' weight='bold'>
|
||||||
<FormattedMessage id='onboarding.header.title' defaultMessage='Pick a cover image' />
|
<FormattedMessage id='onboarding.username.title' defaultMessage='Request a username' />
|
||||||
</Text>
|
</Text>
|
||||||
<Text theme='muted' align='center'>
|
<Text theme='muted' align='center'>
|
||||||
<FormattedMessage id='onboarding.header.subtitle' defaultMessage='This will be shown at the top of your profile.' />
|
<FormattedMessage id='onboarding.username.subtitle' defaultMessage='Having an approved username will promote your account on this server.' />
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Stack space={5} justifyContent='center' alignItems='center' className='w-full'>
|
<Stack space={5} justifyContent='center' alignItems='center' className='w-full'>
|
||||||
<div className='w-full sm:w-3/4'>
|
<div className='w-full sm:w-3/4'>
|
||||||
<FormGroup
|
<FormGroup labelText={intl.formatMessage(messages.label)}>
|
||||||
labelText={
|
|
||||||
<HStack space={2}>
|
|
||||||
<div>
|
|
||||||
{intl.formatMessage(messages.label)}
|
|
||||||
</div>
|
|
||||||
<Popover
|
|
||||||
interaction='hover' content={
|
|
||||||
<Text className='w-48 text-justify sm:w-72'>
|
|
||||||
{intl.formatMessage(messages.helpText)}
|
|
||||||
</Text>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<SvgIcon size={20} src={helpSquare} className='hover:cursor-pointer' />
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
</HStack>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Stack space={4}>
|
<Stack space={4}>
|
||||||
<UsernameInput value={username} onChange={(e) => setUsername(e.target.value)} />
|
<UsernameInput value={username} onChange={(e) => setUsername(e.target.value)} />
|
||||||
<Textarea
|
<Textarea
|
||||||
|
@ -156,4 +127,4 @@ const DisplayUserNameStep: React.FC<IDisplayUserNameStep> = ({ onClose, onNext }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default DisplayUserNameStep;
|
export default UsernameStep;
|
|
@ -160,7 +160,7 @@ export const EditAnnouncementModal = lazy(() => import('soapbox/features/ui/comp
|
||||||
export const FollowedTags = lazy(() => import('soapbox/features/followed-tags/index.tsx'));
|
export const FollowedTags = lazy(() => import('soapbox/features/followed-tags/index.tsx'));
|
||||||
export const AccountNotePanel = lazy(() => import('soapbox/features/ui/components/panels/account-note-panel.tsx'));
|
export const AccountNotePanel = lazy(() => import('soapbox/features/ui/components/panels/account-note-panel.tsx'));
|
||||||
export const ComposeEditor = lazy(() => import('soapbox/features/compose/editor/index.tsx'));
|
export const ComposeEditor = lazy(() => import('soapbox/features/compose/editor/index.tsx'));
|
||||||
export const OnboardingFlowModal = lazy(() => import('soapbox/features/ui/components/modals/onboarding-flow-modal/onboarding-flow-modal.tsx'));
|
export const OnboardingModal = lazy(() => import('soapbox/features/ui/components/modals/onboarding-flow-modal/onboarding-modal.tsx'));
|
||||||
export const NostrSignupModal = lazy(() => import('soapbox/features/ui/components/modals/nostr-signup-modal/nostr-signup-modal.tsx'));
|
export const NostrSignupModal = lazy(() => import('soapbox/features/ui/components/modals/nostr-signup-modal/nostr-signup-modal.tsx'));
|
||||||
export const NostrLoginModal = lazy(() => import('soapbox/features/ui/components/modals/nostr-login-modal/nostr-login-modal.tsx'));
|
export const NostrLoginModal = lazy(() => import('soapbox/features/ui/components/modals/nostr-login-modal/nostr-login-modal.tsx'));
|
||||||
export const EditIdentity = lazy(() => import('soapbox/features/edit-identity/index.tsx'));
|
export const EditIdentity = lazy(() => import('soapbox/features/edit-identity/index.tsx'));
|
||||||
|
|
|
@ -41,7 +41,7 @@ const SoapboxMount = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (showOnboarding && !showCaptcha) {
|
if (showOnboarding && !showCaptcha) {
|
||||||
dispatch(openModal('ONBOARDING_FLOW'));
|
dispatch(openModal('ONBOARDING'));
|
||||||
}
|
}
|
||||||
}, [showOnboarding, showCaptcha]);
|
}, [showOnboarding, showCaptcha]);
|
||||||
|
|
||||||
|
|
|
@ -1233,12 +1233,6 @@
|
||||||
"onboarding.avatar.title": "Choose a profile picture",
|
"onboarding.avatar.title": "Choose a profile picture",
|
||||||
"onboarding.bio.hint": "Max 500 characters",
|
"onboarding.bio.hint": "Max 500 characters",
|
||||||
"onboarding.bio.placeholder": "Tell the world a little about yourself…",
|
"onboarding.bio.placeholder": "Tell the world a little about yourself…",
|
||||||
"onboarding.display_identity.fields.reason_placeholder": "Why do you want to be part of the {siteTitle} community?",
|
|
||||||
"onboarding.display_identity.help_text": "This identifier is a unique username that represents you on the platform. This username can be used to personalize your experience and facilitate communication within the community.",
|
|
||||||
"onboarding.display_identity.label": "Identity",
|
|
||||||
"onboarding.display_identity.request": "Username requested",
|
|
||||||
"onboarding.display_identity.subtitle": "You can always edit this later.",
|
|
||||||
"onboarding.display_identity.title": "Choose an Identity",
|
|
||||||
"onboarding.display_name.label": "Display name",
|
"onboarding.display_name.label": "Display name",
|
||||||
"onboarding.display_name.placeholder": "Eg. John Smith",
|
"onboarding.display_name.placeholder": "Eg. John Smith",
|
||||||
"onboarding.display_name.subtitle": "You can always edit this later.",
|
"onboarding.display_name.subtitle": "You can always edit this later.",
|
||||||
|
@ -1256,6 +1250,11 @@
|
||||||
"onboarding.skip": "Skip for now",
|
"onboarding.skip": "Skip for now",
|
||||||
"onboarding.suggestions.subtitle": "Here are a few of the most popular accounts you might like.",
|
"onboarding.suggestions.subtitle": "Here are a few of the most popular accounts you might like.",
|
||||||
"onboarding.suggestions.title": "Suggested accounts",
|
"onboarding.suggestions.title": "Suggested accounts",
|
||||||
|
"onboarding.username.fields.reason_placeholder": "Why do you want to be part of the {siteTitle} community?",
|
||||||
|
"onboarding.username.label": "Username",
|
||||||
|
"onboarding.username.request": "Username requested",
|
||||||
|
"onboarding.username.subtitle": "Having an approved username will promote your account on this server.",
|
||||||
|
"onboarding.username.title": "Request a username",
|
||||||
"onboarding.view_feed": "View Feed",
|
"onboarding.view_feed": "View Feed",
|
||||||
"password_reset.confirmation": "Check your email for confirmation.",
|
"password_reset.confirmation": "Check your email for confirmation.",
|
||||||
"password_reset.fields.email_placeholder": "E-mail address",
|
"password_reset.fields.email_placeholder": "E-mail address",
|
||||||
|
|
Loading…
Reference in New Issue