我有一个仅支持一种语言环境(法语)的 Angular 应用程序。然后我改进了应用程序以支持另一种语言,其中相同的组件在另一个根路径下可用 /ar
我现在的问题是应用程序使用了很多 [routerLink]="['some', 'thing'] 和其他 router.navigate('...')。我不是 i18n 所有链接,而是思考执行 url 翻译的聪明方法。
我做了以下事情:
this.translateService.onLangChange
.combineLatest(this.router.events)
.subscribe(([langEvent, event]) => {
if (event instanceof NavigationStart) {
let currentUrl = event.url;
let locale = Locale.getLocaleByShortcut(langEvent.lang);
if (locale) {
if (locale.isArabic()) {
if (!ContextUtils.isArabicUrl(currentUrl)) {
this.router.navigate(['/ar/' + currentUrl], {queryParams: this.route.snapshot.queryParams});
}
} else {
if (ContextUtils.isArabicUrl(currentUrl)) {
let url = ContextUtils.frenchifyUrl(currentUrl);
this.router.navigate([url], {queryParams: this.route.snapshot.queryParams});
}
}
}
}
if (event instanceof NavigationEnd) {
if (Config.IS_WEB()) {
$(document).ready(() =>
setTimeout(() => {
Materialize.updateTextFields()
}, 10)
);
}
this.scrollToTop();
}
});
问题是这个解决方案不能完美地工作,尤其是当从一个有 queryParams 的 url 导航到另一个没有它们的 url 时保留的 queryParams。
有什么聪明的方法可以为路由器导航到的 UrlSegments 添加前缀吗?
例子
<a[routerLink]="['some', 'thing']></a> ----> redirect to : /ar/some/thing
设置 AR 语言环境时。和/some/thing 时不。
谢谢。
最佳答案
少了点东西
据我所知,Angular 没有提供任何将语言环境统一到一个网站中的东西。 Angular 要求您使用指定的区域设置参数进行多次构建。本质上,它们是托管在不同地址的不同网站。
还有其他使用管道的开源翻译解决方案。但我个人不愿意将第 3 方解决方案用于影响应用程序每个页面的内容。
我一直觉得着陆页会是一个有效的改进。那将是一个将这些站点链接在一起的 index.html
页面。例如然后你会有这样的设置:
index.html --> root landing page
en/
index.html --> your angular site in English
...
fr/
index.html --> your angular site in French.
...
主要的改进是,您可以在同一地址欢迎所有访客,并从那里无缝转发他们。
开源解决方案
我创建了一个要点,你可以找到它 here ,正是这样做的。这是一个可配置的着陆页。它是有意用纯 html 和 js 编写的。目的是使它成为您的根 index.html
。
因此,您可以轻松地在 1 个根域名下托管所有内容。但是,如果用户决定从一个语言环境切换到另一个语言环境,那仍然意味着要完全重新加载内存。但在正常情况下,用户只会更改一次语言。
基本工作
因此,如果有人只是导航到 http://example.com
,它将尝试以多种方式(例如浏览器语言,...)确定该用户的语言,并且一次它知道该语言,它将使用预定义的路由配置将用户重定向到正确的 URL。在转发请求的同时,它还会转发子路径。 (在我的回答的最后部分对此进行了更多介绍)。
但它还会在本地存储中缓存语言,以供您下次访问。
现在,如果您希望您的用户选择一种语言,那么(例如在您的页面导航栏或设置 Pane 中)您可以添加一个链接,例如http://example.com/?locale=en
。以这种方式指定的语言(即使用查询参数)将比浏览器语言或以前存储的语言具有更高的优先级。
要配置路由机制,您应该设置一个默认区域设置作为回退,并提供路由映射。
var defaultLocale = 'en';
var routing = {
"en": 'https://example.com/en',
"fr": 'https://example.com/fr'
"en-uk": 'https://example.com/uk',
};
脚本将更喜欢完美的语言环境命中。但如果这没有产生匹配项,它将尝试仅使用该语言。 (尽管始终以小写形式定义它们)。
如何处理子路径
具体针对你的问题,转发是如何工作的。
无论您使用哪个网络服务器,对于 Angular 网络服务器都应该始终进行配置,以便所有子路径请求也被转发到您的 index.html
。 (您当前的设置应该已经是这种情况。)
我们的着陆页 html 文件以相同的方式工作,它也接收完整路径。所以,当它想要提取子路径时,它实际上可以访问完整路径。它将通过删除第三个 /
后面的所有内容来提取子路径。
因此,如果您在 http://example.com
上托管此着陆页,并且您具有上述路由配置。然后,如果有人导航到 http://example.com/foo
,并且该用户有英语语言环境,那么他将被重定向到 http://example.com/en/foo
。
关于 Angular 路由器 : Redirect to an i18n URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50632437/