File Coverage

blib/lib/Locale/POFileManager.pm
Criterion Covered Total %
statement 2 4 50.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 4 6 66.6


line stmt bran cond sub pod time code
1             package Locale::POFileManager;
2             BEGIN {
3 4     4   399738 $Locale::POFileManager::AUTHORITY = 'cpan:DOY';
4             }
5             {
6             $Locale::POFileManager::VERSION = '0.05';
7             }
8 4     4   8231 use Moose 0.90;
  0            
  0            
9             use MooseX::Types::Path::Class qw(Dir);
10             use Scalar::Util qw(reftype weaken);
11             # ABSTRACT: Helpers for keeping a set of related .po files in sync
12              
13              
14              
15             has base_dir => (
16             is => 'ro',
17             isa => Dir,
18             required => 1,
19             coerce => 1,
20             );
21              
22              
23             has files => (
24             traits => [qw(Array)],
25             isa => 'ArrayRef[Locale::POFileManager::File]',
26             lazy => 1,
27             builder => '_build_files',
28             init_arg => undef,
29             handles => {
30             files => 'elements',
31             _first_file => 'first',
32             _add_file => 'push',
33             },
34             );
35              
36             sub _build_files {
37             my $self = shift;
38             my $dir = $self->base_dir;
39              
40             require Locale::POFileManager::File;
41              
42             my @files;
43             for my $file ($dir->children) {
44             next if $file->is_dir;
45             next unless $file->stringify =~ /\.po$/;
46             my $msgstr = $self->stub_msgstr;
47             push @files, Locale::POFileManager::File->new(
48             file => $file,
49             defined($msgstr) ? (stub_msgstr => $msgstr) : (),
50             );
51             }
52              
53             return \@files;
54             }
55              
56              
57             has canonical_language => (
58             is => 'ro',
59             isa => 'Str',
60             required => 1, # TODO: make this not required at some point?
61             );
62              
63             has _stub_msgstr => (
64             is => 'ro',
65             isa => 'Str|CodeRef',
66             init_arg => 'stub_msgstr',
67             );
68              
69             sub BUILD {
70             my $self = shift;
71              
72             confess("Canonical language file must exist")
73             unless $self->has_language($self->canonical_language);
74             }
75              
76              
77             sub stub_msgstr {
78             my $self = shift;
79             my $msgstr = $self->_stub_msgstr;
80             return unless defined($msgstr);
81             return $msgstr if !reftype($msgstr);
82             my $weakself = $self;
83             weaken($weakself);
84             return sub {
85             my %args = @_;
86             my $canonical_msgstr;
87             $canonical_msgstr =
88             $weakself->canonical_language_file->msgstr($args{msgid})
89             if $weakself;
90             return $msgstr->(
91             %args,
92             defined($canonical_msgstr) ? (canonical_msgstr => $canonical_msgstr) : (),
93             );
94             }
95             }
96              
97              
98             sub has_language {
99             my $self = shift;
100             my ($lang) = @_;
101              
102             for my $file ($self->files) {
103             return 1 if $file->language eq $lang;
104             }
105              
106             return;
107             }
108              
109              
110             sub add_language {
111             my $self = shift;
112             my ($lang) = @_;
113              
114             return if $self->has_language($lang);
115              
116             my $file = $self->base_dir->file("$lang.po");
117             confess("Can't overwrite existing language file for $lang")
118             if -e $file->stringify;
119              
120             my $canon_pofile = $self->canonical_language_file;
121              
122             my $fh = $file->openw;
123             $fh->binmode(':utf8');
124             $fh->print(qq{msgid ""\n});
125             $fh->print(qq{msgstr ""\n});
126             for my $header_key ($canon_pofile->headers) {
127             $fh->print(qq{"$header_key: }
128             . $canon_pofile->header($header_key)
129             . qq{\\n"\n});
130             }
131             $fh->print(qq{\n});
132             $fh->close;
133              
134             my $msgstr = $self->stub_msgstr;
135             my $pofile = Locale::POFileManager::File->new(
136             file => $file,
137             defined($msgstr) ? (stub_msgstr => $msgstr) : (),
138             );
139              
140              
141             $self->_add_file($pofile);
142             }
143              
144              
145             sub language_file {
146             my $self = shift;
147             my ($lang) = @_;
148              
149             return $self->_first_file(sub {
150             $_->language eq $lang;
151             });
152             }
153              
154              
155             sub canonical_language_file {
156             my $self = shift;
157             return $self->language_file($self->canonical_language);
158             }
159              
160              
161             sub find_missing {
162             my $self = shift;
163             my $canon_file = $self->canonical_language_file;
164              
165             my %ret;
166             for my $file ($self->files) {
167             $ret{$file->language} = [$file->find_missing_from($canon_file)];
168             }
169              
170             return %ret;
171             }
172              
173              
174             sub add_stubs {
175             my $self = shift;
176             my $canon_file = $self->canonical_language_file;
177              
178             for my $file ($self->files) {
179             $file->add_stubs_from($canon_file);
180             }
181             }
182              
183             __PACKAGE__->meta->make_immutable;
184             no Moose;
185              
186              
187             1;
188              
189             __END__
190              
191             =pod
192              
193             =head1 NAME
194              
195             Locale::POFileManager - Helpers for keeping a set of related .po files in sync
196              
197             =head1 VERSION
198              
199             version 0.05
200              
201             =head1 SYNOPSIS
202              
203             use Locale::POFileManager;
204              
205             my $manager = Locale::POFileManager->new(
206             base_dir => '/path/to/app/i18n/po',
207             canonical_language => 'en',
208             );
209              
210             my %missing = $manager->find_missing;
211             $manager->add_stubs;
212             $manager->add_language('de');
213              
214             =head1 DESCRIPTION
215              
216             This module contains helpers for managing a set of gettext translation files,
217             including tools to keep the translation files in sync, adding new translation
218             files, and manipulating the translations contained in the files. It is based on
219             the L<Locale::Maketext::Lexicon> parser library.
220              
221             =head1 METHODS
222              
223             =head2 new
224              
225             Accepts a hash of arguments:
226              
227             =over 4
228              
229             =item base_dir
230              
231             The directory that contains the .po files. Required.
232              
233             =item canonical_language
234              
235             The language for the file that contains the canonical set of msgids. Required.
236              
237             =item stub_msgstr
238              
239             The msgstr to insert when adding stubs to language files. This can be either a
240             literal string, or a coderef which accepts a hash containing the keys C<msgid>,
241             C<lang>, and C<canonical_msgstr> (the msgstr value from the
242             C<canonical_language>. Optional.
243              
244             =back
245              
246             =head2 base_dir
247              
248             Returns a L<Path::Class::Dir> object corresponding to the C<base_dir> passed to
249             the constructor.
250              
251             =head2 files
252              
253             Returns a list of L<Locale::POFileManager::File> objects corresponding to the
254             .po files that were found in the C<base_dir>.
255              
256             =head2 canonical_language
257              
258             Returns the canonical language id passed to the constructor.
259              
260             =head2 stub_msgstr
261              
262             Returns the string passed to the constructor as C<stub_msgstr> if it was a
263             string, or a coderef wrapped to supply the C<canonical_msgstr> option if it was
264             a coderef.
265              
266             =head2 has_language
267              
268             Returns true if a language file exists for the given language in the
269             C<base_dir>, false otherwise.
270              
271             =head2 add_language
272              
273             Creates a new language file for the language passed in as an argument. Creates
274             a header for that file copied over from the header in the C<canonical_language>
275             language file, and saves the newly created file in the C<base_dir>.
276              
277             =head2 language_file
278              
279             Returns the L<Locale::POFileManager::File> object corresponding to the given
280             language.
281              
282             =head2 canonical_language_file
283              
284             Returns the L<Locale::POFileManager::File> object corresponding to the
285             C<canonical_language>.
286              
287             =head2 find_missing
288              
289             Searches through all of the files in the C<base_dir>, and returns a hash
290             mapping language names to an arrayref of msgids that were found in the
291             C<canonical_language> file but not in the file for that language.
292              
293             =head2 add_stubs
294              
295             Adds stub msgid (and possibly msgstr, if the C<stub_msgstr> option was given)
296             entries to each language file for each msgid found in the C<canonical_language>
297             file but not in the language file.
298              
299             =head1 BUGS
300              
301             No known bugs.
302              
303             Please report any bugs through RT: email
304             C<bug-locale-pofilemanager at rt.cpan.org>, or browse to
305             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Locale-POFileManager>.
306              
307             =head1 SEE ALSO
308              
309             L<Locale::Maketext::Lexicon>
310              
311             L<Locale::Maketext>
312              
313             L<Locale::PO>
314              
315             =head1 SUPPORT
316              
317             You can find this documentation for this module with the perldoc command.
318              
319             perldoc Locale::POFileManager
320              
321             You can also look for information at:
322              
323             =over 4
324              
325             =item * AnnoCPAN: Annotated CPAN documentation
326              
327             L<http://annocpan.org/dist/Locale-POFileManager>
328              
329             =item * CPAN Ratings
330              
331             L<http://cpanratings.perl.org/d/Locale-POFileManager>
332              
333             =item * RT: CPAN's request tracker
334              
335             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Locale-POFileManager>
336              
337             =item * Search CPAN
338              
339             L<http://search.cpan.org/dist/Locale-POFileManager>
340              
341             =back
342              
343             =for Pod::Coverage BUILD
344              
345             =head1 AUTHOR
346              
347             Jesse Luehrs <doy at tozt dot net>
348              
349             =head1 COPYRIGHT AND LICENSE
350              
351             This software is copyright (c) 2013 by Jesse Luehrs.
352              
353             This is free software; you can redistribute it and/or modify it under
354             the same terms as the Perl 5 programming language system itself.
355              
356             =cut