自定义翻译组件导出功能



我正在为I18N编写自己的组件。它称为翻译,并连接到我的翻译的Redux Store。

我知道那里有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>
  );
}

我该怎么做?

我看到的两个选项:

  1. <Translate />更改为函数无状态组件。然后,返回字符串而不是跨度。

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>
  );
}
  1. 甚至更好,将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;

最新更新