c19a4386ce5652e09a9baec206bcc0bbb44d71cd
[project/luci.git] / build / i18n-scan.pl
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use Text::Balanced qw(extract_tagged gen_delimited_pat);
6 use POSIX;
7
8 POSIX::setlocale(POSIX::LC_ALL, "C");
9
10 @ARGV >= 1 || die "Usage: $0 <source directory>\n";
11
12
13 my %stringtable;
14
15 sub dec_lua_str
16 {
17 my $s = shift;
18 $s =~ s/\\n/\n/g;
19 $s =~ s/\\t/\t/g;
20 $s =~ s/\\(.)/$1/sg;
21 $s =~ s/[\s\n]+/ /g;
22 $s =~ s/^ //;
23 $s =~ s/ $//;
24 return $s;
25 }
26
27 sub dec_tpl_str
28 {
29 my $s = shift;
30 $s =~ s/-$//;
31 $s =~ s/[\s\n]+/ /g;
32 $s =~ s/^ //;
33 $s =~ s/ $//;
34 $s =~ s/\\/\\\\/g;
35 return $s;
36 }
37
38 if( open F, "find @ARGV -type f '(' -name '*.htm' -o -name '*.lua' -o -name '*.js' ')' | sort |" )
39 {
40 while( defined( my $file = readline F ) )
41 {
42 chomp $file;
43
44 if( open S, "< $file" )
45 {
46 local $/ = undef;
47 my $raw = <S>;
48 close S;
49
50 my $text = $raw;
51 my $line = 1;
52
53 while ($text =~ s/ ^ (.*?) (?:translate|translatef|i18n|_) ([\n\s]*) \( //sgx)
54 {
55 my ($prefix, $suffix) = ($1, $2);
56 my $code;
57 my $res = "";
58 my $sub = "";
59
60 $line += () = $prefix =~ /\n/g;
61
62 my $position = "$file:$line";
63
64 $line += () = $suffix =~ /\n/g;
65
66 while (defined $sub)
67 {
68 undef $sub;
69
70 if ($text =~ /^ ([\n\s]*(?:\.\.[\n\s]*)?) (\[=*\[) /sx)
71 {
72 my $ws = $1;
73 my $stag = quotemeta $2;
74 (my $etag = $stag) =~ y/[/]/;
75
76 ($sub, $text) = extract_tagged($text, $stag, $etag, q{\s*(?:\.\.\s*)?});
77
78 $line += () = $ws =~ /\n/g;
79
80 if (defined($sub) && length($sub)) {
81 $line += () = $sub =~ /\n/g;
82
83 $sub =~ s/^$stag//;
84 $sub =~ s/$etag$//;
85 $res .= $sub;
86 }
87 }
88 elsif ($text =~ /^ ([\n\s]*(?:\.\.[\n\s]*)?) (['"]) /sx)
89 {
90 my $ws = $1;
91 my $quote = $2;
92 my $re = gen_delimited_pat($quote, '\\');
93
94 if ($text =~ m/\G\s*(?:\.\.\s*)?($re)/gcs)
95 {
96 $sub = $1;
97 $text = substr $text, pos $text;
98 }
99
100 $line += () = $ws =~ /\n/g;
101
102 if (defined($sub) && length($sub)) {
103 $line += () = $sub =~ /\n/g;
104
105 $sub =~ s/^$quote//;
106 $sub =~ s/$quote$//;
107 $res .= $sub;
108 }
109 }
110 }
111
112 if (defined($res))
113 {
114 $res = dec_lua_str($res);
115
116 if ($res) {
117 $stringtable{$res} ||= [ ];
118 push @{$stringtable{$res}}, $position;
119 }
120 }
121 }
122
123
124 $text = $raw;
125 $line = 1;
126
127 while( $text =~ s/ ^ (.*?) <% -? [:_] /<%/sgx )
128 {
129 $line += () = $1 =~ /\n/g;
130
131 ( my $code, $text ) = extract_tagged($text, '<%', '%>');
132
133 if( defined $code )
134 {
135 my $position = "$file:$line";
136
137 $line += () = $code =~ /\n/g;
138
139 $code = dec_tpl_str(substr $code, 2, length($code) - 4);
140
141 $stringtable{$code} ||= [];
142 push @{$stringtable{$code}}, $position;
143 }
144 }
145 }
146 }
147
148 close F;
149 }
150
151
152 if( open C, "| msgcat -" )
153 {
154 printf C "msgid \"\"\nmsgstr \"Content-Type: text/plain; charset=UTF-8\"\n\n";
155
156 foreach my $key ( sort keys %stringtable )
157 {
158 if( length $key )
159 {
160 my @positions = @{$stringtable{$key}};
161
162 $key =~ s/\\/\\\\/g;
163 $key =~ s/\n/\\n/g;
164 $key =~ s/\t/\\t/g;
165 $key =~ s/"/\\"/g;
166
167 printf C "#: %s\nmsgid \"%s\"\nmsgstr \"\"\n\n",
168 join(' ', @positions), $key;
169 }
170 }
171
172 close C;
173 }