2017-10-02 08:31:35 +03:00
#!/usr/bin/perl
use strict ;
2023-04-17 15:04:01 +03:00
use warnings ;
use Encode ;
2023-05-09 10:22:16 +03:00
use Getopt::Long ;
2023-04-17 15:04:01 +03:00
use Locale::PO ;
2017-10-02 08:31:35 +03:00
use Time::Local ;
2023-04-17 15:04:01 +03:00
2017-10-02 08:31:35 +03:00
my $ options = { } ;
2023-05-09 10:22:16 +03:00
GetOptions ( $ options , 'o=s' , 'b=s' , 'p=s' ) or die "unable to parse options\n" ;
2017-10-02 08:31:35 +03:00
my $ dirs = [ @ ARGV ] ;
die "no directory specified\n" if ! scalar ( @$ dirs ) ;
foreach my $ dir ( @$ dirs ) {
die "no such directory '$dir'\n" if ! - d $ dir ;
}
2017-10-02 13:46:36 +03:00
my $ projectId = $ options - > { p } || die "missing project ID\n" ;
2017-10-02 08:31:35 +03:00
my $ basehref = { } ;
if ( my $ base = $ options - > { b } ) {
my $ aref = Locale::PO - > load_file_asarray ( $ base ) ||
die "unable to load '$base'\n" ;
my $ charset ;
my $ hpo = $ aref - > [ 0 ] || die "no header" ;
my $ header = $ hpo - > dequote ( $ hpo - > msgstr ) ;
if ( $ header =~ m | ^ Content - Type: \ s + text / plain ; \ s + charset = ( \ S + ) $ | im ) {
$ charset = $ 1 ;
} else {
die "unable to get charset\n" if ! $ charset ;
}
foreach my $ po ( @$ aref ) {
my $ qmsgid = decode ( $ charset , $ po - > msgid ) ;
my $ msgid = $ po - > dequote ( $ qmsgid ) ;
$ basehref - > { $ msgid } = $ po ;
}
}
2023-05-09 10:01:16 +03:00
sub find_js_sources {
my ( $ base_dirs ) = @ _ ;
my $ find_cmd = 'find ' ;
# shell quote heuristic, with the (here safe) assumption that the dirs don't contain single-quotes
$ find_cmd . = join ( ' ' , map { "'$_'" } $ base_dirs - > @ * ) ;
$ find_cmd . = ' -name "*.js"' ;
open ( my $ find_cmd_output , '-|' , "$find_cmd | sort" ) or die "Failed to execute command: $!" ;
my $ sources = [] ;
while ( my $ line = <$find_cmd_output> ) {
chomp $ line ;
print "F: $line\n" ;
push @$ sources , $ line ;
}
close ( $ find_cmd_output ) ;
2023-05-09 09:48:56 +03:00
2023-05-09 10:01:16 +03:00
return $ sources ;
}
2017-10-02 08:31:35 +03:00
2023-05-09 10:13:19 +03:00
my $ header = << '__EOD' ;
2017-10-02 08:31:35 +03:00
Proxmox message catalog .
2023-04-17 15:04:24 +03:00
Copyright ( C ) Proxmox Server Solutions GmbH
2023-05-09 10:13:19 +03:00
This file is free software: you can redistribute it and / or modify it under the terms of the GNU
2023-04-17 15:04:24 +03:00
Affero General Public License as published by the Free Software Foundation , either version 3 of the
License , or ( at your option ) any later version .
- - Proxmox Support Team <support\@proxmox.com>
2017-10-02 08:31:35 +03:00
__EOD
my $ ctime = scalar localtime ;
2023-05-09 10:13:19 +03:00
my $ href = {
'' = > Locale::PO - > new (
- msgid = > '' ,
- comment = > $ header ,
- fuzzy = > 1 ,
- msgstr = > "Project-Id-Version: $projectId\n"
. "Report-Msgid-Bugs-To: <support\@proxmox.com>\n"
. "POT-Creation-Date: $ctime\n"
. "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
. "Last-Translator: FULL NAME <EMAIL\@ADDRESS>\n"
. "Language-Team: LANGUAGE <support\@proxmox.com>\n"
. "MIME-Version: 1.0\n"
. "Content-Type: text/plain; charset=UTF-8\n"
. "Content-Transfer-Encoding: 8bit\n" ,
) ,
} ;
2017-10-02 08:31:35 +03:00
sub extract_msg {
my ( $ filename , $ linenr , $ line ) = @ _ ;
my $ count = 0 ;
while ( 1 ) {
my $ text ;
2023-04-17 15:09:05 +03:00
if ( $ line =~ m/\bgettext\s*\((("((?:[^"\\]++|\\.)*+)")|('((?:[^'\\]++|\\.)*+)'))\)/g ) {
2017-10-02 08:31:35 +03:00
$ text = $ 3 || $ 5 ;
}
last if ! $ text ;
2023-05-09 10:13:19 +03:00
return if $ basehref - > { $ text } ;
2017-10-02 08:31:35 +03:00
$ count + + ;
my $ ref = "$filename:$linenr" ;
if ( my $ po = $ href - > { $ text } ) {
$ po - > reference ( $ po - > reference ( ) . " $ref" ) ;
2023-04-17 15:06:49 +03:00
} else {
2023-05-09 10:13:19 +03:00
$ href - > { $ text } = Locale::PO - > new ( - msgid = > $ text , - reference = > $ ref , - msgstr = > '' ) ;
2017-10-02 08:31:35 +03:00
}
2023-05-09 10:13:19 +03:00
}
die "can't extract gettext message in '$filename' line $linenr\n" if ! $ count ;
return ;
2017-10-02 08:31:35 +03:00
}
2023-05-09 10:01:16 +03:00
my $ sources = find_js_sources ( $ dirs ) ;
2017-10-02 08:31:35 +03:00
foreach my $ s ( @$ sources ) {
2023-04-17 15:06:49 +03:00
open ( my $ SRC_FH , '<' , $ s ) || die "unable to open file '$s' - $!\n" ;
while ( defined ( my $ line = <$SRC_FH> ) ) {
2023-04-17 15:07:18 +03:00
if ( $ line =~ m/gettext\s*\(/ && $ line !~ m/^\s*function gettext/ ) {
2017-10-02 08:31:35 +03:00
extract_msg ( $ s , $. , $ line ) ;
}
}
2023-04-17 15:06:49 +03:00
close ( $ SRC_FH ) ;
2017-10-02 08:31:35 +03:00
}
my $ filename = $ options - > { o } // "messages.pot" ;
Locale::PO - > save_file_fromhash ( $ filename , $ href ) ;