147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
1 |
#!/usr/bin/perl -w
|
2 |
||
3 |
=head1 NAME
|
|
4 |
||
5 |
dh_translations - perform common translation related operations
|
|
6 |
||
7 |
=cut
|
|
8 |
||
9 |
use strict; |
|
10 |
||
11 |
use File::Find; |
|
12 |
use Debian::Debhelper::Dh_Lib; |
|
13 |
||
14 |
=head1 SYNOPSIS
|
|
15 |
||
16 |
B<dh_translations> [S<B<debhelper options>>]
|
|
17 |
||
18 |
=head1 DESCRIPTION
|
|
19 |
||
20 |
dh_translations is a debhelper program to perform common translation
|
|
21 |
related operations during package build:
|
|
22 |
||
23 |
=over 4
|
|
24 |
||
25 |
=item
|
|
26 |
||
27 |
Try to build a current PO template.
|
|
28 |
||
29 |
=item
|
|
30 |
||
31 |
Remove inline translations from *.desktop, *.server, *.schemas, and
|
|
32 |
*.policy files and replace them with a link to the gettext domain, so that
|
|
33 |
strings in them will get translated at runtime from *.mo files. This allows
|
|
34 |
language packs to ship updated translations.
|
|
35 |
||
36 |
=back
|
|
37 |
||
38 |
=cut
|
|
39 |
||
148
by Martin Pitt
dh_translations: Factorize domain detection |
40 |
my ($domain, $use_intltool); |
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
41 |
|
148
by Martin Pitt
dh_translations: Factorize domain detection |
42 |
# figure out intltool usage and domain
|
43 |
sub check_buildsystem { |
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
44 |
$use_intltool = 0; |
164
by Martin Pitt
dh_translations: Try getting domain from Python setup.cfg if po/Makefile |
45 |
if (open MAKEFILE, 'po/Makefile') { |
46 |
while (<MAKEFILE>) { |
|
47 |
$use_intltool = 1 if /intltool/; |
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
48 |
|
164
by Martin Pitt
dh_translations: Try getting domain from Python setup.cfg if po/Makefile |
49 |
$domain = $1 if /^GETTEXT_PACKAGE\s*=\s*(\S*)/; |
50 |
}
|
|
51 |
close (MAKEFILE); |
|
209
by Martin Pitt
dh_translations: Also check configure.ac for GETTEXT_DOMAIN. (LP: #786632) |
52 |
}
|
53 |
if (!$domain && open CFGFILE, 'configure.ac') { |
|
54 |
while (<CFGFILE>) { |
|
55 |
$use_intltool = 1 if /INTLTOOL/; |
|
56 |
||
57 |
$domain = $1 if /^GETTEXT_PACKAGE\s*=\s*(\S*)/; |
|
58 |
}
|
|
231
by Sebastien Bacher
* small improvements to dh_translations: |
59 |
close (CFGFILE); |
60 |
}
|
|
61 |
if (!$domain && open CFGFILE, 'configure.in') { |
|
62 |
while (<CFGFILE>) { |
|
63 |
$use_intltool = 1 if /INTLTOOL/; |
|
64 |
||
65 |
$domain = $1 if /^GETTEXT_PACKAGE\s*=\s*(\S*)/; |
|
66 |
}
|
|
67 |
close (CFGFILE); |
|
68 |
}
|
|
69 |
if (open CFGFILE, 'config.h') { |
|
70 |
while (<CFGFILE>) { |
|
235
by Sebastien Bacher
dh_translations: fixes previous issues harder (lp: #913085) |
71 |
$domain = $1 if /^#define GETTEXT_PACKAGE\s*"(\S*)"/; |
231
by Sebastien Bacher
* small improvements to dh_translations: |
72 |
}
|
73 |
close (CFGFILE); |
|
209
by Martin Pitt
dh_translations: Also check configure.ac for GETTEXT_DOMAIN. (LP: #786632) |
74 |
}
|
75 |
if (!$domain && open CFGFILE, 'setup.cfg') { |
|
164
by Martin Pitt
dh_translations: Try getting domain from Python setup.cfg if po/Makefile |
76 |
while (<CFGFILE>) { |
77 |
$domain = $1 if /^\s*domain\s*=\s*(\S*)/; |
|
78 |
}
|
|
79 |
close (CFGFILE); |
|
209
by Martin Pitt
dh_translations: Also check configure.ac for GETTEXT_DOMAIN. (LP: #786632) |
80 |
}
|
81 |
if (!$domain && open CMAKELISTSFILE, 'CMakeLists.txt') { |
|
168
by Didier Roche
* dh_translations: |
82 |
while (<CMAKELISTSFILE>) { |
169
by Didier Roche
if there is no Makefile, we need a POTFILES.in + some cleanup |
83 |
if ( -e 'po/POTFILES.in' ) { |
84 |
$use_intltool = 1; |
|
85 |
}
|
|
190
by Didier Roche
* dh-translations: |
86 |
$domain = $1 if /^set \(GETTEXT_PACKAGE\s*"(\S*)"\)/; |
168
by Didier Roche
* dh_translations: |
87 |
}
|
88 |
close (CMAKELISTSFILE) |
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
89 |
}
|
209
by Martin Pitt
dh_translations: Also check configure.ac for GETTEXT_DOMAIN. (LP: #786632) |
90 |
|
91 |
verbose_print "check_buildsystem: got domain '$domain', using intltool: $use_intltool"; |
|
148
by Martin Pitt
dh_translations: Factorize domain detection |
92 |
}
|
93 |
||
94 |
# Try to build a POT
|
|
95 |
sub build_pot { |
|
96 |
||
97 |
my @cmd; |
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
98 |
if ($use_intltool) { |
99 |
# use intltool-update
|
|
171
by Martin Pitt
fix indentation |
100 |
if ($domain) { |
101 |
@cmd=('/usr/bin/intltool-update', '-p', '--verbose', '-g', $domain); |
|
102 |
} else { |
|
103 |
@cmd=('/usr/bin/intltool-update', '-p', '--verbose'); |
|
104 |
}
|
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
105 |
} else { |
168
by Didier Roche
* dh_translations: |
106 |
return unless -e 'po/Makefile'; |
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
107 |
if ($domain) { |
108 |
# let the Makefile itself handle it
|
|
109 |
@cmd=('make', $domain . '.pot'); |
|
110 |
} else { |
|
111 |
warn 'Does not use intltool and po/Makefile does not define GETTEXT_PACKAGE, cannot build POT automatically'; |
|
112 |
return; |
|
113 |
}
|
|
114 |
}
|
|
115 |
verbose_print (escape_shell (@cmd)); |
|
116 |
chdir 'po'; |
|
117 |
system @cmd; |
|
118 |
chdir '..'; |
|
119 |
||
120 |
# try to build help POT
|
|
121 |
if (-e 'help/Makefile') { |
|
122 |
chdir 'help'; |
|
123 |
system ('make', 'pot'); |
|
124 |
chdir '..'; |
|
125 |
}
|
|
126 |
}
|
|
127 |
||
152
by Martin Pitt
dh_translations: Implement *.server processing |
128 |
# strip translations and add domain to *.desktop/*.directory
|
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
129 |
sub process_desktop { |
130 |
my @lines = @{$_[0]}; |
|
131 |
my @result; |
|
132 |
my $in_desktop_entry = 0; |
|
133 |
my $added_domain = 0; |
|
134 |
foreach (@lines) { |
|
135 |
# filter out translated fields
|
|
136 |
next if (/^(Name|GenericName|Comment|X-GNOME-FullName)\[/); |
|
162
by Martin Pitt
dh_translations: do not add domain to desktop files which already have it |
137 |
|
138 |
if (/^[A-Za-z-0-9-]*Gettext-Domain\s*=/) { |
|
139 |
$added_domain = 1; |
|
140 |
}
|
|
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
141 |
|
142 |
# catch section headers
|
|
143 |
if (/^\[\s*(.+)\s*\]/) { |
|
144 |
$in_desktop_entry = ($1 eq 'Desktop Entry'); |
|
145 |
}
|
|
146 |
||
147 |
# if we are ending the desktop section, append the domain
|
|
148 |
if (/^\s*$/ && $in_desktop_entry && !$added_domain) { |
|
149 |
push @result, "X-Ubuntu-Gettext-Domain=$domain\n"; |
|
150 |
$added_domain = 1; |
|
151 |
}
|
|
152 |
||
153 |
push @result, $_; |
|
154 |
}
|
|
155 |
||
156 |
# single-section .desktop files without ending empty lines
|
|
157 |
if ($in_desktop_entry && !$added_domain) { |
|
158 |
push @result, "X-Ubuntu-Gettext-Domain=$domain\n"; |
|
159 |
}
|
|
160 |
return @result; |
|
161 |
}
|
|
162 |
||
152
by Martin Pitt
dh_translations: Implement *.server processing |
163 |
# add domain to Bonobo *.server files
|
164 |
sub process_server { |
|
165 |
my @lines = @{$_[0]}; |
|
166 |
my @result; |
|
167 |
foreach (@lines) { |
|
168 |
if (/^<oaf_server\b/ && !/ubuntu-gettext-domain/) { |
|
169 |
s/^<oaf_server/<oaf_server ubuntu-gettext-domain="icecream"/; |
|
170 |
}
|
|
171 |
push @result, $_; |
|
172 |
}
|
|
173 |
return @result; |
|
174 |
}
|
|
175 |
||
154
by Martin Pitt
dh_translations: Implement *.schemas processing |
176 |
# strip translations and add domain to gconf *.schemas files
|
177 |
sub process_gconf { |
|
178 |
my @lines = @{$_[0]}; |
|
179 |
my @result; |
|
180 |
my $in_locale = 0; |
|
181 |
my $wrote_locale_tag = 0; |
|
182 |
my $locale_tag; |
|
183 |
||
184 |
foreach (@lines) { |
|
185 |
#case: within a non-C <locale> tag
|
|
186 |
if ($in_locale) { |
|
187 |
if (/^\s*<default>/) { |
|
188 |
if (!$wrote_locale_tag) { |
|
189 |
push @result, $locale_tag; |
|
190 |
$wrote_locale_tag = 1; |
|
191 |
}
|
|
192 |
push @result, $_; |
|
193 |
} elsif (/^\s*<\/locale>/) { |
|
194 |
push @result, $_ if $wrote_locale_tag; |
|
195 |
$in_locale = 0; |
|
196 |
}
|
|
197 |
}
|
|
198 |
# case: locale name="C": add <gettext_domain> and leave alone
|
|
199 |
elsif (/^(\s*)<locale name=\"C\">/) { |
|
200 |
push @result, "$1<gettext_domain>$domain</gettext_domain>\n"; |
|
201 |
push @result, $_; |
|
202 |
}
|
|
203 |
# case: locale name="something": start $in_locale and purge <short> and <long>
|
|
204 |
elsif (/<locale name=\"[^C]/) { |
|
205 |
$in_locale = 1; |
|
206 |
$wrote_locale_tag = 0; |
|
207 |
$locale_tag = $_; |
|
208 |
}
|
|
209 |
else { |
|
210 |
push @result, $_ unless /^$/; |
|
211 |
push @result, "\n" if /^\s*<\/schema>/; # to not kill all whitespace |
|
212 |
}
|
|
213 |
}
|
|
214 |
return @result; |
|
215 |
}
|
|
216 |
||
153
by Martin Pitt
dh_translations: Implement *.policy processing |
217 |
# strip translations and add domain to *.policy files
|
218 |
sub process_polkit { |
|
219 |
my @lines = @{$_[0]}; |
|
220 |
my @result; |
|
221 |
foreach (@lines) { |
|
222 |
# filter out translated fields
|
|
163
by Martin Pitt
dh_translations: fix back ref in *.policy processing |
223 |
next if (/<(message|description)\s+xml:lang=.*\/\1>/); |
153
by Martin Pitt
dh_translations: Implement *.policy processing |
224 |
|
225 |
# add domain
|
|
157
by Martin Pitt
dh_translations: Fix for packages without po/Makefile |
226 |
s/<(message|description)\b/<$1 gettext-domain="$domain"/; |
153
by Martin Pitt
dh_translations: Implement *.policy processing |
227 |
|
228 |
push @result, $_; |
|
229 |
}
|
|
230 |
return @result; |
|
231 |
}
|
|
232 |
||
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
233 |
sub strip_file { |
234 |
my $f = $_; |
|
154
by Martin Pitt
dh_translations: Implement *.schemas processing |
235 |
return unless $f =~ /\.(desktop|directory|server|policy|schemas)$/; |
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
236 |
my $ext = $1; |
237 |
return if -l $f or -d $f; # Skip directories and symlinks |
|
238 |
||
239 |
# See if we were asked to exclude this file.
|
|
240 |
foreach my $x (@{$dh{EXCLUDE}}) { |
|
241 |
return if ($File::Find::name =~ m/\Q$x\E/); |
|
242 |
}
|
|
243 |
||
151
by Martin Pitt
dh_langpack: add some logging |
244 |
print " $f\n"; |
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
245 |
my @lines; |
246 |
open F, $f or die "open $f: $!"; |
|
247 |
@lines = <F>; |
|
248 |
close F; |
|
249 |
||
250 |
if ($ext eq 'desktop' || $ext eq 'directory') { |
|
251 |
@lines = process_desktop \@lines; |
|
252 |
}
|
|
152
by Martin Pitt
dh_translations: Implement *.server processing |
253 |
elsif ($ext eq 'server' && index($File::Find::name, '/bonobo/servers/') > 0) { |
254 |
@lines = process_server \@lines; |
|
153
by Martin Pitt
dh_translations: Implement *.policy processing |
255 |
} elsif ($ext eq 'policy' && index($File::Find::name, '/polkit-1/actions/') > 0) { |
256 |
@lines = process_polkit \@lines; |
|
154
by Martin Pitt
dh_translations: Implement *.schemas processing |
257 |
} elsif ($ext eq 'schemas' && index($File::Find::name, '/gconf/') > 0) { |
258 |
@lines = process_gconf \@lines; |
|
152
by Martin Pitt
dh_translations: Implement *.server processing |
259 |
}
|
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
260 |
|
261 |
# write back modified result
|
|
262 |
open F, ">$f" or die "open $f: $!"; |
|
263 |
foreach (@lines) { |
|
264 |
print F $_; |
|
265 |
}
|
|
266 |
}
|
|
267 |
||
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
268 |
init(); |
269 |
||
148
by Martin Pitt
dh_translations: Factorize domain detection |
270 |
check_buildsystem(); |
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
271 |
build_pot(); |
272 |
||
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
273 |
if ($domain) { |
151
by Martin Pitt
dh_langpack: add some logging |
274 |
print "dh_langpack: processing files to add translation domain '$domain'..\n"; |
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
275 |
foreach my $package (@{$dh{DOPACKAGES}}) { |
276 |
next if is_udeb($package); |
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
277 |
|
149
by Martin Pitt
dh_translations: Implement *.desktop/*.directory processing |
278 |
find(\&strip_file, tmpdir($package)) |
279 |
}
|
|
147
by Martin Pitt
* Add debhelper script for handling translation operations. This makes it |
280 |
}
|
281 |
||
282 |
=head1 SEE ALSO
|
|
283 |
||
284 |
L<debhelper(1)>
|
|
285 |
||
286 |
=head1 AUTHOR
|
|
287 |
||
288 |
Martin Pitt <martin.pitt@ubuntu.com>
|
|
289 |
||
290 |
Copyright (C) 2011 Canonical Ltd., licensed under the GNU GPL v2 or later.
|
|
291 |
||
292 |
=cut
|