UNPKG

@transifex/react

Version:
249 lines (236 loc) 6.68 kB
import React, { createContext, useContext, useState, useEffect, Fragment, useCallback } from 'react'; import { tx, onEvent, LOCALE_CHANGED, offEvent, t, TRANSLATIONS_FETCHED, FETCHING_TRANSLATIONS } from '@transifex/native'; import PropTypes from 'prop-types'; const TXNativeContext = /*#__PURE__*/createContext({ instance: null }); function useLanguages(txInstance) { const context = useContext(TXNativeContext); const instance = txInstance || context.instance || tx; const [languages, setLanguages] = useState([]); useEffect(() => { const fetch = function () { try { return Promise.resolve(instance.getLanguages()).then(function (_instance$getLanguage) { setLanguages(_instance$getLanguage); }); } catch (e) { return Promise.reject(e); } }; fetch(); }, [instance]); return languages; } function useLocale(txInstance) { const context = useContext(TXNativeContext); const instance = txInstance || context.instance || tx; const [locale, setLocale] = useState(instance.getCurrentLocale()); useEffect(() => { function cb(_, caller) { if (caller === instance) { setLocale(instance.getCurrentLocale()); } } onEvent(LOCALE_CHANGED, cb); return () => { offEvent(LOCALE_CHANGED, cb); }; }, [instance]); return locale; } function translateWithElements(_str, props, tx) { let _t = t; if (tx) { if (tx.instance && tx.instance.t) { _t = tx.instance.t; } else if (tx.t) { _t = tx.t; } } const actualProps = {}; const reactElements = []; if (props) { Object.entries(props).forEach(([key, value]) => { if (/*#__PURE__*/React.isValidElement(value)) { actualProps[key] = `__txnative__${reactElements.length}__txnative__`; reactElements.push(value); } else { actualProps[key] = value; } }); } const translation = _t(_str, actualProps); const result = []; let lastEnd = 0; let lastKey = 0; const regexp = RegExp('__txnative__(\\d+)__txnative__', 'g'); let match = regexp.exec(translation); while (match !== null) { const chunk = translation.slice(lastEnd, match.index); if (chunk) { result.push(/*#__PURE__*/React.createElement(Fragment, { key: lastKey }, chunk)); lastKey += 1; } result.push(/*#__PURE__*/React.cloneElement(reactElements[parseInt(match[1], 10)], { key: lastKey })); lastKey += 1; lastEnd = match.index + match[0].length; match = regexp.exec(translation); } const chunk = translation.slice(lastEnd); if (chunk) { result.push(/*#__PURE__*/React.createElement(Fragment, { key: lastKey }, chunk)); } if (result.length === 0) { return ''; } if (result.length === 1) { return result[0].props.children; } return /*#__PURE__*/React.createElement(Fragment, null, result); } function useT(txInstance) { const context = useContext(TXNativeContext); const instance = txInstance || context.instance || tx; const [counter, setCounter] = useState(0); useEffect(() => { function rerender(_, caller) { if (instance === caller) { setCounter(c => c + 1); } } onEvent(LOCALE_CHANGED, rerender); onEvent(TRANSLATIONS_FETCHED, rerender); return () => { offEvent(LOCALE_CHANGED, rerender); offEvent(TRANSLATIONS_FETCHED, rerender); }; }, [setCounter, instance]); return useCallback((_str, props) => translateWithElements(_str, props, instance), [instance, counter]); } function useTX() { const context = useContext(TXNativeContext); return context.instance || tx; } function useTranslations(filterTags, txInstance) { const context = useContext(TXNativeContext); const instance = txInstance || context.instance || tx; const [ready, setReady] = useState((instance.fetchedTags[instance.currentLocale] || []).indexOf(filterTags) !== -1); useEffect(() => { function setReadyToFalse({ filterTags: eventFilterTags }, caller) { if (caller !== instance) return; if (eventFilterTags === filterTags) { setReady(false); } } const fetchTranslations = function () { try { function _temp2() { setReady(true); } const _temp = function () { if (instance.currentLocale) { return Promise.resolve(instance.fetchTranslations(instance.currentLocale, { filterTags })).then(function () {}); } }(); return Promise.resolve(_temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp)); } catch (e) { return Promise.reject(e); } }; onEvent(FETCHING_TRANSLATIONS, setReadyToFalse); function setReadyToTrue({ filterTags: eventFilterTags }, caller) { if (caller !== instance) return; if (eventFilterTags === filterTags) { setReady(true); } } onEvent(TRANSLATIONS_FETCHED, setReadyToTrue); fetchTranslations(); onEvent(LOCALE_CHANGED, fetchTranslations); return () => { offEvent(FETCHING_TRANSLATIONS, setReadyToFalse); offEvent(TRANSLATIONS_FETCHED, setReadyToTrue); offEvent(LOCALE_CHANGED, fetchTranslations); }; }, [filterTags, instance]); return { ready }; } function LanguagePicker({ className = '' }) { const languages = useLanguages(); const locale = useLocale(); const tx = useTX(); return /*#__PURE__*/React.createElement("select", { className: className, value: locale, onChange: e => tx.setCurrentLocale(e.target.value) }, languages.map(({ name, code }) => /*#__PURE__*/React.createElement("option", { key: code, value: code }, name))); } LanguagePicker.propTypes = { className: PropTypes.string }; function T({ _str, ...props }) { return useT()(_str, props); } T.propTypes = { _str: PropTypes.string.isRequired }; function UT({ _str, _inline = false, ...props }) { const translation = useT()(_str, { _inline, _escapeVars: true, ...props }); const parentProps = { dangerouslySetInnerHTML: { __html: translation } }; const parent = _inline ? 'span' : 'div'; return /*#__PURE__*/React.createElement(parent, parentProps); } UT.propTypes = { _str: PropTypes.string.isRequired, _inline: PropTypes.bool }; function TXProvider({ instance, children }) { return /*#__PURE__*/React.createElement(TXNativeContext.Provider, { value: { instance } }, children); } export { LanguagePicker, T, TXProvider, UT, useLanguages, useLocale, useT, useTX, useTranslations }; //# sourceMappingURL=index.modern.js.map