Skip to content

Commit

Permalink
refactor(Angular 15): rework translate loader on SSR after Angular 15…
Browse files Browse the repository at this point in the history
… update

* desired local translation file should only be loaded

BREAKING CHANGES: ICM Translate Loader needs new configuration.
  • Loading branch information
Eisie96 authored and shauke committed Mar 29, 2023
1 parent e423a82 commit 292d559
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 6 deletions.
21 changes: 21 additions & 0 deletions docs/concepts/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,27 @@ To add other languages except English, German or French:
registerLocaleData(localeNl);
```
7. Add new json-mapping-file import to `LOCAL_TRANSLATIONS` injection token in the [`InternationalizationModule`](../../src/app/core/internationalization.module.ts) provider:
```typescript
providers: [
{
provide: LOCAL_TRANSLATIONS,
useValue: {
useFactory: (lang: string) => {
switch (lang) {
// other added json-mapping-file imports with translations
...
case: nl_NL {
return import('../../assets/i18n/nl_NL.json');
}
}
},
},
}
]
```
# Further References
- [Concept - Multi-Site Handling][concept-multi-site]
Expand Down
26 changes: 26 additions & 0 deletions docs/guides/migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@ In addition all other dependencies where updated as well and resulted in necessa
The placeholder for theme specific assets and styles has been changed from `placeholder` to `theme_placeholder`.
If this is used in any customization, update all paths, which are using the old theme placeholder e.g. `src/styles/themes/placeholder` to `src/styles/themes/theme_placeholder`.

The injection token `LOCAL_TRANSLATIONS` is introduced to use local translation files within the custom [ICM translation loader](https://github.com/intershop/intershop-pwa/blob/4.0.0/src/app/core/utils/translate/icm-translate-loader.ts).
A factory function is provided in the [`internationalization.module.ts`](https://github.com/intershop/intershop-pwa/blob/4.0.0/src/app/core/internationalization.module.ts) to decide which json file with translation keys should be used for a given language.

```typescript
providers: [
...
{
provide: LOCAL_TRANSLATIONS,
useValue: {
useFactory: (lang: string) => {
switch (lang) {
case 'en_US':
return import('../../assets/i18n/en_US.json');
case 'fr_FR':
return import('../../assets/i18n/fr_FR.json');
case 'de_DE':
return import('../../assets/i18n/de_DE.json');
}
},
},
},
],
```

Please adapt the `useFactory()` function to return all imported local translation files depending on the `lang` parameter.

The account navigation was reworked to support navigation grouping (used in `b2b` theme, see [`account-navigation.items.ts`](https://github.com/intershop/intershop-pwa/blob/4.0.0/src/app/pages/account/account-navigation/account-navigation.items.ts)).
For better maintainability and brand specific overriding the account navigation items were externalized in an extra file `account-navigation.items.ts` used by the `account-navigation.component.ts`.
Also with this rework the navigation items data structure was changed from a key value object to a simpler `NavigationItem` Array.
Expand Down
22 changes: 20 additions & 2 deletions src/app/core/internationalization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
FALLBACK_LANG,
FallbackMissingTranslationHandler,
} from './utils/translate/fallback-missing-translation-handler';
import { ICMTranslateLoader } from './utils/translate/icm-translate-loader';
import { ICMTranslateLoader, LOCAL_TRANSLATIONS } from './utils/translate/icm-translate-loader';
import { PWATranslateCompiler } from './utils/translate/pwa-translate-compiler';
import { TranslationGenerator } from './utils/translate/translations-generator';

Expand All @@ -29,7 +29,25 @@ import { TranslationGenerator } from './utils/translate/translations-generator';
compiler: { provide: TranslateCompiler, useClass: PWATranslateCompiler },
}),
],
providers: [{ provide: FALLBACK_LANG, useValue: 'en_US' }, TranslationGenerator],
providers: [
{ provide: FALLBACK_LANG, useValue: 'en_US' },
{
provide: LOCAL_TRANSLATIONS,
useValue: {
useFactory: (lang: string) => {
switch (lang) {
case 'en_US':
return import('../../assets/i18n/en_US.json');
case 'fr_FR':
return import('../../assets/i18n/fr_FR.json');
case 'de_DE':
return import('../../assets/i18n/de_DE.json');
}
},
},
},
TranslationGenerator,
],
})
export class InternationalizationModule {
constructor(
Expand Down
18 changes: 15 additions & 3 deletions src/app/core/utils/translate/icm-translate-loader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { TranslateLoader } from '@ngx-translate/core';
import { memoize } from 'lodash-es';
Expand All @@ -9,14 +9,26 @@ import { LocalizationsService } from 'ish-core/services/localizations/localizati

import { Translations } from './translations.type';

interface LocalTranslations {
// return a promise with desired local translations based on given lang
useFactory(lang: string): Promise<object>;
}

export const LOCAL_TRANSLATIONS = new InjectionToken<LocalTranslations>('translations');

@Injectable()
export class ICMTranslateLoader implements TranslateLoader {
constructor(private transferState: TransferState, private localizations: LocalizationsService) {}
constructor(
private transferState: TransferState,
private localizations: LocalizationsService,
@Inject(LOCAL_TRANSLATIONS) private localTranslations: LocalTranslations
) {}

getTranslation = memoize(lang => {
const SSR_TRANSLATIONS = makeStateKey<Translations>(`ssrTranslations-${lang}`);

const local$ = defer(() => from(import(`../../../../assets/i18n/${lang}.json`)).pipe(catchError(() => of({}))));
const local$ = defer(() => from(this.localTranslations.useFactory(lang)).pipe(catchError(() => of({}))));

const server$ = iif(
() => !SSR && this.transferState.hasKey(SSR_TRANSLATIONS),
of(this.transferState.get(SSR_TRANSLATIONS, {})),
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": true,
"useDefineForClassFields": false
"useDefineForClassFields": false,
"resolveJsonModule": true
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
Expand Down

0 comments on commit 292d559

Please sign in to comment.