summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis M. Hoffmann <jannis.hoffmann@rwth-aachen.de>2022-05-07 00:49:24 +0200
committerJannis M. Hoffmann <jannis.hoffmann@rwth-aachen.de>2022-05-07 00:49:24 +0200
commit77992072b7963d9a96c11a3913f553c820cc21da (patch)
treef83db2a926e66d8ab6bdc3527f501cf47a5fb14e
parent6ac91b3bc730ad8d3476288911e596bbfd2b8880 (diff)
added localization via Locale::Maketext
-rw-r--r--CHANGES.md11
-rw-r--r--Makefile.PL4
-rw-r--r--jwebmail.development.toml7
-rw-r--r--lib/JWebmail/Controller/Webmail.pm4
-rw-r--r--lib/JWebmail/I18N.pm16
-rw-r--r--lib/JWebmail/I18N/de_de.pm78
-rw-r--r--lib/JWebmail/I18N/en_us.pm13
-rw-r--r--lib/JWebmail/Plugin/I18N2.pm67
-rw-r--r--templates/webmail/login.html.ep4
9 files changed, 181 insertions, 23 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 6dd087e..cbd16de 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -148,18 +148,13 @@ Current v1.1.0
- [ ] extract version for Makefile.PL from Application
- [ ] add basic telemetry (goatcounter?)
- [ ] make mime_render return a mojo bytes object
+- [ ] advance toml config plugin
+ - [ ] add template support, maybe
+ - [ ] add config validation
- [x] compute hmac on the client side
- [x] better handling on form
- [ ] better random numbers
-- [ ] advance ini config plugin
- - [x] allow non-leaf nodes to be arrays
- - [ ] allow quotes
- - [ ] allow continuation over multiple lines
- - [ ] warn about overrides
- - [ ] add template support, maybe
- - [x] switch to TOML or a provided format, as INI is too basic
- - [ ] add config validation
- [ ] improve i18n
- [ ] add localization of dates and time
- [x] refactor I18N plugin to allow independent translate provider
diff --git a/Makefile.PL b/Makefile.PL
index 4a9ce64..aad83b0 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -11,10 +11,12 @@ WriteMakefile(
Config::Tiny => 'v2.24',
Crypt::URandom => 'v0.36',
Digest::HMAC_MD5 => '1.04',
- Email::MIME => 'v1.951',
+ Email::MIME => '1.949',
Mail::Box::Manager => 'v3.9',
Role::Tiny => 'v2.2',
Class::Method::Modifiers => 'v2.13',
+ TOML::Tiny => '0.15',
+ namespace::clean => '',
},
test => {TESTS => 't/*.t'},
)
diff --git a/jwebmail.development.toml b/jwebmail.development.toml
index 3975c9f..7f58015 100644
--- a/jwebmail.development.toml
+++ b/jwebmail.development.toml
@@ -3,11 +3,8 @@ scriptadmin = "me@example.com" # for complaints / support
[i18n]
default_language = "en"
-directory = "lang"
-
-[i18n.languages]
-#en = English
-#de = Deutsch
+directory = "lib/JWebmail/I18N"
+# languages = ["en", "de"]
[model.read.driver.devel.json]
[model.read.driver.devel.maildir]
diff --git a/lib/JWebmail/Controller/Webmail.pm b/lib/JWebmail/Controller/Webmail.pm
index bdd7176..c61c493 100644
--- a/lib/JWebmail/Controller/Webmail.pm
+++ b/lib/JWebmail/Controller/Webmail.pm
@@ -34,7 +34,7 @@ sub auth {
my ($pw, $ch) = $self->session_passwd;
unless ($user && $pw) {
- $self->flash(message => $self->l('no_session'));
+ $self->flash(message => $self->l('No active session.'));
$self->res->code(401);
$self->redirect_to('logout');
return 0;
@@ -95,7 +95,7 @@ sub login {
else {
$self->render(
status => 401,
- warning => $self->l('login') . ' ' . $self->l('failed') . '!',
+ warning => $self->l('Login failed!'),
);
}
}
diff --git a/lib/JWebmail/I18N.pm b/lib/JWebmail/I18N.pm
new file mode 100644
index 0000000..576c413
--- /dev/null
+++ b/lib/JWebmail/I18N.pm
@@ -0,0 +1,16 @@
+package JWebmail::I18N;
+
+use parent 'Locale::Maketext';
+
+
+1
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+JWebmail::L10N - Base class for internationalization
+
+=cut
diff --git a/lib/JWebmail/I18N/de_de.pm b/lib/JWebmail/I18N/de_de.pm
new file mode 100644
index 0000000..637e88f
--- /dev/null
+++ b/lib/JWebmail/I18N/de_de.pm
@@ -0,0 +1,78 @@
+package JWebmail::I18N::de_de;
+
+use v5.22;
+use warnings;
+use utf8;
+
+use parent 'JWebmail::I18N';
+
+
+our %Lexicon = (
+ 'login' => 'anmelden',
+ 'userid' => 'nuzerkennung',
+ 'password' => 'passwort',
+ 'failed' => 'fehlgeschlagen',
+ 'about' => 'über',
+ 'mbox_size' => 'mailboxgröße',
+ # and = und
+ 'subject' => 'betreff',
+ 'version' => 'version',
+ 'from' => 'von',
+ 'to' => 'für',
+ 'cc' => 'cc',
+ 'date' => 'datum',
+ 'size' => 'größe',
+ 'content-type' => 'inhaltsart',
+ 'send to' => 'senden an',
+ 'answer_to' => 'antworten gehen an',
+ 'content' => 'inhalt',
+ 'check_all' => 'alle markieren',
+ 'move' => 'verschieben',
+ 'nr' => 'nummer',
+ 'status' => 'mehrteilig',
+ 'logout' => 'abmelden',
+ 'compose' => 'schreiben',
+ 'search' => 'suche',
+ 'of' => 'von',
+ 'messages' => 'nachrichten',
+ 'new' => 'neu',
+ 'mbox_size' => 'mailboxgröße',
+ 'home' => 'übersicht',
+ 'no' => 'nein',
+ 'yes' => 'ja',
+ 'page' => 'seite',
+ 'next' => 'nächste',
+ 'last' => 'letzte',
+ 'first' => 'erste',
+ 'previous' => 'vorherige',
+ 'sender' => 'gesendet von',
+ 'back' => 'zurück',
+
+ # Mailboxen
+ 'queue' => 'warteschlange',
+ 'drafts' => 'vorlagen',
+ 'home' => 'wurzelverzeichnis',
+
+ # Fehler
+ 'No active session.' => 'Keine aktive Sitzung.',
+ 'Login failed!' => 'Einloggen fehlgeschlagen!',
+
+ 'no_folder' => 'Dieses Verzeichnis gibt es nicht.',
+ 'error_send' => 'Die Nachricht konnte nicht gesendet werden.',
+ 'succ_send' => 'Die Nachricht wurde verschikt.',
+ 'succ_move' => 'Nachrichten wurden verschoben.',
+ 'empty_folder' => 'Dies Verzeichnis ist leer.',
+);
+
+
+1
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+JWebmail::I18N::de_de - German translation of JWebmail
+
+=cut
diff --git a/lib/JWebmail/I18N/en_us.pm b/lib/JWebmail/I18N/en_us.pm
new file mode 100644
index 0000000..22de05e
--- /dev/null
+++ b/lib/JWebmail/I18N/en_us.pm
@@ -0,0 +1,13 @@
+package JWebmail::I18N::en_us;
+
+use v5.22;
+use warnings;
+use utf8;
+
+use parent 'JWebmail::I18N';
+
+
+our %Lexicon = (_AUTO => 1);
+
+
+1
diff --git a/lib/JWebmail/Plugin/I18N2.pm b/lib/JWebmail/Plugin/I18N2.pm
index 9c10c8d..8c57ec5 100644
--- a/lib/JWebmail/Plugin/I18N2.pm
+++ b/lib/JWebmail/Plugin/I18N2.pm
@@ -2,6 +2,59 @@ package JWebmail::Plugin::I18N2;
use Mojo::Base 'Mojolicious::Plugin';
+use List::Util 'any';
+
+
+package JWebmail::Plugin::I18N2::Maketext {
+
+ use JWebmail::I18N;
+ use File::Basename 'fileparse';
+
+ sub new {
+ my $class = shift;
+ my $conf = @_ == 1 ? shift : {@_};
+
+ my $lexica = $conf->{directory} || [fileparse(__FILE__)]->[1] . '../I18N';
+
+ my @languages = keys %{$conf->{languages} // {}};
+
+ unless (@languages) {
+ use autodie;
+
+ opendir(my $dh, $lexica);
+ my @res = grep { /\.pm$/ && -f "$lexica/$_" } readdir $dh;
+ closedir($dh);
+ @languages = map { scalar fileparse $_, '.pm' } @res;
+ }
+
+ my $self = {};
+ for (@languages) {
+ $self->{$_} = JWebmail::I18N->get_handle($_) || die "unable to load language $_";
+ }
+
+ if (my $dl = $conf->{default_language}) {
+ $self->{$dl} = JWebmail::I18N->get_handle($dl) || die "unable to load language $dl";
+ }
+
+ return bless $self, $class;
+ }
+
+ sub languages {
+ my $self = shift;
+ if (@_) {
+ return exists $self->{$_[0]};
+ }
+ return wantarray ? sort keys $self->%* : scalar keys $self->%*;
+ }
+
+ sub translate {
+ my $self = shift;
+ my $lang = shift;
+ my $phrase = shift;
+ return $self->{$lang}->maketext($phrase, @_);
+ }
+
+}
package JWebmail::Plugin::I18N2::Translator {
@@ -12,7 +65,6 @@ package JWebmail::Plugin::I18N2::Translator {
sub new {
my $cls = shift;
my $conf = @_ == 1 ? shift : {@_};
- my $self = {};
my @languages = keys %{$conf->{languages} // {}};
@@ -21,6 +73,7 @@ package JWebmail::Plugin::I18N2::Translator {
}
# load languages
+ my $self = {};
for my $l (@languages) {
if (my $dict = __loadi18n($conf->{directory}, $l)) {
$self->{$l} = $dict;
@@ -110,11 +163,11 @@ sub register {
my $i18n_log = $app->log->context('[' . __PACKAGE__ . ']');
- my $translator = $conf->{translator} || sub { JWebmail::Plugin::I18N2::Translator->new(@_) };
+ my $translator = $conf->{translator} || sub { JWebmail::Plugin::I18N2::Maketext->new(@_) };
my $defaultLang = $conf->{default_language} || 'en';
- my $fileLocation = $conf->{directory} && Mojo::File->new($conf->{directory})->is_abs
- ? $conf->{directory}
- : $app->home->child($conf->{directory} || 'lang');
+ my $fileLocation = $conf->{directory}
+ ? Mojo::File->new($conf->{directory})
+ : $app->home->child('lang');
my $t = $translator->(
default_language => $defaultLang,
@@ -126,6 +179,10 @@ sub register {
local $" = ',';
$i18n_log->info("loaded languages (@{[$t->languages]})");
+ unless (any { $defaultLang eq $_ } $t->languages) {
+ die "default language '$defaultLang' not loaded";
+ }
+
if (keys $conf->{languages}->%* > $t->languages) {
$i18n_log->warn("missing languages");
}
diff --git a/templates/webmail/login.html.ep b/templates/webmail/login.html.ep
index 0b7b080..28768e3 100644
--- a/templates/webmail/login.html.ep
+++ b/templates/webmail/login.html.ep
@@ -21,14 +21,14 @@
%= text_field 'userid' => '' => (required => '')
</div>
<div class="pure-control-group">
- %= label_for password => ucfirst l 'passwd'
+ %= label_for password => ucfirst l 'password'
%= password_field 'password' => (required => '')
</div>
% if ($uses_cram) {
%= hidden_field challenge => rand
% }
<div class="pure-controls">
- %= submit_button l('login') => (class => 'pure-button pure-button-primary') => (name => 'submit_button') => $uses_cram ? (disabled => '') : ()
+ %= submit_button ucfirst l('login') => (class => 'pure-button pure-button-primary') => (name => 'submit_button') => $uses_cram ? (disabled => '') : ()
</div>
</fieldset>
% end