Using Regular Expressions to correct mistagged MP3

Two months have passed since I last posted something here. These were 2 busy months in my life. Hooray, I bought a brand new car and got my driver license, not necessarily in this order.

This post is about something I had planned to write sometime ago… the two screenshots shown here I got maybe 3 months ago. :D So let’s get to it.

As a big and eclectic fan of music that I’m, every now and then I see mistagged MP3 files like the ones with title tags that contain both the artist name and the song name. The following picture shows what I mean:

Mistagged MP3 files (Title field has both the Artist and Song names) Picture 1 - Mistagged MP3 files (Title field has both the Artist and Song names)

Here’s where Mp3tag comes to the rescue. As you see in Picture 1, I’m using the dialog “Replace with regular expression”. Read my previous post about this great piece of software called Mp3tag to see how to get to this dialog. It has 3 fields that you must fill to make some magic happen allowing you to correct those wrongly tagged/mistagged MP3 titles all at once. Ha! You won’t lose your precious time correcting MP3 by MP3. I know that this is boring and that’s why I desperately searched for a solution. I know that if you’re reading this, you’re probably in the same situation and you just found a solution. :)

I’ve chosen the Field TITLE since it’s the problematic field in this particular case. Now the most important part, the so called Regex or Regular expression: (.*) - (.*). This thing means that we’re gonna separate the MP3 Title field in two parts. One part will have everything (.*) before the hyphen - and the other part will contain everything after the hyphen (.*).

Example:

Dru Hill - Away (Prod. by B.Cox) (Full + NoShout) (2010)

The regex (.*) - (.*) will separate the MP3 title above in two parts…

$1 = Dru Hill
$2 = Away (Prod. by B.Cox) (Full + NoShout) (2010)

The Replace matches with field has the value $2 because in this case I want to replace/substitute the MP3 Title with only the Song/Track name (the 2nd part/match of the regex above). If instead I wanted to keep the Artist name in the Title tag (D'oh!, not something I’d want to do), I’d write $1 in this field.

Now, take a look at Picture 2. When you click OK, this is the end result/magic you get. Nice and correctly titled/tagged MP3 files. The way I wanted them to be.

Correctly tagged MP3 filesPicture 2 - Correctly tagged MP3 files

To make things last forever, do not forget to click the Save button present in Mp3tag’s toolbar or in the Save tag option present in the File menu. I like to press Ctrl+S as a shortcut.

If you want to learn the basics about regular expressions to use with Mp3tag, check this out: http://help.mp3tag.de/options_format.html#regexp

As you see, using regexes (one of the most powerful features of computers) you can make any kind of change to your MP3 tags like for example removing that (2010) present in each MP3 Title field above. That 2010 should be in its proper MP3 tag, namely the Year tag. Don’t ya think?

Hope this simple process helps someone out there keep an organized MP3 library as I do like to keep mine.

Note
Mp3tag is a Windows only application as is Windows Live Writer that I use to write these blog posts. I use/run it through Parallels Desktop on my Mac mini. Read this post to get more info about how to run Windows side by side with your Mac OS.

Showcase StackOverflow flair/badge in LinkedIn profile

Today I just thought about showcasing/displaying my StackOverflow flair/badge in my LinkedIn profile. LinkedIn is a good place to show it because it’s a perfect match between your reputation as a software guy and possible good opportunities.

Since LinkedIn doesn’t allow one to put html code snippets in profile fields this showed to be a difficult task at first. Nothing that a little bit more thinking couldn’t solve: Google presentation application to the rescue.

Well, basically what you have to do is create a simple online Google Docs presentation. You could also create an Office PowerPoint presentation and upload it. For sure it’ll give you a lot more customization options. I’ve chosen Google presentation because it suffices my needs for the moment.

Inside that presentation you’ll put an image object that points to your StackOverflow flair image URL. Mine is this one:

http://stackoverflow.com/users/flair/114029.png?theme=dark

Just substitute my StackOverflow user id highlighted above by yours to get your flair.

To change the theme, add ?theme=clean or ?theme=dark or ?theme=hotdog to the end of the image URL.

This URL will render a picture that represents your flair this way:

StackOverflow flair/badge

The bad point in this approach is that as your reputation grows your presentation won’t show your updated flair. You’ll have to open the presentation and re-add the flair image to reflect your current SO reputation.

Google should give us a way to have dynamic content inside a presentation (its spreadsheet service allows this kind of content). This is something that is really missing in presentations. Hey Google, can you hear me?

To give a more personal touch to your presentation you can also put a background image in your slide. I selected a Lamborghini Gallardo because it’s my main car in GT 5 today. So it represents my mood right now. One day I’ll have this car. Just kidding. :)

This is the final result:

This post provides an answer to this Meta StackOverlfow question:

IS it possible to show SO flair on LinkedIn?

Software to add Lyrics to MP3 files ID3 metadata

Take a look at the MP3 series. Probably you’ll find something interesting.

If you're like me, you also like to take a look at the lyrics of music that is currently playing in your computer or mobile device as the iPhone. I do it to learn a bit more of English since its not my main language and of course because I also want to sing along correctly. :)

The iPhone for example allows you to read the lyrics of the current song if the lyrics are present in the MP3 ID3 metadata container. This is pretty cool. If you already have lyrics embedded in your MP3 files you can see them while in a bus trip, waiting for a service, etc.

Every MP3 has a specific field (also know as frame) in its metadata to store lyrics information. It’s just a matter of filling this field with the correct lyrics. This is a hard work to do manually because you have to search for the lyrics and then copy/paste it in the right field. This sounds like a great thing to be done by software instead. Again, that’s what computers are for… save us time.

In iTunes (the media player/library software I use) for example, one would right-click a music file and then select the Get Info context menu option. Then you’d select the Lyrics tab and paste the lyrics in the white huge field making sure to click OK as seen in Figure 1 below:

Adding lyrics to an iTunes music file through the Lyrics tab
Figure 1 - Adding lyrics to an iTunes music file through the Lyrics tab

Some time ago I asked a question at SuperUser site: Software to add Lyrics to MP3 files ID3 metadata. It seems that there are a lot of people (3,356 to be precise as the time of this post) out there looking to accomplish what this post tries to clarify.

When I asked the question I was using Windows and I got good answers.

I also discovered other software by myself as MiniLyrics for Windows at that time. If you’re interested in MiniLyrics, here goes a small tutorial to save the lyrics to MP3 metadata!

MiniLyrics
Right click MiniLyrics icon in the system tray, choose Preferences and then select the Lyrics icon. Under the Save downloaded lyrics in: - select Save lyrics in mp3 file.

Other great feature MiniLyrics has is that while the music is playing the lyrics can be shown on your screen according to what is being sung, that is, the lyrics flows in your screen according to the music timing. Fantastic job from crintsoft people... :)

Besides saving the lyrics to MP3 metadata, there are lots of features and possibilities when it comes to lyrics in MiniLyrics software.

From the official site:

    MiniLyrics Display lyrics for your favorite music!

        * Lyrics plugin software for iTunes, Windows Media Player, MediaMonkey, Winamp, etc. You do not need to change the way you enjoy music.
        * Display scrolling lyrics, you can follow along with the artist and catch every word.
        * Automatically search and download lyrics.
        * Huge lyrics database, and it is expanding everyday.
        * Free Trial version that never expires.

Lyricator
Lyricator as suggested by merv is a fantastic/great/cool piece of software to go with MediaMonkey but it is having some problems currently as you can find in this thread.

I had to resort to other service while Lyricator is being repaired. I found other free software that does the job, but only on a Mac computer (that’s OK because I’ve switched to the Mac world). It's name is Get Lyrical.

Get Lyrical

Get Lyrical doing its job in the background
Figure 2 - Get Lyrical doing its job in the background

    Get Lyrical auto-magically add lyrics to songs in iTunes!

You can choose either a selection of tracks, or the current track. Or turn on "Active Tagging" to get lyrics for songs as you play them.

    You can also browse and edit the lyrics of your iTunes tracks right from Get Lyrical.

I highlighted in yellow above a powerful feature of Get Lyrical. You can even add lyrics to a selection of tracks at once. This is a batch processing feature really welcome when you want to add lyrics to an artist’s complete discography for example.

I’ve been using Get Lyrical for some time now and it is really competent in the job. I highly recommend it.

Installing PHP on Mac OS X Snow Leopard 10.6.5

Motivated by this question at StackOverflow: RegExp PHP get text between multiple span tags, I decided to help.

Recently I got a Mac mini. I still hadn’t played with PHP on Mac and to debug my answer to that question I needed a way to test the code. So I thought: why not also give PHP a try on Mac OS since its my main OS today? Oh, good idea, go learn something new… :D

The first thing I did obviously was recurring to Google and searching for something that could help me get there.

I hit a pretty good tutorial to enable PHP on Mac at About.com written by Angela Bradley that gets to the point: How to Install PHP on a Mac. Along the way I had to solve only one minor thing described in the caveat section at the end of this post.

You see that the title of this post has the word installing (well I thought I had to install it – that was my first reaction), but in fact it could be the word enabling because PHP is an integral part of Mac OS X Snow Leopard and we just need to enable it as you’ll see soon.

Here we go. Follow these steps:

1 - Enabling the Web Server
PHP works hand in hand with a webserver. Mac OS already comes with Apache web server and so we just need to enable it. To do so, open System Preferences in the Dock. Then click the 'Sharing' icon in the Internet & Network section. Check the ‘Web Sharing’ box.

Web Sharing option under the Sharing configuration in System Preferences
Figure 1 - Web Sharing option under the Sharing configuration in System Preferences

Now type this address in your browser: http://localhost/. You should get a message that reads: It works!

2 - Enabling PHP
PHP also comes bundled in Mac OS, but it’s disabled by default. To enable it we need to edit a hidden system file located in this path: /private/etc/apache2/httpd.conf.

I used BBEdit text editor to edit such a file (note that I marked the box Show hidden items in the screenshot below):

Editing a hidden file with BBEdit
Figure 2 - Editing the hidden system file httpd.conf with BBEdit

Now within that file search for:

libexec/apache2/libphp5.so

Delete the character # in the start of the line so that that entire line should now read:

LoadModule php5_module          libexec/apache2/libphp5.so

Save the file.

3 - Testing the installation
There’s nothing better to test the PHP installation than using its own information. To accomplish this, write a one liner simple .php file named test.php with this content:

<?php phpinfo() ?>

Place this file inside your personal website folder. Mine is located in this path:

/Users/leniel/Sites/test.php

Now let’s test this page by typing its address in the browser:

http://192.168.1.103/~leniel/test.php

As you see, the address points to my personal website as seen in Figure 1.

When you run this simple .php page you should get something like this:

Testing PHP installation with its own configuration’s information
Figure 3 - Testing PHP installation with its own configuration’s information

If your PHP installation is OK, the test page will display PHP's information. If it displays the page code, you need to restart the Apache server.

You can restart Apache by entering the following in Terminal:

sudo apachectl restart

Try to reload the page again. Everything should work.

Well done!. Now you can play with PHP on your Mac computer and write some neat codez. :)

Caveat
When I tried to restart Apache server I got the following error:

ulimit: open files: cannot modify limit: Invalid argument

I resorted to this solution: Mac OS X 10.6.5 broke my apachectl

Practical use of Right function with Google Docs

Last time I showed you the Practical use of CountIf with Google Docs Spreadsheet.

Today I’m showing a practical use of a function called Right that can help you in a lot of situations.

Consider this sample spreadsheet:

I’m using the above spreadsheet to keep track of my progress during online theoretical practice tests for my first driver’s license.

I like math so I wanted to know how many tests people have taken or how many tests have been served by the server since my last test.

The Right function is being used in the column named ‘’Tests since last’’ starting at the second practice test I’ve taken. For example, the actual formula in cell C4 is this:

C4 = right(B4, 7) - right(B3, 7)

Let’s break this thing and explain each piece:

B4 contains the URL that points to the practice test I took. In this case the URL is this:

http://www.provadetran.com.br/simulado_termino.php?simulado=4396981

As you see, there’s a number at the end of the URL. This number has 7 digits of length and is a sequential that identifies each test. This allows me to go to the test to review what I did right and what I did wrong at a later time.

Well, to answer that intriguing question I need to subtract this number from the number present in the URL just above cell B4, namely B3. Now look at the formula in cell C4 above. It does just that. The right function is giving me the last 7 characters of the URL. Last because it gets the characters from right to left. If you wanted to get the first 7 characters you’d use the left function instead.

The right function has this form: RIGHT(text, number). It defines the last character or characters in a text string. Text is the text of which the right part is to be determined. Number (optional) is the number of characters from the right part of the text.

Easy to understand, isn’t it?

Let’s do the math making the substitution of values:

C4 = right(B4, 7) - right(B3, 7)
C4 = 4396981      - 4396181
C4 = 800

Now I know that from the time I took the first practice test on 11/25 to the second test on the same day but at a different time 800 tests have been served. This is more of a curiosity metric than anything. I like math anyways. :o)

This was a simple and practical use of the right function that came in handy in this situation.

Using jQuery to disable/enable and check/uncheck Radio Buttons on Date selected

Motivated by this question on StackOverflow - Disable radio button depending on date, I decided to help and here I’m with another code snippet post.

This time I show you how to use jQuery UI and its Datepicker control to control a set of radio buttons (only 2 in this post to make things easier) that have their state (enabled/disabled) changed depending on the date selected by the user.

Here’s the code:


<!DOCTYPE html>
<html>
<head>

   
<meta charset="UTF-8" />
    
   
<title>jQuery UI - Datepicker & Radio Buttons</title>

   
<!-- Linking to jQuery stylesheets and libraries -->
   
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/themes/base/jquery-ui.css" type="text/css" media="all" />

   
<link rel="stylesheet" href="http://static.jquery.com/ui/css/demo-docs-theme/ui.theme.css" type="text/css" media="all" />
   
   
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>

   
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js" type="text/javascript"></script>
   
   
<script src="http://jquery-ui.googlecode.com/svn/tags/latest/external/jquery.bgiframe-2.1.2.js" type="text/javascript"></script>

   
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/i18n/jquery-ui-i18n.min.js" type="text/javascript"></script>

</head>

<body>

   
<script>

   
$(function()
    {
       
$("#datepicker").datepicker
        ({          
           
// Event raised everytime a date is selected in the datepicker
            onSelect: function(date)
            {
               
// Self explanatory :) - used to get today's date
                var today = new Date();

               
// Business logic to change radio buttons' state                 if($("#datepicker").datepicker("getDate") > today)
                {
                   
$("#radioButton1").attr('disabled', true);
                   
$("#radioButton2").attr('disabled', false); 
                }
               
else
                {
                   
$("#radioButton1").attr('disabled', false);
                   
$("#radioButton2").attr('disabled', true); 
                }
            }
        });

       
// Just setting the default localization for the datepicker
        $.datepicker.setDefaults($.datepicker.regional['']); 
    });
    
   
</script>

   
<p>Date: <input id="datepicker" type="text"></p>

   
<input id="radioButton1" type="radio" value="myValue1" name="radioButton1"/>Radio button 1<br/>
   
<input id="radioButton2" type="radio" value="myValue2" name="radioButton2"/>Radio button 2

</body>

</html>

If you wanted to control the state (checked/unchecked) you’d have to make a small change in the code as follows:


// Business logic to change radio buttons' state                 if($("#datepicker").datepicker("getDate") > today)

   
$("#radioButton1").attr('checked', true); 
   
$("#radioButton2").attr('checked', false);  

else 

   
$("#radioButton1").attr('checked', false); 
   
$("#radioButton2").attr('checked', true);  
}

When you open the page for the first time you get this screen:

Page when viewed for the first time (both radio buttons are enabled)
Figure 1 - Page when viewed for the first time (both radio buttons are enabled)

If you pick a date that is greater than today’s date, Radio button 1 is disabled (turns to gray) and Radio button 2 is enabled according to the logic implemented.

Radio button 1 is disabled (turns to gray) and Radio button 2 is enabled
Figure 2 - Radio button 1 is disabled (turns to gray) and Radio button 2 is enabled

Otherwise, Radio button 2 is disabled and Radio button 1 is enabled:

Radio button 2 is disabled and Radio button 1 is enabled
Figure 3 - Radio button 2 is disabled and Radio button 1 is enabled

Hope you make good use of it.

Playing with Google Translator Toolkit API

Just out of curiosity I wanted to know how many words I have already translated from English to Portuguese in respect to Translating ScottGu's Blog to Portuguese.

This appeared to be a great chance to play with Google Translator Toolkit (GTT) API since I use GTT to translate Scott Guthrie’s posts.

GTT gives me the number of words it finds in the source document. I could count them one by one but that’d be a tedious task. Don’t you think? That’s what computers are for.

Google Translator Toolkit is a pretty good tool because it helps translators translate better and more quickly through one shared, innovative translation technology. It uses machine translation when possible and still allows human intervention.

When a document is uploaded for translation, GTT pretranslate the doc with a combination of previous translated docs by human translation (translation memories), machine translation, etc. Great technology put to work here. That’s why I’ve chosen it.

Given the above, the translated word count I’m interested won’t be an exact figure but it does show a realistic figure about my work as a translator. So let’s find this magic number using GTT API.

Basically what one needs to write a GTT client app is very well described at Google Translator Toolkit Data API v1.0 Developer's Guide. Pay special attention to the Getting Started section as it teaches you how to set up the Google client library. Refer to this: Getting Started with the Google Data Java Client Library.

Now I’m using a Mac and so I played with GTT API with Eclipse for Mac OS if you mind. The programming language is Java and the following code creates a console application.

This is the code I wrote to satisfy my curiosity:


import
com.google.gdata.client.gtt.*;
import com.google.gdata.client.gtt.DocumentQuery;
import com.google.gdata.data.gtt.*;
import com.google.gdata.util.*;

import java.io.IOException;
import java.net.URL;

/**
*
@author Leniel Macaferi
* 12-11-2010
*/
public class GttClient
{

   
static final String DOCUMENTS_FEED_URI = "http://translate.google.com/toolkit/feeds/documents";

   
public static void main(String[] args) throws IOException, ServiceException
   
{
       
try
       
{
           
GttService myService = new GttService("GoogleTranslatorToolkitClientApp");

           
// Your Google username and password go here...
           
myService.setUserCredentials("YourUserName", "YourPassword");

            URL feedUrl =
new URL(DOCUMENTS_FEED_URI);

            DocumentQuery query =
new DocumentQuery(feedUrl);

           
// Send the query to the server.
           
DocumentFeed resultFeed = myService.getFeed(query, DocumentFeed.class);

            printResults
(resultFeed);
       
}
       
catch (AuthenticationException e)
        {
           
// TODO Auto-generated catch block
           
e.printStackTrace();
       
}
    }

   
/**
     * Iterates the document feed and prints some information to the console screen.
     *
@param resultFeed
     */
   
private static void printResults(DocumentFeed resultFeed)
    {
       
System.out.println("...done, there are " + resultFeed.getEntries().size()
               
+ " documents matching the query in your inbox.\n");

       
int i = 1;
       
int totalWords = 0;

       
for (DocumentEntry entry : resultFeed.getEntries())
        {
           
System.out.println(String.valueOf(i++) ") "
                   
+ "id = " + entry.getId().substring(DOCUMENTS_FEED_URI.length() + 1)
                   
+ ", title = '" + entry.getTitle().getPlainText() + "'"
                   
+ ", number of words = '" + entry.getNumberOfSourceWords().getValue() + "'");

            totalWords += entry.getNumberOfSourceWords
().getValue();
       
}

       
// Here's where I satisfy my curiosity... :D
       
System.out.println("Total words translated so far = " + totalWords);
   
}
}

As you see the code is straightforward.

Make sure to replace the strings YourUserName and YourPassword to match your GTT login information.

When I ran the code, this was the output I got:

1) id = 00001vipkz2ce0w, title = 'a-few-quick-asp-net-mvc-3-installation-notes.aspx', number of words = '482'
2) id = 0000082e1f41udc, title = 'add-reference-dialog-improvements-vs-2010-and-net-4-0-series.aspx', number of words = '399'
3) id = 0000206w1a7tog0, title = 'announcing-entity-framework-code-first-ctp5-release.aspx', number of words = '2165'
4) id = 00001qlrxh63jls, title = 'announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx', number of words = '1500'
5) id = 00001zm1lv1meio, title = 'announcing-silverlight-5.aspx', number of words = '784'
6) id = 00001vgl6hzbwg0, title = 'announcing-the-asp-net-mvc-3-release-candidate.aspx', number of words = '1999'
7) id = 00001rtmq1go4cg, title = 'asp-net-4-seo-improvements-vs-2010-and-net-4-0-series.aspx', number of words = '1113'
8) id = 00000snuf95gd8g, title = 'asp-net-mvc-2-model-validation.aspx', number of words = '2925'
9) id = 00000joo5ihwykg, title = 'asp-net-mvc-2-release-candidate-2-now-available.aspx', number of words = '549'
10) id = 00000si5lunjbi8, title = 'asp-net-mvc-2-released.aspx', number of words = '524'
11) id = 00000f8wakzalts, title = 'asp-net-mvc-2-strongly-typed-html-helpers.aspx', number of words = '705'
12) id = 00000en7g3nkvls, title = 'asp-net-mvc-2.aspx', number of words = '619'
13) id = 00001so4spobfnk, title = 'asp-net-mvc-3-layouts.aspx', number of words = '1817'
14) id = 00001snnr32adc0, title = 'asp-net-mvc-3-new-model-directive-support-in-razor.aspx', number of words = '792'
15) id = 00001vldns8skqo, title = 'asp-net-mvc-3-server-side-comments-with-razor.aspx', number of words = '653'
16) id = 00001r2yti5z4sg, title = 'automating-deployment-with-microsoft-web-deploy.aspx', number of words = '3784'
17) id = 00000m0if2iqmtc, title = 'built-in-charting-controls-vs-2010-and-net-4-series.aspx', number of words = '637'
18) id = 000010zzw2fq1a8, title = 'cleaner-html-markup-with-asp-net-4-web-forms-client-ids-vs-2010-a', number of words = '1725'
19) id = 00001ih7gktv6kg, title = 'code-first-development-with-entity-framework-4.aspx', number of words = '5365'
20) id = 00001r7ki4lh05c, title = 'debugging-tips-with-visual-studio-2010.aspx', number of words = '1692'
21) id = 0000151qr16itj4, title = 'download-and-share-visual-studio-color-schemes.aspx', number of words = '311'
22) id = 00001ibpvmetdkw, title = 'entity-framework-4-code-first-custom-database-schema-mapping.aspx', number of words = '1930'
23) id = 00001f6hlprohz4, title = 'introducing-asp-net-mvc-3-preview-1.aspx', number of words = '2833'
24) id = 00001so0gu8f3ls, title = 'introducing-razor.aspx', number of words = '3312'
25) id = 00000ug44uvcow0, title = 'javascript-intellisense-improvements-with-vs-2010.aspx', number of words = '930'
26) id = 00000jtavmijvgg, title = 'jquery-1-4-1-intellisense-with-visual-studio.aspx', number of words = '179'
27) id = 00001q9k1j435s0, title = 'jquery-templates-data-link-and-globalization-accepted-as-official', number of words = '828'
28) id = 00000b4mu45b4e8, title = 'microsoft-ajax-cdn-now-with-ssl-support.aspx', number of words = '309'
29) id = 00000ao1rdg9dds, title = 'my-presentations-in-europe-december-2009.aspx', number of words = '1684'
30) id = 000010q75bisw74, title = 'new-lt-gt-syntax-for-html-encoding-output-in-asp-net-4-and-asp-ne', number of words = '977'
31) id = 00000lubanp79c0, title = 'no-intellisense-with-vs-2010-rc-and-how-to-fix-it.aspx', number of words = '449'
32) id = 00000tqxxxv1h4w, title = 'optional-parameters-and-named-arguments-in-c-4-and-a-cool-scenari', number of words = '841'
33) id = 000010ydwjqjzeo, title = 'pinning-projects-and-solutions-with-visual-studio-2010.aspx', number of words = '667'
34) id = 00001wjhyhw29ds, title = 'search-engine-optimization-seo-toolkit.aspx', number of words = '711'
35) id = 000007lw738nbwg, title = 'searching-and-navigating-code-in-vs-2010-vs-2010-and-net-4-0-seri', number of words = '1305'
36) id = 00000e1cqi0ta0w, title = 'silverlight-4-demos-from-my-pdc-keynote-now-available.aspx', number of words = '613'
37) id = 00000743lq060hs, title = 'url-routing-with-asp-net-4-web-forms-vs-2010-and-net-4-0-series.a', number of words = '1045'
38) id = 000020npa0inls0, title = 'using-ef-code-first-with-an-existing-database.aspx', number of words = '2520'
39) id = 00001vo9oowkpvk, title = 'Using-Server-Side-Comments-with-ASP.NET-2.0-.aspx', number of words = '460'
40) id = 00000eafvti4sn4, title = 'visual-studio-2010-and-net-4-0-update.aspx', number of words = '391'
41) id = 000017d48tqvpc0, title = 'visual-studio-2010-productivity-power-tool-extensions.aspx', number of words = '682'
42) id = 000008fncz9zpc0, title = 'vs-2010-and-net-4-0-beta-2.aspx', number of words = '590'
43) id = 000007m1ubf8zcw, title = 'vs-2010-code-intellisense-improvements-vs-2010-and-net-4-0-series', number of words = '734'
44) id = 00000jxh5t9ebr4, title = 'vs-2010-net-4-release-candidate.aspx', number of words = '748'
45) id = 00001r3ulw3aygw, title = 'vs-2010-web-deployment.aspx', number of words = '1352'
46) id = 000008sxc7ta800, title = 'wpf-4-vs-2010-and-net-4-0-series.aspx', number of words = '3171'

Total words translated so far = 59801

If I was to charge for those translations and considering that each word translated costs $ 0.07 (market price), this fast math gives how much I’d have accrued so far:

59801 x 0.07 = $ 4,186.07

$ 4,186.07 / 46 = $ 91.00 average per doc translated

That’s a lot of money, but as you know already I do not charge a thing to translate ScottGu’s blog. That’s something I do to help others and to keep myself up to date.

Hope you liked the curiosity that made me write this post, the reasoning regarding the math and of course this simple java console application.

Notes
It’s important to mention that I started using GTT on Oct 17, 2009, that is, more than a year after I started translating Scott’s posts. According to my records, I have translated in fact 77 posts so far since April 2008. Those remaining 31 posts ( 77 - 46 = 31 ) didn’t figure in the math above. :(

GTT cold have folders just like Google Docs so that one could organize their translations by client or whatever.

I tried to get only 100% translate completed documents but GTT doesn’t give me this info. It’s true even if I mark the translation as complete. Although GTT shows 100% complete in its UI, when I read the value of entry.getPercentComplete() it gives me not 100% but what is described at Word count and translation completion. So I had to consider every document even those that I still need to finish translating.

Download
You can download the sample app with the necessary libraries at:

https://sites.google.com/site/leniel/blog/GoogleTranslatorToolkitClientApp.zip