Locale::MakePhrase::Print - Overload of C<print> to automate translations


Locale-MakePhrase documentation Contained in the Locale-MakePhrase distribution.

Index


Code Index:

NAME

Top

Locale::MakePhrase::Print - Overload of print to automate translations

SYNOPSIS

Top

Using this module, it will override print statements so that your application automatically gets translated into the target language.

Example:

Your application will have previously instantiated a Locale::MakePhrase object in some other module. Now you need to use that instantiation within a particular module; from here:

  use Locale::MakePhrase::Print;
  ...
  print "Some text to be translated.";

When print is called, the text is automatically fed into the translation engine.

DESCRIPTION

Top

The purpose of this module, is to de-couple the use of the translation engine, from the API of the translation engine. This saves you from littering your application code with translation-specific function calls. The main benefits are:

API

Top

To use this module, you simply need to use it at the top of your own module. You can optionally specify a specific filehandle to print to (rather than STDOUT), eg:

  use Locale::MakePhrase::Print;
  ...
  print "Some text";

or

  open(FH,">some_output_file.txt") or die;
  use Locale::MakePhrase::Print \*FH;
  ...
  print "Some text";

Will print Some text to STDOUT or the specified filehandle.

To stop overriding print:

  no Locale::MakePhrase::Print;

println "..." [, ...]

This function is explicatly exported so that users can avoid having to specify the newline character in the translation key.

Note: when no Locale::MakePhrase::Print is in effect, println simply prints out the un-translated string, including a the newline.

NOTES

Top

This module overrides print only for the STDOUT filehandle; this also applies to exported the println function. ie: specifying a filehandle to print will result in no translation occurring, or some weired error if used with println.

Thus to specifically avoid using the overridden print function, explicatly specify the filehandle as in:

  print STDOUT "Some un-translated text.";


Locale-MakePhrase documentation Contained in the Locale-MakePhrase distribution.
package Locale::MakePhrase::Print;
our $VERSION = 0.1;
our $DEBUG = 0;

use strict;
use warnings;
use utf8;
use Symbol;
use Exporter;
use base qw(Exporter);
use Locale::MakePhrase::Utils qw(die_from_caller);
our $STDOUT;
our $filehandle;
our $print = 1;
our $println = 1;
our $this;

#
# Install a println handler to handle println'ing to a filehandle
#
sub IO::Handle::println {
  my $FH = shift;
  print $FH (@_,$/);
}

#
# Install a println handler to handle println'ing to a stdout
#
sub main::println {
  CORE::print (@_,$/);
}

#
# Handle use/no options
#
sub get_options {
  my $func = shift;
  my $options = shift;
  $options = {} unless (defined $options);
  if (@_ > 1 and not(@_ % 2)) {
    %$options = @_;
  } elsif (@_ == 1 and ref($_[0]) eq "HASH") {
    %$options = %{$_[0]};
  } elsif (@_ == 1 and ref($_[0]) eq "GLOB") {
    $options->{filehandle} = shift;
  } elsif (@_ == 1 and ref($_[0]) eq "" and $_[0] eq "print") {
    $options->{print} = 1;
  } elsif (@_ == 1 and ref($_[0]) eq "" and $_[0] eq "println") {
    $options->{println} = 1;
  } elsif (@_ > 0) {
    die_from_caller "Unknown arguments to '$func ".__PACKAGE__." ...;' call";
  }
  $print = (exists $options->{print}) ? ($options->{print} ? 1 : 0) : $print;
  $println = (exists $options->{println}) ? ($options->{println} ? 1 : 0) : $println;
}

#
# On module import we override printing to STDOUT, by overriding
# the 'print' function, so that translations become automatic. We
# also export the translation-engine-enabled 'println' function.
#
sub import {
  my $class = shift;
  my $caller = caller;
  my $sym = gensym;
  $STDOUT = select unless (defined $STDOUT);

  my %options;
  get_options('use',\%options,@_) if @_;
  $filehandle = (exists $options{filehandle}) ? $options{filehandle} : (defined $filehandle ? $filehandle : $STDOUT);
  die "Invalid filehandle specification" unless (defined $filehandle);

  $this = tie *$sym, $class, $filehandle;
  bless $sym, $class;

  # Override 'print'
  if ($print) {
    select $sym;
  }

  # Override 'println'
  if ($println) {
    no strict 'refs';
    *{$caller."::println"} = \&{$class."::LM_println"};
  }

  return $class;
}

#
# On module unimport we reset printing to STDOUT so that it
# goes back to Perl's default behaviour.  We also reset the exported
# 'println' function so as to not be bound to the translation-engine.
#
sub unimport {
  my $class = shift;
  my $caller = caller;
  get_options('no',undef,@_) if @_;

  # Reset 'print'
  if ($print) {
    select $STDOUT;
  }

  # Reset 'println'
  if ($println) {
    no strict 'refs';
    *{$caller."::println"} = \&{$class."::CORE_println"};
  }

  return $class;
}

#
# Automatically called when the module is imported due to overriding
# the import() sub.
#
sub TIEHANDLE { 
  my $class = shift;
  my $self = bless {}, $class;
  if (@_ > 0) {
    $self->{fh} = shift or die "No filehandle specified in constructor.";
  } else {
    $self->{fh} = select;
  }
  return $self;
}

#
# Install the appropriate mp() function to point to the correct
# implementation, based on debugging settings.
#
local *mp;
if ($DEBUG > 5) {
  *mp = sub { __PACKAGE__.": ",@_ };
} else {
  *mp = \&Locale::MakePhrase::mp;
}

#
# Implement custom 'print' behaviour
#
sub PRINT {
  my $self = shift;
  my $fh = *{ $self->{fh} };
  CORE::print $fh (mp(@_));
}

#
# Implement custom 'println' behaviour
#
sub PRINTLN {
  my $self = shift;
  my $fh = *{ $self->{fh} };
  CORE::print $fh (mp(@_).$/);
}

#
# Setup object->method signatures 
#
no warnings 'once';
*new = *TIEHANDLE;
*print = *PRINT;
*println = *PRINTLN;
use warnings 'once';

#--------------------------------------------------------------------------

#
# Implement generic 'println' behaviour
#
sub CORE_println {
  CORE::print $STDOUT @_,$/;
}

#
# Implement custom 'println' behaviour
#
sub LM_println {
  PRINTLN $this, @_;
}

#
# 'println' is dyamically linked into the symbol table, based on the
# 'use'/'no' behaviour; see import() sub.
#

1;
__END__
#--------------------------------------------------------------------------