po-php.pl 5.09 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#!/usr/bin/perl -w

# Takes a Mahara .po file generated by php-po.php, and converts it
# into a Mahara language pack containing help files (html) and string
# files (php).

# Assumes the .po reference comments contain either an html filename
# or a php filename followed by a space and a mahara language string
# key.

# po-php.pl /path/to/po/files/fr-1.3_STABLE.po /path/to/langpacks/fr.utf8 fr.utf8

13
use File::Path qw(mkpath);
14 15
use File::Basename qw(fileparse);
use Locale::PO;
Richard Mansfield's avatar
Richard Mansfield committed
16
use FindBin;
17 18 19 20 21 22 23 24

my ($inputfile, $outputdir, $lang) = @ARGV;

my $strings = Locale::PO->load_file_asarray($inputfile);

my %htmlfiles = ();
my %phpfiles = ();

Richard Mansfield's avatar
Richard Mansfield committed
25 26
my $plural = undef;

27 28
foreach my $po (@$strings) {
    my $content = $po->msgstr();
Richard Mansfield's avatar
Richard Mansfield committed
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    my $content_n = $po->msgstr_n();
    next if ( ! defined $content  && ! defined $content_n );

    if ( defined $content ) {
        # A normal, non-pluralised translation
        $content =~ s{\\n}{\n}g;
        next if ( $content eq '' || $content eq '""' );
    }
    if ( defined $content_n ) {
        # A translation with multiple plural forms
        my $anything = 0;
        foreach my $k ( keys %$content_n ) {
            $content_n->{$k} =~ s{\\n}{\n}g;
            $anything ||= ($content_n->{$k} ne '' && $content_n->{$k} ne '""');
        }
        next if ! $anything;
    }

47
    my $reference = $po->reference();
Richard Mansfield's avatar
Richard Mansfield committed
48 49 50 51 52 53 54 55 56 57 58 59 60

    if ( ! defined $reference ) {
        # Look for "Plural-Forms:" po header
        if ( ! defined $plural ) {
            my $msgid = $po->msgid();
            next if ( defined $msgid && $msgid ne '""' && $msgid ne '' );
            if ( $content =~ m{\nPlural-Forms:\s*nplurals\s*=\s*\d+\s*;\s*plural\s*=\s*(.+?)[\s;]*\n} ) {
                $plural = $1;
            }
        }
        next;
    }

61
    if ($reference =~ m{^(\S*lang/)\S+\.utf8(/\S+)\.html$}) {
62
        my $filename = $1 . $lang . $2 . '.html';
63 64 65 66 67
        # $content =~ $po->dequote($content);
        # dequote won't do multiline strings
        $content =~ s{^"(.*)"$}{$1}s;
        $content =~ s{\\"}{"}gs;
        $htmlfiles{$filename} = $content;
68
    }
69
    elsif ($reference =~ m{^(\S*lang/)\S+\.utf8(/\S+)\.php\s+(\S+)$}) {
70 71
        my $key = $3;
        my $filename = $1 . $lang . $2 . '.php';
Richard Mansfield's avatar
Richard Mansfield committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

        # Some things in langconfig.php are fairly meta, and probably
        # shouldn't form part of the translation.  For now, just
        # remove pluralrule & pluralfunction - we'll overwrite them
        # based on the Plural-Forms: header, or the hardcoded list.
        if ($2 eq 'langconfig' && ($key eq 'pluralrule' || $key eq 'pluralfunction')) {
            next;
        }

        # Normal non-plural string.
        if ( defined $content ) {
            $phpfiles{$filename}->{$key}->{msgstr} = fixquotes($content);
            next;
        }

        # Plural forms (in $content_n)
        $phpfiles{$filename}->{$key}->{msgstr_n} = {};
        foreach my $k ( keys %$content_n ) {
            $phpfiles{$filename}->{$key}->{msgstr_n}->{$k} = fixquotes($content_n->{$k});
91
        }
92 93 94 95 96 97
    }
}

foreach my $htmlfile (keys %htmlfiles) {
    my ($filename, $subdir, $suffix) = fileparse($htmlfile);
    my $dir = $outputdir . '/' . $subdir;
98
    mkpath($dir);
99 100 101 102 103 104 105 106
    open(my $fh, '>', "$dir/$filename");
    print $fh $htmlfiles{$htmlfile};
    close $fh;
}

foreach my $phpfile (keys %phpfiles) {
    my ($filename, $subdir, $suffix) = fileparse($phpfile);
    my $dir = $outputdir . '/' . $subdir;
107
    mkpath($dir);
108 109 110
    open(my $fh, '>', "$dir/$filename");
    print $fh "<?php\n\ndefined('INTERNAL') || die();\n\n";
    foreach my $key (sort keys %{$phpfiles{$phpfile}}) {
Richard Mansfield's avatar
Richard Mansfield committed
111 112 113 114 115 116 117 118 119 120
        if ( $phpfiles{$phpfile}->{$key}->{msgstr} ) {
            print $fh "\$string['$key'] = " . $phpfiles{$phpfile}->{$key}->{msgstr} . ";\n";
        }
        elsif ( $phpfiles{$phpfile}->{$key}->{msgstr_n} ) {
            print $fh "\$string['$key'] = array(\n";
            foreach my $k ( sort keys %{$phpfiles{$phpfile}->{$key}->{msgstr_n}} ) {
                print $fh "    $k => $phpfiles{$phpfile}->{$key}->{msgstr_n}->{$k},\n";
            }
            print $fh ");\n";
        }
121 122 123 124
    }
    close $fh;
}

Richard Mansfield's avatar
Richard Mansfield committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
# Write plural forms into langconfig.php
my $langshort = $lang;
$langshort =~ s/^([a-zA-Z_]+)\.utf8/$1/;

if ( ! defined $plural ) {
    # If there was no "Plural-Forms:" po header, read plural forms
    # rule from hardcoded list in pluralforms.pl
    open (my $fh, '<', "perl $FindBin::Bin/pluralforms.pl $langshort");
    $plural = <$fh>;
    close $fh;
}

if ( defined $plural && $plural =~ m/\S+/ ) {
    open(my $fh, '>>', "$outputdir/lang/$lang/langconfig.php");
    $plural =~ s{[']+}{}g;
    my $pluralphp = $plural;
    $pluralphp =~ s{n}{\$n}g;
    print $fh <<EOF;
143

Richard Mansfield's avatar
Richard Mansfield committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
// Plural forms, added by language pack generator
\$string['pluralrule'] = '$plural';
\$string['pluralfunction'] = 'plural_${langshort}_utf8';
function plural_${langshort}_utf8(\$n) {
    return $pluralphp;
}
EOF
    close $fh;
}

sub fixquotes {
    my $content = shift;
    # Output with single quotes or variables get interpolated
    if ( $content =~ m{^".*"$}s ) {
        $content =~ s{'}{\\'}gs;
        $content =~ s{^"(.*)"$}{'$1'}s;
        $content =~ s{\\"}{"}gs;
    }
    return $content;
}