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 )