Skip to content

Commit

Permalink
ADMIN: Switch translation on the fly
Browse files Browse the repository at this point in the history
* NEW: Switch language on admin interface on the fly

Co-authored-by: Peter Weber <peter.weber@rero.ch>
Signed-off-by: Bertrand Zuchuat <bertrand.zuchuat@rero.ch>
Garfield-fr and rerowep committed Dec 19, 2018
1 parent 71eaac0 commit f417ce6
Showing 20 changed files with 86 additions and 71 deletions.
8 changes: 7 additions & 1 deletion rero_ils/modules/patrons/views.py
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@
from flask_babelex import gettext as _
from flask_login import current_user, login_required
from flask_menu import register_menu
from invenio_i18n.ext import current_i18n
from werkzeug.exceptions import NotFound

from ..documents.api import Document
@@ -100,7 +101,12 @@ def logger_user():
patron = Patron.get_patron_by_user(current_user)
if patron is None:
raise NotFound()
return jsonify(patron.dumps())
patronDumps = patron.dumps()
# TODO: Find a better way to transfert user settings
patronDumps['settings'] = {
'language': current_i18n.locale.language
}
return jsonify(patronDumps)


@blueprint.app_template_filter('get_patron_from_barcode')
29 changes: 2 additions & 27 deletions ui/admin/angular.json
Original file line number Diff line number Diff line change
@@ -44,34 +44,10 @@
"with": "src/environments/environment.prod.ts"
}
],
"aot": true,
"aot": false,
"i18nLocale": "fr"
},
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
},
"fr": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
@@ -94,9 +70,8 @@
"maximumError": "5mb"
}
],
"i18nLocale": "fr",
"i18nLocale": "en",
"deployUrl": "/static/js/rero_ils/admin/",
"sourceMap": false,
"outputPath": "../../rero_ils/static/js/rero_ils/admin"
}
}
6 changes: 3 additions & 3 deletions ui/admin/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ui/admin/package.json
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"deploy": "ng build --configuration=fr",
"deploy": "ng build --configuration=production",
"proxy": "ng serve --configuration=proxy",
"extract_messages": "ngx-translate-extract -i ./src -o ./src/assets/i18n/en*.json -m _; key2value.py ./src/assets/i18n/en_US.json; key2value.py ./src/assets/i18n/en.json",
"update_catalog": "ngx-translate-extract -i ./src -o ./src/assets/i18n/{it,de,en,fr}.json -m _"
@@ -33,7 +33,7 @@
"datatables.net-bs": "^1.10.19",
"jquery": "^3.3.1",
"moment": "^2.22.2",
"ngx-bootstrap": "3.0.1",
"ngx-bootstrap": "^3.1.3",
"ngx-toggle-switch": "^2.0.5",
"rxjs": "~6.3.3",
"zone.js": "~0.8.26"
16 changes: 13 additions & 3 deletions ui/admin/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, Input } from '@angular/core';
import { UserService } from './user.service';
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment';

@Component({
selector: 'app-root',
@@ -8,9 +10,17 @@ import { UserService } from './user.service';
})
export class AppComponent implements OnInit {

constructor(private userService: UserService) {}
constructor(
private userService: UserService,
private translate: TranslateService
) {}

ngOnInit() {
this.userService.loggedUser.subscribe();
this.userService.loggedUser.subscribe(user => {
if (user) {
moment.locale(user.settings.language);
this.translate.use(user.settings.language);
}
});
}
}
28 changes: 17 additions & 11 deletions ui/admin/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { BrowserModule } from '@angular/platform-browser';
import { LOCALE_ID, Inject, NgModule } from '@angular/core';
import { NgModule, LOCALE_ID } from '@angular/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { BsLocaleService } from 'ngx-bootstrap/datepicker';
import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import * as moment from 'moment';
import { AlertModule } from 'ngx-bootstrap/alert';
import { ModalModule } from 'ngx-bootstrap/modal';
import { environment } from '../environments/environment';
@@ -21,7 +20,11 @@ export function HttpLoaderFactory(http: HttpClient) {
if (environment.production) {
assets_prefix = '/static/js/rero_ils/admin/';
}
return new TranslateHttpLoader(http, assets_prefix + 'assets/i18n/', '.json');
return new TranslateHttpLoader(
http,
assets_prefix + 'assets/i18n/',
'.json?cacheBuster=' + environment.cacheBusterHash
);
}


@@ -39,15 +42,21 @@ export function HttpLoaderFactory(http: HttpClient) {
AlertModule.forRoot(),
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
providers: [
UserService,
BsLocaleService
BsLocaleService,
TranslateService,
{
provide: LOCALE_ID,
deps: [TranslateService],
useFactory: (translate) => translate.currentLang
}
],
bootstrap: [
AppComponent
@@ -63,12 +72,9 @@ export class AppModule {

constructor(
private translate: TranslateService,
private localeService: BsLocaleService,
@Inject(LOCALE_ID) locale
private localeService: BsLocaleService
) {
moment.locale(locale);
translate.setDefaultLang('en');
translate.use(locale);
for (const [key, value] of Object.entries(this.languages)) {
defineLocale(key, value);
}
Original file line number Diff line number Diff line change
@@ -71,11 +71,11 @@ <h3 class="modal-title" *ngIf="index == null">{{ 'Add' | translate }}</h3>
<div class="col-sm-10 mt-2">
<span class="mb-2" *ngIf="exceptionForm.value.is_open">
{{ 'Opened on' | translate }}
{{ exceptionForm.value.date | date : 'EEEE' }}
{{ exceptionForm.value.date | date : 'EEEE' | lowercase | translate }}
</span>
<span class="mb-2" *ngIf="!exceptionForm.value.is_open">
{{ 'Closed on' | translate }}
{{ exceptionForm.value.date | date : 'EEEE' }}
{{ exceptionForm.value.date | date : 'EEEE' | lowercase | translate }}
</span>
<div class="mb-2">
<em *ngIf="exceptionForm.value && exceptionForm.value.is_open">
@@ -111,7 +111,7 @@ <h3 class="modal-title" *ngIf="index == null">{{ 'Add' | translate }}</h3>
type="button"
*ngIf="times.length == 1"
class="btn btn-light btn-sm"(click)="addTime()"
><i class="fa fa-plus" aria-hidden="true"></i> {{ 'period' || translate }}</button>
><i class="fa fa-plus" aria-hidden="true"></i> {{ 'period' | translate }}</button>
</div>
</div>
<div
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { BsLocaleService } from 'ngx-bootstrap/datepicker';
import { FormArray, FormGroup } from '@angular/forms';
@@ -7,6 +7,7 @@ import * as moment from 'moment';
import { LibraryExceptionFormService } from '../library-exception-form.service';
import { LibrariesService } from '../libraries.service';
import { Library } from '../library';
import { TranslateService } from '@ngx-translate/core';

@Component({
selector: 'libraries-exception-dates-edit',
@@ -24,11 +25,11 @@ export class ExceptionDatesEditComponent implements OnInit {
public bsModalRef: BsModalRef,
public form: LibraryExceptionFormService,
public librariesService: LibrariesService,
@Inject(LOCALE_ID) locale
private translate: TranslateService
) {
this.form.build();
this.exceptionForm = this.form.form;
this.localeService.use(locale);
this.localeService.use(this.translate.currentLang);
}

ngOnInit() {
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
{{ time.start_time }}-{{ time.end_time }}
</div>
<div *ngIf="exception.repeat">
<i class="fa fa-repeat" aria-hidden="true" title="repeated"></i> {{ exception.repeat.period }}={{ exception.repeat.interval }}
<i class="fa fa-repeat" aria-hidden="true" title="repeated"></i> {{ exception.repeat.period | translate }}={{ exception.repeat.interval }}
</div>
</td>
<td class="text-right">
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, Inject, LOCALE_ID } from '@angular/core';
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
import { ExceptionDatesEditComponent } from '../exception-dates-edit/exception-dates-edit.component';

@@ -13,7 +13,10 @@ export class ExceptionDatesListComponent implements OnInit {

@Input() library;

constructor(private modalService: BsModalService) {}
constructor(
private modalService: BsModalService,
@Inject(LOCALE_ID) locale: string
) { }

ngOnInit() {
}
6 changes: 4 additions & 2 deletions ui/admin/src/app/libraries/library-form.service.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import { Library } from './library';
import { TimeValidator } from '../shared/time-validator';
import { LibraryCodeUniqueValidator } from '../shared/library-code-unique-validator';
import { LibrariesService } from './libraries.service';
import { WeekDays } from '../shared/week-days';

@Injectable()
export class LibraryFormService {
@@ -40,7 +41,8 @@ export class LibraryFormService {
Validators.required
],
asyncValidators: [
this.libraryCodeUniqueValidator.validate.bind(this.libraryCodeUniqueValidator)
// TODO: Debug multiple call on request
// this.libraryCodeUniqueValidator.validate.bind(this.libraryCodeUniqueValidator)
],
updateOn: 'blur'
}],
@@ -49,7 +51,7 @@ export class LibraryFormService {
}

createOpeningHours() {
const days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
const days = Object.keys(WeekDays);
const openings = [];
for (let step = 0; step < 7; step++) {
openings.push(this.buildOpeningHours(false, days[step], this.fb.array([this.buildTimes()])));
2 changes: 1 addition & 1 deletion ui/admin/src/app/libraries/library/library.component.html
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ <h1>{{ 'Library' | translate }}</h1>
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label required">Code</label>
<label for="email" class="col-sm-2 col-form-label required">{{ 'Code' | translate }}</label>
<div class="col-sm-10">
<input
id="code"
5 changes: 5 additions & 0 deletions ui/admin/src/app/users.ts
Original file line number Diff line number Diff line change
@@ -18,9 +18,14 @@ export class User {
street: string;
organisation_pid: string;
barcode?: string;
settings: UserSettings;
loans?: Loan[];

constructor(obj?: any) {
Object.assign(this, obj);
}
}

export interface UserSettings {
language: string;
}
1 change: 1 addition & 0 deletions ui/admin/src/assets/i18n/de.json
Original file line number Diff line number Diff line change
@@ -93,6 +93,7 @@
"Address must be at least 4 characters long.": "",
"Email": "",
"Email format is not correct.": "",
"Code": "",
"Please insert a code": "",
"Code is already taken.": "",
"Validating…": "",
17 changes: 9 additions & 8 deletions ui/admin/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
@@ -21,13 +21,13 @@
"Please enter an item barcode.": "Please enter an item barcode.",
"request not found": "request not found",
"The item is ": "The item is ",
"monday": "monday",
"tuesday": "tuesday",
"wednesday": "wednesday",
"thursday": "thursday",
"friday": "friday",
"saturday": "saturday",
"sunday": "sunday",
"monday": "Monday",
"tuesday": "Tuesday",
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"saturday": "Saturday",
"sunday": "Sunday",
"Document": "Document",
"Item": "Item",
"Location": "Location",
@@ -93,6 +93,7 @@
"Address must be at least 4 characters long.": "Address must be at least 4 characters long.",
"Email": "Email",
"Email format is not correct.": "Email format is not correct.",
"Code": "Code",
"Please insert a code": "Please insert a code",
"Code is already taken.": "Code is already taken.",
"Validating…": "Validating…",
@@ -135,4 +136,4 @@
"Deadline": "Deadline",
"Return date": "Return date",
"The returned item has requests!": "The returned item has pending requests!"
}
}
1 change: 1 addition & 0 deletions ui/admin/src/assets/i18n/en_US.json
Original file line number Diff line number Diff line change
@@ -93,6 +93,7 @@
"Address must be at least 4 characters long.": "Address must be at least 4 characters long.",
"Email": "Email",
"Email format is not correct.": "Email format is not correct.",
"Code": "Code",
"Please insert a code": "Please insert a code",
"Code is already taken.": "Code is already taken.",
"Validating\u2026": "Validating\u2026",
5 changes: 3 additions & 2 deletions ui/admin/src/assets/i18n/fr.json
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@
"Repeat": "Répéter",
"daily": "journalisé",
"weekly": "hebdomadaire",
"monthly": "menuelle",
"monthly": "mensuelle",
"yearly": "annuelle",
"Interval is required.": "L'intervale est obligatoire.",
"Interval must greater than 0.": "L'intervale doit être supérieur à 0.",
@@ -89,10 +89,11 @@
"Please insert a name": "Veuillez introduire un nom",
"Name is required.": "Le nom est obligatoire.",
"Name must be at least 4 characters long.": "Le nom doit être supérieur à 4 caractères.",
"Address": "Addresse",
"Address": "Adresse",
"Address must be at least 4 characters long.": "L'adresse doit être supérieur à 4 caractères.",
"Email": "E-mail",
"Email format is not correct.": "Le format de l'email est incorrect.",
"Code": "Code",
"Please insert a code": "Veuillez introduire un code",
"Code is already taken.": "Le code est déjà utilisé.",
"Validating…": "Validation…",
1 change: 1 addition & 0 deletions ui/admin/src/assets/i18n/it.json
Original file line number Diff line number Diff line change
@@ -93,6 +93,7 @@
"Address must be at least 4 characters long.": "",
"Email": "",
"Email format is not correct.": "",
"Code": "",
"Please insert a code": "",
"Code is already taken.": "",
"Validating…": "",
3 changes: 2 additions & 1 deletion ui/admin/src/environments/environment.prod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const environment = {
production: true
production: true,
cacheBusterHash: 'da39a3ee5e6b4b0d3255bfef95601890afd80711'
};
3 changes: 2 additions & 1 deletion ui/admin/src/environments/environment.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@
// The list of file replacements can be found in `angular.json`.

export const environment = {
production: false
production: false,
cacheBusterHash: 'da39a3ee5e6b4b0d3255bfef95601890afd80711'
};

/*

0 comments on commit f417ce6

Please sign in to comment.