source: trunk/gsdl/perllib/gsprintf.pm@ 9969

Last change on this file since 9969 was 9969, checked in by jrm21, 19 years ago

better error checking if an encoding conversion failed.

on !windows platforms, look at the locale to choose the best output
encoding.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 KB
Line 
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###########################################################################
25use strict;
26no strict 'refs';
27
28package gsprintf;
29require Exporter;
30@gsprintf::ISA=qw(Exporter);
31
32use unicode;
33use util;
34
35@gsprintf::EXPORT_OK = qw'gsprintf'; # functions we can export into namespace
36
37
38# Language-specific resource bundle
39my %specialresourcebundle = ();
40our $specialoutputencoding; # our, so that it can be changed outside.
41
42# Default resource bundle
43my %defaultresourcebundle;
44my $defaultoutputencoding;
45
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
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));
60
61 # Look up all the strings in the dictionary
62 $text_string =~ s/(\{[^\}]+\})/&lookup_string($1)/eg;
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
69sub lookup_string
70{
71 my ($stringkey) = @_;
72 # Try the language-specific resource bundle first
73 my $utf8string = $specialresourcebundle{$stringkey};
74 my $outputencoding = $specialoutputencoding;
75
76 # Try the default resource bundle next
77 if (!defined($utf8string)) {
78 # Load the default resource bundle if it is not already loaded
79 &load_default_resource_bundle() if (!%defaultresourcebundle);
80
81 $utf8string = $defaultresourcebundle{$stringkey};
82 $outputencoding = $defaultoutputencoding;
83 }
84
85 # Try the English resource bundle last
86 if (!defined($utf8string)) {
87 # Load the English resource bundle if it is not already loaded
88 &load_english_resource_bundle() if (!%englishresourcebundle);
89
90 $utf8string = $englishresourcebundle{$stringkey};
91 $outputencoding = $englishoutputencoding;
92 }
93
94 # No matching string was found, so just return the key
95 if (!defined($utf8string)) {
96 return $stringkey;
97 }
98
99 # Return the string matching the key
100 return $utf8string if (!defined($outputencoding) || $outputstringsinUTF8
101 || $outputencoding eq "utf8");
102
103 # If an 8-bit output encoding has been defined, encode the string appropriately
104 my $encoded=unicode::unicode2singlebyte(&unicode::utf82unicode($utf8string), $outputencoding);
105
106 # If we successfully encoded it, return it
107 if ($encoded) { return $encoded }
108
109 # Otherwise, we can't convert to the requested encoding. return the utf8?
110 $specialoutputencoding='utf8';
111 return $utf8string;
112}
113
114
115sub load_language_specific_resource_bundle
116{
117 my $language = shift(@_);
118
119 # Read the specified resource bundle
120 my $resourcebundlehome = &util::filename_cat("$ENV{'GSDLHOME'}", "perllib");
121 my $resourcebundlename = "strings_" . $language . ".rb";
122 my $resourcebundlefile = &util::filename_cat($resourcebundlehome, $resourcebundlename);
123
124 %specialresourcebundle = &read_resource_bundle($resourcebundlefile);
125 return if (!%specialresourcebundle);
126
127 # Read the output encoding to use from the resource bundle
128 if ($ENV{'GSDLOS'} =~ /windows/) {
129 $specialoutputencoding = $specialresourcebundle{"{OutputEncoding.windows}"};
130 }
131 else {
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}"};
145 }
146}
147
148
149sub load_default_resource_bundle
150{
151 # Read the default resource bundle
152 my $resourcebundlehome = &util::filename_cat("$ENV{'GSDLHOME'}", "perllib");
153 my $resourcebundlename = "strings.rb";
154 my $resourcebundlefile = &util::filename_cat($resourcebundlehome, $resourcebundlename);
155
156 %defaultresourcebundle = &read_resource_bundle($resourcebundlefile);
157 return if (!%defaultresourcebundle);
158
159 # Read the output encoding to use from the resource bundle
160 if ($ENV{'GSDLOS'} =~ /windows/) {
161 $defaultoutputencoding = $defaultresourcebundle{"{OutputEncoding.windows}"};
162 }
163 else {
164 $defaultoutputencoding = $defaultresourcebundle{"{OutputEncoding.unix}"};
165 }
166}
167
168
169sub load_english_resource_bundle
170{
171 # Ensure the English resource bundle hasn't already been loaded
172 if (%specialresourcebundle && $specialresourcebundle{"{Language.code}"} eq "en") {
173 %englishresourcebundle = %specialresourcebundle;
174 $englishoutputencoding = $specialoutputencoding;
175 }
176 if ($defaultresourcebundle{"{Language.code}"} eq "en") {
177 %englishresourcebundle = %defaultresourcebundle;
178 $englishoutputencoding = $defaultoutputencoding;
179 }
180
181 # Read the English resource bundle
182 my $resourcebundlehome = &util::filename_cat("$ENV{'GSDLHOME'}", "perllib");
183 my $resourcebundlename = "strings_en.rb";
184 my $resourcebundlefile = &util::filename_cat($resourcebundlehome, $resourcebundlename);
185
186 %englishresourcebundle = &read_resource_bundle($resourcebundlefile);
187 return if (!%englishresourcebundle);
188
189 # Read the output encoding to use from the resource bundle
190 if ($ENV{'GSDLOS'} =~ /windows/) {
191 $englishoutputencoding = $englishresourcebundle{"{OutputEncoding.windows}"};
192 }
193 else {
194 $englishoutputencoding = $englishresourcebundle{"{OutputEncoding.unix}"};
195 }
196}
197
198
199sub read_resource_bundle
200{
201 my ($resourcebundlefilepath) = shift(@_);
202
203 # Return an empty hash if the specified resource bundle could not be read
204 return () if (!open(RESOURCE_BUNDLE, "<$resourcebundlefilepath"));
205
206 # Load this resource bundle
207 my @resourcebundlelines = <RESOURCE_BUNDLE>;
208 close(RESOURCE_BUNDLE);
209
210 # Parse the resource bundle
211 my %resourcebundle = ();
212 foreach my $line (@resourcebundlelines) {
213 # Remove any trailing whitespace
214 $line =~ s/(\s*)$//;
215
216 # Ignore comments and empty lines
217 if ($line !~ /^\#/ && $line ne "") {
218 # Parse key (everything up to the first colon)
219 $line =~ /^([^:]+):(.+)$/;
220 my $linekey = "{" . $1 . "}";
221 my $linetext = $2;
222
223 # Map key to text
224 $resourcebundle{$linekey} = $linetext;
225 }
226 }
227
228 return %resourcebundle;
229}
230
231
232sub output_strings_in_UTF8
233{
234 $outputstringsinUTF8 = 1;
235}
236
237
2381;
Note: See TracBrowser for help on using the repository browser.