在 Ember 中为 ember-i18n 动态渲染组件
Dynamically render components in Ember for ember-i18n
首先,ember 的组件助手在这种情况下没有帮助。只有当我知道需要渲染多少个组件以及渲染顺序时,这才会有所帮助。
我需要能够基于如下字符串呈现组件:
{{user}} has made a bid of {{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 component t-t
template.hbs
{{#each parts as |part|}}
{{#if part.isComponent}}
{{component part.content}}
{{else}}
{{part.content}}
{{/if}}
{{/each}}
component.js
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']
});
用法
{{t-t
'your-ember-i18n-path'
key1='Normal Content (example)'
key2=(component 'your-component') }}
首先,ember 的组件助手在这种情况下没有帮助。只有当我知道需要渲染多少个组件以及渲染顺序时,这才会有所帮助。
我需要能够基于如下字符串呈现组件:
{{user}} has made a bid of {{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 component t-t
template.hbs
{{#each parts as |part|}}
{{#if part.isComponent}}
{{component part.content}}
{{else}}
{{part.content}}
{{/if}}
{{/each}}
component.js
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']
});
用法
{{t-t
'your-ember-i18n-path'
key1='Normal Content (example)'
key2=(component 'your-component') }}