[ACS-5629] enhanced way of providing translations ()

* enhanced way providing translations

* update documentation

* update documentation

* test fixes

* try add missing module import

* inject i18n to core module to cause the setup
This commit is contained in:
Denys Vuika 2023-07-18 20:06:09 +01:00 committed by GitHub
parent d70f689e06
commit 1a4d7ba008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 99 additions and 183 deletions
demo-shell/src/app
docs/core/services
lib
content-services/src/lib
core/src/lib
insights/src/lib
process-services-cloud/src/lib
process-services/src/lib

@ -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,

@ -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)

@ -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,

@ -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 { }

@ -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')
]
});

@ -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'
})

@ -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')
]
};
}

@ -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: {}

@ -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 },

@ -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 { }

@ -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 }
]