Locale-Maketext-Gettext

 view release on metacpan or  search on metacpan

lib/Locale/Maketext/Gettext/Functions.pm  view on Meta::CPAN

# Locale::Maketext::Gettext::Functions - Functional interface to Locale::Maketext::Gettext

# Copyright (c) 2003-2021 imacat. All rights reserved. This program is free
# software; you can redistribute it and/or modify it under the same terms
# as Perl itself.
# First written: 2003/4/28

package Locale::Maketext::Gettext::Functions;
use 5.008;
use strict;
use warnings;
use base qw(Exporter);
our ($VERSION, @EXPORT, @EXPORT_OK);
$VERSION = 0.14;
@EXPORT = qw(
bindtextdomain textdomain get_handle maketext __ N_
dmaketext pmaketext dpmaketext
reload_text read_mo encoding key_encoding encode_failure
die_for_lookup_failures);
@EXPORT_OK = @EXPORT;
# Prototype declaration
sub bindtextdomain($;$);
sub textdomain(;$);
sub get_handle(@);
sub maketext(@);
sub __(@);
sub N_(@);
sub dmaketext($$@);
sub pmaketext($$@);
sub dpmaketext($$$@);
sub reload_text();
sub encoding(;$);
sub key_encoding(;$);
sub encode_failure(;$);
sub die_for_lookup_failures(;$);
sub _declare_class($);
sub _cat_class(@);
sub _init_textdomain($);
sub _get_langs($$);
sub _get_handle();
sub _get_empty_handle();
sub _reset();
sub _new_rid();
sub _k($);
sub _lang($);

use Encode qw(encode decode from_to FB_DEFAULT);
use File::Spec::Functions qw(catdir catfile);
use Locale::Maketext::Gettext qw(read_mo);
our (%LOCALEDIRS, %RIDS, %CLASSES, %LANGS);
our (%LHS, $_EMPTY, $LH, $DOMAIN, $CATEGORY, $BASE_CLASS, @LANGS, %PARAMS);
our (@SYSTEM_LOCALEDIRS);
%LHS = qw();
# The category is always LC_MESSAGES
$CATEGORY = "LC_MESSAGES";
$BASE_CLASS = "Locale::Maketext::Gettext::_runtime";
# Current language parameters
@LANGS = qw();
@SYSTEM_LOCALEDIRS = @Locale::Maketext::Gettext::SYSTEM_LOCALEDIRS;
%PARAMS = qw();
$PARAMS{"KEY_ENCODING"} = "US-ASCII";
$PARAMS{"ENCODE_FAILURE"} = FB_DEFAULT;
$PARAMS{"DIE_FOR_LOOKUP_FAILURES"} = 0;
# Parameters for random class IDs
our ($RID_LEN, @RID_CHARS);
$RID_LEN = 8;
@RID_CHARS = split //,
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

# Bind a text domain to a locale directory
sub bindtextdomain($;$) {
    local ($_, %_);
    my ($domain, $LOCALEDIR);
    ($domain, $LOCALEDIR) = @_;
    # Return the current registry
    return (exists $LOCALEDIRS{$domain}? $LOCALEDIRS{$domain}: undef)
        if !defined $LOCALEDIR;
    # Register the locale directory
    $LOCALEDIRS{$domain} = $LOCALEDIR;
    # Reinitialize the text domain
    _init_textdomain($domain);
    # Reset the current language handle
    _get_handle() if defined $DOMAIN && $domain eq $DOMAIN;
    # Return the locale directory
    return $LOCALEDIR;
}

# Set the current text domain
sub textdomain(;$) {
    local ($_, %_);
    my ($new_domain);
    $new_domain = $_[0];
    # Return the current text domain
    return $DOMAIN if !defined $new_domain;
    # Set the current text domain
    $DOMAIN = $new_domain;
    # Reinitialize the text domain
    _init_textdomain($DOMAIN);
    # Reset the current language handle
    _get_handle();
    return $DOMAIN;
}

# Get a language handle
sub get_handle(@) {
    local ($_, %_);
    # Register the current get_handle arguments
    @LANGS = @_;
    # Reset and return the current language handle
    return _get_handle();
}

# Maketext, in its long name
#   Use @ instead of $@ in prototype, so that we can pass @_ to it.
sub maketext(@) {
    return __($_[0], @_[1..$#_]);
}

# Maketext, in its shortcut name
#   Use @ instead of $@ in prototype, so that we can pass @_ to it.
sub __(@) {
    local ($_, %_);
    my ($key, @param, $keyd);
    ($key, @param) = @_;
    # Reset the current language handle if it is not set yet
    _get_handle() if !defined $LH;
    
    # Decode the source text
    $keyd = $key;
    $keyd = decode($PARAMS{"KEY_ENCODING"}, $keyd, $PARAMS{"ENCODE_FAILURE"})
        if exists $PARAMS{"KEY_ENCODING"} && !Encode::is_utf8($key);
    # Maketext
    $_ = $LH->maketext($keyd, @param);
    # Output to the requested encoding
    if (exists $PARAMS{"ENCODING"}) {
        $_ = encode($PARAMS{"ENCODING"}, $_, $PARAMS{"ENCODE_FAILURE"});
    # Pass through the empty/invalid lexicon
    } elsif (   scalar(keys %{$LH->{"Lexicon"}}) == 0
                && exists $PARAMS{"KEY_ENCODING"}
                && !Encode::is_utf8($key)) {
        $_ = encode($PARAMS{"KEY_ENCODING"}, $_, $PARAMS{"ENCODE_FAILURE"});
    }
    
    return $_;
}

# Return the original text untouched, so that it can be cached
#   with xgettext
#   Use @ instead of $@ in prototype, so that we can pass @_ to it.
sub N_(@) {
    # Watch out for this Perl magic! :p
    return $_[0] unless wantarray;
    return @_;
}

# Maketext in another text domain temporarily,
#   an equivalent to dgettext().
sub dmaketext($$@) {
    local ($_, %_);
    my ($domain, $key, @param, $lh0, $domain0, $text);
    ($domain, $key, @param) = @_;
    # Preserve the current status
    ($lh0, $domain0) = ($LH, $DOMAIN);
    # Reinitialize the text domain
    textdomain($domain);
    # Maketext
    $text = maketext($key, @param);
    # Return the current status
    ($LH, $DOMAIN) = ($lh0, $domain0);
    # Return the "made text"
    return $text;
}

# Maketext with context,
#   an equivalent to pgettext().
sub pmaketext($$@) {
    local ($_, %_);
    my ($context, $key, @param);
    ($context, $key, @param) = @_;
    # This is actually a wrapper to the maketext() function
    return maketext("$context\x04$key", @param);
}

# Maketext with context in another text domain temporarily,
#   an equivalent to dpgettext().
sub dpmaketext($$$@) {
    local ($_, %_);
    my ($domain, $context, $key, @param);
    ($domain, $context, $key, @param) = @_;
    # This is actually a wrapper to the dmaketext() function
    return dmaketext($domain, "$context\x04$key", @param);
}

# Purge the lexicon cache
sub reload_text() {
    # reload_text is static.
    Locale::Maketext::Gettext->reload_text;
}

# Set the output encoding
sub encoding(;$) {
    local ($_, %_);
    $_ = $_[0];
    
    # Set the output encoding
    if (@_ > 0) {
        if (defined $_) {
            $PARAMS{"ENCODING"} = $_;
        } else {
            delete $PARAMS{"ENCODING"};

lib/Locale/Maketext/Gettext/Functions.pm  view on Meta::CPAN

        if (exists $LH->{"MO_ENCODING"}) {
            $PARAMS{"ENCODING"} = $LH->{"MO_ENCODING"};
        } else {
            delete $PARAMS{"ENCODING"};
        }
    }
    # We handle the encoding() and key_encoding() ourselves.
    $LH->key_encoding(undef);
    $LH->encoding(undef);
    # Register it
    $LHS{$subclass} = $LH;
    
    return _lang($LH);
}

# Obtain the empty language handle
sub _get_empty_handle() {
    local ($_, %_);
    if (!defined $_EMPTY) {
        $_EMPTY = Locale::Maketext::Gettext::Functions::_EMPTY->get_handle;
        $_EMPTY->key_encoding(undef);
        $_EMPTY->encoding(undef);
    }
    $LH = $_EMPTY;
    $LH->die_for_lookup_failures($PARAMS{"DIE_FOR_LOOKUP_FAILURES"});
    return _lang($LH);
}

# Initialize everything
sub _reset() {
    local ($_, %_);
    
    %LOCALEDIRS = qw();
    undef $LH;
    undef $DOMAIN;
    @LANGS = qw();
    %PARAMS = qw();
    $PARAMS{"KEY_ENCODING"} = "US-ASCII";
    $PARAMS{"ENCODE_FAILURE"} = FB_DEFAULT;
    $PARAMS{"DIE_FOR_LOOKUP_FAILURES"} = 0;
    
    return;
}

# Generate a new random ID
sub _new_rid() {
    local ($_, %_);
    my ($id);
    
    do {
        for ($id = "", $_ = 0; $_ < $RID_LEN; $_++) {
            $id .= $RID_CHARS[int rand scalar @RID_CHARS];
        }
    } while exists $RIDS{$id};
    $RIDS{$id} = 1;
    
    return $id;
}

# Build the key for the domain registry
sub _k($) {
    return join "\n", $LOCALEDIRS{$_[0]}, $CATEGORY, $_[0];
}

# The language from a language handle.  language_tag is not quite sane.
sub _lang($) {
    local ($_, %_);
    $_ = $_[0];
    $_ = ref($_);
    s/^.+:://;
    s/_/-/g;
    return $_;
}

# Public empty lexicon
package Locale::Maketext::Gettext::Functions::_EMPTY;
use 5.008;
use strict;
use warnings;
use base qw(Locale::Maketext::Gettext);
our $VERSION = 0.01;

package Locale::Maketext::Gettext::Functions::_EMPTY::i_default;
use 5.008;
use strict;
use warnings;
use base qw(Locale::Maketext::Gettext);
our $VERSION = 0.01;

return 1;

__END__

=head1 NAME

Locale::Maketext::Gettext::Functions - Functional interface to Locale::Maketext::Gettext

=head1 SYNOPSIS

  use Locale::Maketext::Gettext::Functions;
  bindtextdomain(DOMAIN, LOCALEDIR);
  textdomain(DOMAIN);
  get_handle("de");
  print __("Hello, world!\n");

=head1 DESCRIPTION

Locale::Maketext::Gettext::Functions is a functional
interface to
L<Locale::Maketext::Gettext(3)|Locale::Maketext::Gettext/3> (and
L<Locale::Maketext(3)|Locale::Maketext/3>).  It works exactly the GNU
gettext way.  It plays magic to
L<Locale::Maketext(3)|Locale::Maketext/3> for you.  No more
localization class/subclasses and language handles are required at
all.

The C<maketext>, C<dmaketext>, C<pmaketext> and C<dpmaketext>
functions attempt to translate a text message into the native
language of the user, by looking up the translation in an MO lexicon
file.



( run in 2.649 seconds using v1.01-cache-2.11-cpan-2398b32b56e )