angularjs 带有路径参数的 i18n 路由

angularjs i18n routing with path params

在我正在使用的一个应用程序中,路由系统需要与 i18n 集成,如下例所示:

$routeProvider.when('/:i18n/section', ...);

但我遇到了一些问题,我猜是因为 $digest 循环,它不会在运行时更改 i18n 参数。

我面临的另一个问题是,如果位置路径指向如下内容:

http://localhost:9000/section/...

不喜欢:

http://localhost:9000/en/section/...

i18n 路径参数结束与 /section/ 的关联,这意味着,在 $routeParams 服务上,$routeParams.i18n = 'section';。这是预料之中的,但我需要能够解析 /:i18n/ 参数,以避免这种冲突,并更改 URL,连接一个语言环境,以将会话上下文化,用新路由替换当前路由一,国际化,没有自动刷新view/app,但select非常好,因为一些功能只需要更改,而不是全部。

此外,我设计了一项服务,该服务根据可能的语言设置及其权重列表来评估将 select 编辑到当前上下文的语言:

var criteria = {
    default: {
        tag: 'en',
        weight: 10
    },
    user: {
        tag: 'pt',
        weight: 20
    },
    cookie: {
        tag: 'zh',
        weight: 30
    },
    url: {
        tag: 'ru',
        weight: 40
    },
    runtime: {
        tag: 'es',
        weight: 50
    }
};

function chooseLanguage (languages) {
    var deferred = $q.defer();
    var weights = [];
    var competitors = {};
    var choosen = null;

    if (defineType(languages) === 'array') {
        for (var i = languages.length - 1; i >= 0; i--) {
            if (languages[i].tag !== null) {
                weights.push(languages[i].weight);

                competitors[languages[i].weight] = languages[i];
            }
        }

        choosen = competitors[Math.max.apply(Math, weights)];
    } else if (defineType(languages) === 'object') {
        choosen = languages;
    } else {
        return;
    }

    setRuntimeLanguage(choosen.tag);

    deferred.resolve(choosen);

    return deferred.promise;
}

解释上面的代码,当 angular bootstrap 应用程序时,将执行代码片段,select 确定定义了哪种语言以及它是否足够强大 select编辑。其他方法与此操作相关,如检测 URL 参数,是否有一个登录用户等,并且该过程不仅在 bootstrap 上执行,而且在几个上下文中执行:$routeChangeStart 事件,当用户验证其会话时,在 select 框上切换语言,等等。

因此,在简历中,我需要能够:

  1. 解析 URL 并正确应用 locale 参数,如果它没有通知初始化;
  2. 在运行时更改 URL i18n 参数,无需重新加载整个 view/app;
  3. 正确处理语言变化,这意味着,如果我基于权重的方法不是更好的方法,如果你建议我其他方法。

编辑 1:

A $watcher 无法解决问题,因为应用程序在每个路径中都需要正确的区域设置,甚至在它实例化所有元素之前也是如此。 AngularJS 用于此检查的每个步骤,但如果有任何线索可以在外部执行此操作,在 Angular 实例化之前,我们可以讨论它。

现在,我使用下面接受的答案,以及我开发的解决方案,但它必须改进。

我最终对 URL 进行了初步解析。仅使用 ngRouteui-router 不是一个选项...),我检查路径是否与限制匹配,如果不匹配,则触发重定向,正确定义路径。

下面是解决方案的一个片段,用于主要路线,以及一个简单的后续示例,由于应用程序上路线的数量及其特定数据,不属于基础思想:

$routeProvider
    .otherwise({
        redirectTo: function () {
            return '/404/';
        }
    })

    .when('/:i18n/', {
        redirectPath: '/:i18n/',
        templateUrl: 'home.html',
        controller: 'HomeCtrl',
        resolve: {
            i18n: [
                '$location',
                '$route',
                'i18nService',
                function ($location, $route, i18nService) {
                    var params = $route.current.params;

                    return i18nService.init(params.i18n)
                        .then(null, function (fallback) {
                            if (params.i18n === '404') {
                                return $location.path('/' + params.i18n + '/404/').search({}).replace();
                            }

                            $location.path('/' + fallback).search({}).replace();
                        });
                }
            ],
            data: [
                'dataService',
                function (dataService) {
                    return dataService.resolve();
                }
            ]
        }
    })

    .when('/:i18n/search/:search/', {
        redirectPath: '/:i18n/search/:search/',
        templateUrl: 'search.html',
        controller: 'SearchCtrl',
        resolve: {
            i18n: [
                '$location',
                '$route',
                'i18nService',
                function ($location, $route, i18nService) {
                    var params = $route.current.params;

                    return i18nService.init(params.i18n)
                        .then(null, function (fallback) {
                            $location.path('/' + fallback + '/search/').search({
                                search: params.search
                            }).replace();
                        });
                }
            ],
            data: [
                '$route',
                'searchService',
                function ($route, searchService) {
                    var params = $route.current.params;

                    return searchService.resolve({
                        'search': params.search
                    });
                }
            ]
        }
    });

redirectPath 属性 在您需要该路线的模式时使用,因为 ngRoute 保留一份供私人使用,但不提供访问权限具有 $route public 属性。

由于在任何应用程序请求之前都需要解析(i18nService 除外,它加载语言环境列表并触发 angular-translate 加载翻译),此方法会导致多次重定向,从而导致实例化的显着延迟。

如果有任何可能的改进,我会感谢,如果我找到更好的方法,我会用它更新这个答案。