@transifex/react
Advanced tools
Comparing version 0.6.5 to 0.7.0
@@ -26,16 +26,70 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
function translateWithElements(_str, props) { | ||
const actualProps = {}; | ||
const reactElements = []; | ||
Object.entries(props).forEach(([key, value]) => { | ||
if ( /*#__PURE__*/React__default.isValidElement(value)) { | ||
actualProps[key] = `__txnative__${reactElements.length}__txnative__`; | ||
reactElements.push(value); | ||
} else { | ||
actualProps[key] = value; | ||
} | ||
}); | ||
const translation = native.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__default.createElement(React__default.Fragment, { | ||
key: lastKey | ||
}, chunk)); | ||
lastKey += 1; | ||
} | ||
result.push( /*#__PURE__*/React__default.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__default.createElement(React__default.Fragment, { | ||
key: lastKey | ||
}, chunk)); | ||
} | ||
if (result.length === 0) { | ||
return ''; | ||
} | ||
if (result.length === 1) { | ||
return result[0].props.children; | ||
} | ||
return /*#__PURE__*/React__default.createElement(Fragment, null, result); | ||
} | ||
function useT(_str, props) { | ||
const [translation, setTranslation] = React.useState(''); | ||
const [, setCounter] = React.useState(0); | ||
React.useEffect(() => { | ||
function render() { | ||
setTranslation(native.t(_str, props)); | ||
function rerender() { | ||
setCounter(c => c + 1); | ||
} | ||
render(); | ||
native.onEvent(native.LOCALE_CHANGED, render); | ||
native.onEvent(native.LOCALE_CHANGED, rerender); | ||
return () => { | ||
native.offEvent(native.LOCALE_CHANGED, render); | ||
native.offEvent(native.LOCALE_CHANGED, rerender); | ||
}; | ||
}, [_str, props]); | ||
return translation; | ||
}, [setCounter]); | ||
return translateWithElements(_str, props); | ||
} | ||
@@ -42,0 +96,0 @@ |
import React, { useState, useEffect } from 'react'; | ||
import { tx, onEvent, LOCALE_CHANGED, offEvent, t } from '@transifex/native'; | ||
import { tx, t, onEvent, LOCALE_CHANGED, offEvent } from '@transifex/native'; | ||
import PropTypes from 'prop-types'; | ||
@@ -23,16 +23,70 @@ | ||
function translateWithElements(_str, props) { | ||
const actualProps = {}; | ||
const reactElements = []; | ||
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(React.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(React.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(_str, props) { | ||
const [translation, setTranslation] = useState(''); | ||
const [, setCounter] = useState(0); | ||
useEffect(() => { | ||
function render() { | ||
setTranslation(t(_str, props)); | ||
function rerender() { | ||
setCounter(c => c + 1); | ||
} | ||
render(); | ||
onEvent(LOCALE_CHANGED, render); | ||
onEvent(LOCALE_CHANGED, rerender); | ||
return () => { | ||
offEvent(LOCALE_CHANGED, render); | ||
offEvent(LOCALE_CHANGED, rerender); | ||
}; | ||
}, [_str, props]); | ||
return translation; | ||
}, [setCounter]); | ||
return translateWithElements(_str, props); | ||
} | ||
@@ -39,0 +93,0 @@ |
{ | ||
"name": "@transifex/react", | ||
"version": "0.6.5", | ||
"version": "0.7.0", | ||
"description": "Transifex Native for React", | ||
@@ -37,5 +37,5 @@ "keywords": [ | ||
"peerDependencies": { | ||
"@transifex/native": "^0.6.0", | ||
"@transifex/native": "^0.7.0", | ||
"prop-types": "^15.0.0", | ||
"react": "^16.0.0" | ||
"react": "^16.0.0 || ^17.0.0" | ||
}, | ||
@@ -45,3 +45,3 @@ "devDependencies": { | ||
"@testing-library/react": "^10.4.9", | ||
"@transifex/native": "^0.6.5", | ||
"@transifex/native": "^0.7.0", | ||
"eslint": "^6.6.0", | ||
@@ -48,0 +48,0 @@ "eslint-config-airbnb": "^18.2.0", |
@@ -48,2 +48,35 @@ # Transifex Native for React | ||
The T-component can accept React elements as properties and they will be | ||
rendered properly, ie this would be possible: | ||
```javascript | ||
<T | ||
_str="A {button} and a {bold} walk into a bar" | ||
button={<button><T _str="button" /></button>} | ||
bold={<b><T _str="bold" /></b>} /> | ||
``` | ||
This will render like this in English: | ||
```html | ||
A <button>button</button> and a <b>bold</b> walk into a bar | ||
``` | ||
And like this in Greek: | ||
```html | ||
Ένα <button>κουμπί</button> και ένα <b>βαρύ</b> μπαίνουν σε ένα μπαρ | ||
``` | ||
Assuming the translations look like this: | ||
| source | translation | | ||
|-----------------------------------------|--------------------------------------------------| | ||
| A {button} and a {bold} walk into a bar | Ένα {button} και ένα {bold} μπαίνουν σε ένα μπαρ | | ||
| button | κουμπί | | ||
| bold | βαρύ | | ||
The main thing to keep in mind is that the `_str` property to the T-component | ||
must **always** be a valid ICU messageformat template. | ||
### `UT` Component | ||
@@ -77,2 +110,6 @@ | ||
_Note: If you supply React elements as properties to the `UT` component, it | ||
will misbehave by rendering `[object Object]`. Only use React elements as | ||
properties with the `T` component._ | ||
### `useT` hook | ||
@@ -79,0 +116,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40390
314
210