简体   繁体   English

如何创建有角度的多语言路由路径

[英]how to create an angular multilingual routing path

I'm using the ngx-translate library to add multilingual support to my lazy loaded Angular website.我正在使用ngx-translate库为我的延迟加载的 Angular 网站添加多语言支持。
I was wondering how to properly add multilingual logics to the angular routing system.我想知道如何将多语言逻辑正确添加到角度路由系统中。

Example例子

// HOME is my exported variable containing my routes
export const routes: Routes = [{
 path: HOME, 
 loadChildren: () => import('app/pages/home.module').then((m) => m.HomeModule),
}]

Now, when a user comes on my website, he should find the home pages with those URLs现在,当用户访问我的网站时,他应该找到带有这些 URL 的主页

  • English : my-domain/home中文 : my-domain/home
  • French : my-domain/acceuil法语 : my-domain/acceuil
  • German : my-domain/startseite德语 : my-domain/startseite

I know, I could create multiple app-routing.module.ts files, one for each language, but when the website have many pages and should be translated in many languages, it become overcomplicated to use this technique.我知道,我可以创建多个app-routing.module.ts文件,每种语言一个,但是当网站有很多页面并且应该翻译成多种语言时,使用这种技术变得过于复杂。

Edit编辑

An other Idea was to reload the page, be even through this solution, I'll then have to change the url, what is also complicated in an nested routing system.另一个想法是重新加载页面,即使通过这个解决方案,我也必须更改 url,这在嵌套路由系统中也很复杂。 like :喜欢 :

  • English : my-domain/en/products/my-product中文 : my-domain/en/products/my-product
  • French : my-domain/fr/produits/mon-produit法语 : my-domain/fr/produits/mon-produit

I'm guessing HOME is a constant.我猜HOME是一个常数。

What if you create a config object that gets initialized / updated when you change language, and it simply changes the values.. for example:如果您创建一个在更改语言时初始化/更新的配置对象,并且它只是更改值.. 例如:

const PATHS = {
  en: {
    home: 'home',
  },
  fr: {
    home: 'acceuil',
  },
  it: {
    home: 'inizio',
  }
}

and then you just substitute HOME with PATHS[language].home , and language is whatever the language is set to, it could even be another property of your config object.然后您只需将 HOME 替换为PATHS[language].home ,并且语言是语言设置的任何内容,它甚至可能是您的配置对象的另一个属性。

config = {
  currentLanguage: 'en',
  paths: {},
}

as long as it's available to all, it should be fine (create a root config.ts object, and export these variables, and modify them wherever imported as needed)只要它对所有人可用,应该没问题(创建一个根 config.ts 对象,并导出这些变量,并根据需要在导入的任何地方修改它们)

export const routes: Routes = [{
 path: config.path[config.currentLanguage].home, 
 loadChildren: () => import('app/pages/home.module').then((m) => m.HomeModule),
}]

you could even make this become more specialized by creating a function / generator that retrieves what you want particularly, but that's a little way too much for this example您甚至可以通过创建一个函数/生成器来检索您特别想要的内容,从而使其变得更加专业化,但这对于本示例来说有点太多了

First of all, here is the stackblitz of the working code首先,这是工作代码的stackblitz

All the ideas presented in this answer are compiled together in the snippet (stackblitz) bellow:此答案中提出的所有想法都汇总在下面的代码段 (stackblitz) 中:

https://stackblitz.com/edit/angular-ivy-bys583 https://stackblitz.com/edit/angular-ivy-bys583

About changing routes with no need to refresh关于无需刷新即可更改路线

In order to change the routes without refreshing the page, you may access the list of routes in route.config and change the property path of the desired route.为了在不刷新页面的情况下更改路由,您可以访问route.config中的路由列表并更改所需路由的属性path

Just to show how it works, see the simple example bellow, where the route /home is changed to /accueil , no need to refresh the app:只是为了展示它是如何工作的,请参阅下面的简单示例,其中路由/home更改为/accueil ,无需刷新应用程序:

import { Router } from '@angular/router';

export class AppComponent {

  constructor(private router: Router){}

  changeHomeRoute(){
    for (let route of this.router.config){
      if (route.path == 'home'){
        route.path = 'accueil';
      }
    }
  }
}

Storing language in localStorage and setting default route on application start在 localStorage 中存储语言并在应用程序启动时设置默认路由

Let´s work on a simple application that has three supported languages ( en , fr and de ) and only one component ( HomeComponent ).让我们开发一个简单的应用程序,它具有三种支持的语言( enfrde )和只有一个组件( HomeComponent )。

First of all, as suggested by the OP, one option is to store the language in localStorage .首先,正如 OP 所建议的,一种选择是将语言存储在localStorage

The paths of the routes may be stored in an const like that:路由的路径可以像这样存储在一个常量中:

route-paths.ts路由路径.ts

export const DEFAULT_LANGUAGE = "en";

export const ROUTE_PATHS = {
    de: {
        home: 'startseite'
    },
    en: {
        home: 'home'
    },
    fr: {
        home: 'accueil'
    }
};

During application first load the routes may be configured like that:在应用程序首次加载期间,路由可以这样配置:

app-routing.module.ts app-routing.module.ts

import { DEFAULT_LANGUAGE, ROUTE_PATHS } from './route-paths';

const routes: Routes = [
  {
    path: localStorage.getItem('lang') ? ROUTE_PATHS[localStorage.getItem('lang')]['home'] : ROUTE_PATHS[DEFAULT_LANGUAGE]['home'],
    component: HomeComponent
  }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Changing language triggers update in the routes and in the menu of the app更改语言会触发routes和应用程序menu中的更新

In the following code you can see examples of在以下代码中,您可以看到以下示例

  • Changing the language in the <select> and updating the routes accordingly (see method onChangeLang() that changes the routes using route.config[i].path ).更改<select>的语言并相应地更新路由(请参阅使用route.config[i].path更改路由的方法onChangeLang() )。
  • Automatically updating the menu links once the routes have changed (see the ngFor and the routes() method).一旦路由发生变化,自动更新菜单链接(参见ngForroutes()方法)。

app.component.html应用程序组件.html

<div>
  Language:
  <select (change)="onChangeLang($event)">
    <option *ngFor="let lang of languagesAvailable" [value]="lang" [selected]="langSelected == lang">{{lang}}</option>
  </select>

  <div>
    <span>Menu:</span>
    <a *ngFor="let route of routes() | keyvalue" [routerLink]="['/' + route.value]">
      {{route.value}} 
    </a>
  </div>
</div>

<router-outlet></router-outlet>

app.component.ts app.component.ts

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { DEFAULT_LANGUAGE, ROUTE_PATHS } from './route-paths';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  languagesAvailable = ['de', 'en', 'fr'];
  
  langSelected = null;

  constructor(private router: Router){}

  ngOnInit(){
    this.langSelected = localStorage.getItem('lang');
    if (!this.langSelected){
      this.langSelected = DEFAULT_LANGUAGE;
      localStorage.setItem('lang', this.langSelected);
    }
  }

  onChangeLang(event){
    let previousLanguage = this.langSelected;
    let newLanguage = event.target.value;
    
    console.log('Routes before:');
    this.printRoutes();

    for (let route of this.router.config){
      for(let routeId in ROUTE_PATHS[previousLanguage]){
        let oldRoute = ROUTE_PATHS[previousLanguage][routeId];
        if (oldRoute == route.path){
          let newRoute = ROUTE_PATHS[newLanguage][routeId];
          console.log('old route for ' + routeId + ' is ' + route.path + '. Changing to ' + newRoute);
          route.path = ROUTE_PATHS[newLanguage][routeId];
        }
      }     
    };

    this.langSelected = newLanguage;
    localStorage.setItem('lang', this.langSelected);

    console.log('Routes after:');
    this.printRoutes();
  }

  routes(){
    return ROUTE_PATHS[this.langSelected];
  }

  printRoutes(){
    this.router.config.forEach(function(route, index, routes){
      console.log(route);        
    });
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM