From fed6f130d16526ee8de7895458f1dd1c32a7a46a Mon Sep 17 00:00:00 2001 From: Joan Gallego Girona Date: Thu, 28 Sep 2023 09:25:01 +0200 Subject: [PATCH 1/2] Translations v2 remove v1 code (#6181) * fix flakyness * remove unused param * WIP, moving specs to only V2 * WIP, removed duplicated tests and v1 code * moved usefull tests to translations.spec * remove translations v1 fixtures * remove translationsv1 from sync module * fix all specs broken without translationsV2 fixtures * removed unused translations fixtures * remove translationsV2 feature flag * fix eslints * remove translations v2 from fixtures * moved migration to migrations folder * remove translationsModel * fix eslint * create translationsV2 indices when inserting fixtures --- app/api/config.ts | 1 - app/api/csv/specs/csvLoaderFixtures.ts | 5 +- app/api/csv/specs/csvLoaderSelectsFixtures.ts | 5 +- app/api/csv/specs/fixtures.ts | 3 +- .../entities/specs/denormalization.spec.ts | 14 +- .../specs/entitiesDeleteMultiple.spec.ts | 4 - app/api/entities/specs/fixtures.js | 5 +- .../database/MongoTranslationsDataSource.ts | 2 +- app/api/i18n/specs/fixtures.ts | 2 - ...turesTranslationsV2ToTranslationsLegacy.ts | 57 -- app/api/i18n/specs/routes.spec.ts | 41 +- app/api/i18n/specs/translations.spec.ts | 74 +- .../specs/translations_v2_support.spec.ts | 902 ------------------ app/api/i18n/translations.ts | 188 +--- app/api/i18n/translationsModel.ts | 22 - app/api/i18n/v2_support.ts | 184 ++-- .../index.js | 2 +- .../specs/fixtures.js | 0 .../translations_to_translations_v2.spec.js | 2 +- .../search.v2/specs/fixturesSnippetsSearch.ts | 4 - .../specs/setupTestingEnvironment.ts | 4 - app/api/services/preserve/specs/fixtures.ts | 32 - app/api/sync/processNamespaces.ts | 43 +- app/api/sync/specs/fixtures.ts | 80 -- app/api/sync/specs/syncWorker.spec.ts | 68 +- .../v2_newRelationshipProperties.spec.ts | 1 - app/api/tenants/tenantContext.ts | 1 - app/api/thesauri/specs/fixtures.ts | 5 +- app/api/topicclassification/specs/fixtures.ts | 1 - app/api/utils/testing_db.ts | 30 +- 30 files changed, 194 insertions(+), 1588 deletions(-) delete mode 100644 app/api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy.ts delete mode 100644 app/api/i18n/specs/translations_v2_support.spec.ts delete mode 100644 app/api/i18n/translationsModel.ts rename app/api/{i18n.v2/migrations => migrations/migrations/144-translations-to-translationsV2}/index.js (99%) rename app/api/{i18n.v2/migrations => migrations/migrations/144-translations-to-translationsV2}/specs/fixtures.js (100%) rename app/api/{i18n.v2/migrations => migrations/migrations/144-translations-to-translationsV2}/specs/translations_to_translations_v2.spec.js (99%) diff --git a/app/api/config.ts b/app/api/config.ts index d645f9d109..45da19bbc2 100644 --- a/app/api/config.ts +++ b/app/api/config.ts @@ -61,7 +61,6 @@ export const config = { activityLogs: ACTIVITY_LOGS_FOLDER || `${filesRootPath}/log/`, featureFlags: { s3Storage: false, - translationsV2: false, }, }, externalServices: Boolean(process.env.EXTERNAL_SERVICES) || false, diff --git a/app/api/csv/specs/csvLoaderFixtures.ts b/app/api/csv/specs/csvLoaderFixtures.ts index 681161d1c2..f4e7240d89 100644 --- a/app/api/csv/specs/csvLoaderFixtures.ts +++ b/app/api/csv/specs/csvLoaderFixtures.ts @@ -2,7 +2,6 @@ import db from 'api/utils/testing_db'; import { propertyTypes } from 'shared/propertyTypes'; import { templateUtils } from 'api/templates'; import { LanguageISO6391 } from 'shared/types/commonTypes'; -import { fixturesTranslationsV2ToTranslationsLegacy } from 'api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy'; import { TranslationDBO } from 'api/i18n.v2/schemas/TranslationDBO'; import { getFixturesFactory } from 'api/utils/fixturesFactory'; @@ -164,11 +163,11 @@ export default { }, ], - translations: fixturesTranslationsV2ToTranslationsLegacy([ + translationsV2: [ ...commonTranslationsV2('en'), ...commonTranslationsV2('es'), ...commonTranslationsV2('fr'), - ]), + ], }; export { template1Id, templateWithGeneratedTitle, thesauri1Id }; diff --git a/app/api/csv/specs/csvLoaderSelectsFixtures.ts b/app/api/csv/specs/csvLoaderSelectsFixtures.ts index 18f3e1b78e..9b4d4aed72 100644 --- a/app/api/csv/specs/csvLoaderSelectsFixtures.ts +++ b/app/api/csv/specs/csvLoaderSelectsFixtures.ts @@ -1,6 +1,5 @@ import db from 'api/utils/testing_db'; import { getFixturesFactory } from 'api/utils/fixturesFactory'; -import { fixturesTranslationsV2ToTranslationsLegacy } from 'api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy'; const fixtureFactory = getFixturesFactory(); const createTranslationDBO = fixtureFactory.v2.database.translationDBO; @@ -76,7 +75,7 @@ const fixtures = { ], }, ], - translations: fixturesTranslationsV2ToTranslationsLegacy([ + translationsV2: [ createTranslationDBO('B', 'Bes', 'es', { id: fixtureFactory.id('multiselect_thesaurus').toString(), type: 'Thesaurus', @@ -197,7 +196,7 @@ const fixtures = { type: 'Uwazi UI', label: 'System', }), - ]), + ], }; export { fixtures, fixtureFactory }; diff --git a/app/api/csv/specs/fixtures.ts b/app/api/csv/specs/fixtures.ts index eba7b6b895..1f3c3e722b 100644 --- a/app/api/csv/specs/fixtures.ts +++ b/app/api/csv/specs/fixtures.ts @@ -2,7 +2,6 @@ import db, { DBFixture } from 'api/utils/testing_db'; import { propertyTypes } from 'shared/propertyTypes'; import { templateUtils } from 'api/templates'; import { TranslationDBO } from 'api/i18n.v2/schemas/TranslationDBO'; -import { fixturesTranslationsV2ToTranslationsLegacy } from 'api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy'; import { getFixturesFactory } from 'api/utils/fixturesFactory'; const template1Id = db.id(); @@ -125,7 +124,7 @@ const fixtures: DBFixture = { }, ], - translations: fixturesTranslationsV2ToTranslationsLegacy(translationsV2), + translationsV2, }; export { fixtures, template1Id, thesauri1Id, templateToRelateId }; diff --git a/app/api/entities/specs/denormalization.spec.ts b/app/api/entities/specs/denormalization.spec.ts index 20ea4dc81d..183ded5951 100644 --- a/app/api/entities/specs/denormalization.spec.ts +++ b/app/api/entities/specs/denormalization.spec.ts @@ -7,10 +7,9 @@ import thesauris from 'api/thesauri'; import { elasticTesting } from 'api/utils/elastic_testing'; import translations from 'api/i18n/translations'; import { getFixturesFactory } from '../../utils/fixturesFactory'; -import { fixturesTranslationsV2ToTranslationsLegacy } from 'api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy'; -const load = async (data: DBFixture, index?: string) => { - return db.setupFixturesAndContext( +const load = async (data: DBFixture, index?: string) => + db.setupFixturesAndContext( { ...data, settings: [ @@ -22,14 +21,9 @@ const load = async (data: DBFixture, index?: string) => { ], }, ], - translations: data.translations || [ - { locale: 'en', contexts: [] }, - { locale: 'es', contexts: [] }, - ], }, index ); -}; describe('Denormalize relationships', () => { const factory = getFixturesFactory(); @@ -627,7 +621,7 @@ describe('Denormalize relationships', () => { { language: 'es' } ), ], - translations: fixturesTranslationsV2ToTranslationsLegacy([ + translationsV2: [ createTranslationDBO('One', 'One', 'en', { id: factory.id('Numbers').toString(), type: 'Thesaurus', @@ -659,7 +653,7 @@ describe('Denormalize relationships', () => { type: 'Thesaurus', label: 'Numbers', }), - ]), + ], }, 'index_denormalization' ); diff --git a/app/api/entities/specs/entitiesDeleteMultiple.spec.ts b/app/api/entities/specs/entitiesDeleteMultiple.spec.ts index e1c8b2a2fb..c899e204c6 100644 --- a/app/api/entities/specs/entitiesDeleteMultiple.spec.ts +++ b/app/api/entities/specs/entitiesDeleteMultiple.spec.ts @@ -24,10 +24,6 @@ const loadFixtures = async () => ], }, ], - translations: [ - { locale: 'en', contexts: [] }, - { locale: 'es', contexts: [] }, - ], }, 'entities.delete.multiple.spec2' ); diff --git a/app/api/entities/specs/fixtures.js b/app/api/entities/specs/fixtures.js index 08d6210792..5cf9d6fbe0 100644 --- a/app/api/entities/specs/fixtures.js +++ b/app/api/entities/specs/fixtures.js @@ -1,6 +1,5 @@ /* eslint-disable max-lines */ /* eslint-disable max-len */ -import { fixturesTranslationsV2ToTranslationsLegacy } from 'api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy'; import { getFixturesFactory } from 'api/utils/fixturesFactory'; import db from 'api/utils/testing_db'; import { AccessLevels, PermissionType } from 'shared/types/permissionSchema'; @@ -661,7 +660,7 @@ export default { ], }, ], - translations: fixturesTranslationsV2ToTranslationsLegacy([ + translationsV2: [ { language: 'pt', key: 'town2', @@ -752,7 +751,7 @@ export default { value: 'Country1', context: { id: dictionary.toString(), type: 'Thesauri', label: 'dictionary' }, }, - ]), + ], ixsuggestions: [ { diff --git a/app/api/i18n.v2/database/MongoTranslationsDataSource.ts b/app/api/i18n.v2/database/MongoTranslationsDataSource.ts index 42eb5e2dd0..f03255d78d 100644 --- a/app/api/i18n.v2/database/MongoTranslationsDataSource.ts +++ b/app/api/i18n.v2/database/MongoTranslationsDataSource.ts @@ -118,6 +118,6 @@ export class MongoTranslationsDataSource ]) .toArray(); - return result?.notFoundKeys || []; + return result?.notFoundKeys || keys; } } diff --git a/app/api/i18n/specs/fixtures.ts b/app/api/i18n/specs/fixtures.ts index 8bb9fbb377..3f8ecbddc6 100644 --- a/app/api/i18n/specs/fixtures.ts +++ b/app/api/i18n/specs/fixtures.ts @@ -1,6 +1,5 @@ import { getFixturesFactory } from 'api/utils/fixturesFactory'; import db, { DBFixture } from 'api/utils/testing_db'; -import { fixturesTranslationsV2ToTranslationsLegacy } from './fixturesTranslationsV2ToTranslationsLegacy'; const entityTemplateId = db.id(); const documentTemplateId = db.id(); @@ -164,7 +163,6 @@ const translationsV2: DBFixture['translationsV2'] = [ const fixtures: DBFixture = { // eslint-disable-next-line camelcase translationsV2, - translations: fixturesTranslationsV2ToTranslationsLegacy(translationsV2), settings: [ { _id: db.id(), diff --git a/app/api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy.ts b/app/api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy.ts deleted file mode 100644 index 7de90dea20..0000000000 --- a/app/api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { TranslationDBO } from 'api/i18n.v2/schemas/TranslationDBO'; -import { EnforcedWithId } from 'api/odm'; -import { TranslationContext, TranslationType, TranslationValue } from 'shared/translationType'; -import { LanguageISO6391 } from 'shared/types/commonTypes'; - -export const fixturesTranslationsV2ToTranslationsLegacy = (translations: TranslationDBO[]) => { - const languageSet = new Set(); - translations.forEach(t => { - languageSet.add(t.language); - }); - const languageKeys = Array.from(languageSet); - - // const resultMap: { [language: string]: TranslationType & { locale: string } } = {}; - const resultMap = languageKeys.reduce<{ - [language: string]: TranslationType & { locale: string }; - }>((memo, key) => { - // eslint-disable-next-line no-param-reassign - memo[key] = { locale: key, contexts: [] }; - return memo; - }, {}); - - const contexts = languageKeys.reduce<{ - [language: string]: { [context: string]: TranslationContext & { values: TranslationValue[] } }; - }>((memo, key) => { - // eslint-disable-next-line no-param-reassign - memo[key] = {}; - return memo; - }, {}); - - translations.forEach(translation => { - if (!resultMap[translation.language]) { - resultMap[translation.language] = { - locale: translation.language, - contexts: [], - }; - contexts[translation.language] = {}; - } - if (!contexts[translation.language][translation.context.id]) { - contexts[translation.language][translation.context.id] = { - id: translation.context.id, - label: translation.context.label, - type: translation.context.type, - values: [], - }; - } - contexts[translation.language][translation.context.id].values.push({ - key: translation.key, - value: translation.value, - }); - }); - - return Object.values(resultMap).map(translation => { - // eslint-disable-next-line no-param-reassign - translation.contexts = Object.values(contexts[translation.locale]); - return translation; - }) as EnforcedWithId[]; -}; diff --git a/app/api/i18n/specs/routes.spec.ts b/app/api/i18n/specs/routes.spec.ts index 1c2fdedb73..9bf4d178d8 100644 --- a/app/api/i18n/specs/routes.spec.ts +++ b/app/api/i18n/specs/routes.spec.ts @@ -15,7 +15,6 @@ import { availableLanguages } from 'shared/languagesList'; import { LanguageSchema } from 'shared/types/commonTypes'; import { UserRole } from 'shared/types/userSchema'; import { DefaultTranslations } from '../defaultTranslations'; -import { fixturesTranslationsV2ToTranslationsLegacy } from './fixturesTranslationsV2ToTranslationsLegacy'; import { sortByLocale } from './sortByLocale'; describe('i18n translations routes', () => { @@ -65,9 +64,8 @@ describe('i18n translations routes', () => { }, ], translationsV2, - translations: fixturesTranslationsV2ToTranslationsLegacy(translationsV2), }, - 'index' + 'index_i18n_routes' ); }); @@ -305,12 +303,6 @@ describe('i18n translations routes', () => { { locale: 'zh', contexts: [ - { - id: 'contextID', - label: 'Template', - type: 'Entity', - values: { title: 'Template 1' }, - }, { id: 'System', label: 'User Interface', @@ -319,6 +311,12 @@ describe('i18n translations routes', () => { Search: 'Search', }, }, + { + id: 'contextID', + label: 'Template', + type: 'Entity', + values: { title: 'Template 1' }, + }, ], }, ], @@ -328,18 +326,18 @@ describe('i18n translations routes', () => { { locale: 'ja', contexts: [ - { - id: 'contextID', - label: 'Template', - type: 'Entity', - values: { title: 'Template 1' }, - }, { id: 'System', label: 'User Interface', type: 'Uwazi UI', values: { Search: 'Search' }, }, + { + id: 'contextID', + label: 'Template', + type: 'Entity', + values: { title: 'Template 1' }, + }, ], }, ], @@ -366,6 +364,7 @@ describe('i18n translations routes', () => { describe('when encountering an error', () => { let mockCalls: any[]; + jest.spyOn(console, 'error').mockImplementation(() => true); let response: request.Response; let settingsAddLanguageMock: jest.SpyInstance; @@ -417,12 +416,6 @@ describe('i18n translations routes', () => { expect(response.body).toMatchObject([ { contexts: [ - { - id: 'contextID', - label: 'Template', - type: 'Entity', - values: { title: 'Plantilla 1' }, - }, { id: 'System', label: 'User Interface', @@ -431,6 +424,12 @@ describe('i18n translations routes', () => { Search: 'Buscar traducida', }, }, + { + id: 'contextID', + label: 'Template', + type: 'Entity', + values: { title: 'Plantilla 1' }, + }, ], locale: 'es', }, diff --git a/app/api/i18n/specs/translations.spec.ts b/app/api/i18n/specs/translations.spec.ts index 4e13a67798..ca69b677fb 100644 --- a/app/api/i18n/specs/translations.spec.ts +++ b/app/api/i18n/specs/translations.spec.ts @@ -7,14 +7,12 @@ import { ContextType } from 'shared/translationSchema'; import * as fs from 'fs'; import { UITranslationNotAvailable } from '../defaultTranslations'; import translations from '../translations'; -import { migrateTranslationsToV2 } from '../v2_support'; import fixtures, { dictionaryId } from './fixtures'; import { sortByLocale } from './sortByLocale'; describe('translations', () => { beforeEach(async () => { await db.setupFixturesAndContext(fixtures); - await migrateTranslationsToV2(); }); afterAll(async () => { @@ -248,30 +246,70 @@ describe('translations', () => { const translated = await translations.get(); expect(translated[0].contexts?.length).toBe(1); + expect(translated[0].contexts?.[0].type).toBe('Thesaurus'); + expect(translated[1].contexts?.[0].type).toBe('Thesaurus'); expect(translated[1].contexts?.length).toBe(1); }); }); describe('updateContext()', () => { - it('should add values if the context values are undefined', async () => { - const keyNameChanges = { Password: 'Pass', Account: 'Acc', System: 'Interface' }; - const deletedProperties = ['Age']; - const context = { - Pass: 'Pass', - Acc: 'Acc', - Email: 'Email', - Name: 'Name', - Interface: 'Interface', - }; + it('should change the value of a translation when changing the key if the locale is the default one', async () => { + await translations.updateContext( + { id: dictionaryId.toString(), label: 'new context name', type: 'Thesaurus' }, + { 'property should only change value on default languge': 'new property name' }, + [], + {} + ); - const result = await translations.updateContext( - { id: 'System', label: 'Menu', type: 'Uwazi UI' }, - keyNameChanges, - deletedProperties, - context + const [esTranslations] = await translations.get({ locale: 'es' }); + const esThesauriContext = (esTranslations.contexts || []).find(c => c.type === 'Thesaurus'); + expect(esThesauriContext?.values).toMatchObject({ + 'new property name': 'property', + }); + + const [zhTranslations] = await translations.get({ locale: 'zh' }); + const zhThesauriContext = (zhTranslations.contexts || []).find(c => c.type === 'Thesaurus'); + expect(zhThesauriContext?.values).toMatchObject({ + 'new property name': 'property', + }); + + const [enTranslations] = await translations.get({ locale: 'en' }); + const enThesauriContext = (enTranslations.contexts || []).find(c => c.type === 'Thesaurus'); + expect(enThesauriContext?.values).toMatchObject({ + 'new property name': 'new property name', + }); + }); + it('should properly change context name, key names, values for the keys changed and deleteProperties, and create new values as new translations if key does not exists', async () => { + await translations.updateContext( + { id: dictionaryId.toString(), label: 'new context name', type: 'Thesaurus' }, + { Account: 'New Account Key', Password: 'New Password key' }, + ['Age', 'Email'], + { 'new key': 'new value' } ); - expect(result).toBe('ok'); + const [enTranslations] = await translations.get({ locale: 'en' }); + const enThesauriContext = (enTranslations.contexts || []).find(c => c.type === 'Thesaurus'); + + expect(enThesauriContext?.label).toBe('new context name'); + expect(enThesauriContext?.values).toEqual({ + 'property should only change value on default languge': 'property', + 'New Account Key': 'New Account Key', + 'New Password key': 'New Password key', + 'new key': 'new value', + 'dictionary 2': 'dictionary 2', + }); + + const [esTranslations] = await translations.get({ locale: 'es' }); + const esThesauriContext = (esTranslations.contexts || []).find(c => c.type === 'Thesaurus'); + + expect(esThesauriContext?.label).toBe('new context name'); + expect(esThesauriContext?.values).toEqual({ + 'property should only change value on default languge': 'property', + 'New Account Key': 'Cuenta', + 'New Password key': 'Contraseña', + 'new key': 'new value', + 'dictionary 2': 'dictionary 2', + }); }); it('should update a context with its values', async () => { diff --git a/app/api/i18n/specs/translations_v2_support.spec.ts b/app/api/i18n/specs/translations_v2_support.spec.ts deleted file mode 100644 index 5166b7af87..0000000000 --- a/app/api/i18n/specs/translations_v2_support.spec.ts +++ /dev/null @@ -1,902 +0,0 @@ -import settings from 'api/settings'; -import { testingTenants } from 'api/utils/testingTenants'; -import testingDB from 'api/utils/testing_db'; -import { Db, ObjectId } from 'mongodb'; -import { TranslationValue } from 'shared/translationType'; -import { ContextType } from 'shared/translationSchema'; - -import migration from '../../i18n.v2/migrations'; -import translations from '../translations'; -import { migrateTranslationsToV2 } from '../v2_support'; -import fixtures, { dictionaryId } from './fixtures'; - -let db: Db; -const newTranslationsCollection = 'translationsV2'; - -describe('translations v2 support', () => { - beforeEach(async () => { - jest.spyOn(process.stdout, 'write').mockImplementation(() => true); - await testingDB.setupFixturesAndContext({ - ...fixtures, - translations: [ - { - locale: 'es', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - { key: 'Key3', value: 'Value3' }, - ], - }, - { - id: 'contextId2', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }, - { - locale: 'zh', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - { key: 'Key3', value: 'Value3' }, - ], - }, - { - id: 'contextId2', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }, - ], - }); - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: true } }); - await migrateTranslationsToV2(); - db = testingDB.mongodb as Db; - }); - - afterAll(async () => { - await testingDB.disconnect(); - }); - - const deactivateFeature = async () => { - await testingDB.setupFixturesAndContext({ ...fixtures, translations: [] }); - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: false } }); - await migrateTranslationsToV2(); - }; - - const createTranslation = async () => - translations.save({ - locale: 'en', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }); - - const updateTranslation = async (_id: ObjectId, values: TranslationValue[]) => - translations.save({ - _id, - locale: 'en', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values, - }, - ], - }); - - describe('save', () => { - it('should do nothing when the feature flag is off (Temporary test)', async () => { - await deactivateFeature(); - - await createTranslation(); - - const createdTranslations = await db.collection(newTranslationsCollection).find().toArray(); - expect(createdTranslations).toEqual([]); - }); - - it('should use locale to update the old translations collection (Temporary test)', async () => { - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: false } }); - await createTranslation(); - await createTranslation(); - const oldTranslations = await db.collection('translations').find().toArray(); - expect(oldTranslations.map(t => t.locale)).toEqual(['es', 'zh', 'en']); - }); - - it('should save the translations to the new translations collection', async () => { - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: true } }); - await testingDB.setupFixturesAndContext({ - settings: [{ languages: [{ key: 'en', label: 'English', default: true }] }], - translations: [], - }); - await migrateTranslationsToV2(); - await createTranslation(); - - const createdTranslations = await db - .collection(newTranslationsCollection) - .find({ language: 'en' }) - .toArray(); - - expect(createdTranslations).toMatchObject([ - { - language: 'en', - key: 'Key', - value: 'Value', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - { - language: 'en', - key: 'Key2', - value: 'Value2', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - ]); - }); - - describe('when updating (the translation already exists on db)', () => { - it('should not save anything on the new collection', async () => { - await deactivateFeature(); - - const savedTranslations = await createTranslation(); - await updateTranslation(savedTranslations._id, [{ key: 'Key', value: 'updatedValue' }]); - - const createdTranslations = await db.collection(newTranslationsCollection).find().toArray(); - expect(createdTranslations).toEqual([]); - }); - - it('should update already existing translations and create new ones', async () => { - const enTranslationId = testingDB.id(); - await testingDB.setupFixturesAndContext({ - settings: [{ languages: [{ key: 'en', label: 'English', default: true }] }], - translations: [ - { - _id: enTranslationId, - locale: 'en', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }, - ], - }); - await migrateTranslationsToV2(); - await updateTranslation(enTranslationId, [ - { key: 'Key', value: 'updatedValue' }, - { key: 'Key2', value: 'updatedValue2' }, - { key: 'Key3', value: 'createdValue' }, - ]); - - const createdTranslations = await db - .collection(newTranslationsCollection) - .find({ language: 'en' }) - .toArray(); - - expect(createdTranslations).toMatchObject([ - { - language: 'en', - key: 'Key', - value: 'updatedValue', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - { - language: 'en', - key: 'Key2', - value: 'updatedValue2', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - { - language: 'en', - key: 'Key3', - value: 'createdValue', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - ]); - }); - }); - }); - - describe('addLanguage', () => { - it('should not create new ones on the new collection', async () => { - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: false } }); - await createTranslation(); - await translations.addLanguage('ca'); - - const createdTranslations = await db - .collection(newTranslationsCollection) - .find({ language: 'ca' }) - .toArray(); - - expect(createdTranslations).toEqual([]); - }); - - it('should duplicate translations from the default language to the new one', async () => { - await testingDB.setupFixturesAndContext({ - settings: [{ languages: [{ key: 'en', label: 'English', default: true }] }], - translations: [ - { - locale: 'en', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }, - ], - }); - await migrateTranslationsToV2(); - - await settings.addLanguage({ label: 'catalan', key: 'ca' }); - await translations.addLanguage('ca'); - - const createdTranslations = await db - .collection(newTranslationsCollection) - .find({ language: 'ca' }) - .toArray(); - - expect(createdTranslations).toMatchObject([ - { - language: 'ca', - key: 'Key', - value: 'Value', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - { - language: 'ca', - key: 'Key2', - value: 'Value2', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId' }, - }, - ]); - }); - }); - - describe('deleteContext', () => { - it('should delete all translations belonging to a context', async () => { - await translations.save({ - locale: 'en', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - { - id: 'contextId2', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }); - - await translations.deleteContext('contextId'); - const translationsRemaining = await db - .collection(newTranslationsCollection) - .find({ language: 'en' }) - .toArray(); - expect(translationsRemaining).toMatchObject([ - { - language: 'en', - key: 'Key', - value: 'Value', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId2' }, - }, - { - language: 'en', - key: 'Key2', - value: 'Value2', - context: { type: 'Entity', label: 'contextLabel', id: 'contextId2' }, - }, - ]); - }); - }); - - describe('removeLanguage', () => { - it('should delete all translations belonging to a language', async () => { - await createTranslation(); - - await translations.removeLanguage('en'); - - const enTranslations = ( - await db.collection(newTranslationsCollection).find({ language: 'en' }).toArray() - ).length; - expect(enTranslations).toBe(0); - - const esTranslations = ( - await db.collection(newTranslationsCollection).find({ language: 'es' }).toArray() - ).length; - expect(esTranslations).toBe(5); - }); - }); - - describe('get', () => { - describe('when feature flag is off', () => { - it('should not migrate translations to new collection', async () => { - await testingDB.setupFixturesAndContext(fixtures); - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: false } }); - - await migrateTranslationsToV2(); - - const translationsMigrated = await db - .collection(newTranslationsCollection) - .find() - .toArray(); - - expect(translationsMigrated).toMatchObject([]); - }); - it('should empty the new translations collection', async () => { - await testingDB.setupFixturesAndContext(fixtures); - - await migrateTranslationsToV2(); - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: false } }); - await migrateTranslationsToV2(); - - const translationsMigrated = await db - .collection(newTranslationsCollection) - .find() - .toArray(); - - expect(translationsMigrated).toMatchObject([]); - }); - }); - describe('when feature flag is on', () => { - it('should migrate current translations to the new collection', async () => { - await testingDB.setupFixturesAndContext(fixtures); - await migrateTranslationsToV2(); - - const translationsMigrated = await db - .collection(newTranslationsCollection) - .find({ 'context.id': 'System', language: 'en' }) - .sort({ key: 1 }) - .toArray(); - - expect(translationsMigrated).toMatchObject([ - { - language: 'en', - key: 'Account', - value: 'Account', - context: { type: 'Uwazi UI', label: 'System', id: 'System' }, - }, - { - language: 'en', - key: 'Age', - value: 'Age', - context: { type: 'Uwazi UI', label: 'System', id: 'System' }, - }, - { - language: 'en', - key: 'Email', - value: 'E-Mail', - context: { type: 'Uwazi UI', label: 'System', id: 'System' }, - }, - { - language: 'en', - key: 'Library', - value: 'Library', - context: { type: 'Uwazi UI', label: 'System', id: 'System' }, - }, - { - language: 'en', - key: 'Password', - value: 'Password', - context: { type: 'Uwazi UI', label: 'System', id: 'System' }, - }, - ]); - }); - - it('should only migrate once (on concurrent calls also)', async () => { - await deactivateFeature(); - await testingDB.setupFixturesAndContext(fixtures); - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: true } }); - - jest.spyOn(migration, 'up'); - await Promise.all([translations.get(), translations.get(), translations.get()]); - await translations.get(); - expect(migration.up).toHaveBeenCalledTimes(1); - - const translationsHelperCount = await db - .collection('translationsV2_helper') - .find() - .toArray(); - expect(translationsHelperCount).toMatchObject([ - { - migrating: false, - migrated: true, - }, - ]); - }); - - it('should return from the old collection when not migrated', async () => { - await testingDB.setupFixturesAndContext({ - ...fixtures, - translations: [ - { - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Password' }, - { key: 'Account', value: 'Account' }, - ], - }, - ], - }, - ], - }); - const [english] = await translations.get({ locale: 'en' }); - expect(english).toMatchObject({ - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: { - Account: 'Account', - Password: 'Password', - }, - }, - ], - }); - }); - - it('should return from the new collection when migrated', async () => { - await testingDB.setupFixturesAndContext({ - ...fixtures, - translations: [ - { - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Contraseña' }, - { key: 'Account', value: 'Cuenta' }, - ], - }, - ], - }, - { - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Password' }, - { key: 'Account', value: 'Account' }, - ], - }, - ], - }, - ], - }); - const [spanish, english] = await translations.get(); - - const englishComesFromTheOldCollection = english._id; - expect(englishComesFromTheOldCollection).toBeFalsy(); - - expect(english).toMatchObject({ - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: { Password: 'Password', Account: 'Account' }, - }, - ], - }); - - const spanishComesFromTheOldCollection = spanish._id; - expect(spanishComesFromTheOldCollection).toBeFalsy(); - - expect(spanish).toMatchObject({ - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: { Password: 'Contraseña', Account: 'Cuenta' }, - }, - ], - }); - }); - - it('should return only the language requested', async () => { - await testingDB.setupFixturesAndContext({ - ...fixtures, - translations: [ - { - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Contraseña' }, - { key: 'Account', value: 'Cuenta' }, - ], - }, - ], - }, - { - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Password' }, - { key: 'Account', value: 'Account' }, - ], - }, - ], - }, - ], - }); - await translations.get(); - const [spanish, english] = await translations.get({ locale: 'es' }); - expect(english).toBeUndefined(); - expect(spanish).toMatchObject({ - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: { Password: 'Contraseña', Account: 'Cuenta' }, - }, - ], - }); - }); - - it('should return only the language and context requested', async () => { - await testingDB.setupFixturesAndContext({ - ...fixtures, - translations: [ - { - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Contraseña' }, - { key: 'Account', value: 'Cuenta' }, - ], - }, - { - id: 'context 2', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Contraseña' }, - { key: 'Account', value: 'Cuenta' }, - ], - }, - ], - }, - { - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Password' }, - { key: 'Account', value: 'Account' }, - ], - }, - ], - }, - ], - }); - const [spanish] = await translations.get({ context: 'System' }); - expect(spanish).toMatchObject({ - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: { Password: 'Contraseña', Account: 'Cuenta' }, - }, - ], - }); - }); - - describe('when requesting a locale (old collection)', () => { - it('should return the new collection values', async () => { - const spanishId = new ObjectId(); - await testingDB.setupFixturesAndContext({ - ...fixtures, - translations: [ - { - _id: spanishId, - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Contraseña' }, - { key: 'Account', value: 'Cuenta' }, - ], - }, - ], - }, - { - locale: 'en', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: [ - { key: 'Password', value: 'Password' }, - { key: 'Account', value: 'Account' }, - ], - }, - ], - }, - ], - }); - await translations.get(); - const [spanish, rest] = await translations.get({ locale: 'es' }); - expect(rest).toBeUndefined(); - expect(spanish).toMatchObject({ - locale: 'es', - contexts: [ - { - id: 'System', - label: 'System', - type: 'Uwazi UI', - values: { Password: 'Contraseña', Account: 'Cuenta' }, - }, - ], - }); - }); - }); - }); - }); - - describe('updateContext', () => { - describe('when feature flag is on', () => { - it('should change the value of a translation when changing the key if the locale is the default one', async () => { - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: true } }); - await testingDB.setupFixturesAndContext(fixtures); - await translations.get(); - - const values = {}; - - await translations.updateContext( - { id: dictionaryId.toString(), label: 'new context name', type: 'Thesaurus' }, - { 'property should only change value on default languge': 'new property name' }, - [], - values - ); - - const [propertyES] = await db - .collection(newTranslationsCollection) - .find({ key: 'new property name', language: 'es' }) - .toArray(); - - const [propertyEN] = await db - .collection(newTranslationsCollection) - .find({ key: 'new property name', language: 'en' }) - .toArray(); - - const [propertyZH] = await db - .collection(newTranslationsCollection) - .find({ key: 'new property name', language: 'zh' }) - .toArray(); - - expect(propertyES.value).toBe('property'); - expect(propertyZH.value).toBe('property'); - expect(propertyEN.value).toBe('new property name'); - }); - - it('should properly change context name, key names, values for the keys changed and deleteProperties, and create new values as new translations if key does not exists', async () => { - //changed keys should change value also when the locale is the default one - //! use the previous commit to remove the update and then implement the key change functionality - testingTenants.changeCurrentTenant({ featureFlags: { translationsV2: true } }); - await testingDB.setupFixturesAndContext(fixtures); - await translations.get(); - - const values = { - 'new key': 'new value', - 'property should only change value on default languge': 'new value', - }; - - await translations.updateContext( - { id: dictionaryId.toString(), label: 'new context name', type: 'Thesaurus' }, - { Account: 'New Account Key', Password: 'New Password key' }, - ['Email', 'Age'], - values - ); - - const updatedTranslations = await db - .collection(newTranslationsCollection) - .find({ language: { $in: ['es', 'en'] }, 'context.id': dictionaryId.toString() }) - .sort({ language: 1, key: 1 }) - .toArray(); - - expect(updatedTranslations.filter(t => t.language === 'en')).toMatchObject([ - { - language: 'en', - key: 'New Account Key', - value: 'New Account Key', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'en', - key: 'New Password key', - value: 'New Password key', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'en', - key: 'dictionary 2', - value: 'dictionary 2', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'en', - key: 'new key', - value: 'new value', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'en', - key: 'property should only change value on default languge', - value: 'property', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - ]); - - expect(updatedTranslations.filter(t => t.language === 'es')).toMatchObject([ - { - language: 'es', - key: 'New Account Key', - value: 'Cuenta', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'es', - key: 'New Password key', - value: 'Contraseña', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'es', - key: 'dictionary 2', - value: 'dictionary 2', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'es', - key: 'new key', - value: 'new value', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - { - language: 'es', - key: 'property should only change value on default languge', - value: 'property', - context: { type: 'Thesaurus', label: 'new context name', id: dictionaryId.toString() }, - }, - ]); - }); - }); - }); - - describe('addContext()', () => { - it('should add a context with its values', async () => { - await testingDB.setupFixturesAndContext(fixtures); - await migrateTranslationsToV2(); - - const values = { Name: 'Name', Surname: 'Surname' }; - const result = await translations.addContext('context', 'Judge', values, ContextType.entity); - - expect(result).toBe('ok'); - - const newContextTranslations = await db - .collection(newTranslationsCollection) - .find({ language: { $in: ['es', 'en'] }, 'context.id': 'context' }) - .sort({ language: 1, key: 1 }) - .toArray(); - - expect(newContextTranslations.filter(t => t.language === 'es')).toMatchObject([ - { - language: 'es', - key: 'Name', - value: 'Name', - context: { type: ContextType.entity, label: 'Judge', id: 'context' }, - }, - { - language: 'es', - key: 'Surname', - value: 'Surname', - context: { type: ContextType.entity, label: 'Judge', id: 'context' }, - }, - ]); - - expect(newContextTranslations.filter(t => t.language === 'en')).toMatchObject([ - { - language: 'en', - key: 'Name', - value: 'Name', - context: { type: ContextType.entity, label: 'Judge', id: 'context' }, - }, - { - language: 'en', - key: 'Surname', - value: 'Surname', - context: { type: ContextType.entity, label: 'Judge', id: 'context' }, - }, - ]); - }); - }); -}); diff --git a/app/api/i18n/translations.ts b/app/api/i18n/translations.ts index 34d4697cec..7d52abb06f 100644 --- a/app/api/i18n/translations.ts +++ b/app/api/i18n/translations.ts @@ -17,7 +17,6 @@ import { availableLanguages } from 'shared/languagesList'; import { ContextType } from 'shared/translationSchema'; import { LanguageISO6391 } from 'shared/types/commonTypes'; import { pipeline } from 'stream/promises'; -import model from './translationsModel'; import { addLanguageV2, deleteTranslationsByContextIdV2, @@ -25,7 +24,6 @@ import { getTranslationsV2, getTranslationsV2ByContext, getTranslationsV2ByLanguage, - migrateTranslationsToV2, updateContextV2, upsertTranslationsV2, } from './v2_support'; @@ -171,82 +169,44 @@ const translationTypeToIndexedTranslation = (translations?: EnforcedWithId { - const currentTranslationData = await model.getById(translation._id); - if (!currentTranslationData) { - throw new Error('currentTranslationData does not exist'); - } - - const processedTranslation: TranslationType & { contexts: TranslationContext[] } = { - ...translation, - contexts: (translation.contexts || []).map(processContextValues), - }; - - await propagateTranslation(processedTranslation, currentTranslationData); - - (currentTranslationData?.contexts || []).forEach(context => { - const isPresentInTheComingData = processedTranslation.contexts.find( - _context => _context.id?.toString() === context.id?.toString() - ); - - if (!isPresentInTheComingData) { - processedTranslation.contexts.push(context); - } - }); - - return model.save({ - ...processedTranslation, - contexts: processedTranslation.contexts.map(processContextValues), - }); -}; - export default { prepareContexts, - async get(query: { locale?: LanguageISO6391; context?: string } = {}, selector = {}) { - const alreadyMigrated = await migrateTranslationsToV2(); - if (alreadyMigrated) { - const language = query.locale; - - if (query.context) { - return translationTypeToIndexedTranslation(await getTranslationsV2ByContext(query.context)); - } - - if (language) { - return translationTypeToIndexedTranslation(await getTranslationsV2ByLanguage(language)); - } + async get(query: { locale?: LanguageISO6391; context?: string } = {}) { + const language = query.locale; - return translationTypeToIndexedTranslation(await getTranslationsV2()); + if (query.context) { + return translationTypeToIndexedTranslation(await getTranslationsV2ByContext(query.context)); } - const { context, ...actualQuery } = query; - const translations = await model.get(actualQuery, { - ...selector, - ...(context ? { locale: 1 } : {}), - ...(context ? { contexts: { $elemMatch: { id: context } } } : {}), - }); + if (language) { + return translationTypeToIndexedTranslation(await getTranslationsV2ByLanguage(language)); + } - return translationTypeToIndexedTranslation(translations); + return translationTypeToIndexedTranslation(await getTranslationsV2()); }, - async oldSave(translation: TranslationType | IndexedTranslations) { + async save(translation: TranslationType | IndexedTranslations) { const translationToSave = { ...translation, contexts: translation.contexts && translation.contexts.map(processContextValues), } as TranslationType; - const [oldTranslationExists] = await model.get({ locale: translation.locale }); - if (oldTranslationExists) { - return update({ _id: oldTranslationExists._id, ...translation }); + if (!translation.locale) { + throw new Error('translation to save should have a locale'); } - return model.save(translationToSave); - }, + const [currentTranslationData] = await getTranslationsV2ByLanguage(translation.locale); - async save(translation: TranslationType | IndexedTranslations) { - const result = await this.oldSave(translation); - await upsertTranslationsV2([result]); - return result; + const processedTranslation: TranslationType & { contexts: TranslationContext[] } = { + ...translation, + contexts: (translation.contexts || []).map(processContextValues), + }; + + await propagateTranslation(processedTranslation, currentTranslationData); + + await upsertTranslationsV2([translationToSave]); + return translationToSave; }, async updateEntries( @@ -264,8 +224,7 @@ export default { const translationsToUpdate = await Promise.all( languagesToUpdate.map(async language => { - const [translation] = - (await getTranslationsV2ByLanguage(language)) || (await model.get({ locale: language })); + const [translation] = await getTranslationsV2ByLanguage(language); return translation; }) ); @@ -302,22 +261,6 @@ export default { translatedValues.push({ key, value: values[key] }); }); - const legacyTranslations = await model.get(); - - await Promise.all( - legacyTranslations.map(async translation => { - // eslint-disable-next-line no-param-reassign - translation.contexts = translation.contexts || []; - translation.contexts.push({ - id: id.toString(), - label: contextName, - values: translatedValues, - type, - }); - return this.oldSave(translation); - }) - ); - const result = await getTranslationsV2(); await upsertTranslationsV2( result.map(translation => { @@ -337,15 +280,6 @@ export default { }, async deleteContext(contextId: string) { - const results = await model.get(); - await Promise.all( - results.map(async translation => - model.save({ - ...translation, - contexts: (translation.contexts || []).filter(tr => tr.id !== contextId), - }) - ) - ); await deleteTranslationsByContextIdV2(contextId); return 'ok'; }, @@ -356,93 +290,23 @@ export default { deletedProperties: string[], values: IndexedContextValues ) { - const translatedValues: TranslationValue[] = []; - Object.keys(values).forEach(key => { - translatedValues.push({ key, value: values[key] }); - }); - - const [translations, defaultLanguage] = await Promise.all([ - model.get(), - settings.getDefaultLanguage(), - ]); - - await Promise.all( - translations.map(async translation => { - translation.contexts = translation.contexts || []; - const contextData = translation.contexts.find(c => c.id?.toString() === context.id); - if (!contextData) { - translation.contexts.push({ - id: context.id, - label: context.label, - values: translatedValues, - type: context.type, - }); - - return this.oldSave(translation); - } - - contextData.values = contextData.values || []; - contextData.values = contextData.values.filter( - v => !deletedProperties.includes(v.key || '') - ); - contextData.type = context.type; - - Object.keys(keyNamesChanges).forEach(originalKey => { - const newKey = keyNamesChanges[originalKey]; - contextData.values = contextData.values || []; - const value = contextData.values.find(v => v.key === originalKey); - if (value) { - value.key = newKey; - - if (translation.locale === defaultLanguage.key) { - value.value = newKey; - } - } - if (!value) { - contextData.values.push({ key: newKey, value: values[newKey] }); - } - }); - - Object.keys(values).forEach(key => { - contextData.values = contextData.values || []; - if (!contextData.values.find(v => v.key === key)) { - contextData.values.push({ key, value: values[key] }); - } - }); - - contextData.label = context.label; - - return this.oldSave(translation); - }) - ); await updateContextV2(context, keyNamesChanges, deletedProperties, values); return 'ok'; }, async addLanguage(newLanguage: LanguageISO6391) { - const [languageTranslationAlreadyExists] = await model.get({ locale: newLanguage }); - if (languageTranslationAlreadyExists) { + const [translations] = await getTranslationsV2ByLanguage(newLanguage); + if (translations.contexts?.length) { return Promise.resolve(); } const defaultLanguage = await settings.getDefaultLanguage(); - const [defaultTranslation] = await model.get({ locale: defaultLanguage.key }); - - const newLanguageTranslations = { - ...defaultTranslation, - _id: undefined, - locale: newLanguage, - contexts: (defaultTranslation.contexts || []).map(({ _id, ...context }) => context), - }; - await addLanguageV2(newLanguage, defaultLanguage.key); - return model.save(newLanguageTranslations); + return addLanguageV2(newLanguage, defaultLanguage.key); }, async removeLanguage(locale: LanguageISO6391) { - const result = await model.delete({ locale }); - await deleteTranslationsByLanguageV2(locale); - return result; + return deleteTranslationsByLanguageV2(locale); }, async importPredefined(locale: string) { diff --git a/app/api/i18n/translationsModel.ts b/app/api/i18n/translationsModel.ts deleted file mode 100644 index cbe2ecdb6f..0000000000 --- a/app/api/i18n/translationsModel.ts +++ /dev/null @@ -1,22 +0,0 @@ -import mongoose from 'mongoose'; -import { instanceModel } from 'api/odm'; -import { TranslationType } from 'shared/translationType'; - -const contextSchema = new mongoose.Schema({ - id: String, - label: String, - type: String, - values: [ - { - key: String, - value: String, - }, - ], -}); - -const translationSchema = new mongoose.Schema({ - locale: String, - contexts: [contextSchema], -}); - -export default instanceModel('translations', translationSchema); diff --git a/app/api/i18n/v2_support.ts b/app/api/i18n/v2_support.ts index 3f130831e2..b91314b61c 100644 --- a/app/api/i18n/v2_support.ts +++ b/app/api/i18n/v2_support.ts @@ -15,27 +15,13 @@ import { UpsertTranslationsService } from 'api/i18n.v2/services/UpsertTranslatio import { ValidateTranslationsService } from 'api/i18n.v2/services/ValidateTranslationsService'; import { EnforcedWithId, models } from 'api/odm'; import { DefaultSettingsDataSource } from 'api/settings.v2/database/data_source_defaults'; -import { tenants } from 'api/tenants'; -import { Db } from 'mongodb'; import { TranslationContext, TranslationType, TranslationValue } from 'shared/translationType'; import { LanguageISO6391 } from 'shared/types/commonTypes'; -import migration from '../i18n.v2/migrations'; import { IndexedContextValues } from './translations'; models.translationsV2 = () => new MongoTranslationsSyncDataSource(getConnection(), DefaultTransactionManager()); -const cleanUpV2Collections = async (db: Db) => { - try { - await db.collection('translationsV2').drop({}); - await db.collection('translationsV2_helper').drop(); - } catch (e) { - if (e.message !== 'ns not found') { - throw e; - } - } -}; - const flattenTranslations = (translation: TranslationType): CreateTranslationsData[] => { if (translation.contexts?.length) { return translation.contexts.reduce((flatTranslations, context) => { @@ -114,57 +100,49 @@ export const resultsToV1TranslationType = async ( }; export const createTranslationsV2 = async (translation: TranslationType) => { - if (tenants.current().featureFlags?.translationsV2) { - const transactionManager = new MongoTransactionManager(getClient()); - await new CreateTranslationsService( + const transactionManager = new MongoTransactionManager(getClient()); + await new CreateTranslationsService( + DefaultTranslationsDataSource(transactionManager), + new ValidateTranslationsService( DefaultTranslationsDataSource(transactionManager), - new ValidateTranslationsService( - DefaultTranslationsDataSource(transactionManager), - DefaultSettingsDataSource(transactionManager) - ), - transactionManager - ).create(flattenTranslations(translation)); - } + DefaultSettingsDataSource(transactionManager) + ), + transactionManager + ).create(flattenTranslations(translation)); }; export const upsertTranslationsV2 = async (translations: TranslationType[]) => { - if (tenants.current().featureFlags?.translationsV2) { - const transactionManager = new MongoTransactionManager(getClient()); - await new UpsertTranslationsService( + const transactionManager = new MongoTransactionManager(getClient()); + await new UpsertTranslationsService( + DefaultTranslationsDataSource(transactionManager), + DefaultSettingsDataSource(transactionManager), + new ValidateTranslationsService( DefaultTranslationsDataSource(transactionManager), - DefaultSettingsDataSource(transactionManager), - new ValidateTranslationsService( - DefaultTranslationsDataSource(transactionManager), - DefaultSettingsDataSource(transactionManager) - ), - transactionManager - ).upsert( - translations.reduce( - (flattened, t) => flattened.concat(flattenTranslations(t)), - [] - ) - ); - } + DefaultSettingsDataSource(transactionManager) + ), + transactionManager + ).upsert( + translations.reduce( + (flattened, t) => flattened.concat(flattenTranslations(t)), + [] + ) + ); }; export const deleteTranslationsByContextIdV2 = async (contextId: string) => { - if (tenants.current().featureFlags?.translationsV2) { - const transactionManager = new MongoTransactionManager(getClient()); - await new DeleteTranslationsService( - DefaultTranslationsDataSource(transactionManager), - transactionManager - ).deleteByContextId(contextId); - } + const transactionManager = new MongoTransactionManager(getClient()); + await new DeleteTranslationsService( + DefaultTranslationsDataSource(transactionManager), + transactionManager + ).deleteByContextId(contextId); }; -export const deleteTranslationsByLanguageV2 = async (language: string) => { - if (tenants.current().featureFlags?.translationsV2) { - const transactionManager = new MongoTransactionManager(getClient()); - return new DeleteTranslationsService( - DefaultTranslationsDataSource(transactionManager), - transactionManager - ).deleteByLanguage(language); - } +export const deleteTranslationsByLanguageV2 = async (language: LanguageISO6391) => { + const transactionManager = new MongoTransactionManager(getClient()); + return new DeleteTranslationsService( + DefaultTranslationsDataSource(transactionManager), + transactionManager + ).deleteByLanguage(language); }; export const getTranslationsV2ByContext = async (context: string) => @@ -174,16 +152,13 @@ export const getTranslationsV2ByContext = async (context: string) => ).getByContext(context) ); -export const getTranslationsV2ByLanguage = async (language: LanguageISO6391) => { - if (tenants.current().featureFlags?.translationsV2) { - return resultsToV1TranslationType( - new GetTranslationsService( - DefaultTranslationsDataSource(new MongoTransactionManager(getClient())) - ).getByLanguage(language), - language - ); - } -}; +export const getTranslationsV2ByLanguage = async (language: LanguageISO6391) => + resultsToV1TranslationType( + new GetTranslationsService( + DefaultTranslationsDataSource(new MongoTransactionManager(getClient())) + ).getByLanguage(language), + language + ); export const getTranslationsV2 = async () => resultsToV1TranslationType( @@ -198,71 +173,30 @@ export const updateContextV2 = async ( keysToDelete: string[], valueChanges: IndexedContextValues ) => { - if (tenants.current().featureFlags?.translationsV2) { - const transactionManager = new MongoTransactionManager(getClient()); - await new UpsertTranslationsService( + const transactionManager = new MongoTransactionManager(getClient()); + await new UpsertTranslationsService( + DefaultTranslationsDataSource(transactionManager), + DefaultSettingsDataSource(transactionManager), + new ValidateTranslationsService( DefaultTranslationsDataSource(transactionManager), - DefaultSettingsDataSource(transactionManager), - new ValidateTranslationsService( - DefaultTranslationsDataSource(transactionManager), - DefaultSettingsDataSource(transactionManager) - ), - transactionManager - ).updateContext(context, keyNamesChanges, valueChanges, keysToDelete); - } + DefaultSettingsDataSource(transactionManager) + ), + transactionManager + ).updateContext(context, keyNamesChanges, valueChanges, keysToDelete); }; export const addLanguageV2 = async ( newLanguage: LanguageISO6391, defaultLanguage: LanguageISO6391 ) => { - if (tenants.current().featureFlags?.translationsV2) { - const [defaultTranslation] = (await getTranslationsV2ByLanguage(defaultLanguage)) || []; - const newLanguageTranslations = { - ...defaultTranslation, - locale: newLanguage, - contexts: (defaultTranslation.contexts || []).map(({ _id, ...context }) => context), - }; - - await createTranslationsV2(newLanguageTranslations); - const [result] = (await getTranslationsV2ByLanguage(newLanguage)) || []; - return result; - } -}; - -export const migrateTranslationsToV2 = async () => { - const db = getConnection(); - - if (!tenants.current().featureFlags?.translationsV2) { - await cleanUpV2Collections(db); - return false; - } - - try { - await db - .collection('translationsV2_helper') - .createIndex({ migration_helper: 1 }, { unique: true }); - await db - .collection('translationsV2_helper') - .insertOne({ migration_helper: true, migrated: false }); - } catch (e) {} - - const migrationHelper = await db - .collection('translationsV2_helper') - .findOneAndUpdate({ migration_helper: true, migrated: false }, { $set: { migrating: true } }); - - if (migrationHelper.value?.migrating) { - return false; - } - - if (migrationHelper.value?.migrated || !migrationHelper.value) { - return true; - } - - await migration.up(db); - - await db - .collection('translationsV2_helper') - .findOneAndUpdate({ migration_helper: true }, { $set: { migrated: true, migrating: false } }); - return true; + const [defaultTranslation] = (await getTranslationsV2ByLanguage(defaultLanguage)) || []; + const newLanguageTranslations = { + ...defaultTranslation, + locale: newLanguage, + contexts: (defaultTranslation.contexts || []).map(({ _id, ...context }) => context), + }; + + await createTranslationsV2(newLanguageTranslations); + const [result] = (await getTranslationsV2ByLanguage(newLanguage)) || []; + return result; }; diff --git a/app/api/i18n.v2/migrations/index.js b/app/api/migrations/migrations/144-translations-to-translationsV2/index.js similarity index 99% rename from app/api/i18n.v2/migrations/index.js rename to app/api/migrations/migrations/144-translations-to-translationsV2/index.js index 1e0984bcb6..f5b8436f5c 100644 --- a/app/api/i18n.v2/migrations/index.js +++ b/app/api/migrations/migrations/144-translations-to-translationsV2/index.js @@ -48,7 +48,7 @@ const flattenTranslations = (translation, languagesByKeyContext) => { const newTranslationsCollection = 'translationsV2'; export default { - delta: 137, + delta: 144, name: 'translations to translations v2', diff --git a/app/api/i18n.v2/migrations/specs/fixtures.js b/app/api/migrations/migrations/144-translations-to-translationsV2/specs/fixtures.js similarity index 100% rename from app/api/i18n.v2/migrations/specs/fixtures.js rename to app/api/migrations/migrations/144-translations-to-translationsV2/specs/fixtures.js diff --git a/app/api/i18n.v2/migrations/specs/translations_to_translations_v2.spec.js b/app/api/migrations/migrations/144-translations-to-translationsV2/specs/translations_to_translations_v2.spec.js similarity index 99% rename from app/api/i18n.v2/migrations/specs/translations_to_translations_v2.spec.js rename to app/api/migrations/migrations/144-translations-to-translationsV2/specs/translations_to_translations_v2.spec.js index e6a476f489..1bf59eedfc 100644 --- a/app/api/i18n.v2/migrations/specs/translations_to_translations_v2.spec.js +++ b/app/api/migrations/migrations/144-translations-to-translationsV2/specs/translations_to_translations_v2.spec.js @@ -18,7 +18,7 @@ describe('migration set_up_new_relationship_collection', () => { }); it('should have a delta number', () => { - expect(migration.delta).toBe(137); + expect(migration.delta).toBe(144); }); it('should set up the relationships collection', async () => { diff --git a/app/api/search.v2/specs/fixturesSnippetsSearch.ts b/app/api/search.v2/specs/fixturesSnippetsSearch.ts index beb9164248..1af509e3f6 100644 --- a/app/api/search.v2/specs/fixturesSnippetsSearch.ts +++ b/app/api/search.v2/specs/fixturesSnippetsSearch.ts @@ -125,10 +125,6 @@ const fixturesSnippetsSearch: DBFixture = { }, }, ], - translations: [ - { locale: 'en', contexts: [] }, - { locale: 'es', contexts: [] }, - ], }; export { fixturesSnippetsSearch, entity1enId, entity2enId }; diff --git a/app/api/search.v2/specs/setupTestingEnvironment.ts b/app/api/search.v2/specs/setupTestingEnvironment.ts index 9b0c15e366..26746aa1aa 100644 --- a/app/api/search.v2/specs/setupTestingEnvironment.ts +++ b/app/api/search.v2/specs/setupTestingEnvironment.ts @@ -14,10 +14,6 @@ const setupTestingEnviroment = async (data: DBFixture, index?: string) => ], }, ], - translations: [ - { locale: 'en', contexts: [] }, - { locale: 'es', contexts: [] }, - ], }, index ); diff --git a/app/api/services/preserve/specs/fixtures.ts b/app/api/services/preserve/specs/fixtures.ts index 4a532929af..61b17e60b7 100644 --- a/app/api/services/preserve/specs/fixtures.ts +++ b/app/api/services/preserve/specs/fixtures.ts @@ -83,36 +83,4 @@ export const fixtures: DBFixture = { }, ], dictionaries: [{ _id: thesauri1Id, name: 'thesauri1', values: [] }], - translations: [ - { - _id: db.id(), - locale: 'en', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Value' }, - { key: 'Key2', value: 'Value2' }, - ], - }, - ], - }, - { - _id: db.id(), - locale: 'es', - contexts: [ - { - id: 'contextId', - label: 'contextLabel', - type: 'Entity', - values: [ - { key: 'Key', value: 'Valor' }, - { key: 'Key2', value: 'Valor2' }, - ], - }, - ], - }, - ], }; diff --git a/app/api/sync/processNamespaces.ts b/app/api/sync/processNamespaces.ts index 374ab87190..79a9710372 100644 --- a/app/api/sync/processNamespaces.ts +++ b/app/api/sync/processNamespaces.ts @@ -27,7 +27,6 @@ const namespaces = [ 'dictionaries', 'relationtypes', 'translationsV2', - 'translations', ]; type MethodNames = @@ -38,8 +37,7 @@ type MethodNames = | 'files' | 'dictionaries' | 'relationtypes' - | 'translationsV2' - | 'translations'; + | 'translationsV2'; interface Options { change: DataType; @@ -363,45 +361,6 @@ class ProcessNamespaces { return { skip: true }; } - private async translations() { - const data = await this.fetchData(); - const templatesData = await templatesModel.get({ - _id: { $in: this.templatesConfigKeys }, - }); - - data.contexts = data.contexts - .map((context: any) => { - if (this.assessTranslationApproved(context)) { - return context; - } - - if (this.templatesConfigKeys.includes(context.id.toString())) { - const contextTemplate = ensure>( - templatesData.find(t => t._id.toString() === context.id.toString()) - ); - const templateConfigProperties = this.templatesConfig[context.id.toString()].properties; - const templateTitle = contextTemplate.commonProperties?.find(p => p.name === 'title') - ?.label; - - const approvedKeys = [contextTemplate.name, templateTitle] - .concat( - (contextTemplate.properties || []) - .filter(p => templateConfigProperties.includes(p._id?.toString() || '')) - .map(p => p.label) - ) - .filter(k => Boolean(k)); - - context.values = (context.values || []).filter((v: any) => approvedKeys.includes(v.key)); - return context; - } - - return null; - }) - .filter((c: any) => Boolean(c)); - - return { data }; - } - public async process() { const { namespace } = this.change; let method: string = namespace; diff --git a/app/api/sync/specs/fixtures.ts b/app/api/sync/specs/fixtures.ts index c05a67a6da..42937749db 100644 --- a/app/api/sync/specs/fixtures.ts +++ b/app/api/sync/specs/fixtures.ts @@ -74,8 +74,6 @@ const hub1 = db.id(); const hub2 = db.id(); const hub3 = db.id(); -const translation1 = db.id(); - const settingsId = db.id(); const sessionsId = db.id(); @@ -318,12 +316,6 @@ const fixtures: DBFixture = { mongoId: sessionsId, deleted: false, }, - { - timestamp: 11500, - namespace: 'translations', - mongoId: translation1, - deleted: false, - }, { timestamp: 9000, namespace: 'files', @@ -632,78 +624,6 @@ const fixtures: DBFixture = { }), ], - translations: [ - { - _id: translation1, - locale: 'en', - contexts: [ - { - id: 'System', - values: [{ key: 'Sytem Key', value: 'System Value' }], - }, - { - type: 'Entity', - id: template1, - values: [ - { key: 'template1', value: 'template1T' }, - { key: 't1Property1L', value: 't1Property1T' }, - { key: 't1Relationship1L', value: 't1Relationship1T' }, - { key: 't1Relationship2L', value: 't1Relationship2T' }, - { key: 't1Thesauri2SelectL', value: 't1Thesauri2SelectT' }, - { key: 't1Thesauri3MultiSelectL', value: 't1Thesauri3MultiSelectT' }, - { key: 't1Relationship1', value: 't1Relationship1' }, - { key: 'Template Title', value: 'Template Title translated' }, - ], - }, - { - type: 'Entity', - id: template2, - values: [ - { key: 'template2', value: 'template2T' }, - { key: 't2Relationship2L', value: 't2Relationship2T' }, - { key: 'anotherL', value: 'anotherT' }, - ], - }, - { - type: 'Entity', - id: template3, - }, - { - type: 'Dictionary', - id: thesauri1, - }, - { - type: 'Dictionary', - id: thesauri2, - }, - { - type: 'Dictionary', - id: thesauri3, - values: [], - }, - { - type: 'Connection', - id: relationtype1, - values: [], - }, - { - type: 'Connection', - id: relationtype2, - }, - { - type: 'Connection', - id: relationtype4, - values: [], - }, - { - type: 'Connection', - id: relationtype7, - values: [], - }, - ], - }, - ], - settings: [ { _id: settingsId, diff --git a/app/api/sync/specs/syncWorker.spec.ts b/app/api/sync/specs/syncWorker.spec.ts index 9219386bb4..29a029b6e4 100644 --- a/app/api/sync/specs/syncWorker.spec.ts +++ b/app/api/sync/specs/syncWorker.spec.ts @@ -24,7 +24,6 @@ import { MongoTransactionManager } from 'api/common.v2/database/MongoTransaction import { getClient } from 'api/common.v2/database/getConnectionForCurrentTenant'; import { DefaultTranslationsDataSource } from 'api/i18n.v2/database/data_source_defaults'; import { CreateTranslationsService } from 'api/i18n.v2/services/CreateTranslationsService'; -import { GetTranslationsService } from 'api/i18n.v2/services/GetTranslationsService'; import { ValidateTranslationsService } from 'api/i18n.v2/services/ValidateTranslationsService'; import { DefaultSettingsDataSource } from 'api/settings.v2/database/data_source_defaults'; // eslint-disable-next-line node/no-restricted-import @@ -41,10 +40,8 @@ import { newDoc1, newDoc3, relationship9, - relationtype4, template1, template2, - thesauri1, thesauri1Value2, } from './fixtures'; @@ -407,70 +404,23 @@ describe('syncWorker', () => { await runAllTenants(); - await tenants.run(async () => { - const transactionManager = new MongoTransactionManager(getClient()); - const syncedTranslations = await new GetTranslationsService( - DefaultTranslationsDataSource(transactionManager) - ) - .getAll() - .all(); - - expect(syncedTranslations).toEqual([ - { - language: 'en', - key: 'System Key', - value: 'System Value', - context: { id: 'System', type: 'Uwazi UI', label: 'System' }, - }, - { - language: 'en', - key: 'template1', - value: 'template1T', - context: { id: template1.toString(), type: 'Entity', label: 'Entity' }, - }, - { - language: 'en', - key: 't1Property1L', - value: 't1Property1T', - context: { id: template1.toString(), type: 'Entity', label: 'Entity' }, - }, - { - language: 'en', - key: 't1Relationship1L', - value: 't1Relationship1T', - context: { id: template1.toString(), type: 'Entity', label: 'Entity' }, - }, - { - language: 'en', - key: 'Template Title', - value: 'Template Title translated', - context: { id: template1.toString(), type: 'Entity', label: 'Entity' }, - }, - ]); - }, 'target1'); - }); - - it('should syncronize translations that match configured properties', async () => { - await runAllTenants(); await tenants.run(async () => { const syncedTranslations = await translations.get({}); expect(syncedTranslations).toEqual([ { - __v: 0, - _id: expect.anything(), contexts: [ { - _id: expect.anything(), id: 'System', + label: 'System', type: 'Uwazi UI', values: { - 'Sytem Key': 'System Value', + 'System Key': 'System Value', }, }, { - _id: expect.anything(), id: template1.toString(), type: 'Entity', + label: 'Entity', values: { 'Template Title': 'Template Title translated', t1Property1L: 't1Property1T', @@ -478,18 +428,6 @@ describe('syncWorker', () => { template1: 'template1T', }, }, - { - _id: expect.anything(), - id: thesauri1.toString(), - type: 'Dictionary', - values: {}, - }, - { - _id: expect.anything(), - id: relationtype4.toString(), - type: 'Connection', - values: {}, - }, ], locale: 'en', }, diff --git a/app/api/templates/specs/v2_newRelationshipProperties.spec.ts b/app/api/templates/specs/v2_newRelationshipProperties.spec.ts index 8413135eda..b05743abcf 100644 --- a/app/api/templates/specs/v2_newRelationshipProperties.spec.ts +++ b/app/api/templates/specs/v2_newRelationshipProperties.spec.ts @@ -102,7 +102,6 @@ const fixtures: DBFixture = { }, }, ], - translations: [], }; const newQueryInput = [ diff --git a/app/api/tenants/tenantContext.ts b/app/api/tenants/tenantContext.ts index 9fdd865796..223118d8d9 100644 --- a/app/api/tenants/tenantContext.ts +++ b/app/api/tenants/tenantContext.ts @@ -13,7 +13,6 @@ export type Tenant = { activityLogs: string; featureFlags?: { s3Storage?: boolean; - translationsV2?: boolean; }; }; diff --git a/app/api/thesauri/specs/fixtures.ts b/app/api/thesauri/specs/fixtures.ts index a89fa81ec9..b3436b10ed 100644 --- a/app/api/thesauri/specs/fixtures.ts +++ b/app/api/thesauri/specs/fixtures.ts @@ -1,4 +1,3 @@ -import { fixturesTranslationsV2ToTranslationsLegacy } from 'api/i18n/specs/fixturesTranslationsV2ToTranslationsLegacy'; import { getFixturesFactory } from 'api/utils/fixturesFactory'; import { DBFixture, testingDB } from 'api/utils/testing_db'; @@ -139,7 +138,7 @@ const fixtures: DBFixture = { ], }, ], - translations: fixturesTranslationsV2ToTranslationsLegacy([ + translationsV2: [ createTranslationDBO('Parent', 'Parent', 'en', { id: dictionaryId, type: 'Thesaurus', @@ -181,7 +180,7 @@ const fixtures: DBFixture = { type: 'Thesaurus', label: 'Dictionary', }), - ]), + ], }; export { diff --git a/app/api/topicclassification/specs/fixtures.ts b/app/api/topicclassification/specs/fixtures.ts index a336753900..c99067c03c 100644 --- a/app/api/topicclassification/specs/fixtures.ts +++ b/app/api/topicclassification/specs/fixtures.ts @@ -106,7 +106,6 @@ const fixtures: DBFixture = { languages: [{ key: 'en', label: 'English', default: true }], }, ], - translations: [{ locale: 'en', contexts: [] }], }; export default fixtures; diff --git a/app/api/utils/testing_db.ts b/app/api/utils/testing_db.ts index cfb982a182..19c64eee08 100644 --- a/app/api/utils/testing_db.ts +++ b/app/api/utils/testing_db.ts @@ -1,10 +1,8 @@ import { setupTestUploadedPaths } from 'api/files/filesystem'; import { TranslationDBO } from 'api/i18n.v2/schemas/TranslationDBO'; -import { migrateTranslationsToV2 } from 'api/i18n/v2_support'; import { DB } from 'api/odm'; import { models } from 'api/odm/model'; import { RelationshipDBOType } from 'api/relationships.v2/database/schemas/relationshipTypes'; -import { tenants } from 'api/tenants'; import { UserInContextMockFactory } from 'api/utils/testingUserInContext'; import { Db, ObjectId } from 'mongodb'; import mongoose, { Connection } from 'mongoose'; @@ -91,6 +89,7 @@ const testingDB: { * @deprecated */ clearAllAndLoad: (fixtures: DBFixture, elasticIndex?: string) => Promise; + createIndices: () => Promise; setupFixturesAndContext: ( fixtures: DBFixture, elasticIndex?: string, @@ -151,22 +150,9 @@ const testingDB: { optionalMongo = DB.connectionForDB(dbName).db; } await fixturer.clearAllAndLoad(optionalMongo || mongodb, fixtures); - this.UserInContextMockFactory.mockEditorUser(); + await this.createIndices(); - try { - if ( - tenants.current().featureFlags?.translationsV2 && - !expect.getState().testPath?.includes('api/migrations') && - Object.keys(fixtures).includes('translations') && - !Object.keys(fixtures).includes('translationsV2') - ) { - await migrateTranslationsToV2(); - } - } catch (e) { - if (!e.message.match('nonexistent async')) { - throw e; - } - } + this.UserInContextMockFactory.mockEditorUser(); if (elasticIndex) { testingTenants.changeCurrentTenant({ indexName: elasticIndex }); @@ -174,6 +160,16 @@ const testingDB: { } }, + async createIndices() { + const newTranslationsCollection = 'translationsV2'; + + await mongodb + .collection(newTranslationsCollection) + .createIndex({ language: 1, key: 1, 'context.id': 1 }, { unique: true }); + + await mongodb.collection(newTranslationsCollection).createIndex({ 'context.id': 1, key: 1 }); + }, + /** * @deprecated */ From d0a3ebb48da0dd303d27f222d61a55dccc122034 Mon Sep 17 00:00:00 2001 From: Daneryl Date: Thu, 28 Sep 2023 09:31:13 +0200 Subject: [PATCH 2/2] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3da9a51ccf..4d8622cb8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uwazi", - "version": "1.135.0", + "version": "1.135.1", "description": "Uwazi is a free, open-source solution for organising, analysing and publishing your documents.", "keywords": [ "react"