NAME
Apache2::API::Headers::AcceptLanguage - Parser and matcher for HTTP Accept-Language header
SYNOPSIS
use Apache2::API::Headers::AcceptLanguage;
my $al = Apache2::API::Headers::AcceptLanguage->new( 'fr-FR;q=0.9,en;q=0.8' );
my $locale = $al->match( ['en', 'fr-FR'] ); # => 'fr-FR'
my $prefs = $al->prefs; # => ['fr-FR', 'en']
DESCRIPTION
Parses HTTP Accept-Language header and provides the "match" in Apache2::API::Headers::AcceptCommon method to match against supported locales (languages).
Full tag matches (e.g. fr-FR) trump primary-language matches (e.g. fr matching fr-CA), with quality values (q) per RFC 7231 and RFC 9110. Language/locale parsing is done with Locale::Unicode.
It inherits from Apache2::API::Headers::AcceptCommon.
The algorithm is as follows:
Exact
localematch beats primary language match at the sameq. For example,fr-CAbeatsfrPrimary language tokens, such as
en, can match more specific locales, such asen-GB.*wildcard is a low-specificity fallback and never outranks an equal-qspecific match.Duplicates keep highest
q;q=0excludes a tag.
CONSTRUCTOR
new( $header )
Creates a new instance with the given Accept-Language header string, and returns it.
If an error occurred, it sets an error that can be retrieved with the error method, and it returns undef in scalar context, or an empty list in list context.
METHODS
languages
As per BCP47, and Unicode CLDR, a language is just a 2 to 3-characters code ths is possibly part of a locale. Yet, this method is defined here for convenience.
This is an alias to "preferences"
locales
This is an alias to "preferences"
match( \@supported_locales )
Returns the best matching locale from the provided list of supported locales.
It returns an empty string if nothing matched, or sets an error and returns undef in scalar context, or returns an empty list in list context.
preferences
Read-only.
Returns an array reference of locales, submitted by the user Accept-Language header in his HTTP request, sorted by decreasing quality, with duplicates removed (keeping highest q).
If an error occurred, it sets an error that can be retrieved with the error method, and it returns undef in scalar context, or an empty list in list context.
EXAMPLES
1. Exact beats primary language at same q
my $al = Apache2::API::Headers::AcceptLanguage->new('fr-FR;q=0.9, fr;q=0.9');
$al->match([ 'fr-CA', 'fr-FR' ]);
# "fr-FR"
2. Primary language matches a more specific server locale
my $al = Apache2::API::Headers::AcceptLanguage->new('en;q=0.9, fr;q=0.8');
$al->match([ 'fr-FR', 'en-GB' ]);
# "en-GB"
3. Wildcard at higher q picks first supported
my $al = Apache2::API::Headers::AcceptLanguage->new('*;q=1.0, en;q=0.9');
$al->match([ 'fr-FR', 'en-GB' ]);
# "fr-FR"
LEGACY MATCH PRIORITY
Set $Apache2::API::Headers::AcceptLanguage::MATCH_PRIORITY_0_01_STYLE to true to apply “offer order” tie-breaking within equal-q buckets (see "MATCH PRIORITY MODE" in Apache2::API::Headers::AcceptCommon for details).
NOTES ON TAGS
Tags are parsed using Locale::Unicode. Invalid tags are discarded. For robust behavior, pass your supported locales in the same syntax you intend to serve, such as en, en-GB, ja-JP.
PERFORMANCE
The matchers called with "match" in Apache2::API::Headers::AcceptCommon loops through the array reference of supported locales times the number of parsed acceptable locales as submitted by the client.
Typical HTTP Accept-Language headers are small, so the performance should be very good.
"preferences" in Apache2::API::Headers::AcceptCommon and sorted results are cached per object.
CREDITS
Based on HTTP::AcceptLanguage by Kazuhiro Osawa
AUTHOR
Jacques Deguest <jack@deguest.jp>
SEE ALSO
Apache2::API::Headers::Accept, Apache2::API::Headers::AcceptCommon, Locale::Unicode, RFC 5646 (BCP 47), RFC 7231, RFC 9110.
Apache2::API::DateTime, Apache2::API::Query, Apache2::API::Request, Apache2::API::Request::Params, Apache2::API::Request::Upload, Apache2::API::Response, Apache2::API::Status
Apache2::Request, Apache2::RequestRec, Apache2::RequestUtil
COPYRIGHT & LICENSE
Copyright (c) 2023 DEGUEST Pte. Ltd.
You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.