Skip to content

Pre-compile translations at build time

setTranslation() runs the configured TranslateCompiler over the values you pass. For a small app, this is invisibly fast. For a large translations bundle on a cold-start-sensitive page, the compile pass can matter.

setCompiledTranslation() lets you skip the runtime compiler if you’ve already compiled the translations at build time:

this.translate.setCompiledTranslation("en", {
welcome: "Welcome",
greeting: (params) => `Hello ${params["name"]}`,
});

The function-valued entries are interpolation functions in their final form. v18 calls them directly when the key is requested.

Use setCompiledTranslation() if:

  • Your translations bundle is large (≥ ~1000 keys with interpolation).
  • Cold start time matters (PWA, embedded widget, SSR-hydrated app).
  • You have a build step that can produce interpolation functions.

For most apps, the standard setTranslation() path is fine — the runtime compiler is cheap.

The build step’s job is to turn:

{ "greeting": "Hello {{name}}" }

into:

{ greeting: (params) => `Hello ${params["name"]}` }

The exact tooling depends on your stack (a small Node script, an Angular build plugin, a Vite transformer). Once built, import the result and feed it to setCompiledTranslation():

app.config.ts
import { ApplicationConfig, APP_INITIALIZER, inject } from "@angular/core";
import { provideTranslateService, TranslateService } from "@ngx-translate/core";
import enCompiled from "./i18n/en.compiled";
export const appConfig: ApplicationConfig = {
providers: [
provideTranslateService({ fallbackLang: "en" }),
{
provide: APP_INITIALIZER,
multi: true,
useFactory: () => {
const translate = inject(TranslateService);
return () => {
translate.setCompiledTranslation("en", enCompiled);
return translate.use("en");
};
},
},
],
};

use("en") resolves immediately (no HTTP fetch, no compile pass) because the translations are already in the store.

To prevent any accidental re-compile pass on values that arrive via setTranslation() later (e.g. a runtime extension), provide a no-op compiler.

v18 ships one out of the box — TranslateNoOpCompiler:

import {
provideTranslateService,
provideTranslateCompiler,
TranslateNoOpCompiler,
} from "@ngx-translate/core";
provideTranslateService({
fallbackLang: "en",
compiler: provideTranslateCompiler(TranslateNoOpCompiler),
});

If you want your own subclass (e.g. to log or count compile calls), the shape matches the abstract TranslateCompiler base class exactly — note that compileTranslations() takes a TranslationObject and returns an InterpolatableTranslationObject:

import {
TranslateCompiler,
Language,
TranslationObject,
InterpolatableTranslationObject,
InterpolateFunction,
} from "@ngx-translate/core";
class NoopTranslateCompiler extends TranslateCompiler {
compile(value: string, _lang: Language): string | InterpolateFunction {
return value;
}
compileTranslations(
translations: TranslationObject,
_lang: Language,
): InterpolatableTranslationObject {
return translations as InterpolatableTranslationObject;
}
}

The cast is needed because the base class widens its return type — for a no-op, we’re asserting “these strings are already in their final form”.

Register it alongside the service:

provideTranslateService({
fallbackLang: "en",
compiler: provideTranslateCompiler(() => new NoopTranslateCompiler()),
});
Imprint Privacy