Capitalising interpolated language keys - reactjs

The problem:
With i18next you can interpolate variables into your string like "AddNew": "Add new {{item}}" Now I have a language where the grammar requires the {{item}} needs to be the first word like "AddNew": "{{item}} toevoegen".
In the docs they show some support for formatting, but these are all related to dates or numbers. I am looking for a way to add a capitalisation formatting function e.g: "AddNew": "{{item, capitalise }} toevoegen"
What I have so far but isn't working
A function that capitalises the first letter.
export function capitalizeFirstLetter(string: string): string {
return string.charAt(0).toUpperCase() + string.slice(1);
};
And attempting to add it to the formatters
i18n.services.formatter?.add('capitalize', (value, lng, options) => {
return capitalizeFirstLetter(value);
});
Now I had to add a ? after .formatter for TS to not complain. But I'd guess that this is also the issue, formatter is undefined. I can only import Formatter and Services with a capital letter from the i18next library, so I'm a bit lost on how to continue.

Make sure you add your custom formatter AFTER you called i18next.init(): https://www.i18next.com/translation-function/formatting#adding-custom-format-function

Related

How can I do string interpolation in a string variable in React?

I have a variable coming from a static JSON file:
`const label = json.myString`
Where json.myString is "Hello, ${ name }". Since this is a variable, I do not know what it would be before hand.
And I want to do some string interpolation in my react component:
<div>{ label }</div>
How can I do this? Bonus points for a backup/default option if xyz is undefined
You should use template engine for this, for example, Mustache.
However, you can use an eval, but you don't want to use it, because it is unsafe in your case (some injections can be performed, if someone will perform a MITM-attack for your server, for example).
var a = "kappa"
console.log(eval("`Hello, ${a}!`"))
The other option that you can use is regular expressions.
There are 2 moments, that you should notice in this case:
Variables must be exist in some context, e.g. this, to allow stringified variables names be passed as key
You should not use special symbols of your template bounds inside template, or you should additionaly handle each special symbol inside regular expression.
var template = "My awesome template says: \"${ say }\""
var data = { say: "Hello!" }
console.log(template.replace(/\$\{([^}]+)\}/g, (match, group) => {
return data[group.trim()]
}))
By the way, this question is not React-specific, I suppose, but JS-specific. React doen't provide any profit features for this kind of logic tasks :)
The purpose of template literals is to avoid the usage of "some string" + "another string", and not much functionally.
In this scenario, it would be best to decouple the name with Hello.
That way, you could call
<div>Hello, ${name} </div>
In case you'd like to create a flexible greeting as well, you could then add the greeting as another string. E.g.:
{
name: "John Doe",
greeting: "Hello"
}
And go,
<div>${greeting}, ${name}</div>

Replace , with . in input field bound to property using Angular 1

I have an input field that is supposed to contain numbers.
It is bound to an object property.
I want input entered as 4,5 to automatically get converted to 4.5 in both model and view.
HTML:
<input data-ng-model="productContent(product.Id).Org" value="{{productContent(product.Id).Org | replaceComma}}" />
Control:
$scope.productContent = function (prodId) {
var content = $.grep($scope.productsContent, function (el) { return el.ProdId === prodId });
return content[0];}
Filter:
app.filter('replaceComma', function () {
return function (val) {
return (typeof val) == "string" ? val.toString().trim().replace(",", ".") : val
};
});
Result:
When I enter a number, at first the model (productContent) retrieves the correct object. Then the filter code is called and returns a correctly converted string. I would expect both the model and view to be updated to the filtered value, but both are updated with the unfiltered value. What am I doing wrong?
I have faced the same problem in the past but instead of creating my own filter, I took a different path and found something ready to use instead.
angular-input-masks by assisrafael one of my favourite angular extensions for this purpose:
https://github.com/assisrafael/angular-input-masks
Examples:
http://assisrafael.github.io/angular-input-masks/
Since the author has written the documentation, I don't want to get extensive on it and be outdated in the future. As a quick reference, look for ui-number-mask.
Maybe this is not a direct answer to your question, since it's not replacing commas with periods, but making you type the decimals instead.
On a side note, you can suppress the thousands separators with ui-hide-group-sep
I hope that's helpful, otherwise leave a comment and I'll be happy to continue to assist you!
-Helvio

Angular material autocomplete search anywhere in string?

https://material.angularjs.org/latest/#/demo/material.components.autocomplete
Please can someone tell me how to make autocomplete (Angular material) to search string not only at the beginning of words, but anywhere within the words.
For example the word Alabama:
Works when you type "Ala", but does not work when you type "bama".
How do I make it to work when I type "bama"?
I know I can use a third party directive such as Angucomplete Alt:
http://ghiden.github.io/angucomplete-alt/
but I think Angular material should have this option?
This is a function from the original md-autocomplete:
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(state) {
return (state.value.indexOf(lowercaseQuery) === 0);
};
}
Please try changing the condition a little bit, like this:
return (state.value.indexOf(lowercaseQuery) >= 0);
and it should work the way you want.
The demo only matches characters at the beginning of the result due to specifying the caret flag, ie: md-highlight-flags="^i"
To allow autocomplete to find any matching characters you should use the global flag, ie: md-highlight-flags="gi"
You will also need to change the state.value.indexOf(lowercaseQuery) === 0 line in the filterFn function to state.value.indexOf(lowercaseQuery) !== -1
Check this codepen for a working example:
http://codepen.io/DevVersion/pen/KrOYoG

Make part of the text as link.(react - localization)

I need to mark part of the text as a link. Something like:
"Please log in with your email...". This text must be localized later.
I need that "log in" part to be the link.
When I do something like this in the render method:
var link = React.DOM.a({
href: this.makeHref('login')
},
'log in'
);// or React.createElement or
//var link = <a href={this.makeHref('login')}>
// 'log in'</a>;
<div>{'Please '+ link + ' with your email...'}</div>
It will output:
Please `[object Object]` with your email...
Without surround text, I receive the expected result. In other words: How to make react render HTML not object.
This is a simplified example - I need to insert link text with format marker {0} like in C# - or any other working solution.
Thank you for help!
If you want to use an element within another element, just use curly braces like so:
var Component = React.createClass({
render: function() {
var link = <a href={this.makeHref('login')}>log in</a>;
return <div>Please {link} with your email.</div>;
}
};
You can see a working fiddle here: https://jsfiddle.net/jrunning/fencjn4x/
If you're going to be internationalizing your app at some point in the future I recommend a) crossing that bridge when you come to it, and b) using a solution like React Intl instead of trying to build your own solution with string concatenation.

How to stringify JSON to JavaScript array

My form in the html DOM is a checkbox to click (there can be more than one). The problem occurs in the description string when ever I use an apostrophe, since my list object is single-quote deliniated. This is one of the checkboxes in the form:
<input type="checkbox" id="cbx" name="cbx" value="{'getPic': 'url', 'picsrc': 'http://lh3.ggpht.com/_ZB3cttqooN0/SVmJPfusGWI/AAAAAAAADvA/GuIRgh6eMOI/Grand%20Canyon%201213_121508214.JPG', 'pos': None, 'description': 'Here's what it REALLY looks like at 5:30am! Bring your headlight!'}">
The javascript that reads the values of the checked checkboxes and pushes them into an array (list):
var pylist = [];
for (i=0; i<document.picList.cbx.length; i++) {
if (document.picList.cbx[i].checked) {
pylist.push( document.picList.cbx[i].value );
}
}
var getstr = JSON.stringify(pylist);
The problem is always that getstr at this point has chopped off everthing after the single quote in the description property.
I've tried different ways of escaping it to little avail.
The problem is that the value of the checkbox already is a JSON string. One solution would be to call JSON.parse() on the value:
var pylist = [];
for (i=0; i<document.picList.cbx.length; i++) {
if (document.picList.cbx[i].checked) {
pylist.push( JSON.parse( document.picList.cbx[i].value) );
}
}
var getstr = JSON.stringify(pylist);
I've run into the same issue - we stick json in a hidden field so we don't have to query the server on every page. We replace apostrophes with a "code" before putting into the html - we added a javascript function that replaces the code with an apostrophe.
Really hacky, but it works really well. Of course, we have one place in the code that gets json from the server and one place where javascript needs to parse it - if you find you're repeating the methods throughout your code, your mileage will vary.

Resources