
При использовании интернационализации в своем проекте на spring через MessageSource вы можете столкнуться с неприятной ситуацией: в коде используется какое-то сообщение, но в property файле его нет. К примеру, удалили, забыли закоммитить или допустили опечатку (как намеренно сделал я в примере далее). В этом случае сборка не завалится и только после запуска вы получите блокирующий баг из-за исключения вида:
org.springframework.context.NoSuchMessageException: No message found under code 'сard.Dialog.windowTtle' for locale 'ru'. - опечатка в слове Title.
Я решил написать скрипт на perl, который сделал частью процесса сборки - сразу после скачивания (check out) из репозитория. Таким образом я уменьшаю цену нахождения и исправления ошибки - чем раньше, тем лучше. Скрипт возвращает 1 в случае найденных ошибок или 0, когда в исходниках все правильно. В случае ошибок вы получите такой отчет:
field.lengthExceeded not found in messages_ru.properties
field.lengthExceeded not found in messages_en.properties
card.fullFileName not found in messages_en.properties
Вот его код:
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my @usages = ();
my @ru_messages = ();
my @en_messages = ();
sub process_java_file {
return unless -f ;
my $filename = $File::Find::name;
open my $info, $filename or die "Could not open $filename: $!";
while( my $line = <$info>) {
while($line =~ /messageSource\.\s*getMessage\s*\(\s*"([^"]*)/g) {
unless ($1 ~~ @usages) {
push @usages, $1;
}
}
}
}
sub process_message_file {
my $filename = $_[0];
my @list = ();
open my $message_file, $filename or die "Could not open $filename: $!";
while( my $line = <$message_file>) {
while($line =~ /([^=\s]*)\s*=/g) {
push @list, $1;
}
}
@list
}
my $source_base="/some/path";
my $messages_en="$source_base/path/to/messages_en.properties";
my $messages_ru="$source_base/path/to/messages_ru.properties";
my @DIRLIST = ("$source_base/path/to/java/sources");
find(\&process_java_file, @DIRLIST);
@en_messages = &process_message_file($messages_en);
@ru_messages = &process_message_file($messages_ru);
my $res = 0;
foreach my $used_message (@usages){
unless ($used_message ~~ @ru_messages){
print "$used_message not found in messages_ru.properties\n";
$res = 1;
}
unless ($used_message ~~ @en_messages){
print "$used_message not found in messages_en.properties\n";
$res = 1;
}
}
exit $res; |
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
my @usages = ();
my @ru_messages = ();
my @en_messages = ();
sub process_java_file {
return unless -f ;
my $filename = $File::Find::name;
open my $info, $filename or die "Could not open $filename: $!";
while( my $line = <$info>) {
while($line =~ /messageSource\.\s*getMessage\s*\(\s*"([^"]*)/g) {
unless ($1 ~~ @usages) {
push @usages, $1;
}
}
}
}
sub process_message_file {
my $filename = $_[0];
my @list = ();
open my $message_file, $filename or die "Could not open $filename: $!";
while( my $line = <$message_file>) {
while($line =~ /([^=\s]*)\s*=/g) {
push @list, $1;
}
}
@list
}
my $source_base="/some/path";
my $messages_en="$source_base/path/to/messages_en.properties";
my $messages_ru="$source_base/path/to/messages_ru.properties";
my @DIRLIST = ("$source_base/path/to/java/sources");
find(\&process_java_file, @DIRLIST);
@en_messages = &process_message_file($messages_en);
@ru_messages = &process_message_file($messages_ru);
my $res = 0;
foreach my $used_message (@usages){
unless ($used_message ~~ @ru_messages){
print "$used_message not found in messages_ru.properties\n";
$res = 1;
}
unless ($used_message ~~ @en_messages){
print "$used_message not found in messages_en.properties\n";
$res = 1;
}
}
exit $res;
Пара замечаний. Ожидается, что использование сообщений будет в вызовах вида
messageSource.getMessage("key"), допустимы пробелы. В цикле, который создает отчет, можно сделать подсчет в переменной $res числа ошибок или менять ее значение на 1 только если там еще 0.