Skip to content

Releases: ngx-translate/core

v18.0.0

09 Jun 14:46

Choose a tag to compare

@ngx-translate/core@18.0.0 and @ngx-translate/http-loader@18.0.0 are now stable on npm (latest).

v18 is the major API-cleanup release: standalone providers everywhere, signal-based internals, the defaultfallback rename finalized, and the deprecated surface removed. It also resolves three long-standing semantic gotchas and baselines the workspace on Angular 22 / TypeScript 6.0.

Highlights

  • Standalone-first setup. TranslateModule is gone — use provideTranslateService() / provideChildTranslateService() (works in standalone and NgModule apps).
  • New *translateBlock="let t" structural directive for cleaner template translations.
  • New isLoading: Signal<boolean> — true while any use() load is in flight; read it for language-switching spinners.
  • Isolated subtrees are now truly isolated — own events, lookups, and language state.
  • Angular 18–22 supported (16 and 17 dropped); built and tested against Angular 18/19/20/21/22.

Breaking changes — required edits

TranslateModule removed. Replace TranslateModule.forRoot({...}) / forChild({...}) with provideTranslateService({...}) / provideChildTranslateService({...}). The pipe, directive, and service are standalone.

Deprecated default* symbols removed — rename:

Removed Replacement
defaultLang fallbackLang
setDefaultLang() setFallbackLang()
getDefaultLang() getFallbackLang()
onDefaultLangChange onFallbackLangChange
DefaultLangChangeEvent FallbackLangChangeEvent
langs getLangs()
setValue() (util) insertValue()

Also removed: useDefaultLang and defaultLanguage config fields (along with TranslateModule).

Deprecated (still works, warns once): using element text content as a key (<span translate>Hello</span>). Use [translate]="'KEY'", the translate pipe, or *translateBlock. It will be removed next major.

Potentially breaking — low impact (behavior changes)

  • A failed use() no longer mutates state. On loader failure, currentLang() / lastUseLanguage stay at the prior value instead of switching to the failed language. Use isLoading() or the returned Observable's error channel to drive switching UI.
  • Isolated subtrees no longer see ancestor translationChange$ events, nor borrow keys from outer scopes. Isolation now means own events + own lookups + own language state. If you wanted shared translations with subtree-scoped state, use provideChildTranslateService({ extend: true }).
  • instant() "unloaded language" warning is deduplicated per isolated subtree (was once per service instance).
  • ITranslateService gains isLoading: Signal<boolean>. If you mock it via implements/extends ITranslateService, add isLoading = signal(false).asReadonly(). See the "Mocking TranslateService" recipe in the README.
  • Loader errors are now logged instead of silently swallowed.

Migration

Full step-by-step guide: https://ngx-translate.org → Getting Started → Migration Guide.


Angular compatibility: 18, 19, 20, 21, 22 · TypeScript: 6.0 · RxJS: ≥7

v18.0.0-rc.1

07 May 07:11

Choose a tag to compare

v18.0.0-rc.1 Pre-release
Pre-release

💥 npm install fix for the RC pair (reported by @Julien-Marcou)
The http-loader's peer dependency on @ngx-translate/core was ">=18", which npm's semver doesn't match against pre-release versions. Installing both packages at 18.0.0-rc.0 failed with ETARGET. The peer dep is now ">=18.0.0-rc.1", so RC combinations install cleanly — no more overrides workaround needed.

✨ Function-form parameters for translate() (suggested by @Silas770)
TranslateService.translate() and the standalone translate() function now accept arrow functions alongside plain values and Signals. No more separate computed() wrapper for derived inputs:

// Before — needed an extra computed()
model = signal({ currentKey: 'HELLO' });
keyComputed = computed(() => this.model().currentKey);
greeting = translate(this.keyComputed);

// Now — pass the arrow directly
model = signal({ currentKey: 'HELLO' });
greeting = translate(() => this.model().currentKey);

Signals still work — Signal<T> is structurally () => T, so existing signal-based call sites compile and run unchanged. The key parameter also now accepts string[] for multi-key lookup, matching get(), instant(), and stream().

Thanks

Thanks to @Julien-Marcou and @Silas770 for the feedback — both reports are addressed in this release.

Keep the feedback coming!

v18.0.0-rc.0

07 May 07:08

Choose a tag to compare

v18.0.0-rc.0 Pre-release
Pre-release

What's new in @ngx-translate/core v18-rc.0

v18 rebuilds ngx-translate on Angular Signals. The library is now fully standalone — TranslateModule is gone — and gains hierarchical service isolation, a block directive for templates, and per-call language selection. Existing template syntax (| translate, [translate]) works as before.

Requires Angular 18 or later. The library uses effect(), takeUntilDestroyed(), and stable signal APIs that are only available from Angular 18+.

Highlights

  • Signals everywherecurrentLang, fallbackLang, internal state management, the pipe, and the directive are all signal-driven. The new standalone translate() function returns a reactive Signal — no subscriptions, no cleanup.
  • *translateBlock directive — Exposes a typed translation function to a template block. Cleaner than chaining pipes when you need multiple keys in one place.
  • Hierarchical servicesprovideChildTranslateService() creates an isolated child with its own store and loader. Translations resolve child-first, then walk up to the parent. provideTranslateService() creates a fully independent root.
  • Per-call language overridetranslate(), get(), instant(), stream(), and getParsedResult() accept an optional lang parameter to bypass the current/fallback chain.

BREAKING CHANGES

TranslateModule removed — Impact: High

TranslateModule, TranslateModule.forRoot(), and TranslateModule.forChild() have been removed. Use the standalone provider functions and import the pipe/directive directly:

// v17
@NgModule({
    imports: [
        TranslateModule.forRoot({
            loader: { provide: TranslateLoader, useClass: MyLoader },
            compiler: { provide: TranslateCompiler, useClass: MyCompiler },
            parser: { provide: TranslateParser, useClass: MyParser },
            missingTranslationHandler: { provide: MissingTranslationHandler, useClass: MyHandler },
            defaultLanguage: "en",
        }),
    ],
})

// v18 — in bootstrapApplication() or route config
providers: [
    provideTranslateService({
        loader: provideTranslateLoader(MyLoader),
        compiler: provideTranslateCompiler(MyCompiler),
        parser: provideTranslateParser(MyParser),
        missingTranslationHandler: provideMissingTranslationHandler(MyHandler),
        fallbackLang: "en",
    }),
]

// Component imports (replace TranslateModule in component imports)
@Component({
    imports: [TranslatePipe, TranslateDirective],
})

currentLang is now a Signal — Impact: High

TranslateService.currentLang was a plain string getter in v17. In v18 it returns a Signal<Language | null>. Any code that reads it as a string must call the signal:

// v17
if (service.currentLang === "en") { ... }

// v18
if (service.currentLang() === "en") { ... }

The upside: currentLang now works directly in computed() and effect(), and Angular's template change detection tracks it automatically — no manual subscriptions needed.

getCurrentLang() can return null — Impact: Medium

The return type changed from Language to Language | null. Before any language is set, it returns null.

Deprecated defaultLang aliases removed — Impact: Medium

defaultLang, setDefaultLang(), getDefaultLang(), and onDefaultLangChange have been removed. These were deprecated v17 aliases for the fallback equivalents:

  • defaultLangfallbackLang signal
  • setDefaultLang(lang)setFallbackLang(lang)
  • getDefaultLang()getFallbackLang()
  • onDefaultLangChangeonFallbackLangChange

Deprecated config options useDefaultLang and defaultLanguage removed — Impact: Medium

These v16-era compatibility options have been removed from RootTranslateServiceConfig. Use fallbackLang instead.

extend config replaced by root/child hierarchy — Impact: Medium

The extend: true config option has been removed. Use provideChildTranslateService() instead — it automatically creates a non-root service. Child services delegate language selection to the root and maintain their own translation loader.

// v17
TranslateModule.forChild({
    loader: { provide: TranslateLoader, useClass: FeatureLoader },
    extend: true,
})

// v18
provideChildTranslateService({
    loader: provideTranslateLoader(FeatureLoader),
})

Child services now have their own store — Impact: Medium

provideChildTranslateService() now creates its own TranslateStore instance with a full set of default plugin providers. Child services look up translations in their own store first, then walk up the parent chain — so lazy-loaded modules can still access translations provided by the parent, while local translations take precedence. Child translations never write to the parent store, keeping scopes cleanly separated. To create a fully independent service (no parent fallback), use provideTranslateService() — which creates a root-level service with its own language state and store.

Mixed child content in [translate] elements — Impact: Medium

The directive now sets el.textContent directly for explicit-key bindings, replacing all child content. In v17, individual text nodes were updated, potentially preserving sibling HTML. If you have mixed content inside translated elements, restructure:

<!-- This will lose the <b> in v18 -->
<span [translate]="'GREETING'"><b>Bold</b></span>

<!-- Instead, restructure -->
<span [translate]="'GREETING'"></span>

setValue() removed — Impact: Low

The deprecated setValue() utility function has been removed. Use insertValue() instead. Note that insertValue() returns a new object rather than mutating in place:

// v17 (mutation)
setValue(obj, "a.b", 42);

// v18 (immutable — assign the return value)
obj = insertValue(obj, "a.b", 42);

TranslateStore rewritten with Angular Signals — Impact: Low

The store's internal state is now held in WritableSignals with public read-only Signal accessors:

  • translations: Signal<Record<Language, InterpolatableTranslationObject>>
  • languages: Signal<Language[]>
  • lastTranslationChange: Signal<TranslationChangeEvent | null>

The translationChange$ observable is still available for push-based subscribers.

All state updates are now immutable — each setTranslations() or deleteTranslations() call produces a new object reference, enabling proper signal change detection.

Language management moved from store to service — Impact: Low

currentLang, fallbackLang, and their associated getters, setters, and observables (onLangChange, onFallbackLangChange) have been removed from TranslateStore. These responsibilities now live in TranslateService.

getTranslation(key) removed from store — Impact: Low

The convenience method that looked up a key against current + fallback language has been removed because the store no longer tracks language selection. Use TranslateService.instant(key) or store.getTranslationValue(language, key).

getValue()getTranslationValue() — Impact: Low

The protected getValue(language, key) method is now public and renamed to getTranslationValue(language, key).

onTranslationChangetranslationChange$ — Impact: Low

The observable getter onTranslationChange has been replaced by the translationChange$ property. For template-reactive reads, use the lastTranslationChange signal instead.

langs getter removed — Impact: Low

Replace translateService.langs with translateService.getLangs().

currentLoader and compiler are now protected — Impact: Low

These properties are no longer part of the public API. Use the service's public methods instead.

Empty keys no longer throw — Impact: Low

get("") and instant("") now return empty strings instead of throwing an Error. Code that relied on catching those exceptions needs adjustment.

setTranslation() no longer auto-merges with extend — Impact: Low

In v17, setTranslation() would force-merge when the service had extend: true. In v18, merging only happens when shouldMerge is explicitly true.

DefaultLangChangeEvent type removed — Impact: Low

The deprecated type alias has been removed. Use FallbackLangChangeEvent directly.

TranslatePipe rewritten with signals — Impact: Low

The pipe is now powered by TranslateService.translate() signals internally. All manual RxJS subscriptions, ChangeDetectorRef.markForCheck(), and OnDestroy cleanup are gone. Template usage is unchanged — {{ 'KEY' | translate }} works exactly as before. Previously-public internals (lastKey, lastParams, updateValue(), subscription fields) are removed.

TranslateDirective rewritten with signals — Impact: Low

The directive now uses WritableSignals for key/params and an effect() for DOM writes when using explicit key binding ([translate]="'KEY'"). The content-as-key path is delegated to ContentKeyHandler (deprecated). Manual subscriptions replaced by onTranslationRefresh + takeUntilDestroyed. Previously-public methods (checkNodes(), updateValue(), getContent(), setContent()) are removed.

Internal

  • Plugin base classes (TranslateLoader, TranslateCompiler, TranslateParser, MissingTranslationHandler) are unchanged in API and behavior
  • InterpolatableTranslationObject type extracted from translate.service.ts into translate.service.interface.ts (no consumer impact)

New Features

Hierarchical services with isolation

provideChildTranslateService() creates a child service with its own TranslateStore and loader, scoped to a lazy-loaded module or component subtree. Child services delegate language selection (current/fallback lang) to the root, but l...

Read more

v17.0.0

28 Jul 17:48

Choose a tag to compare

What's Changed

See the migration guide for all changes and how to migrate from v16 -> v17:
https://ngx-translate.org/getting-started/migration-guide/

New Contributors

Full Changelog: v16.0.4...v17.0.0

v16.0.4

19 Dec 10:05

Choose a tag to compare

What's Changed

  • Updated for Angular 19
  • Fix: null values are now skipped in translations instead of creating empty objects
  • Code improvements, lint warnings
  • Chore: Fixed in the README

New Contributors

Full Changelog: v16.0.3...v16.0.4

v16.0.3

04 Nov 10:01

Choose a tag to compare

Documentation and Guides

Features

  • core: Support for Standalone components in Angular:
  • core: Parameters and return values now have explicit types instead of any. Due to TypeScript
    limitations, any is still partially required in recursive type definitions.
  • core: Introduced _(id) to tag translations for automated extraction from source code.
  • core/http-loader: Resolved ESLint warnings, improved overall code quality.
  • core/http-loader: Enhanced documentation available at ngx-translate.org.
  • core/http-loader: Set MIT License for npm modules.
  • core/http-loader: Implemented GitHub Actions for continuous integration.

Fixes

Deprecations

v15.0.0

09 May 21:44
9c3244d

Choose a tag to compare

15.0.0 (2023-05-09)

Features

  • core/http-loader: add support for Angular v16
  • core/http-loader: the code for both core & http-loader is now managed with Bit

BREAKING CHANGES

  • core/http-loader: ngx-translate is now built for Angular 16, if you use Angular 15 or below please refer to the compatibility table to know which version you can install.

v14.0.0

08 Nov 11:38
3a4c7ee

Choose a tag to compare

14.0.0 (2021-11-08)

Features

  • core/http-loader: add support for Angular v13 and RxJS 7 (3a4c7ee), closes #1345
  • http-loader: the code for http-loader has been moved to this repository

BREAKING CHANGES

  • core/http-loader: ngx-translate is now built for Angular 13, if you use Angular 12 or below please refer to the compatibility table to know which version you can install.
    The library is now distributed only for ivy as the view engine is no longer supported by Angular.

v13.0.0

26 Jun 13:56
efcb4f4

Choose a tag to compare

13.0.0 (2020-06-26)

Features

  • core: update dependencies to Angular v10 (efcb4f4), closes #1225

BREAKING CHANGES

  • core: ngx-translate is now built for Angular 10, if you use Angular 9 or below please refer to the compatibility table to know which version you can install

v12.1.2

27 Feb 19:47
b92a433

Choose a tag to compare

12.1.2 (2020-02-27)

Bug Fixes

  • core: remove semantic-release from the dependencies (b92a433), closes #1171