traxlog has asked for the wisdom of the Perl Monks concerning the following question:

Apart from creating the longest title for a question, I'm also attempting to create 10 language modules for my program which contain about 40 words and phrases.
In my travels as a newbie I've come accross a method of declaring program wide variables in a (e.g.) "dutch.pl" module, which simply looks like this:

%language = qw( blue => blauw, red => rood);

And called by

require "dutch.pl";

No use strict, no use Exporter... etc, just variable declarations
Its simplicity appeals to me - however I'm assuming it's unsafe as I've not seen it used often. I thought about using a DB_File but the file must be plain text as I'm sending the files to friends for translation.
Any recommendations as to how to go about this simple task?
thanks

Replies are listed 'Best First'.
Re: Translation modules and the importation of global language variables
by hardburn (Abbot) on Oct 08, 2003 at 20:13 UTC

    It's used often enough, but not the way you're doing it. Usually, the file would become a proper module in the @INC and is used instead of required. I'm using a similar method for configuration files in an application I'm creating at work.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

      Thanks for your reply hardburn.
      Could you be more specific? What do mean by "proper module", a package?
      I did forget to mention it was included in @INC, but how do you then routinely load the variables?
      I would also like to use the same method for config files.
      Some simple code extract would get me on track!
      thanks again

        Modules usually have a '.pm' extention, although there is this whole debate about identifying files by their extention being a bad thing. Modules and packages look the same if you squint enough, so there are probably no practical differences between your code and a 'proper module' as it is.

        Something like this is what I'm talking about:

        package My::Language::Dutch; use strict; my %language = ( blue => 'blauw', red => 'rood', ); sub get_word { my $class = shift; my $word = shift || return; return $language{$word}; } 1; # IMPORTANT -- modules have to return a true value at the end

        You put that somewhere in your @INC under a My/Languages directory, so that perl knows where to find it, and then use it like this:

        use My::Language::Dutch; my $blue_dutch = My::Language::Dutch->get_word( 'blue' );

        If you need to dynamically use a language at runtime, you'll have to fall back to require and some class name tricks:

        my $language = 'Dutch'; require "My/Language/$language.pm"; my $class = "My::Language::$language"; my $blue = $class->get_word( 'blue' );

        ----
        I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
        -- Schemer

        Note: All code is untested, unless otherwise stated

Re: Translation modules and the importation of global language variables
by BrowserUk (Patriarch) on Oct 08, 2003 at 22:45 UTC

    Would this meet your needs?

    #! perl -slw use strict; use vars qw[ $LANG ]; BEGIN{ $LANG ||= 'ENGLISH'; } use Language $LANG; print RED, GREEN, BLUE; print "The RED ballon floated over the GREEN fields in the BLUE sky"; { no Language; print RED, GREEN, BLUE; print "The RED ballon floated over the GREEN fields in the BLUE sk +y"; } print RED, GREEN, BLUE; print "The RED ballon floated over the GREEN fields in the BLUE sky"; __END__ P:\test>junk redgreenblue The red ballon floated over the green fields in the blue sky redgreenblue The RED ballon floated over the GREEN fields in the BLUE sky redgreenblue The red ballon floated over the green fields in the blue sky P:\test>junk -LANG=DUTCH roodgroenblauw The rood ballon floated over the groen fields in the blauw sky roodgroenblauw The RED ballon floated over the GREEN fields in the BLUE sky roodgroenblauw The rood ballon floated over the groen fields in the blauw sky P:\test>junk -LANG=FRENCH rougevertbleu The rouge ballon floated over the vert fields in the bleu sky rougevertbleu The RED ballon floated over the GREEN fields in the BLUE sky rougevertbleu The rouge ballon floated over the vert fields in the bleu sky

    The language is choosen by a command line switch -LANG=DUTCH. This could be converted to use one of the GetOpt::* modules easily, if they're your thing.

    The module (Langauge) exports constants for the words which will also be interpolated into string constants. This could be extended to interpolation into regexes as well if that was a requirement.

    Caveats

    You can also change languages on the fly, though currently this will produce a warning for each constant that is redefined -- I haven't found a way to suppress this yet, which is why I haven't included it in the demonstration.

    Also, changing langauges is not lexically constrained. Once it is changed, it remains changed at all scopes, though you can always change it back. You can however, disable the interpolation lexically.

    The module

    package Language; use Inline::Files; use strict; use overload; my %words; sub import { no strict 'refs'; my $caller = caller; my( $class, $lang ) = @_; $lang = uc $lang; my $fh = \*{$lang}; while( <$fh> ) { my( $english, $trans ) = m[(\w+)\s*=\s*(\w+)]; $words{ $english } = $trans; eval qq[ # line 1 "Language::import" *${caller}::$english = bless sub() { '$trans' }, '$class'; ]; } overload::constant ( q => \&interp ); } sub unimport { overload::remove_constant ( q => \&interp ); } sub interp{ my( $orig, $perl, $use) = @_; $orig =~ s[\b([A-Z]+)\b]{ exists $words{ $1 } ? $words{ $1 } : $1 }ge; $orig; } 1; __ENGLISH__ RED = red BLUE = blue GREEN = green __FRENCH__ RED = rouge BLUE = bleu GREEN = vert __DUTCH__ RED = rood BLUE = blauw GREEN = groen

    It uses Inline::Files to incorporate all the languages into the module file for compactness, but this could easily be changed to use separate files.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail

Re: Translation modules and the importation of global language variables
by PodMaster (Abbot) on Oct 09, 2003 at 09:39 UTC
    Hmm, sounds like you want a wheel I know, called Locale::Maketext :)

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.