หลังจากลองใช้วิธีแก้ปัญหาไม่กี่วิธีฉันคิดว่าฉันพบวิธีแก้ปัญหาที่ใช้งานได้ดีและน่าจะเป็นวิธีแก้ปัญหาสำหรับ React 0.14 (กล่าวคือไม่ใช้ mixins แต่เป็นส่วนประกอบลำดับที่สูงกว่า) ( แก้ไข : ยังใช้ได้ดีกับ React 15 แน่นอน! )
ดังนั้นที่นี่วิธีแก้ปัญหาโดยเริ่มจากด้านล่าง (ส่วนประกอบแต่ละส่วน):
ส่วนประกอบ
สิ่งเดียวที่คุณต้องการ (ตามแบบแผน) คือstrings
อุปกรณ์ประกอบฉาก ควรเป็นวัตถุที่มีสตริงต่างๆที่ต้องการ Component ของคุณ แต่จริงๆแล้วรูปร่างของมันขึ้นอยู่กับคุณ
มันมีการแปลเริ่มต้นดังนั้นคุณสามารถใช้ส่วนประกอบที่อื่นได้โดยไม่จำเป็นต้องให้คำแปลใด ๆ (มันจะทำงานนอกกรอบด้วยภาษาเริ่มต้นภาษาอังกฤษในตัวอย่างนี้)
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);
ส่วนประกอบการสั่งซื้อที่สูงขึ้น
ในตัวอย่างก่อนหน้านี้คุณอาจสังเกตเห็นสิ่งนี้ในบรรทัดสุดท้าย:
translate('MyComponent')(MyComponent)
translate
ในกรณีนี้คือคอมโพเนนต์ลำดับที่สูงขึ้นซึ่งห่อหุ้มส่วนประกอบของคุณและมีฟังก์ชันพิเศษบางอย่าง (โครงสร้างนี้แทนที่ส่วนผสมของ React เวอร์ชันก่อนหน้า)
อาร์กิวเมนต์แรกคือคีย์ที่จะใช้ค้นหาคำแปลในไฟล์การแปล (ฉันใช้ชื่อของส่วนประกอบที่นี่ แต่อาจเป็นอะไรก็ได้) อันที่สอง (สังเกตว่าฟังก์ชั่นเป็นแบบแกงเพื่อให้ผู้ตกแต่ง ES7) คือส่วนประกอบในการห่อหุ้ม
นี่คือรหัสสำหรับองค์ประกอบการแปล:
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;
};
}
ไม่ใช่เวทมนตร์: มันจะอ่านภาษาปัจจุบันจากบริบท (และบริบทนั้นไม่ได้มีเลือดออกทั่วฐานรหัสเพียงใช้ที่นี่ใน wrapper นี้) จากนั้นรับวัตถุสตริงที่เกี่ยวข้องจากไฟล์ที่โหลด ตรรกะนี้ค่อนข้างไร้เดียงสาในตัวอย่างนี้สามารถทำได้ในแบบที่คุณต้องการจริงๆ
ส่วนที่สำคัญคือใช้ภาษาปัจจุบันจากบริบทและแปลงเป็นสตริงตามคีย์ที่ให้มา
ที่ด้านบนสุดของลำดับชั้น
ในองค์ประกอบรากคุณเพียงแค่ต้องตั้งค่าภาษาปัจจุบันจากสถานะปัจจุบันของคุณ ตัวอย่างต่อไปนี้ใช้ Redux เป็นการนำไปใช้งานแบบ Flux แต่สามารถแปลงได้อย่างง่ายดายโดยใช้กรอบ / รูปแบบ / ไลบรารีอื่น ๆ
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);
และเพื่อให้เสร็จสิ้นไฟล์แปล:
ไฟล์การแปล
// 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'
}
};
พวกคุณคิดว่าอย่างไร?
ฉันคิดว่าสามารถแก้ปัญหาทั้งหมดที่ฉันพยายามหลีกเลี่ยงในคำถามของฉัน: ตรรกะการแปลไม่มีเลือดออกทั่วซอร์สโค้ดมันค่อนข้างแยกและอนุญาตให้ใช้ส่วนประกอบซ้ำได้โดยไม่ต้องใช้มัน
ตัวอย่างเช่น MyComponent ไม่จำเป็นต้องห่อด้วย translate () และสามารถแยกออกจากกันได้โดยอนุญาตให้บุคคลอื่นที่ต้องการระบุstrings
ค่าเฉลี่ยของตัวเอง
[แก้ไข: 31/03/2016]: ฉันเพิ่งทำงานใน Retrospective Board (สำหรับ Agile Retrospectives) ซึ่งสร้างขึ้นด้วย React & Redux และสามารถพูดได้หลายภาษา เนื่องจากผู้คนจำนวนมากขอตัวอย่างชีวิตจริงในความคิดเห็นนี่คือ:
คุณสามารถค้นหารหัสได้ที่นี่: https://github.com/antoinejaussoin/retro-board/tree/master