angularjs i18n路由与路径参数

时间:2015-03-04 13:10:19

标签: javascript angularjs routes internationalization ngroute

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

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

但我面临一些问题,因为我认为它是$digest周期,它不会在运行时更改i18n参数。

我面临的其他问题是,如果位置路径指向如下:

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

不喜欢:

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

i18n路径参数结束与/section/相关联,即$routeParams服务$routeParams.i18n = 'section';。这是预期的,但我需要能够解析/:i18n/ param,以避免这种冲突,并更改URL,连接一个语言环境,将会话上下文化,用新的路由替换当前路由,i18n-虽然有些功能只需要更改,但不是全部,只需要自动刷新视图/应用程序,而不是全部。

此外,我设计了一项服务,根据可能的语言设置及其权重列表,评估当前背景下选择的语言:

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;
}

解释上面的代码,当角度引导应用程序时,执行代码段,选择定义的语言以及是否足够强大以便选择。其他方法与此操作有关,例如对URL参数的de检测,是否有一个已记录的用户等,并且该过程不仅在引导程序上执行,而且在几个上下文中执行:$routeChangeStart事件,当用户对其会话进行认证时,在选择框上切换语言,等等。

所以,在简历中,我需要能够:

  1. 解析URL并正确应用语言环境参数,如果未初步通知;
  2. 在运行时更改URL i18n参数,无需重新加载整个视图/应用程序;
  3. 正确处理语言更改,这意味着,如果我的方法基于权重不是更好的方法,如果你建议我别的。
  4. 编辑1:

    A $watcher没有做到这一点,因为应用程序需要在每个路径中都有正确的语言环境,甚至在它实例化所有元素之前。 AngularJS用于此检查的每个步骤,但如果有任何线索可以在外部执行此操作,则在Angular实例化之前,我们可以讨论它。

    目前,我使用下面接受的答案,使用我开发的解决方案,但必须对其进行改进。

1 个答案:

答案 0 :(得分:0)

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

下面,根据解决方案的片段,主要路线和简单的后续示例,由于应用程序上的路线数量及其特定数据,这些不属于基础理念:< / p>

$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访问该副本公共财产。

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

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