File Coverage

blib/lib/Mojolicious/Plugin/Localize/Quantify.pm
Criterion Covered Total %
statement 32 32 100.0
branch 32 34 94.1
condition 16 21 76.1
subroutine 4 4 100.0
pod 1 1 100.0
total 85 92 92.3


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Localize::Quantify;
2 12     12   9362 use Mojo::Base 'Mojolicious::Plugin';
  12         23  
  12         94  
3 12     12   3154 use Scalar::Util qw/looks_like_number/;
  12         27  
  12         9351  
4              
5             # From http://search.cpan.org/~toddr/Locale-Maketext-1.26/lib/Locale/Maketext.pod
6             # >> The basic quant method that Locale::Maketext provides should be good for many languages. For some languages, it might be useful to modify it (or its constituent numerate method) to take a plural form in the two-argument call to quant (as in "[quant,_1,files]") if it's all-around easier to infer the singular form from the plural, than to infer the plural form from the singular. <<
7              
8             our $RANGE_RE = qr/^\s*?([<>]?)\s*([-+]?\d+?)(?:\s*\.\.\s*([-+]?\d+))?\s*$/;
9              
10             # Register the plugin
11             sub register {
12 13     13 1 555 my ($self, $mojo) = @_;
13              
14             # Establish helper
15             $mojo->helper(
16             quant => sub {
17 44     44   11720 my $c = shift;
18 44         62 my $num = shift;
19              
20 44 50       137 return '' unless looks_like_number $num;
21              
22             # Check for parameter hash
23 44 100 66     222 my $param = pop if $_[-1] && ref $_[-1] && ref $_[-1] eq 'HASH';
      66        
24 44         72 my $default = shift;
25              
26             # There are no other dictionary entries
27 44 50 66     86 return $default if !$param && @_ == 0;
28              
29             # Plural default value
30 44         69 my $default_pl = shift;
31              
32             # Zero default value
33 44   100     113 my $default_null = shift // $default;
34              
35             # It's a bit more complicated ...
36 44 100       65 if ($param) {
37              
38             # Exact match found
39 35 100       116 return $param->{$num} if exists $param->{$num};
40              
41             # Iterate over all parameters
42 28         136 foreach (sort keys %$param) {
43 84 100       534 next unless $_ =~ $RANGE_RE;
44              
45             # 'Littler than' or 'greater than'
46 70 100       188 if ($1) {
    100          
47 21 100       39 if ($1 eq '<') {
48 6 100       28 return $param->{$_} if $num < $2;
49             }
50             else {
51 15 100       51 return $param->{$_} if $num > $2;
52             };
53             }
54              
55             # Range
56             elsif ($3) {
57 21 100 100     116 return $param->{$_} if $num >= $2 && $num <= $3;
58             };
59             };
60              
61             # Check for 'even' value
62 14 100       29 if ($num % 2 == 0) {
63 8 100       32 return $param->{even} if exists $param->{even};
64             }
65              
66             # Check for 'odd' value
67             else {
68 6 100       23 return $param->{odd} if exists $param->{odd};
69             };
70             };
71              
72             # Simple plural value
73 16 100 66     39 if ($num > 1 || $num < -1) {
    100          
74 9   66     40 return $default_pl // $default;
75             }
76             # Simple null value
77             elsif ($num == 0) {
78 4         13 return $default_null;
79             };
80              
81             # Default value
82 3         14 return $default;
83             }
84 13         206 );
85             };
86              
87              
88             1;
89              
90              
91             =pod
92              
93             =head1 NAME
94              
95             Mojolicious::Plugin::Localize::Quantify - Localize Quantifiable Expressions
96              
97              
98             =head1 SYNOPSIS
99              
100             my $g_counter = 5;
101              
102             # Get singular and plural expression, depending on number
103             my $word = $c->quant($g_counter, 'guest', 'guests');
104              
105             # In templates
106             %= quant $g_counter, 'guest', 'guests'
107              
108              
109             =head1 DESCRIPTION
110              
111             L helps you to get countable expressions
112             of words depending on the number of units (e.g. singular or plural expressions).
113              
114              
115             =head1 METHODS
116              
117             L inherits all methods
118             from L and implements the following
119             new ones.
120              
121              
122             =head2 register
123              
124             # Mojolicious
125             $mojo->plugin('Localize::Quantify');
126              
127             # Mojolicious::Lite
128             plugin 'Localize::Quantify';
129              
130             Called when registering the plugin.
131             The plugin is registered by L by default.
132              
133              
134             =head1 HELPERS
135              
136             =head2 quant
137              
138             my $number = 3;
139              
140             my $was = $c->quant($number, 'was', 'were');
141             my $tree = $c->quant($number, 'tree', 'trees');
142             print "There $was $number $tree.";
143             # There were 3 trees.
144              
145             my $count = $c->quant($number, 'some', {
146             0 => 'no',
147             1 => 'one',
148             2 => 'both',
149             '3..11' => 'a few',
150             12 => 'a dozen',
151             '>50' => 'many'
152             });
153             print "There $was $count $tree.";
154             # There were a few trees.
155              
156             # In templates
157             %= quant $g_counter, 'guest', 'guests'
158              
159             Return an expression based on a given number.
160              
161             Expects at least 2 parameters: The number which the lookup is based on and
162             a default dictionary entry (e.g. a singular term).
163             This can be followed by two optional scalar parameters: the first optional
164             parameter is an entry chosen for all numerical values E 1 or E -1,
165             the second parameter is an entry chosen for the zero value.
166              
167             A final hash reference can refine the lookup, overriding the given default parameters.
168             Supported keys for dictionary lookups are as follows:
169              
170             =over 2
171              
172             =item Exact Matches
173              
174             {
175             2 => 'both',
176             12 => 'dozens'
177             }
178              
179             =item Boundaries
180              
181             {
182             '< 5' => 'few',
183             '> 14' => 'many'
184             }
185              
186             =item Ranges
187              
188             {
189             '100 .. 999' => 'hundreds',
190             '1000 .. 9999' => 'thousands'
191             }
192              
193             =item Even/odd
194              
195             {
196             even => 'robots',
197             odd => 'humans'
198             }
199              
200             =back
201              
202             Exact matches have the highest precedence, followed by ranges and boundaries
203             in arbitrary order. Even and odd values will match before the default values.
204              
205              
206             =head1 DEPENDENCIES
207              
208             L.
209              
210              
211             =head1 AVAILABILITY
212              
213             https://github.com/Akron/Mojolicious-Plugin-Localize
214              
215              
216             =head1 COPYRIGHT AND LICENSE
217              
218             Copyright (C) 2014-2016, L.
219              
220             This program is free software, you can redistribute it
221             and/or modify it under the terms of the Artistic License version 2.0.
222              
223             =cut