import React from 'react'; import { RenderTextCallbackType } from '../types/Util'; type FullJSX = Array | JSX.Element | string; interface Props { /** The translation string id */ id: string; components?: Array; renderText?: RenderTextCallbackType; } export class Intl extends React.Component { public static defaultProps: Partial = { renderText: ({ text }) => text, }; public getComponent(index: number): FullJSX | undefined { const { id, components } = this.props; if (!components || !components.length || components.length <= index) { // tslint:disable-next-line no-console console.log(`Error: Intl missing provided components for id ${id}, index ${index}`); return; } return components[index]; } public render() { const { id, renderText } = this.props; const text = window.i18n(id); const results: Array = []; const FIND_REPLACEMENTS = /\$[^$]+\$/g; // We have to do this, because renderText is not required in our Props object, // but it is always provided via defaultProps. if (!renderText) { return; } let componentIndex = 0; let key = 0; let lastTextIndex = 0; let match = FIND_REPLACEMENTS.exec(text); if (!match) { return renderText({ text, key: 0 }); } while (match) { if (lastTextIndex < match.index) { const textWithNoReplacements = text.slice(lastTextIndex, match.index); results.push(renderText({ text: textWithNoReplacements, key: key })); key += 1; } results.push(this.getComponent(componentIndex)); componentIndex += 1; // @ts-ignore lastTextIndex = FIND_REPLACEMENTS.lastIndex; match = FIND_REPLACEMENTS.exec(text); } if (lastTextIndex < text.length) { results.push(renderText({ text: text.slice(lastTextIndex), key: key })); key += 1; } return results; } }