在我正在使用的一个应用程序中,路由系统需要与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
事件,当用户对其会话进行认证时,在选择框上切换语言,等等。
所以,在简历中,我需要能够:
i18n
参数,无需重新加载整个视图/应用程序; A $watcher
没有做到这一点,因为应用程序需要在每个路径中都有正确的语言环境,甚至在它实例化所有元素之前。 AngularJS
用于此检查的每个步骤,但如果有任何线索可以在外部执行此操作,则在Angular实例化之前,我们可以讨论它。
目前,我使用下面接受的答案,使用我开发的解决方案,但必须对其进行改进。
答案 0 :(得分:0)
我最终对URL进行了一种初步解析。仅使用ngRoute
(ui-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
加载翻译),此方法会导致多个重定向,从而导致重要延迟实例化。
如果有任何改进,我也会感谢,如果我找到了更好的方法,我会用它来更新这个答案。