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

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

Return to bug 15395