View | Details | Raw Unified | Return to bug 15395
Collapse All | Expand All

(-)a/C4/Installer/PerlDependencies.pm (+5 lines)
Lines 722-727 our $PERL_DEPS = { Link Here
722
        'required' => '1',
722
        'required' => '1',
723
        'min_ver'  => '1.20',
723
        'min_ver'  => '1.20',
724
    },
724
    },
725
    'PPI' => {
726
        'usage'    => 'I18N',
727
        'required' => '0',
728
        'min_ver'  => '1.215',
729
    },
725
    'LWP::Protocol::https' => {
730
    'LWP::Protocol::https' => {
726
        'usage'    => 'OverDrive integration',
731
        'usage'    => 'OverDrive integration',
727
        'required' => '0',
732
        'required' => '0',
(-)a/Koha/Template/Plugin/I18N.pm (+72 lines)
Line 0 Link Here
1
package Koha::Template::Plugin::I18N;
2
3
# Copyright BibLibre 2015
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use base qw( Template::Plugin );
23
24
use C4::Context;
25
use Koha::I18N;
26
27
sub t {
28
    my ($self, $msgid) = @_;
29
    return __($msgid);
30
}
31
32
sub tx {
33
    my ($self, $msgid, $vars) = @_;
34
    return __x($msgid, %$vars);
35
}
36
37
sub tn {
38
    my ($self, $msgid, $msgid_plural, $count) = @_;
39
    return __n($msgid, $msgid_plural, $count);
40
}
41
42
sub tnx {
43
    my ($self, $msgid, $msgid_plural, $count, $vars) = @_;
44
    return __nx($msgid, $msgid_plural, $count, %$vars);
45
}
46
47
sub txn {
48
    my ($self, $msgid, $msgid_plural, $count, $vars) = @_;
49
    return __xn($msgid, $msgid_plural, $count, %$vars);
50
}
51
52
sub tp {
53
    my ($self, $msgctxt, $msgid) = @_;
54
    return __p($msgctxt, $msgid);
55
}
56
57
sub tpx {
58
    my ($self, $msgctxt, $msgid, $vars) = @_;
59
    return __px($msgctxt, $msgid, %$vars);
60
}
61
62
sub tnp {
63
    my ($self, $msgctxt, $msgid, $msgid_plural, $count) = @_;
64
    return __np($msgctxt, $msgid, $msgid_plural, $count);
65
}
66
67
sub tnpx {
68
    my ($self, $msgctxt, $msgid, $msgid_plural, $count, $vars) = @_;
69
    return __np($msgctxt, $msgid, $msgid_plural, $count, %$vars);
70
}
71
72
1;
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/i18n.inc (+39 lines)
Line 0 Link Here
1
[%
2
  USE I18N;
3
4
  MACRO t(msgid) BLOCK;
5
    I18N.t(msgid);
6
  END;
7
8
  MACRO tx(msgid, vars) BLOCK;
9
    I18N.tx(msgid, vars);
10
  END;
11
12
  MACRO tn(msgid, msgid_plural, count) BLOCK;
13
    I18N.tn(msgid, msgid_plural, count);
14
  END;
15
16
  MACRO tnx(msgid, msgid_plural, count, vars) BLOCK;
17
    I18N.tnx(msgid, msgid_plural, count, vars);
18
  END;
19
20
  MACRO txn(msgid, msgid_plural, count, vars) BLOCK;
21
    I18N.txn(msgid, msgid_plural, count, vars);
22
  END;
23
24
  MACRO tp(msgctxt, msgid) BLOCK;
25
    I18N.tp(msgctxt, msgid);
26
  END;
27
28
  MACRO tpx(msgctxt, msgid, vars) BLOCK;
29
    I18N.tpx(msgctxt, msgid, vars);
30
  END;
31
32
  MACRO tnp(msgctxt, msgid, msgid_plural, count) BLOCK;
33
    I18N.tnp(msgctxt, msgid, msgid_plural, count);
34
  END;
35
36
  MACRO tnpx(msgctxt, msgid, msgid_plural, count, vars) BLOCK;
37
    I18N.tnpx(msgctxt, msgid, msgid_plural, count, vars);
38
  END;
39
%]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/i18n.inc (+39 lines)
Line 0 Link Here
1
[%
2
  USE I18N;
3
4
  MACRO t(msgid) BLOCK;
5
    I18N.t(msgid);
6
  END;
7
8
  MACRO tx(msgid, vars) BLOCK;
9
    I18N.tx(msgid, vars);
10
  END;
11
12
  MACRO tn(msgid, msgid_plural, count) BLOCK;
13
    I18N.tn(msgid, msgid_plural, count);
14
  END;
15
16
  MACRO tnx(msgid, msgid_plural, count, vars) BLOCK;
17
    I18N.tnx(msgid, msgid_plural, count, vars);
18
  END;
19
20
  MACRO txn(msgid, msgid_plural, count, vars) BLOCK;
21
    I18N.txn(msgid, msgid_plural, count, vars);
22
  END;
23
24
  MACRO tp(msgctxt, msgid) BLOCK;
25
    I18N.tp(msgctxt, msgid);
26
  END;
27
28
  MACRO tpx(msgctxt, msgid, vars) BLOCK;
29
    I18N.tpx(msgctxt, msgid, vars);
30
  END;
31
32
  MACRO tnp(msgctxt, msgid, msgid_plural, count) BLOCK;
33
    I18N.tnp(msgctxt, msgid, msgid_plural, count);
34
  END;
35
36
  MACRO tnpx(msgctxt, msgid, msgid_plural, count, vars) BLOCK;
37
    I18N.tnpx(msgctxt, msgid, msgid_plural, count, vars);
38
  END;
39
%]
(-)a/misc/translator/LangInstaller.pm (-2 / +82 lines)
Lines 25-31 use C4::Context; Link Here
25
use YAML::Syck qw( Dump LoadFile );
25
use YAML::Syck qw( Dump LoadFile );
26
use Locale::PO;
26
use Locale::PO;
27
use FindBin qw( $Bin );
27
use FindBin qw( $Bin );
28
use File::Basename;
29
use File::Find;
28
use File::Path qw( make_path );
30
use File::Path qw( make_path );
31
use File::Slurp;
32
use File::Temp qw( tempdir );
33
use Template::Parser;
34
use PPI;
29
35
30
$YAML::Syck::ImplicitTyping = 1;
36
$YAML::Syck::ImplicitTyping = 1;
31
37
Lines 502-507 sub update_messages { Link Here
502
    system "$self->{msgmerge} -U $pofile $self->{domain}.pot";
508
    system "$self->{msgmerge} -U $pofile $self->{domain}.pot";
503
}
509
}
504
510
511
sub extract_messages_from_templates {
512
    my ($self, $tempdir, @files) = @_;
513
514
    my $intranetdir = $self->{context}->config('intranetdir');
515
    my @keywords = qw(t tx tn txn tnx tp tpx tnp tnpx);
516
    my $parser = Template::Parser->new();
517
518
    foreach my $file (@files) {
519
        my $template = read_file("$intranetdir/$file");
520
        my $data = $parser->parse($template);
521
        my $document = PPI::Document->new(\$data->{BLOCK});
522
523
        # [% t('foo') %] is compiled to $output .= $stash->get(['t', ['foo']]);
524
        # We try to find all nodes corresponding to keyword (here 't')
525
        my $nodes = $document->find(sub {
526
            my ($topnode, $element) = @_;
527
528
            # Filter out non-valid keywords
529
            return 0 unless ($element->isa('PPI::Token::Quote::Single'));
530
            return 0 unless (grep {$element->content eq qq{'$_'}} @keywords);
531
532
            # keyword (e.g. 't') should be the first element of the arrayref
533
            # passed to $stash->get()
534
            return 0 if $element->sprevious_sibling;
535
536
            return 0 unless $element->snext_sibling
537
                && $element->snext_sibling->snext_sibling
538
                && $element->snext_sibling->snext_sibling->isa('PPI::Structure::Constructor');
539
540
            # Check that it's indeed a call to $stash->get()
541
            my $statement = $element->statement->parent->statement->parent->statement;
542
            return 0 unless grep { $_->isa('PPI::Token::Symbol') && $_->content eq '$stash' } $statement->children;
543
            return 0 unless grep { $_->isa('PPI::Token::Operator') && $_->content eq '->' } $statement->children;
544
            return 0 unless grep { $_->isa('PPI::Token::Word') && $_->content eq 'get' } $statement->children;
545
546
            return 1;
547
        });
548
549
        next unless $nodes;
550
551
        # Write the Perl equivalent of calls to t* functions family, so xgettext
552
        # can extract the strings correctly
553
        make_path(dirname("$tempdir/$file"));
554
        open my $fh, '>', "$tempdir/$file";
555
556
        foreach my $node (@$nodes) {
557
            my @args = map {
558
                $_->significant && !$_->isa('PPI::Token::Operator') ? $_->content : ()
559
            } $node->snext_sibling->snext_sibling->find_first('PPI::Statement')->children;
560
561
            my $keyword = $node->content;
562
            $keyword =~ s/^'t(.*)'$/__$1/;
563
564
            say $fh "$keyword(" . join(', ', @args) . ");";
565
        }
566
567
        close $fh;
568
    }
569
570
    return $tempdir;
571
}
572
505
sub extract_messages {
573
sub extract_messages {
506
    my $self = shift;
574
    my $self = shift;
507
575
Lines 524-534 sub extract_messages { Link Here
524
        }
592
        }
525
    }
593
    }
526
594
595
    my @tt_files;
596
    find(sub {
597
        if ($File::Find::dir =~ m|/en/| && $_ =~ m/\.(tt|inc)$/) {
598
            my $filename = $File::Find::name;
599
            $filename =~ s|^$intranetdir/||;
600
            push @tt_files, $filename;
601
        }
602
    }, "$intranetdir/koha-tmpl");
603
604
    my $tempdir = tempdir('Koha-translate-XXXX', TMPDIR => 1, CLEANUP => 1);
605
    $self->extract_messages_from_templates($tempdir, @tt_files);
606
    push @files_to_scan, @tt_files;
607
527
    my $xgettext_cmd = "$self->{xgettext} -L Perl --from-code=UTF-8 "
608
    my $xgettext_cmd = "$self->{xgettext} -L Perl --from-code=UTF-8 "
528
        . "-k -k__ -k__x -k__n:1,2 -k__nx:1,2 -k__xn:1,2 -k__p:1c,2 "
609
        . "-k -k__ -k__x -k__n:1,2 -k__nx:1,2 -k__xn:1,2 -k__p:1c,2 "
529
        . "-k__px:1c,2 -k__np:1c,2,3 -k__npx:1c,2,3 -kN__ -kN__n:1,2 "
610
        . "-k__px:1c,2 -k__np:1c,2,3 -k__npx:1c,2,3 -kN__ -kN__n:1,2 "
530
        . "-kN__p:1c,2 -kN__np:1c,2,3 "
611
        . "-kN__p:1c,2 -kN__np:1c,2,3 "
531
        . "-o $Bin/$self->{domain}.pot -D $intranetdir";
612
        . "-o $Bin/$self->{domain}.pot -D $tempdir -D $intranetdir";
532
    $xgettext_cmd .= " $_" foreach (@files_to_scan);
613
    $xgettext_cmd .= " $_" foreach (@files_to_scan);
533
614
534
    if (system($xgettext_cmd) != 0) {
615
    if (system($xgettext_cmd) != 0) {
535
- 

Return to bug 15395