#!/usr/bin/env perl use utf8; use strict; use warnings; use open qw(:std :utf8); use feature 'say'; use Locale::PO; use Try::Tiny; use Getopt::Long qw( GetOptions ); use Pod::Usage qw( pod2usage ); sub extract_perl_braces { my $string = shift; # Strip text before the first and after the last brace $string =~ s/^[^{]*{?|}?[^}]*$//g; # Extract the fields my @fields = split /}[^{]*{/, $string; return @fields; } sub diff_perl_braces { my $got_string = shift // die 'undefined value for $got_string'; my $expected_string = shift // die 'undefined value for $expected_string'; my %got_fields = map { $_ => 1 } extract_perl_braces( $got_string ); my %expected_fields = map { $_ => 1 } extract_perl_braces( $expected_string ); my %missing = %expected_fields; delete @missing{ keys %got_fields }; my %extra = %got_fields; delete @extra{ keys %expected_fields }; return [ sort keys %missing ], [ sort keys %extra ]; } sub check_perl_braces { my $po = shift; my $filename = shift; my $msgid = $po->dequote( $po->msgid ); my $msgstr = $po->dequote( $po->msgstr ); my ( $missing, $extra ) = diff_perl_braces( $msgstr, $msgid ); if ( @{$missing} or @{$extra} ) { say ""; say '# ' . $filename . ' line ' . $po->loaded_line_number; print map { "#. $_\n" } split /\n/, $po->automatic // ''; say "msgid ", $po->msgid; say "msgstr ", $po->msgstr; for my $field ( @{$missing} ) { say " Only in msgid: {$field}"; } for my $field ( @{$extra} ) { say " Only in msgstr: {$field}"; } } return; } my $opt_help = 0; my $opt_man = 0; GetOptions( "help|h" => \$opt_help, "man" => \$opt_man, ) or pod2usage( 2 ); pod2usage( 1 ) if $opt_help; pod2usage( -verbose => 2 ) if $opt_man; for my $filename ( @ARGV ) { my $aref = Locale::PO->load_file_asarray( $filename, 'UTF-8' ) // die "Failed to load PO file '$filename'"; for my $po ( @$aref ) { try { if ( $po->has_flag( 'perl-brace-format' ) ) { check_perl_braces( $po, $filename ); } } catch { say STDERR "error processing $filename at line " . $po->loaded_line_number . ": " . $_; exit 1; }; } } =head1 NAME check-msg-args - Verify that PO files have the same args in the msgid and msgstr of their perl-brace-format messages =head1 SYNOPSIS check-msg-args [options] [file ...] =head1 OPTIONS =over 4 =item B<--help> Print a brief help message and exit. =item B<--man> Print the manual page and exit. =back