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:
Félix Malfait
2025-02-09 22:10:41 +01:00
committed by GitHub
parent fd3f01ab80
commit bb24c97f80
163 changed files with 84053 additions and 2554 deletions
@@ -197,6 +197,7 @@ export class AuthResolver {
const { userData } = this.authService.formatUserDataPayload(
{
email: signUpInput.email,
locale: signUpInput.locale,
},
existingUser,
);
@@ -18,8 +18,8 @@ import { GoogleProviderEnabledGuard } from 'src/engine/core-modules/auth/guards/
import { AuthService } from 'src/engine/core-modules/auth/services/auth.service';
import { GoogleRequest } from 'src/engine/core-modules/auth/strategies/google.auth.strategy';
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service';
import { User } from 'src/engine/core-modules/user/user.entity';
@Controller('auth/google')
@UseFilters(AuthRestApiExceptionFilter)
@@ -51,6 +51,7 @@ export class GoogleAuthController {
workspaceInviteHash,
workspaceId,
billingCheckoutSessionState,
locale,
} = req.user;
const currentWorkspace = await this.authService.findWorkspaceForSignInUp({
@@ -79,6 +80,7 @@ export class GoogleAuthController {
lastName,
email,
picture,
locale,
},
existingUser,
);
@@ -17,8 +17,8 @@ import { MicrosoftProviderEnabledGuard } from 'src/engine/core-modules/auth/guar
import { AuthService } from 'src/engine/core-modules/auth/services/auth.service';
import { MicrosoftRequest } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy';
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { GuardRedirectService } from 'src/engine/core-modules/guard-redirect/services/guard-redirect.service';
import { User } from 'src/engine/core-modules/user/user.entity';
@Controller('auth/microsoft')
@UseFilters(AuthRestApiExceptionFilter)
@@ -52,6 +52,7 @@ export class MicrosoftAuthController {
workspaceInviteHash,
workspaceId,
billingCheckoutSessionState,
locale,
} = req.user;
const currentWorkspace = await this.authService.findWorkspaceForSignInUp({
@@ -80,6 +81,7 @@ export class MicrosoftAuthController {
lastName,
email,
picture,
locale,
},
existingUser,
);
@@ -1,6 +1,7 @@
import { ArgsType, Field } from '@nestjs/graphql';
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { APP_LOCALES } from 'twenty-shared';
@ArgsType()
export class SignUpInput {
@@ -33,4 +34,9 @@ export class SignUpInput {
@IsString()
@IsOptional()
captchaToken?: string;
@Field(() => String, { nullable: true })
@IsString()
@IsOptional()
locale?: keyof typeof APP_LOCALES;
}
@@ -3,6 +3,7 @@ import { PassportStrategy } from '@nestjs/passport';
import { Request } from 'express';
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
import { APP_LOCALES } from 'twenty-shared';
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
@@ -15,6 +16,7 @@ export type GoogleRequest = Omit<
lastName?: string | null;
email: string;
picture: string | null;
locale?: keyof typeof APP_LOCALES | null;
workspaceInviteHash?: string;
workspacePersonalInviteToken?: string;
workspaceId?: string;
@@ -70,6 +72,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
workspacePersonalInviteToken: state.workspacePersonalInviteToken,
workspaceId: state.workspaceId,
billingCheckoutSessionState: state.billingCheckoutSessionState,
locale: state.locale,
};
done(null, user);
@@ -3,6 +3,7 @@ import { PassportStrategy } from '@nestjs/passport';
import { Request } from 'express';
import { VerifyCallback } from 'passport-google-oauth20';
import { Strategy } from 'passport-microsoft';
import { APP_LOCALES } from 'twenty-shared';
import {
AuthException,
@@ -19,6 +20,7 @@ export type MicrosoftRequest = Omit<
lastName?: string | null;
email: string;
picture: string | null;
locale?: keyof typeof APP_LOCALES | null;
workspaceInviteHash?: string;
workspacePersonalInviteToken?: string;
workspaceId?: string;
@@ -44,6 +46,7 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') {
state: JSON.stringify({
workspaceInviteHash: req.query.workspaceInviteHash,
workspaceId: req.params.workspaceId,
locale: req.query.locale,
billingCheckoutSessionState: req.query.billingCheckoutSessionState,
workspacePersonalInviteToken: req.query.workspacePersonalInviteToken,
}),
@@ -84,6 +87,7 @@ export class MicrosoftStrategy extends PassportStrategy(Strategy, 'microsoft') {
workspacePersonalInviteToken: state.workspacePersonalInviteToken,
workspaceId: state.workspaceId,
billingCheckoutSessionState: state.billingCheckoutSessionState,
locale: state.locale,
};
done(null, user);
@@ -1,6 +1,8 @@
import { APP_LOCALES } from 'twenty-shared';
import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity';
import { User } from 'src/engine/core-modules/user/user.entity';
import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type';
import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
export type SignInUpBaseParams = {
@@ -15,6 +17,7 @@ export type SignInUpNewUserPayload = {
lastName?: string | null;
picture?: string | null;
passwordHash?: string | null;
locale?: keyof typeof APP_LOCALES | null;
};
export type PartialUserWithPicture = {
@@ -0,0 +1,20 @@
import { Injectable, NestMiddleware } from '@nestjs/common';
import { i18n } from '@lingui/core';
import { NextFunction, Request, Response } from 'express';
import { APP_LOCALES } from 'twenty-shared';
@Injectable()
export class I18nMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const locale = req.headers['x-locale'] as keyof typeof APP_LOCALES;
if (locale && Object.values(APP_LOCALES).includes(locale)) {
i18n.activate(locale);
} else {
i18n.activate('en');
}
next();
}
}
@@ -1,5 +1,6 @@
import { Global, Module } from '@nestjs/common';
import { Global, MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { I18nMiddleware } from 'src/engine/core-modules/i18n/i18n.middleware';
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
@Global()
@@ -7,4 +8,8 @@ import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
providers: [I18nService],
exports: [I18nService],
})
export class I18nModule {}
export class I18nModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(I18nMiddleware).forRoutes('*');
}
}
@@ -1,35 +1,44 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { i18n } from '@lingui/core';
import { APP_LOCALES } from 'twenty-shared';
import { messages as deMessages } from 'src/engine/core-modules/i18n/locales/generated/de';
import { messages as deMessages } from 'src/engine/core-modules/i18n/locales/generated/de-DE';
import { messages as enMessages } from 'src/engine/core-modules/i18n/locales/generated/en';
import { messages as esMessages } from 'src/engine/core-modules/i18n/locales/generated/es';
import { messages as frMessages } from 'src/engine/core-modules/i18n/locales/generated/fr';
import { messages as itMessages } from 'src/engine/core-modules/i18n/locales/generated/it';
import { messages as jaMessages } from 'src/engine/core-modules/i18n/locales/generated/ja';
import { messages as koMessages } from 'src/engine/core-modules/i18n/locales/generated/ko';
import { messages as esMessages } from 'src/engine/core-modules/i18n/locales/generated/es-ES';
import { messages as frMessages } from 'src/engine/core-modules/i18n/locales/generated/fr-FR';
import { messages as itMessages } from 'src/engine/core-modules/i18n/locales/generated/it-IT';
import { messages as jaMessages } from 'src/engine/core-modules/i18n/locales/generated/ja-JP';
import { messages as koMessages } from 'src/engine/core-modules/i18n/locales/generated/ko-KR';
import { messages as pseudoEnMessages } from 'src/engine/core-modules/i18n/locales/generated/pseudo-en';
import { messages as ptBRMessages } from 'src/engine/core-modules/i18n/locales/generated/pt-BR';
import { messages as ptPTMessages } from 'src/engine/core-modules/i18n/locales/generated/pt-PT';
import { messages as zhHansMessages } from 'src/engine/core-modules/i18n/locales/generated/zh-Hans';
import { messages as zhHantMessages } from 'src/engine/core-modules/i18n/locales/generated/zh-Hant';
import { messages as zhHansMessages } from 'src/engine/core-modules/i18n/locales/generated/zh-CN';
import { messages as zhHantMessages } from 'src/engine/core-modules/i18n/locales/generated/zh-TW';
@Injectable()
export class I18nService implements OnModuleInit {
async loadTranslations() {
i18n.load('en', enMessages);
i18n.load('fr', frMessages);
i18n.load('pseudo-en', pseudoEnMessages);
i18n.load('ko', koMessages);
i18n.load('de', deMessages);
i18n.load('it', itMessages);
i18n.load('es', esMessages);
i18n.load('ja', jaMessages);
i18n.load('pt-PT', ptPTMessages);
i18n.load('pt-BR', ptBRMessages);
i18n.load('zh-Hans', zhHansMessages);
i18n.load('zh-Hant', zhHantMessages);
const messages: Record<keyof typeof APP_LOCALES, any> = {
en: enMessages,
'pseudo-en': pseudoEnMessages,
'fr-FR': frMessages,
'ko-KR': koMessages,
'de-DE': deMessages,
'it-IT': itMessages,
'es-ES': esMessages,
'ja-JP': jaMessages,
'pt-PT': ptPTMessages,
'pt-BR': ptBRMessages,
'zh-CN': zhHansMessages,
'zh-TW': zhHantMessages,
};
(Object.entries(messages) as [keyof typeof APP_LOCALES, any][]).forEach(
([locale, message]) => {
i18n.load(locale, message);
},
);
i18n.activate('en');
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: de\n"
"Project-Id-Version: \n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "Ihr Teammitglied, das für die Verwaltung des Unternehmenskontos verantwortlich ist"
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: es\n"
"Project-Id-Version: \n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: es\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "Miembro de su equipo responsable de gestionar la cuenta de la empresa"
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fr\n"
"Project-Id-Version: \n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "Le membre de votre équipe responsable de la gestion du compte entreprise"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: it\n"
"Project-Id-Version: \n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "Il membro del team responsabile della gestione dell'account aziendale"
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ja\n"
"Project-Id-Version: \n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Japanese\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr ""
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr ""
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ko\n"
"Project-Id-Version: \n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Korean\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "회사 계정을 관리하는 팀원"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pt-BR\n"
"Project-Id-Version: \n"
"Language: pt\n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Portuguese, Brazilian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "Seu membro da equipe responsável por gerenciar a conta da empresa"
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pt-PT\n"
"Project-Id-Version: \n"
"Language: pt\n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Portuguese\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: pt\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "O membro da sua equipa responsável pela gestão da conta da empresa"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: zh-Hans\n"
"Project-Id-Version: \n"
"Language: zh\n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Chinese Simplified\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "负责管理公司账户的团队成员"
@@ -1,17 +1,22 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2025-02-01 10:10+0100\n"
"POT-Creation-Date: 2025-01-29 18:14+0100\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: zh-Hant\n"
"Project-Id-Version: \n"
"Language: zh\n"
"Project-Id-Version: cf448e737e0d6d7b78742f963d761c61\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"PO-Revision-Date: 2025-02-09 12:39\n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
"Language-Team: Chinese Traditional\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: cf448e737e0d6d7b78742f963d761c61\n"
"X-Crowdin-Project-ID: 1\n"
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /packages/twenty-server/src/engine/core-modules/i18n/locales/en.po\n"
"X-Crowdin-File-ID: 31\n"
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
msgid "(System) View Fields"
@@ -2240,3 +2245,4 @@ msgstr "X"
#: src/modules/company/standard-objects/company.workspace-entity.ts:177
msgid "Your team member responsible for managing the company account"
msgstr "負責管理公司帳戶的團隊成員"
@@ -13,6 +13,7 @@ import {
AuthExceptionCode,
} from 'src/engine/core-modules/auth/auth.exception';
import { AvailableWorkspaceOutput } from 'src/engine/core-modules/auth/dto/available-workspaces.output';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { User } from 'src/engine/core-modules/user/user.entity';
import { userValidator } from 'src/engine/core-modules/user/user.validate';
@@ -24,7 +25,6 @@ import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { assert } from 'src/utils/assert';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> {
constructor(
@@ -70,14 +70,15 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> {
await workspaceDataSource?.query(
`INSERT INTO ${dataSourceMetadata.schema}."workspaceMember"
("nameFirstName", "nameLastName", "colorScheme", "userId", "userEmail", "avatarUrl")
VALUES ($1, $2, 'System', $3, $4, $5)`,
("nameFirstName", "nameLastName", "colorScheme", "userId", "userEmail", "avatarUrl", "locale")
VALUES ($1, $2, 'System', $3, $4, $5, $6)`,
[
user.firstName,
user.lastName,
user.id,
user.email,
user.defaultAvatarUrl ?? '',
user.locale ?? 'en',
],
);
const workspaceMember = await workspaceDataSource?.query(
@@ -81,6 +81,10 @@ export class User {
@DeleteDateColumn({ type: 'timestamptz' })
deletedAt: Date;
@Field(() => String, { nullable: false })
@Column({ nullable: false, default: 'en' })
locale: string;
@OneToMany(() => AppToken, (appToken) => appToken.user, {
cascade: true,
})
@@ -2,10 +2,10 @@ import { Field, InputType } from '@nestjs/graphql';
import {
IsBoolean,
IsNotIn,
IsOptional,
IsString,
Matches,
IsNotIn,
} from 'class-validator';
@InputType()
@@ -92,11 +92,48 @@ export class UpdateWorkspaceInput {
'au',
'nz',
'za',
'uk',
'eu',
'uk',
'ru',
'ua',
'pl',
'ro',
'bg',
'gr',
'cz',
'sk',
'hu',
'hr',
'si',
'rs',
'me',
'ba',
'mk',
'al',
'az',
'tr',
'cy',
'lv',
'lt',
'ee',
'fi',
'is',
'no',
'se',
'dk',
'asia',
'africa',
'america',
'europe',
'north-america',
'south-africa',
'north-africa',
'south-america',
'oceania',
'paris',
'london',
'new-york',
'san-francisco',
])
subdomain?: string;