More progress on translations (#9951)

This commit is contained in:
Félix Malfait
2025-01-31 15:49:37 +01:00
committed by GitHub
parent b801307d92
commit d6788348ba
57 changed files with 31344 additions and 3935 deletions

View File

@ -1,18 +1,9 @@
import { defineConfig } from '@lingui/cli';
import { APP_LOCALES } from 'twenty-shared';
export default defineConfig({
sourceLocale: 'en',
locales: [
'en',
'fr',
'pt',
'de',
'it',
'es',
'zh-Hans',
'zh-Hant',
'pseudo-en',
],
locales: Object.values(APP_LOCALES),
pseudoLocale: 'pseudo-en',
fallbackLocales: {
'pseudo-en': 'en',

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\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"
#: src/modules/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel.ts:129
msgid "{aggregateLabel} of {fieldLabel}"
@ -269,11 +275,11 @@ msgstr "Change {to}"
msgid "Change Password"
msgstr "Change Password"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:86
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:103
msgid "Chinese — Simplified"
msgstr "Chinese — Simplified"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:90
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:107
msgid "Chinese — Traditional"
msgstr "Chinese — Traditional"
@ -617,7 +623,7 @@ msgstr "Empty"
msgid "Endpoint URL"
msgstr "Endpoint URL"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:82
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:71
msgid "English"
msgstr "English"
@ -743,7 +749,7 @@ msgstr "Filter"
msgid "Filters"
msgstr "Filters"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:66
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:75
msgid "French"
msgstr "French"
@ -770,7 +776,7 @@ msgstr "Functions"
msgid "General"
msgstr "General"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:70
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:83
msgid "German"
msgstr "German"
@ -867,10 +873,14 @@ msgstr "Invite link sent to email addresses"
msgid "Invite your team"
msgstr "Invite your team"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:74
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:87
msgid "Italian"
msgstr "Italian"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:91
msgid "Korean"
msgstr "Korean"
#: src/modules/settings/components/SettingsNavigationDrawerItems.tsx:217
msgid "Lab"
msgstr "Lab"
@ -1131,9 +1141,25 @@ msgstr "Please type \"{confirmationValue}\" to confirm you want to delete this A
msgid "Please type {confirmationText} to confirm you want to delete this webhook."
msgstr "Please type {confirmationText} to confirm you want to delete this webhook."
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:62
msgid "Portuguese"
msgstr "Portuguese"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:66
#~ msgid "Portuguese"
#~ msgstr "Portuguese"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:99
msgid "Portuguese — Brazil"
msgstr "Portuguese — Brazil"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:95
msgid "Portuguese — Portugal"
msgstr "Portuguese — Portugal"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:94
#~ msgid "Portuguese (Brazil)"
#~ msgstr "Portuguese (Brazil)"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:90
#~ msgid "Portuguese (Portugal)"
#~ msgstr "Portuguese (Portugal)"
#: src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectSettingsFormCard.tsx:52
#: src/modules/settings/data-model/components/SettingsDataModelPreviewFormCard.tsx:30
@ -1146,7 +1172,7 @@ msgstr "Preview"
msgid "Profile"
msgstr "Profile"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:97
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:113
msgid "Pseudo-English"
msgstr "Pseudo-English"
@ -1326,7 +1352,7 @@ msgstr "Skip"
msgid "Sort"
msgstr "Sort"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:78
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:79
msgid "Spanish"
msgstr "Spanish"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,12 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: pseudo-en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/modules/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel.ts:129
msgid "{aggregateLabel} of {fieldLabel}"
@ -269,11 +275,11 @@ msgstr ""
msgid "Change Password"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:86
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:103
msgid "Chinese — Simplified"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:90
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:107
msgid "Chinese — Traditional"
msgstr ""
@ -617,7 +623,7 @@ msgstr ""
msgid "Endpoint URL"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:82
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:71
msgid "English"
msgstr ""
@ -743,7 +749,7 @@ msgstr ""
msgid "Filters"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:66
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:75
msgid "French"
msgstr ""
@ -770,7 +776,7 @@ msgstr ""
msgid "General"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:70
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:83
msgid "German"
msgstr ""
@ -867,10 +873,14 @@ msgstr ""
msgid "Invite your team"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:74
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:87
msgid "Italian"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:91
msgid "Korean"
msgstr ""
#: src/modules/settings/components/SettingsNavigationDrawerItems.tsx:217
msgid "Lab"
msgstr ""
@ -1131,10 +1141,26 @@ msgstr ""
msgid "Please type {confirmationText} to confirm you want to delete this webhook."
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:62
msgid "Portuguese"
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:66
#~ msgid "Portuguese"
#~ msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:99
msgid "Portuguese — Brazil"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:95
msgid "Portuguese — Portugal"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:94
#~ msgid "Portuguese (Brazil)"
#~ msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:90
#~ msgid "Portuguese (Portugal)"
#~ msgstr ""
#: src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectSettingsFormCard.tsx:52
#: src/modules/settings/data-model/components/SettingsDataModelPreviewFormCard.tsx:30
msgid "Preview"
@ -1146,7 +1172,7 @@ msgstr ""
msgid "Profile"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:97
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:113
msgid "Pseudo-English"
msgstr ""
@ -1326,7 +1352,7 @@ msgstr ""
msgid "Sort"
msgstr ""
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:78
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx:79
msgid "Spanish"
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,10 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { Select } from '@/ui/input/components/Select';
import { useRefreshObjectMetadataItems } from '@/object-metadata/hooks/useRefreshObjectMetadataItem';
import { i18n } from '@lingui/core';
import { useLingui } from '@lingui/react/macro';
import { APP_LOCALES } from 'twenty-shared';
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
import { isDefined } from '~/utils/isDefined';
import { logError } from '~/utils/logError';
@ -30,6 +32,9 @@ export const LocalePicker = () => {
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
});
const { refreshObjectMetadataItems } =
useRefreshObjectMetadataItems('network-only');
const updateWorkspaceMember = async (changedFields: any) => {
if (!currentWorkspaceMember?.id) {
throw new Error('User is not logged in');
@ -47,51 +52,62 @@ export const LocalePicker = () => {
if (!isDefined(currentWorkspaceMember)) return;
const handleLocaleChange = (value: string) => {
const handleLocaleChange = async (value: string) => {
setCurrentWorkspaceMember({
...currentWorkspaceMember,
...{ locale: value },
});
updateWorkspaceMember({ locale: value });
await updateWorkspaceMember({ locale: value });
dynamicActivate(value);
await dynamicActivate(value);
await refreshObjectMetadataItems();
};
const localeOptions = [
const localeOptions: Array<{
label: string;
value: (typeof APP_LOCALES)[keyof typeof APP_LOCALES];
}> = [
{
label: t`Portuguese`,
value: 'pt',
label: t`English`,
value: APP_LOCALES.en,
},
{
label: t`French`,
value: 'fr',
},
{
label: t`German`,
value: 'de',
},
{
label: t`Italian`,
value: 'it',
value: APP_LOCALES.fr,
},
{
label: t`Spanish`,
value: 'es',
value: APP_LOCALES.es,
},
{
label: t`English`,
value: 'en',
label: t`German`,
value: APP_LOCALES.de,
},
{
label: t`Italian`,
value: APP_LOCALES.it,
},
{
label: t`Korean`,
value: APP_LOCALES.ko,
},
{
label: t`Portuguese — Portugal`,
value: APP_LOCALES['pt-PT'],
},
{
label: t`Portuguese — Brazil`,
value: APP_LOCALES['pt-BR'],
},
{
label: t`Chinese — Simplified`,
value: 'zh-Hans',
value: APP_LOCALES['zh-Hans'],
},
{
label: t`Chinese — Traditional`,
value: 'zh-Hant',
value: APP_LOCALES['zh-Hant'],
},
];
if (isDebugMode) {
localeOptions.push({
label: t`Pseudo-English`,

View File

@ -1,8 +1,13 @@
import { defineConfig } from '@lingui/cli';
import { APP_LOCALES } from 'twenty-shared';
export default defineConfig({
sourceLocale: 'en',
locales: ['en', 'fr'],
locales: Object.values(APP_LOCALES),
pseudoLocale: 'pseudo-en',
fallbackLocales: {
'pseudo-en': 'en',
},
extractorParserOptions: {
tsExperimentalDecorators: true,
},
@ -14,6 +19,7 @@ export default defineConfig({
],
catalogsMergePath:
'<rootDir>/src/engine/core-modules/i18n/locales/generated/{locale}',
compileNamespace: 'ts',
...(process.env.TRANSLATION_IO_API_KEY_BACKEND
? {
service: {

View File

@ -2,14 +2,31 @@ import { Injectable, OnModuleInit } from '@nestjs/common';
import { i18n } from '@lingui/core';
import { messages as enMessages } from 'src/engine/core-modules/i18n/locales/generated/en.js';
import { messages as frMessages } from 'src/engine/core-modules/i18n/locales/generated/fr.js';
import { messages as deMessages } from 'src/engine/core-modules/i18n/locales/generated/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 koMessages } from 'src/engine/core-modules/i18n/locales/generated/ko';
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';
@Injectable()
export class I18nService implements OnModuleInit {
async onModuleInit() {
i18n.load('fr', frMessages);
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('pt-PT', ptPTMessages);
i18n.load('pt-BR', ptBRMessages);
i18n.load('zh-Hans', zhHansMessages);
i18n.load('zh-Hant', zhHantMessages);
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 one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,9 @@
import { APP_LOCALES } from 'twenty-shared';
export type I18nContext = {
req: {
headers: {
'x-locale': string | undefined;
'x-locale': (typeof APP_LOCALES)[keyof typeof APP_LOCALES] | undefined;
};
};
};

View File

@ -5,6 +5,7 @@ import { i18n } from '@lingui/core';
import { Query, QueryOptions } from '@ptc-org/nestjs-query-core';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import { isDefined } from 'class-validator';
import { APP_LOCALES } from 'twenty-shared';
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';
@ -538,7 +539,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
async resolveTranslatableString(
objectMetadata: ObjectMetadataDTO,
labelKey: 'labelPlural' | 'labelSingular' | 'description',
locale: string | undefined,
locale: keyof typeof APP_LOCALES | undefined,
): Promise<string> {
if (objectMetadata.isCustom) {
return objectMetadata[labelKey];
@ -548,6 +549,8 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
return objectMetadata[labelKey];
}
i18n.activate(locale);
const messageId = generateMessageId(objectMetadata[labelKey] ?? '');
const translatedMessage = i18n._(messageId);

View File

@ -0,0 +1,13 @@
export const APP_LOCALES = {
en: 'en',
fr: 'fr',
de: 'de',
it: 'it',
es: 'es',
ko: 'ko',
'pt-PT': 'pt-PT',
'pt-BR': 'pt-BR',
'zh-Hans': 'zh-Hans',
'zh-Hant': 'zh-Hant',
'pseudo-en': 'pseudo-en',
} as const;

View File

@ -1,4 +1,5 @@
export * from './constants/FieldForTotalCountAggregateOperation';
export * from './constants/Locales';
export * from './constants/TwentyCompaniesBaseUrl';
export * from './constants/TwentyIconsBaseUrl';
export * from './types/ConnectedAccountProvider';