使用属性的后期评估进行应用程序本地化



我有一堆控制器,其中一些属性是用翻译库生成的:

App.CallsStatusTotalsPerHourChartController = Ember.ArrayController.extend({
    title: Ember.I18n.t('dashboard.calls-per-hour.title'),
    subTitle: Ember.I18n.t('dashboard.calls-per-hour.subtitle'),
    noDataText: Ember.I18n.t('dashboard.calls-per-hour.no-data'),
    content: []
});

问题是语言文件尚未加载(需要一些时间),因此在定义时,Ember.I18n.t没有数据,并且所有翻译都失败。有几种解决方案,但对我来说似乎更简单的解决方案如下:

我不会直接调用Ember.I18n.t,而是调用一个delayedT,它将基于一个属性:

function delayedT(key) {
    return property depending on App.languageLoaded, to do Ember.I18n.t(key)
}

每当设置应用程序标志时,都会计算此属性:App.languageLoaded。每当语言文件完成加载时,我都会执行App.set('languageLoaded', true),这将触发所有翻译。这样,只需在正确的时间(当语言数据到达时)为应用程序执行一次翻译。

这有意义吗?我将如何实现延迟 T?

首先,我建议不要在全局App上设置属性。

总的来说,您可以通过创建在加载语言时失效的计算属性来解决此问题。

下面是一些未经测试的代码来说明该方法。创建翻译器类:

App.Translator = Ember.Object.extend({
  languageLoaded: false,
  translate: function(key){
    if (this.get('languageLoaded')) {
      return Ember.I18n.t(key);
    }
  }
});

将其注册为单例,并将其注入控制器:

Ember.Application.initializer({
    name: 'setup translation',
    initialize: function(container, application) {
        application.register('translator:main', App.Translator);
        container.injection('controller', 'translator', 'translator:main');
    }
});

然后在控制器中,您可以拥有一个依赖于 languageLoaded 属性的属性(因此当 languageLoaded 变为 true 时,它将失效并重新运行:

App.CallsStatusTotalsPerHourChartController = Ember.ArrayController.extend({
  title: function(){
    return this.get('translator').translate('dashboard.calls-per-hour.title');
  }.property('translator.languageLoaded'),
});

您可以使用宏缩短此时间:

function t(key){
  return function(){
    return this.get('translator').translate(key);
  }.property('translator.languageLoaded')
}
App.CallsStatusTotalsPerHourChartController = Ember.ArrayController.extend({
  title: t('dashboard.calls-per-hour.title'),
  subTitle: t('dashboard.calls-per-hour. subtitle'),
  noDataText: t('dashboard.calls-per-hour.no-data'),
  content: []
});

加载语言后,不要忘记查找转换器并设置布尔值:

// yippee, my language finally loaded
Ember.run(function(){
  this.container.lookup('translator:main').set('languageLoaded', true);
});

如果你真的想要,有很多方法可以在这里使用承诺,但我可能不会打扰。

最新更新