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 框上切换语言,等等。
因此,在简历中,我需要能够:
- 解析 URL 并正确应用 locale 参数,如果它没有通知初始化;
- 在运行时更改 URL
i18n
参数,无需重新加载整个 view/app;
- 正确处理语言变化,这意味着,如果我基于权重的方法不是更好的方法,如果你建议我其他方法。
编辑 1:
A $watcher
无法解决问题,因为应用程序在每个路径中都需要正确的区域设置,甚至在它实例化所有元素之前也是如此。 AngularJS
用于此检查的每个步骤,但如果有任何线索可以在外部执行此操作,在 Angular 实例化之前,我们可以讨论它。
现在,我使用下面接受的答案,以及我开发的解决方案,但它必须改进。
我最终对 URL 进行了初步解析。仅使用 ngRoute
(ui-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
加载翻译),此方法会导致多次重定向,从而导致实例化的显着延迟。
如果有任何可能的改进,我会感谢,如果我找到更好的方法,我会用它更新这个答案。
在我正在使用的一个应用程序中,路由系统需要与 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 框上切换语言,等等。
因此,在简历中,我需要能够:
- 解析 URL 并正确应用 locale 参数,如果它没有通知初始化;
- 在运行时更改 URL
i18n
参数,无需重新加载整个 view/app; - 正确处理语言变化,这意味着,如果我基于权重的方法不是更好的方法,如果你建议我其他方法。
编辑 1:
A $watcher
无法解决问题,因为应用程序在每个路径中都需要正确的区域设置,甚至在它实例化所有元素之前也是如此。 AngularJS
用于此检查的每个步骤,但如果有任何线索可以在外部执行此操作,在 Angular 实例化之前,我们可以讨论它。
现在,我使用下面接受的答案,以及我开发的解决方案,但它必须改进。
我最终对 URL 进行了初步解析。仅使用 ngRoute
(ui-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
加载翻译),此方法会导致多次重定向,从而导致实例化的显着延迟。
如果有任何可能的改进,我会感谢,如果我找到更好的方法,我会用它更新这个答案。