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

react-localization

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-localization - npm Package Compare versions

Comparing version 0.1.10 to 1.0.0

254

lib/LocalizedStrings.js
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
value: true
});

@@ -9,4 +9,2 @@

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

@@ -18,12 +16,8 @@

var _utils = require('./utils');
var _localizedStrings = require('localized-strings');
var utils = _interopRequireWildcard(_utils);
var _localizedStrings2 = _interopRequireDefault(_localizedStrings);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**

@@ -45,210 +39,52 @@ * Simple module to localize the React interface using the same syntax

var placeholderRegex = /(\{[\d|\w]+\})/;
var isReactComponent = function isReactComponent(value) {
return _typeof(value.$$typeof) === 'symbol';
return _typeof(value.$$typeof) === 'symbol';
};
var placeholderRegex = /(\{[\d|\w]+\})/;
var LocalizedStrings = function () {
_createClass(LocalizedStrings, [{
key: '_getBestMatchingLanguage',
value: function _getBestMatchingLanguage(language, props) {
//If an object with the passed language key exists return it
if (props[language]) return language;
/**
* Format the passed string replacing the numbered or tokenized placeholders
* eg. 1: I'd like some {0} and {1}, or just {0}
* eg. 2: I'd like some {bread} and {butter}, or just {bread}
* Use example:
* eg. 1: strings.formatString(strings.question, strings.bread, strings.butter)
* eg. 2: strings.formatString(strings.question, { bread: strings.bread, butter: strings.butter }
*
* THIS METHOD OVERRIDE the one of the parent class by adding support for JSX code
*/
_localizedStrings2.default.prototype.formatString = function (str) {
for (var _len = arguments.length, valuesForPlaceholders = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
valuesForPlaceholders[_key - 1] = arguments[_key];
}
//if the string is composed try to find a match with only the first language identifiers (en-US --> en)
var idx = language.indexOf('-');
var auxLang = idx >= 0 ? language.substring(0, idx) : language;
return props[auxLang] ? auxLang : Object.keys(props)[0];
return str.split(placeholderRegex).filter(function (textPart) {
return !!textPart;
}).map(function (textPart, index) {
if (textPart.match(placeholderRegex)) {
var matchedKey = textPart.slice(1, -1);
var valueForPlaceholder = valuesForPlaceholders[matchedKey];
// If no value found, check if working with an object instead
if (valueForPlaceholder == undefined) {
var valueFromObjectPlaceholder = valuesForPlaceholders[0][matchedKey];
if (valueFromObjectPlaceholder !== undefined) {
valueForPlaceholder = valueFromObjectPlaceholder;
} else {
// If value still isn't found, then it must have been undefined/null
return valueForPlaceholder;
}
}]);
}
function LocalizedStrings(props) {
_classCallCheck(this, LocalizedStrings);
if (isReactComponent(valueForPlaceholder)) {
return _react2.default.Children.toArray(valueForPlaceholder).map(function (component) {
return _extends({}, component, { key: index.toString() });
});
}
this._interfaceLanguage = utils.getInterfaceLanguage();
this._language = this._interfaceLanguage;
this.setContent(props);
return valueForPlaceholder;
}
return textPart;
});
};
_createClass(LocalizedStrings, [{
key: 'setContent',
value: function setContent(props) {
this._defaultLanguage = Object.keys(props)[0];
this._defaultLanguageFirstLevelKeys = [];
//Store locally the passed strings
this._props = props;
utils.validateTranslationKeys(Object.keys(props[this._defaultLanguage]));
//Store first level keys (for identifying missing translations)
for (var key in this._props[this._defaultLanguage]) {
if (typeof this._props[this._defaultLanguage][key] == "string") {
this._defaultLanguageFirstLevelKeys.push(key);
}
}
//Set language to its default value (the interface)
this.setLanguage(this._interfaceLanguage);
}
//Can be used from ouside the class to force a particular language
//indipendently from the interface one
}, {
key: 'setLanguage',
value: function setLanguage(language) {
//Check if exists a translation for the current language or if the default
//should be used
var bestLanguage = this._getBestMatchingLanguage(language, this._props);
var defaultLanguage = Object.keys(this._props)[0];
this._language = bestLanguage;
//Associate the language object to the this object
if (this._props[bestLanguage]) {
//delete default propery values to identify missing translations
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = this._defaultLanguageFirstLevelKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
key = _step.value;
delete this[key];
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var localizedStrings = Object.assign({}, this._props[this._language]);
for (var key in localizedStrings) {
if (localizedStrings.hasOwnProperty(key)) {
this[key] = localizedStrings[key];
}
}
//Now add any string missing from the translation but existing in the default language
if (defaultLanguage !== this._language) {
localizedStrings = this._props[defaultLanguage];
this._fallbackValues(localizedStrings, this);
}
}
}
//Load fallback values for missing translations
}, {
key: '_fallbackValues',
value: function _fallbackValues(defaultStrings, strings) {
for (var key in defaultStrings) {
if (defaultStrings.hasOwnProperty(key) && !strings[key]) {
strings[key] = defaultStrings[key];
console.log('\uD83D\uDEA7 \uD83D\uDC77 key \'' + key + '\' not found in localizedStrings for language ' + this._language + ' \uD83D\uDEA7');
} else {
if (typeof strings[key] != "string") {
//It's an object
this._fallbackValues(defaultStrings[key], strings[key]);
}
}
}
}
//The current language displayed (could differ from the interface language
// if it has been forced manually and a matching translation has been found)
}, {
key: 'getLanguage',
value: function getLanguage() {
return this._language;
}
//The current interface language (could differ from the language displayed)
}, {
key: 'getInterfaceLanguage',
value: function getInterfaceLanguage() {
return this._interfaceLanguage;
}
//Return an array containing the available languages passed as props in the constructor
}, {
key: 'getAvailableLanguages',
value: function getAvailableLanguages() {
if (!this._availableLanguages) {
this._availableLanguages = [];
for (var language in this._props) {
this._availableLanguages.push(language);
}
}
return this._availableLanguages;
}
//Format the passed string replacing the numbered or tokenized placeholders
//eg. 1: I'd like some {0} and {1}, or just {0}
//eg. 2: I'd like some {bread} and {butter}, or just {bread}
//Use example:
//eg. 1: strings.formatString(strings.question, strings.bread, strings.butter)
//eg. 2: strings.formatString(strings.question, { bread: strings.bread, butter: strings.butter })
}, {
key: 'formatString',
value: function formatString(str) {
for (var _len = arguments.length, valuesForPlaceholders = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
valuesForPlaceholders[_key - 1] = arguments[_key];
}
return str.split(placeholderRegex).filter(function (textPart) {
return !!textPart;
}).map(function (textPart, index) {
if (textPart.match(placeholderRegex)) {
var matchedKey = textPart.slice(1, -1);
var valueForPlaceholder = valuesForPlaceholders[matchedKey];
// If no value found, check if working with an object instead
if (valueForPlaceholder == undefined) {
var valueFromObjectPlaceholder = valuesForPlaceholders[0][matchedKey];
if (valueFromObjectPlaceholder !== undefined) {
valueForPlaceholder = valueFromObjectPlaceholder;
} else {
// If value still isn't found, then it must have been undefined/null
return valueForPlaceholder;
}
}
if (isReactComponent(valueForPlaceholder)) {
return _react2.default.Children.toArray(valueForPlaceholder).map(function (component) {
return _extends({}, component, { key: index.toString() });
});
}
return valueForPlaceholder;
}
return textPart;
});
}
//Return a string with the passed key in a different language
}, {
key: 'getString',
value: function getString(key, language) {
try {
return this._props[language][key];
} catch (ex) {
console.log("No localization found for key " + key + " and language " + language);
}
return null;
}
}]);
return LocalizedStrings;
}();
exports.default = LocalizedStrings;
exports.default = _localizedStrings2.default;

3

package.json
{
"name": "react-localization",
"version": "0.1.10",
"version": "1.0.0",
"description": "Simple module to localize the React interface using the same syntax used in the ReactNativeLocalization module, use 'npm run build' before publishing",

@@ -36,4 +36,5 @@ "scripts": {

"dependencies": {
"localized-strings": "0.0.4",
"react": "^16.0.0"
}
}

@@ -5,2 +5,5 @@ # react-localization

### Note about version 1.x
This library has been refactored to use the newly created [localized-strings package]((https://github.com/stefalda/localized-strings), now added as a dependency, so to unify the code and make it easier to mantain
## How it works

@@ -46,30 +49,2 @@

```
## TYPESCRIPT SUPPORT
Because of the dynamically generated class properties, it's a little tricky to have the autocomplete functionality working.
Anyway it's possible to gain the desired results by:
1. defining an Interface that extends the LocalizedStringsMethods interface and has all the object string's keys
2. defining that the LocalizedStrings instance implements that interface
This is the suggested solution to work with Typescript:
```js
export interface IStrings extends LocalizedStringsMethods{
score:string;
time: String;
}
public strings: IStrings;
this.strings = new LocalizedStrings({
it: {
score: "Punti",
time: "Tempo"
},
en: {
score: "Score",
time: "Time"
}
});
```
## API

@@ -124,4 +99,31 @@

```
## Typescript support
Because of the dynamically generated class properties, it's a little tricky to have the autocomplete functionality working.
Anyway it's possible to gain the desired results by:
1. defining an Interface that extends the LocalizedStringsMethods interface and has all the object string's keys
2. defining that the LocalizedStrings instance implements that interface
This is the suggested solution to work with Typescript:
```js
export interface IStrings extends LocalizedStringsMethods{
score:string;
time: String;
}
public strings: IStrings;
this.strings = new LocalizedStrings({
it: {
score: "Punti",
time: "Tempo"
},
en: {
score: "Score",
time: "Time"
}
});
```
## Questions or suggestions?
Feel free to contact me on [Twitter](https://twitter.com/talpaz) or [open an issue](https://github.com/stefalda/react-localization/issues/new).
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