144 lines
3 KiB
Perl
Executable file
144 lines
3 KiB
Perl
Executable file
#!/usr/bin/env perl
|
|
use strict;
|
|
use warnings;
|
|
use YAML::Syck qw(LoadFile);
|
|
use Test::Differences;
|
|
use Pod::Usage ();
|
|
use Getopt::Long ();
|
|
|
|
=head1 NAME
|
|
|
|
locale-diff - Compare two YAML files and print how their datastructures differ
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
diff en.yml is.yml
|
|
# --keys is the default
|
|
diff --keys en.yml is.yml
|
|
# --untranslated-values compares prints keys whose values don't differ
|
|
diff --untranslated-values en.yml is.yml
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This utility prints the differences between two YAML files using
|
|
L<Test::Differences>. The purpose of it is to diff the files is
|
|
F<config/locales> to find out what keys need to be added to the
|
|
translated files when F<en.yml> changes.
|
|
|
|
=head1 OPTIONS
|
|
|
|
=over
|
|
|
|
=item -h, --help
|
|
|
|
Print this help message.
|
|
|
|
=item --keys
|
|
|
|
Show the hash keys that differ between the two files, useful merging
|
|
new entries from F<en.yml> to a local file.
|
|
|
|
=item --untranslated-values
|
|
|
|
Show keys whose values are either exactly the same between the two
|
|
files, or don't exist in the target file (the latter file specified).
|
|
|
|
This helps to find untranslated values.
|
|
|
|
=back
|
|
|
|
=head1 AUTHOR
|
|
|
|
E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@f-prot.com>
|
|
|
|
=cut
|
|
|
|
# Get the command-line options
|
|
Getopt::Long::Parser->new(
|
|
config => [ qw< bundling no_ignore_case no_require_order pass_through > ],
|
|
)->getoptions(
|
|
'h|help' => \my $help,
|
|
'keys' => \my $keys,
|
|
'untranslated-values' => \my $untranslated_values,
|
|
) or help();
|
|
|
|
# On --help
|
|
help() if $help;
|
|
|
|
# If we're not given two .yml files
|
|
help() if @ARGV != 2 or (!-f $ARGV[0] or !-f $ARGV[1]);
|
|
|
|
my ($from, $to) = @ARGV;
|
|
|
|
my $from_data = LoadFile($from);
|
|
my $to_data = LoadFile($to);
|
|
|
|
my $from_parsed = { iterate($from_data->{basename($from)}) };
|
|
my $to_parsed = { iterate($to_data->{basename($to)}) };
|
|
|
|
# Since this used to be the default, support that...
|
|
if ((not $untranslated_values and not $keys) or $keys)
|
|
{
|
|
print_key_differences();
|
|
}
|
|
elsif ($untranslated_values)
|
|
{
|
|
my @untranslated = untranslated_keys($from_parsed, $to_parsed);
|
|
|
|
print $_, "\n" for @untranslated;
|
|
}
|
|
|
|
exit 0;
|
|
|
|
sub print_key_differences
|
|
{
|
|
# Hack around Test::Differences wanting a Test::* module loaded
|
|
$INC{"Test.pm"} = 1;
|
|
sub Test::ok { print shift }
|
|
|
|
# Diff the tree
|
|
eq_or_diff([ sort keys %$from_parsed ], [ sort keys %$to_parsed ]);
|
|
}
|
|
|
|
sub untranslated_keys
|
|
{
|
|
my ($from_parsed, $to_parsed) = @_;
|
|
sort grep { not exists $to_parsed->{$_} or $from_parsed->{$_} eq $to_parsed->{$_} } keys %$from_parsed;
|
|
}
|
|
|
|
sub iterate
|
|
{
|
|
my ($hash, @path) = @_;
|
|
my @ret;
|
|
|
|
while (my ($k, $v) = each %$hash)
|
|
{
|
|
if (ref $v eq 'HASH')
|
|
{
|
|
push @ret => iterate($v, @path, $k);
|
|
}
|
|
else
|
|
{
|
|
push @ret => join(".",@path, $k), $v;
|
|
}
|
|
}
|
|
|
|
return @ret;
|
|
}
|
|
|
|
sub basename
|
|
{
|
|
my $name = shift;
|
|
$name =~ s[\..*?$][];
|
|
$name;
|
|
}
|
|
|
|
sub help
|
|
{
|
|
my %arg = @_;
|
|
|
|
Pod::Usage::pod2usage(
|
|
-verbose => $arg{ verbose },
|
|
-exitval => $arg{ exitval } || 0,
|
|
);
|
|
}
|