#! /usr/bin/perl # The copyright notice and license are in the POD at the bottom. use strict; use warnings; use Locale::PO qw(); use Getopt::Long qw(GetOptions :config bundling gnu_compat); use autouse 'Pod::Usage' => qw(pod2usage); my $VERSION = "1.1"; sub show_version { print "check-accelerator-conflicts.pl $VERSION\n"; pod2usage({-verbose => 99, -sections => "COPYRIGHT AND LICENSE", -exitval => 0}); } my $Accelerator_tag; sub check_po_file ($) { my($po_file_name) = @_; my %contexts; my $warnings = 0; my $pos = do { # Locale::PO 0.16 doesn't understand "#~" obsolete lines and # spews warnings. local $SIG{__WARN__} = sub {}; Locale::PO->load_file_asarray($po_file_name) or warn "$po_file_name: $!\n", return 2; }; foreach my $po (@$pos) { next if $po->fuzzy(); my $msgstr = $po->msgstr() or next; my($accelerator) = ($msgstr =~ /\Q$Accelerator_tag\E(.)/s) or next; $accelerator = uc($accelerator); my $automatic = $po->automatic() or next; my($contexts) = ($automatic =~ /^accelerator_context\(([^\)]*)\)/) or next; foreach my $context (split(/\s*,\s*/, $contexts)) { my $prev = $contexts{$context}{$accelerator}; if (defined($prev)) { warn "$po_file_name: Accelerator conflict for \"$accelerator\" in \"$context\":\n"; warn "$po_file_name: 1st msgid " . $prev->msgid() . "\n"; warn "$po_file_name: 1st msgstr " . $prev->msgstr() . "\n"; warn "$po_file_name: 2nd msgid " . $po->msgid() . "\n"; warn "$po_file_name: 2nd msgstr " . $po->msgstr() . "\n"; $warnings++; } else { $contexts{$context}{$accelerator} = $po; } } } return $warnings ? 1 : 0; } GetOptions("accelerator-tag=s" => sub { my($option, $value) = @_; die "Cannot use multiple --accelerator-tag options\n" if defined($Accelerator_tag); die "--accelerator-tag requires a single-character argument\n" if length($value) != 1; $Accelerator_tag = $value; }, "help" => sub { pod2usage({-verbose => 1, -exitval => 0}) }, "version" => \&show_version) or exit 2; $Accelerator_tag = "~" unless defined $Accelerator_tag; print(STDERR "$0: missing file operand\n"), exit 2 unless @ARGV; my $max_error = 0; foreach my $po_file_name (@ARGV) { my $error = check_po_file($po_file_name); $max_error = $error if $error > $max_error; } exit $max_error; __END__ =head1 NAME check-accelerator-conflicts.pl - Scan a PO file for conflicting accelerator keys. =head1 SYNOPSIS B [I