diff --git a/demo-shell/src/app/app.module.ts b/demo-shell/src/app/app.module.ts index ed4c4c0768..251bb4f8aa 100644 --- a/demo-shell/src/app/app.module.ts +++ b/demo-shell/src/app/app.module.ts @@ -24,11 +24,11 @@ import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform import { TranslateModule } from '@ngx-translate/core'; import { AppConfigService, - TRANSLATION_PROVIDER, DebugAppConfigService, CoreModule, CoreAutomationService, - AuthModule + AuthModule, + provideTranslations } from '@alfresco/adf-core'; import { ExtensionsModule } from '@alfresco/adf-extensions'; import { AppComponent } from './app.component'; @@ -211,22 +211,8 @@ registerLocaleData(localeSv); ], providers: [ { provide: AppConfigService, useClass: DebugAppConfigService }, // not use this service in production - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'app', - source: 'resources' - } - }, - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'lazy-loading', - source: 'resources/lazy-loading' - } - }, + provideTranslations('app', 'resources'), + provideTranslations('lazy-loading', 'resources/lazy-loading'), AppNotificationsService, { provide: APP_INITIALIZER, diff --git a/docs/core/services/translation.service.md b/docs/core/services/translation.service.md index 0049a978f0..16e23b8fa8 100644 --- a/docs/core/services/translation.service.md +++ b/docs/core/services/translation.service.md @@ -62,7 +62,7 @@ this.trans.get( total: "122" } ).subscribe(translation => { - this.translatedText = translation; + this.translatedText = translation; }); ``` @@ -79,16 +79,21 @@ general format of the path to this folder will be: If you wanted English and French translations then you would add `en.json` and `fr.json` files into the `i18n` folder and add your new keys: - // en.json +**en.json** - ... - "WELCOME_MESSAGE": "Welcome!" - ... +```json +{ + "WELCOME_MESSAGE": "Welcome!" +} +``` - // fr.json - ... - "WELCOME_MESSAGE": "Bienvenue !" - ... +**fr.json** + +```json +{ + "WELCOME_MESSAGE": "Bienvenue !" +} +``` The files follow the same hierarchical key:value JSON format as the built-in translations. You can add new keys to your local files or redefine existing keys but the built-in definitions @@ -97,66 +102,53 @@ look like the following: ```json { - "title": "my app", - "LOGIN": { - "LABEL": { - "LOGIN": "Custom Sign In" - } - } + "title": "my app", + "LOGIN": { + "LABEL": { + "LOGIN": "Custom Sign In" + } + } } ``` -To enable the new translations in your app, you also need to register them in your -`app.module.ts` file. Import `TRANSLATION_PROVIDER` and add the path of your -translations folder to the `providers`: +To enable the new translations in your app, you also need to register them in your `app.module.ts` file using `provideTranslations` api: ```ts -// Other imports... - -import { TRANSLATION_PROVIDER } from "@alfresco/adf-core"; - - ... +import { provideTranslations } from "@alfresco/adf-core"; @NgModule({ - imports: [ - ... - ], - declarations: [ - ... - ], - providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'my-translations', - source: 'assets/my-translations' - } - } - ... + providers: [ + provideTranslations('my-translations', 'assets/my-translations') + ] +}) +export class MyModule {} ``` You can now use your new keys in your component: ```ts - ... -ngOnInit() { - this.trans.use("fr"); - - this.trans.get("WELCOME_MESSAGE").subscribe(translation => { - this.translatedText = translation; - }); - } - ... +export class MyComponent implements OnInit { + translateService = inject(TranslationService); + translatedText = ''; + + ngOnInit() { + this.translateService.use("fr"); + this.translatedText = this.translateService.instant('WELCOME_MESSAGE'); + } +} ``` -Note: the `source` property points to the web application root. Ensure you have -webpack correctly set up to copy all the i18n files at compile time. +Note: the `source` property points to the web application root. +Do not forget to configure your Angular application to copy the newly created files to the build output, for example: -```text -index.html -assets/ng2-alfresco-core/i18n/en.json -... +**angular.json** + +```json +{ + "glob": "**/*", + "input": "lib/core/src/lib/i18n", + "output": "/assets/adf-core/i18n" +} ``` You can register as many entries as you like. @@ -180,4 +172,4 @@ class MyComponent { ## See Also -- [Internationalization](../../user-guide/internationalization.md) +- [Internationalization](../../user-guide/internationalization.md) diff --git a/lib/content-services/src/lib/content.module.ts b/lib/content-services/src/lib/content.module.ts index 6d6e39367d..c82047ef47 100644 --- a/lib/content-services/src/lib/content.module.ts +++ b/lib/content-services/src/lib/content.module.ts @@ -18,7 +18,7 @@ import { CommonModule } from '@angular/common'; import { NgModule, ModuleWithProviders, APP_INITIALIZER } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CoreModule, TRANSLATION_PROVIDER, SearchTextModule } from '@alfresco/adf-core'; +import { CoreModule, SearchTextModule, provideTranslations } from '@alfresco/adf-core'; import { MaterialModule } from './material.module'; @@ -89,14 +89,7 @@ import { CategoriesModule } from './category/category.module'; CategoriesModule ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-content-services', - source: 'assets/adf-content-services' - } - } + provideTranslations('adf-content-services', 'assets/adf-content-services') ], exports: [ ContentPipeModule, @@ -134,14 +127,7 @@ export class ContentModule { return { ngModule: ContentModule, providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-content-services', - source: 'assets/adf-content-services' - } - }, + provideTranslations('adf-content-services', 'assets/adf-content-services'), { provide: APP_INITIALIZER, useFactory: versionCompatibilityFactory, diff --git a/lib/core/src/lib/testing/core.story.module.ts b/lib/core/src/lib/testing/core.story.module.ts index ac02e8a5d4..e368b8f409 100644 --- a/lib/core/src/lib/testing/core.story.module.ts +++ b/lib/core/src/lib/testing/core.story.module.ts @@ -19,7 +19,7 @@ import { NgModule } from '@angular/core'; import { CoreModule } from '../core.module'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateModule } from '@ngx-translate/core'; -import { TRANSLATION_PROVIDER } from '../translation/translation.service'; +import { provideTranslations } from '../translation/translation.service'; @NgModule({ imports: [ @@ -28,14 +28,7 @@ import { TRANSLATION_PROVIDER } from '../translation/translation.service'; BrowserAnimationsModule ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-core', - source: 'assets/adf-core' - } - } + provideTranslations('adf-core', 'assets/adf-core') ] }) export class CoreStoryModule { } diff --git a/lib/core/src/lib/translation/translation.service.spec.ts b/lib/core/src/lib/translation/translation.service.spec.ts index 961a55a431..74b900d87d 100644 --- a/lib/core/src/lib/translation/translation.service.spec.ts +++ b/lib/core/src/lib/translation/translation.service.spec.ts @@ -21,7 +21,7 @@ import { getTestBed, TestBed } from '@angular/core/testing'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoaderService } from './translate-loader.service'; -import { TRANSLATION_PROVIDER, TranslationService } from './translation.service'; +import { provideTranslations, TranslationService } from './translation.service'; import { AppConfigService } from '../app-config/app-config.service'; import { AppConfigServiceMock } from '../common/mock/app-config.service.mock'; import { AlfrescoApiService } from '../services/alfresco-api.service'; @@ -47,14 +47,7 @@ describe('TranslationService', () => { providers: [ { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, { provide: AppConfigService, useClass: AppConfigServiceMock }, - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: '@alfresco/adf-core', - source: 'assets/ng2-alfresco-core' - } - } + provideTranslations('@alfresco/adf-core', 'assets/ng2-alfresco-core') ] }); diff --git a/lib/core/src/lib/translation/translation.service.ts b/lib/core/src/lib/translation/translation.service.ts index 8dce751904..a3e5bef236 100644 --- a/lib/core/src/lib/translation/translation.service.ts +++ b/lib/core/src/lib/translation/translation.service.ts @@ -28,6 +28,24 @@ export interface TranslationProvider { source: string; } +/** + * Generate translation provider + * + * @param id Unique identifier + * @param path Path to translation files + * @returns Provider + */ +export function provideTranslations(id: string, path: string) { + return { + provide: TRANSLATION_PROVIDER, + multi: true, + useValue: { + name: id, + source: path + } + }; +} + @Injectable({ providedIn: 'root' }) diff --git a/lib/insights/src/lib/insights.module.ts b/lib/insights/src/lib/insights.module.ts index d2214b6cc4..2cb5485447 100644 --- a/lib/insights/src/lib/insights.module.ts +++ b/lib/insights/src/lib/insights.module.ts @@ -18,7 +18,7 @@ import { CommonModule } from '@angular/common'; import { NgModule, ModuleWithProviders } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CoreModule, TRANSLATION_PROVIDER } from '@alfresco/adf-core'; +import { CoreModule, provideTranslations } from '@alfresco/adf-core'; import { DiagramsModule } from './diagram/diagram.module'; import { AnalyticsProcessModule } from './analytics-process/analytics-process.module'; @@ -45,14 +45,7 @@ export class InsightsModule { return { ngModule: InsightsModule, providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-insights', - source: 'assets/adf-insights' - } - } + provideTranslations('adf-insights', 'assets/adf-insights') ] }; } diff --git a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts index 803db3b824..3b615c2670 100644 --- a/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/form-cloud.component.spec.ts @@ -25,7 +25,7 @@ import { FormModel, FormOutcomeEvent, FormOutcomeModel, FormRenderingService, FormService, - TRANSLATION_PROVIDER, UploadWidgetContentLinkModel, WidgetVisibilityService + UploadWidgetContentLinkModel, WidgetVisibilityService, provideTranslations } from '@alfresco/adf-core'; import { Node } from '@alfresco/js-api'; import { ESCAPE } from '@angular/cdk/keycodes'; @@ -54,6 +54,7 @@ import { FormCloudRepresentation } from '../models/form-cloud-representation.mod import { FormCloudService } from '../services/form-cloud.service'; import { CloudFormRenderingService } from './cloud-form-rendering.service'; import { FormCloudComponent } from './form-cloud.component'; +import { ProcessServicesCloudModule } from '../../process-services-cloud.module'; const mockOauth2Auth: any = { oauth2Auth: { @@ -1152,17 +1153,11 @@ describe('Multilingual Form', () => { imports: [ NoopAnimationsModule, TranslateModule.forRoot(), - CoreModule.forRoot() + CoreModule.forRoot(), + ProcessServicesCloudModule.forRoot() ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'app', - source: 'resources' - } - } + provideTranslations('app', 'resources') ] }); translateService = TestBed.inject(TranslateService); @@ -1184,20 +1179,20 @@ describe('Multilingual Form', () => { formComponent.ngOnChanges({ appName: new SimpleChange(null, appName, true) }); expect(formCloudService.getForm).toHaveBeenCalledWith(appName, formId, 1); - fixture.ngZone.run(() => translateService.use('fr')); + await translateService.use('fr').toPromise(); - await fixture.whenStable(); fixture.detectChanges(); + await fixture.whenStable(); expect(getLabelValue('textField')).toEqual('Champ de texte'); expect(getLabelValue('fildUploadField')).toEqual('Téléchargement de fichiers'); expect(getLabelValue('dateField')).toEqual('Champ de date (D-M-YYYY)'); expect(getLabelValue('amountField')).toEqual('Champ Montant'); - fixture.ngZone.run(() => translateService.use('en')); + await translateService.use('en').toPromise(); - await fixture.whenStable(); fixture.detectChanges(); + await fixture.whenStable(); expect(getLabelValue('textField')).toEqual('Text field'); expect(getLabelValue('fildUploadField')).toEqual('File Upload'); @@ -1237,14 +1232,7 @@ describe('retrieve metadata on submit', () => { FormCloudModule ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'app', - source: 'resources' - } - }, + provideTranslations('app', 'resources'), { provide: VersionCompatibilityService, useValue: {} diff --git a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts index df149f1576..1941696171 100644 --- a/lib/process-services-cloud/src/lib/process-services-cloud.module.ts +++ b/lib/process-services-cloud/src/lib/process-services-cloud.module.ts @@ -16,7 +16,7 @@ */ import { NgModule, ModuleWithProviders } from '@angular/core'; -import { TRANSLATION_PROVIDER, CoreModule, FormRenderingService } from '@alfresco/adf-core'; +import { CoreModule, FormRenderingService, provideTranslations } from '@alfresco/adf-core'; import { AppListCloudModule } from './app/app-list-cloud.module'; import { TaskCloudModule } from './task/task-cloud.module'; import { ProcessCloudModule } from './process/process-cloud.module'; @@ -52,14 +52,7 @@ import { RichTextEditorModule } from './rich-text-editor/rich-text-editor.module RichTextEditorModule ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-process-services-cloud', - source: 'assets/adf-process-services-cloud' - } - } + provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud') ], exports: [ AppListCloudModule, @@ -81,14 +74,7 @@ export class ProcessServicesCloudModule { return { ngModule: ProcessServicesCloudModule, providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-process-services-cloud', - source: 'assets/adf-process-services-cloud' - } - }, + provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud'), { provide: PROCESS_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService }, { provide: TASK_FILTERS_SERVICE_TOKEN, useExisting: filterPreferenceServiceInstance ?? LocalPreferenceCloudService }, { provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useExisting: listPreferenceServiceInstance ?? LocalPreferenceCloudService }, diff --git a/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts b/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts index a8edbaf744..b95dc72f36 100644 --- a/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts +++ b/lib/process-services-cloud/src/lib/testing/process-services-cloud-story.module.ts @@ -16,25 +16,20 @@ */ import { NgModule } from '@angular/core'; -import { CoreModule, TRANSLATION_PROVIDER } from '@alfresco/adf-core'; +import { CoreModule, provideTranslations } from '@alfresco/adf-core'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { TranslateModule } from '@ngx-translate/core'; +import { ProcessServicesCloudModule } from '../process-services-cloud.module'; @NgModule({ imports: [ + BrowserAnimationsModule, TranslateModule.forRoot(), CoreModule.forRoot(), - BrowserAnimationsModule + ProcessServicesCloudModule.forRoot() ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-process-services-cloud', - source: 'assets/adf-process-services-cloud' - } - } + provideTranslations('adf-process-services-cloud', 'assets/adf-process-services-cloud') ] }) export class ProcessServicesCloudStoryModule { } diff --git a/lib/process-services/src/lib/process.module.ts b/lib/process-services/src/lib/process.module.ts index 04f4a6fcba..5905535464 100644 --- a/lib/process-services/src/lib/process.module.ts +++ b/lib/process-services/src/lib/process.module.ts @@ -18,7 +18,7 @@ import { CommonModule } from '@angular/common'; import { NgModule, ModuleWithProviders } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { CoreModule, TRANSLATION_PROVIDER, FormRenderingService } from '@alfresco/adf-core'; +import { CoreModule, FormRenderingService, provideTranslations } from '@alfresco/adf-core'; import { MaterialModule } from './material.module'; @@ -53,14 +53,7 @@ import { ProcessUserInfoModule } from './process-user-info/process-user-info.mod ProcessServicesPipeModule ], providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-process-services', - source: 'assets/adf-process-services' - } - } + provideTranslations('adf-process-services', 'assets/adf-process-services') ], exports: [ CommonModule, @@ -83,14 +76,7 @@ export class ProcessModule { return { ngModule: ProcessModule, providers: [ - { - provide: TRANSLATION_PROVIDER, - multi: true, - useValue: { - name: 'adf-process-services', - source: 'assets/adf-process-services' - } - }, + provideTranslations('adf-process-services', 'assets/adf-process-services'), FormRenderingService, { provide: FormRenderingService, useClass: ProcessFormRenderingService } ]