Locale...::Fuzzy(3pm)
π Locale::Maketext::Fuzzy π
okay bestie, so this is Locale::Maketext::Fuzzy β the 3pm perl manual page, from the User Contributed Perl Documentation. It's giving "maketext, but make it β¨fuzzyβ¨" and honestly? iconic.
πΈ NAME πΈ
Locale::Maketext::Fuzzy β Maketext from already interpolated strings. like, the strings already did their little interpolation thing and we're just vibing with it.
β¨ SYNOPSIS β¨
no cap, here's the whole vibe in code:
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 π¦
so this module is a subclass of Locale::Maketext, and it adds extra support for localizing messages that already contain interpolated variables. yeah. the variables are already in there. it's fine. we deal with it. π
this is highkey most useful when the messages come back from external sources β like, for example, matching dir: command not found against [_1]: command not found. chef's kiss.
and of course, this module is also useful if you're simply too lazy to write
$lh->maketext("[quant,_1,file,files] deleted.", $count);
but you wish to write
$lh->maketext_fuzzy("$count files deleted");
instead, and have the correct plural form figured out automatically. the way that it just knows? obsessed. π«Ά
and if maketext_fuzzy is too long to type for you (no judgement, typing is hard), this module also provides an override_maketext method to turn all maketext calls into maketext_fuzzy calls. slay.
π METHODS π
π $lh->maketext_fuzzy(key[, parameters...]);
this method takes exactly the same arguments as the maketext method of Locale::Maketext. no extra hoops, no drama.
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 matching the resulting regular expression against key. it's giving detective energy fr fr. π
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. periodt.
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. they're already there bestie, they did the work. π
π $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. keep that in mind bestie, don't be surprised when the other languages don't get the memo. π
if you want to override all language handles in a certain application, try this:
MyApp::L10N->override_maketext(1);
main character energy, honestly.
π CAVEATS π
- the "longer is better" heuristic to determine the best match is reasonably good, but could certainly be improved. it's doing its best. π
- currently,
[quant,_1,file] deletedwon't match3 files deleted; you'll have to write[quant,_1,file,files] deletedinstead, or simply use[_1] file deletedas the lexicon key and put the correct plural form handling into the corresponding value. yeah. you gotta spell it out. that's just how it is. π - when used in combination with
Locale::Maketext::Lexicon'sTiebackend, all keys would be iterated over each time a fuzzy match is performed, and may cause serious speed penalty. patches welcome. π₯² like, genuinely, patches welcome.
π₯ SEE ALSO π₯
Locale::MaketextLocale::Maketext::Lexicon
go read those too, iykyk. π
β 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 | <B>from the [% story.dept %] dept.</B>
Output| <B>[%|loc( story.dept )%]from the [_1] dept.[%END%]</B>
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 linguistic drama never ends bestie. π
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. β¨ birth of an icon, truly.
π AUTHORS π
Audrey Tang <cpan@audreyt.org>
π 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>
π POD ERRORS π
hey! the above document had some coding errors, which are explained below:
around line 318:
Non-ASCII character seen before =encoding in 'ει³³'. Assuming UTF-8
not me getting called out for the non-ASCII characters, the audacity β but like, they're in the author's name, so. π assuming UTF-8, as one does.
and that's the whole page bestie!! π«Ά this was perl v5.36.0, dated 2022-12-13, from the Locale::Maketext::Fuzzy(3pm) manual β go forth and fuzzy-match your interpolated strings, you absolute legend. πβ¨π
π¦ where this page comes from
- debian bookworm: liblocale-maketext-fuzzy-perl 0.11-3 Β· CC0-1.0
- debian trixie: liblocale-maketext-fuzzy-perl 0.11-3 Β· CC0-1.0
- ubuntu noble: liblocale-maketext-fuzzy-perl 0.11-3 Β· CC0-1.0
- ubuntu resolute: liblocale-maketext-fuzzy-perl 0.11-3 Β· CC0-1.0
- ubuntu stonking: liblocale-maketext-fuzzy-perl 0.11-3 Β· CC0-1.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms