Getting started with Globalization: Part 2: Internationalization and Localization in an Express app

This is part two of a 3 part series dedicated to getting started with G11N in your node.js application. Make sure you go through part 1 of this series in case you want an overview about the terms Globalization (G11N), Internationalization(I18N) and Localization(L10N). In this part, we will look at adding localized content to an Express app. Without any further adieu, lets create a folder to create a simple Express app,

Keep hitting enter, accepting all the defaults till the initialization process exits. Now, let’s install a few things that we will use, namely

  • Express (for the application itself)
  • Makara (to enable I18N – if you recollect from Part 1 of this series, I18N is the process of making your software ‘ready’ to accept localized content)
  • Dust Makara helpers (We will use dust for the sake of this walkthrough)

File Structure

At this point, our little project should already have the package.json file along with the node_modules folder. Additionally, create a bunch of files and folders such that the file structure resembles the following:

Now we have all that we need to get started with G11N in a Node.js Express app! Through the file structure, you can guess that the locales folder is going to be made up of folders for the countries that we support. The general convention is to use the 2 letter (uppercase) code for each country. The country folder will have the folders for the languages we will support for (specific to that country). The languages are specified by their 2 letter (lowercase) codes. In this example, we can see that the country is the United States and the language is English. The language(en) and the country(US) put together is called the locale (en-US). We will add more countries and languages as we provide support for them.

Sample app

Open the index.js file in your code editor and initialize a Express app:

Nothing fancy here, just an extremely minimal Express app that listens to requests on port 3000 and responds to the root path with the content in a dust template called home. One thing to note is the fallback property we set while wiring up makara for the app. We are setting the fallback locale to be en-US. Needless to say, you can set it to whichever locale that your website would cater to.

Properties file

Before we test out the index.js, we need to add something to the home.dust and the home.properties files so that something shows up when we run index.js. Open locales/US/en/home.properties file created earlier in the file structure step and add the following line:

A properties file is just a text file with property names and values. You can add provision to pass dynamic data too, but we will look into that shortly. For now, open up public/templates/home.dust and simply put a H1 tag and add a dust helper to show content from home.properties.

The pre tag within the curly braces reads like this,

I want to replace these curly braces with the value of a key called “greeting” from a .properties file that has the same name as this dust file.

Now we can take a look at what we’ve got so far, run the following in the terminal (in the folder where have our project)

This will start the server. Open a new tab and go to http://localhost:3000. You should be greeted with “Hello World!”. Now create a new folder inside locales/US/ and call it ‘es’. That’s right, we are now going to provide support for the Spanish language for the US audience in our website!

Once you create the folder locales/US/es/, add a properties file to it with the same name as before: home.properties but this time add the content for the Spanish language:

At this point our simple app falls back to en-US, we need to make it cater to es-US (Spanish locale for the US). Update index.js such that we explicitly set the locale to es-US in the app’s get route

Once you add that, the get route should look like this:

Restart the app

Reload the page in the browser and we should now see “Hola Mundo!”. Not bad, eh? You might wonder how do I set the locales dynamically? Well, each website or the company that owns the website has their own way of implementing this. Either you can set the locale in a cookie and read it before serving the page, or you could get it from the Accept-Language request header – obtained from req.header(‘Accept-Language’) – and parse it to get the locale or you could simply ask the user to select it from a dropdown. Whichever method you use, all you have to do is to set it before you actually render the page using


Categories: How To, Javascript, Node.js, Useful | 3 comments

Getting started with Globalization: Part 1: Introduction to G11N, I18N & L10N

Globalization is what happens when we are not limited by geographical boundaries.

When you create a website or an application (desktop/web/mobile), you want everyone to use it. Globalization(G11N) is a step you take when you get serious about this goal. It is a technique to help a whole lot of people to come to your website. Most people would know this by now but,

G11N is a numeronym.

It s a number based acronym for writing long words such as Globalization. Take the first letter and the last letter of a long word, count the number of letters in between and put it all together. In other words, Globalization is a word made up of 11 letters in between ‘G’ and ‘N’, hence G11N. Numeronyms are used by people who are experts in these fields as it saves them a whole lot of time in actually typing out, or gulp… writing those words in their entirety.

Globalization (G11N) is made up of Localization (L10N) and Internationalization (I18N).

Localization

L10N is the process of adapting the content on your website to various geographies and to translate it accordingly. When I say ‘adapting’ I mean the process where you first adapt the content in English itself. For example, let’s say the originating country for the application is the United States and the initial language set is US English, then in case of India, the content will first be adapted as per British English as that is the colloquial used in India. Only after ‘adapting’ the English itself, comes the process of actually translating the content in Hindi (which is the national language of India).

Internationalization

I18N is the process of preparing your software to be able to take these language related changes along with dynamic data. Here dynamic data does not imply data simply coming in from the database, it means data such as currencies, dates, addresses, phone numbers and other such things which are depicted differently from country to country. For example, a date in the US is written with the month followed by the day when written numerical. For example, 12/20/1974 for December 20, 1974. The same is depicted as 20/12/1974 in India, where the date precedes the month. The $ sign is used for depicting currency in the US but ₹ is used in India as the currency symbol. These differences are known as dynamic data when it comes to L10N. Making provision to accept these differences in your software is I18N.

At PayPal we have a world class G11N team that helps us ramp up to over 200 countries. We also have the most excellent KrakenJS framework for all our node applications. KrakenJS is a open source, widely used Node.js framework built on top of Express. The beauty of KrakenJS is, the Makara module is baked right into the framework. This module wires up the application with I18N support without you having to write a single line of code. Needless to say, Makara can be used independently as well.

In the subsequent parts of this article, we’ll look at implementing Globalization in a Express app followed by an implementation using the KrakenJS framework. Stay tuned!


Categories: How To, Javascript, Node.js, Tips, Useful | Tags: , , , , , , , , , | 1 comment

Effective JavaScript & How to behave when you sit next to Douglas Crockford

Before I go into the most unique experience I had with Douglas Crockford, I want to put down the real essence of this post, which is the notes I took in the Effective JavaScript session that I attended. The most important thing I learnt in the training is the first line in my notes (the rest is secondary and you can actually skip it and move on to other things if you like)

All work you do must stem from Service to Humanity

And,
  • Programming Style is important. But style is not about personal expression via code.
  • Write code that is easy to read, share, improve and expand upon.
  • Look at programs as literary work
  • We are paid to write programs that work well and are free of errors
  • Read Thinking fast & slow by Daniel Kahneman
  • There is no way of testing a program to check if it s 100% perfect, hence it’s all about perfection for programmers
  • When people argue about something technical, they speak from an inner emotional space which may not be necessarily logical
  • If someone says, “That hardly happens“, they actually mean, “It happens!
  • The origin of word processing: Authors had no control over presentation
  • CSS has lead to classitis and iditis
  • In JavaScript, if you take this out, what you are left with is a functional programming language, which is great
  • Use TitleCase only for constructor functions
  • An activation record is created every time a variable is needed
  • Closures are great coz they don’t keep variables in the stack, instead they keep it in the heap
  • Avoid globals. In this statement, b is a global: var a = b = 0;
  • Doug feels, Ken Thompson is the most amazing programmer ever. He created B, C, Regular Expressions, Unix, UTF-8 etc.
  • Buffer overruns come from using ++. Hence use += instead.
  • The Mosaic browser was instrumental in popularizing the world wide web. It was graphical, had support for multiple internet protocols, it displayed images inline (instead of separate windows)
  • Objects in JavaScript work by the principle of differential inheritance where an object maintains a reference to its prototype from a table of properties. It creates a new property in the table only if it is different than its reference
  • The splice command is slow
  • 0.1 + 0.2 === 0.3 // this returns false as it s really difficult for the computer to represent certain floating point numbers. In this example, adding 0.1 and 0.2 actually results in 0.30000000000000004 which is not 0.3
  • Choose to loop over Object.keys instead of for (var i in obj)
  • Choose function expression over function statement
  • JavaScript has function scope (not block scope) but block scope will be added in ES6
  • Binding of this happens late (at invocation point) This is done to preserve memory
  • If you do something like arr.push(fn), fn has access to arr as this (as arr is to the left of the period) This can be a security loophole
  • Look up and read about Auguste Kerckhoff and his work
  • Look up waterken which makes web services using the Actor model
  • Learn about the Actor model
  • The law of turns must be respected, hence avoid using the sync counterparts of the async functions of node.
  • Douglas Crockford has created a new number type DEC64 which can represent decimal fractions with 16 decimal places which makes it well suited to apps that are concerned with money

OK, so here is the unique experience.

Firstly it was a 3 day event. On all 3 days, Douglas came in way before time and stood behind the podium and he looked like Gandalf was checking his email. At the beginning of the training on day 2, he encountered some issues with his tablet and needed to replace it with his laptop which was at his residence. He looked around and asked most politely if anybody had a car and was willing to take him home to get his laptop and get it back just in time for the training. Now this is enough to prompt all the JavaScript programmers in the room to literally go into a frenzy. I mean this was not about 2 spaces in a tab OR 4… it was not about soft tabs OR hard, it was not about === OR == and it was certainly not about Angular OR React! This was about getting the opportunity to take Douglas Crockford to ‘his’ house and getting his laptop back in ‘your’ car.

Anyway, so I was obviously a lot more polite and positive. I had a bouncier bounce to my step while escorting him to my car. A million questions were racing through my mind. JavaScript questions, software questions… do you use Sublime or Atom or are you more of a emacs dude? Vim maybe? Do you think the framework that I am good at is the best framework of them all? Node.js or io.js? Should I start using Harmony right away or should I wait for this year to end? Is there a God? No kidding!

When we started toward his house I noticed there was some traffic on the freeway! Never was I so happy to be stuck in traffic!

So I started thinking on the lines of which question to ask first. As some time went by, the questions started melting away or falling apart. I told myself, this guy must’ve been asked all these questions so many times and in so many different ways by so many different people. No amount of rephrasing is going to add any novel juice to any of them. Besides how does it matter? All these  preferences and opinions that developers have. Why should one be better than the other. And even if it is, how much sense does it make to apply any of it without fully understanding it and hence making it your own personal opinion. At the end of the day it’s all about how genuine you are as a human being.

I looked at him. Sitting there. Staring out of the window. I said to myself, ‘Fuck it!‘ I m not asking anything. He s probably going to be asked a whole lot of questions by the ‘JavaScript’ developers waiting back at the training anyway. One less developer may not make a massive difference but these 15 – 20 minutes can be made better for him instead of me. I just drove quietly. We went to his house. He picked his laptop and we drove back. No fanfare, no guru-disciple kinda drama. Nothing. Just a quiet drive. I cannot speak for him, but I had the most amazing time of my computing life for those 3 days.

There are some smart people out there who like to challenge Douglas Crockford’s opinions about JavaScript. In fact they use it as a tool to pronounce their smartness. They cannot create a data exchange format that the world will adopt unanimously. Nor can they create a number type that can aid in applications dealing with finances. And of course they cannot possibly have the first hand historic context that he has. But they continue to think their understanding is way better than his. And I m not going to refute that. I m just gonna save up my questions for them :)


Categories: Javascript, Tips | 1 comment

Understanding JavaScript closures through the context of Indian classical music and modern art

One good thing about music, when it hits you, you feel no pain.
- Bob Marley

As of EcmaScript 5, closures, along with functions, are at the heart of creating modules in JavaScript. While understanding closures can take some time initially, the effort invested yields great results on the dawn of understanding of what closures are. A “closure” is an expression (typically a function) that returns an object or function along with the environment it was created in, such that it has access to the variables and identifiers from the environment, even after that environment or the function that surrounds (or closes) it, has returned.

In Indian classical music, there is a concept called Raaga. Raaga is like an advanced scale or mode with melody. Using a scale as the means to define a Raaga is like using tap water to explain the concept of rain. But there is really no simpler way to explain this to an audience which comprises of both Indian as well non Indian ‘closure’.

There are many different Raagas. In many cases, a Raaga is explored in a concert by a vocal artist or instrumentalist with an attempt to invoke in the listeners, the original emotion that was responsible for the birth of the Raaga. To give the listeners the same feeling without giving them the circumstances that caused that feeling.

JavaScript closures and Indian classical music

Awareness of the feeling thru the rendition of a Raaga is the transfer of state(emotion) and data(notes) to the listener. Once the listener is one with the feeling that the artist is trying to express, a perfect closure scenario takes place. The feeling the listener gets is the object returned and the rendition itself is the closure. The same analogy can be easily applied to the other art forms. An artist’s painting is the closure and the disturbance or joy derived by soaking oneself in the artwork is the object returned. No wonder then, we feel nothing sometimes when we look at some of the modern art. That happens when the closure fails to return an object along with it’s environment.

To sum it up, closures give out a function or object that remembers the environment it was created in. The general approach to understanding closures is to get as many different perspectives about it till one of ‘em clicks for you. I hope this abstract comparison to art  and music for explaining closures acts as yet another perspective about closures. Happy coding!


Categories: Javascript | Tags: , | Leave a comment

Simple pattern matching with Javascript String.replace

The first rule of any technology used in a business is that automation applied to an efficient operation will magnify the efficiency. The second is that automation applied to an inefficient operation will magnify the inefficiency.
-Bill Gates

For my personal music related project (Scribbletune) I wanted to generate an array of objects from a string. Here are some examples of the input expected and the output desired in each case:

Input (String):

Output(Array of Objects):

What’s happening here is, x denotes a Note On state and one or more underscores following an x denotes the length of the note in units of 32. Each hyphen denotes an interval or a Note Off state. The first thing that came to mind was to use a for loop on the string input and then whenever x is detected, I could split the string from that x to the end of the string and run one more loop to find the occurence of the underscores and use them to compute the noteLength value.

So then it would like

This is fine and it will get the job done. But I wanted to break away from the dependency on the for loop.

Enter String.replace

The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.  The pattern can be a string or a RegExp, and the replacement can be a string or a function to be called for each match.

Basically I d need to ‘match’ occurrences of  x followed by zero or more underscores and occurrences of hyphens. Then based on those, I d just need to push the desired object to an array.

And that’s about it. The jsperf for this shows tremendous performance improvement as well as reduced number of lines of code (from 25 lines it went down to 4 lines) without sacrificing readability!


Categories: Javascript | Tags: , | Leave a comment

How to run Grunt tasks only on changed files

You can observe a lot by just watching.
-Yogi Berra

For a recent workflow improvement I was trying at work, I needed to setup a Grunt watch and uglify on a bunch of javascript files to minify them into individual minified files and then concatenate them. The number of files to be concatenated was over 50 hence uglifying the whole bunch each time a file was updated would slow down the workflow.

So the goal was to minify each file individually into its own minified version and then run a watch on the minified files directory contents and concatenate the minified files into one js file. The uglify target looked like this:

The second part of the goal was to concatenate minified files into one main.js. This needed to happen every time a file was minified. Which means I needed to run the uglify task only on the file that was changed or updated and then concatenate the minified files. Before moving on, here’s the Grunt concat task inside the watch:

A watch task on the ‘js’ directory would run the uglify task and a watch task on the ‘js-min’ directory would run the concat task. The challenge was, every time the uglify task ran, it went through all of the js files specified in it’s target and uglified them. And then the watch task on the ‘js-min’ directory would kick in and concatenate all the files in the ‘js-min’ directory. SO the required behaviour was to set the watch task for uglify to run only on the updated/changed file.

Say hello to the on watch event

Grunt watch has a ‘on’ event so that one can compile files as needed. My first hack was to use this ‘on’ event and run uglify on the changed file from this event’s handler which provides a filepath paramenter. Grunt’s core developers will not advise us to use this event method in this fashion as it deviates from the standard procedure of assigning tasks using Grunt. Hence we ll maintain the existing uglify task just the way it was defined earlier. In the watch event handler, we ll simply change our uglify task’s source parameter to the file that was updated. So instead of taking all the files defined in the src parameter, Grunt watch will only process the updated file

This will make sure that only the changed file is uglified. Once it compiles it as a minified file, we run concat on the minified files by adding another watch target in the Gruntfile.

This solution helps meet the goal I set out to achieve. Though there is an issue in this. What if we wanted to append .min.js to the end of all the files we minify? We could just add that in the uglify target object as ext: min.js. But then it will create some problems on files that have a dot (or 2) in their ‘name’ itself. For example its a common practice to name jquery plugins like this: jquery.pluginname.js

At the time of this writing, Grunt uglify will not differentiate between files with more than one dot in their name. It will use the first dot that it finds in the file name and consider the rest of the file path as an extension of the file. So let’s say we decide to append a .min.js to our uglified files, our Grunt task will convert both jquery.pluginname.js and jquery.js to jquery.min.js. This is not what we want! There is a bug filed for this and maybe the core team will do something to tackle it, but since one can pass a rename function, they may not consider tackling this right away.

A quick and dirty solution is to explicitly rename the changed files the way you want in the on watch event itself. So you’d first uncomment the ext portion in the uglify task and update the on watch task:

If you know a better way than this, then please do leave it in the comments.


Categories: How To, Javascript | Tags: , , | 1 comment

Install Apache, MySQL PHP and phpMyAdmin on Ubuntu 13.04 Raring Ringtail

When Thomas Edison worked late into the night on the electric light, he had to do it by a gas LAMP or candle. I’m sure it made the work seem that much more urgent.
-George Carlin

Ubuntu 13.04 ‘Raring Ringtail’ released yesterday and though I use Crunchbang, like any ex Ubuntu fanboy I got myself the iso, put it on a thumbdrive and installed it on a small netbook I have that was just lying around doing nothing fancy. I thought I d install the new Ubuntu on it and use it to ‘code’ while in the John or while standing in the line at Starbucks :D

So anyway, I had to setup a LAMP server:

MySQL

Apache

PHP

Restart Apache

phpMyAdmin

I don’t like to use Apache’s default http folder /var/www so I need to update the apache2.conf file:

Changing the default location will require me to make sure phpMyAdmin continues to load on http://localhost/phpMyAdmin so at the end of the same file I ll add the virtual host configuration for phpMyAdmin

Restart Apache


Categories: How To, Linux, Useful | 29 comments

Rearrange characters of a string to create all possible combinations

Governments tend not to solve problems, only rearrange them
-Ronald Reagan

How to take a word(string) and rearrange its letters to create all possible combinations? Lets say we want to use the word ‘goal’ and list out all possible words that can be made by rearranging the letters of the word ‘goal’. Take the first letter ‘g‘ and then create permutations and combinations of the balance letters ‘oal‘ and append them to ‘g‘.

g oal
ola
alo
aol
loa
lao 

Then take go and create create permutations for the balance letters ’al‘ and append them to ‘go‘.

go al
la

Then we take goa and l

goa l

This is done for each of the letters. As you can see, with each letter, the permutations will reduce for the subsequent letters. The parameters that are passed to our recursive function are a prefix that will be used to prepend (starting with an empty string) AND the balance letters of the word.

Here’s the function in JavaScript:


Categories: How To, Javascript | 1 comment

jQuery Timer Plugin

Update: This plugin has undergone an a complete overhaul and is a much robust solution than what I started in 2012. Please refer to this dedicated site for details on how to use it.

I m happy to post about my first ever jQuery plugin. This plugin will allow you to add a simple timer to a HTML element like DIV or SPAN or any other valid display element. You can style this element to show the timer in a nice way ;)

Currently this plugin has 3 self explainatory methods to interact with it:

  1. $(“#divId”).timer(“start”);  -> this will initialize the timer inside the div with id = “divId”. You can even pass in the number of seconds you’d like to start the timer at, like this, $(“#divId”).timer(“start”, 2500);
  2. $(“#divId”).timer(“pause”); -> this will pause a started timer
  3. $(“#divId”).timer(“resume”); -> and this will obviously resume a paused timer.

Make sure to include the latest jQuery file and this plugin file in your HEAD section. Click here for a demo of this plugin. Download the zipped folder (includes the plugin + demo HTML page) from GitHub. Here’s the script itself.

 


Categories: jQuery, Useful | Tags: , , | 8 comments

How to find and replace in multiple files from the terminal

You have to kiss a few frogs before you find a prince.
-Anonymous

There are times when you d like to search for a word/phrase or regular expression in a number of files together and optionally replace it with something else. If you do not use a IDE then you may need to use the terminal to do this. In a terminal, change directory(cd) to the directory where you want to ‘find and replace’ and do

grep -lr -e '<oldword>' * | xargs sed -i 's/<oldword>/<newword>/g'

This will work on a Mac as well by providing a backup file as an argument to sed after the -i parameter (Thanks to Derek R):

grep -lr -e '<oldword>' * | xargs sed -i '' 's/<oldword>/<newword>/g'

Explanation

  • grep is a command line text search utility
  • -l get the files with matches
  • -r recursiveget a list of all matched files
  • -e stands for the PATTERN to match
  • xargs will will return the matched files as arguments
  • sed is th Unix stream editor utility
  • -i edit files in place

Reference (not man pages)


Categories: How To | Tags: , | 3 comments

← Older posts