2017-05-27 17:47:15 +02:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use Cwd 'abs_path';
|
|
|
|
|
|
|
|
# script which checks how out of sync the i18ns are drifting
|
|
|
|
|
|
|
|
# example i18n format:
|
|
|
|
# "%(oneUser)sleft": "%(oneUser)sleft",
|
|
|
|
|
|
|
|
$|=1;
|
|
|
|
|
|
|
|
$0 =~ /^(.*\/)/;
|
|
|
|
my $i18ndir = abs_path($1."/../src/i18n/strings");
|
2017-05-27 18:13:17 +02:00
|
|
|
my $srcdir = abs_path($1."/../src");
|
|
|
|
|
2017-05-27 17:47:15 +02:00
|
|
|
my $en = read_i18n($i18ndir."/en_EN.json");
|
|
|
|
|
2017-05-27 18:13:17 +02:00
|
|
|
my $src_strings = read_src_strings($srcdir);
|
2017-05-27 19:35:34 +02:00
|
|
|
my $src = {};
|
2017-05-27 18:13:17 +02:00
|
|
|
|
|
|
|
print "Checking strings in src\n";
|
2017-05-27 18:27:58 +02:00
|
|
|
foreach my $tuple (@$src_strings) {
|
|
|
|
my ($s, $file) = (@$tuple);
|
2017-05-27 19:35:34 +02:00
|
|
|
$src->{$s} = $file;
|
2017-05-27 18:13:17 +02:00
|
|
|
if (!$en->{$s}) {
|
|
|
|
if ($en->{$s . '.'}) {
|
2017-05-27 18:27:58 +02:00
|
|
|
printf ("%50s %24s\t%s\n", $file, "en_EN has fullstop!", $s);
|
2017-05-27 18:13:17 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
$s =~ /^(.*)\.?$/;
|
|
|
|
if ($en->{$1}) {
|
2017-05-27 18:27:58 +02:00
|
|
|
printf ("%50s %24s\t%s\n", $file, "en_EN lacks fullstop!", $s);
|
2017-05-27 18:13:17 +02:00
|
|
|
}
|
|
|
|
else {
|
2017-05-27 18:27:58 +02:00
|
|
|
printf ("%50s %24s\t%s\n", $file, "Translation missing!", $s);
|
2017-05-27 18:13:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-27 19:35:34 +02:00
|
|
|
print "\nChecking en_EN\n";
|
|
|
|
my $count = 0;
|
2017-05-27 20:03:26 +02:00
|
|
|
my $remaining_src = {};
|
|
|
|
foreach (keys %$src) { $remaining_src->{$_}++ };
|
|
|
|
|
2017-05-27 19:35:34 +02:00
|
|
|
foreach my $k (sort keys %$en) {
|
2017-05-27 19:38:37 +02:00
|
|
|
# crappy heuristic to ignore country codes for now...
|
|
|
|
next if ($k =~ /^(..|..-..)$/);
|
2017-05-27 21:14:52 +02:00
|
|
|
|
|
|
|
if ($en->{$k} ne $k) {
|
|
|
|
printf ("%50s %24s\t%s\n", "en_EN", "en_EN is not symmetrical", $k);
|
|
|
|
}
|
|
|
|
|
2017-05-27 19:35:34 +02:00
|
|
|
if (!$src->{$k}) {
|
|
|
|
if ($src->{$k. '.'}) {
|
|
|
|
printf ("%50s %24s\t%s\n", $src->{$k. '.'}, "src has fullstop!", $k);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$k =~ /^(.*)\.?$/;
|
|
|
|
if ($src->{$1}) {
|
|
|
|
printf ("%50s %24s\t%s\n", $src->{$1}, "src lacks fullstop!", $k);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf ("%50s %24s\t%s\n", '???', "Not present in src?", $k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$count++;
|
2017-05-27 20:03:26 +02:00
|
|
|
delete $remaining_src->{$k};
|
2017-05-27 19:35:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
printf ("$count/" . (scalar keys %$src) . " strings found in src are present in en_EN\n");
|
2017-05-27 20:03:26 +02:00
|
|
|
foreach (keys %$remaining_src) {
|
2017-05-27 21:14:52 +02:00
|
|
|
print "missing: $_\n";
|
2017-05-27 20:03:26 +02:00
|
|
|
}
|
2017-05-27 19:35:34 +02:00
|
|
|
|
2017-05-27 17:47:15 +02:00
|
|
|
opendir(DIR, $i18ndir) || die $!;
|
|
|
|
my @files = readdir(DIR);
|
|
|
|
closedir(DIR);
|
2017-05-27 19:41:43 +02:00
|
|
|
foreach my $lang (grep { -f "$i18ndir/$_" && !/(basefile|en_EN)\.json/ } @files) {
|
2017-05-27 17:47:15 +02:00
|
|
|
print "\nChecking $lang\n";
|
|
|
|
|
|
|
|
my $map = read_i18n($i18ndir."/".$lang);
|
|
|
|
my $count = 0;
|
|
|
|
|
2017-05-27 20:03:26 +02:00
|
|
|
my $remaining_en = {};
|
|
|
|
foreach (keys %$en) { $remaining_en->{$_}++ };
|
|
|
|
|
2017-05-27 17:47:15 +02:00
|
|
|
foreach my $k (sort keys %$map) {
|
2017-05-27 21:14:52 +02:00
|
|
|
{
|
|
|
|
no warnings 'uninitialized';
|
|
|
|
my $vars = {};
|
|
|
|
while ($k =~ /%\((.*?)\)s/g) {
|
|
|
|
$vars->{$1}++;
|
|
|
|
}
|
|
|
|
while ($map->{$k} =~ /%\((.*?)\)s/g) {
|
|
|
|
$vars->{$1}--;
|
|
|
|
}
|
|
|
|
foreach my $var (keys %$vars) {
|
|
|
|
if ($vars->{$var} != 0) {
|
|
|
|
printf ("%10s %24s\t%s\n", $lang, "Broken var ($var)s", $k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:47:15 +02:00
|
|
|
if ($en->{$k}) {
|
|
|
|
if ($map->{$k} eq $k) {
|
2017-05-27 19:35:34 +02:00
|
|
|
printf ("%10s %24s\t%s\n", $lang, "Untranslated string?", $k);
|
2017-05-27 17:47:15 +02:00
|
|
|
}
|
|
|
|
$count++;
|
2017-05-27 20:03:26 +02:00
|
|
|
delete $remaining_en->{$k};
|
2017-05-27 17:47:15 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ($en->{$k . "."}) {
|
2017-05-27 19:35:34 +02:00
|
|
|
printf ("%10s %24s\t%s\n", $lang, "en_EN has fullstop!", $k);
|
2017-05-27 17:47:15 +02:00
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
$k =~ /^(.*)\.?$/;
|
|
|
|
if ($en->{$1}) {
|
2017-05-27 19:35:34 +02:00
|
|
|
printf ("%10s %24s\t%s\n", $lang, "en_EN lacks fullstop!", $k);
|
2017-05-27 17:47:15 +02:00
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2017-05-27 19:35:34 +02:00
|
|
|
printf ("%10s %24s\t%s\n", $lang, "Not present in en_EN", $k);
|
2017-05-27 17:47:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-27 20:03:26 +02:00
|
|
|
if (scalar keys %$remaining_en < 100) {
|
|
|
|
foreach (keys %$remaining_en) {
|
|
|
|
printf ("%10s %24s\t%s\n", $lang, "Not yet translated", $_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:47:15 +02:00
|
|
|
printf ("$count/" . (scalar keys %$en) . " strings translated\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_i18n {
|
|
|
|
my $path = shift;
|
|
|
|
my $map = {};
|
2017-05-28 22:28:11 +02:00
|
|
|
$path =~ /.*\/(.*)$/;
|
|
|
|
my $lang = $1;
|
2017-05-27 17:47:15 +02:00
|
|
|
|
|
|
|
open(FILE, "<", $path) || die $!;
|
|
|
|
while(<FILE>) {
|
|
|
|
if ($_ =~ m/^(\s+)"(.*?)"(: *)"(.*?)"(,?)$/) {
|
|
|
|
my ($indent, $src, $colon, $dst, $comma) = ($1, $2, $3, $4, $5);
|
2017-05-27 18:36:02 +02:00
|
|
|
$src =~ s/\\"/"/g;
|
|
|
|
$dst =~ s/\\"/"/g;
|
2017-05-28 22:28:11 +02:00
|
|
|
|
|
|
|
if ($map->{$src}) {
|
|
|
|
printf ("%10s %24s\t%s\n", $lang, "Duplicate translation!", $src);
|
|
|
|
}
|
2017-05-27 17:47:15 +02:00
|
|
|
$map->{$src} = $dst;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(FILE);
|
|
|
|
|
|
|
|
return $map;
|
2017-05-27 18:13:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub read_src_strings {
|
|
|
|
my $path = shift;
|
|
|
|
|
|
|
|
use File::Find;
|
|
|
|
use File::Slurp;
|
|
|
|
|
|
|
|
my $strings = [];
|
|
|
|
|
|
|
|
my @files;
|
|
|
|
find( sub { push @files, $File::Find::name if (-f $_ && /\.jsx?$/) }, $path );
|
|
|
|
foreach my $file (@files) {
|
|
|
|
my $src = read_file($file);
|
2017-05-27 19:20:35 +02:00
|
|
|
$src =~ s/'\s*\+\s*'//g;
|
|
|
|
$src =~ s/"\s*\+\s*"//g;
|
|
|
|
|
2017-05-27 18:27:58 +02:00
|
|
|
$file =~ s/^.*\/src/src/;
|
2017-06-01 02:17:39 +02:00
|
|
|
while ($src =~ /_t(?:Jsx)?\(\s*'(.*?[^\\])'/sg) {
|
2017-05-27 18:13:17 +02:00
|
|
|
my $s = $1;
|
|
|
|
$s =~ s/\\'/'/g;
|
2017-05-27 18:27:58 +02:00
|
|
|
push @$strings, [$s, $file];
|
2017-05-27 18:13:17 +02:00
|
|
|
}
|
2017-06-01 02:17:39 +02:00
|
|
|
while ($src =~ /_t(?:Jsx)?\(\s*"(.*?[^\\])"/sg) {
|
2017-05-27 18:27:58 +02:00
|
|
|
push @$strings, [$1, $file];
|
2017-05-27 18:13:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $strings;
|
2017-05-27 17:47:15 +02:00
|
|
|
}
|