Retry only for https protocol
[elinks.git] / po / perl / Locale / PO.pm
blobd3d78641e81121d6543cf7da1c5ca2e7abcff7fa
1 # This file has been changed from the "Standard Version" Locale-PO-0.16.
2 # The copyright, license, and change log are in the POD at the bottom.
4 use strict;
5 use warnings;
7 package Locale::PO;
9 use Carp;
11 # Internally, each Locale::PO object is a reference to a hash
12 # (or pseudo-hash, for Perl < 5.9) with the following keys.
13 # The format of the hash is subject to change; other modules
14 # should use the accessor methods instead.
15 use fields
16 # Multiline strings including quotes and newlines, but excluding
17 # the initial keywords and any "#~ " obsoletion marks. Can be
18 # either undef or "" if not present. These normally do not end
19 # with a newline.
20 qw(msgid msgid_plural msgstr),
21 # A reference to a hash where keys are numbers (as strings)
22 # and values are in the same format as $self->{msgstr}.
23 qw(msgstr_n),
24 # Line numbers. The file name is not currently saved.
25 qw(_msgid_begin_lineno _msgstr_begin_lineno),
26 # Multiline strings excluding the trailing newline and comment
27 # markers, or undef if there are no such lines.
28 qw(comment automatic reference),
29 # Named flags. These are kept in two formats:
30 # - $self->{'_flaghash'} is undef Locale::PO has not yet parsed the flags.
31 # Otherwise, it refers to a hash where the keys are names of flags that
32 # have been set, and the values are all 1. (The hash can be empty.)
33 # - $self->{'_flagstr'} is undef if there are no flags; or a string in the
34 # same format as $self->{'automatic'}; or a reference to the same hash as
35 # $self->{'_flaghash'} if Locale::PO has changed a flag and not yet
36 # reformatted the flags as a string.
37 qw(_flagstr _flaghash),
38 # 1 if the entry is obsolete; undef if not.
39 qw(_obsolete);
41 #use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
42 #use locale;
44 #require Exporter;
45 #require AutoLoader;
47 #@ISA = qw(Exporter AutoLoader);
48 #@EXPORT = qw();
49 our $VERSION = '0.16.kon';
51 # Preloaded methods go here.
53 sub new {
54 my $this = shift;
55 my %options = @_;
56 my Locale::PO $self = ref($this) ? $this : fields::new($this);
57 $self->msgid( $options{'-msgid'} ) if defined( $options{'-msgid'} );
58 $self->msgid_plural( $options{'-msgid_plural'} )
59 if defined( $options{'-msgid_plural'} );
60 $self->msgstr( $options{'-msgstr'} ) if defined( $options{'-msgstr'} );
61 $self->msgstr_n( $options{'-msgstr_n'} )
62 if defined( $options{'-msgstr_n'} );
63 $self->comment( $options{'-comment'} ) if defined( $options{'-comment'} );
64 $self->fuzzy( $options{'-fuzzy'} ) if defined( $options{'-fuzzy'} );
65 $self->automatic( $options{'-automatic'} )
66 if defined( $options{'-automatic'} );
67 $self->reference( $options{'-reference'} )
68 if defined( $options{'-reference'} );
69 $self->c_format(1) if defined( $options{'-c-format'} );
70 $self->c_format(1) if defined( $options{'-c_format'} );
71 $self->c_format(0) if defined( $options{'-no-c-format'} );
72 $self->c_format(0) if defined( $options{'-no_c_format'} );
73 return $self;
76 sub msgid {
77 my Locale::PO $self = shift;
78 if (@_) {
79 $self->{msgid} = $self->quote(shift);
80 # TODO: Should this erase $self->{_msgid_begin_lineno}?
82 else {
83 return $self->{msgid};
87 sub msgid_begin_lineno {
88 my Locale::PO $self = shift;
89 # We should have a way to pass extra arguments (e.g. quoting
90 # level) to getters, without making them behave as setters. That
91 # may require an incompatible API change, which in turn requires
92 # extra methods in order to preserve compatibility. Don't allow
93 # setting msgid_begin_lineno yet; thus this method won't have to
94 # be duplicated.
95 croak "Setting msgid_begin_lineno is not currently allowed" if @_;
96 return $self->{_msgid_begin_lineno};
99 sub msgid_plural {
100 my Locale::PO $self = shift;
102 ? $self->{'msgid_plural'} =
103 $self->quote(shift)
104 : $self->{'msgid_plural'};
107 sub msgstr {
108 my Locale::PO $self = shift;
109 if (@_) {
110 $self->{msgstr} = $self->quote(shift);
111 # TODO: Should this erase $self->{_msgstr_begin_lineno}?
113 else {
114 return $self->{msgstr};
118 sub msgstr_begin_lineno {
119 my Locale::PO $self = shift;
120 # We should have a way to pass extra arguments (e.g. quoting
121 # level) to getters, without making them behave as setters. That
122 # may require an incompatible API change, which in turn requires
123 # extra methods in order to preserve compatibility. Don't allow
124 # setting msgstr_begin_lineno yet; thus this method won't have to
125 # be duplicated.
126 croak "Setting msgstr_begin_lineno is not currently allowed" if @_;
127 return $self->{_msgstr_begin_lineno};
130 sub msgstr_n {
131 my Locale::PO $self = shift;
132 if (@_) {
133 my $hashref = shift;
135 # check that we have a hashref.
136 croak
137 'Argument to msgstr_n must be a hashref: { n => "string n", ... }.'
138 unless ref($hashref) eq 'HASH';
140 # Check that the keys are all numbers.
141 croak 'Keys to msgstr_n hashref must be numbers'
142 if grep { m/\D/ } keys %$hashref;
144 # Quote all the values in the hashref.
145 $self->{'msgstr_n'}{$_} = $self->quote( $$hashref{$_} )
146 for keys %$hashref;
150 return $self->{'msgstr_n'};
153 sub comment {
154 my Locale::PO $self = shift;
155 @_ ? $self->{'comment'} = shift: $self->{'comment'};
158 sub automatic {
159 my Locale::PO $self = shift;
160 @_ ? $self->{'automatic'} = shift: $self->{'automatic'};
163 sub reference {
164 my Locale::PO $self = shift;
165 @_ ? $self->{'reference'} = shift: $self->{'reference'};
168 # Methods whose names begin with "_" may be changed or removed in
169 # future versions.
170 sub _update_flaghash {
171 my Locale::PO $self = shift;
172 if (!defined($self->{'_flaghash'})) {
173 my @flags;
174 @flags = split(/[\s,]+/, $self->{'_flagstr'})
175 if defined $self->{'_flagstr'};
176 $self->{'_flaghash'} = { map { $_ => 1 } @flags };
180 # Methods whose names begin with "_" may be changed or removed in
181 # future versions.
182 sub _update_flagstr {
183 my Locale::PO $self = shift;
184 if (ref($self->{'_flagstr'}) eq 'HASH') {
185 # GNU Gettext seems to put the "fuzzy" flag first.
186 # Do the same here, in case someone's relying on it.
187 # However, the other flags will be sorted differently.
188 my %flags = %{$self->{'_flagstr'}};
189 my @flags = ();
190 push @flags, 'fuzzy' if delete $flags{'fuzzy'};
191 push @flags, sort { $a cmp $b } keys %flags;
192 $self->{'_flagstr'} = (@flags ? join(', ', @flags) : undef);
196 # Methods whose names begin with "_" may be changed or removed in
197 # future versions.
198 sub _flag {
199 my Locale::PO $self = shift;
200 my $name = shift;
201 $self->_update_flaghash();
202 if (@_) { # set or clear the flag
203 $self->{'_flagstr'} = $self->{'_flaghash'};
204 if (shift) {
205 $self->{'_flaghash'}{$name} = 1;
206 return 1;
208 else {
209 delete $self->{'_flaghash'}{$name};
210 return "";
213 else { # check the flag
214 return exists $self->{'_flaghash'}{$name};
218 # Methods whose names begin with "_" may be changed or removed in
219 # future versions.
220 sub _tristate {
221 my Locale::PO $self = shift;
222 my $name = shift;
223 $self->_update_flaghash();
224 if (@_) { # set or clear the flags
225 $self->{'_flagstr'} = $self->{'_flaghash'};
226 my $val = shift;
227 if (!defined($val) || $val eq "") {
228 delete $self->{'_flaghash'}{"$name"};
229 delete $self->{'_flaghash'}{"no-$name"};
230 return undef;
232 elsif ($val) {
233 $self->{'_flaghash'}{"$name"} = 1;
234 delete $self->{'_flaghash'}{"no-$name"};
235 return 1;
237 else {
238 delete $self->{'_flaghash'}{"$name"};
239 $self->{'_flaghash'}{"no-$name"} = 1;
240 return 0;
243 else { # check the flags
244 return 1 if $self->{'_flaghash'}{"$name"};
245 return 0 if $self->{'_flaghash'}{"no-$name"};
246 return undef;
250 sub fuzzy {
251 my Locale::PO $self = shift;
252 return $self->_flag('fuzzy', @_);
255 sub c_format {
256 my Locale::PO $self = shift;
257 return $self->_tristate('c-format', @_);
260 sub php_format {
261 my Locale::PO $self = shift;
262 return $self->_tristate('php-format', @_);
265 sub obsolete {
266 my Locale::PO $self = shift;
267 @_ ? $self->{_obsolete} = shift : $self->{_obsolete};
270 # Methods whose names begin with "_" may be changed or removed in
271 # future versions.
272 sub _normalize_str {
273 my $self = shift; # can be called as a class method
274 my $string = shift;
275 my $dequoted = $self->dequote($string);
277 # This isn't quite perfect, but it's fast and easy
278 if ( $dequoted =~ /(^|[^\\])(\\\\)*\\n./ ) {
280 # Multiline
281 my $output;
282 my @lines;
283 $output = '""' . "\n";
284 @lines = split( /\\n/, $dequoted, -1 );
285 my $lastline = pop @lines; # special treatment for this one
286 foreach (@lines) {
287 $output .= $self->quote("$_\\n") . "\n";
289 $output .= $self->quote($lastline) . "\n" if $lastline ne "";
290 return $output;
292 else {
294 # Single line
295 return "$string\n";
299 sub dump {
300 my Locale::PO $self = shift;
301 my $dump;
302 $dump .= $self->_dump_multi_comment( $self->comment, "# " )
303 if defined( $self->comment );
304 $dump .= $self->_dump_multi_comment( $self->automatic, "#. " )
305 if defined( $self->automatic );
306 $dump .= $self->_dump_multi_comment( $self->reference, "#: " )
307 if defined( $self->reference );
308 $self->_update_flagstr();
309 $dump .= $self->_dump_multi_comment( $self->{'_flagstr'}, "#, " )
310 if defined( $self->{'_flagstr'} );
311 $dump .= "msgid " . $self->_normalize_str( $self->msgid )
312 if $self->msgid;
313 $dump .= "msgid_plural " . $self->_normalize_str( $self->msgid_plural )
314 if $self->msgid_plural;
316 $dump .= "msgstr " . $self->_normalize_str( $self->msgstr )
317 if $self->msgstr;
319 if ( my $msgstr_n = $self->msgstr_n ) {
320 $dump .= "msgstr[$_] " . $self->_normalize_str( $$msgstr_n{$_} )
321 for sort { $a <=> $b } keys %$msgstr_n;
324 $dump =~ s/^(?!#)/#~ /gm if $self->{_obsolete};
325 $dump .= "\n";
326 return $dump;
329 # Methods whose names begin with "_" may be changed or removed in
330 # future versions.
331 sub _dump_multi_comment {
332 my $self = shift; # can be called as a class method
333 my $comment = shift;
334 my $leader = shift;
335 my $chopped = $leader;
336 chop($chopped);
337 my $result = $leader . $comment;
338 $result =~ s/\n/\n$leader/g;
339 $result =~ s/^$leader$/$chopped/gm;
340 $result .= "\n";
341 return $result;
344 # Quote a string properly
345 sub quote {
346 my $self = shift; # can be called as a class method
347 my $string = shift;
348 $string =~ s/"/\\"/g;
349 return "\"$string\"";
352 sub dequote {
353 my $self = shift; # can be called as a class method
354 my $string = shift;
355 $string =~ s/^"(.*)"/$1/gm;
356 $string =~ s/\\"/"/g;
357 return $string;
360 sub save_file_fromarray {
361 my $self = shift; # normally called as a class method
362 $self->save_file( @_, 0 );
365 sub save_file_fromhash {
366 my $self = shift; # normally called as a class method
367 $self->save_file( @_, 1 );
370 sub save_file {
371 my $self = shift; # normally called as a class method
372 my $file = shift;
373 my $entries = shift;
374 my $ashash = shift;
375 my $err = undef;
376 open( OUT, ">$file" ) or return undef;
377 if ($ashash) {
378 foreach ( sort keys %$entries ) {
379 print OUT $entries->{$_}->dump or $err=$!, last;
382 else {
383 foreach (@$entries) {
384 print OUT $_->dump or $err=$!, last;
387 close OUT or $err=$!;
388 if ($err) { $!=$err; return undef }
389 else { return 1 }
392 sub load_file_asarray {
393 my $self = shift; # normally called as a class method
394 my $file = shift;
395 my @entries;
396 my $po;
397 my $last_buffer;
398 use constant {
399 # Nothing other than comments has been seen for $po yet.
400 # $po may also be undef.
401 # On comment: save it, and stay in this state.
402 # On msgid: save it, and switch to STATE_STRING.
403 # On some other string: warn that the msgid is missing,
404 # and redo in STATE_STRING.
405 STATE_COMMENT => 1,
407 # A non-comment string has been seen for $po.
408 # $po can not be undef.
409 # If $po->{msgid} is undef, that has already been warned about.
410 # On comment: close the entry, and redo in STATE_COMMENT.
411 # On msgid: close the entry, and redo in STATE_COMMENT.
412 # On some other string: save it, and stay in this state.
413 STATE_STRING => 2,
415 my $state = STATE_COMMENT;
416 local $/ = "\n";
417 local $_;
419 # "my sub" not yet implemented
420 my $check_and_push_entry = sub {
421 # Call this only if defined($po).
422 warn "$file:$.: Expected msgid\n"
423 unless defined $po->{msgid} or $state == STATE_STRING;
424 if (defined $po->{msgid_plural}) {
425 warn "$file:$.: Expected msgstr[n]\n"
426 unless defined $po->{msgstr_n};
428 else {
429 warn "$file:$.: Expected msgstr\n"
430 unless defined $po->{msgstr};
433 push( @entries, $po);
434 $po = undef;
435 $last_buffer = undef;
438 open( IN, "<$file" ) or return undef;
439 LINE: while (<IN>) {
440 chomp;
441 my $obsolete = s/^#~ ?//;
442 next LINE if /^$/;
444 if (/^"/) {
445 # Continued string. This is very common, so check it first.
446 warn("$file:$.: There is no string to be continued\n"), next LINE
447 unless defined $last_buffer;
448 $$last_buffer .= "\n$_";
450 elsif (/^#([,.:]?)()$/ or /^#([,.:]?) (.*)$/) {
451 &$check_and_push_entry if $state == STATE_STRING;
452 $state = STATE_COMMENT;
453 $po = new Locale::PO unless defined $po;
455 my $comment;
456 if ($1 eq "") { $comment = \$po->{comment} }
457 elsif ($1 eq ",") { $comment = \$po->{_flagstr} }
458 elsif ($1 eq ".") { $comment = \$po->{automatic} }
459 elsif ($1 eq ":") { $comment = \$po->{reference} }
460 else { warn "Bug: did not recognize '$1'"; next LINE }
462 if (defined( $$comment )) { $$comment .= "\n$2" }
463 else { $$comment = $2 }
465 elsif (/^msgid (.*)$/) {
466 &$check_and_push_entry if $state == STATE_STRING;
467 $state = STATE_STRING;
468 $po = new Locale::PO unless defined $po;
469 $last_buffer = \($po->{msgid} = $1);
470 $po->{_msgid_begin_lineno} = $.;
472 elsif (/^msgid_plural (.*)$/) {
473 if ($state == STATE_COMMENT) {
474 warn "$file:$.: Expected msgid\n";
475 $po = new Locale::PO unless defined $po;
476 $state = STATE_STRING;
478 if (defined $po->{msgid_plural}) {
479 warn "$file:$.: Replacing previous msgid_plural\n";
481 elsif (defined $po->{msgstr}) {
482 warn "$file:$.: Should not have msgid_plural with msgstr\n";
484 $last_buffer = \($po->{msgid_plural} = $1);
486 elsif (/^msgstr (.*)$/) {
487 if ($state == STATE_COMMENT) {
488 warn "$file:$.: Expected msgid\n";
489 $po = new Locale::PO unless defined $po;
490 $state = STATE_STRING;
492 if (defined $po->{msgstr}) {
493 warn "$file:$.: Replacing previous msgstr\n";
495 elsif (defined $po->{msgid_plural}) {
496 warn "$file:$.: Should not have msgstr with msgid_plural\n";
498 elsif (defined $po->{msgstr_n}) {
499 warn "$file:$.: Should not have msgstr with msgstr[n]\n";
501 $last_buffer = \($po->{msgstr} = $1);
502 $po->{_msgstr_begin_lineno} = $.;
504 elsif (/^msgstr\[(\d+)\] (.*)$/) {
505 if ($state == STATE_COMMENT) {
506 warn "$file:$.: Expected msgid\n";
507 $po = new Locale::PO unless defined $po;
508 $state = STATE_STRING;
510 if (defined $po->{msgstr_n}) {
511 warn "$file:$.: Replacing previous msgstr[$1]\n"
512 if defined $po->{msgstr_n}{$1};
514 elsif (defined $po->{msgstr}) {
515 warn "$file:$.: Should not have msgstr[n] with msgstr\n";
517 $last_buffer = \($po->{msgstr_n}{$1} = $2);
519 else {
520 warn "$file:$.: Ignoring strange line: $_\n";
522 $po->{_obsolete} = 1 if $obsolete && defined $po;
524 &$check_and_push_entry if defined $po;
525 close IN;
526 return \@entries;
529 sub load_file_ashash {
530 my $self = shift; # normally called as a class method
531 my $file = shift;
532 my $entries = $self->load_file_asarray( $file );
533 my %entries;
535 ENTRY: foreach my $po (@$entries) {
536 my $msgid = $po->msgid;
537 if (!defined( $msgid )) {
538 # The entry had no msgid line in the input file.
539 # &load_file_asarray already warned about that. Such
540 # entries have no identity and cannot be put in the hash.
541 next ENTRY;
543 # The hash keys were quoted strings in Locale-PO-0.16,
544 # so keep them that way. However, if the same string has
545 # been quoted in two different ways, there should not be
546 # two different hash entries. Canonicalize the key.
547 my $key = $po->quote( $po->dequote( $msgid ));
548 if (exists( $entries{$key} ) && $entries{$key}->msgstr =~ /\w/) {
549 # This msgid has a translation already. Don't replace it.
550 next ENTRY;
552 $entries{$key} = $po;
555 return \%entries;
558 sub load_file {
559 my $self = shift; # normally called as a class method
560 my $file = shift;
561 my $ashash = shift;
563 if ($ashash) {
564 return $self->load_file_ashash($file);
566 else {
567 return $self->load_file_asarray($file);
571 # Autoload methods go after =cut, and are processed by the autosplit program.
574 __END__
576 # Below is the stub of documentation for your module. You better edit it!
578 =head1 NAME
580 Locale::PO - Perl module for manipulating .po entries from GNU gettext
582 =head1 SYNOPSIS
584 use Locale::PO;
586 $po = new Locale::PO([-option=>value,...])
588 # get fields # set fields
589 $fully_quoted = $po->msgid; $po->msgid($backslashed);
590 $fully_quoted = $po->msgid_plural; $po->msgid_plural($backslashed);
591 $fully_quoted = $po->msgstr; $po->msgstr($backslashed);
592 $lineno = $po->msgstr_begin_lineno;
593 $fully_quoted_href = $po->msgstr_n; $po->msgstr_n($backslashed_href);
594 $string = $po->comment; $po->comment($string);
595 $string = $po->automatic; $po->automatic($string);
596 $string = $po->reference; $po->reference($string);
597 $flag = $po->fuzzy; $po->fuzzy($flag);
598 $flag = $po->obsolete; $po->obsolete($flag);
599 $tristate = $po->c_format; $po->c_format($tristate);
600 $tristate = $po->php_format; $po->php_format($tristate);
602 print $po->dump;
604 $fully_quoted_string = $po->quote($backslashed_string);
605 $backslashed_string = $po->dequote($fully_quoted_string);
607 $aref = Locale::PO->load_file_asarray($filename);
608 $href = Locale::PO->load_file_ashash($filename);
609 $ref = Locale::PO->load_file($filename, $ashash);
610 Locale::PO->save_file_fromarray($filename, $aref);
611 Locale::PO->save_file_fromhash($filename, $href);
612 Locale::PO->save_file($filename, $ref, $fromhash);
614 =head1 DESCRIPTION
616 This module simplifies management of GNU gettext .po files and is an
617 alternative to using emacs po-mode. It provides an object-oriented
618 interface in which each entry in a .po file is a Locale::PO object.
620 =head2 Levels of Quoting
622 When you use methods of Locale::PO, you need to distinguish between
623 three possible levels of quoting strings. These levels are described
624 below. The descriptions also list how the following sample msgid
625 string would be quoted in each level.
627 msgid "The characters /\\ denote the \"AND\" operator.\n"
628 "Please enter all numbers in octal."
630 =over
632 =item FULLY-QUOTED
634 The same format as in a PO file: the string may consist of multiple
635 lines, and each line has double-quote characters around it and may
636 contain backslash sequences. Any double-quote or backslash characters
637 that should be part of the data must be escaped with backslashes.
639 The example in Perl syntax: C<qq("The characters /\\\\ denote the
640 \\"AND\\" operator.\\n"\n"Please enter all numbers in octal.")>
642 =item BACKSLASHED
644 The string may consist of multiple lines. The lines do not have
645 double-quote characters around them, but they may contain backslash
646 sequences. Any backslash characters that should be part of the data
647 must be escaped with backslashes, but double-quote characters must not.
649 The example in Perl syntax: C<qq(The characters /\\\\ denote the
650 "AND" operator.\\n\nPlease enter all numbers in octal.)>
652 =item NOT-QUOTED
654 This is the format that a C program would pass to the C<gettext>
655 function or output to a terminal device. Any remaining quotes are
656 part of the data itself, and backslash escapes have been replaced
657 with control characters. Locale::PO does not currently support
658 this quoting level.
660 The example in Perl syntax: C<qq(The characters /\\ denote the "AND"
661 operator.\nPlease enter all numbers in octal.)>
663 =back
665 =head1 METHODS
667 =over 4
669 =item new
671 my Locale::PO $po = new Locale::PO;
672 my Locale::PO $po = new Locale::PO(%options);
674 Create a new Locale::PO object to represent a po entry.
675 You can optionally set the attributes of the entry by passing
676 a list/hash of the form:
678 -option=>value, -option=>value, etc.
680 Where options are msgid, msgstr, comment, automatic, reference, fuzzy,
681 c-format, and no-c-format. See accessor methods below. Currently, you
682 cannot set the "obsolete" or "php-format" flags via options.
684 To generate a po file header, add an entry with an empty
685 msgid, like this:
687 $po = new Locale::PO(-msgid=>'', -msgstr=>
688 "Project-Id-Version: PACKAGE VERSION\\n" .
689 "PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\\n" .
690 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n" .
691 "Language-Team: LANGUAGE <LL@li.org>\\n" .
692 "MIME-Version: 1.0\\n" .
693 "Content-Type: text/plain; charset=CHARSET\\n" .
694 "Content-Transfer-Encoding: ENCODING\\n");
696 Note that the C<msgid> and C<msgstr> must be in BACKSLASHED form.
698 =item msgid
700 $fully_quoted_string = $po->msgid;
701 # $backslashed_string = $po->dequote($fully_quoted_string);
702 $po->msgid($backslashed_string);
704 Set or get the untranslated string from the object.
706 The value is C<undef> if there is no such string for this message, not
707 even an empty string. If the message was loaded from a PO file, this
708 can occur if there are comments after the last C<msgid> line. The
709 loading functions warn about such omissions.
711 This method expects the new string in BACKSLASHED form
712 but returns the current string in FULLY-QUOTED form.
714 =item msgid_begin_lineno
716 $line_number = $po->msgid_begin_lineno;
718 Get the line number at which the C<msgid> string begins in the PO file.
719 This is undef if the entry was not loaded from a file.
720 There is currently no setter method for this field.
722 =item msgid_plural
724 $fully_quoted_string = $po->msgid_plural;
725 # $backslashed_string = $po->dequote($fully_quoted_string);
726 $po->msgid_plural($backslashed_string);
728 Set or get the untranslated plural string from the object. The value
729 is C<undef> if there is no plural form for this message.
731 This method expects the new string in BACKSLASHED form
732 but returns the current string in FULLY-QUOTED form.
734 =item msgstr
736 $fully_quoted_string = $po->msgstr;
737 # $backslashed_string = $po->dequote($fully_quoted_string);
738 $po->msgstr($backslashed_string);
740 Set or get the translated string from the object.
742 If the string has plural forms, then they are instead accessible via
743 C<msgstr_n>, and C<msgstr> normally returns C<undef>. However, if the
744 entry has been loaded from an incorrectly formatted PO file, then it
745 is also possible that both C<msgstr> and C<msgstr_n> return C<undef>,
746 or that they both return defined values. The loading functions warn
747 about such transgressions.
749 This method expects the new string in BACKSLASHED form
750 but returns the current string in FULLY-QUOTED form.
752 =item msgstr_begin_lineno
754 $line_number = $po->msgstr_begin_lineno;
756 Get the line number at which the C<msgstr> string begins in the PO file.
757 This is undef if the entry was not loaded from a file.
758 There is currently no setter method for this field.
760 =item msgstr_n
762 $fully_quoted_hashref = $po->msgstr_n;
763 # $backslashed_hashref = { %$fully_quoted_hashref };
764 # $_ = $po->dequote($_) foreach values(%$backslashed_hashref);
765 $po->msgstr_n($backslashed_hashref);
767 Get or set the translations if there are plurals involved. Takes and
768 returns a hashref where the keys are the 'N' case and the values are
769 the strings. eg:
771 $po->msgstr_n(
773 0 => 'found %d plural translations',
774 1 => 'found %d singular translation',
778 The value C<undef> should be treated the same as an empty hash.
779 Callers should neither modify the hash to which the returned reference
780 points, nor assume it to remain valid if C<msgstr_n> is later called
781 to install a new set of translations.
783 This method expects the new strings in BACKSLASHED form
784 but returns the current strings in FULLY-QUOTED form.
786 =item comment
788 $string = $po->comment;
789 $po->comment($string);
791 Set or get translator comments from the object.
793 If there are no such comments, then the value is C<undef>. Otherwise,
794 the value is a string that contains the comment lines delimited with
795 "\n". The string includes neither the S<"# "> at the beginning of
796 each comment line nor the newline at the end of the last comment line.
798 =item automatic
800 $string = $po->automatic;
801 $po->automatic($string);
803 Set or get automatic comments from the object (inserted by
804 emacs po-mode or xgettext).
806 If there are no such comments, then the value is C<undef>. Otherwise,
807 the value is a string that contains the comment lines delimited with
808 "\n". The string includes neither the S<"#. "> at the beginning of
809 each comment line nor the newline at the end of the last comment line.
811 =item reference
813 $string = $po->reference;
814 $po->reference($string);
816 Set or get reference marking comments from the object (inserted
817 by emacs po-mode or gettext).
819 If there are no such comments, then the value is C<undef>. Otherwise,
820 the value is a string that contains the comment lines delimited with
821 "\n". The string includes neither the S<"#: "> at the beginning of
822 each comment line nor the newline at the end of the last comment line.
824 =item fuzzy
826 $flag = $po->fuzzy;
827 $po->fuzzy($flag);
829 Set or get the fuzzy flag on the object ("check this translation").
830 When setting, use 1 to turn on fuzzy, and 0 to turn it off.
832 =item obsolete
834 $flag = $po->obsolete;
835 $po->obsolete($flag);
837 Set or get the obsolete flag on the object ("no longer used").
838 When setting, use 1 to turn on obsolete, and 0 to turn it off.
840 =item c_format
842 $tristate = $po->obsolete;
843 $po->obsolete($tristate);
845 Set or get the c-format or no-c-format flag on the object.
846 This can take 3 values: 1 implies c-format, 0 implies no-c-format,
847 and blank or undefined implies neither.
849 =item php_format
851 $tristate = $po->php_format;
852 $po->php_format($tristate);
854 Set or get the php-format or no-php-format flag on the object.
855 This can take 3 values: 1 implies php-format, 0 implies no-php-format,
856 and blank or undefined implies neither.
858 =item dump
860 print $po->dump;
862 Returns the entry as a string, suitable for output to a po file.
864 =item quote
866 $fully_quoted_string = $po->quote($backslashed_string);
868 Converts a string from BACKSLASHED to FULLY-QUOTED form.
869 Specifically, the quoted string will have all existing double-quote
870 characters escaped by backslashes, and each line will be enclosed in
871 double quotes. Preexisting backslashes will not be doubled.
873 =item dequote
875 $backslashed_string = $po->dequote($fully_quoted_string);
877 Converts a string from FULLY-QUOTED to BACKSLASHED form.
878 Specifically, it first removes the double-quote characters that
879 surround each line. After this, each remaining double-quote character
880 should have a backslash in front of it; the method then removes those
881 backslashes. Backslashes in any other position will be left intact.
883 =item load_file_asarray
885 $arrayref = Locale::PO->load_file_asarray($filename);
887 Given the filename of a po-file, reads the file and returns a
888 reference to a list of Locale::PO objects corresponding to the contents of
889 the file, in the same order.
891 If the file cannot be read, then this method returns C<undef>, and you
892 can check C<$!> for the actual error. If the file does not follow the
893 expected syntax, then the method generates warnings but keeps going.
894 Other errors (e.g. out of memory) may result in C<die> being called,
895 of course.
897 =item load_file_ashash
899 $hashref = Locale::PO->load_file_ashash($filename);
901 Given the filename of a po-file, reads the file and returns a
902 reference to a hash of Locale::PO objects corresponding to the contents of
903 the file. The hash keys are the untranslated strings (in BACKSLASHED form),
904 so this is a cheap way to remove duplicates. The method will prefer to keep
905 entries that have been translated.
907 This handles errors in the same way as C<load_file_asarray> does.
909 =item load_file
911 $ref = Locale::PO->load_file($filename, $ashash);
913 This method behaves as C<load_file_asarray> if the C<$ashash>
914 parameter is 0, or as C<load_file_ashash> if C<$ashash> is 1.
915 Your code will probably be easier to understand if you call either
916 of those methods instead of this one.
918 =item save_file_fromarray
920 $ok = Locale::PO->save_file_fromarray($filename, \@objects)
922 Given a filename and a reference to a list of Locale::PO objects,
923 saves those objects to the file, creating a po-file.
925 Returns true if successful.
926 Returns C<undef> and sets C<$!> if an I/O error occurs.
927 Dies if a serious error occurs.
929 =item save_file_fromhash
931 $ok = Locale::PO->save_file_fromhash($filename, \%objects);
933 Given a filename and a reference to a hash of Locale::PO objects,
934 saves those objects to the file, creating a po-file. The entries
935 are sorted alphabetically by untranslated string.
937 Returns true if successful.
938 Returns C<undef> and sets C<$!> if an I/O error occurs.
939 Dies if a serious error occurs.
941 =item save_file
943 $ok = Locale::PO->save_file($filename, $ref, $fromhash);
945 This method behaves as C<save_file_fromarray> if the C<$fromhash>
946 parameter is 0, or as C<save_file_fromhash> if C<$fromhash> is 1.
947 Your code will probably be easier to understand if you call either
948 of those methods instead of this one.
950 =back
952 =head1 AUTHOR
954 Alan Schwartz, alansz@pennmush.org
956 =head1 DIFFERENCES FROM Locale-PO-0.16
958 List of changes in this file, as stipulated in section 3. of the
959 L<"Artistic License"|perlartistic> and subsection 2. a) of L<GNU
960 General Public License version 2|perlgpl>:
962 =over 4
964 =item Z<>2006-01-06 Kalle Olavi Niemitalo <kon@iki.fi>
966 Appended ".kon" to C<$VERSION>.
967 Use C<fields>, and C<my Locale::PO> where applicable.
969 POD changes:
970 Added the copyright notice (from F<README>) and this history.
971 Corrected a typo in the documentation.
972 Documented quoting in the C<msgid>, C<msgid_plural>, C<msgstr>, and C<msgstr_n> methods.
973 Documented newlines in the C<comment>, C<automatic>, and C<reference> methods.
975 =item Z<>2006-01-07 Kalle Olavi Niemitalo <kon@iki.fi>
977 POD changes:
978 Documented the C<php_format> method.
980 =item Z<>2006-01-08 Kalle Olavi Niemitalo <kon@iki.fi>
982 POD changes:
983 Greatly expanded the L</BUGS> section.
984 Reformatted this list of changes.
986 =item Z<>2006-02-05 Kalle Olavi Niemitalo <kon@iki.fi>
988 Added comments about the fields of Locale::PO objects.
989 The C<load_file> function binds C<$/> and C<$_> dynamically.
990 Renamed C<normalize_str> to C<_normalize_str>, and C<dump_multi_comment> to C<_dump_multi_comment>.
992 POD changes:
993 Documented C<load_file> and C<save_file>.
995 =item Z<>2006-02-11 Kalle Olavi Niemitalo <kon@iki.fi>
997 Rewrote the file parser. It now warns about various inconsistencies, and no longer relies on empty lines.
998 The parser writes directly to fields of Locale::PO objects, preserving internal newlines in strings. Changed C<dequote> to process all lines of multi-line strings.
999 The parser supports obsolete entries. Added the C<_obsolete> field and the C<obsolete> method. C<dump> comments the entry out if it is obsolete.
1000 The parser preserves the original string of flags and scans it more carefully. Added the C<_flag> field. Implemented "no-php-format".
1001 C<dump> dumps comments even if they are C<eq "0">.
1003 POD changes:
1004 Documented the bugs fixed with the changes above.
1005 Documented levels of quoting, and the exact behaviour of C<quote> and C<dequote>.
1006 Documented the C<obsolete> method.
1007 Documented error handling in C<load_file_asarray> and C<load_file_ashash>.
1008 Documented when C<msgid>, C<msgstr> etc. can return C<undef>.
1010 =item Z<>2006-02-12 Kalle Olavi Niemitalo <kon@iki.fi>
1012 C<save_file> returns C<undef> and remembers C<$!> if C<print> fails.
1013 C<load_file_asarray> saves line numbers of C<msgid> and C<msgstr>. New fields C<_msgid_begin_lineno> and C<_msgstr_begin_lineno>; new methods C<msgid_begin_lineno> and C<msgstr_begin_lineno>.
1015 POD changes:
1016 Revised the synopses of the methods, paying attention to levels of quoting.
1017 Repeat the synopsis above the description of each method.
1018 Never write C<< CZ<><Locale::PO> >>; it looks bad in B<pod2text>.
1019 Documented that C<msgstr> normally returns C<undef> if there are plurals.
1020 Documented the new methods C<msgid_begin_lineno> and C<msgstr_begin_lineno>.
1022 =item Z<>2006-02-18 Kalle Olavi Niemitalo <kon@iki.fi>
1024 Locale::PO now preserves unrecognized flags, although there is still no documented way to access them. It also preserves the order of flags, if no flags are modified. Replaced the C<fuzzy>, C<c_format>, and C<php_format> fields with C<_flaghash>, and renamed the C<_flag> field to C<_flagstr>.
1025 Flag-setting functions silently map unsupported values (e.g. 42) to supported ones (e.g. 1), which they also return.
1026 The C<c_format> and C<php_format> methods treat empty strings as C<undef>, rather than as 0.
1027 Names of flags are case-sensitive, like in GNU Gettext.
1029 POD changes:
1030 Unlisted the bugs that have now been fixed.
1032 =item Z<>2006-02-19 Kalle Olavi Niemitalo <kon@iki.fi>
1034 The C<dump> method doesn't output an C<msgid> if there isn't one.
1036 =back
1038 =head1 COPYRIGHT AND LICENSE
1040 Copyright (c) 2000-2004 Alan Schwartz <alansz@pennmush.org>.
1041 All rights reserved. This program is free software; you can
1042 redistribute it and/or modify it under the same terms as Perl itself.
1044 =head1 BUGS
1046 If you C<load_file> then C<save_file>, the output file may have slight
1047 cosmetic differences from the input file (an extra blank line here or there).
1049 The C<quote> and C<dequote> methods assume Perl knows the encoding
1050 of the string. If it doesn't, they'll treat each 0x5C byte as a
1051 backslash even if it's actually part of a multibyte character.
1052 Therefore, Locale::PO should parse the charset parameter from the
1053 header entry, and decode the strings with that. It is unclear whether
1054 the charset must be decoded even before the newlines and quotes are
1055 parsed; this would mainly be a requirement with UTF-16, which GNU
1056 Gettext doesn't support.
1058 =head2 Almost Bugs
1060 C<msgid_begin_lineno> and C<msgstr_begin_lineno> are read-only.
1061 Perhaps there should also be ways to get the line numbers of the
1062 other strings. Probably not line numbers of comments, though.
1064 The C<msgid>, C<msgid_plural>, C<msgstr>, and C<msgstr_n> methods
1065 output FULLY-QUOTED strings, but they expect BACKSLASHED strings as
1066 input. It would be better to have both FULLY-QUOTED or both
1067 BACKSLASHED; or perhaps C<< $po->msgid(-level => 'BACKSLASHED') >>.
1069 Locale::PO discards all types of comments it does not recognize.
1070 The B<msgmerge> program of GNU gettext-tools 0.14.3 does the same,
1071 so perhaps it's not a problem.
1073 =head1 SEE ALSO
1075 xgettext(1).
1077 =cut