Скрипт для проверки наличия использованных i18n сообщений

При использовании интернационализации в своем проекте на 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;

Пара замечаний. Ожидается, что использование сообщений будет в вызовах вида messageSource.getMessage(«key»), допустимы пробелы. В цикле, который создает отчет, можно сделать подсчет в переменной $res числа ошибок или менять ее значение на 1 только если там еще 0.

You can leave a response, or trackback from your own site.

Leave a Reply