From beab5c704f42b5d111b6308c89b41abe343e31e0 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Tue, 9 Feb 2021 09:46:33 +0100 Subject: [PATCH] fix: synchronize sources Translation units with manually defined ids can have their source changed. In order to detect that, the sources are compared on startup and updated accordingly. --- server/models/translation-target.ts | 8 +++- .../translation-target-registry.spec.ts | 38 +++++++++++++++++++ .../translation-target-registry.ts | 25 ++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/server/models/translation-target.ts b/server/models/translation-target.ts index f796cc0..dfc223b 100644 --- a/server/models/translation-target.ts +++ b/server/models/translation-target.ts @@ -92,8 +92,12 @@ export class TranslationTarget { } private _calculateDistance(a: TranslationTargetUnit, b: TranslationTargetUnit) { - const sourceA = a.source.replace(/\s+/g, ' ').trim(); - const sourceB = b.source.replace(/\s+/g, ' ').trim(); + const sourceA = this._normalizeWhitespace(a.source); + const sourceB = this._normalizeWhitespace(b.source); return levenshtein(sourceA, sourceB); } + + private _normalizeWhitespace(value: string) { + return value.replace(/\s+/g, ' ').trim(); + } } diff --git a/server/persistence/translation-target-registry.spec.ts b/server/persistence/translation-target-registry.spec.ts index c5cf603..da31738 100644 --- a/server/persistence/translation-target-registry.spec.ts +++ b/server/persistence/translation-target-registry.spec.ts @@ -78,4 +78,42 @@ describe('TranslationTargetRegistry', () => { const target = registry.register('de', new Map(), baseHref); expect(target.baseHref).toEqual(baseHref); }); + + it('should update stale source with only whitespace change', () => { + const sourceUnit = MOCK_SOURCE.units[0]; + const sourceWithWhitespace = sourceUnit.source + ' '; + let unit: TranslationTargetUnit = { + ...sourceUnit, + source: sourceWithWhitespace, + target: sourceWithWhitespace, + state: 'translated', + }; + expect(unit.source).toEqual(sourceWithWhitespace); + const target = registry.register( + 'de', + new Map().set(unit.id, unit) + ); + unit = target.unitMap.get(unit.id)!; + expect(unit.source).toEqual(sourceUnit.source); + expect(unit.state).toEqual('translated'); + }); + + it('should update stale source and state with textual change', () => { + const sourceUnit = MOCK_SOURCE.units[0]; + const sourceWithTextChange = sourceUnit.source + ' test'; + let unit: TranslationTargetUnit = { + ...sourceUnit, + source: sourceWithTextChange, + target: sourceWithTextChange, + state: 'translated', + }; + expect(unit.source).toEqual(sourceWithTextChange); + const target = registry.register( + 'de', + new Map().set(unit.id, unit) + ); + unit = target.unitMap.get(unit.id)!; + expect(unit.source).toEqual(sourceUnit.source); + expect(unit.state).toEqual('initial'); + }); }); diff --git a/server/persistence/translation-target-registry.ts b/server/persistence/translation-target-registry.ts index ff8376a..7b8e04d 100644 --- a/server/persistence/translation-target-registry.ts +++ b/server/persistence/translation-target-registry.ts @@ -22,6 +22,7 @@ export class TranslationTargetRegistry { target.changed .pipe(debounceTime(300)) .subscribe(() => this._persistenceStrategy.update(target)); + this._synchronizeSources(target); this._targets.set(language, target); return target; } @@ -47,4 +48,28 @@ export class TranslationTargetRegistry { values(): TranslationTarget[] { return Array.from(this._targets.values()); } + + private _synchronizeSources(target: TranslationTarget) { + let changeRequired = false; + for (const unit of target.units) { + const sourceUnit = target.source.unitMap.get(unit.id)!; + if (unit.source !== sourceUnit.source) { + if ( + this._normalizeWhitespace(unit.source) !== this._normalizeWhitespace(sourceUnit.source) + ) { + unit.state = 'initial'; + } + unit.source = sourceUnit.source; + changeRequired = true; + } + } + + if (changeRequired) { + this._persistenceStrategy.update(target); + } + } + + private _normalizeWhitespace(value: string) { + return value.replace(/\s+/g, ' ').trim(); + } }