in reply to Relationship between timezone country and locale territory?

Hi Nocturnus,

Not an expert on locales, but I think the modules Locale::Codes::Language and Locale::Codes::Country might be helpful. I played with this a bit and here's my naive implementation which seems to work on my Linux box. See also Finding locales in perllocale.

use Locale::Codes::Language 'code2language'; use Locale::Codes::Country 'code2country'; for (`locale -a`) { chomp; my ($lang,$terr) = /^(\w+)_(\w+)\b/; print "$_ - ",code2language($lang)//'(unknown)', " - ",code2country($terr)//'(unknown)',"\n"; }

Update: You said "I don't think that (all) territory codes are valid country codes or vice versa". The information I am finding is that locale names are typically (apparently this varies from system to system) made up of the ISO 639 (language) and ISO 3166-1 (country) codes, which is what the two aforementioned modules handle. Also, at least on Debian-based systems, the list of all supported locales (as opposed to just the ones installed reported by locale -a) is in the file /usr/share/i18n/SUPPORTED.

Update 2: I assume the list of supported locales is not an exhaustive list of which languages are spoken in each country. You'll have to draw the line somewhere though, depending on what you want the user's choice to mean in your application (do you plan on supporting hundreds of locales?). Anyway, I revised the script based on the above:

#!/usr/bin/env perl use warnings; use strict; use Locale::Codes::Language 'code2language'; use Locale::Codes::Country 'code2country'; # list of supported locales (at least on Debian-based systems) open my $fh, '<', '/usr/share/i18n/SUPPORTED' or die $!; chomp( my @locales = grep {/\S/ && !/^\s*#/} <$fh> ); close $fh; # just a test of getting installed locales chomp( my @installed_locales = `locale -a` ); push @locales, @installed_locales; my %locales; for (@locales) { my ($lang,$terr) = /^([a-z]+)(?:_([a-z]+))?\b/i; $terr = code2country($terr) ||"unknown"; $lang = code2language($lang)||"unknown"; push @{ $locales{$terr}{$lang} }, $_; } for my $terr (sort keys %locales) { print "$terr\n"; for my $lang (sort keys %{ $locales{$terr} }) { print "\t$lang: ", join(" / ",@{ $locales{$terr}{$lang} }), "\n"; } }

Update 3: Ok, last update for tonight ;-) You asked how to match the locale codes to timezone names, and the documentation for DateTime::TimeZone->names_in_country says that it accepts two-letter ISO3166 codes, which is apparently the same code typically used in locale names, so you should be able to just match those up.

Hope this helps,
-- Hauke D

Replies are listed 'Best First'.
Re^2: Relationship between timezone country and locale territory? (updated x3)
by Nocturnus (Scribe) on Sep 15, 2016 at 06:26 UTC

    Hi haukex,

    thank you very much for your hints and code. Due to the different wording, I had been quite sure that the country code and the territory code could not be the same. So your hints regarding the structure of locales' codes have been very important for me, and your code shows how to solve the problem.

    By the way, I have no idea if even one single user will sign up for the application. But in the unlikely case that it becomes successful, I actually will have to support several dozens or even hundreds of locales. The application, if successful, will be translated into at least 8 languages and addresses private persons as well as commercial and non-commercial organizations all over the world.

    The application does a lot of input, output and calculations of dates, times, currencies and other numbers, and it is of utmost importance that every user (after having logged in) is working in the time zone he has chosen, gets output in the locale he has chosen, and can give input in the locale he has chosen. Due to the nature of the application, the user should consistently use always the same locale and time zone, regardless of the browser he uses and from where he works.

    Thanks again,

    Nocturnus