npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

localize-router-ignoreroutes

v0.7.0

Published

An implementation of routes localization for Angular 2

Downloads

3

Readme

localize-router

Build Status npm version

An implementation of routes localization for Angular.

Based on and extension of ngx-translate. Demo project can be found here.

Table of contents:

Installation

npm install --save localize-router

Usage

In order to use localize-router you must initialize it with following information:

  • Available languages/locales
  • Prefix for route segment translations
  • Routes to be translated

Initialize module

Module can be initialized either using static file or manually by passing necessary values.

Static initialization

import {BrowserModule} from "@angular/platform-browser";
import {NgModule} from '@angular/core';
import {HttpModule} from '@angular/http';
import {TranslateModule} from '@ngx-translate/core';
import {LocalizeRouterModule} from 'localize-router/localize-router';
import {RouterModule} from '@angular/router';

import {routes} from './app.routes';

@NgModule({
    imports: [
        BrowserModule,
        HttpModule,
        TranslateModule.forRoot(),
        LocalizeRouterModule.forRoot(routes),
        RouterModule.forRoot(routes)
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

Static file's default path is assets/locales.json. You can override the path by calling StaticParserLoader on you own:

LocalizeRouterModule.forRoot(routes, {
    provide: LocalizeParser,
    useFactory: (translate, location, http) =>
        new StaticParserLoader(translate, location, http, 'your/path/to/config.json'),
    deps: [TranslateService, Location, Http]
})

If you are using child modules or routes you need to initialize them with forChild command:

@NgModule({
  imports: [
    TranslateModule,
    LocalizeRouterModule.forChild(routes),
    RouterModule.forChild(routes)
  ],
  declarations: [ChildComponent]
})
export class ChildModule { }

JSON config file

JSON config file has following structure:

{
    "locales": ["en", "de", ...],
    "prefix": "MY_PREFIX"
}
interface ILocalizeRouteConfig {
    locales: Array<string>;
    prefix?: string;
}

Prefix field is not mandatory and default value is empty string.

Manual initialization

With manual initialization you need to provide information directly:

LocalizeRouterModule.forRoot(routes, {
    provide: LocalizeParser,
    useFactory: (translate, location) =>
        new ManualParserLoader(translate, location, ['en','de',...], 'YOUR_PREFIX'),
    deps: [TranslateService, Location]
})

Server side initialization

In order to use server side initialization in isomorphic/universal projects you need to create loader similar to this:

export class LocalizeUniversalLoader extends LocalizeParser {
  /**
   * Gets config from the server
   * @param routes
   */
  public load(routes: Routes): Promise<any> {
    return new Promise((resolve: any) => {
      let data: any = JSON.parse(fs.readFileSync(`assets/locales.json`, 'utf8'));
      this.locales = data.locales;
      this.prefix = data.prefix;
      this.init(routes).then(resolve);
    });
  }
}

export function localizeLoaderFactory(translate: TranslateService, location: Location) {
  return new LocalizeUniversalLoader(translate, location);
}

Don't forget to create similar loader for ngx-translate as well:

export class TranslateUniversalLoader implements TranslateLoader {
  /**
   * Gets the translations from the server
   * @param lang
   * @returns {any}
   */
  public getTranslation(lang: string): Observable<any> {
    return Observable.create(observer => {
      observer.next(JSON.parse(fs.readFileSync(`src/assets/locales/${lang}.json`, 'utf8')));
      observer.complete();
    });
  }
}
export function translateLoaderFactory() {
  return new TranslateUniversalLoader();
}

Since node server expects to know which routes are allowed you can feed it like this:

let fs = require('fs');
let data: any = JSON.parse(fs.readFileSync(`src/assets/locales.json`, 'utf8'));

app.get('/', ngApp);
data.locales.forEach(route => {
  app.get(`/${route}`, ngApp);
  app.get(`/${route}/*`, ngApp);
});

Working example can be found here.

How it works

Localize router intercepts Router initialization and translates each path and redirectTo path of Routes. The translation process is done with ngx-translate. In order to separate router translations from normal application translations we use prefix. Default value for prefix is ROUTES..

'home' -> 'ROUTES.home'

Upon every route change Localize router kicks in to check if there was a change to language. Translated routes are prepended with two letter language code:

http://yourpath/home -> http://yourpath/en/home

If no language is provided in the url path, application uses:

  • cached language in LocalStorage (browser only) or
  • current language of the browser (browser only) or
  • first locale in the config

Make sure you therefore place most common language (e.g. 'en') as a first string in the array of locales.

Note that localize-router does not redirect routes like my/route to translated ones e.g. en/my/route. All routes are prepended by currently selected language so route without language is unknown to Router.

ngx-translate integration

LocalizeRouter depends on ngx-translate core service and automatically initializes it with selected locales. Following code is run on LocalizeParser init:

this.translate.setDefaultLang(cachedLanguage || languageOfBrowser || firstLanguageFromConfig);
// ...
this.translate.use(languageFromUrl || cachedLanguage || languageOfBrowser || firstLanguageFromConfig);

Both languageOfBrowser and languageFromUrl are cross-checked with locales from config.

Pipe

LocalizeRouterPipe is used to translate routerLink directive's content. Pipe can be appended to partial strings in the routerLink's definition or to entire array element:

<a [routerLink]="['user', userId, 'profile'] | localize">{{'USER_PROFILE' | translate}}</a>
<a [routerLink]="['about' | localize]">{{'ABOUT' | translate}}</a>

Root routes work the same way with addition that in case of root links, link is prepended by language. Example for german language and link to 'about':

'/about' | localize -> '/de/über'

Service

Routes can be manually translated using LocalizeRouterService. This is important if you want to use router.navigate for dynamical routes.

class MyComponent {
    constructor(private localize: LocalizeRouterService) { }

    myMethod() {
        let translatedPath: any = this.localize.translateRoute('about/me');
       
        // do something with translated path
        // e.g. this.router.navigate([translatedPath]);
    }
}

AOT

In order to use Ahead-Of-Time compilation any custom loaders must be exported as functions. This is the implementation currently in the solution:

export function localizeLoaderFactory(translate: TranslateService, location: Location, http: Http) {
  return new StaticParserLoader(translate, location, http);
}

API

LocalizeRouterService

Properties:

  • routerEvents: An EventEmitter to listen to language change event
localizeService.routerEvents.subscribe((language: string) => {
    // do something with language
});
  • parser: Used instance of LocalizeParser
let selectedLanguage = localizeService.parser.currentLang;

Methods:

  • translateRoute(path: string | any[]): string | any[]: Translates given path. If path starts with backslash then path is prepended with currently set language.
localizeService.translateRoute('/'); // -> e.g. '/en'
localizeService.translateRoute('/about'); // -> '/de/uber' (e.g. for German language)
localizeService.translateRoute('about'); // -> 'uber' (e.g. for German language)
  • changeLanguage(lang: string): Translates current url to given language and changes the application's language For german language and route defined as :lang/users/:user_name/profile
yoursite.com/en/users/John%20Doe/profile -> yoursite.com/de/benutzer/John%20Doe/profil

LocalizeParser

Properties:

  • locales: Array of used language codes
  • currentLang: Currently selected language
  • routes: Active translated routes

Methods:

  • translateRoutes(language: string): Observable<any>: Translates all the routes and sets language and current language across the application.
  • translateRoute(path: string): string: Translates single path
  • getLocationLang(url?: string): string: Extracts language from current url if matching defined locales

License

Licensed under MIT