MetaTrans

 view release on metacpan or  search on metacpan

lib/MetaTrans.pm  view on Meta::CPAN

=cut

sub enable_translator
{
    my $self  = shift;
    my $trans = shift;

    ${$self->{enabled}}{$trans} = 1;
}

=item $mt->disable_translator($trans)

Disable the translator. The argument is an object.

=cut

sub disable_translator
{
    my $self  = shift;
    my $trans = shift;

    ${$self->{enabled}}{$trans} = 0;
}

=item $mt->toggle_enabled_translator($trans)

Togle translator's enabled/disabled status. The argument is an object.

=cut

sub toggle_enabled_translator
{
    my $self  = shift;
    my $trans = shift;

    ${$self->{enabled}}{$trans} = not ${$self->{enabled}}{$trans};
}

=item $mt->is_enabled_translator($trans)

Returns true value if the translator is enabled, false otherwise.
The argument is an object.

=cut

sub is_enabled_translator
{
    my $self  = shift;
    my $trans = shift;

    return ${$self->{enabled}}{$trans};
}

=item $mt->get_translators_state($trans)

Returns current state of the translator. Possible values are

    VALUE       MEANING
    ---------   --------------------------------------------------------
    "ok"        successfully finished a translation (initial state, too)
    "busy"      working on a translation
    "timeout"   a timeout occured when querying an online translator
    "error"     unknown error occured when queryign an online translator

=cut

sub get_translators_state
{
    my $self  = shift;
    my $trans = shift;

    return "ok" unless exists ${$self->{state}}{$trans};
    return ${$self->{state}}{$trans};
}

=item $mt->get_all_src_lang_codes

Returns a list of language codes, which some of the enabled plug-ins are
able to translate from.

The method calls the C<get_all_src_lang_codes> method for all enabled
plug-ins (see L<MetaTrans::Base>) and unions results.

=cut

sub get_all_src_lang_codes
{
    my $self = shift;
    my @codes;
    my %codes_hash;
    
    foreach my $trans (@{$self->{translators}})
    {
        next unless $self->is_enabled_translator($trans);
        foreach my $code ($trans->get_all_src_lang_codes)
        { 
            push @codes, $code
                unless $codes_hash{$code};
            $codes_hash{$code} = 1;
        }
    }

    return @codes;
}

=item $mt->get_dest_lang_codes_for_src_lang_code($src_lang_code)

Returns a list of language codes, which some of the enabled plug-ins are
able to translate to from the language with $src_lang_code.

The method calls the C<get_dest_lang_codes_for_src_lang_codes> method for
all enabled plug-ins (see L<MetaTrans::Base>) and unions results.

=cut

sub get_dest_lang_codes_for_src_lang_code
{
    my $self          = shift;
    my $src_lang_code = shift;
    my @codes;
    my %codes_hash;

    foreach my $trans (@{$self->{translators}})
    {
        next unless $self->is_enabled_translator($trans);
        foreach my $code
            ($trans->get_dest_lang_codes_for_src_lang_code($src_lang_code))
        {
            push @codes, $code
                unless $codes_hash{$code};
            $codes_hash{$code} = 1;
        }
    }

    return @codes;
}

=item $mt->get_translators_for_direction($src_lang_code, $dest_lang_code)

Retuns an array of enabled tranlators, which support the translation direction
from language with C<$src_lang_code> to language with C<$dest_lang_code>.

=cut

sub get_translators_for_direction
{
    my $self           = shift;
    my $src_lang_code  = shift;
    my $dest_lang_code = shift;
    my @result;

    foreach my $trans (@{$self->{translators}})
    {
        next unless $self->is_enabled_translator($trans);
        push @result, $trans
            if $trans->is_supported_dir($src_lang_code, $dest_lang_code);
    }

    return @result;
}

=item $mt->run_translators($expression, $src_lang_code, $dest_lang_code,
%options)

Perform a translation of C<$expression> from C<$src_lang_code> language to
C<$dest_lang_code> language simultaneously on all enabled translators
(plug-ins), which support this translation direction. The method returns
true value on success, false on error. Use C<get_translation> method for
retrieving the results of particular translations.

The method sets the state of all plug-ins to C<"busy">. See C<get_state>
method.

There are two ways of performing parallel run. If C<$options{tk_safe}> is
undefined or set to false value, then a child process is forked for every
translator to be used and C<translate> method is called. This is generally
cleaner and more effective way of doing so then the one mentioned bellow.
However, this causes trouble if the module is used in Perl/Tk applications.

If C<$options{tk_safe}> is set to a true value, then a brand new child
process is created for every plug-in to be used. For this plug-ins are
required to implement C<get_trans_command> method, which is expected to
return a string containing a command, which can be run from a shell and
provides appropriate functionality for the translation to be performed.
This is an ugly hack necessary for making C<MetaTrans> work in Perl/Tk
applications. Hopefully this will be fixed in some of the future releases.
See also L<MetaTrans::Base> for more information on this.

Generally, if the plug-ins are only to be run with C<$options{tk_safe}> set to
false, they are not required to implement the C<get_trans_command> method.
Reversely, if the plug-ins are only to be run with C<$options{tk_safe}>
set to true, the are not required to implement the C<translate> method.
Plug-ins derrived from C<MetaTrans::Base> implement both methods.

=cut

sub run_translators
{
    my $self           = shift;
    my $expression     = shift;
    my $src_lang_code  = shift;
    my $dest_lang_code = shift;
    my %options        = @_;

    my @translators = $self->get_translators_for_direction(
        $src_lang_code, $dest_lang_code);
    if (@translators == 0)
    {
        Carp::cluck "no translators available for direction: " . 
            "'${src_lang_code}2${dest_lang_code}'";
        return undef;
    }

    $self->{running} = 0;
    undef $self->{pids};
    $self->{select} = new IO::Select();
    my @fhs;
    my $i = 0;

    foreach my $translator (@translators)
    {
        my $pid;
        if ($options{tk_safe})
        {
            # tk-safe fork
            my $translator_id = $self->_get_trans_id($translator);
            my @command = $translator->get_trans_command($expression,
                $src_lang_code, $dest_lang_code, "/$translator_id");

            ($fhs[$i], $pid) = sync_popen_noshell('r', @command);
            unless($pid)
            {
                carp("can't run '@command', make sure that runtrans is ".
                    "in your \$PATH variable");
                return undef;
            }
        }
        else
        {
            # non-tk-safe fork
            do
            {
                $pid = open($fhs[$i], '-|');
                unless (defined $pid)
                {
                    warn "cannot fork: $!, still trying...";
                    sleep 2;
                }
            }
            until defined $pid;
        }

        ${$self->{state}}{$translator} = "busy";

        if ($pid)
        {
            # parent
            push @{$self->{pids}}, $pid;
            $self->{select}->add($fhs[$i]);
            $self->{running}++;
        }
        else
        {
            #child (non-tk-safe fork only)
            $self->_run_process($translator, $expression, $src_lang_code,
                $dest_lang_code);
        }
    }
    continue
        { $i++; }

    return 1;
}

=item $mt->get_translation(%options)

Returns a translation returned by one of the running plug-ins (translators)
as a string of following form:

    expression = translation

The method blocks until there is a translation is available (until some of
the running plug-ins is ready to provide an output). The order, in which
the translations are returned depends on the order, in which the translators
return their result and is therefore non-deterministic.

The behaviour of the method depends on the C<$options{return_translators}>
option. If undefined or set to a false value then every call returns one
translation, C<undef> value is returned to indicate the end.

If C<$options{return_value}> is set to true value, the every call returns a
(translation, translator) pair in an array, where the translator is the one,
which returned the translation. (C<undef>, translator) pair is returned to
indicate that the translator finished running and. C<undef> value is returned
to indicate that no more translations are available.

The method also sets states of particular translators. See C<get_state> method.

=cut

sub get_translation
{
    my $self    = shift;
    my %options = @_;

    return undef
        if $self->{running} == 0;

    while (1)
    {
        my @ready;
        do { @ready = $self->{select}->can_read(0.1); } until @ready > 0;

lib/MetaTrans.pm  view on Meta::CPAN

            if $options{return_translators};

        # return translations only
        return undef
            if $self->{running} == 0;
        return $translation
            unless $translation eq '';
    }
}

=item $mt->is_translation_available($timeout)

A non-blocking call, which returns a true value if next translation is already
available. Otherwise it blocks for at most C<$timeout> seconds and then returns
false if a translation is still unavailable. However, if the C<$timeout> is
undefined then the method always blocks and never returns false value.

It is useful if you want to do something while waiting for the next
translation. Example:

    LOOP: while (1)
    {
        # check every second
        until ($mt->is_translation_available(1.0))
        {
            last LOOP
                if &something_happened;
        }

        my $translation = $mt->get_translation;

        # ... do something with $translation ...
    }

Note: To be more exact, the C<is_translation_available> returns a true value if
the C<get_translation_method> has something to say. This must not necessairly
be a next translation, but also an C<undef> value or (<undef>, translator)
pair.

=cut

sub is_translation_available
{
    my $self    = shift;
    my $timeout = shift;

    return 1
        if $self->{running} == 0;

    my @handles = $self->{select}->handles;
    return 1
        if @handles  = 0;

    my @ready = $self->{select}->can_read($timeout);
    return (@ready > 0);
}

=item $mt->stop_translators

Stop all running plug-ins. This simply kills all running child processes.
The correspondent translators will end in the C<"busy"> state.

=cut

sub stop_translators
{
    my $self = shift;

    kill(9, @{$self->{pids}});
    foreach my $fh ($self->{select}->handles)
        { $fh->close; }
}

=back

Following methods set correspondent attributes of all plug-ins being used
to specified values. See C<ATTRIBUTES> section of L<MetaTrans::Base> for
more information.

=over 4

=item $mt->set_timeout($timeout)

=item $mt->set_matching($type)

=item $mt->set_match_at_bounds($bool)

=back

=cut

sub set_timeout
{
    my $self    = shift;
    my $timeout = shift;

    foreach my $trans (@{$self->{translators}})
        { $trans->timeout($timeout); }
}

sub set_matching
{
    my $self     = shift;
    my $matching = shift;

    foreach my $trans (@{$self->{translators}})
        { $trans->matching($matching); }
}

sub set_match_at_bounds
{
    my $self      = shift;
    my $at_bounds = shift;

    foreach my $trans (@{$self->{translators}})
        { $trans->match_at_bounds($at_bounds); }
}

=head1 FUNCTIONS

=over 4



( run in 1.272 second using v1.01-cache-2.11-cpan-39bf76dae61 )