README
1NAME
2 Locale::Maketext::Fuzzy - Maketext from already interpolated strings
3
4SYNOPSIS
5 package MyApp::L10N;
6 use base 'Locale::Maketext::Fuzzy'; # instead of Locale::Maketext
7
8 package MyApp::L10N::de;
9 use base 'MyApp::L10N';
10 our %Lexicon = (
11 # Exact match should always be preferred if possible
12 "0 camels were released."
13 => "Exact match",
14
15 # Fuzzy match candidate
16 "[quant,_1,camel was,camels were] released."
17 => "[quant,_1,Kamel wurde,Kamele wurden] freigegeben.",
18
19 # This could also match fuzzily, but is less preferred
20 "[_2] released[_1]"
21 => "[_1][_2] ist frei[_1]",
22 );
23
24 package main;
25 my $lh = MyApp::L10N->get_handle('de');
26
27 # All ->maketext calls below will become ->maketext_fuzzy instead
28 $lh->override_maketext(1);
29
30 # This prints "Exact match"
31 print $lh->maketext('0 camels were released.');
32
33 # "1 Kamel wurde freigegeben." -- quant() gets 1
34 print $lh->maketext('1 camel was released.');
35
36 # "2 Kamele wurden freigegeben." -- quant() gets 2
37 print $lh->maketext('2 camels were released.');
38
39 # "3 Kamele wurden freigegeben." -- parameters are ignored
40 print $lh->maketext('3 released.');
41
42 # "4 Kamele wurden freigegeben." -- normal usage
43 print $lh->maketext('[*,_1,camel was,camels were] released.', 4);
44
45 # "!Perl ist frei!" -- matches the broader one
46 # Note that the sequence ([_2] before [_1]) is preserved
47 print $lh->maketext('Perl released!');
48
49DESCRIPTION
50 This module is a subclass of "Locale::Maketext", with additional support
51 for localizing messages that already contains interpolated variables.
52
53 This is most useful when the messages are returned by external sources
54 -- for example, to match "dir: command not found" against "[_1]: command
55 not found".
56
57 Of course, this module is also useful if you're simply too lazy to use
58 the
59
60 $lh->maketext("[quant,_1,file,files] deleted.", $count);
61
62 syntax, but wish to write
63
64 $lh->maketext_fuzzy("$count files deleted");
65
66 instead, and have the correct plural form figured out automatically.
67
68 If "maketext_fuzzy" seems too long to type for you, this module also
69 provides a "override_maketext" method to turn *all* "maketext" calls
70 into "maketext_fuzzy" calls.
71
72METHODS
73 $lh->maketext_fuzzy(*key*[, *parameters...*]);
74 That method takes exactly the same arguments as the "maketext" method of
75 "Locale::Maketext".
76
77 If *key* is found in lexicons, it is applied in the same way as
78 "maketext". Otherwise, it looks at all lexicon entries that could
79 possibly yield *key*, by turning "[...]" sequences into "(.*?)" and
80 match the resulting regular expression against *key*.
81
82 Once it finds all candidate entries, the longest one replaces the *key*
83 for the real "maketext" call. Variables matched by its bracket sequences
84 ($1, $2...) are placed before *parameters*; the order of variables in
85 the matched entry are correctly preserved.
86
87 For example, if the matched entry in %Lexicon is "Test [_1]", this call:
88
89 $fh->maketext_fuzzy("Test string", "param");
90
91 is equivalent to this:
92
93 $fh->maketext("Test [_1]", "string", "param");
94
95 However, most of the time you won't need to supply *parameters* to a
96 "maketext_fuzzy" call, since all parameters are already interpolated
97 into the string.
98
99 $lh->override_maketext([*flag*]);
100 If *flag* is true, this accessor method turns "$lh->maketext" into an
101 alias for "$lh->maketext_fuzzy", so all consecutive "maketext" calls in
102 the $lh's packages are automatically fuzzy. A false *flag* restores the
103 original behaviour. If the flag is not specified, returns the current
104 status of override; the default is 0 (no overriding).
105
106 Note that this call only modifies the symbol table of the *language
107 class* that $lh belongs to, so other languages are not affected. If you
108 want to override all language handles in a certain application, try
109 this:
110
111 MyApp::L10N->override_maketext(1);
112
113CAVEATS
114 * The "longer is better" heuristic to determine the best match is
115 reasonably good, but could certainly be improved.
116
117 * Currently, "[quant,_1,file] deleted" won't match "3 files deleted";
118 you'll have to write "[quant,_1,file,files] deleted" instead, or
119 simply use "[_1] file deleted" as the lexicon key and put the
120 correct plural form handling into the corresponding value.
121
122 * When used in combination with "Locale::Maketext::Lexicon"'s "Tie"
123 backend, all keys would be iterated over each time a fuzzy match is
124 performed, and may cause serious speed penalty. Patches welcome.
125
126SEE ALSO
127 Locale::Maketext, Locale::Maketext::Lexicon
128
129HISTORY
130 This particular module was written to facilitate an *auto-extraction*
131 layer for Slashcode's *Template Toolkit* provider, based on
132 "HTML::Parser" and "Template::Parser". It would work like this:
133
134 Input | <B>from the [% story.dept %] dept.</B>
135 Output| <B>[%|loc( story.dept )%]from the [_1] dept.[%END%]</B>
136
137 Now, this layer suffers from the same linguistic problems as an ordinary
138 "Msgcat" or "Gettext" framework does -- what if we want to make ordinals
139 from "[% story.dept %]" (i.e. "from the 3rd dept."), or expand the
140 "dept." to "department" / "departments"?
141
142 The same problem occurred in RT's web interface, where it had to
143 localize messages returned by external modules, which may already
144 contain interpolated variables, e.g. ""Successfully deleted 7 ticket(s)
145 in 'c:\temp'."".
146
147 Since I didn't have the time to refactor "DBI" and "DBI::SearchBuilder",
148 I devised a "loc_match" method to pre-process their messages into one of
149 the *candidate strings*, then applied the matched string to "maketext".
150
151 Afterwards, I realized that instead of preparing a set of candidate
152 strings, I could actually match against the original *lexicon file*
153 (i.e. PO files via "Locale::Maketext::Lexicon"). This is how
154 "Locale::Maketext::Fuzzy" was born.
155
156AUTHORS
157 Audrey Tang <cpan@audreyt.org>
158
159CC0 1.0 Universal
160 To the extent possible under law, 唐鳳 has waived all copyright and
161 related or neighboring rights to Locale-Maketext-Fuzzy.
162
163 This work is published from Taiwan.
164
165 <http://creativecommons.org/publicdomain/zero/1.0>
166
167
README.mkdn
1# NAME
2
3Locale::Maketext::Fuzzy - Maketext from already interpolated strings
4
5# SYNOPSIS
6
7 package MyApp::L10N;
8 use base 'Locale::Maketext::Fuzzy'; # instead of Locale::Maketext
9
10 package MyApp::L10N::de;
11 use base 'MyApp::L10N';
12 our %Lexicon = (
13 # Exact match should always be preferred if possible
14 "0 camels were released."
15 => "Exact match",
16
17 # Fuzzy match candidate
18 "[quant,_1,camel was,camels were] released."
19 => "[quant,_1,Kamel wurde,Kamele wurden] freigegeben.",
20
21 # This could also match fuzzily, but is less preferred
22 "[_2] released[_1]"
23 => "[_1][_2] ist frei[_1]",
24 );
25
26 package main;
27 my $lh = MyApp::L10N->get_handle('de');
28
29 # All ->maketext calls below will become ->maketext_fuzzy instead
30 $lh->override_maketext(1);
31
32 # This prints "Exact match"
33 print $lh->maketext('0 camels were released.');
34
35 # "1 Kamel wurde freigegeben." -- quant() gets 1
36 print $lh->maketext('1 camel was released.');
37
38 # "2 Kamele wurden freigegeben." -- quant() gets 2
39 print $lh->maketext('2 camels were released.');
40
41 # "3 Kamele wurden freigegeben." -- parameters are ignored
42 print $lh->maketext('3 released.');
43
44 # "4 Kamele wurden freigegeben." -- normal usage
45 print $lh->maketext('[*,_1,camel was,camels were] released.', 4);
46
47 # "!Perl ist frei!" -- matches the broader one
48 # Note that the sequence ([_2] before [_1]) is preserved
49 print $lh->maketext('Perl released!');
50
51# DESCRIPTION
52
53This module is a subclass of `Locale::Maketext`, with additional
54support for localizing messages that already contains interpolated
55variables.
56
57This is most useful when the messages are returned by external sources
58-- for example, to match `dir: command not found` against
59`[_1]: command not found`.
60
61Of course, this module is also useful if you're simply too lazy
62to use the
63
64 $lh->maketext("[quant,_1,file,files] deleted.", $count);
65
66syntax, but wish to write
67
68 $lh->maketext_fuzzy("$count files deleted");
69
70instead, and have the correct plural form figured out automatically.
71
72If `maketext_fuzzy` seems too long to type for you, this module
73also provides a `override_maketext` method to turn _all_ `maketext`
74calls into `maketext_fuzzy` calls.
75
76# METHODS
77
78## $lh->maketext_fuzzy(_key_[, _parameters..._]);
79
80That method takes exactly the same arguments as the `maketext` method
81of `Locale::Maketext`.
82
83If _key_ is found in lexicons, it is applied in the same way as
84`maketext`. Otherwise, it looks at all lexicon entries that could
85possibly yield _key_, by turning `[...]` sequences into `(.*?)` and
86match the resulting regular expression against _key_.
87
88Once it finds all candidate entries, the longest one replaces the
89_key_ for the real `maketext` call. Variables matched by its bracket
90sequences (`$1`, `$2`...) are placed before _parameters_; the order
91of variables in the matched entry are correctly preserved.
92
93For example, if the matched entry in `%Lexicon` is `Test [_1]`,
94this call:
95
96 $fh->maketext_fuzzy("Test string", "param");
97
98is equivalent to this:
99
100 $fh->maketext("Test [_1]", "string", "param");
101
102However, most of the time you won't need to supply _parameters_ to
103a `maketext_fuzzy` call, since all parameters are already interpolated
104into the string.
105
106## $lh->override_maketext([_flag_]);
107
108If _flag_ is true, this accessor method turns `$lh->maketext`
109into an alias for `$lh->maketext_fuzzy`, so all consecutive
110`maketext` calls in the `$lh`'s packages are automatically fuzzy.
111A false _flag_ restores the original behaviour. If the flag is not
112specified, returns the current status of override; the default is
1130 (no overriding).
114
115Note that this call only modifies the symbol table of the _language
116class_ that `$lh` belongs to, so other languages are not affected.
117If you want to override all language handles in a certain application,
118try this:
119
120 MyApp::L10N->override_maketext(1);
121
122# CAVEATS
123
124- The "longer is better" heuristic to determine the best match is
125reasonably good, but could certainly be improved.
126- Currently, `"[quant,_1,file] deleted"` won't match `"3 files deleted"`;
127you'll have to write `"[quant,_1,file,files] deleted"` instead, or
128simply use `"[_1] file deleted"` as the lexicon key and put the correct
129plural form handling into the corresponding value.
130- When used in combination with `Locale::Maketext::Lexicon`'s `Tie`
131backend, all keys would be iterated over each time a fuzzy match is
132performed, and may cause serious speed penalty. Patches welcome.
133
134# SEE ALSO
135
136[Locale::Maketext](http://search.cpan.org/perldoc?Locale::Maketext), [Locale::Maketext::Lexicon](http://search.cpan.org/perldoc?Locale::Maketext::Lexicon)
137
138# HISTORY
139
140This particular module was written to facilitate an _auto-extraction_
141layer for Slashcode's _Template Toolkit_ provider, based on
142`HTML::Parser` and `Template::Parser`. It would work like this:
143
144 Input | <B>from the [% story.dept %] dept.</B>
145 Output| <B>[%|loc( story.dept )%]from the [_1] dept.[%END%]</B>
146
147Now, this layer suffers from the same linguistic problems as an
148ordinary `Msgcat` or `Gettext` framework does -- what if we want
149to make ordinals from `[% story.dept %]` (i.e. `from the 3rd dept.`),
150or expand the `dept.` to `department` / `departments`?
151
152The same problem occurred in RT's web interface, where it had to
153localize messages returned by external modules, which may already
154contain interpolated variables, e.g. `"Successfully deleted 7
155ticket(s) in 'c:\temp'."`.
156
157Since I didn't have the time to refactor `DBI` and `DBI::SearchBuilder`,
158I devised a `loc_match` method to pre-process their messages into one
159of the _candidate strings_, then applied the matched string to `maketext`.
160
161Afterwards, I realized that instead of preparing a set of candidate
162strings, I could actually match against the original _lexicon file_
163(i.e. PO files via `Locale::Maketext::Lexicon`). This is how
164`Locale::Maketext::Fuzzy` was born.
165
166# AUTHORS
167
168Audrey Tang <cpan@audreyt.org>
169
170# CC0 1.0 Universal
171
172To the extent possible under law, 唐鳳 has waived all copyright and related
173or neighboring rights to Locale-Maketext-Fuzzy.
174
175This work is published from Taiwan.
176
177[http://creativecommons.org/publicdomain/zero/1.0](http://creativecommons.org/publicdomain/zero/1.0)