How to implement validations in multi language support website? - reactjs

I am currently implementing the multi language support in one of the website which is being implemented in react as front end tool. I am using react-i18next library for the translation of UI literals in the site. But I am not getting how to implement the various validations in the site , because the regex which I shall use in one text area for english language, shall not work with other language (e.g: Japanese). Kindly help me to figure out this.

What kind of validation are we talking about? Could you give some examples?
For most values the language shouldn't matter e.g numbers are all the same. Select options don't depend on the language - use the default language (before translating) to do the validation and only then translate.
For example:
const schema = yup.object().shape({
name: yup.string().required(i18.t("This field is required")),
pin_number: yup.matches(/\d{4}/, t("Is not in correct format"))
});
However if there is validation that is specific to a language, then yes you need to create a separate regex for each of them.
getLanguageSpecificRegex = () => {
let regex;
if (i18n.language === "en") {
regex = "C\d+";
} else (i18n.language === "et") {
regex = "K\d+";
} else {
regex = "\d+";
}
return regex;
}

As well as Regex, there is also date format and number format to consider, but regex is the biggest problem. Step 1 has got to be
i18n your regexes as well as your validation strings
so that you validation against e.g.
new Regex(i18n.t('regexFirstName'))
Instead of against /\w+/
Markup becomes messier if you are using a declarative markup validation framework:
render() {
return (
...
<input name="firstName" regex={new Regex(i18n.t('regexFirstName'))} />
...
)
but if you are setting validation in code then using
new Regex(i18n.t('regexFirstName'))
instead of
/regexLiteral/
is not a problem?

You are looking for the strategy design pattern.
You need to implement different strategies for different languages for your validation.

Related

can we edit the definitely typed file in typescript to change some parameter types?

Can we edit definitely typed file in Typescript?
When using ui-grid with typescript I came across a scenario where I edited the
ui-grid.d.ts file to make the date filter work. I need to filter the date based on the displayed result in the ui-grid and not on the
raw data (the data which I am getting from the Web API).
Here is the code snippet:
ui-grid.d.ts file code:(under interface IFilterOptions)
condition?: number;
Corresponding typescript code:
column.filter = {
condition: (searchTerm, cellValue, row, column) => {
var date = this.$filter("date")(row.entity.Date, this.masks.date.angular)
return (date + '').toLowerCase().indexOf(searchTerm.toLowerCase().replace(/\\/g, "")) !== -1;
}
}
The error I faced is as follows:
Type '(searchTerm:any, cellValue:any, row:any, coloumn:any) => boolean' is not assignable to type 'number'
After that I made the changes to the filter object to return a number as follows:
column.filter = {
condition: (searchTerm, cellValue, row, column) => {
var date = this.$filter("date")(row.entity.Date, this.masks.date.angular)
var res: number = (date + '').toLowerCase().indexOf(searchTerm.toLowerCase().replace(/\\/g, "")) !== -1 ? 1 : 0;
return res;
}
}
But after this I got error saying that:
Type '(searchTerm:any, cellValue:any, row:any, coloumn:any) => number' is not assignable to type 'number'
After this I made the change in the definitely typed file i.e. in the ui-grid.d.ts file as follows:
under interface IFilterOptions
I changed
condition?: number;
to
condition?: (searchTerm: any, cellValue: any, row: any, column: any) => boolean | number;
so the corresponding filter function which worked for me is as follows:
column.filter = {
condition: (searchTerm, cellValue, row, column) => {
var date = this.$filter("date")(row.entity.Date, this.masks.date.angular)
return (date + '').toLowerCase().indexOf(searchTerm.toLowerCase().replace(/\\/g, "")) !== -1;
}
}
Is this the right way to solve this problem?
Can anyone guide me to the right solution if the above solution is not good or it is not a good practice to edit the definitely typed file?
And also used
column.filterCellFiltered = true;
instead of filter function but it didn't work. This is also a concern as why it didn't work because I need to filter the date based on the displayed result in the ui-grid and not on the raw data. Can anyone explain why it didn't work?
Please help me understand the right approach. Let me know if anyone require any other details. Thanks in advance.
Angular JS version: AngularJS v1.4.7
Angular JS definitely typed version : Angular JS 1.4+
ui-grid Version: * ui-grid - v3.0.5
ui-grid definitely typed version: ui-grid v3.0.3
typescript version: 1.0.3.0
i had also same problem ,
adding "< any >" beginning of the function should solve the problem.
like this :
condition: <any>((searchTerm, cellValue, row, column) =>
{
return cellValue.indexOf(searchTerm) > -1
})
and don't forget to parenthesis ().
You can, but the changes will be overwritten the next time you install/upgrade that dependency, and won't be reflected in git (assuming you're not checking generated files into source control). You're better off overriding the type definitions in your project. The common way to do this is within an #types directory but anywhere within your TS project will work.
You'll want to create a file with the extension .d.ts under TS's project files. The modules within this file will be merged with other declaration files, to determine the final type definition. So in your case you'd want:
// ui-grid.override.d.ts
declare module 'ui-grid' {
// overriden types go here
}
The benefit of this method is that you only need to add the types you want, and the rest will be merged with the definitely typed declarations.
This is a very useful tool if you need to do things like type globals, or to provide additional type information for libraries. It's used extensively in the definitely typed declarations for library plugins which alter an api in some way.
I'd recommend reading the TS docs on declaration files as they're an incredibly useful tool if used correctly.
Although if you do find the types in definitely typed are incorrect/incomplete then please create a PR for the benefit of everyone
I do not recommend to modify definitions and sources of the libraries you do not actively develop. What will happen when you will decide to upgrade to the newer version and it will override your changes? You will be forced to merge them each time you upgrade. And the larger your project will get the more complicated this will become.
I would recommend to either submit a request to the angular-ui team, or find a way to go with existing functionality.
Hope this helps.

How do I implement angular ui-mask?

I am trying to create multiple masked input fields. Angular ui-mask looks like the way to go, however, I can't find very good documentation on the utility. I found an example for credit cards that was very nicely done. I would like to implement this feature in almost exactly the same way, but with 1) phone number 2) decimal 3) percentage 4) email 5) currency, such that the fields are dynamically masked as the user types. My question is how would I go about using ui-mask to accomplish these tasks? Or is there a better way to achieve this? Examples or links to documentation would be appreciated
I guess you can find your answer here:
https://github.com/angular-ui/ui-utils/issues/16
As it is explained in the link a dynamic way is that you can get the mask from a scope/controller variable, check the input and change the mask as needed like:
<input type="text" ui-mask="{{mask}}" ng-keyup="onKeyUp()" ng-model="myinput">
$scope.myinput = '';
var defaultMask = '(99) 9999-9999';
$scope.mask = defaultMask;
$scope.onKeyUp = function(){
if ($scope.myinput.slice(0,3) == '119') { // (11) 9 means mobile, or instead, you could use a regex
$scope.mask = '(99) 99999-9999';
} else {
$scope.mask = defaultMask;
}
};

the best way to make codeigniter website multi-language. calling from lang arrays depends on lang session?

I'm researching hours and hours, but I could not find any clear, efficient way to make it :/
I have a codeigniter base website in English and I have to add a Polish language now. What is the best way to make my site in 2 language depending visitor selection?
is there any way to create array files for each language and call them in view files depends on Session from lang selection? I don't wanna use database.
Appreciate helps! I'm running out of deadline :/ thanks!!
Have you seen CodeIgniter's Language library?
The Language Class provides functions
to retrieve language files and lines
of text for purposes of internationalization.
In your CodeIgniter system folder you'll
find one called language containing sets
of language files. You can create your
own language files as needed in order
to display error and other messages in
other languages.
Language files are typically stored in
your system/language directory. Alternately
you can create a folder called language
inside your application folder and store
them there. CodeIgniter will look first
in your application/language directory.
If the directory does not exist or the
specified language is not located there
CI will instead look in your global
system/language folder.
In your case...
you need to create a polish_lang.php and english_lang.php inside application/language/polish
then create your keys inside that file (e.g. $lang['hello'] = "Witaj";
then load it in your controller like $this->lang->load('polish_lang', 'polish');
then fetch the line like $this->lang->line('hello'); Just store the return value of this function in a variable so you can use it in your view.
Repeat the steps for the english language and all other languages you need.
Also to add the language to the session, I would define some constants for each language, then make sure you have the session library autoloaded in config/autoload.php, or you load it whenever you need it. Add the users desired language to the session:
$this->session->set_userdata('language', ENGLISH);
Then you can grab it anytime like this:
$language = $this->session->userdata('language');
In the controller add following lines when you make the cunstructor
i.e, after
parent::Controller();
add below lines
$this->load->helper('lang_translate');
$this->lang->load('nl_site', 'nl'); // ('filename', 'directory')
create helper file lang_translate_helper.php with following function and put it in directory system\application\helpers
function label($label, $obj)
{
$return = $obj->lang->line($label);
if($return)
echo $return;
else
echo $label;
}
for each of the language, create a directory with language abbrevation like en, nl, fr, etc., under
system\application\languages
create language file in above (respective) directory which will contain $lang array holding pairs label=>language_value as given below
nl_site_lang.php
$lang['welcome'] = 'Welkom';
$lang['hello word'] = 'worde Witaj';
en_site_lang.php
$lang['welcome'] = 'Welcome';
$lang['hello word'] = 'Hello Word';
you can store multiple files for same language with differently as per the requirement
e.g, if you want separate language file for managing backend (administrator section) you can use it in controller as $this->lang->load('nl_admin', 'nl');
nl_admin_lang.php
$lang['welcome'] = 'Welkom';
$lang['hello word'] = 'worde Witaj';
and finally
to print the label in desired language, access labels as below in view
label('welcome', $this);
OR
label('hello word', $this);
note the space in hello & word you can use it like this way as well :)
whene there is no lable defined in the language file, it will simply print it what you passed to the function label.
I second Randell's answer.
However, one could always integrate a GeoIP such as http://www.maxmind.com/app/php
or http://www.ipinfodb.com/. Then you can save the results with the codeigniter session class.
If you want to use the ipinfodb.com api You can add the ip2locationlite.class.php file to your codeigniter application library folder and then create a model function to do whatever geoip logic you need for your application, such as:
function geolocate()
{
$ipinfodb = new ipinfodb;
$ipinfodb->setKey('API KEY');
//Get errors and locations
$locations = $ipinfodb->getGeoLocation($this->input->ip_address());
$errors = $ipinfodb->getError();
//Set geolocation cookie
if(empty($errors))
{
foreach ($locations as $field => $val):
if($field === 'CountryCode')
{
$place = $val;
}
endforeach;
}
return $place;
}
For easier use CI have updated this so you can just use
$this->load->helper('language');
and to translate text
lang('language line');
and if you want to warp it inside label then use optional parameter
lang('language line', 'element id');
This will output
// becomes <label for="form_item_id">language_key</label>
For good reading
http://ellislab.com/codeigniter/user-guide/helpers/language_helper.html
I've used Wiredesignz's MY_Language class with great success.
I've just published it on github, as I can't seem to find a trace of it anywhere.
https://github.com/meigwilym/CI_Language
My only changes are to rename the class to CI_Lang, in accordance with the new v2 changes.
When managing the actual files, things can get out of sync pretty easily unless you're really vigilant. So we've launched a (beta) free service called String which allows you to keep track of your language files easily, and collaborate with translators.
You can either import existing language files (in PHP array, PHP Define, ini, po or .strings formats) or create your own sections from scratch and add content directly through the system.
String is totally free so please check it out and tell us what you think.
It's actually built on Codeigniter too! Check out the beta at http://mygengo.com/string
Follow this https://github.com/EllisLab/CodeIgniter/wiki/CodeIgniter-2.1-internationalization-i18n
its simple and clear, also check out the document # http://ellislab.com/codeigniter/user-guide/libraries/language.html
its way simpler than
I am using such code in config.php:
$lang = 'ru'; // this language will be used if there is no any lang information from useragent (for example, from command line, wget, etc...
if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2);
$tmp_value = $_COOKIE['language'];
if (!empty($tmp_value)) $lang = $tmp_value;
switch ($lang)
{
case 'ru':
$config['language'] = 'russian';
setlocale(LC_ALL,'ru_RU.UTF-8');
break;
case 'uk':
$config['language'] = 'ukrainian';
setlocale(LC_ALL,'uk_UA.UTF-8');
break;
case 'foo':
$config['language'] = 'foo';
setlocale(LC_ALL,'foo_FOO.UTF-8');
break;
default:
$config['language'] = 'english';
setlocale(LC_ALL,'en_US.UTF-8');
break;
}
.... and then i'm using usualy internal mechanizm of CI
o, almost forget! in views i using buttons, which seting cookie 'language' with language, prefered by user.
So, first this code try to detect "preffered language" setted in user`s useragent (browser). Then code try to read cookie 'language'. And finaly - switch sets language for CI-application
you can make a function like this
function translateTo($language, $word) {
define('defaultLang','english');
if (isset($lang[$language][$word]) == FALSE)
return $lang[$language][$word];
else
return $lang[defaultLang][$word];
}
Friend, don't worry, if you have any application installed built in codeigniter and you wanna add some language pack just follow these steps:
1. Add language files in folder application/language/arabic (i add arabic lang in sma2 built in ci)
2. Go to the file named setting.php in application/modules/settings/views/setting.php. Here you find the array
<?php /*
$lang = array (
'english' => 'English',
'arabic' => 'Arabic', // i add this here
'spanish' => 'EspaƱol'
Now save and run the application. It's worked fine.

How to export Rich Text fields as HTML from Notes with LotusScript?

I'm working on a data migration task, where I have to export a somewhat large Lotus Notes application into a blogging platform. My first task was to export the articles from Lotus Notes into CSV files.
I created a Agent in LotusScript to export the data into CSV files. I use a modified version of this IBM DeveloperWorks forum post. And it basically does the job. But the contents of the Rich Text field is stripped of any formatting. And this is not what I want, I want the Rich Text field rendered as HTML.
The documentation for the GetItemValue method explicitly states that the text is rendered into plain text. So I began to research for something that would retrieve the HTML. I found the NotesMIMEEntity class and some sample code in the IBM article How To Access HTML in a Rich Text Field Using LotusScript.
But for the technique described in the above article to work, the Rich Text field need to have the property "Store Contents as HTML and MIME". And this is not the case with my Lotus Notes database. I tried to set the property on the fields in question, but it didn't do the trick.
Is it possible to use the NotesMIMEEntity and set the "Store Contents as HTML and MIME" property after the content has been added, to export the field rendered as HTML?
Or what are my options for exporting the Notes database Rich Text fields as HTML?
Bonus information: I'm using IBM Lotus Domino Designer version 8.5
There is this fairly unknown command that does exactly what you want: retrieve the URL using the command OpenField.
Example that converts only the Body-field:
http://SERVER/your%5Fdatabase%5Fpath.nsf/NEW%5FVIEW/docid/Body?OpenField
Here is how I did it, using the OpenField command, see D.Bugger's post above
Function GetHtmlFromField(doc As NotesDocument, fieldname As String) As String
Dim obj
Set obj = CreateObject("Microsoft.XMLHTTP")
obj.open "GET", "http://www.mydomain.dk/database.nsf/0/" + doc.Universalid + "/" + fieldname + "?openfield&charset=utf-8", False, "", ""
obj.send("")
Dim html As String
html = Trim$(obj.responseText)
GetHtmlFromField = html
End Function
I'd suggest looking at Midas' Rich Text LSX (http://www.geniisoft.com/showcase.nsf/MidasLSX)
I haven't used the personally, but I remember them from years ago being the best option for working with Rich Text. I'd bet it saves you a lot of headaches.
As for the NotesMIMEEntity class, I don't believe there is a way to convert RichText to MIME, only MIME to RichText (or retain the MIME within the document for emailing purposes).
If you upgrade to Notes Domino 8.5.1 then you can use the new ConvertToMIME method of the NotesDocument class. See the docs. This should do what you want.
Alternativly the easiest way to get the Domino server to render the RichText will be to actually retrieve it via a url call. Set up a simple form that just has the RichText field and then use your favourite HTTP api to pull in the page. It should then be pretty straight forward to pull out the body.
Keep it simple.
Change the BODY field to Store contents as HTML and MIME
Open the doc in editmode.
Save.
Close.
You can now use the NotesMIMEEntity to get what you need from script.
You can use the NotesDXLExporter class to export the Rich Text and use an XSLT to transform the output to what you need.
I know you mentioned using LotusScript, but if you don't mind writing a small Java agent (in the Notes client), this can be done fairly easily - and there is no need to modify the existing form design.
The basic idea is to have your Java code open a particular document through a localhost http request (which is simple in Java) and to have your code capture that html output and save it back to that document. You basically allow the Domino rendering engine to do the heavy lifting.
You would want do this:
Create a form which contains only the rich-text field you want to convert, and with Content Type of HTML
Create a view with a selection formula for all of the documents you want to convert, and with a form formula which computes to the new form
Create the Java agent which just walks your view, and for each document gets its docid, opens a URL in the form http://SERVER/your_database_path.nsf/NEW_VIEW/docid?openDocument, grabs the http response and saves it.
I put up some sample code in a similar SO post here:
How to convert text and rich text fields in a document to html using lotusscript?
Works in Domino 10 (have not tested with 9)
HTMLStrings$ = NotesRichTextItem .Converttohtml([options] ) As String
See documentation :
https://help.hcltechsw.com/dom_designer/10.0.1/basic/H_CONVERTOHTML_METHOD_NOTESRICHTEXTITEM.html
UPDATE (2022)
HCL no longer support this method since version 11. The documentation does not include any info about the method.
I have made some tests and it still works in v12 but HCL recommended to not use it.
Casper's recommendation above works well, but make sure the ACL is such to allow Anonymous Access otherwise your HTML will be the HTML from your login form
If you do not need to get the Richtext from the items specifically, you can use ?OpenDocument, which is documented (at least) here: https://www.ibm.com/developerworks/lotus/library/ls-Domino_URL_cheat_sheet/
https://www.ibm.com/support/knowledgecenter/SSVRGU_9.0.1/com.ibm.designer.domino.main.doc/H_ABOUT_URL_COMMANDS_FOR_OPENING_DOCUMENTS_BY_KEY.html
OpenDocument also allows you to expand sections (I am unsure if OpenField does)
Syntax is:
http://Host/Database/View/DocumentUniversalID?OpenDocument
But be sure to include the charset parameter as well - Japanese documents were unreadable without specifying utf-8 as the charset.
Here is the method I use that takes a NotesDocument and returns the HTML for the doc as a string.
private string ConvertDocumentToHml(Domino.NotesDocument doc, string sectionList = null)
{
var server = doc.ParentDatabase.Server.Split('/')[0];
var dbPath = doc.ParentDatabase.FilePath;
string viewName = "0";
string documentId = doc.UniversalID.ToUpper();
var ub = new UriBuilder();
ub.Host = server;
ub.Path = dbPath.Replace("\\", "/") + "/" + viewName + "/" + documentId;
if (string.IsNullOrEmpty(sectionList))
{
ub.Query = "OpenDocument&charset=utf-8";
}
else
{
ub.Query = "OpenDocument&charset=utf-8&ExpandSection=" + sectionList;
}
var url = ub.ToString();
var req = HttpWebRequest.CreateHttp(url);
try
{
var resp = req.GetResponse();
string respText = null;
using (var sr = new StreamReader(resp.GetResponseStream()))
{
respText = sr.ReadToEnd();
}
return respText;
}
catch (WebException ex)
{
return "";
}
}

Do you expect query string parameter names to be case sensitive?

Silverlight is case sensitive for query string parameters so the following code would return false with "callid=5"
string callId;
if (System.Windows.Browser.HtmlPage.Document.QueryString.TryGetValue("callId", out callId))
{
....
}
Microsoft defends the decision by citing the www.w3.org spec, but I think it leads to a less friendly experience for people trying to link to you, or give a URL over the phone.
Looks like Stackoverflow is case insensitive:
https://stackoverflow.com/search?q=silverlight+bug
https://stackoverflow.com/search?Q=silverlight+bug
I think you should focus on your naming conventions rather than the implementations of standards, making sure to avoid similar field names and mixed case. For example, you can use a convention of words that over the phone can be read out stating "all lowercase" or "all uppercase".
I did this. Don't know if it helps.
var keyName = "";
if (!string.IsNullOrEmpty(keyName = someDictionary.SomeKeys.FirstOrDefault(k => k.ToLowerInvariant() == "size")))
{
var someValue = someDictionary[keyName];
}
Yes, I'm used to it being case sensitive, and therefore have been programming to it for a long time. I know of some people that have implemented methods to do intermediate parsing to convert them all to lowercase, or other things server side, and it really depends on what you are working with specifically.
As for usability, yes it is harder to read. BUT, at the same time a URL over the phone that has a querystring is not easy to give out anyway.
This workaround will not use the power of dictionaries because it will iterate through all keys, but it is likely to be a sufficient work-around for most scenarios.
var keyName = HtmlPage.Document.QueryString.Keys.SingleOrDefault(key => key.Equals("callid", StringComparison.OrdinalIgnoreCase));
string callid;
HtmlPage.Document.QueryString.TryGetValue(keyName, out callid)
You could also transform the whole QueryString dictionary to a new dictionary with a case insensitive comparer if you are having many dictionary lookups.
var insensitiveQueryString = HtmlPage.Document.QueryString.ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);

Resources