some tidying up and fuller comments; no logic changes
fix for bug in LanguageRouteDecorator.GetRouteData: trim of language suffix was not happening because of case-sentivity of TrimEnd method. Modified EndsWithAnyIgnoreCase extension to facilitate the fix.
Modification such that template PO files (where all msgstr elements are empty) are considered as unavailable. These .PO files are generated by the gettext merge mechanism as a result of the CreateEmptyMessages mechanism and so duping the GetLanguageIfAvailable into thinking valid translation are available when they aren't. At least one msgstr must now exist in a PO file for it to be used.
Refactoring after previous change to GetLanguageIfAvailable.
LocalizingService: Factored out cachekey generation to ensure consistency, notably to ensure it is lowercase.
Tidied up comment: Tested with a one-char msgstr entry and it does work.
Removed unnecessary lock
Moved class 'Extensions' up hierarchy, from project i18n.MVC3 to i18n, thus allowing it to be used from i18n.
fix for problem with multiple-line strings of 1 char not reading. Involved replacement of Regex with string extension helper for unquoting strings. The following PO now parses correctly:

msgid "A"
msgstr ""
"A"
""
"B"
"CD"

This parses to "ABCD".
Added handling of escaped characters in PO msgid and msgstr strings. E.g. if the msgstr value is itself to be a quoted string such as "Hello", this was being loaded as \"Hello\". Now loaded as "Hello".
Improved handling of a race condition.
performance improvement: replaced list<msg> with dictionary<msgid, msg> for faster lookups.
Merge pull request #27 from turquoiseowl/master

Some small updates