我正在为i18n编写自己的组件。它被称为翻译,并连接到我的翻译所在的redux商店。
我知道有i18n库,但我想避免使用HOC,因为它很难为应用程序编写测试。
就是这样(我正在使用Typescript):
import * as React from 'react'
import { connect } from 'react-redux'
import IStoreState from '../../store/IStoreState'
import { LocalizationData } from '../../apiTypes/localizationData'
import { Translation } from '../../apiTypes/translation'
interface IProps {
localizationData: LocalizationData | null
context: string
options?: Translation
fallback?: string
}
class Translate extends React.Component<IProps, {}> {
public render() {
const { localizationData, context, options, fallback } = this.props
return <span>{localizationData && this.translate(context, options, fallback)}</span>
}
public translate = (context: string, options?: Translation, fallback?: string): string => {
const { localizationData } = this.props
if (localizationData) {
let res: string = localizationData.translations![context]
if (options && res && res) {
// replace optional strings
for (const key in options) {
if (options.hasOwnProperty(key)) {
res = res.replace(`%${key}`, options[key] + '')
}
}
}
// fallback to fallback string OR last segment of translation key
if (!res) {
res = fallback || context.substr(context.lastIndexOf('.') + 1)
}
return res
}
return ''
}
}
function mapStateToProps(state: IStoreState) {
return {
localizationData: state.localizationData,
}
}
export default connect(mapStateToProps)(Translate)
它的使用方式如下:
import './components/Translate'
public render() {
return (
<div>
<Translate context="page.title" />
</div>
);
}
这很好但我希望能够将它作为一个功能使用,以便能够做到这样的事情:
public render() {
return (
<div>
<img alt={t('image.title')}/>
</div>
);
}
我该怎么做?
答案 0 :(得分:0)
我看到两个选项:
<Translate />
更改为功能无状态组件。然后,返回一个字符串而不是一个span。FSC翻译:
import translate from '../../services/translate';
const Translate = props => {
const { localizationData, context, options, fallback } = props;
return localizationData && translate(context, options, fallback)
};
function mapStateToProps(state: IStoreState) {
return {
localizationData: state.localizationData,
}
}
export default connect(mapStateToProps)(Translate)
这会将您的使用情况改为:
import './components/Translate'
public render() {
return (
<div>
<span><Translate context="page.title" /></span>
</div>
);
}
但它也允许您将组件作为返回字符串的函数调用:
public render() {
return (
<div>
<img alt={Translate({ context: 'image.title' })}/>
</div>
);
}
translate
函数,并将其存储在可以在任何地方使用的单独文件中。然后<Translate />
成为:
import * as React from 'react'
import { connect } from 'react-redux'
import IStoreState from '../../store/IStoreState'
import { LocalizationData } from '../../apiTypes/localizationData'
import { Translation } from '../../apiTypes/translation'
import translate from '../../services/translate';
interface IProps {
localizationData: LocalizationData | null
context: string
options?: Translation
fallback?: string
}
class Translate extends React.Component<IProps, {}> {
public render() {
const { localizationData, context, options, fallback } = this.props
return <span>{localizationData && translate(context, options, fallback, localizationData)}</span>
}
function mapStateToProps(state: IStoreState) {
return {
localizationData: state.localizationData,
}
}
export default connect(mapStateToProps)(Translate)
translate.js
const translate = (context: string, options?: Translation, fallback?: string, localizationData: object): string => {
if (localizationData) {
let res: string = localizationData.translations![context]
if (options && res && res) {
// replace optional strings
for (const key in options) {
if (options.hasOwnProperty(key)) {
res = res.replace(`%${key}`, options[key] + '')
}
}
}
// fallback to fallback string OR last segment of translation key
if (!res) {
res = fallback || context.substr(context.lastIndexOf('.') + 1)
}
return res
}
return ''
}
export default translate;