首页 文章

在routerLink中的Angular 5 - ngx-translate

提问于
浏览
1

在我的项目(Angular 5 Firebase)中,用户需要在登录页面选择语言 . 为此,我添加了选择选项并将所选值作为参数传递给第一页,如下所示:

form_login(f:NgForm){
    if (!f.valid)
      return;
    this.afAuth.auth.signInWithEmailAndPassword(f.controls.email.value, f.controls.password.value)
      .then(ok => {     
        this.router.navigate(["/perfil", f.controls.lang.value]); //>> here
      });
  }

在url中使用此参数,我检索此值并使用ngx-translate翻译整个页面,如下所示:

perfil.component.ts

import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';

constructor(private translate: TranslateService,  
    private route: ActivatedRoute, 
    private router: Router) { 

      ...
      translate.setDefaultLang('en');

      let lang = this.route.snapshot.paramMap.get('lang');
      this.translate.use(lang);
      console.log(lang);
    }

perfil.component.html

<h5 translate>Companyprofile</h5>

它完美无缺 . 除非因为还有导航栏,否则此组件根本不会获得语言值 . 虽然翻译了链接标签,但每个 routerLink 的值都没有捕获参数的值,而是将每个链接设置为 undefined ,其中应该是该语言的值 .

navbar.component.ts

import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';

constructor(private translate: TranslateService,  
    private route: ActivatedRoute, 
    private router: Router) { 

      ...
      translate.setDefaultLang('en');

      let lang = this.route.snapshot.paramMap.get('lang');
      this.translate.use(lang);
      console.log(lang); // >> in this case, the console displays `null`
    }

试图在navbar.component.ts上获取此值,我在控制台上有这个错误:

navbar.component.ts:36 null
zone.js:2935 GET http://localhost:4200/assets/i18n/null.json 404 (Not Found)

core.js:1440 ERROR HttpErrorResponse {headers: HttpHeaders, status: 404, statusText: "Not Found", url: "http://localhost:4200/assets/i18n/null.json", ok: false, …}

navbar.component.html

<header id="topnav">
   <ul class="navbar-nav" *ngFor="let p of perfil | async">
     <li class="nav-item">
       <a [routerLink]="['/agenda/', lang]" class="nav-link" translate>Agenda</a>
     </li>
     <li class="nav-item">
       <a [routerLink]="['/admin/', lang]" class="nav-link" translate>Admin</a>
     </li>
   ...
   </ul>
 </header>
 <router-outlet></router-outlet> <!-- here I call other components, e.g perfil.component.html

例如, lang 参数应带值 'en' . 但是,相反,它是 undefined .

EDIT: 我的所有组件都是 NavbarComponent 的子组件 . NavbarComponent 没有 path ,因此无法在其上设置参数,就像我在其他路径中所做的那样 .

app.routing.module.ts

const AppRoutes: Routes = [

    {path: '', component: AppComponent, children: [
        { path: '', redirectTo: '/login', pathMatch: 'full' },
        {path: '', component: NavbarComponent, children: [
            {path: 'agenda/:lang', component: AgendaComponent},
            {path: 'perfil/:lang', component: PerfilComponent},
            {path: 'servicos/:lang', component: CadastroServicoComponent},
            {path: 'profissionais/:lang', component: ProfissionaisComponent},
            {path: 'admin/:lang', component: AdminComponent},
            {path: 'dashboard/:lang', component: DashboardComponent},
            {path: 'signup/:lang', component: SignUpFormComponent}
        ]}
    ]}
]    

@NgModule({
imports: [RouterModule.forRoot(AppRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

代码有什么问题?

1 回答

  • 0

    好的,这是基于我从代码中可以看到的建议 .

    您的导航栏可能作为子组件在您的一个组件内部调用,可能就像 perfil.component.html 中的这样 .

    <navbar [parameters...]></navbar>
    

    我不是100%肯定这一点,但我想 ActivatedRoute 注入仅适用于通过直接路由器链接加载的组件,而不适用于子模块(我真的不确定) . 这意味着 AcitvatedRoute 适用于 perfil.component 但不适用于 navbar.component (因为未从您的路由器调用) . 但是,如果如上所示调用导航栏,则可以将 lang 变量从 perfil.component 发送到导航栏作为输入参数 .

    这是 perfil.component.html

    <navbar [lang]="lang"></navbar>
    

    这是 navbar.component.ts

    // the lang string is now an input parameter
    @Input() lang: string;
    
    constructor(private translate: TranslateService, private router: Router) { 
      ...
      // the default language should already been set in the parent component
      // NO NEED: translate.setDefaultLang('en');
    }
    
    // the input parameter are not yet availbable in the constructor, but on init
    ngOnInit(){
      this.translate.use(lang);
      console.log(lang);
    }
    

    希望这可以帮助 .


    编辑

    看到你的命令后,我看到导航栏出了什么问题 . 您的navbar组件是第一个被调用的组件,可以这么说,在初始化子组件之前构建 .

    问题是导航栏有自己的当前路线 . 你发现了一个类似的问题here,其答案似乎不再适用 . 如果有必要,你可以检查一下,那里不确定这是否可行 .

    改进建议

    我看到的问题是方法本身使用语言作为子组件的路由参数而不是父组件 . 该语言当前是在导航栏的每个子路径上设置的路由参数,导致代码中出现大量重复 . 所有孩子无论如何都必须通过导航栏初始化过程,那么为什么不处理那里的语言呢?这样,您只需在代码中的一个位置执行语言加载 .

    在这种情况下你可能需要调整你的路由器,就像这样 .

    { path: '', redirectTo: '/login', pathMatch: 'full' },
        { path: ':lang', component: NavbarComponent, children: [
            {path: 'agenda', component: AgendaComponent},
            {path: 'perfil', component: PerfilComponent},
            {path: 'servicos', component: CadastroServicoComponent},
            {path: 'profissionais', component: ProfissionaisComponent},
            {path: 'admin', component: AdminComponent},
            {path: 'dashboard', component: DashboardComponent},
            {path: 'signup', component: SignUpFormComponent}
        ]}
    

    此外,不再需要当前不工作的代码,因为您不必再将语言提供给子路由 .

    <header id="topnav">
       <ul class="navbar-nav" *ngFor="let p of perfil | async">
         <li class="nav-item">
           <!-- without / the router routes to children relative to the current path -->
           <!-- no need for the language anymore -->
           <a [routerLink]="['agenda']" class="nav-link" translate>Agenda</a>
         </li>
         <li class="nav-item">
           <a [routerLink]="['admin']" class="nav-link" translate>Admin</a>
         </li>
       ...
       </ul>
     </header>
    

    从您的登录页面,您可以直接路由到 /lang 页面(这是导航栏),然后在那里初始化语言(并且只执行一次) . 所有子组件现在都是 lang 路由的子组件,而不是拥有自己的 lang 参数 . 在 navbar.component.ts 中,您可以使用与当前使用的完全相同的代码 . 在子组件中,不要再初始化 ngx-translate ,它只是向左侧稍微坐一点 .

    希望这足够准确 .

相关问题