与$ translateProvider.useStaticFilesLoader角转换异步计时问题

2019-10-22 14:03发布

我使用的是优秀的角转换( $translate )指令/服务来处理多个区域设置语言,因为我有多个区域设置文件我使用便捷$translateProvider.useStaticFilesLoader通过localeAbbr.json的结构来加载我的翻译文件,例如en.jsones.json ,等...我建了一个Plunker显示我的开源项目,该项目通过Git使用的语言环境原始文件(指向实际Github的资料库,这意味着不是本地的plunker演示)。 作为指导和服务,我做了一个小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');
}]);

通过控制器打电话给我的服务:

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">&times;</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; 我尝试过,但似乎并没有帮助。

在这里再次是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;
});

Answer 1:

当与AngularJS或JavaScript为此事工作,你真的需要接受异步模式。 为了使处理异步代码不麻烦,你可以聘请使用承诺。 角度为您提供了一种名为$ Q这确实繁重的你

https://docs.angularjs.org/api/ng/service/$q

越来越的人的头周围的承诺需要时间,但非常值得在长期运行的努力。

从本质上讲,你需要与你的validationService做的是要利用$翻译的承诺API,它会给你你根据所提供的密钥时,它是在一个位置,这样做需要翻译。 这是什么归结为是,你问$翻译所有的translationId的你希望得到一个翻译,当一切都被你拿来填充在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作为角将使呼叫翻译上的每个消化每个键。 要考虑的一个办法是提供您的虚拟机与标签对象,并使用$过滤服务来填充他们在控制器实例。



Answer 2:

我的答案找到了我的传递额外的参数给承诺的匿名函数的问题是使用闭包 ,这样的变量是承诺之前,太里面一样。 所以我基本上要总结我的$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);

现在终于,我的变量是正确的,在时间上保持的价值在这一点:)



Answer 3:

虽然这是事实, $translateProvider.useStaticFilesLoader不返回一个承诺,我看了$翻译服务中,发现它提供了一个方便的回调onReady()这确实返回一个承诺。 此回调被调用时, $translate服务已完成加载当前选定的语言,是确保页面初始化后如预期即时翻译将工作有用:

$translate.onReady(function () {
    // perform your instant translations here
    var translatedMsg = $translate.instant('INVALID_ALPHA');
});


文章来源: Angular Translate async timing issue with $translateProvider.useStaticFilesLoader