source: main/trunk/greenstone2/perllib/gsprintf.pm@ 21289

Last change on this file since 21289 was 21289, checked in by kjdon, 14 years ago

extension handling extended to include gs3 extensions

  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
RevLine 
[5613]1###########################################################################
2#
3# gsprintf.pm --
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
[7828]25use strict;
26no strict 'refs';
[5613]27
28package gsprintf;
[7828]29require Exporter;
30@gsprintf::ISA=qw(Exporter);
[5613]31
[6934]32use unicode;
[5613]33use util;
34
[15007]35@gsprintf::EXPORT_OK = qw(gsprintf); # functions we can export into namespace
[5613]36
[7828]37
[6945]38# Language-specific resource bundle
39my %specialresourcebundle = ();
[6993]40our $specialoutputencoding; # our, so that it can be changed outside.
[6925]41
[6945]42# Default resource bundle
43my %defaultresourcebundle;
44my $defaultoutputencoding;
[6925]45
[6945]46# English resource bundle
47my %englishresourcebundle;
48my $englishoutputencoding;
49
50# Ignore the OutputEncoding strings in the resource bundles and output all text in UTF-8
51my $outputstringsinUTF8 = 0;
52
53
[5613]54sub gsprintf
55{
56 my ($handle, $text_string, @text_arguments) = @_;
57
58 # Return unless the required arguments were supplied
59 return unless (defined($handle) && defined($text_string));
[18981]60
[5613]61 # Look up all the strings in the dictionary
[6925]62 $text_string =~ s/(\{[^\}]+\})/&lookup_string($1)/eg;
[5613]63
64 # Resolve the string arguments using sprintf, then write out to the handle
65 print $handle sprintf($text_string, @text_arguments);
66}
67
68
[6920]69sub lookup_string
[5613]70{
[6934]71 my ($stringkey) = @_;
[10228]72 return "" unless defined $stringkey;
[6945]73 # Try the language-specific resource bundle first
74 my $utf8string = $specialresourcebundle{$stringkey};
75 my $outputencoding = $specialoutputencoding;
76
77 # Try the default resource bundle next
78 if (!defined($utf8string)) {
[18981]79 # Load the default resource bundle if it is not already loaded
80 &load_default_resource_bundle() if (!%defaultresourcebundle);
81
82 $utf8string = $defaultresourcebundle{$stringkey};
83 $outputencoding = $defaultoutputencoding;
[6925]84 }
[18981]85
[6945]86 # Try the English resource bundle last
87 if (!defined($utf8string)) {
[18981]88 # Load the English resource bundle if it is not already loaded
89 &load_english_resource_bundle() if (!%englishresourcebundle);
90
91 $utf8string = $englishresourcebundle{$stringkey};
92 $outputencoding = $englishoutputencoding;
[6945]93 }
[18981]94
[6945]95 # No matching string was found, so just return the key
96 if (!defined($utf8string)) {
[18981]97 return $stringkey;
[6945]98 }
[18981]99
[6945]100 # Return the string matching the key
[6993]101 return $utf8string if (!defined($outputencoding) || $outputstringsinUTF8
[18981]102 || $outputencoding eq "utf8");
103
[6934]104 # If an 8-bit output encoding has been defined, encode the string appropriately
[9969]105 my $encoded=unicode::unicode2singlebyte(&unicode::utf82unicode($utf8string), $outputencoding);
106
107 # If we successfully encoded it, return it
108 if ($encoded) { return $encoded }
[18981]109
[9969]110 # Otherwise, we can't convert to the requested encoding. return the utf8?
111 $specialoutputencoding='utf8';
112 return $utf8string;
[5613]113}
114
115
[6945]116sub load_language_specific_resource_bundle
[5613]117{
[6934]118 my $language = shift(@_);
[18981]119
[6945]120 # Read the specified resource bundle
[11632]121 my $resourcebundlename = "strings_" . $language . ".properties";
[18981]122
123 %specialresourcebundle
124 = &read_resource_bundle_and_extensions($ENV{'GSDLHOME'},"perllib",$resourcebundlename);
[6945]125 return if (!%specialresourcebundle);
[18981]126
[6945]127 # Read the output encoding to use from the resource bundle
128 if ($ENV{'GSDLOS'} =~ /windows/) {
[18981]129 $specialoutputencoding = $specialresourcebundle{"{OutputEncoding.windows}"};
[5613]130 }
[6945]131 else {
[18981]132 # see if there is an encoding set in the appropriate locale env var
133
134 foreach my $envvar ('LC_ALL', 'LANG') {
135 if (!exists $ENV{$envvar}) { next }
136 my $locale=$ENV{$envvar};
137 if ($locale !~ /^\w+\.(.+)$/) { next }
138 my $enc=lc($1);
139 $enc =~ s/-/_/g;
140 if ($enc eq 'utf_8') { $enc='utf8' } # normalise to this name
141 $specialoutputencoding = $enc;
142 return;
143 }
144 $specialoutputencoding = $specialresourcebundle{"{OutputEncoding.unix}"};
[6945]145 }
146}
[5613]147
[6945]148
149sub load_default_resource_bundle
150{
151 # Read the default resource bundle
[11632]152 my $resourcebundlename = "strings.properties";
[5613]153
[18981]154 %defaultresourcebundle
155 = &read_resource_bundle_and_extensions($ENV{'GSDLHOME'},"perllib",$resourcebundlename);
[10982]156 if (!%defaultresourcebundle) {
157 # $! will still have the error value for the last failed syscall
[18981]158 print STDERR "$! $resourcebundlename\n";
159 # set something so we don't bother trying to load it again
160 $defaultresourcebundle{0}=undef;
[10982]161 return;
162 }
[18981]163
[6945]164 # Read the output encoding to use from the resource bundle
165 if ($ENV{'GSDLOS'} =~ /windows/) {
[18981]166 $defaultoutputencoding = $defaultresourcebundle{"{OutputEncoding.windows}"};
[5613]167 }
[6945]168 else {
[18981]169 $defaultoutputencoding = $defaultresourcebundle{"{OutputEncoding.unix}"};
[6945]170 }
171}
[5613]172
[6945]173
174sub load_english_resource_bundle
175{
176 # Ensure the English resource bundle hasn't already been loaded
[9362]177 if (%specialresourcebundle && $specialresourcebundle{"{Language.code}"} eq "en") {
[18981]178 %englishresourcebundle = %specialresourcebundle;
179 $englishoutputencoding = $specialoutputencoding;
[6945]180 }
[10982]181
182 if ($defaultresourcebundle{"{Language.code}"} &&
[17533]183 $defaultresourcebundle{"{Language.code}"} eq "en") {
[18981]184 %englishresourcebundle = %defaultresourcebundle;
185 $englishoutputencoding = $defaultoutputencoding;
[6945]186 }
[18981]187
[6945]188 # Read the English resource bundle
[11632]189 my $resourcebundlename = "strings_en.properties";
[6945]190
[18981]191 %englishresourcebundle
192 = &read_resource_bundle_and_extensions($ENV{'GSDLHOME'},"perllib",$resourcebundlename);
[6945]193 return if (!%englishresourcebundle);
[18981]194
[6945]195 # Read the output encoding to use from the resource bundle
196 if ($ENV{'GSDLOS'} =~ /windows/) {
[18981]197 $englishoutputencoding = $englishresourcebundle{"{OutputEncoding.windows}"};
[6945]198 }
199 else {
[18981]200 $englishoutputencoding = $englishresourcebundle{"{OutputEncoding.unix}"};
[6945]201 }
202}
203
204
[18981]205sub read_resource_bundle_and_extensions
206{
207 my ($bundle_base,$primary_dir,$resourcename) = @_;
208
209 my $primary_resourcebundlefile
210 = &util::filename_cat($bundle_base,$primary_dir,$resourcename);
211
212 my $resourcebundle = read_resource_bundle($primary_resourcebundlefile);
213 return if (!defined $resourcebundle);
214
[19026]215 if (defined $ENV{'GSDLEXTS'}) {
216 my @extensions = split(/:/,$ENV{'GSDLEXTS'});
217 foreach my $e (@extensions) {
218 my $ext_base
219 = &util::filename_cat($bundle_base,"ext",$e);
220
221 my $ext_resourcebundlefile
222 = &util::filename_cat($ext_base,$primary_dir,$resourcename);
223
224 # can ignore return value (will be same reference to $resourcebundle)
225 read_resource_bundle($ext_resourcebundlefile,$resourcebundle);
226 }
[18981]227 }
[21289]228 if (defined $ENV{'GSDL3EXTS'}) {
229 my @extensions = split(/:/,$ENV{'GSDL3EXTS'});
230 foreach my $e (@extensions) {
231 my $ext_base
232 = &util::filename_cat($ENV{'GSDL3SRCHOME'},"ext",$e);
233
234 my $ext_resourcebundlefile
235 = &util::filename_cat($ext_base,$primary_dir,$resourcename);
236
237 # can ignore return value (will be same reference to $resourcebundle)
238 read_resource_bundle($ext_resourcebundlefile,$resourcebundle);
239 }
240 }
[18981]241
242 return %$resourcebundle;
243}
244
245
[6945]246sub read_resource_bundle
247{
[18981]248 my ($resourcebundlefilepath,$resourcebundle) = @_;
[6945]249
[18981]250 if (!open(RESOURCE_BUNDLE, "<$resourcebundlefilepath")) {
251 # When called for the first time (primary resource), $resourcebundle
252 # is not defined (=undef). If the file does not exist, then we return
253 # this 'undef' to signal it was not found
254 # For an extension resource bundle, if it does not exist this
255 # is not so serious (in fact quite likely) => return what we
256 # have built up so far
257
258 return $resourcebundle;
259 }
[6945]260
[18981]261 if (!defined $resourcebundle) {
262 # resource files exists, so exect some content to be stored
263 $resourcebundle = {};
264 }
265
[6945]266 # Load this resource bundle
[6934]267 my @resourcebundlelines = <RESOURCE_BUNDLE>;
[5613]268 close(RESOURCE_BUNDLE);
269
[6945]270 # Parse the resource bundle
[18981]271
[7828]272 foreach my $line (@resourcebundlelines) {
[17533]273 # Remove any trailing whitespace
274 $line =~ s/(\s*)$//;
[5613]275
[17533]276 # Ignore comments and empty lines
277 if ($line !~ /^\#/ && $line ne "") {
278 # Parse key (everything up to the first colon)
279 if ($line =~ m/^([^:]+):(.+)$/) {
280 my $linekey = "{" . $1 . "}";
281 my $linetext = $2;
282 $linetext =~ s/(\s*)\#\s+Updated\s+(\d?\d-\D\D\D-\d\d\d\d).*$//i;
[5613]283
[17533]284 # Map key to text
[18981]285 $resourcebundle->{$linekey} = $linetext;
[17533]286 }
287 }
[5613]288 }
[6934]289
[18981]290 return $resourcebundle;
[5613]291}
292
293
[6945]294sub output_strings_in_UTF8
[6934]295{
[6945]296 $outputstringsinUTF8 = 1;
[6934]297}
298
299
[15007]300sub debug_unicode_string
301{
302 join("",
[17533]303 map { $_ > 255 ? # if wide character...
304 sprintf("\\x{%04X}", $_) : # \x{...}
305 chr($_)
306 } unpack("U*", $_[0])); # unpack Unicode characters
[15007]307}
308
309
[5613]3101;
Note: See TracBrowser for help on using the repository browser.