我正在使用优秀的Angular Translate($translate
)指令/服务来处理多种语言环境语言,因为我有多个语言环境文件,所以我使用方便的$translateProvider.useStaticFilesLoader
通过结构加载我的翻译文件localeAbbr.json,例如en.json
,es.json
等...我构建了一个Plunker来显示我的开源项目,该项目通过Git原始文件使用语言环境(指向实际的Github存储库) ,意思不是plunker demo的本地化)。我的项目是作为指令和服务构建的,我制作了一个小的Plunker来显示我的时序问题,加载JSON文件。
所有这一切都说$translateProvider.useStaticFilesLoader
似乎asynchronous
,而我确实需要它synchronous
,因为当plunker运行时,JSON文件尚未解析我已经在我的邮件上打了$translate.instant()
。
我有Plunker显示问题。
这是我的快速服务演示的一部分:
app.factory('validationService', ['$filter', '$translate', function ($filter, $translate) {
var service = this;
var validationSummary = [];
var errorMessages = [
'INVALID_ALPHA',
'INVALID_ALPHA_SPACE',
'INVALID_ALPHA_NUM',
'INVALID_BOOLEAN'
];
//var $translate = $filter('translate');
for(var i=0, ln=errorMessages.length; i < ln; i++) {
validationSummary.push({
field: i,
message: $translate.instant(errorMessages[i])
});
}
// attach public functions
service.getValidationSummary = getValidationSummary;
return service;
// function declaration
function getValidationSummary() {
return validationSummary;
}
}]);
$ translateProvider配置
app.config(['$translateProvider', function ($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'https://rawgit.com/ghiscoding/angular-validation/master/locales/validation/',
suffix: '.json'
});
// load English ('en') table on startup
$translateProvider.preferredLanguage('en').fallbackLanguage('en');
}]);
通过Controller致电我的服务:
app.controller("TestController", function($scope, validationService) {
var vm = this;
vm.displayValidationSummary = true;
vm.validationSummary = validationService.getValidationSummary();
});
最后使用控制器的HTML:
<div class="alert alert-danger alert-dismissable" ng-show="vm.displayValidationSummary">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true" ng-click="displayValidationSummary = false">×</button>
<h4><strong>{{ 'ERRORS' | translate }}!</strong></h4>
<ul>
<li ng-repeat="item in vm.validationSummary">{{item.field }}: {{item.message}}</li>
</ul>
</div>
由于我使用的是AngularJS 1.3+,我还发现$translate
只翻译了一次,因此作者建议使用translateFilter.$stateful = true;
并尝试过,但似乎没有帮助。< / p>
这里再次是Plunker
我花了好几周的时间试图找到并编写所有类型的解决方案,但我从来没有让它工作,我真的很难看到我的原始翻译代码:(
请帮助!!!
修改的
我意识到我的问题并未涵盖与我的问题相关的所有内容。除了翻译延迟问题之外,我还必须传递额外的参数,这是将它们传递给翻译匿名函数的一个巨大问题。当承诺结束时,我的论点的状态已经改变了。例如:
$translate(validator.message).then(function(translation) {
// only log the invalid message in the $validationSummary
addToValidationSummary(formElmObj, translation);
// error Display
if(!isValid) {
updateErrorMsg(translation, isValid);
}else if(!!formElmObj && formElmObj.isValid) {
addToValidationSummary(formElmObj, '');
}
}, function(data) {
throw 'Failed to translate' + data;
});
答案 0 :(得分:2)
在使用AngularJS或JavaScript时,您确实需要采用异步范例。为了减少处理异步代码的麻烦,可以使用Promises。 Angular为您提供了一个名为$ q的服务,它为您提供了繁重的工作
https://docs.angularjs.org/api/ng/service/$q
让人们了解Promises可能需要时间,但从长远来看非常值得付出努力。基本上你需要对validationService做的是使用$ translate的promise api,它可以根据提供的密钥为你提供所需的翻译。这可以归结为你要求翻译所有翻译的翻译,并且当你获取所有翻译时,你用你的消息填充validationSummary数组。
app.factory('validationService', ['$q', '$translate', function ($q, $translate) {
var translationsPromises = [],
validationSummary = [],
errorMessages = [
'INVALID_ALPHA',
'INVALID_ALPHA_SPACE',
'INVALID_ALPHA_NUM',
'INVALID_BOOLEAN'
];
angular.forEach(errorMessages, function(val, key) {
translationsPromises.push($translate(val));
});
$q.all(translationsPromises)
.then(function(translations) {
angular.forEach(translations, function(val, key) {
validationSummary.push({
filed: key,
message: val
});
});
})
.catch(function (err) {
console.error('Failed to translate error messages for validation summary', err);
});
// function declaration
function getValidationSummary() {
return validationSummary;
}
return {
getValidationSummary: getValidationSummary
};
}]);
我已经将您的plunker分叉并修改它以包含上面的示例
http://plnkr.co/edit/7DCwvY9jloXwfetKtcDA?p=preview
另一个观察结果是您在HTML中使用翻译过滤器。请注意,如果您有一个大型DOM,这可能会被证明是昂贵的,因为Angular会调用每个摘要翻译每个键。要考虑的方法是为vm提供标签对象,并使用$ filter服务在控制器实例化时填充它们。
答案 1 :(得分:1)
我发现我的问题的答案是将额外的参数传递给promise的匿名函数是使用Closures,这样变量在promise之前和在其中也是相同的。所以我基本上必须将$translate
调用包装到闭包中,如下所示:
(function(formElmObj, isValid, validator) {
$translate(validator.message).then(function(translation) {
message = message.trim();
// only log the invalid message in the $validationSummary
addToValidationSummary(formElmObj, message);
// error Display
if(!isValid) {
updateErrorMsg(message, isValid);
}else if(!!formElmObj && formElmObj.isValid) {
addToValidationSummary(formElmObj, '');
}
}, function(data) {
throw 'Failed to translate' + data;
});
})(formElmObj, isValid, validator);
现在最后,我的变量是正确的,并保持该时间点的值:)
答案 2 :(得分:0)
虽然$translateProvider.useStaticFilesLoader
确实没有返回承诺,但我查看了$ translate服务,发现它提供了一个方便的回调onReady()
,它确实返回了一个承诺。当$translate
服务加载了当前选定的语言时,将调用此回调,这对于确保在页面初始化后即时翻译将按预期工作非常有用:
$translate.onReady(function () {
// perform your instant translations here
var translatedMsg = $translate.instant('INVALID_ALPHA');
});