Problems after Upgrading
I'm submitting a...
[ ] bug report
[ ] feature request
[x] support request
Expected behavior Translation of text Actual behavior Usage of the Keynames Steps to reproduce the behavior I have upgraded an running project from angular v7.2.2 and angular-l10n v7.0.2 to angular v12.2.12 and angular-l10n v12.0.1. After clearing all compiling blockers I can successfully run the application but the translations are not displayed just the keynames.
Previous app.module.ts:
const l10nConfig: L10nConfig = {
logger: {
level: environment.production ? LogLevel.Off : LogLevel.Warn
},
locale: {
languages: [{ code: 'de', dir: 'ltr' }, { code: 'en', dir: 'ltr' }, { code: 'it', dir: 'ltr' }],
defaultLocale: { languageCode: 'de', countryCode: 'AT' },
currency: 'EUR',
storage: StorageStrategy.Cookie
},
translation: {
composedKeySeparator: '.',
providers: [
{ type: ProviderType.Fallback, prefix: './assets/i18n/global', fallbackLanguage: [] },
{ type: ProviderType.Fallback, prefix: './assets/i18n/locale-', fallbackLanguage: [ISOCode.Language] },
{ type: ProviderType.Static, prefix: './assets/i18n/locale-' }
],
composedLanguage: [ISOCode.Language, ISOCode.Country]
}
};
export function initL10n(injector: Injector, l10nLoader: L10nLoader): Function {
return () =>
new Promise(resolve => {
const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
locationInitialized.then(() => {
l10nLoader.load().then(() => resolve(null));
});
});
}
Current app.module.ts (minimal and with Inline-Text just for test purposes):
export const l10nConfig: L10nConfig = {
format: 'language-region',
providers: [
{ name: 'app', asset: i18nAsset }
],
cache: true,
keySeparator: '.',
defaultLocale: { language: 'de-AT', currency: 'EUR', timeZone: 'Europe/Vienna' },
schema: [
{ locale: { language: 'de-AT', currency: 'EUR', timeZone: 'Europe/Vienna' }, dir: 'ltr', text: 'Austria' },
{ locale: { language: 'en-US', currency: 'USD', timeZone: 'America/Los_Angeles' }, dir: 'ltr', text: 'United States' },
{ locale: { language: 'it-IT', currency: 'EUR', timeZone: 'Europe/Rome' }, dir: 'ltr', text: 'Italia' }
],
};
The Login Component:
import { HttpErrorResponse } from '@angular/common/http';
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Response, ResponseType } from '@angular/http';
import { MatDialog } from '@angular/material/dialog';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { L10nConfig, L10nLocale, L10nTranslationService, L10N_CONFIG, L10N_LOCALE } from 'angular-l10n';
import { throwError as observableThrowError } from 'rxjs';
import { oase_config } from '../../environments/environment';
import { AuthService } from '../shared/auth.service';
import { LoggerService } from '../shared/logger.service';
import { Httpstatus } from '../shared/response/httpstatus.model';
import { Kernantwort } from '../shared/response/kernantwort.model';
import { SessionService } from '../shared/session.service';
const PATH_FILE = 'app/unprotected/signin.component.ts';
const BACKEND_PATH_PREFIX = 'signin/';
@Component({
templateUrl: './signin.component.html'
})
export class SigninComponent implements OnInit {
lang: string;
isSigninRunning = false;
signinForm: FormGroup;
fehler: Kernantwort = null;
appid_vorhanden = false;
fehler_keineappid = '';
appVersion: string = oase_config.appversion;
@ViewChild('password') password;
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
private fb: FormBuilder,
private authService: AuthService,
public sessService: SessionService,
public dialogRef: MatDialog,
public title: Title,
@Inject(L10N_LOCALE) public locale: L10nLocale,
@Inject(L10N_CONFIG) private l10nConfig: L10nConfig,
public translation: L10nTranslationService,
private _logger: LoggerService
) {
// Set document title.
this.title.setTitle(this.getTitle());
// this.translation.onChange().subscribe(() => { this.title.setTitle(this.getTitle()); });
this._logger.log(PATH_FILE + ' - isAuth: ' + this.isAuth());
if (this.isAuth()) {
this.router.navigate(['/home']);
} else {
// close open dialogs on token expiration
this.dialogRef.closeAll();
}
}
onSignin() {
this.isSigninRunning = true;
this.fehler = null;
let auth_token: string = null;
let success = null;
this._logger.log(PATH_FILE + ' - onSignin vor authService.signinUser');
this.authService.signinUser(this.signinForm.value).subscribe(
data => {
this._logger.log(PATH_FILE + ' - onSignin subscribe data: ', data);
(auth_token = data.authtoken), (success = data.success);
},
err => {
this._logger.log(PATH_FILE + ' - onSignin subscribe err: ', err);
this.isSigninRunning = false;
this.handleError(err, 'Fehler bei Anmeldung');
},
() => {
this._logger.log(PATH_FILE + ' - onSignin subscribe complete');
// Merken wann der Benutzer sich eingeloggt hat (wird für die Anzeige von neuen Schlüssel benötigt)
this.authService.storeJwToken(auth_token, new Date().getTime());
this.authService.logTokenInfos(PATH_FILE + ' - signinUser');
this.router.navigate(['/home']);
this.isSigninRunning = false;
}
);
}
ngOnInit(): any {
// Set document title.
this.translation.onChange().subscribe(() => {
this.title.setTitle(this.getTitle());
});
this.activatedRoute.params.subscribe((params: Params) => {
console.log(PATH_FILE + " - params['appid'] param: " + params['appid']);
this.appid_vorhanden = oase_config.singlecompany || (params['appid'] != null && params['appid'].length > 0);
if (!this.appid_vorhanden) {
this.fehler = new Kernantwort();
this.fehler.messagehtml = this.translation.translate('login.keine_appid', { url: '/' + BACKEND_PATH_PREFIX });
}
console.log(PATH_FILE + " - params['appid']: " + params['appid']);
this.signinForm = this.fb.group({
appid: oase_config.singlecompany ? oase_config.defaultyappid : params['appid'],
user: [{ value: '', disabled: !this.appid_vorhanden }, Validators.required],
password: [{ value: '', disabled: !this.appid_vorhanden }, Validators.required]
});
});
}
isAuth() {
return this.authService.isAuthenticated();
}
getTitle() {
return this.translation.translate('login.title') + ' - ' + this.translation.translate('project.title');
}
public handleError(error: Response | HttpErrorResponse | any, prefix = 'handleError') {
let fehler = new Kernantwort();
this._logger.log(PATH_FILE + ' - handleError error error.constructor.name: ', error.constructor.name);
if (error instanceof Response || error instanceof HttpErrorResponse) {
try {
fehler = error instanceof HttpErrorResponse ? error.error : error.json();
if (
error.status === 0 &&
!error.ok &&
((error instanceof Response && error.type === ResponseType.Error && error.statusText.length === 0) ||
(error instanceof HttpErrorResponse && error.error.type === 'error' && error.statusText === 'Unknown Error'))
) {
fehler.httpstatus = new Httpstatus();
fehler.httpstatus.name = 'vermutlich 503er Service Temporarily Unavailable';
fehler.httpstatus.number = 500;
}
} catch (e) {
fehler = new Kernantwort();
fehler.messagehtml = this.translation.translate('allgemein.fehler');
this._logger.error(
PATH_FILE + ' - ERROR ' + error.status + ': ' + prefix + ' (' + error.statusText + ' (' + error.status + ')' + '): ',
error instanceof HttpErrorResponse ? error.message : error.text()
);
}
} else {
fehler = new Kernantwort();
fehler.message = error.message ? error.message : error.toString();
}
if (!fehler.messagehtml) {
fehler.messagehtml = fehler.message;
}
if (fehler && fehler.httpstatus && fehler.httpstatus.number === 500) {
this._logger.error(PATH_FILE + ' - ' + prefix + ':' + fehler.messagehtml);
fehler.messagehtml = this.translation.translate('allgemein.fehler');
this._logger.error(
PATH_FILE + ' - ERROR 500: ' + prefix + ' (' + fehler.httpstatus.name + ' (' + fehler.httpstatus.number + ')' + '): ',
fehler
);
} else {
this._logger.info(PATH_FILE + ' - ' + prefix + ': ', fehler);
}
// Nach dem der Fehler fertig erstellt wurde die entsprechende Fehler variable setzten
this.fehler = fehler;
return observableThrowError(fehler.message);
}
showPassword(event: any): void {
// https://developer.mozilla.org/en-US/docs/Web/Events/mousedown
this.password.nativeElement.type = 'text';
}
hidePassword(event: any): void {
// https://developer.mozilla.org/en-US/docs/Web/Events/mouseup
// https://developer.mozilla.org/en-US/docs/Web/Events/mouseout
this.password.nativeElement.type = 'password';
}
}
And the Login-Template:
<mat-card class="login">
<mat-card-header>
<mat-card-title>{{ 'project.title' | translate:locale.language }} - {{ 'login.title' | translate:locale.language }}</mat-card-title>
<mat-card-subtitle>{{ 'login.subtitle' | translate:locale.language }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<form [formGroup]="signinForm" (ngSubmit)="onSignin()" fxLayout="row wrap" fxLayout.lt-sm="column" fxLayoutGap="20px" fxLayoutGap.lt-sm="0px" fxLayoutAlign="space-between baseline" fxLayoutAlign.lt-sm="stretch stretch">
<input matInput [hidden]="true" formControlName="appid" type="appid" id="appid" #appid required />
<div fxFlex="0 0 100%">
<p class="errors" *ngIf="fehler" [innerHTML]="fehler.messagehtml"></p>
</div>
<mat-form-field fxFlex>
<input matInput formControlName="user" [disabled]="isSigninRunning" type="user" id="user" #user required placeholder="{{ 'login.username' | translate:locale.language }}" />
<mat-icon matPrefix>person_outline</mat-icon>
</mat-form-field>
<mat-form-field fxFlex>
<input matInput formControlName="password" [disabled]="isSigninRunning" type="password" id="password" #password required placeholder="{{ 'login.password' | translate:locale.language }}" />
<mat-icon matPrefix>lock_outline</mat-icon>
<span matSuffix><button type="button" [disabled]="password.value==null || password.value==''" (mousedown)="showPassword($event)" (mouseup)="hidePassword($event)" (mouseout)="hidePassword($event)" mat-icon-button class="md-24" style="height:16px; width:16px; line-height:16px;"><i class="material-icons app-input-icon">visibility</i></button></span>
</mat-form-field>
<div fxFlex>
<button mat-raised-button color="primary" [disabled]="isSigninRunning || !appid_vorhanden || !signinForm.valid">
<mat-spinner *ngIf="isSigninRunning" [diameter]="30"></mat-spinner>
<i *ngIf="!isSigninRunning" class="material-icons app-input-icon">power_settings_new</i>
{{ (isSigninRunning ? 'allgemein.daten.verarbeiten' : 'login.btn_login') | translate:locale.language }}
</button>
</div>
</form>
<span class="version">{{ appVersion }}</span>
<mat-progress-bar *ngIf="isSigninRunning" color="primary" mode="indeterminate"></mat-progress-bar>
</mat-card-content>
</mat-card>
I can't seem to find the mistake i made. I looked through this all day long and there's not even error messages coming in the debug windows.
I also tried Firefox and Chrome. With deleting the cache...
Hi @djanesch ,
component & template seem correct.
In the samples you provided I can't see:
export function initL10n(l10nLoader: L10nLoader): () => Promise<void> {
return () => l10nLoader.init();
}
are you sure you are initializing the library?
Compare the doc for v12:
- https://github.com/robisim74/angular-l10n/tree/angular_v12
- https://github.com/robisim74/angular-l10n/blob/master/MIGRATION_GUIDE.md
You could also try to add:
ngOnInit() {
this.translation.onChange().subscribe({
next: (locale: L10nLocale) => {
console.log(locale);
console.log(this.translation.data);
}
});
this.translation.onError().subscribe({
next: (error: any) => {
if (error) console.log(error);
}
});
}
and check in console if translation data are loaded without errors.
Let me know.
Closed due to inactivity