LP#1770973 AngJS-compatible locale selector
authorBill Erickson <berickxx@gmail.com>
Wed, 1 Aug 2018 20:31:06 +0000 (16:31 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 1 Aug 2018 20:31:08 +0000 (16:31 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/core/locale.service.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/nav.component.html
Open-ILS/src/eg2/src/app/staff/nav.component.ts
Open-ILS/src/eg2/src/environments/environment.prod.ts
Open-ILS/src/eg2/src/environments/environment.ts

diff --git a/Open-ILS/src/eg2/src/app/core/locale.service.ts b/Open-ILS/src/eg2/src/app/core/locale.service.ts
new file mode 100644 (file)
index 0000000..9c4ae64
--- /dev/null
@@ -0,0 +1,67 @@
+import {Injectable} from '@angular/core';
+import {Location} from '@angular/common';
+import {environment} from '../../environments/environment';
+import {Observable} from 'rxjs/Observable';
+import 'rxjs/add/observable/of'
+import {CookieService} from 'ngx-cookie';
+import {IdlObject} from '@eg/core/idl.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+
+@Injectable({providedIn: 'root'})
+export class LocaleService {
+
+    constructor(
+        private ngLocation: Location, 
+        private cookieService: CookieService,
+        private pcrud: PcrudService) {
+    }
+
+    setLocale(code: string) {
+        let url = this.ngLocation.prepareExternalUrl('/');
+
+        // The last part of the base path will be the locale
+        // Replace it with the selected locale
+        url = url.replace(/\/[a-z]{2}-[A-Z]{2}\/$/, `/${code}`);
+
+        // Finally tack the path of the current page back onto the URL
+        // which is more friendly than forcing them back to the splash page.
+        url += this.ngLocation.path()
+        
+        // Set a 10-year locale cookie to maintain compatibility
+        // with the AngularJS client.
+        // Cookie takes the form aa_bb instead of aa-BB
+        const cookie = code.replace(/-/, '_').toLowerCase();
+        this.cookieService.put('eg_locale', 
+            cookie, {path : '/', secure: true, expires: '+10y'});
+
+        window.location.href = url;
+    }
+
+    // Returns i18n_l objects
+    supportedLocaleCodes(): string[] {
+        return environment.locales || [];
+    }
+
+    supportedLocales(): Observable<IdlObject> {
+        const locales = this.supportedLocaleCodes();
+
+        if (locales.length === 0) {
+            return Observable.of();
+        }
+
+        return this.pcrud.search('i18n_l', {code: locales});
+    }
+
+    // Extract the local from the URL.
+    // It's the last component of the base path.
+    // Note we don't extract it from the cookie since using cookies
+    // to store the locale will not be necessary when AngularJS 
+    // is deprecated.
+    currentLocaleCode(): string {
+        const base = this.ngLocation.prepareExternalUrl('/');
+        const code = base.match(/\/([a-z]{2}-[A-Z]{2})\/$/);
+        return code ? code[1] : '';
+    }
+}
+
+
index ad002a0..54fb503 100644 (file)
     <div class="navbar-nav" *ngIf="user()">
       <span i18n>{{user()}} @ {{workstation()}}</span>
     </div>
+    <div class="navbar-nav" *ngIf="locales.length > 1 && currentLocale">
+      <div ngbDropdown class="nav-item dropdown" placement="bottom-right">
+        <!-- TODO set / display current locale -->
+        <a ngbDropdownToggle i18n i18n-title
+          title="Select Locale"
+          class="nav-link dropdown-toggle no-caret with-material-icon">
+          <i class="material-icons">flag</i>
+          <span>{{currentLocale.name()}}</span>
+        </a>
+        <div class="dropdown-menu" ngbDropdownMenu>
+          <a class="dropdown-item" (click)="setLocale(locale)" 
+            [ngClass]="{disabled: currentLocale.code() == locale.code()}"
+            *ngFor="let locale of locales">
+            <span class="material-icons">add_location</span>
+            <span i18n>{{locale.name()}}</span>
+          </a>
+        </div>
+      </div>
+    </div>
     <div class="navbar-nav" *ngIf="user()">
       <div ngbDropdown class="nav-item dropdown" placement="bottom-right">
         <a ngbDropdownToggle i18n 
index c528d03..a6720f5 100644 (file)
@@ -1,6 +1,9 @@
 import {Component, OnInit, ViewChild} from '@angular/core';
 import {ActivatedRoute, Router} from '@angular/router';
+import {Location} from '@angular/common';
 import {AuthService} from '@eg/core/auth.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {LocaleService} from '@eg/core/locale.service';
 import {PrintService} from '@eg/share/print/print.service';
 
 @Component({
@@ -11,13 +14,31 @@ import {PrintService} from '@eg/share/print/print.service';
 
 export class StaffNavComponent implements OnInit {
 
+    // Locales that have Angular staff translations
+    locales: any[];
+    currentLocale: any;
+
     constructor(
         private router: Router,
         private auth: AuthService,
+        private pcrud: PcrudService,
+        private locale: LocaleService,
         private printer: PrintService
-    ) {}
+    ) {
+        this.locales = [];
+    }
 
     ngOnInit() {
+
+        this.locale.supportedLocales().subscribe(
+            l => this.locales.push(l),
+            err => {},
+            () => {
+                this.currentLocale = this.locales.filter(
+                    l => l.code() === this.locale.currentLocaleCode())[0]
+                console.log('current locale ' + this.currentLocale.code());
+            }
+        );
     }
 
     user() {
@@ -28,6 +49,10 @@ export class StaffNavComponent implements OnInit {
         return this.auth.user() ? this.auth.workstation() : '';
     }
 
+    setLocale(locale: any) {
+        this.locale.setLocale(locale.code());
+    }
+
     opChangeActive(): boolean {
         return this.auth.opChangeIsActive();
     }
index 3612073..50385bf 100644 (file)
@@ -1,3 +1,4 @@
 export const environment = {
-  production: true
+  production: true,
+  locales: ['en-US', 'fr-CA']
 };
index b7f639a..113cbe3 100644 (file)
@@ -4,5 +4,7 @@
 // The list of which env maps to which file can be found in `.angular-cli.json`.
 
 export const environment = {
-  production: false
+  production: false,
+  // currently locales are only supported in production builds.
+  locales: ['en-US']
 };