Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@m6web/react-i18n

Package Overview
Dependencies
Maintainers
6
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@m6web/react-i18n - npm Package Compare versions

Comparing version 1.9.2 to 2.0.0-alpha.0

es/utils/html.utils.js

6

es/components/i18n.provider.js

@@ -10,6 +10,7 @@ import React from 'react';

children = _ref.children,
errorCallback = _ref.errorCallback;
errorCallback = _ref.errorCallback,
parseHTML = _ref.parseHTML;
return React.createElement(
Context.Provider,
{ value: translate(lang, i18nNames, errorCallback) },
{ value: translate(lang, i18nNames, errorCallback, parseHTML) },
children

@@ -22,4 +23,5 @@ );

lang: PropTypes.object.isRequired,
parseHTML: PropTypes.bool,
i18nNames: PropTypes.object,
errorCallback: PropTypes.func
};

@@ -7,7 +7,4 @@ import _has from 'lodash-es/has';

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
import React from 'react';
import { sprintf } from 'sprintf-js';
import { interpolateHTMLTags } from './html.utils';

@@ -52,89 +49,6 @@ var pluralizeFunctions = {

// find tags like : <Something>with content inside</Something>
var JSX_TAG_WITH_CONTENT_REGEX = /(.*?)<([A-Z]\w+)>(.*)<\/\2+>(.*)/;
// find tags like : <Something />
var SHORT_JSX_TAG_REGEX = /(.*?)<([A-Z]\w+) ?\/>(.*)/;
var parseJSX = function parseJSX(content) {
var regexResultTagWithContent = JSX_TAG_WITH_CONTENT_REGEX.exec(content);
if (regexResultTagWithContent) {
return {
beforeTagContent: regexResultTagWithContent[1],
componentTag: regexResultTagWithContent[2],
insideTagContent: regexResultTagWithContent[3],
afterTagContent: regexResultTagWithContent[4]
};
}
var regexResultShortTag = SHORT_JSX_TAG_REGEX.exec(content);
if (regexResultShortTag) {
return {
beforeTagContent: regexResultShortTag[1],
componentTag: regexResultShortTag[2],
afterTagContent: regexResultShortTag[3]
};
}
return null;
};
var createComponentInstance = function createComponentInstance(component, children) {
if (!component) {
return null;
}
return React.createElement.apply(React, [component, {}].concat(_toConsumableArray(Array.isArray(children) ? children : [children])));
};
var interpolateJSXInsideTranslation = function interpolateJSXInsideTranslation(translation, renderers) {
var parsingResult = parseJSX(translation);
if (!parsingResult) {
return translation;
}
var beforeTagContent = parsingResult.beforeTagContent,
componentTag = parsingResult.componentTag,
insideTagContent = parsingResult.insideTagContent,
afterTagContent = parsingResult.afterTagContent;
var translationChildren = [];
var interpolateAndAddToChildren = function interpolateAndAddToChildren(content) {
var interpolatedContent = interpolateJSXInsideTranslation(content, renderers);
if (typeof interpolatedContent === 'string') {
translationChildren.push(interpolatedContent);
}
if (Array.isArray(interpolatedContent)) {
translationChildren.push.apply(translationChildren, _toConsumableArray(interpolatedContent));
}
};
if (beforeTagContent) {
interpolateAndAddToChildren(beforeTagContent);
}
if (componentTag) {
var interpolatedChildren = insideTagContent ? interpolateJSXInsideTranslation(insideTagContent, renderers) : null;
var rendererToUse = renderers[componentTag];
var componentInstance = createComponentInstance(rendererToUse, interpolatedChildren);
if (componentInstance) {
translationChildren.push(componentInstance);
} else {
// eslint-disable-next-line no-console
console.warn('No renderer provided for component "' + componentTag + '"');
}
}
if (afterTagContent) {
interpolateAndAddToChildren(afterTagContent);
}
return translationChildren;
};
export var translate = function translate(lang) {
var i18nNames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var errorCallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _noop;
var parseHTML = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

@@ -164,8 +78,8 @@ var pluralize = pluralizeFunctions[_get(lang, '_i18n.lang')] || pluralizeFunctions.fr;

var translatedResult = sprintf(translation, _extends({}, data, i18nNames, { number: number }));
if (renderers) {
var JSXTranslated = interpolateJSXInsideTranslation(translatedResult, renderers);
return createComponentInstance(React.Fragment, JSXTranslated);
}
if (!parseHTML) return translatedResult;
var htmlTags = interpolateHTMLTags(translatedResult, renderers);
if (htmlTags.length > 1) return htmlTags;
return translatedResult;

@@ -172,0 +86,0 @@ };

@@ -26,6 +26,7 @@ 'use strict';

children = _ref.children,
errorCallback = _ref.errorCallback;
errorCallback = _ref.errorCallback,
parseHTML = _ref.parseHTML;
return _react2.default.createElement(
_i18n2.Context.Provider,
{ value: (0, _i18n.translate)(lang, i18nNames, errorCallback) },
{ value: (0, _i18n.translate)(lang, i18nNames, errorCallback, parseHTML) },
children

@@ -38,4 +39,5 @@ );

lang: _propTypes2.default.object.isRequired,
parseHTML: _propTypes2.default.bool,
i18nNames: _propTypes2.default.object,
errorCallback: _propTypes2.default.func
};

@@ -10,6 +10,2 @@ 'use strict';

var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _lodash = require('lodash');

@@ -21,6 +17,6 @@

var _html = require('./html.utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var pluralizeFunctions = {

@@ -64,89 +60,6 @@ en: function en(number) {

// find tags like : <Something>with content inside</Something>
var JSX_TAG_WITH_CONTENT_REGEX = /(.*?)<([A-Z]\w+)>(.*)<\/\2+>(.*)/;
// find tags like : <Something />
var SHORT_JSX_TAG_REGEX = /(.*?)<([A-Z]\w+) ?\/>(.*)/;
var parseJSX = function parseJSX(content) {
var regexResultTagWithContent = JSX_TAG_WITH_CONTENT_REGEX.exec(content);
if (regexResultTagWithContent) {
return {
beforeTagContent: regexResultTagWithContent[1],
componentTag: regexResultTagWithContent[2],
insideTagContent: regexResultTagWithContent[3],
afterTagContent: regexResultTagWithContent[4]
};
}
var regexResultShortTag = SHORT_JSX_TAG_REGEX.exec(content);
if (regexResultShortTag) {
return {
beforeTagContent: regexResultShortTag[1],
componentTag: regexResultShortTag[2],
afterTagContent: regexResultShortTag[3]
};
}
return null;
};
var createComponentInstance = function createComponentInstance(component, children) {
if (!component) {
return null;
}
return _react2.default.createElement.apply(_react2.default, [component, {}].concat(_toConsumableArray(Array.isArray(children) ? children : [children])));
};
var interpolateJSXInsideTranslation = function interpolateJSXInsideTranslation(translation, renderers) {
var parsingResult = parseJSX(translation);
if (!parsingResult) {
return translation;
}
var beforeTagContent = parsingResult.beforeTagContent,
componentTag = parsingResult.componentTag,
insideTagContent = parsingResult.insideTagContent,
afterTagContent = parsingResult.afterTagContent;
var translationChildren = [];
var interpolateAndAddToChildren = function interpolateAndAddToChildren(content) {
var interpolatedContent = interpolateJSXInsideTranslation(content, renderers);
if (typeof interpolatedContent === 'string') {
translationChildren.push(interpolatedContent);
}
if (Array.isArray(interpolatedContent)) {
translationChildren.push.apply(translationChildren, _toConsumableArray(interpolatedContent));
}
};
if (beforeTagContent) {
interpolateAndAddToChildren(beforeTagContent);
}
if (componentTag) {
var interpolatedChildren = insideTagContent ? interpolateJSXInsideTranslation(insideTagContent, renderers) : null;
var rendererToUse = renderers[componentTag];
var componentInstance = createComponentInstance(rendererToUse, interpolatedChildren);
if (componentInstance) {
translationChildren.push(componentInstance);
} else {
// eslint-disable-next-line no-console
console.warn('No renderer provided for component "' + componentTag + '"');
}
}
if (afterTagContent) {
interpolateAndAddToChildren(afterTagContent);
}
return translationChildren;
};
var translate = exports.translate = function translate(lang) {
var i18nNames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var errorCallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _lodash2.default.noop;
var parseHTML = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;

@@ -176,8 +89,8 @@ var pluralize = pluralizeFunctions[_lodash2.default.get(lang, '_i18n.lang')] || pluralizeFunctions.fr;

var translatedResult = (0, _sprintfJs.sprintf)(translation, _extends({}, data, i18nNames, { number: number }));
if (renderers) {
var JSXTranslated = interpolateJSXInsideTranslation(translatedResult, renderers);
return createComponentInstance(_react2.default.Fragment, JSXTranslated);
}
if (!parseHTML) return translatedResult;
var htmlTags = (0, _html.interpolateHTMLTags)(translatedResult, renderers);
if (htmlTags.length > 1) return htmlTags;
return translatedResult;

@@ -184,0 +97,0 @@ };

{
"name": "@m6web/react-i18n",
"version": "1.9.2",
"version": "2.0.0-alpha.0",
"description": "Provider and utils for translation in a react app",

@@ -54,4 +54,3 @@ "main": "lib/index.js",

"release": "yarn lint && yarn test && yarn build && yarn version"
},
"gitHead": "d4af2194bd9db341492239d0375e3cf4ab0e5738"
}
}

@@ -51,3 +51,3 @@ # @m6web/react-i18n

const Root = () => (
<I18nProvider lang={translations} i18nNames={i18nNames} errorCallback={errorCallback}>
<I18nProvider lang={translations} i18nNames={i18nNames} errorCallback={errorCallback} parseHTML>
<App />

@@ -60,2 +60,11 @@ </I18nProvider>

### i18n Provider
This component will provide the translation function to following components via the React.Context api.
* **lang**: translation dictionary
* **i18nNames**: static translation values for interpolation
* **errorCallback**: callback triggered when an error happens during the execution of the translation function
* **parseHTML**: activates parsing of HTML inside translation
* **children**: your App main component
### i18n String component

@@ -72,3 +81,3 @@

export default const MyComponent = ({ nbExample, t }) => {
export const MyComponent = ({ nbExample, t }) => {
return (

@@ -102,3 +111,3 @@ <div class="foo">

export default const MyComponent = ({ nbExample, t }) => {
export const MyComponent = ({ nbExample, t }) => {
return (

@@ -223,4 +232,114 @@ <div class="foo">

### JSX Interpolation
### HTML Interpolation
Basic html tags are automatically interpolated in translation if the syntax is correct (opening tag should be close within the translation).
Attributes are supported too.
Basic textual interpolations are proceeded first, and the HTML comes in a second time.
- translation
```json
{
"foo": {
"bar": "<a href=\"/page-%(number)s\">To page %(number)s</a>"
}
}
```
- code
```jsx
import React from 'react';
import { useTranslate } from './useTranslate';
export const MyComponent = () => {
const t = useTranslate();
return (
<div class="foo">
<p>{t('foo.bar', { number: 2 })}</p>
</div>
);
}
```
- result
```jsx harmony
<div>
<p>
<a href="/page-2">To page 2</a>
</p>
</div>
```
#### excluded elements
For now `script` and `iframe` elements are ignored with all their children in the HTML tree.
#### keys
In case of arrays of component, keys will be automatically generated to please React.
- translation
```js
{
foo: {
bar:
'<h1>Test</h1>' +
'<p>This is not what we wanna do with this lib but we need to ensure it works anyway</p>' +
'<ul>' +
'<li>simple link to <a href="https://github.com/M6Web/i18n-tools" target="_blank">the package</a>.</li>' +
'<li>a disabled <button disabled>button</button></li>' +
'<li>and an auto closing br <br /></li>' +
'</ul>'
}
};
```
- result
```jsx harmony
<div>
<h1
key="h1-0"
>
Test
</h1>
<p
key="p-1"
>
This is not what we wanna do with this lib but we need to ensure it works anyway
</p>
<ul
key="ul-2"
>
<li
key="li-0"
>
simple link to
<a
href="https://github.com/M6Web/i18n-tools"
key="a-1"
target="_blank"
>
the package
</a>
.
</li>
<li
key="li-1"
>
a disabled
<button
disabled={true}
key="button-1"
>
button
</button>
</li>
<li
key="li-2"
>
and an auto closing br
<br
key="br-1"
/>
</li>
</ul>
</div>
```
#### JSX Interpolation
It is possible to interpolate JSX components inside translation, to do so you have to give `renderers` parameter or props.

@@ -231,6 +350,7 @@ For example if you have in your translation : `foo <LinkToHome>bar</LinkToHome>` you should have a `LinkToHome` renderer.

import React from 'react';
import { Link } from 'react-router-dom';
import { useTranslate } from '@m6web/react-i18n';
const renderers = {
LinkToHome: ({ children }) => <a href="/">{children}</a>,
LinkToHome: ({ children }) => <Link to="home">{children}</Link>,
};

@@ -251,11 +371,4 @@

For the moment only the children props are used by the renderer.
Attributes are also supported.
```jsx harmony
// Do
<Link>Home</Link>
<Link /> or <Link/>
// Don't
<Link href="/home">Home</Link>
```
:warning: If the translation contains an unknown tag, the translation will be display without HTML parsing.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc