~ubuntu-branches/ubuntu/vivid/pkgbinarymangler/vivid

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