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:
@ -1,5 +1,4 @@
|
|||||||
import { defineConfig } from '@lingui/cli';
|
import { defineConfig } from '@lingui/cli';
|
||||||
import { formatter } from '@lingui/format-po';
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
sourceLocale: 'en',
|
sourceLocale: 'en',
|
||||||
@ -7,9 +6,6 @@ export default defineConfig({
|
|||||||
extractorParserOptions: {
|
extractorParserOptions: {
|
||||||
tsExperimentalDecorators: true,
|
tsExperimentalDecorators: true,
|
||||||
},
|
},
|
||||||
format: formatter({
|
|
||||||
explicitIdAsDefault: true,
|
|
||||||
}),
|
|
||||||
catalogs: [
|
catalogs: [
|
||||||
{
|
{
|
||||||
path: '<rootDir>/src/engine/core-modules/i18n/locales/{locale}',
|
path: '<rootDir>/src/engine/core-modules/i18n/locales/{locale}',
|
||||||
|
|||||||
@ -1,33 +1,11 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"POT-Creation-Date: 2025-01-25 21:24+0100\n"
|
"POT-Creation-Date: 2025-01-28 21:09+0100\n"
|
||||||
"MIME-Version: 1.0\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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: @lingui/cli\n"
|
"X-Generator: @lingui/cli\n"
|
||||||
"Language: en\n"
|
"Language: en\n"
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"PO-Revision-Date: \n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Plural-Forms: \n"
|
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
|
||||||
#: src/engine/metadata-modules/object-metadata/object-metadata.service.ts:557
|
|
||||||
#: src/engine/metadata-modules/object-metadata/object-metadata.service.ts:561
|
|
||||||
msgid "Company"
|
|
||||||
msgstr "Company"
|
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
|
||||||
#: src/modules/company/standard-objects/company.workspace-entity.ts:57
|
|
||||||
#~ msgid "Companies"
|
|
||||||
#~ msgstr "Companies"
|
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
|
||||||
#: src/modules/company/standard-objects/company.workspace-entity.ts:58
|
|
||||||
#~ msgid "A company"
|
|
||||||
#~ msgstr "A company"
|
|
||||||
|
|
||||||
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
|
#: src/modules/view/standard-objects/view-field.workspace-entity.ts:32
|
||||||
msgid "(System) View Fields"
|
msgid "(System) View Fields"
|
||||||
@ -61,10 +39,6 @@ msgstr "A company"
|
|||||||
msgid "A connected account"
|
msgid "A connected account"
|
||||||
msgstr "A connected account"
|
msgstr "A connected account"
|
||||||
|
|
||||||
#: src/modules/favorite/standard-objects/favorite.workspace-entity.ts:37
|
|
||||||
#~ msgid "A favorite"
|
|
||||||
#~ msgstr "A favorite"
|
|
||||||
|
|
||||||
#: src/modules/favorite/standard-objects/favorite.workspace-entity.ts:37
|
#: src/modules/favorite/standard-objects/favorite.workspace-entity.ts:37
|
||||||
msgid "A favorite that can be accessed from the left menu"
|
msgid "A favorite that can be accessed from the left menu"
|
||||||
msgstr "A favorite that can be accessed from the left menu"
|
msgstr "A favorite that can be accessed from the left menu"
|
||||||
@ -149,10 +123,6 @@ msgstr "An event related to user behavior"
|
|||||||
msgid "An opportunity"
|
msgid "An opportunity"
|
||||||
msgstr "An opportunity"
|
msgstr "An opportunity"
|
||||||
|
|
||||||
#: src/modules/task/standard-objects/task-target.workspace-entity.ts:27
|
|
||||||
#~ msgid "An task target"
|
|
||||||
#~ msgstr "An task target"
|
|
||||||
|
|
||||||
#: src/modules/api-key/standard-objects/api-key.workspace-entity.ts:17
|
#: src/modules/api-key/standard-objects/api-key.workspace-entity.ts:17
|
||||||
msgid "API Key"
|
msgid "API Key"
|
||||||
msgstr "API Key"
|
msgstr "API Key"
|
||||||
@ -308,6 +278,10 @@ msgstr "Message Threads"
|
|||||||
msgid "Messages"
|
msgid "Messages"
|
||||||
msgstr "Messages"
|
msgstr "Messages"
|
||||||
|
|
||||||
|
#: src/modules/company/standard-objects/company.workspace-entity.ts:67
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Name"
|
||||||
|
|
||||||
#: src/modules/note/standard-objects/note.workspace-entity.ts:46
|
#: src/modules/note/standard-objects/note.workspace-entity.ts:46
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr "Note"
|
msgstr "Note"
|
||||||
@ -356,6 +330,10 @@ msgstr "Task Targets"
|
|||||||
msgid "Tasks"
|
msgid "Tasks"
|
||||||
msgstr "Tasks"
|
msgstr "Tasks"
|
||||||
|
|
||||||
|
#: src/modules/company/standard-objects/company.workspace-entity.ts:68
|
||||||
|
msgid "The company name"
|
||||||
|
msgstr "The company name"
|
||||||
|
|
||||||
#: src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts:34
|
#: src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts:34
|
||||||
msgid "Timeline Activities"
|
msgid "Timeline Activities"
|
||||||
msgstr "Timeline Activities"
|
msgstr "Timeline Activities"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"POT-Creation-Date: 2025-01-28 09:39+0100\n"
|
"POT-Creation-Date: 2025-01-28 21:09+0100\n"
|
||||||
"MIME-Version: 1.0\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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
@ -208,12 +208,6 @@ msgstr "Entreprises"
|
|||||||
msgid "Company"
|
msgid "Company"
|
||||||
msgstr "Entreprise"
|
msgstr "Entreprise"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
|
||||||
#: src/engine/metadata-modules/object-metadata/object-metadata.service.ts:557
|
|
||||||
#: src/engine/metadata-modules/object-metadata/object-metadata.service.ts:561
|
|
||||||
msgid "Company"
|
|
||||||
msgstr "Entreprise"
|
|
||||||
|
|
||||||
#: src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts:33
|
#: src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts:33
|
||||||
msgid "Connected Account"
|
msgid "Connected Account"
|
||||||
msgstr "Compte connecté"
|
msgstr "Compte connecté"
|
||||||
@ -284,6 +278,10 @@ msgstr "Fils de messages"
|
|||||||
msgid "Messages"
|
msgid "Messages"
|
||||||
msgstr "Messages"
|
msgstr "Messages"
|
||||||
|
|
||||||
|
#: src/modules/company/standard-objects/company.workspace-entity.ts:67
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Nom"
|
||||||
|
|
||||||
#: src/modules/note/standard-objects/note.workspace-entity.ts:46
|
#: src/modules/note/standard-objects/note.workspace-entity.ts:46
|
||||||
msgid "Note"
|
msgid "Note"
|
||||||
msgstr "Note"
|
msgstr "Note"
|
||||||
@ -332,6 +330,10 @@ msgstr "Objectifs de la tâche"
|
|||||||
msgid "Tasks"
|
msgid "Tasks"
|
||||||
msgstr "Tâches"
|
msgstr "Tâches"
|
||||||
|
|
||||||
|
#: src/modules/company/standard-objects/company.workspace-entity.ts:68
|
||||||
|
msgid "The company name"
|
||||||
|
msgstr "Le nom de l'entreprise"
|
||||||
|
|
||||||
#: src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts:34
|
#: src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts:34
|
||||||
msgid "Timeline Activities"
|
msgid "Timeline Activities"
|
||||||
msgstr "Calendrier des activités"
|
msgstr "Calendrier des activités"
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
/*eslint-disable*/module.exports={messages:JSON.parse("{\"Company\":[\"Company\"],\"Companies\":[\"Companies\"],\"A company\":[\"A company\"],\"(System) View Fields\":[\"(System) View Fields\"],\"(System) View Filter Groups\":[\"(System) View Filter Groups\"],\"(System) View Filters\":[\"(System) View Filters\"],\"(System) View Groups\":[\"(System) View Groups\"],\"(System) View Sorts\":[\"(System) View Sorts\"],\"(System) Views\":[\"(System) Views\"],\"A connected account\":[\"A connected account\"],\"A favorite\":[\"A favorite\"],\"A favorite that can be accessed from the left menu\":[\"A favorite that can be accessed from the left menu\"],\"A Folder of favorites\":[\"A Folder of favorites\"],\"A group of related messages (e.g. email thread, chat thread)\":[\"A group of related messages (e.g. email thread, chat thread)\"],\"A message sent or received through a messaging channel (email, chat, etc.)\":[\"A message sent or received through a messaging channel (email, chat, etc.)\"],\"A note\":[\"A note\"],\"A note target\":[\"A note target\"],\"A person\":[\"A person\"],\"A task\":[\"A task\"],\"A task target\":[\"A task target\"],\"A webhook\":[\"A webhook\"],\"A workflow\":[\"A workflow\"],\"A workflow event listener\":[\"A workflow event listener\"],\"A workflow run\":[\"A workflow run\"],\"A workflow version\":[\"A workflow version\"],\"A workspace member\":[\"A workspace member\"],\"Aggregated / filtered event to be displayed on the timeline\":[\"Aggregated / filtered event to be displayed on the timeline\"],\"An API key\":[\"An API key\"],\"An attachment\":[\"An attachment\"],\"An audit log of actions performed in the system\":[\"An audit log of actions performed in the system\"],\"An event related to user behavior\":[\"An event related to user behavior\"],\"An opportunity\":[\"An opportunity\"],\"An task target\":[\"An task target\"],\"API Key\":[\"API Key\"],\"API Keys\":[\"API Keys\"],\"Attachment\":[\"Attachment\"],\"Attachments\":[\"Attachments\"],\"Audit Log\":[\"Audit Log\"],\"Audit Logs\":[\"Audit Logs\"],\"Behavioral Event\":[\"Behavioral Event\"],\"Behavioral Events\":[\"Behavioral Events\"],\"Blocklist\":[\"Blocklist\"],\"Blocklists\":[\"Blocklists\"],\"Calendar Channel\":[\"Calendar Channel\"],\"Calendar Channel Event Association\":[\"Calendar Channel Event Association\"],\"Calendar Channel Event Associations\":[\"Calendar Channel Event Associations\"],\"Calendar Channels\":[\"Calendar Channels\"],\"Calendar event\":[\"Calendar event\"],\"Calendar event participant\":[\"Calendar event participant\"],\"Calendar event participants\":[\"Calendar event participants\"],\"Calendar events\":[\"Calendar events\"],\"Connected Account\":[\"Connected Account\"],\"Connected Accounts\":[\"Connected Accounts\"],\"Favorite\":[\"Favorite\"],\"Favorite Folder\":[\"Favorite Folder\"],\"Favorite Folders\":[\"Favorite Folders\"],\"Favorites\":[\"Favorites\"],\"Message\":[\"Message\"],\"Message Channel\":[\"Message Channel\"],\"Message Channel Message Association\":[\"Message Channel Message Association\"],\"Message Channel Message Associations\":[\"Message Channel Message Associations\"],\"Message Channels\":[\"Message Channels\"],\"Message Participant\":[\"Message Participant\"],\"Message Participants\":[\"Message Participants\"],\"Message Synced with a Message Channel\":[\"Message Synced with a Message Channel\"],\"Message Thread\":[\"Message Thread\"],\"Message Threads\":[\"Message Threads\"],\"Messages\":[\"Messages\"],\"Note\":[\"Note\"],\"Note Target\":[\"Note Target\"],\"Note Targets\":[\"Note Targets\"],\"Notes\":[\"Notes\"],\"Opportunities\":[\"Opportunities\"],\"Opportunity\":[\"Opportunity\"],\"People\":[\"People\"],\"Person\":[\"Person\"],\"Task\":[\"Task\"],\"Task Target\":[\"Task Target\"],\"Task Targets\":[\"Task Targets\"],\"Tasks\":[\"Tasks\"],\"Timeline Activities\":[\"Timeline Activities\"],\"Timeline Activity\":[\"Timeline Activity\"],\"View\":[\"View\"],\"View Field\":[\"View Field\"],\"View Fields\":[\"View Fields\"],\"View Filter\":[\"View Filter\"],\"View Filter Group\":[\"View Filter Group\"],\"View Filter Groups\":[\"View Filter Groups\"],\"View Filters\":[\"View Filters\"],\"View Group\":[\"View Group\"],\"View Groups\":[\"View Groups\"],\"View Sort\":[\"View Sort\"],\"View Sorts\":[\"View Sorts\"],\"Views\":[\"Views\"],\"Webhook\":[\"Webhook\"],\"Webhooks\":[\"Webhooks\"],\"Workflow\":[\"Workflow\"],\"Workflow Run\":[\"Workflow Run\"],\"Workflow Runs\":[\"Workflow Runs\"],\"Workflow Version\":[\"Workflow Version\"],\"Workflow Versions\":[\"Workflow Versions\"],\"WorkflowEventListener\":[\"WorkflowEventListener\"],\"WorkflowEventListeners\":[\"WorkflowEventListeners\"],\"Workflows\":[\"Workflows\"],\"Workspace Member\":[\"Workspace Member\"],\"Workspace Members\":[\"Workspace Members\"]}")};
|
/*eslint-disable*/module.exports={messages:JSON.parse("{\"Qyrd7v\":[\"(System) View Fields\"],\"9Y3fTB\":[\"(System) View Filter Groups\"],\"TB2jLV\":[\"(System) View Filters\"],\"Y7M7Ro\":[\"(System) View Groups\"],\"9vliLw\":[\"(System) View Sorts\"],\"5B59WE\":[\"(System) Views\"],\"kZR6+h\":[\"A company\"],\"+aeifv\":[\"A connected account\"],\"HCoswz\":[\"A favorite that can be accessed from the left menu\"],\"6w8bHl\":[\"A Folder of favorites\"],\"sSGYmf\":[\"A group of related messages (e.g. email thread, chat thread)\"],\"vZj1Xc\":[\"A message sent or received through a messaging channel (email, chat, etc.)\"],\"bufuBA\":[\"A note\"],\"6kUkZW\":[\"A note target\"],\"Io42ej\":[\"A person\"],\"mkFXEH\":[\"A task\"],\"hk2NzW\":[\"A task target\"],\"HTSJFW\":[\"A webhook\"],\"ZIN9Ga\":[\"A workflow\"],\"juBVjt\":[\"A workflow event listener\"],\"1+xDbI\":[\"A workflow run\"],\"N0g7rp\":[\"A workflow version\"],\"HpZ/I5\":[\"A workspace member\"],\"W58PBh\":[\"Aggregated / filtered event to be displayed on the timeline\"],\"qeHcQj\":[\"An API key\"],\"MjyFvC\":[\"An attachment\"],\"+bL++X\":[\"An audit log of actions performed in the system\"],\"muVHgL\":[\"An event related to user behavior\"],\"bZq8rL\":[\"An opportunity\"],\"yRnk5W\":[\"API Key\"],\"FfSJ1Y\":[\"API Keys\"],\"UY1vmE\":[\"Attachment\"],\"w/Sphq\":[\"Attachments\"],\"ilRCh1\":[\"Audit Log\"],\"EPEFrH\":[\"Audit Logs\"],\"20B9kW\":[\"Behavioral Event\"],\"Jeh/Q/\":[\"Behavioral Events\"],\"K1172m\":[\"Blocklist\"],\"L5JhJe\":[\"Blocklists\"],\"Nh6GTX\":[\"Calendar Channel\"],\"jfNQ0m\":[\"Calendar Channel Event Association\"],\"kYNT3F\":[\"Calendar Channel Event Associations\"],\"Znix/S\":[\"Calendar Channels\"],\"bRk+FR\":[\"Calendar event\"],\"N2kMfO\":[\"Calendar event participant\"],\"AWDqkQ\":[\"Calendar event participants\"],\"X9A2xC\":[\"Calendar events\"],\"s2QZS6\":[\"Companies\"],\"7i8j3G\":[\"Company\"],\"PQ1Dw2\":[\"Connected Account\"],\"AMDUqA\":[\"Connected Accounts\"],\"6Ki4Pv\":[\"Favorite\"],\"TDlZ/o\":[\"Favorite Folder\"],\"SStz54\":[\"Favorite Folders\"],\"X9kySA\":[\"Favorites\"],\"xDAtGP\":[\"Message\"],\"g+QGD6\":[\"Message Channel\"],\"disipM\":[\"Message Channel Message Association\"],\"ijQY3P\":[\"Message Channel Message Associations\"],\"k7LXPQ\":[\"Message Channels\"],\"IUmVwu\":[\"Message Participant\"],\"FhIFx7\":[\"Message Participants\"],\"IC5A8V\":[\"Message Synced with a Message Channel\"],\"de2nM/\":[\"Message Thread\"],\"RD0ecC\":[\"Message Threads\"],\"t7TeQU\":[\"Messages\"],\"6YtxFj\":[\"Name\"],\"KiJn9B\":[\"Note\"],\"spaO7l\":[\"Note Target\"],\"tD4BxK\":[\"Note Targets\"],\"1DBGsz\":[\"Notes\"],\"4MyDFl\":[\"Opportunities\"],\"SV/iis\":[\"Opportunity\"],\"1wdjme\":[\"People\"],\"OZdaTZ\":[\"Person\"],\"Q3P/4s\":[\"Task\"],\"WSiiWf\":[\"Task Target\"],\"836FiO\":[\"Task Targets\"],\"GtycJ/\":[\"Tasks\"],\"N31Pso\":[\"The company name\"],\"az1boY\":[\"Timeline Activities\"],\"K/kU4E\":[\"Timeline Activity\"],\"jpctdh\":[\"View\"],\"cZPDyy\":[\"View Field\"],\"GUFYyq\":[\"View Fields\"],\"JRtI7Y\":[\"View Filter\"],\"l9/6pD\":[\"View Filter Group\"],\"/aP3iG\":[\"View Filter Groups\"],\"vj5JsR\":[\"View Filters\"],\"ziEP12\":[\"View Group\"],\"V4nZs/\":[\"View Groups\"],\"EUjpwJ\":[\"View Sort\"],\"UsdY3K\":[\"View Sorts\"],\"1I6UoR\":[\"Views\"],\"TRDppN\":[\"Webhook\"],\"v1kQyJ\":[\"Webhooks\"],\"bLt/0J\":[\"Workflow\"],\"5vIcqC\":[\"Workflow Run\"],\"u6DF/V\":[\"Workflow Runs\"],\"+wYPET\":[\"Workflow Version\"],\"OCyhkn\":[\"Workflow Versions\"],\"ENOy6I\":[\"WorkflowEventListener\"],\"3JA9se\":[\"WorkflowEventListeners\"],\"woYYQq\":[\"Workflows\"],\"qc38qR\":[\"Workspace Member\"],\"YCAEr+\":[\"Workspace Members\"]}")};
|
||||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,7 @@
|
|||||||
|
export type I18nContext = {
|
||||||
|
req: {
|
||||||
|
headers: {
|
||||||
|
'x-locale': string | undefined;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import crypto from 'crypto';
|
||||||
|
|
||||||
|
const UNIT_SEPARATOR = '\u001F';
|
||||||
|
|
||||||
|
export function generateMessageId(msg: string, context = '') {
|
||||||
|
return crypto
|
||||||
|
.createHash('sha256')
|
||||||
|
.update(msg + UNIT_SEPARATOR + (context || ''))
|
||||||
|
.digest('base64')
|
||||||
|
.slice(0, 6);
|
||||||
|
}
|
||||||
@ -16,6 +16,7 @@ import { FieldMetadataType } from 'twenty-shared';
|
|||||||
|
|
||||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
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 { 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 { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
|
import { IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
|
||||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||||
@ -43,6 +44,30 @@ export class FieldMetadataResolver {
|
|||||||
private readonly featureFlagService: FeatureFlagService,
|
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)
|
@Mutation(() => FieldMetadataDTO)
|
||||||
async createOneField(
|
async createOneField(
|
||||||
@Args('input') input: CreateOneFieldMetadataInput,
|
@Args('input') input: CreateOneFieldMetadataInput,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { i18n } from '@lingui/core';
|
||||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||||
import isEmpty from 'lodash.isempty';
|
import isEmpty from 'lodash.isempty';
|
||||||
import { FieldMetadataType } from 'twenty-shared';
|
import { FieldMetadataType } from 'twenty-shared';
|
||||||
@ -8,6 +9,7 @@ import { DataSource, FindOneOptions, Repository } from 'typeorm';
|
|||||||
import { v4 as uuidV4, v4 } from 'uuid';
|
import { v4 as uuidV4, v4 } from 'uuid';
|
||||||
|
|
||||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
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 { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
Resolver,
|
Resolver,
|
||||||
} from '@nestjs/graphql';
|
} from '@nestjs/graphql';
|
||||||
|
|
||||||
|
import { I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||||
@ -32,7 +33,7 @@ export class ObjectMetadataResolver {
|
|||||||
@ResolveField(() => String, { nullable: true })
|
@ResolveField(() => String, { nullable: true })
|
||||||
async labelPlural(
|
async labelPlural(
|
||||||
@Parent() objectMetadata: ObjectMetadataDTO,
|
@Parent() objectMetadata: ObjectMetadataDTO,
|
||||||
@Context() context,
|
@Context() context: I18nContext,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return this.objectMetadataService.resolveTranslatableString(
|
return this.objectMetadataService.resolveTranslatableString(
|
||||||
objectMetadata,
|
objectMetadata,
|
||||||
@ -44,7 +45,7 @@ export class ObjectMetadataResolver {
|
|||||||
@ResolveField(() => String, { nullable: true })
|
@ResolveField(() => String, { nullable: true })
|
||||||
async labelSingular(
|
async labelSingular(
|
||||||
@Parent() objectMetadata: ObjectMetadataDTO,
|
@Parent() objectMetadata: ObjectMetadataDTO,
|
||||||
@Context() context,
|
@Context() context: I18nContext,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return this.objectMetadataService.resolveTranslatableString(
|
return this.objectMetadataService.resolveTranslatableString(
|
||||||
objectMetadata,
|
objectMetadata,
|
||||||
@ -56,7 +57,7 @@ export class ObjectMetadataResolver {
|
|||||||
@ResolveField(() => String, { nullable: true })
|
@ResolveField(() => String, { nullable: true })
|
||||||
async description(
|
async description(
|
||||||
@Parent() objectMetadata: ObjectMetadataDTO,
|
@Parent() objectMetadata: ObjectMetadataDTO,
|
||||||
@Context() context,
|
@Context() context: I18nContext,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return this.objectMetadataService.resolveTranslatableString(
|
return this.objectMetadataService.resolveTranslatableString(
|
||||||
objectMetadata,
|
objectMetadata,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { FindManyOptions, FindOneOptions, In, Not, Repository } from 'typeorm';
|
|||||||
|
|
||||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||||
|
|
||||||
|
import { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
import { IndexMetadataService } from 'src/engine/metadata-modules/index-metadata/index-metadata.service';
|
import { IndexMetadataService } from 'src/engine/metadata-modules/index-metadata/index-metadata.service';
|
||||||
@ -539,14 +540,18 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
async resolveTranslatableString(
|
async resolveTranslatableString(
|
||||||
objectMetadata: ObjectMetadataDTO,
|
objectMetadata: ObjectMetadataDTO,
|
||||||
labelKey: 'labelPlural' | 'labelSingular' | 'description',
|
labelKey: 'labelPlural' | 'labelSingular' | 'description',
|
||||||
locale: string,
|
locale: string | undefined,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
if (objectMetadata.isCustom) {
|
if (objectMetadata.isCustom) {
|
||||||
return objectMetadata[labelKey];
|
return objectMetadata[labelKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!locale) {
|
||||||
|
return objectMetadata[labelKey];
|
||||||
|
}
|
||||||
|
|
||||||
i18n.activate(locale);
|
i18n.activate(locale);
|
||||||
|
|
||||||
return i18n._(objectMetadata[labelKey]);
|
return i18n._(generateMessageId(objectMetadata[labelKey]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { MessageDescriptor } from '@lingui/core';
|
||||||
import { FieldMetadataType } from 'twenty-shared';
|
import { FieldMetadataType } from 'twenty-shared';
|
||||||
|
|
||||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||||
@ -14,8 +15,14 @@ export interface WorkspaceFieldOptions<
|
|||||||
> {
|
> {
|
||||||
standardId: string;
|
standardId: string;
|
||||||
type: T;
|
type: T;
|
||||||
label: string | ((objectMetadata: ObjectMetadataEntity) => string);
|
label:
|
||||||
description?: string | ((objectMetadata: ObjectMetadataEntity) => string);
|
| string
|
||||||
|
| MessageDescriptor
|
||||||
|
| ((objectMetadata: ObjectMetadataEntity) => string);
|
||||||
|
description?:
|
||||||
|
| string
|
||||||
|
| MessageDescriptor
|
||||||
|
| ((objectMetadata: ObjectMetadataEntity) => string);
|
||||||
icon?: string;
|
icon?: string;
|
||||||
defaultValue?: FieldMetadataDefaultValue<T>;
|
defaultValue?: FieldMetadataDefaultValue<T>;
|
||||||
options?: FieldMetadataOptions<T>;
|
options?: FieldMetadataOptions<T>;
|
||||||
@ -72,9 +79,15 @@ export function WorkspaceField<T extends FieldMetadataType>(
|
|||||||
target: object.constructor,
|
target: object.constructor,
|
||||||
standardId: options.standardId,
|
standardId: options.standardId,
|
||||||
name: propertyKey.toString(),
|
name: propertyKey.toString(),
|
||||||
label: options.label,
|
label:
|
||||||
|
typeof options.label === 'object'
|
||||||
|
? (options.label.message ?? '')
|
||||||
|
: options.label,
|
||||||
type: options.type,
|
type: options.type,
|
||||||
description: options.description,
|
description:
|
||||||
|
typeof options.description === 'object'
|
||||||
|
? (options.description.message ?? '')
|
||||||
|
: options.description,
|
||||||
icon: options.icon,
|
icon: options.icon,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
options: options.options,
|
options: options.options,
|
||||||
|
|||||||
@ -64,8 +64,8 @@ export class CompanyWorkspaceEntity extends BaseWorkspaceEntity {
|
|||||||
@WorkspaceField({
|
@WorkspaceField({
|
||||||
standardId: COMPANY_STANDARD_FIELD_IDS.name,
|
standardId: COMPANY_STANDARD_FIELD_IDS.name,
|
||||||
type: FieldMetadataType.TEXT,
|
type: FieldMetadataType.TEXT,
|
||||||
label: 'Name',
|
label: msg`Name`,
|
||||||
description: 'The company name',
|
description: msg`The company name`,
|
||||||
icon: 'IconBuildingSkyscraper',
|
icon: 'IconBuildingSkyscraper',
|
||||||
})
|
})
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user