Update user friendly errors for translations (#15000)
Force msg typing instead of string for user friendly errors
This commit is contained in:
@@ -24,6 +24,7 @@ import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { useSentryTracing } from 'src/engine/core-modules/exception-handler/hooks/use-sentry-tracing';
|
||||
import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook';
|
||||
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { type User } from 'src/engine/core-modules/user/user.entity';
|
||||
@@ -47,6 +48,7 @@ export class GraphQLConfigService
|
||||
private readonly moduleRef: ModuleRef,
|
||||
private readonly metricsService: MetricsService,
|
||||
private readonly dataloaderService: DataloaderService,
|
||||
private readonly i18nService: I18nService,
|
||||
) {}
|
||||
|
||||
createGqlOptions(): YogaDriverConfig {
|
||||
@@ -63,6 +65,7 @@ export class GraphQLConfigService
|
||||
useGraphQLErrorHandlerHook({
|
||||
metricsService: this.metricsService,
|
||||
exceptionHandlerService: this.exceptionHandlerService,
|
||||
i18nService: this.i18nService,
|
||||
twentyConfigService: this.twentyConfigService,
|
||||
}),
|
||||
];
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { QUERY_MAX_RECORDS } from 'twenty-shared/constants';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -47,7 +47,7 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
`Maximum number of records to upsert is ${QUERY_MAX_RECORDS}.`,
|
||||
GraphqlQueryRunnerExceptionCode.UPSERT_MAX_RECORDS_EXCEEDED,
|
||||
{
|
||||
userFriendlyMessage: t`Maximum number of records to upsert is ${QUERY_MAX_RECORDS}.`,
|
||||
userFriendlyMessage: msg`Maximum number of records to upsert is ${QUERY_MAX_RECORDS}.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -359,7 +359,7 @@ export class GraphqlQueryCreateManyResolverService extends GraphqlQueryBaseResol
|
||||
`Multiple records found with the same unique field values for ${conflictingFieldsValues}. Cannot determine which record to update.`,
|
||||
GraphqlQueryRunnerExceptionCode.UPSERT_MULTIPLE_MATCHING_RECORDS_CONFLICT,
|
||||
{
|
||||
userFriendlyMessage: t`Multiple records found with the same unique field values for ${conflictingFieldsValues}. Cannot determine which record to update.`,
|
||||
userFriendlyMessage: msg`Multiple records found with the same unique field values for ${conflictingFieldsValues}. Cannot determine which record to update.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graph
|
||||
import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { I18nModule } from 'src/engine/core-modules/i18n/i18n.module';
|
||||
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
import { MetricsModule } from 'src/engine/core-modules/metrics/metrics.module';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
@@ -21,13 +23,19 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
|
||||
GraphQLModule.forRootAsync<YogaDriverConfig>({
|
||||
driver: YogaDriver,
|
||||
useFactory: metadataModuleFactory,
|
||||
imports: [GraphQLConfigModule, DataloaderModule, MetricsModule],
|
||||
imports: [
|
||||
GraphQLConfigModule,
|
||||
DataloaderModule,
|
||||
MetricsModule,
|
||||
I18nModule,
|
||||
],
|
||||
inject: [
|
||||
TwentyConfigService,
|
||||
ExceptionHandlerService,
|
||||
DataloaderService,
|
||||
CacheStorageNamespace.EngineWorkspace,
|
||||
MetricsService,
|
||||
I18nService,
|
||||
],
|
||||
}),
|
||||
MetadataEngineModule,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphq
|
||||
import { type CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { type ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook';
|
||||
import { type I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
import { type MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { type TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { type DataloaderService } from 'src/engine/dataloaders/dataloader.service';
|
||||
@@ -20,6 +21,7 @@ export const metadataModuleFactory = async (
|
||||
dataloaderService: DataloaderService,
|
||||
cacheStorageService: CacheStorageService,
|
||||
metricsService: MetricsService,
|
||||
i18nService: I18nService,
|
||||
): Promise<YogaDriverConfig> => {
|
||||
const config: YogaDriverConfig = {
|
||||
autoSchemaFile: true,
|
||||
@@ -39,6 +41,7 @@ export const metadataModuleFactory = async (
|
||||
useGraphQLErrorHandlerHook({
|
||||
metricsService: metricsService,
|
||||
exceptionHandlerService,
|
||||
i18nService,
|
||||
twentyConfigService,
|
||||
}),
|
||||
useCachedMetadata({
|
||||
|
||||
+10
-3
@@ -1,3 +1,4 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type QueryFailedError } from 'typeorm';
|
||||
|
||||
@@ -42,7 +43,7 @@ export const handleDuplicateKeyError = (
|
||||
`A duplicate entry was detected`,
|
||||
TwentyORMExceptionCode.DUPLICATE_ENTRY_DETECTED,
|
||||
{
|
||||
userFriendlyMessage: `This record already exists. Please check your data and try again.`,
|
||||
userFriendlyMessage: msg`This record already exists. Please check your data and try again.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -50,20 +51,26 @@ export const handleDuplicateKeyError = (
|
||||
const columnNames = affectedColumns.join(', ');
|
||||
|
||||
if (affectedColumns?.length === 1) {
|
||||
const fieldName = columnNames.toLowerCase();
|
||||
|
||||
throw new UserInputError(
|
||||
`Duplicate ${columnNames} ${duplicatedValues ? `with value ${duplicatedValues}` : ''}. Please set a unique one.`,
|
||||
{
|
||||
userFriendlyMessage: `This ${columnNames.toLowerCase()} ${duplicatedValues ? `with value ${duplicatedValues}` : ''} is already taken. Please choose a different value.`,
|
||||
userFriendlyMessage: duplicatedValues
|
||||
? msg`This ${fieldName} with value ${duplicatedValues} is already taken. Please choose a different value.`
|
||||
: msg`This ${fieldName} is already taken. Please choose a different value.`,
|
||||
isExpected: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const fieldNames = columnNames.toLowerCase();
|
||||
|
||||
throw new TwentyORMException(
|
||||
`A duplicate entry was detected. The combination of ${columnNames} must be unique.`,
|
||||
TwentyORMExceptionCode.DUPLICATE_ENTRY_DETECTED,
|
||||
{
|
||||
userFriendlyMessage: `This combination of ${columnNames.toLowerCase()} already exists. Please use different values.`,
|
||||
userFriendlyMessage: msg`This combination of ${fieldNames} already exists. Please use different values.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user