perf: memoize TranslatePipe instead of re-walking translations every CD cycle
pure:false stays (needed so language switches propagate without touching every | translate template call site), but repeat calls with unchanged key/params/language now hit a Map lookup instead of re-splitting the key and re-walking the translation object tree. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,42 @@
|
|||||||
import { Pipe, PipeTransform, inject } from '@angular/core';
|
import { Pipe, PipeTransform, inject } from '@angular/core';
|
||||||
import { TranslateService } from './translate.service';
|
import { TranslateService } from './translate.service';
|
||||||
|
import { LanguageService } from '../services/language.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stays impure (must re-run every CD cycle so a live language switch
|
||||||
|
* updates every binding without touching hundreds of `| translate`
|
||||||
|
* template call sites to pass the language explicitly as a pure-pipe
|
||||||
|
* argument). Memoized per-instance instead: repeat calls with the same
|
||||||
|
* key/params/language - the overwhelming majority of CD cycles, since
|
||||||
|
* nothing actually changed - hit a Map lookup instead of re-walking the
|
||||||
|
* translation tree and re-running the interpolation regex.
|
||||||
|
*/
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'translate',
|
name: 'translate',
|
||||||
pure: false,
|
pure: false,
|
||||||
})
|
})
|
||||||
export class TranslatePipe implements PipeTransform {
|
export class TranslatePipe implements PipeTransform {
|
||||||
private translateService = inject(TranslateService);
|
private translateService = inject(TranslateService);
|
||||||
|
private langService = inject(LanguageService);
|
||||||
|
|
||||||
|
private lastLang = '';
|
||||||
|
private readonly cache = new Map<string, string>();
|
||||||
|
|
||||||
transform(key: string, params?: Record<string, string | number>): string {
|
transform(key: string, params?: Record<string, string | number>): string {
|
||||||
return this.translateService.t(key, params);
|
const lang = this.langService.currentLanguage();
|
||||||
|
if (lang !== this.lastLang) {
|
||||||
|
this.lastLang = lang;
|
||||||
|
this.cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const cacheKey = params ? `${key}::${JSON.stringify(params)}` : key;
|
||||||
|
const cached = this.cache.get(cacheKey);
|
||||||
|
if (cached !== undefined) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = this.translateService.t(key, params);
|
||||||
|
this.cache.set(cacheKey, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user