Skip to content

Commit

Permalink
feat(i18n): browser tab page title translations
Browse files Browse the repository at this point in the history
  • Loading branch information
tomastrajan committed Aug 1, 2018
1 parent bb44d0e commit 8a5346d
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 56 deletions.
2 changes: 1 addition & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
{
"type": "bundle",
"name": "vendor",
"baseline": "700kb",
"baseline": "750kb",
"warning": "100kb",
"error": "200kb"
},
Expand Down
4 changes: 1 addition & 3 deletions src/app/app-routing.module.ts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ const routes: Routes = [
{
path: 'settings',
component: SettingsComponent,
data: {
title: 'Settings'
}
data: { title: 'anms.menu.settings' }
},
{
path: 'examples',
Expand Down
43 changes: 12 additions & 31 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import browser from 'browser-detect';
import { Title } from '@angular/platform-browser';
import { OverlayContainer } from '@angular/cdk/overlay';
import { Component, HostBinding, OnDestroy, OnInit } from '@angular/core';
import { ActivationEnd, Router, NavigationEnd } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { Store } from '@ngrx/store';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { takeUntil } from 'rxjs/operators';

import {
ActionAuthLogin,
ActionAuthLogout,
AnimationsService,
TitleService,
selectorAuth,
routeAnimations
} from '@app/core';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class AppComponent implements OnInit, OnDestroy {
public overlayContainer: OverlayContainer,
private store: Store<any>,
private router: Router,
private titleService: Title,
private titleService: TitleService,
private animationService: AnimationsService,
private translate: TranslateService
) {}
Expand Down Expand Up @@ -154,33 +154,14 @@ export class AppComponent implements OnInit, OnDestroy {
}

private subscribeToRouterEvents() {
this.router.events
.pipe(
filter(
event =>
event instanceof ActivationEnd || event instanceof NavigationEnd
),
takeUntil(this.unsubscribe$)
)
.subscribe(event => {
if (event instanceof ActivationEnd) {
this.setPageTitle(event);
}

if (event instanceof NavigationEnd) {
AppComponent.trackPageView(event);
}
});
}

private setPageTitle(event: ActivationEnd) {
let lastChild = event.snapshot;
while (lastChild.children.length) {
lastChild = lastChild.children[0];
}
const { title } = lastChild.data;
this.titleService.setTitle(
title ? `${title} - ${env.appName}` : env.appName
);
this.router.events.pipe(takeUntil(this.unsubscribe$)).subscribe(event => {
if (event instanceof ActivationEnd) {
this.titleService.setTitle(event.snapshot);
}

if (event instanceof NavigationEnd) {
AppComponent.trackPageView(event);
}
});
}
}
8 changes: 7 additions & 1 deletion src/app/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { authReducer } from './auth/auth.reducer';
import { AuthEffects } from './auth/auth.effects';
import { AuthGuardService } from './auth/auth-guard.service';
import { AnimationsService } from './animations/animations.service';
import { TitleService } from './title/title.service';

export const metaReducers: MetaReducer<any>[] = [initStateFromLocalStorage];

Expand Down Expand Up @@ -51,7 +52,12 @@ if (!environment.production) {
})
],
declarations: [],
providers: [LocalStorageService, AuthGuardService, AnimationsService],
providers: [
LocalStorageService,
AuthGuardService,
AnimationsService,
TitleService
],
exports: [TranslateModule]
})
export class CoreModule {
Expand Down
1 change: 1 addition & 0 deletions src/app/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export * from './animations/route.animations';
export * from './animations/animations.service';
export * from './auth/auth.reducer';
export * from './auth/auth-guard.service';
export * from './title/title.service';
export * from './core.module';
38 changes: 38 additions & 0 deletions src/app/core/title/title.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Title } from '@angular/platform-browser';
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { filter } from 'rxjs/operators';

import { environment as env } from '@env/environment';

@Injectable()
export class TitleService {
constructor(
private translateService: TranslateService,
private title: Title
) {
}

setTitle(
snapshot: ActivatedRouteSnapshot,
lazyTranslateService?: TranslateService
) {
let lastChild = snapshot;
while (lastChild.children.length) {
lastChild = lastChild.children[0];
}
const { title } = lastChild.data;
const translate = lazyTranslateService || this.translateService;
if (title) {
translate
.get(title)
.pipe(filter(translatedTitle => translatedTitle !== title))
.subscribe(translatedTitle =>
this.title.setTitle(`${translatedTitle} - ${env.appName}`)
);
} else {
this.title.setTitle(env.appName);
}
}
}
16 changes: 4 additions & 12 deletions src/app/examples/examples-routing.module.ts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,23 @@ const routes: Routes = [
{
path: 'todos',
component: TodosComponent,
data: {
title: 'Todos'
}
data: { title: 'anms.examples.menu.todos' }
},
{
path: 'stock-market',
component: StockMarketComponent,
data: {
title: 'Stock Market'
}
data: { title: 'anms.examples.menu.stocks' }
},
{
path: 'theming',
component: ParentComponent,
data: {
title: 'Theming'
}
data: { title: 'anms.examples.menu.theming' }
},
{
path: 'authenticated',
component: AuthenticatedComponent,
canActivate: [AuthGuardService],
data: {
title: 'Authenticated'
}
data: { title: 'anms.examples.menu.auth' }
}
]
}
Expand Down
3 changes: 2 additions & 1 deletion src/app/examples/examples/examples.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { CoreModule } from '@app/core';
import { TestingModule } from '@testing/utils';

import { ExamplesComponent } from './examples.component';
Expand All @@ -11,7 +12,7 @@ describe('ExamplesComponent', () => {
beforeEach(
async(() => {
TestBed.configureTestingModule({
imports: [TestingModule],
imports: [TestingModule, CoreModule],
declarations: [ExamplesComponent]
}).compileComponents();
})
Expand Down
43 changes: 38 additions & 5 deletions src/app/examples/examples/examples.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Store } from '@ngrx/store';
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { takeUntil } from 'rxjs/operators';
import { ActivationEnd, Router } from '@angular/router';
import { filter, takeUntil, map } from 'rxjs/operators';
import { Subject } from 'rxjs';

import { routeAnimations } from '@app/core';
import { routeAnimations, TitleService } from '@app/core';
import { selectorSettings, SettingsState } from '@app/settings';

@Component({
Expand All @@ -13,7 +14,7 @@ import { selectorSettings, SettingsState } from '@app/settings';
styleUrls: ['./examples.component.scss'],
animations: [routeAnimations]
})
export class ExamplesComponent implements OnInit {
export class ExamplesComponent implements OnInit, OnDestroy {
private unsubscribe$: Subject<void> = new Subject<void>();

examples = [
Expand All @@ -23,15 +24,47 @@ export class ExamplesComponent implements OnInit {
{ link: 'authenticated', label: 'anms.examples.menu.auth' }
];

constructor(private store: Store<any>, private translate: TranslateService) {}
constructor(
private store: Store<any>,
private router: Router,
private titleService: TitleService,
private translate: TranslateService
) {
}

ngOnInit(): void {
this.translate.setDefaultLang('en');
this.subscribeToSettings();
this.subscribeToRouterEvents();
}

ngOnDestroy(): void {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}

private subscribeToSettings() {
this.store
.select(selectorSettings)
.pipe(takeUntil(this.unsubscribe$))
.subscribe((settings: SettingsState) =>
this.translate.use(settings.language)
);
}

private subscribeToRouterEvents() {
this.titleService.setTitle(
this.router.routerState.snapshot.root,
this.translate
);
this.router.events
.pipe(
filter(event => event instanceof ActivationEnd),
map((event: ActivationEnd) => event.snapshot),
takeUntil(this.unsubscribe$)
)
.subscribe(snapshot =>
this.titleService.setTitle(snapshot, this.translate)
);
}
}
8 changes: 6 additions & 2 deletions src/app/static/static-routing.module.ts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import { AboutComponent } from './about/about.component';
import { FeaturesComponent } from './features/features.component';

const routes: Routes = [
{ path: 'about', component: AboutComponent, data: { title: 'About' } },
{
path: 'about',
component: AboutComponent,
data: { title: 'anms.menu.about' }
},
{
path: 'features',
component: FeaturesComponent,
data: { title: 'Features' }
data: { title: 'anms.menu.features' }
}
];

Expand Down

0 comments on commit 8a5346d

Please sign in to comment.