It looks like it does what it does badly, but it does it quite well otherwise.
One question for the author: You use Module::Install as your builder, why aren't you 'install_share'-ing all those data files? The pairing of Module::Install and File::ShareDir to get at data files is one of the big advantages of using Module::Install as opposed to M::B or EU::MM.
This module really fills an annoying gap, and therefore 4 stars. It's also well documented and easy to use. But ...
Data files in a Perl distribution always make me frown. Why do you parse a file LL.dat from a Perl module? Turn them into Perl modules themselves, and let the Perl interpreter do the job. It can do it a lot better, faster, and additionally - with a nice, perlish interface - your users would have it a lot easier to extend your module.
Why do you read "INCDIR/Locale/Country/Multilingual/LL.dat" yourself, but not simply "require Locale::Counry::Multilingual::LL". That has several big advantages (apart from being faster and perlisher):
- People can add more languages by simply placing a language module somewhere in @INC. Currently they have to place that in a directory, where they maybe don't have write access.
- People can override translations for a particular language.
- With a minor internal change it is also possible to override one particular translation. I would actually turn all the data into subroutines. The translation for country "cn" in language "bg" would then be retrieved by a call to Locale::Country::Multilingual::bg::cn(), and if you want to override that, you just override that particular method.
With that change, you can also elegantly solve the problem with country-specific translations. The module Locale::Country::Multilingual::ll_CC would simply have to inherit from Locale::Country::Multilingual::ll, and override only those few methods, where it is needed, instead of redefining the entire data.
An internal change like that described above would then suggest an alternative API: You could turn the module into a mere factory class for the translator objects. These translator objects all inherit from a base class that handles the nasty I/O aspects (utf-8 flag ...), and the users would invoke the methods like CA(), GB(), and so on themselves.
Implementation that falls back to a default language? No problem. Define an additional import flag, where you can define base language(s). In presence of this flags, the translator objects created by the factory simply inherit from the translator for that language (by fiddling with @INC, no problem), and voilÃ ! you get a translator that gives you a country name for country CC in the selected language, or falls back to some default language.
The only thing that becomes tricky is to get a list of the countries that a particular translator knows translations for, but even that is feasible and not an important feature anyway.