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

(-)a/C4/Installer/PerlDependencies.pm (+5 lines)
Lines 727-732 our $PERL_DEPS = { Link Here
727
        'required' => '1',
727
        'required' => '1',
728
        'min_ver'  => '1.20',
728
        'min_ver'  => '1.20',
729
    },
729
    },
730
    'PPI' => {
731
        'usage'    => 'I18N',
732
        'required' => '0',
733
        'min_ver'  => '1.215',
734
    },
730
    'LWP::Protocol::https' => {
735
    'LWP::Protocol::https' => {
731
        'usage'    => 'OverDrive integration',
736
        'usage'    => 'OverDrive integration',
732
        'required' => '0',
737
        '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 507-512 sub update_messages { Link Here
507
    system "$self->{msgmerge} -U $pofile $self->{domain}.pot";
513
    system "$self->{msgmerge} -U $pofile $self->{domain}.pot";
508
}
514
}
509
515
516
sub extract_messages_from_templates {
517
    my ($self, $tempdir, @files) = @_;
518
519
    my $intranetdir = $self->{context}->config('intranetdir');
520
    my @keywords = qw(t tx tn txn tnx tp tpx tnp tnpx);
521
    my $parser = Template::Parser->new();
522
523
    foreach my $file (@files) {
524
        my $template = read_file("$intranetdir/$file");
525
        my $data = $parser->parse($template);
526
        my $document = PPI::Document->new(\$data->{BLOCK});
527
528
        # [% t('foo') %] is compiled to $output .= $stash->get(['t', ['foo']]);
529
        # We try to find all nodes corresponding to keyword (here 't')
530
        my $nodes = $document->find(sub {
531
            my ($topnode, $element) = @_;
532
533
            # Filter out non-valid keywords
534
            return 0 unless ($element->isa('PPI::Token::Quote::Single'));
535
            return 0 unless (grep {$element->content eq qq{'$_'}} @keywords);
536
537
            # keyword (e.g. 't') should be the first element of the arrayref
538
            # passed to $stash->get()
539
            return 0 if $element->sprevious_sibling;
540
541
            return 0 unless $element->snext_sibling
542
                && $element->snext_sibling->snext_sibling
543
                && $element->snext_sibling->snext_sibling->isa('PPI::Structure::Constructor');
544
545
            # Check that it's indeed a call to $stash->get()
546
            my $statement = $element->statement->parent->statement->parent->statement;
547
            return 0 unless grep { $_->isa('PPI::Token::Symbol') && $_->content eq '$stash' } $statement->children;
548
            return 0 unless grep { $_->isa('PPI::Token::Operator') && $_->content eq '->' } $statement->children;
549
            return 0 unless grep { $_->isa('PPI::Token::Word') && $_->content eq 'get' } $statement->children;
550
551
            return 1;
552
        });
553
554
        next unless $nodes;
555
556
        # Write the Perl equivalent of calls to t* functions family, so xgettext
557
        # can extract the strings correctly
558
        make_path(dirname("$tempdir/$file"));
559
        open my $fh, '>', "$tempdir/$file";
560
561
        foreach my $node (@$nodes) {
562
            my @args = map {
563
                $_->significant && !$_->isa('PPI::Token::Operator') ? $_->content : ()
564
            } $node->snext_sibling->snext_sibling->find_first('PPI::Statement')->children;
565
566
            my $keyword = $node->content;
567
            $keyword =~ s/^'t(.*)'$/__$1/;
568
569
            say $fh "$keyword(" . join(', ', @args) . ");";
570
        }
571
572
        close $fh;
573
    }
574
575
    return $tempdir;
576
}
577
510
sub extract_messages {
578
sub extract_messages {
511
    my $self = shift;
579
    my $self = shift;
512
580
Lines 529-539 sub extract_messages { Link Here
529
        }
597
        }
530
    }
598
    }
531
599
600
    my @tt_files;
601
    find(sub {
602
        if ($File::Find::dir =~ m|/en/| && $_ =~ m/\.(tt|inc)$/) {
603
            my $filename = $File::Find::name;
604
            $filename =~ s|^$intranetdir/||;
605
            push @tt_files, $filename;
606
        }
607
    }, "$intranetdir/koha-tmpl");
608
609
    my $tempdir = tempdir('Koha-translate-XXXX', TMPDIR => 1, CLEANUP => 1);
610
    $self->extract_messages_from_templates($tempdir, @tt_files);
611
    push @files_to_scan, @tt_files;
612
532
    my $xgettext_cmd = "$self->{xgettext} -L Perl --from-code=UTF-8 "
613
    my $xgettext_cmd = "$self->{xgettext} -L Perl --from-code=UTF-8 "
533
        . "-k -k__ -k__x -k__n:1,2 -k__nx:1,2 -k__xn:1,2 -k__p:1c,2 "
614
        . "-k -k__ -k__x -k__n:1,2 -k__nx:1,2 -k__xn:1,2 -k__p:1c,2 "
534
        . "-k__px:1c,2 -k__np:1c,2,3 -k__npx:1c,2,3 -kN__ -kN__n:1,2 "
615
        . "-k__px:1c,2 -k__np:1c,2,3 -k__npx:1c,2,3 -kN__ -kN__n:1,2 "
535
        . "-kN__p:1c,2 -kN__np:1c,2,3 "
616
        . "-kN__p:1c,2 -kN__np:1c,2,3 "
536
        . "-o $Bin/$self->{domain}.pot -D $intranetdir";
617
        . "-o $Bin/$self->{domain}.pot -D $tempdir -D $intranetdir";
537
    $xgettext_cmd .= " $_" foreach (@files_to_scan);
618
    $xgettext_cmd .= " $_" foreach (@files_to_scan);
538
619
539
    if (system($xgettext_cmd) != 0) {
620
    if (system($xgettext_cmd) != 0) {
540
- 

Return to bug 15395