Angular路由:是否可以为不同的语言使用不同的“path”字符串?

15

我正在进行一项i18n Angular应用程序的开发,目前它运行得很好。

但是,对于不同的语言,我具有相同的路由字符串,这对于SEO来说并不是最佳选择。

是否有可能使Routes数组的“路径”属性对于每种语言都不同?

例如:

const appRoutesEN: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  { path: 'hero/:id',      component: HeroDetailComponent },
  {
    path: 'heroes',
    component: HeroListComponent,
    data: { title: 'Heroes List' }
  },
  { path: '**', component: PageNotFoundComponent }
];

如果我希望定义一个 appRoutesFR: Routes ,这是否可能? 如果是,我该如何使用它? 我需要将 LOCALE_ID 注入路由模块吗? 如果需要,应该怎么做呢?


1
请参见 https://github.com/Greentube/localize-router 和 https://github.com/ngx-i18n-router/core,如此处所建议 https://github.com/ngx-translate/core/issues/178。 - Estus Flask
@estus 虽然它们看起来很不错,但我正在使用 Angular 的默认 i18n,而不是 ngx-translate,我希望能够在那里看到一些解决方案,而不是再增加一个依赖项。 - Bogac
你是为每种语言构建专用应用程序,还是如何支持多个本地化? - PeterFromCologne
嗨@PeterFromCologne,应用程序已经从头开始创建,考虑到i18n,包括数据库对象的创建等,使用Angular团队提供的i18n工具/指令。 ngx-i18nsupport软件包对于简化流程非常有帮助。更多信息请参见此处。唯一无法帮助的是路由字符串。如果您一直在创建i18n方式的应用程序,则路由变量不是问题,路由变量可以是翻译版本,但路由字符串不行。 - Bogac
@PeterFromCologne 你会在链接中看到,你有一个代码库,但有几个 npm scripts 来提取需要翻译的字符串,然后构建/服务于选定的语言。由于路由字符串是唯一无法在此过程中进行优化的部分,因此我已经在所有可用语言中创建了所有路由定义,并在构建所需语言之前将那些需要的注释掉,不需要使用的则取消注释。这是丑陋的部分,这是因为我使用了具有子路由的惰性加载模块。如果没有,我可以使用 @estus 推荐的软件包。如果需要更多信息,请联系我。 - Bogac
3个回答

4
如果您需要像您在评论中描述的那样针对每种语言使用不同的路由,您可以为每种语言单独创建一个专用的路由模块。然后,在angular-cli.json中为每种语言定义一个专用的应用程序,该应用程序具有自己的main.ts和自己的AppModule,仅拉取特定语言所需的路由模块。
  "apps": [
   {
      "root": "src",
      "name": "yourapp_FR",
...
      "main": "./app/yourapp_FR/main.ts",
...   
    },
   {
      "root": "src",
      "name": "yourapp_DE",
...
      "main": "./app/yourapp_DE/main.ts",
...   
    }
    ]

您需要为每种语言构建以下应用程序(示例代码):
ng build --app yourapp_FR --i18n-file src/i18n/messages.fr.xlf --locale fr --i18n-format xlf --aot

通过这种方式,您可以一次性设置它,并且每次构建时无需注释任何内容。我没有完整的上下文。您说每种语言具有单独的路由对于SEO更好。我不理解这一点,但如果您这么说,那就好。然而,我不希望为每种语言专门设置路由。这意味着很多冗余和更多的维护工作。


哇,看起来非常可行和合乎逻辑。很快就会测试它。我可以将产品名称(或新闻标题等)作为所选语言中的路由变量,这对于SEO更好,但在前面你会看到“产品”或“新闻”等。这并不理想。不确定这对SEO有多大影响,我更喜欢使用所选语言。 - Bogac
啊,现在我明白了。感谢您的评论。 - PeterFromCologne

4

目前似乎没有简单的解决方案。如果我找到了一个,我会更新的。

Angular i18n 的人正在努力将代码级别的国际化集成进去,也许那时候会有更好的解决方案。

我能想到的最好的解决方案是,在你的代码中更改路由模块和模板中的routerLink属性以及其他部分的所有链接,为每种语言构建单独的应用程序。

这绝非理想的解决方案。

更新

如@estus所推荐,我尝试了Greentube/localize-router

我不想安装像@ngx-translate/core@ngx-translate/http-loader这样的依赖项,因为我使用的是 Angular i18n 实现/工具,而不是 ngx-translate。

它可以正常工作,直到遇到一个带有子路由的延迟加载模块

因此,如果您没有任何带有子级的延迟加载模块,那么localize-router就是正确的选择。

更新

最新版的localize-router支持惰性加载模块。
一旦程序化翻译到位,Angular i18n将得到支持。

0
如果您已经在使用像@ngx-translate/core这样的东西,那么您可以创建自己的映射而不是添加更多的外部库。
例如:
function generateI18nRoutes(
    elements: Array<{ i18nPaths: string[]; component: any; data: object; canActivate?: 
[] }>
): Routes {
    return elements.reduce(
        (accumulator, currentValue) => [
            ...accumulator,
            ...currentValue.i18nPaths.map((path: string) => ({
                path,
                component: currentValue.component,
                data: currentValue.data,
                canActivate: currentValue.canActivate
            }))
        ],
        []
    );
}

然后像这样使用:

const routes: Routes = [
    {
        path: "admin",
        component: AdminLayoutComponent,
        canActivate: [AdminAuthGuard],
        children: generateI18nRoutes([{ i18nPaths: [""], component: HomeComponent, data: { title: "ADMIN" } }])
    },
    {
        path: "",
        component: GeneralLayoutComponent,
        children: generateI18nRoutes([
            { i18nPaths: [""], component: HomeComponent, data: { title: "HOME" } },
            {
                i18nPaths: ["sign-in", "iniciar-sesión", "iniciar-sessão"],
                component: SignInComponent,
                data: { title: "SIGN_IN" }
            }
        ])
    },
    {
        path: "**",
        component: PageNotFoundComponent,
        data: { title: "PAGE_NOT_FOUND" }
    }
];

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接