- Clone all 5 Zonemaster component repos (LDNS, Engine, CLI, Backend, GUI) - Dockerfile.backend: 8-stage multi-stage build LDNS→Engine→CLI→Backend - Dockerfile.gui: Astro static build served via nginx - docker-compose.yml: backend (internal) + frontend (port 5353) - nginx.conf: root redirects to /es/, /api/ proxied to backend - zonemaster-gui/config.ts: defaultLanguage set to 'es' (Spanish) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
2.6 KiB
Perl
Executable File
111 lines
2.6 KiB
Perl
Executable File
#!/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
|