Add POC for Field translation (#9898)

Similar to ObjectMetadata translation

Also fixed an issue linked to the migration from `t` to `message`
helper: we're forced to rebuild the ID ourselves
This commit is contained in:
Félix Malfait
2025-01-28 21:25:09 +01:00
committed by GitHub
parent 8754b7107d
commit b1219ff107
13 changed files with 120 additions and 55 deletions

View File

@ -16,6 +16,7 @@ import { FieldMetadataType } from 'twenty-shared';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@ -43,6 +44,30 @@ export class FieldMetadataResolver {
private readonly featureFlagService: FeatureFlagService,
) {}
@ResolveField(() => String, { nullable: true })
async label(
@Parent() fieldMetadata: FieldMetadataDTO,
@Context() context: I18nContext,
): Promise<string> {
return this.fieldMetadataService.resolveTranslatableString(
fieldMetadata,
'label',
context.req.headers['x-locale'],
);
}
@ResolveField(() => String, { nullable: true })
async description(
@Parent() fieldMetadata: FieldMetadataDTO,
@Context() context: I18nContext,
): Promise<string> {
return this.fieldMetadataService.resolveTranslatableString(
fieldMetadata,
'description',
context.req.headers['x-locale'],
);
}
@Mutation(() => FieldMetadataDTO)
async createOneField(
@Args('input') input: CreateOneFieldMetadataInput,

View File

@ -1,6 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { i18n } from '@lingui/core';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import isEmpty from 'lodash.isempty';
import { FieldMetadataType } from 'twenty-shared';
@ -8,6 +9,7 @@ import { DataSource, FindOneOptions, Repository } from 'typeorm';
import { v4 as uuidV4, v4 } from 'uuid';
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
import { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
@ -773,4 +775,29 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
return fieldMetadataInput;
}
async resolveTranslatableString(
fieldMetadata: FieldMetadataDTO,
labelKey: 'label' | 'description',
locale: string | undefined,
): Promise<string> {
if (fieldMetadata.isCustom) {
return fieldMetadata[labelKey] ?? '';
}
if (!locale) {
return fieldMetadata[labelKey] ?? '';
}
i18n.activate(locale);
const messageId = generateMessageId(fieldMetadata[labelKey] ?? '');
const translatedMessage = i18n._(messageId);
if (translatedMessage === messageId) {
return fieldMetadata[labelKey] ?? '';
}
return translatedMessage;
}
}