# MAPLAT (C) 2008-2011 Rene Schickbauer
# Developed under Artistic license
# for Magna Powertrain Ilz
package Maplat::Web::Translate;
use strict;
use warnings;
use 5.012;
use base qw(Maplat::Web::BaseModule);
use Maplat::Helpers::DateStrings;
use Maplat::Helpers::DBSerialize;
use Maplat::Web::TT::Translate;
use Maplat::Helpers::Translator;
use Maplat::Helpers::FileSlurp qw(slurpBinFile);
our $VERSION = 0.995;
use Carp;
use Readonly;
Readonly my $TESTRANGE => 1_000_000;
sub new {
my ($proto, %config) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new(%config); # Call parent NEW
bless $self, $class; # Re-bless with our class
my @themes;
foreach my $key (sort keys %{$self->{view}}) {
my %theme = %{$self->{view}->{$key}};
$theme{name} = $key;
push @themes, \%theme;
}
$self->{Themes} = \@themes;
$self->{firstReload} = 1;
return $self;
}
sub reload {
my ($self) = shift;
# Update the handles for the template plugin
my $dbh = $self->{server}->{modules}->{$self->{db}};
my $memh = $self->{server}->{modules}->{$self->{memcache}};
if($self->{firstReload}) {
$self->{firstReload} = 0;
Maplat::Web::TT::Translate->setDBH($dbh);
Maplat::Web::TT::Translate->setMEMH($memh);
}
tr_reload($dbh, $memh);
return;
}
sub register {
my $self = shift;
$self->register_webpath($self->{settings}->{webpath}, "get_settings");
$self->register_webpath($self->{languages}->{webpath}, "get_languages");
$self->register_webpath($self->{translations}->{webpath}, "get_translations");
$self->register_webpath($self->{export}->{webpath}, "get_export");
$self->register_webpath($self->{exportfile}->{webpath}, "get_file");
$self->register_prerender("prerender");
return;
}
sub get_settings {
my ($self, $cgi) = @_;
my $webpath = $cgi->path_info();
my $seth = $self->{server}->{modules}->{$self->{usersettings}};
my $dbh = $self->{server}->{modules}->{$self->{db}};
my @AvailLangs;
my $sth = $dbh->prepare_cached("SELECT * FROM translate_languages
ORDER BY lang")
or croak($dbh->errstr);
$sth->execute or croak($dbh->errstr);
while((my $lang = $sth->fetchrow_hashref)) {
push @AvailLangs, $lang;
}
$sth->finish;
my %webdata =
(
$self->{server}->get_defaultwebdata(),
PageTitle => $self->{settings}->{pagetitle},
webpath => $self->{settings}->{webpath},
AvailLanguages => \@AvailLangs,
);
# We don't actually set the Theme into webdata here, this is done during the prerender stage.
# Also, we don't handle the "select a default theme if non set" case, TemplateCache falls back to
# its own default theme anyway
my $mode = $cgi->param('mode') || 'view';
if($mode eq "setvalue") {
my $lang = $cgi->param('language') || "eng";
if($lang ne "") {
$seth->set($webdata{userData}->{user}, "UserLanguage", \$lang);
}
}
my $template = $self->{server}->{modules}->{templates}->get("translate_select", 1, %webdata);
return (status => 404) unless $template;
return (status => 200,
type => "text/html",
data => $template);
}
sub get_languages {
my ($self, $cgi) = @_;
my $webpath = $cgi->path_info();
my $seth = $self->{server}->{modules}->{$self->{usersettings}};
my $dbh = $self->{server}->{modules}->{$self->{db}};
my %webdata =
(
$self->{server}->get_defaultwebdata(),
PageTitle => $self->{languages}->{pagetitle},
webpath => $self->{languages}->{webpath},
);
my $mode = $cgi->param('mode') || 'view';
given($mode) {
when("change") {
my $upsth = $dbh->prepare_cached("UPDATE translate_languages
SET lang = ?, description = ?
WHERE lang = ?")
or croak($dbh->errstr);
my $oldlang = $cgi->param('language') || '';
my $newlang = $cgi->param('newlanguage') || '';
my $description = $cgi->param('description') || '';
if($oldlang ne '' && $newlang ne '') {
if($upsth->execute($newlang, $description, $oldlang)) {
$dbh->commit;
} else {
$dbh->rollback;
}
}
}
when("delete") {
my $delsth = $dbh->prepare_cached("DELETE FROM translate_languages
WHERE lang = ?")
or croak($dbh->errstr);
my $oldlang = $cgi->param('language') || '';
if($oldlang ne '') {
if($delsth->execute($oldlang)) {
$dbh->commit;
} else {
$dbh->rollback;
}
}
}
when("create") {
my $insth = $dbh->prepare_cached("INSERT INTO translate_languages
(lang, description)
VALUES (?,?)")
or croak($dbh->errstr);
my $newlang = $cgi->param('newlanguage') || '';
my $description = $cgi->param('description') || '';
if($newlang ne '') {
if($insth->execute($newlang, $description)) {
$dbh->commit;
} else {
$dbh->rollback;
}
}
}
}
my @AvailLangs;
my $sth = $dbh->prepare_cached("SELECT * FROM translate_languages
ORDER BY lang")
or croak($dbh->errstr);
$sth->execute or croak($dbh->errstr);
while((my $lang = $sth->fetchrow_hashref)) {
push @AvailLangs, $lang;
}
$sth->finish;
$webdata{AvailLanguages} = \@AvailLangs;
my $template = $self->{server}->{modules}->{templates}->get("translate_languages", 1, %webdata);
return (status => 404) unless $template;
return (status => 200,
type => "text/html",
data => $template);
}
sub get_translations {
my ($self, $cgi) = @_;
my $webpath = $cgi->path_info();
my $seth = $self->{server}->{modules}->{$self->{usersettings}};
my $dbh = $self->{server}->{modules}->{$self->{db}};
my $memh = $self->{server}->{modules}->{$self->{memcache}};
my @AvailLangs;
my $sth = $dbh->prepare_cached("SELECT * FROM translate_languages
ORDER BY lang")
or croak($dbh->errstr);
$sth->execute or croak($dbh->errstr);
while((my $lang = $sth->fetchrow_hashref)) {
push @AvailLangs, $lang;
}
$sth->finish;
my %webdata =
(
$self->{server}->get_defaultwebdata(),
PageTitle => $self->{translations}->{pagetitle},
webpath => $self->{translations}->{webpath},
AvailLanguages => \@AvailLangs,
);
my ($ok, $langname) = $seth->get($webdata{userData}->{user}, "EditLanguage");
my $lang = "eng"; # Use english as default
if(defined($langname)) {
$langname = dbderef($langname);
}
if($ok && defined($langname) && $langname ne "") {
$lang = $langname;
}
my $mode = $cgi->param('mode') || 'view';
given($mode) {
when("setlanguage") {
$lang = $cgi->param('language') || "eng";
$seth->set($webdata{userData}->{user}, "EditLanguage", \$lang);
}
when("change") {
my @keys = $cgi->param('originaltext');
my $upsth = $dbh->prepare("SELECT merge_translation(?, ?, ?)")
or croak($dbh->errstr);
foreach my $key (@keys) {
my $translation = $cgi->param("translate_$key") || '';
if($upsth->execute($key, $lang, $translation)) {
$dbh->commit;
} else {
$dbh->rollback;
}
}
tr_reload($dbh, $memh);
}
}
$webdata{EditLanguage} = $lang;
my @trLines;
my $selsth = $dbh->prepare_cached("SELECT k.originaltext, t.translation
FROM translate_keys k
LEFT OUTER JOIN translate_translations t
ON (k.originaltext = t.originaltext)
AND t.lang = ?
ORDER BY originaltext")
or croak($dbh->errstr);
$selsth->execute($lang) or croak($dbh->errstr);
while((my $line = $selsth->fetchrow_hashref)) {
if(!defined($line->{translation})) {
$line->{translation} = '';
}
push @trLines, $line;
}
$selsth->finish;
$webdata{trLines} = \@trLines;
my $template = $self->{server}->{modules}->{templates}->get("translate_translate", 1, %webdata);
return (status => 404) unless $template;
return (status => 200,
type => "text/html",
data => $template);
}
sub get_export {
my ($self, $cgi) = @_;
my $webpath = $cgi->path_info();
my $dbh = $self->{server}->{modules}->{$self->{db}};
my $memh = $self->{server}->{modules}->{$self->{memcache}};
my @AvailLangs;
my $sth = $dbh->prepare_cached("SELECT * FROM translate_languages
ORDER BY lang")
or croak($dbh->errstr);
$sth->execute or croak($dbh->errstr);
while((my $lang = $sth->fetchrow_hashref)) {
push @AvailLangs, $lang;
}
$sth->finish;
my %webdata =
(
$self->{server}->get_defaultwebdata(),
PageTitle => $self->{export}->{pagetitle},
webpath => $self->{export}->{webpath},
AvailLanguages => \@AvailLangs,
);
my $mode = $cgi->param('mode') || 'view';
given($mode) {
when("import") {
my $fh = $cgi->upload("filename");
my $data;
if($fh) {
while((my $line = <$fh>)) {
$data .= $line;
}
tr_import($dbh, $memh, $data);
}
}
}
$webdata{ExportFile} = $self->{exportfile}->{webpath}. "/EXPORT" . int(rand($TESTRANGE) + 1) . "." . int(rand($TESTRANGE) + 1) . ".txt";
my $template = $self->{server}->{modules}->{templates}->get("translate_export", 1, %webdata);
return (status => 404) unless $template;
return (status => 200,
type => "text/html",
data => $template);
}
sub get_file {
my ($self, $cgi) = @_;
my $dbh = $self->{server}->{modules}->{$self->{db}};
my $memh = $self->{server}->{modules}->{$self->{memcache}};
my $exp = tr_export($dbh, $memh);
return (status => 404) unless $exp;
return (status => 200,
type => "text/plain",
"Content-Disposition" => "attachment; filename=\"translations_export.txt\";",
data => $exp);
}
sub prerender {
my ($self, $webdata) = @_;
# Unless the user is logged in, we don't have set a user selected Language, use English
if(!defined($webdata->{userData}) ||
!defined($webdata->{userData}->{user}) ||
$webdata->{userData}->{user} eq "") {
$webdata->{UserLanguage} = "eng";
Maplat::Web::TT::Translate->setLang("eng");
}
my $seth = $self->{server}->{modules}->{$self->{usersettings}};
my $memh = $self->{server}->{modules}->{$self->{memcache}};
my ($ok, $langname) = $seth->get($webdata->{userData}->{user}, "UserLanguage");
my $lang = "eng"; # Use english as default
if(defined($langname)) {
$langname = dbderef($langname);
}
if($ok && defined($langname) && $langname ne "") {
# Now, we have to check if this theme is still available
# FIXME: Check if language still available!
if(tr_checklang($memh, $langname)) {
$lang = $langname;
}
}
$webdata->{UserLanguage} = $lang;
Maplat::Web::TT::Translate->setLang($lang);
return;
}
1;
__END__
=head1 NAME
Maplat::Web::Translate - add multilanguage support to your project
=head1 SYNOPSIS
Adds multilanguage support for the web projects.
=head1 DESCRIPTION
This module adds various hooks to the system as well as managment of all translations
via webpages.
=head1 Configuration
<module>
<modname>translate</modname>
<pm>Translate</pm>
<options>
<memcache>realmemcache</memcache>
<db>maindb</db>
<memdb>memdb</memdb>
<usersettings>usersettings</usersettings>
<languages>
<webpath>/admin/languages</webpath>
<pagetitle>Languages</pagetitle>
</languages>
<translations>
<webpath>/admin/translate</webpath>
<pagetitle>Translations</pagetitle>
</translations>
<settings>
<webpath>/settings/language</webpath>
<pagetitle>Language</pagetitle>
</settings>
<export>
<webpath>/admin/trexport</webpath>
<pagetitle>Import/Export</pagetitle>
</export>
<exportfile>
<webpath>/admin/trexpfile</webpath>
</exportfile>
</options>
</module>
=head2 get_export
Import/Export mask
=head2 get_file
The actual file download for the export mask
=head2 get_languages
Manage languages through the web.
=head2 get_settings
Manage the user settings.
=head2 get_translations
Managne translated texts
=head2 prerender
Hook to properly set up the Template-Toolkit plugin before rendering.
=head1 SEE ALSO
Maplat::Web
=head1 AUTHOR
Rene Schickbauer, E<lt>rene.schickbauer@gmail.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2008-2011 by Rene Schickbauer
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.10.0 or,
at your option, any later version of Perl 5 you may have available.
=cut