Locale-Maketext-Fuzzy-0.11/000755 000765 000024 00000000000 11671011253 016354 5ustar00audreytstaff000000 000000 Locale-Maketext-Fuzzy-0.11/Changes000644 000765 000024 00000001303 11671011110 017634 0ustar00audreytstaff000000 000000 [Changes for 0.11 - 2011-12-11] * LICENSING CHANGE: This compilation and all individual files in it are now under public domain with the "CC0 Universal" declaration. * Skip fuzzy matches which are only placeholders and whitespace. (Alex Vandiver) [Changes for 0.10 - 2007-10-14] * LICENSING CHANGE: This compilation and all individual files in it are now under the permissive "MIT" license. * Modernized the build infrastructure with Module::Install. * Tidied up source code, test files, and this changelog. [Changes for 0.02 - 2002-10-01] * Failed matches no longer interpolates. (This makes normal strings with brackets possible.) [Changes for 0.01 - 2002-08-02] * Initial CPAN release. Locale-Maketext-Fuzzy-0.11/inc/000755 000765 000024 00000000000 11671011252 017124 5ustar00audreytstaff000000 000000 Locale-Maketext-Fuzzy-0.11/lib/000755 000765 000024 00000000000 11671011252 017121 5ustar00audreytstaff000000 000000 Locale-Maketext-Fuzzy-0.11/Makefile.PL000644 000765 000024 00000000071 11671010505 020323 0ustar00audreytstaff000000 000000 #!/usr/bin/env perl use inc::Module::Package 'Au:dry 1'; Locale-Maketext-Fuzzy-0.11/MANIFEST000644 000765 000024 00000000732 11671011251 017505 0ustar00audreytstaff000000 000000 Changes inc/Module/Install.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/GithubMeta.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Package.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm inc/Module/Package.pm inc/Pod/Markdown.pm lib/Locale/Maketext/Fuzzy.pm Makefile.PL MANIFEST This list of files META.yml README README.mkdn SIGNATURE t/0-signature.t t/1-basic.t Locale-Maketext-Fuzzy-0.11/META.yml000644 000765 000024 00000001012 11671011237 017621 0ustar00audreytstaff000000 000000 --- abstract: 'Maketext from already interpolated strings' author: - 'Audrey Tang ' build_requires: ExtUtils::MakeMaker: 6.42 configure_requires: ExtUtils::MakeMaker: 6.42 distribution_type: module generated_by: 'Module::Install version 1.01' license: unrestricted meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 module_name: Locale::Maketext::Fuzzy name: Locale-Maketext-Fuzzy no_index: directory: - inc - t requires: perl: 5.005 version: 0.11 Locale-Maketext-Fuzzy-0.11/README000644 000765 000024 00000014650 11671011237 017244 0ustar00audreytstaff000000 000000 NAME Locale::Maketext::Fuzzy - Maketext from already interpolated strings SYNOPSIS package MyApp::L10N; use base 'Locale::Maketext::Fuzzy'; # instead of Locale::Maketext package MyApp::L10N::de; use base 'MyApp::L10N'; our %Lexicon = ( # Exact match should always be preferred if possible "0 camels were released." => "Exact match", # Fuzzy match candidate "[quant,_1,camel was,camels were] released." => "[quant,_1,Kamel wurde,Kamele wurden] freigegeben.", # This could also match fuzzily, but is less preferred "[_2] released[_1]" => "[_1][_2] ist frei[_1]", ); package main; my $lh = MyApp::L10N->get_handle('de'); # All ->maketext calls below will become ->maketext_fuzzy instead $lh->override_maketext(1); # This prints "Exact match" print $lh->maketext('0 camels were released.'); # "1 Kamel wurde freigegeben." -- quant() gets 1 print $lh->maketext('1 camel was released.'); # "2 Kamele wurden freigegeben." -- quant() gets 2 print $lh->maketext('2 camels were released.'); # "3 Kamele wurden freigegeben." -- parameters are ignored print $lh->maketext('3 released.'); # "4 Kamele wurden freigegeben." -- normal usage print $lh->maketext('[*,_1,camel was,camels were] released.', 4); # "!Perl ist frei!" -- matches the broader one # Note that the sequence ([_2] before [_1]) is preserved print $lh->maketext('Perl released!'); DESCRIPTION This module is a subclass of "Locale::Maketext", with additional support for localizing messages that already contains interpolated variables. This is most useful when the messages are returned by external sources -- for example, to match "dir: command not found" against "[_1]: command not found". Of course, this module is also useful if you're simply too lazy to use the $lh->maketext("[quant,_1,file,files] deleted.", $count); syntax, but wish to write $lh->maketext_fuzzy("$count files deleted"); instead, and have the correct plural form figured out automatically. If "maketext_fuzzy" seems too long to type for you, this module also provides a "override_maketext" method to turn *all* "maketext" calls into "maketext_fuzzy" calls. METHODS $lh->maketext_fuzzy(*key*[, *parameters...*]); That method takes exactly the same arguments as the "maketext" method of "Locale::Maketext". If *key* is found in lexicons, it is applied in the same way as "maketext". Otherwise, it looks at all lexicon entries that could possibly yield *key*, by turning "[...]" sequences into "(.*?)" and match the resulting regular expression against *key*. Once it finds all candidate entries, the longest one replaces the *key* for the real "maketext" call. Variables matched by its bracket sequences ($1, $2...) are placed before *parameters*; the order of variables in the matched entry are correctly preserved. For example, if the matched entry in %Lexicon is "Test [_1]", this call: $fh->maketext_fuzzy("Test string", "param"); is equivalent to this: $fh->maketext("Test [_1]", "string", "param"); However, most of the time you won't need to supply *parameters* to a "maketext_fuzzy" call, since all parameters are already interpolated into the string. $lh->override_maketext([*flag*]); If *flag* is true, this accessor method turns "$lh->maketext" into an alias for "$lh->maketext_fuzzy", so all consecutive "maketext" calls in the $lh's packages are automatically fuzzy. A false *flag* restores the original behaviour. If the flag is not specified, returns the current status of override; the default is 0 (no overriding). Note that this call only modifies the symbol table of the *language class* that $lh belongs to, so other languages are not affected. If you want to override all language handles in a certain application, try this: MyApp::L10N->override_maketext(1); CAVEATS * The "longer is better" heuristic to determine the best match is reasonably good, but could certainly be improved. * Currently, "[quant,_1,file] deleted" won't match "3 files deleted"; you'll have to write "[quant,_1,file,files] deleted" instead, or simply use "[_1] file deleted" as the lexicon key and put the correct plural form handling into the corresponding value. * When used in combination with "Locale::Maketext::Lexicon"'s "Tie" backend, all keys would be iterated over each time a fuzzy match is performed, and may cause serious speed penalty. Patches welcome. SEE ALSO Locale::Maketext, Locale::Maketext::Lexicon HISTORY This particular module was written to facilitate an *auto-extraction* layer for Slashcode's *Template Toolkit* provider, based on "HTML::Parser" and "Template::Parser". It would work like this: Input | from the [% story.dept %] dept. Output| [%|loc( story.dept )%]from the [_1] dept.[%END%] Now, this layer suffers from the same linguistic problems as an ordinary "Msgcat" or "Gettext" framework does -- what if we want to make ordinals from "[% story.dept %]" (i.e. "from the 3rd dept."), or expand the "dept." to "department" / "departments"? The same problem occurred in RT's web interface, where it had to localize messages returned by external modules, which may already contain interpolated variables, e.g. ""Successfully deleted 7 ticket(s) in 'c:\temp'."". Since I didn't have the time to refactor "DBI" and "DBI::SearchBuilder", I devised a "loc_match" method to pre-process their messages into one of the *candidate strings*, then applied the matched string to "maketext". Afterwards, I realized that instead of preparing a set of candidate strings, I could actually match against the original *lexicon file* (i.e. PO files via "Locale::Maketext::Lexicon"). This is how "Locale::Maketext::Fuzzy" was born. AUTHORS Audrey Tang CC0 1.0 Universal To the extent possible under law, 唐鳳 has waived all copyright and related or neighboring rights to Locale-Maketext-Fuzzy. This work is published from Taiwan. Locale-Maketext-Fuzzy-0.11/README.mkdn000644 000765 000024 00000014153 11671011237 020172 0ustar00audreytstaff000000 000000 # NAME Locale::Maketext::Fuzzy - Maketext from already interpolated strings # SYNOPSIS package MyApp::L10N; use base 'Locale::Maketext::Fuzzy'; # instead of Locale::Maketext package MyApp::L10N::de; use base 'MyApp::L10N'; our %Lexicon = ( # Exact match should always be preferred if possible "0 camels were released." => "Exact match", # Fuzzy match candidate "[quant,_1,camel was,camels were] released." => "[quant,_1,Kamel wurde,Kamele wurden] freigegeben.", # This could also match fuzzily, but is less preferred "[_2] released[_1]" => "[_1][_2] ist frei[_1]", ); package main; my $lh = MyApp::L10N->get_handle('de'); # All ->maketext calls below will become ->maketext_fuzzy instead $lh->override_maketext(1); # This prints "Exact match" print $lh->maketext('0 camels were released.'); # "1 Kamel wurde freigegeben." -- quant() gets 1 print $lh->maketext('1 camel was released.'); # "2 Kamele wurden freigegeben." -- quant() gets 2 print $lh->maketext('2 camels were released.'); # "3 Kamele wurden freigegeben." -- parameters are ignored print $lh->maketext('3 released.'); # "4 Kamele wurden freigegeben." -- normal usage print $lh->maketext('[*,_1,camel was,camels were] released.', 4); # "!Perl ist frei!" -- matches the broader one # Note that the sequence ([_2] before [_1]) is preserved print $lh->maketext('Perl released!'); # DESCRIPTION This module is a subclass of `Locale::Maketext`, with additional support for localizing messages that already contains interpolated variables. This is most useful when the messages are returned by external sources -- for example, to match `dir: command not found` against `[_1]: command not found`. Of course, this module is also useful if you're simply too lazy to use the $lh->maketext("[quant,_1,file,files] deleted.", $count); syntax, but wish to write $lh->maketext_fuzzy("$count files deleted"); instead, and have the correct plural form figured out automatically. If `maketext_fuzzy` seems too long to type for you, this module also provides a `override_maketext` method to turn _all_ `maketext` calls into `maketext_fuzzy` calls. # METHODS ## $lh->maketext_fuzzy(_key_[, _parameters..._]); That method takes exactly the same arguments as the `maketext` method of `Locale::Maketext`. If _key_ is found in lexicons, it is applied in the same way as `maketext`. Otherwise, it looks at all lexicon entries that could possibly yield _key_, by turning `[...]` sequences into `(.*?)` and match the resulting regular expression against _key_. Once it finds all candidate entries, the longest one replaces the _key_ for the real `maketext` call. Variables matched by its bracket sequences (`$1`, `$2`...) are placed before _parameters_; the order of variables in the matched entry are correctly preserved. For example, if the matched entry in `%Lexicon` is `Test [_1]`, this call: $fh->maketext_fuzzy("Test string", "param"); is equivalent to this: $fh->maketext("Test [_1]", "string", "param"); However, most of the time you won't need to supply _parameters_ to a `maketext_fuzzy` call, since all parameters are already interpolated into the string. ## $lh->override_maketext([_flag_]); If _flag_ is true, this accessor method turns `$lh->maketext` into an alias for `$lh->maketext_fuzzy`, so all consecutive `maketext` calls in the `$lh`'s packages are automatically fuzzy. A false _flag_ restores the original behaviour. If the flag is not specified, returns the current status of override; the default is 0 (no overriding). Note that this call only modifies the symbol table of the _language class_ that `$lh` belongs to, so other languages are not affected. If you want to override all language handles in a certain application, try this: MyApp::L10N->override_maketext(1); # CAVEATS - The "longer is better" heuristic to determine the best match is reasonably good, but could certainly be improved. - Currently, `"[quant,_1,file] deleted"` won't match `"3 files deleted"`; you'll have to write `"[quant,_1,file,files] deleted"` instead, or simply use `"[_1] file deleted"` as the lexicon key and put the correct plural form handling into the corresponding value. - When used in combination with `Locale::Maketext::Lexicon`'s `Tie` backend, all keys would be iterated over each time a fuzzy match is performed, and may cause serious speed penalty. Patches welcome. # SEE ALSO [Locale::Maketext](http://search.cpan.org/perldoc?Locale::Maketext), [Locale::Maketext::Lexicon](http://search.cpan.org/perldoc?Locale::Maketext::Lexicon) # HISTORY This particular module was written to facilitate an _auto-extraction_ layer for Slashcode's _Template Toolkit_ provider, based on `HTML::Parser` and `Template::Parser`. It would work like this: Input | from the [% story.dept %] dept. Output| [%|loc( story.dept )%]from the [_1] dept.[%END%] Now, this layer suffers from the same linguistic problems as an ordinary `Msgcat` or `Gettext` framework does -- what if we want to make ordinals from `[% story.dept %]` (i.e. `from the 3rd dept.`), or expand the `dept.` to `department` / `departments`? The same problem occurred in RT's web interface, where it had to localize messages returned by external modules, which may already contain interpolated variables, e.g. `"Successfully deleted 7 ticket(s) in 'c:\temp'."`. Since I didn't have the time to refactor `DBI` and `DBI::SearchBuilder`, I devised a `loc_match` method to pre-process their messages into one of the _candidate strings_, then applied the matched string to `maketext`. Afterwards, I realized that instead of preparing a set of candidate strings, I could actually match against the original _lexicon file_ (i.e. PO files via `Locale::Maketext::Lexicon`). This is how `Locale::Maketext::Fuzzy` was born. # AUTHORS Audrey Tang # CC0 1.0 Universal To the extent possible under law, 唐鳳 has waived all copyright and related or neighboring rights to Locale-Maketext-Fuzzy. This work is published from Taiwan. [http://creativecommons.org/publicdomain/zero/1.0](http://creativecommons.org/publicdomain/zero/1.0)Locale-Maketext-Fuzzy-0.11/SIGNATURE000644 000765 000024 00000004132 11671011253 017640 0ustar00audreytstaff000000 000000 This file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.68. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 579ccb49e2964dc987bed621a43bd4e35557abde Changes SHA1 538423015aaec0a95230f0684fe6f643929eaf41 MANIFEST SHA1 ce7f0fbbd97c08fe069e7cbbf1f5a01215eb277e META.yml SHA1 9e01754121ecd53c68cb1f5b0c02ebb7b4fce959 Makefile.PL SHA1 ba427236a1c626d098fe0a99abb0b66a5e64acc5 README SHA1 7607f8dd40c93d4f0b9580fa59a2561589084ee4 README.mkdn SHA1 7b4ae50ebac72d20761171c4c2b50c206344ea40 inc/Module/Install.pm SHA1 d9fe55a427fe2fd75b5029afeeaa61b592e07f79 inc/Module/Install/Base.pm SHA1 62d3922826d9f89f20c185e7031ac8f028504745 inc/Module/Install/Can.pm SHA1 dc809f64fb70a26b069a36f8d3d353d520dbb7e1 inc/Module/Install/Fetch.pm SHA1 82e6709c1cdb488770cb21f6149a7f22913cd8c1 inc/Module/Install/GithubMeta.pm SHA1 73ab91490a628452cc140db72ef9d13a1326d211 inc/Module/Install/Makefile.pm SHA1 8ce3f2b414e4617e6233dd4ba10830f8c5d672ec inc/Module/Install/Metadata.pm SHA1 a815f14e3aeaa8c6f5f318cda7a2fb431b462780 inc/Module/Install/Package.pm SHA1 3b0acd2eeac93a0afe48120f5648f0db362e5bbf inc/Module/Install/Win32.pm SHA1 f08924f051e623f8e09fa6a121993c4a9cf7d9eb inc/Module/Install/WriteAll.pm SHA1 5011127553463730d768e68ac9765d28d21490b1 inc/Module/Package.pm SHA1 ccb48d3fec5ef96403f50b13eec529ce10961c02 inc/Pod/Markdown.pm SHA1 4673f68c8a614668d68488ca173af3bfa6948d9e lib/Locale/Maketext/Fuzzy.pm SHA1 41afe2c04bb573b40e283e2b210ed70a47a3f8ba t/0-signature.t SHA1 ccd6690df0db3383aeb608c753c91736ab301cff t/1-basic.t -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (Darwin) iEYEARECAAYFAk7kEqoACgkQtLPdNzw1AaDWKACfToL4CJ/cu1Cckt1lHbE8CaWg WDcAoISo8RbTssmcyFaPmuaDoFGtQufe =z8R5 -----END PGP SIGNATURE----- Locale-Maketext-Fuzzy-0.11/t/000755 000765 000024 00000000000 11671011252 016616 5ustar00audreytstaff000000 000000 Locale-Maketext-Fuzzy-0.11/t/0-signature.t000644 000765 000024 00000001337 10704256154 021155 0ustar00audreytstaff000000 000000 #!/usr/bin/perl use strict; print "1..1\n"; if (!$ENV{TEST_SIGNATURE}) { print "ok 1 # skip set the environment variable TEST_SIGNATURE to enable this test\n"; } elsif (!-s 'SIGNATURE') { print "ok 1 # skip No signature file found\n"; } elsif (!eval { require Module::Signature; 1 }) { print "ok 1 # skip ", "Next time around, consider install Module::Signature, ", "so you can verify the integrity of this distribution.\n"; } elsif (!eval { require Socket; Socket::inet_aton('pgp.mit.edu') }) { print "ok 1 # skip ", "Cannot connect to the keyserver\n"; } else { (Module::Signature::verify() == Module::Signature::SIGNATURE_OK()) or print "not "; print "ok 1 # Valid signature\n"; } __END__ Locale-Maketext-Fuzzy-0.11/t/1-basic.t000644 000765 000024 00000004073 10704256161 020234 0ustar00audreytstaff000000 000000 #!/usr/bin/perl -w use strict; use Test::More tests => 15; package MyApp::L10N; use Test::More; use Locale::Maketext::Fuzzy; use_ok(base => 'Locale::Maketext::Fuzzy'); package MyApp::L10N::de; use vars qw/@ISA %Lexicon/; @ISA = 'MyApp::L10N'; %Lexicon = ( # Exact match should always be preferred if possible "0 camels were released." => "Exact match", # Fuzzy match candidate "[*,_1,camel was,camels were] released." => "[quant,_1,Kamel wurde,Kamele wurden] freigegeben.", # This could also match fuzzily, but is less preferred "[_2] released[_1]" => "[_1][_2] ist frei[_1]", ); package main; ################################################################ ok(my $lh = MyApp::L10N->get_handle('de'), 'get_handle'); is($lh->override_maketext, 0, 'override_maketext() is initially 0'); is($lh->override_maketext(0), 0, 'override_maketext(0)'); is($lh->override_maketext(1), 1, 'override_maketext(1)'); is($lh->override_maketext(undef), 0, 'override_maketext(undef) is 0'); is($lh->override_maketext(-1), 1, 'override_maketext(-1) is 1'); is($lh->override_maketext, 1, 'override_maketext() is now 1'); ################################################################ is( $lh->maketext('0 camels were released.'), 'Exact match', 'exact match', ); is( $lh->maketext('1 camel was released.'), '1 Kamel wurde freigegeben.', 'fuzzy match - singular', ); is( $lh->maketext('2 camels were released.'), '2 Kamele wurden freigegeben.', 'fuzzy match - plural', ); is( $lh->maketext('3 released.'), '3 Kamele wurden freigegeben.', 'fuzzy match - ignore parameters', ); is( $lh->maketext('[*,_1,camel was,camels were] released.', 4), '4 Kamele wurden freigegeben.', 'exact match on the bracketed entry', ); is( $lh->maketext('[Perl] released!'), '![Perl] ist frei!', 'fuzzy match on the broader candidate', ); is( eval { $lh->maketext('Square [bracket]!') }, 'Square [bracket]!', 'no interpolation on failed matches', ); ################################################################ 1; Locale-Maketext-Fuzzy-0.11/lib/Locale/000755 000765 000024 00000000000 11671011252 020320 5ustar00audreytstaff000000 000000 Locale-Maketext-Fuzzy-0.11/lib/Locale/Maketext/000755 000765 000024 00000000000 11671011252 022102 5ustar00audreytstaff000000 000000 Locale-Maketext-Fuzzy-0.11/lib/Locale/Maketext/Fuzzy.pm000644 000765 000024 00000023044 11671011116 023571 0ustar00audreytstaff000000 000000 package Locale::Maketext::Fuzzy; $Locale::Maketext::Fuzzy::VERSION = '0.11'; use 5.005; use strict; use Locale::Maketext; use base 'Locale::Maketext'; sub override_maketext { my ( $class, $flag ) = @_; $class = ref($class) if ref($class); no strict 'refs'; if ($flag) { *{"$class\::maketext"} = \&maketext_fuzzy; } elsif ( @_ >= 2 ) { delete ${"$class\::"}{maketext}; } return ( defined &{"$class\::maketext"} ? 1 : 0 ); } # Global cache of entries and their regexified forms my %regex_cache; sub maketext_fuzzy { my ( $handle, $phrase ) = splice( @_, 0, 2 ); # An array of all lexicon hashrefs my @lexicons = @{ $handle->_lex_refs }; # Try exact match if possible at all. foreach my $lex (@lexicons) { return $handle->SUPER::maketext( $phrase, @_ ) if exists $lex->{$phrase}; } # Keys are matched entries; values are arrayrefs of extracted params my %candidate; # Fuzzy match phase 1 -- extract all candidates foreach my $lex (@lexicons) { # We're not interested in non-bracketed entries, so ignore them foreach my $entry ( grep /(?:(?[0] ) or next; $candidate{$entry} ||= ( @{ $re->[1] } ? [ @vars[ @{ $re->[1] } ] ] : \@vars ); } } # Fail early if we cannot find anything that matches return $phrase unless %candidate; # Fuzzy match phase 2 -- select the best candidate $phrase = ( sort { # For now, we just use a very crude heuristic: "Longer is better" length($b) <=> length($a) or $b cmp $a } keys %candidate )[0]; return $handle->SUPER::maketext( $phrase, @{ $candidate{$phrase} }, @_ ); } sub _regexify { my $text = quotemeta(shift); my @ords; $text =~ s{ ( # capture into $1... (? length($a) # longest first } map { /^_(?:(\d+)|\\\*)$/ ? do { push @{$ordref}, ( $1 - 1 ) if defined $1; ''; } : $_ # turn _1, _2, _*... into '' } @choices ) . ')'; $out =~ s/\Q(?:)\E$//; } return $out; } 1; =head1 NAME Locale::Maketext::Fuzzy - Maketext from already interpolated strings =head1 SYNOPSIS package MyApp::L10N; use base 'Locale::Maketext::Fuzzy'; # instead of Locale::Maketext package MyApp::L10N::de; use base 'MyApp::L10N'; our %Lexicon = ( # Exact match should always be preferred if possible "0 camels were released." => "Exact match", # Fuzzy match candidate "[quant,_1,camel was,camels were] released." => "[quant,_1,Kamel wurde,Kamele wurden] freigegeben.", # This could also match fuzzily, but is less preferred "[_2] released[_1]" => "[_1][_2] ist frei[_1]", ); package main; my $lh = MyApp::L10N->get_handle('de'); # All ->maketext calls below will become ->maketext_fuzzy instead $lh->override_maketext(1); # This prints "Exact match" print $lh->maketext('0 camels were released.'); # "1 Kamel wurde freigegeben." -- quant() gets 1 print $lh->maketext('1 camel was released.'); # "2 Kamele wurden freigegeben." -- quant() gets 2 print $lh->maketext('2 camels were released.'); # "3 Kamele wurden freigegeben." -- parameters are ignored print $lh->maketext('3 released.'); # "4 Kamele wurden freigegeben." -- normal usage print $lh->maketext('[*,_1,camel was,camels were] released.', 4); # "!Perl ist frei!" -- matches the broader one # Note that the sequence ([_2] before [_1]) is preserved print $lh->maketext('Perl released!'); =head1 DESCRIPTION This module is a subclass of C, with additional support for localizing messages that already contains interpolated variables. This is most useful when the messages are returned by external sources -- for example, to match C against C<[_1]: command not found>. Of course, this module is also useful if you're simply too lazy to use the $lh->maketext("[quant,_1,file,files] deleted.", $count); syntax, but wish to write $lh->maketext_fuzzy("$count files deleted"); instead, and have the correct plural form figured out automatically. If C seems too long to type for you, this module also provides a C method to turn I C calls into C calls. =head1 METHODS =head2 $lh->maketext_fuzzy(I[, I]); That method takes exactly the same arguments as the C method of C. If I is found in lexicons, it is applied in the same way as C. Otherwise, it looks at all lexicon entries that could possibly yield I, by turning C<[...]> sequences into C<(.*?)> and match the resulting regular expression against I. Once it finds all candidate entries, the longest one replaces the I for the real C call. Variables matched by its bracket sequences (C<$1>, C<$2>...) are placed before I; the order of variables in the matched entry are correctly preserved. For example, if the matched entry in C<%Lexicon> is C, this call: $fh->maketext_fuzzy("Test string", "param"); is equivalent to this: $fh->maketext("Test [_1]", "string", "param"); However, most of the time you won't need to supply I to a C call, since all parameters are already interpolated into the string. =head2 $lh->override_maketext([I]); If I is true, this accessor method turns C<$lh-Emaketext> into an alias for C<$lh-Emaketext_fuzzy>, so all consecutive C calls in the C<$lh>'s packages are automatically fuzzy. A false I restores the original behaviour. If the flag is not specified, returns the current status of override; the default is 0 (no overriding). Note that this call only modifies the symbol table of the I that C<$lh> belongs to, so other languages are not affected. If you want to override all language handles in a certain application, try this: MyApp::L10N->override_maketext(1); =head1 CAVEATS =over 4 =item * The "longer is better" heuristic to determine the best match is reasonably good, but could certainly be improved. =item * Currently, C<"[quant,_1,file] deleted"> won't match C<"3 files deleted">; you'll have to write C<"[quant,_1,file,files] deleted"> instead, or simply use C<"[_1] file deleted"> as the lexicon key and put the correct plural form handling into the corresponding value. =item * When used in combination with C's C backend, all keys would be iterated over each time a fuzzy match is performed, and may cause serious speed penalty. Patches welcome. =back =head1 SEE ALSO L, L =head1 HISTORY This particular module was written to facilitate an I layer for Slashcode's I