react-localization
Advanced tools
Comparing version 0.1.10 to 1.0.0
'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; |
{ | ||
"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). |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
127
11029
2
6
92
1
+ Addedlocalized-strings@0.0.4
+ Addedlocalized-strings@0.0.4(transitive)