Epeyce çözüm denedikten sonra, sanırım iyi çalışan ve React 0.14 için deyimsel bir çözüm olması gereken bir çözüm buldum (yani mixin kullanmıyor, ancak Higher Order Bileşenleri kullanıyor) ( düzenleme : React 15 ile de gayet iyi tabi ki! ).
İşte çözüm, alttan başlayarak (tek tek bileşenler):
Bileşen
Bileşeninizin ihtiyaç duyacağı tek şey (geleneksel olarak) bir strings
sahne donanımıdır. Bileşeninizin ihtiyaç duyduğu çeşitli dizeleri içeren bir nesne olmalıdır, ancak gerçekten şekli size bağlıdır.
Varsayılan çevirileri içerir, böylece bileşeni herhangi bir çeviri sağlamaya gerek kalmadan başka bir yerde kullanabilirsiniz (kutudan çıktığı gibi varsayılan dil, bu örnekte ingilizce ile çalışır)
import { default as React, PropTypes } from 'react';
import translate from './translate';
class MyComponent extends React.Component {
render() {
return (
<div>
{ this.props.strings.someTranslatedText }
</div>
);
}
}
MyComponent.propTypes = {
strings: PropTypes.object
};
MyComponent.defaultProps = {
strings: {
someTranslatedText: 'Hello World'
}
};
export default translate('MyComponent')(MyComponent);
Yüksek Dereceli Bileşen
Önceki kod parçacığında, bunu son satırda fark etmiş olabilirsiniz:
translate('MyComponent')(MyComponent)
translate
bu durumda, bileşeninizi saran ve bazı ekstra işlevler sağlayan bir Yüksek Dereceli Bileşendir (bu yapı, önceki React sürümlerinin karışımlarının yerini alır).
İlk argüman, çeviri dosyasındaki çevirileri aramak için kullanılacak bir anahtardır (burada bileşenin adını kullandım, ancak herhangi bir şey olabilir). İkincisi (ES7 dekoratörlerine izin vermek için işlevin köreldiğine dikkat edin) Bileşenin kendisinin sarmalamasıdır.
Çeviri bileşeninin kodu:
import { default as React } from 'react';
import en from '../i18n/en';
import fr from '../i18n/fr';
const languages = {
en,
fr
};
export default function translate(key) {
return Component => {
class TranslationComponent extends React.Component {
render() {
console.log('current language: ', this.context.currentLanguage);
var strings = languages[this.context.currentLanguage][key];
return <Component {...this.props} {...this.state} strings={strings} />;
}
}
TranslationComponent.contextTypes = {
currentLanguage: React.PropTypes.string
};
return TranslationComponent;
};
}
Bu sihir değil: sadece geçerli dili bağlamdan okuyacak (ve bu bağlam, kod tabanının her yerine taşmayacak, sadece burada bu sarmalayıcıda kullanıldı) ve sonra yüklenen dosyalardan ilgili dizeler nesnesini alacak. Bu mantık parçası bu örnekte oldukça saftır, gerçekten istediğiniz şekilde yapılabilir.
Önemli olan, mevcut dili bağlamdan alması ve sağlanan anahtar verildiğinde bunu dizelere dönüştürmesidir.
Hiyerarşinin en tepesinde
Kök bileşende, sadece geçerli dili mevcut durumunuzdan ayarlamanız gerekir. Aşağıdaki örnek, Flux benzeri uygulama olarak Redux kullanıyor, ancak başka herhangi bir çerçeve / desen / kitaplık kullanılarak kolayca dönüştürülebilir.
import { default as React, PropTypes } from 'react';
import Menu from '../components/Menu';
import { connect } from 'react-redux';
import { changeLanguage } from '../state/lang';
class App extends React.Component {
render() {
return (
<div>
<Menu onLanguageChange={this.props.changeLanguage}/>
<div className="">
{this.props.children}
</div>
</div>
);
}
getChildContext() {
return {
currentLanguage: this.props.currentLanguage
};
}
}
App.propTypes = {
children: PropTypes.object.isRequired,
};
App.childContextTypes = {
currentLanguage: PropTypes.string.isRequired
};
function select(state){
return {user: state.auth.user, currentLanguage: state.lang.current};
}
function mapDispatchToProps(dispatch){
return {
changeLanguage: (lang) => dispatch(changeLanguage(lang))
};
}
export default connect(select, mapDispatchToProps)(App);
Ve bitirmek için çeviri dosyaları:
Çeviri Dosyaları
// en.js
export default {
MyComponent: {
someTranslatedText: 'Hello World'
},
SomeOtherComponent: {
foo: 'bar'
}
};
// fr.js
export default {
MyComponent: {
someTranslatedText: 'Salut le monde'
},
SomeOtherComponent: {
foo: 'bar mais en français'
}
};
Siz ne düşünüyorsunuz?
Sanırım sorumda kaçınmaya çalıştığım tüm problemleri çözüyor: çeviri mantığı kaynak kodun her yerine yayılmıyor, oldukça izole edilmiş ve bileşenlerin onsuz yeniden kullanılmasına izin veriyor.
Örneğin, MyComponent'in translate () ile sarmalanması gerekmez ve ayrı olabilir, bu strings
da kendi imkanlarıyla sağlamak isteyen başka herhangi biri tarafından yeniden kullanılmasına izin verir .
[Düzenleme: 31/03/2016]: Yakın zamanda React & Redux ile oluşturulmuş ve çok dilli bir Retrospective Board (Çevik Retrospektifler için) üzerinde çalıştım. Pek çok insan yorumlarda gerçek hayattan bir örnek istediğinden, işte burada:
Kodu burada bulabilirsiniz: https://github.com/antoinejaussoin/retro-board/tree/master