Vastly improved Internationalization support (ref #228)
This commit is contained in:
parent
88f0d80b1e
commit
63ac6df2ab
|
@ -0,0 +1,45 @@
|
||||||
|
package eu.eudat.controllers;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequestMapping(value = {"/api/language/"})
|
||||||
|
public class LanguageController {
|
||||||
|
|
||||||
|
Environment environment;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public LanguageController(Environment environment) {
|
||||||
|
this.environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "{lang}", method = RequestMethod.GET)
|
||||||
|
public ResponseEntity getLanguage(@PathVariable String lang) throws IOException {
|
||||||
|
|
||||||
|
String fileName = this.environment.getProperty("language.path") + lang + ".json";
|
||||||
|
InputStream is = getClass().getClassLoader().getResource(fileName).openStream();
|
||||||
|
|
||||||
|
HttpHeaders responseHeaders = new HttpHeaders();
|
||||||
|
responseHeaders.setContentLength(is.available());
|
||||||
|
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||||
|
responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName);
|
||||||
|
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
|
||||||
|
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
|
||||||
|
|
||||||
|
byte[] content = new byte[is.available()];
|
||||||
|
is.read(content);
|
||||||
|
is.close();
|
||||||
|
|
||||||
|
return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
|
@ -67,3 +67,5 @@ zenodo.access_token=
|
||||||
|
|
||||||
#############CONTACT EMAIL CONFIGURATIONS#########
|
#############CONTACT EMAIL CONFIGURATIONS#########
|
||||||
contact_email.mail=
|
contact_email.mail=
|
||||||
|
|
||||||
|
language.path=/tempLang/i18n/
|
|
@ -12,6 +12,7 @@ import { BreadCrumbResolverService } from './ui/misc/breadcrumb/service/breadcru
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
import { NgcCookieConsentService, NgcStatusChangeEvent } from "ngx-cookieconsent";
|
import { NgcCookieConsentService, NgcStatusChangeEvent } from "ngx-cookieconsent";
|
||||||
import { CookieService } from "ngx-cookie-service";
|
import { CookieService } from "ngx-cookie-service";
|
||||||
|
import { LanguageService } from './core/services/language/language.service';
|
||||||
|
|
||||||
|
|
||||||
declare const gapi: any;
|
declare const gapi: any;
|
||||||
|
@ -38,7 +39,8 @@ export class AppComponent implements OnInit {
|
||||||
private titleService: Title,
|
private titleService: Title,
|
||||||
private cultureService: CultureService,
|
private cultureService: CultureService,
|
||||||
private cookieService: CookieService,
|
private cookieService: CookieService,
|
||||||
private ccService: NgcCookieConsentService
|
private ccService: NgcCookieConsentService,
|
||||||
|
private language: LanguageService
|
||||||
) {
|
) {
|
||||||
this.initializeServices();
|
this.initializeServices();
|
||||||
}
|
}
|
||||||
|
@ -145,6 +147,7 @@ export class AppComponent implements OnInit {
|
||||||
initializeServices() {
|
initializeServices() {
|
||||||
this.translate.setDefaultLang('en');
|
this.translate.setDefaultLang('en');
|
||||||
this.authentication.current() && this.authentication.current().culture ? this.cultureService.cultureSelected(this.authentication.current().culture) : this.cultureService.cultureSelected(environment.defaultCulture);
|
this.authentication.current() && this.authentication.current().culture ? this.cultureService.cultureSelected(this.authentication.current().culture) : this.cultureService.cultureSelected(environment.defaultCulture);
|
||||||
|
this.authentication.current() && this.authentication.current().language ? this.language.changeLanguage(this.authentication.current().language) : this.language.changeLanguage('en');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,13 @@ import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { CookieService } from 'ngx-cookie-service';
|
import { CookieService } from 'ngx-cookie-service';
|
||||||
import { NgcCookieConsentConfig, NgcCookieConsentModule } from 'ngx-cookieconsent';
|
import { NgcCookieConsentConfig, NgcCookieConsentModule } from 'ngx-cookieconsent';
|
||||||
|
import { TranslateServerLoader } from './core/services/language/server.loader';
|
||||||
|
import { BaseHttpService } from './core/services/http/base-http.service';
|
||||||
|
|
||||||
// AoT requires an exported function for factories
|
// AoT requires an exported function for factories
|
||||||
export function HttpLoaderFactory(http: HttpClient) {
|
export function HttpLoaderFactory(http: HttpClient) {
|
||||||
return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
|
return new TranslateServerLoader(http);
|
||||||
|
//return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
const cookieConfig: NgcCookieConsentConfig = {
|
const cookieConfig: NgcCookieConsentConfig = {
|
||||||
|
|
|
@ -35,6 +35,7 @@ import { OrganisationService } from './services/organisation/organisation.servic
|
||||||
import { EmailConfirmationService } from './services/email-confirmation/email-confirmation.service';
|
import { EmailConfirmationService } from './services/email-confirmation/email-confirmation.service';
|
||||||
import { FunderService } from './services/funder/funder.service';
|
import { FunderService } from './services/funder/funder.service';
|
||||||
import { ContactSupportService } from './services/contact-support/contact-support.service';
|
import { ContactSupportService } from './services/contact-support/contact-support.service';
|
||||||
|
import { LanguageService } from './services/language/language.service';
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// This is shared module that provides all the services. Its imported only once on the AppModule.
|
// This is shared module that provides all the services. Its imported only once on the AppModule.
|
||||||
|
@ -89,7 +90,8 @@ export class CoreServiceModule {
|
||||||
QuickWizardService,
|
QuickWizardService,
|
||||||
OrganisationService,
|
OrganisationService,
|
||||||
EmailConfirmationService,
|
EmailConfirmationService,
|
||||||
ContactSupportService
|
ContactSupportService,
|
||||||
|
LanguageService
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { isNullOrUndefined } from 'util';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LanguageService {
|
||||||
|
private currentLanguage: string = 'en';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private translate: TranslateService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public changeLanguage(lang: string) {
|
||||||
|
this.currentLanguage = lang;
|
||||||
|
this.translate.use(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCurrentLanguage() {
|
||||||
|
return this.currentLanguage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { TranslateLoader } from '@ngx-translate/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { environment } from 'environments/environment';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
export class TranslateServerLoader implements TranslateLoader{
|
||||||
|
private languageUrl = `${environment.Server}language`;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private http: HttpClient
|
||||||
|
) {}
|
||||||
|
getTranslation(lang: string): Observable<any> {
|
||||||
|
return this.http.get(`${this.languageUrl}/${lang}`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/serv
|
||||||
import { BaseComponent } from '@common/base/base.component';
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { TranslateServerLoader } from '@app/core/services/language/server.loader';
|
||||||
|
import { LanguageService } from '@app/core/services/language/language.service';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-admin-login',
|
selector: 'app-admin-login',
|
||||||
templateUrl: './admin-login.component.html',
|
templateUrl: './admin-login.component.html',
|
||||||
|
@ -24,9 +26,10 @@ export class AdminLoginComponent extends BaseComponent implements OnInit {
|
||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private uiNotificationService: UiNotificationService,
|
private uiNotificationService: UiNotificationService,
|
||||||
private language: TranslateService,
|
private translate: TranslateService,
|
||||||
private cultureService: CultureService,
|
private cultureService: CultureService,
|
||||||
private router: Router
|
private router: Router,
|
||||||
|
private language: LanguageService
|
||||||
) { super(); }
|
) { super(); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,12 +51,13 @@ export class AdminLoginComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public onLogInSuccess(loginResponse: any) {
|
public onLogInSuccess(loginResponse: any) {
|
||||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success);
|
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success);
|
||||||
if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); }
|
if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); }
|
||||||
|
if (this.authService.current().language) { this.language.changeLanguage(this.authService.current().language); }
|
||||||
this.router.navigate(['/']);
|
this.router.navigate(['/']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onLogInError(errorMessage: string) {
|
public onLogInError(errorMessage: string) {
|
||||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error);
|
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { CultureService } from '@app/core/services/culture/culture-service';
|
||||||
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||||
import { BaseService } from '@common/base/base.service';
|
import { BaseService } from '@common/base/base.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { TranslateServerLoader } from '@app/core/services/language/server.loader';
|
||||||
|
import { LanguageService } from '@app/core/services/language/language.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LoginService extends BaseService {
|
export class LoginService extends BaseService {
|
||||||
|
@ -12,10 +14,11 @@ export class LoginService extends BaseService {
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private language: TranslateService,
|
private translate: TranslateService,
|
||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
private cultureService: CultureService,
|
private cultureService: CultureService,
|
||||||
private uiNotificationService: UiNotificationService
|
private uiNotificationService: UiNotificationService,
|
||||||
|
private language: LanguageService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -44,14 +47,15 @@ export class LoginService extends BaseService {
|
||||||
|
|
||||||
public onLogInSuccess(loginResponse: any, returnUrl: string) {
|
public onLogInSuccess(loginResponse: any, returnUrl: string) {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success);
|
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success);
|
||||||
if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); }
|
if (this.authService.current().culture) { this.cultureService.cultureSelected(this.authService.current().culture); }
|
||||||
|
if (this.authService.current().language) { this.language.changeLanguage(this.authService.current().language); }
|
||||||
const redirectUrl = returnUrl || '/';
|
const redirectUrl = returnUrl || '/';
|
||||||
this.router.navigate([redirectUrl]);
|
this.router.navigate([redirectUrl]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public onLogInError(errorMessage: string) {
|
public onLogInError(errorMessage: string) {
|
||||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error);
|
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,31 @@
|
||||||
</div>
|
</div>
|
||||||
</form> -->
|
</form> -->
|
||||||
|
|
||||||
|
<!-- Language
|
||||||
|
|
||||||
|
<div class="col-auto">
|
||||||
|
<button mat-icon-button [matMenuTriggerFor]="languageMenu">
|
||||||
|
<mat-icon>language</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-menu #languageMenu="matMenu">
|
||||||
|
<button mat-menu-item
|
||||||
|
(click)="onLanguageSelected(languageTypes.English)">{{'NAVIGATION.ENGLISH-LANGUAGE' | translate}}</button>
|
||||||
|
<button mat-menu-item
|
||||||
|
(click)="onLanguageSelected(languageTypes.Greek)">{{'NAVIGATION.GREEK-LANGUAGE' | translate}}</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="col-md-auto" *ngIf="!isAuthenticated()">
|
||||||
|
<button mat-icon-button [matMenuTriggerFor]="languageMenu">
|
||||||
|
<mat-icon>language</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-menu #languageMenu="matMenu">
|
||||||
|
<button mat-menu-item *ngFor="let lang of languages" (click)="onLanguageSelected(lang)">
|
||||||
|
{{ lang.label }}
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
<app-search></app-search>
|
<app-search></app-search>
|
||||||
|
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav">
|
||||||
|
|
|
@ -9,6 +9,11 @@ import { BaseComponent } from '@common/base/base.component';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { UserDialogComponent } from '../misc/navigation/user-dialog/user-dialog.component';
|
import { UserDialogComponent } from '../misc/navigation/user-dialog/user-dialog.component';
|
||||||
import { DATASETS_ROUTES, DMP_ROUTES, GENERAL_ROUTES } from '../sidebar/sidebar.component';
|
import { DATASETS_ROUTES, DMP_ROUTES, GENERAL_ROUTES } from '../sidebar/sidebar.component';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { Language } from '@app/models/language/Language';
|
||||||
|
import { LanguageService } from '@app/core/services/language/language.service';
|
||||||
|
|
||||||
|
const availableLanguages: any[] = require('../../../assets/resources/language.json');
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-navbar',
|
selector: 'app-navbar',
|
||||||
|
@ -22,13 +27,17 @@ export class NavbarComponent extends BaseComponent implements OnInit {
|
||||||
mobile_menu_visible: any = 0;
|
mobile_menu_visible: any = 0;
|
||||||
private toggleButton: any;
|
private toggleButton: any;
|
||||||
private sidebarVisible: boolean;
|
private sidebarVisible: boolean;
|
||||||
|
languages = availableLanguages;
|
||||||
|
language = this.languages[0];
|
||||||
|
|
||||||
|
|
||||||
constructor(location: Location,
|
constructor(location: Location,
|
||||||
private element: ElementRef,
|
private element: ElementRef,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private authentication: AuthService,
|
private authentication: AuthService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private progressIndicationService: ProgressIndicationService
|
private progressIndicationService: ProgressIndicationService,
|
||||||
|
private languageService: LanguageService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
@ -182,4 +191,9 @@ export class NavbarComponent extends BaseComponent implements OnInit {
|
||||||
position: { top: '64px', right: '1em' }
|
position: { top: '64px', right: '1em' }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onLanguageSelected(selectedLanguage: any) {
|
||||||
|
this.languageService.changeLanguage(selectedLanguage.value);
|
||||||
|
this.router.navigate([this.router.url]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||||
import * as moment from 'moment-timezone';
|
import * as moment from 'moment-timezone';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { map, takeUntil } from 'rxjs/operators';
|
import { map, takeUntil } from 'rxjs/operators';
|
||||||
|
import { LanguageService } from '@app/core/services/language/language.service';
|
||||||
|
|
||||||
const availableLanguages: any[] = require('../../../assets/resources/language.json');
|
const availableLanguages: any[] = require('../../../assets/resources/language.json');
|
||||||
|
|
||||||
|
@ -37,8 +38,8 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private language: TranslateService,
|
private language: TranslateService,
|
||||||
private cultureService: CultureService,
|
private cultureService: CultureService,
|
||||||
private translate: TranslateService,
|
private authentication: AuthService,
|
||||||
private authentication: AuthService
|
private languageService: LanguageService
|
||||||
) { super(); }
|
) { super(); }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -126,7 +127,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
|
||||||
.subscribe(
|
.subscribe(
|
||||||
x => {
|
x => {
|
||||||
this.editMode = false;
|
this.editMode = false;
|
||||||
this.translate.use(this.formGroup.value.language);
|
this.languageService.changeLanguage(this.formGroup.value.language.value);
|
||||||
this.authService.current().culture = this.formGroup.value.culture.name;
|
this.authService.current().culture = this.formGroup.value.culture.name;
|
||||||
this.formGroup.disable();
|
this.formGroup.disable();
|
||||||
this.authService.me()
|
this.authService.me()
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,10 @@
|
||||||
"GENERAL": {
|
"GENERAL": {
|
||||||
"VALIDATION": {
|
"VALIDATION": {
|
||||||
"REQUIRED": "Required"
|
"REQUIRED": "Required"
|
||||||
}
|
},
|
||||||
|
"ACTIONS": {
|
||||||
|
"LOG-IN": "Είσοδος"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"USER-PROFILE": {
|
"USER-PROFILE": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
|
|
|
@ -6,5 +6,9 @@
|
||||||
{
|
{
|
||||||
"label": "Greek",
|
"label": "Greek",
|
||||||
"value": "gr"
|
"value": "gr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Spanish",
|
||||||
|
"value": "es"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue