Skip to content

Commit b54b990

Browse files
Update dependency @ngx-translate/core to v17 (#214)
* Update dependency @ngx-translate/core to v17 * fix types and deprecated stuff * convert to standalone * update readme --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: larscom <[email protected]>
1 parent edd7e1c commit b54b990

13 files changed

+129
-158
lines changed

README.md

Lines changed: 42 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
![npm](https://img.shields.io/npm/dw/@larscom/ngx-translate-module-loader)
55
[![license](https://img.shields.io/npm/l/@larscom/ngx-translate-module-loader.svg)](https://github.com/larscom/ngx-translate-module-loader/blob/main/LICENSE)
66

7-
87
> Highly configurable and flexible translations loader for [@ngx-translate/core](https://github.com/ngx-translate/core). Fetch multiple translations (http only) and configure them to your needs. Each translation file has it's own **namespace** out of the box so the key/value pairs do not conflict with each other.
98
109
### [View on StackBlitz](https://stackblitz.com/edit/ngx-translate-module-loader)
@@ -21,52 +20,36 @@ npm i @larscom/ngx-translate-module-loader
2120

2221
## Usage
2322

24-
Create an exported `moduleHttpLoaderFactory` function
23+
Import the `provideModuleTranslateLoader` function and provide the options.
2524

2625
```ts
27-
import { NgModule } from '@angular/core'
28-
import { BrowserModule } from '@angular/platform-browser'
29-
import { HttpClientModule, HttpClient } from '@angular/common/http'
30-
import { TranslateModule, TranslateLoader } from '@ngx-translate/core'
31-
import { ModuleTranslateLoader, IModuleTranslationOptions } from '@larscom/ngx-translate-module-loader'
32-
import { AppComponent } from './app'
33-
34-
export function moduleHttpLoaderFactory(http: HttpClient) {
35-
const baseTranslateUrl = './assets/i18n'
36-
37-
const options: IModuleTranslationOptions = {
38-
modules: [
39-
// final url: ./assets/i18n/en.json
40-
{ baseTranslateUrl },
41-
// final url: ./assets/i18n/feature1/en.json
42-
{ baseTranslateUrl, moduleName: 'feature1' },
43-
// final url: ./assets/i18n/feature2/en.json
44-
{ baseTranslateUrl, moduleName: 'feature2' }
45-
]
46-
}
47-
48-
return new ModuleTranslateLoader(http, options)
49-
}
50-
51-
@NgModule({
52-
imports: [
53-
BrowserModule,
54-
HttpClientModule,
55-
TranslateModule.forRoot({
56-
loader: {
57-
provide: TranslateLoader,
58-
useFactory: moduleHttpLoaderFactory,
59-
deps: [HttpClient]
60-
}
61-
})
62-
],
63-
bootstrap: [AppComponent]
64-
})
65-
export class AppModule {
66-
constructor(readonly translate: TranslateService) {
67-
translate.setDefaultLang('en')
68-
}
69-
}
26+
import { provideHttpClient } from '@angular/common/http'
27+
import { bootstrapApplication } from '@angular/platform-browser'
28+
import { provideModuleTranslateLoader } from '@larscom/ngx-translate-module-loader'
29+
import { provideTranslateService } from '@ngx-translate/core'
30+
import { AppComponent } from './app/app.component'
31+
32+
const baseTranslateUrl = './assets/i18n'
33+
34+
bootstrapApplication(AppComponent, {
35+
providers: [
36+
provideTranslateService({
37+
// use loader and provide options
38+
loader: provideModuleTranslateLoader({
39+
modules: [
40+
// final url: ./assets/i18n/en.json
41+
{ baseTranslateUrl },
42+
// final url: ./assets/i18n/feature1/en.json
43+
{ moduleName: 'feature1', baseTranslateUrl },
44+
// final url: ./assets/i18n/feature2/en.json
45+
{ moduleName: 'feature2', baseTranslateUrl }
46+
]
47+
})
48+
}),
49+
// http client is mandatory
50+
provideHttpClient()
51+
]
52+
}).catch((err) => console.error(err))
7053
```
7154

7255
## Namespacing
@@ -76,20 +59,17 @@ By default, each translation file gets it's own namespace based on the `moduleNa
7659
For example with these options:
7760

7861
```ts
79-
export function moduleHttpLoaderFactory(http: HttpClient) {
80-
const baseTranslateUrl = './assets/i18n'
62+
const baseTranslateUrl = './assets/i18n'
8163

82-
const options: IModuleTranslationOptions = {
83-
modules: [
84-
// no moduleName/namespace
85-
{ baseTranslateUrl },
86-
// namespace: FEATURE1
87-
{ baseTranslateUrl, moduleName: 'feature1' },
88-
// namespace: FEATURE2
89-
{ baseTranslateUrl, moduleName: 'feature2' }
90-
]
91-
}
92-
return new ModuleTranslateLoader(http, options)
64+
const options: IModuleTranslationOptions = {
65+
modules: [
66+
// no moduleName/namespace
67+
{ baseTranslateUrl },
68+
// namespace: FEATURE1
69+
{ baseTranslateUrl, moduleName: 'feature1' },
70+
// namespace: FEATURE2
71+
{ baseTranslateUrl, moduleName: 'feature2' }
72+
]
9373
}
9474
```
9575

@@ -122,7 +102,7 @@ Even though all JSON files from those modules are the same, they don't conflict
122102
The configuration is very flexible, you can even define custom templates for fetching translations.
123103

124104
```ts
125-
interface IModuleTranslationOptions {
105+
export interface IModuleTranslationOptions {
126106
/**
127107
* The translation module configurations
128108
*/
@@ -155,7 +135,7 @@ interface IModuleTranslationOptions {
155135
* Custom translate merge function after retrieving all translation files
156136
* @param translations the resolved translation files
157137
*/
158-
translateMerger?: (translations: Translation[]) => Translation
138+
translateMerger?: (translations: TranslationObject[]) => TranslationObject
159139
/**
160140
* Provide custom headers at 'root' level, which means this headers gets added to every request
161141
* unless you specify headers at 'module' level.
@@ -166,7 +146,7 @@ interface IModuleTranslationOptions {
166146
```
167147

168148
```ts
169-
interface IModuleTranslation {
149+
export interface IModuleTranslation {
170150
/**
171151
* The module name
172152
*
@@ -194,7 +174,7 @@ interface IModuleTranslation {
194174
* Custom translation map function after retrieving a translation file
195175
* @param translation the resolved translation file
196176
*/
197-
translateMap?: (translation: Translation) => Translation
177+
translateMap?: (translation: TranslationObject) => TranslationObject
198178
/**
199179
* Custom path template for fetching translations
200180
* @example

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@angular/platform-browser": "20.1.3",
1818
"@angular/platform-browser-dynamic": "20.1.3",
1919
"@angular/router": "20.1.3",
20-
"@ngx-translate/core": "16.0.4",
20+
"@ngx-translate/core": "17.0.0",
2121
"rxjs": "7.8.2",
2222
"tslib": "2.8.1",
2323
"zone.js": "0.15.1"

projects/ngx-translate-module-loader/src/lib/module-translate-loader.spec.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import { HttpClientTestingModule, HttpTestingController, TestRequest } from '@an
33
import { NO_ERRORS_SCHEMA } from '@angular/core'
44
import { TestBed } from '@angular/core/testing'
55
import { BrowserTestingModule } from '@angular/platform-browser/testing'
6-
import { Translation } from 'projects/ngx-translate-module-loader/src/public-api'
6+
import { TranslationObject } from '@ngx-translate/core'
77
import { ModuleTranslateLoader } from './module-translate-loader'
88
import { IModuleTranslationOptions } from './module-translation-options'
9-
import { TranslationKey } from './translation'
109

11-
const translation: Translation = {
10+
const translation: TranslationObject = {
1211
key: 'value',
1312
key1: 'value1',
1413
parent: {
@@ -18,7 +17,7 @@ const translation: Translation = {
1817
}
1918
}
2019

21-
const completeTranslation: Translation = {
20+
const completeTranslation: TranslationObject = {
2221
feature1: {
2322
key1: 'feature1_value1',
2423
key2: 'feature1_value2',
@@ -175,7 +174,7 @@ describe('ModuleTranslateLoader', () => {
175174
it('should load the english translation from different modules with a custom translateMerger', (done) => {
176175
const options: IModuleTranslationOptions = {
177176
...defaultOptions,
178-
translateMerger: (translations: Translation[]) => {
177+
translateMerger: (translations: TranslationObject[]) => {
179178
return translations.reduce((acc, curr) => ({ ...acc, ...curr }), Object())
180179
}
181180
}
@@ -220,7 +219,7 @@ describe('ModuleTranslateLoader', () => {
220219
const mock = createTestRequest(getTranslatePath(baseTranslateUrl, moduleName!, language))
221220
expect(mock.request.method).toEqual('GET')
222221
const response = moduleName ? completeTranslation[moduleName as keyof Object] : translation
223-
mock.flush(response)
222+
mock.flush(Object(response))
224223
})
225224
})
226225
it('should load the english translation from different modules with a custom translateMap', (done) => {
@@ -230,9 +229,8 @@ describe('ModuleTranslateLoader', () => {
230229
{
231230
moduleName: undefined,
232231
baseTranslateUrl: './assets/i18n',
233-
translateMap: (translation: Translation) => {
232+
translateMap: (translation: TranslationObject) => {
234233
return Object.keys(translation)
235-
.map((key) => key as TranslationKey)
236234
.reduce((acc, curr) => {
237235
return {
238236
...acc,
@@ -244,9 +242,8 @@ describe('ModuleTranslateLoader', () => {
244242
{
245243
moduleName: 'feature1',
246244
baseTranslateUrl: './assets/i18n',
247-
translateMap: (translation: Translation) => {
245+
translateMap: (translation: TranslationObject) => {
248246
return Object.keys(translation)
249-
.map((key) => key as TranslationKey)
250247
.reduce((acc, curr) => {
251248
return {
252249
...acc,
@@ -284,7 +281,7 @@ describe('ModuleTranslateLoader', () => {
284281
const mock = createTestRequest(getTranslatePath(baseTranslateUrl, moduleName!, language))
285282
expect(mock.request.method).toEqual('GET')
286283
const response = moduleName ? completeTranslation[moduleName as keyof Object] : translation
287-
mock.flush(response)
284+
mock.flush(Object(response))
288285
})
289286
})
290287

@@ -323,7 +320,7 @@ describe('ModuleTranslateLoader', () => {
323320
const mock = createTestRequest(getTranslatePath(baseTranslateUrl, moduleName!, language))
324321
expect(mock.request.method).toEqual('GET')
325322
const response = moduleName ? completeTranslation[moduleName as keyof Object] : translation
326-
mock.flush(response)
323+
mock.flush(Object(response))
327324
})
328325
})
329326

@@ -362,7 +359,7 @@ describe('ModuleTranslateLoader', () => {
362359
const mock = createTestRequest(getTranslatePath(baseTranslateUrl, moduleName!, language))
363360
expect(mock.request.method).toEqual('GET')
364361
const response = moduleName ? completeTranslation[moduleName as keyof Object] : translation
365-
mock.flush(response)
362+
mock.flush(Object(response))
366363
})
367364
})
368365

@@ -406,7 +403,7 @@ describe('ModuleTranslateLoader', () => {
406403

407404
const response = moduleName ? completeTranslation[moduleName as keyof Object] : translation
408405

409-
mock.flush(response, {
406+
mock.flush(Object(response), {
410407
status: moduleName == null ? 404 : 200,
411408
statusText: moduleName == null ? 'not found' : 'ok'
412409
})

projects/ngx-translate-module-loader/src/lib/module-translate-loader.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import { HttpClient } from '@angular/common/http'
2-
import { TranslateLoader, mergeDeep } from '@ngx-translate/core'
2+
import { TranslateLoader, TranslationObject, mergeDeep } from '@ngx-translate/core'
33
import { forkJoin as ForkJoin, MonoTypeOperatorFunction, Observable, of } from 'rxjs'
44
import { catchError, map } from 'rxjs/operators'
55
import { IModuleTranslation } from './module-translation'
66
import { IModuleTranslationOptions } from './module-translation-options'
7-
import { Translation } from './translation'
87

98
const concatJson = (path: string) => path.concat('.json')
109

@@ -32,15 +31,15 @@ export class ModuleTranslateLoader implements TranslateLoader {
3231
*/
3332
constructor(private readonly http: HttpClient, private readonly options: IModuleTranslationOptions) {}
3433

35-
public getTranslation(language: string): Observable<Translation> {
34+
public getTranslation(language: string): Observable<TranslationObject> {
3635
const { defaultOptions: options } = this
3736
return this.mergeTranslations(this.getModuleTranslations(language, options), options)
3837
}
3938

4039
private mergeTranslations(
41-
moduleTranslations: Observable<Translation>[],
40+
moduleTranslations: Observable<TranslationObject>[],
4241
{ deepMerge, translateMerger }: IModuleTranslationOptions
43-
): Observable<Translation> {
42+
): Observable<TranslationObject> {
4443
return ForkJoin(moduleTranslations).pipe(
4544
map((translations) => {
4645
return translateMerger
@@ -50,7 +49,7 @@ export class ModuleTranslateLoader implements TranslateLoader {
5049
)
5150
}
5251

53-
private getModuleTranslations(language: string, options: IModuleTranslationOptions): Observable<Translation>[] {
52+
private getModuleTranslations(language: string, options: IModuleTranslationOptions): Observable<TranslationObject>[] {
5453
const { modules } = options
5554

5655
return modules.map((module) => {
@@ -65,7 +64,7 @@ export class ModuleTranslateLoader implements TranslateLoader {
6564
language: string,
6665
{ translateError, version, headers }: IModuleTranslationOptions,
6766
{ pathTemplate, baseTranslateUrl, translateMap }: IModuleTranslation
68-
): Observable<Translation> {
67+
): Observable<TranslationObject> {
6968
const pathOptions = Object({ baseTranslateUrl, language })
7069
const template = pathTemplate || DEFAULT_PATH_TEMPLATE
7170

@@ -75,7 +74,7 @@ export class ModuleTranslateLoader implements TranslateLoader {
7574

7675
const path = version ? `${cleanedPath}?v=${version}` : cleanedPath
7776

78-
return this.http.get<Translation>(path, { headers }).pipe(
77+
return this.http.get<TranslationObject>(path, { headers }).pipe(
7978
map((translation) => (translateMap ? translateMap(translation) : translation)),
8079
this.catchError(cleanedPath, translateError)
8180
)
@@ -85,7 +84,7 @@ export class ModuleTranslateLoader implements TranslateLoader {
8584
language: string,
8685
{ disableNamespace, lowercaseNamespace, translateError, version, headers }: IModuleTranslationOptions,
8786
{ pathTemplate, baseTranslateUrl, moduleName, namespace, translateMap, headers: moduleHeaders }: IModuleTranslation
88-
): Observable<Translation> {
87+
): Observable<TranslationObject> {
8988
const pathOptions = Object({ baseTranslateUrl, moduleName, language })
9089
const template = pathTemplate || DEFAULT_PATH_TEMPLATE
9190

@@ -101,7 +100,7 @@ export class ModuleTranslateLoader implements TranslateLoader {
101100

102101
const path = version ? `${cleanedPath}?v=${version}` : cleanedPath
103102

104-
return this.http.get<Translation>(path, { headers: moduleHeaders || headers }).pipe(
103+
return this.http.get<TranslationObject>(path, { headers: moduleHeaders || headers }).pipe(
105104
map((translation) => {
106105
return translateMap
107106
? translateMap(translation)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { HttpClient } from '@angular/common/http'
2+
import { InjectionToken, Provider } from '@angular/core'
3+
import { TranslateLoader } from '@ngx-translate/core'
4+
import { ModuleTranslateLoader } from './module-translate-loader'
5+
import { IModuleTranslationOptions } from './module-translation-options'
6+
7+
export const MODULE_TRANSLATE_LOADER_CONFIG = new InjectionToken<IModuleTranslationOptions>(
8+
'MODULE_TRANSLATE_LOADER_CONFIG'
9+
)
10+
11+
export function provideModuleTranslateLoader(options: IModuleTranslationOptions): Provider[] {
12+
return [
13+
{
14+
provide: MODULE_TRANSLATE_LOADER_CONFIG,
15+
useValue: options
16+
},
17+
{
18+
provide: TranslateLoader,
19+
useClass: ModuleTranslateLoader,
20+
deps: [HttpClient, MODULE_TRANSLATE_LOADER_CONFIG]
21+
}
22+
]
23+
}

0 commit comments

Comments
 (0)