Ember.js 在Ember中为Ember-i18n动态渲染组件

Ember.js 在Ember中为Ember-i18n动态渲染组件,ember.js,ember-cli,ember-i18n,Ember.js,Ember Cli,Ember I18n,首先,在这种情况下,ember的组件帮助器没有帮助。只有当我知道需要渲染多少组件以及渲染顺序时,这才会有所帮助 我需要能够基于如下字符串渲染组件: {{user}}已出价{{bid},其中: {{user}}和{{{bid}}将替换为组件 给定字符串未知,表示组件的动态节数未知(组件将与给定字符串一起传入) 如果这些动态部分是助手,这将很容易-但助手只是不削减我的游戏中的某些项目 理想情况下,我可以这样做: {{translated-content content='{{user}} has

首先,在这种情况下,ember的组件帮助器没有帮助。只有当我知道需要渲染多少组件以及渲染顺序时,这才会有所帮助

我需要能够基于如下字符串渲染组件:
{{user}}已出价{{bid}
,其中:

  • {{user}}
    {{{bid}}
    将替换为组件
  • 给定字符串未知,表示组件的动态节数未知(组件将与给定字符串一起传入)
  • 如果这些动态部分是助手,这将很容易-但助手只是不削减我的游戏中的某些项目

    理想情况下,我可以这样做:

    {{translated-content
      content='{{user}} has made a bid of {{bid}}'
      user=(component 'user-ui')
      bid=(component 'bid-ui') }}
    

    这在ember中是可能的吗?

    在一些帮助下,我想出了以下组件,可用于ember-i18n和ember 1.11或更高版本

    它可能会被进一步优化,但它的工作方式又好又快

    创建新组件

    ember g组件t-t

    模板.hbs

    {{#each parts as |part|}}
    
      {{#if part.isComponent}}
        {{component part.content}}
      {{else}}
        {{part.content}}
      {{/if}}
    
    {{/each}}
    
    import Ember from 'ember';
    const { $ } = Ember;
    
    export default Ember.Component.extend({
    
      tagName: 'span',
    
      updateComponents: Ember.on('didReceiveAttrs',function(opts){
    
        let newAttrs = opts.newAttrs;
        let components = {};
    
        $.each(newAttrs,(key,val)=>{
    
          if( key !== 't' && typeof val === 'object' ){
            let keys = Object.keys(val);
            if(keys.length && keys[0].indexOf('COMPONENT_')>=0){
              components[key] = val;
            }
          }
    
        });
    
        this.set('_components',components);
    
      }),
    
      parts: Ember.computed('_components','t','i18n.locale',function(){
    
        let attrs = [];
        let components = this.get('_components');
        let componentKeys = Object.keys(components);
    
        $.each(this.attrs,(key,val)=>{
          if( key !== 't'){
            if( componentKeys.indexOf(key)<0 ){
              attrs[key] = val;
            } else {
              attrs[key] = `{{${key}}}`;
            }
          }
        });
    
        let content = this.get('i18n').t(this.get('t'),attrs).toString();
        content = content.replace(/\{\{(\w+?)\}\}/g,(fullMatch)=>{
          return `{{split}}${fullMatch}{{split}}`;
        });
    
        let parts = content.split('{{split}}');
    
        parts.forEach((val,i)=>{
          let isComponent;
          let key = val.replace(/\{\{(\w+?)\}\}/g,(fullMatch,key)=>{
            isComponent = true;
            return key;
          });
    
          if(isComponent && components[key]){
            parts[i] = {
              isComponent: true,
              content: components[key]
            };
          } else {
            parts[i] = {
              content: Ember.String.htmlSafe(val)
            };
          }
    
        });
    
        return parts;
    
      }),
    
    }).reopenClass({
      positionalParams: ['t']
    });
    
    component.js

    {{#each parts as |part|}}
    
      {{#if part.isComponent}}
        {{component part.content}}
      {{else}}
        {{part.content}}
      {{/if}}
    
    {{/each}}
    
    import Ember from 'ember';
    const { $ } = Ember;
    
    export default Ember.Component.extend({
    
      tagName: 'span',
    
      updateComponents: Ember.on('didReceiveAttrs',function(opts){
    
        let newAttrs = opts.newAttrs;
        let components = {};
    
        $.each(newAttrs,(key,val)=>{
    
          if( key !== 't' && typeof val === 'object' ){
            let keys = Object.keys(val);
            if(keys.length && keys[0].indexOf('COMPONENT_')>=0){
              components[key] = val;
            }
          }
    
        });
    
        this.set('_components',components);
    
      }),
    
      parts: Ember.computed('_components','t','i18n.locale',function(){
    
        let attrs = [];
        let components = this.get('_components');
        let componentKeys = Object.keys(components);
    
        $.each(this.attrs,(key,val)=>{
          if( key !== 't'){
            if( componentKeys.indexOf(key)<0 ){
              attrs[key] = val;
            } else {
              attrs[key] = `{{${key}}}`;
            }
          }
        });
    
        let content = this.get('i18n').t(this.get('t'),attrs).toString();
        content = content.replace(/\{\{(\w+?)\}\}/g,(fullMatch)=>{
          return `{{split}}${fullMatch}{{split}}`;
        });
    
        let parts = content.split('{{split}}');
    
        parts.forEach((val,i)=>{
          let isComponent;
          let key = val.replace(/\{\{(\w+?)\}\}/g,(fullMatch,key)=>{
            isComponent = true;
            return key;
          });
    
          if(isComponent && components[key]){
            parts[i] = {
              isComponent: true,
              content: components[key]
            };
          } else {
            parts[i] = {
              content: Ember.String.htmlSafe(val)
            };
          }
    
        });
    
        return parts;
    
      }),
    
    }).reopenClass({
      positionalParams: ['t']
    });
    

    我很抱歉地说,目前这是不可能的。如果你只是通过用户和出价翻译的内容组件。在那里,您可以使用计算属性来获取它们,并根据翻译内容模板中的重构数据呈现获取的用户和获取的出价组件。但如果你想要具体的例子,你需要提供一些具体的代码。不回答你的问题,但如果你正在寻找一个Ember的国际化解决方案,看看,我目前在一个复杂的应用程序中使用它,效果非常好。@terseus我实际上在使用Ember-i18n,并用他们的
    t
    助手尝试了上述示例。除非我遗漏了什么,否则他们不会支持我在这里所做的。@lependu是的!这和我的想法是一样的。实际上,我刚刚完成了一个组件的编写,它完美地处理了我上面的理想示例。我只是想在发布之前再做一些测试。