Angular 路由器:重定向到 i18n URL

Rad*_*FID 3 angular-ui-router angular angular5

我有一个角度应用程序仅支持一种语言环境(法语)。然后,我改进了应用程序以支持另一种语言,其中相同的组件在另一个根路径下可用/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();
    }
});
Run Code Online (Sandbox Code Playgroud)

问题是这个解决方案不能完美工作,特别是当从具有 queryParams 的 url 导航到另一个不具有 queryParams 的 url 时保留的 queryParams。

有没有什么聪明的方法来为路由器导航到的 UrlSegments 加上前缀?

<a[routerLink]="['some', 'thing']></a> ----> redirect to : /ar/some/thing设置 AR 区域设置时的示例 。没有的时候到/some/thing。

谢谢。

bvd*_*vdb 6

缺了点什么

据我所知,Angular 没有提供任何将语言环境统一到单个网站的功能。Angular 要求您使用指定的区域设置参数进行多个构建。本质上,它们是托管在不同地址上的不同网站。

还有其他使用管道的开源翻译解决方案。但我个人不愿意使用第三方解决方案来处理影响应用程序每个页面的问题。

我总觉得登陆页面会是一个有效的改进。那将是一个index.html将这些站点链接在一起的页面。例如,您将有这样的设置:

index.html --> root landing page
en/
   index.html --> your angular site in English
   ...
fr/
   index.html --> your angular site in French.
   ...
Run Code Online (Sandbox Code Playgroud)

主要的改进是,您可以欢迎同一地址上的所有访客,并从那里无缝转发他们。

开源解决方案

我创建了一个要点,您可以在这里找到它,它正是这样做的。这是一个可配置的登陆页面。它是故意用纯 html 和 js编写的。目的是使之成为你的根源index.html

因此,您可以轻松地将所有内容托管在 1 个根域名下。但是,如果用户决定从一种语言环境切换到另一种语言环境,这仍然意味着完全重新加载内存。但在正常情况下,用户只会更改一次语言。

基本工作

因此,如果有人只是导航到http://example.com,它将尝试以多种方式确定该用户的语言(例如浏览器语言,...),一旦它知道该语言,它将使用预定义的路由配置将用户重定向到正确的网址。并且在转发请求的同时,也会转发子路径。(在我的答案的最后部分对此有更多了解)。

但它还会在本地存储中缓存语言,以供您下次访问。

现在,如果您希望用户选择一种语言,那么(例如在页面导航栏或设置窗格中)您可以添加一个链接,例如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',
};
Run Code Online (Sandbox Code Playgroud)

该脚本将更喜欢完美的语言环境命中。但如果没有产生匹配,它将尝试仅使用该语言。(但始终以小写形式定义它们)。

如何处理子路径

具体针对您的问题,转发是如何工作的。

无论您使用哪个 Web 服务器,都应始终配置 Angular Web 服务器,以便所有子路径请求也转发到您的index.html. (您当前的设置应该已经是这种情况。)

我们的登陆页面 html 文件以同样的方式工作,它也接收完整路径。因此,当它想要提取子路径时,它实际上可以访问完整路径。它将通过删除第三个后面的所有内容来提取子路径/

因此,如果您托管此登陆页面http://example.com并且具有上述路由配置。然后,如果有人导航到http://example.com/foo,并且该用户具有英语区域设置,那么他将被重定向到http://example.com/en/foo