Translations - Crowdin, Set workspace member locale on signup, and optimizations (#10091)
More progress on translations: - Migrate from translations.io to crowdin - Optimize performance and robustness - Set workspaceMember/user locale upon signup
This commit is contained in:
@ -21,6 +21,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { OnboardingStatus } from '~/generated/graphql';
|
||||
|
||||
@ -55,6 +56,7 @@ const validationSchema = z
|
||||
type Form = z.infer<typeof validationSchema>;
|
||||
|
||||
export const CreateProfile = () => {
|
||||
const { t } = useLingui();
|
||||
const onboardingStatus = useOnboardingStatus();
|
||||
const setNextOnboardingStatus = useSetNextOnboardingStatus();
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
@ -148,8 +150,12 @@ export const CreateProfile = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title noMarginTop>Create profile</Title>
|
||||
<SubTitle>How you'll be identified on the app.</SubTitle>
|
||||
<Title noMarginTop>
|
||||
<Trans>Create profile</Trans>
|
||||
</Title>
|
||||
<SubTitle>
|
||||
<Trans>How you'll be identified on the app.</Trans>
|
||||
</SubTitle>
|
||||
<StyledContentContainer>
|
||||
<StyledSectionContainer>
|
||||
<H2Title title="Picture" />
|
||||
@ -157,8 +163,8 @@ export const CreateProfile = () => {
|
||||
</StyledSectionContainer>
|
||||
<StyledSectionContainer>
|
||||
<H2Title
|
||||
title="Name"
|
||||
description="Your name as it will be displayed on the app"
|
||||
title={t`Name`}
|
||||
description={t`Your name as it will be displayed on the app`}
|
||||
/>
|
||||
{/* TODO: When react-web-hook-form is added to edit page we should create a dedicated component with context */}
|
||||
<StyledComboInputContainer>
|
||||
@ -171,7 +177,7 @@ export const CreateProfile = () => {
|
||||
}) => (
|
||||
<TextInputV2
|
||||
autoFocus
|
||||
label="First Name"
|
||||
label={t`First Name`}
|
||||
value={value}
|
||||
onFocus={() => setIsEditingMode(true)}
|
||||
onBlur={() => {
|
||||
@ -193,7 +199,7 @@ export const CreateProfile = () => {
|
||||
fieldState: { error },
|
||||
}) => (
|
||||
<TextInputV2
|
||||
label="Last Name"
|
||||
label={t`Last Name`}
|
||||
value={value}
|
||||
onFocus={() => setIsEditingMode(true)}
|
||||
onBlur={() => {
|
||||
@ -212,7 +218,7 @@ export const CreateProfile = () => {
|
||||
</StyledContentContainer>
|
||||
<StyledButtonContainer>
|
||||
<MainButton
|
||||
title="Continue"
|
||||
title={t`Continue`}
|
||||
onClick={handleSubmit(onSubmit)}
|
||||
disabled={!isValid || isSubmitting}
|
||||
fullWidth
|
||||
|
||||
@ -15,6 +15,7 @@ import { WorkspaceLogoUploader } from '@/settings/workspace/components/Workspace
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import {
|
||||
OnboardingStatus,
|
||||
@ -34,15 +35,8 @@ const StyledButtonContainer = styled.div`
|
||||
width: 200px;
|
||||
`;
|
||||
|
||||
const validationSchema = z
|
||||
.object({
|
||||
name: z.string().min(1, { message: 'Name can not be empty' }),
|
||||
})
|
||||
.required();
|
||||
|
||||
type Form = z.infer<typeof validationSchema>;
|
||||
|
||||
export const CreateWorkspace = () => {
|
||||
const { t } = useLingui();
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
const onboardingStatus = useOnboardingStatus();
|
||||
const setNextOnboardingStatus = useSetNextOnboardingStatus();
|
||||
@ -50,6 +44,14 @@ export const CreateWorkspace = () => {
|
||||
const { loadCurrentUser } = useAuth();
|
||||
const [activateWorkspace] = useActivateWorkspaceMutation();
|
||||
|
||||
const validationSchema = z
|
||||
.object({
|
||||
name: z.string().min(1, { message: t`Name can not be empty` }),
|
||||
})
|
||||
.required();
|
||||
|
||||
type Form = z.infer<typeof validationSchema>;
|
||||
|
||||
// Form
|
||||
const {
|
||||
control,
|
||||
@ -75,7 +77,7 @@ export const CreateWorkspace = () => {
|
||||
});
|
||||
|
||||
if (isDefined(result.errors)) {
|
||||
throw result.errors ?? new Error('Unknown error');
|
||||
throw result.errors ?? new Error(t`Unknown error`);
|
||||
}
|
||||
await loadCurrentUser();
|
||||
setNextOnboardingStatus();
|
||||
@ -90,6 +92,7 @@ export const CreateWorkspace = () => {
|
||||
enqueueSnackBar,
|
||||
loadCurrentUser,
|
||||
setNextOnboardingStatus,
|
||||
t,
|
||||
],
|
||||
);
|
||||
|
||||
@ -106,20 +109,24 @@ export const CreateWorkspace = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title noMarginTop>Create your workspace</Title>
|
||||
<Title noMarginTop>
|
||||
<Trans>Create your workspace</Trans>
|
||||
</Title>
|
||||
<SubTitle>
|
||||
A shared environment where you will be able to manage your customer
|
||||
relations with your team.
|
||||
<Trans>
|
||||
A shared environment where you will be able to manage your customer
|
||||
relations with your team.
|
||||
</Trans>
|
||||
</SubTitle>
|
||||
<StyledContentContainer>
|
||||
<StyledSectionContainer>
|
||||
<H2Title title="Workspace logo" />
|
||||
<H2Title title={t`Workspace logo`} />
|
||||
<WorkspaceLogoUploader />
|
||||
</StyledSectionContainer>
|
||||
<StyledSectionContainer>
|
||||
<H2Title
|
||||
title="Workspace name"
|
||||
description="The name of your organization"
|
||||
title={t`Workspace name`}
|
||||
description={t`The name of your organization`}
|
||||
/>
|
||||
<Controller
|
||||
name="name"
|
||||
@ -144,7 +151,7 @@ export const CreateWorkspace = () => {
|
||||
</StyledContentContainer>
|
||||
<StyledButtonContainer>
|
||||
<MainButton
|
||||
title="Continue"
|
||||
title={t`Continue`}
|
||||
onClick={handleSubmit(onSubmit)}
|
||||
disabled={!isValid || isSubmitting}
|
||||
Icon={() => isSubmitting && <Loader />}
|
||||
|
||||
@ -71,27 +71,27 @@ export const LocalePicker = () => {
|
||||
},
|
||||
{
|
||||
label: t`French`,
|
||||
value: APP_LOCALES.fr,
|
||||
value: APP_LOCALES['fr-FR'],
|
||||
},
|
||||
{
|
||||
label: t`Spanish`,
|
||||
value: APP_LOCALES.es,
|
||||
value: APP_LOCALES['es-ES'],
|
||||
},
|
||||
{
|
||||
label: t`German`,
|
||||
value: APP_LOCALES.de,
|
||||
value: APP_LOCALES['de-DE'],
|
||||
},
|
||||
{
|
||||
label: t`Italian`,
|
||||
value: APP_LOCALES.it,
|
||||
value: APP_LOCALES['it-IT'],
|
||||
},
|
||||
{
|
||||
label: t`Korean`,
|
||||
value: APP_LOCALES.ko,
|
||||
value: APP_LOCALES['ko-KR'],
|
||||
},
|
||||
{
|
||||
label: t`Japanese`,
|
||||
value: APP_LOCALES.ja,
|
||||
value: APP_LOCALES['ja-JP'],
|
||||
},
|
||||
{
|
||||
label: t`Portuguese — Portugal`,
|
||||
@ -103,17 +103,17 @@ export const LocalePicker = () => {
|
||||
},
|
||||
{
|
||||
label: t`Chinese — Simplified`,
|
||||
value: APP_LOCALES['zh-Hans'],
|
||||
value: APP_LOCALES['zh-CN'],
|
||||
},
|
||||
{
|
||||
label: t`Chinese — Traditional`,
|
||||
value: APP_LOCALES['zh-Hant'],
|
||||
value: APP_LOCALES['zh-TW'],
|
||||
},
|
||||
];
|
||||
if (isDebugMode) {
|
||||
localeOptions.push({
|
||||
label: t`Pseudo-English`,
|
||||
value: 'pseudo-en',
|
||||
value: APP_LOCALES['pseudo-en'],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user