1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
extern crate accept_language;
pub extern crate rocket;
pub extern crate tinystr;
pub extern crate unic_langid;
mod macros;
use unic_langid::parser::parse_language_identifier;
pub use unic_langid::LanguageIdentifier;
use rocket::request::{self, FromRequest, Request};
use rocket::Outcome;
#[derive(Debug, Clone)]
pub struct AcceptLanguage {
pub accept_language: Vec<LanguageIdentifier>,
}
macro_rules! impl_request_guard {
($request:ident) => {
{
let raw_accept_language: Option<&str> = $request.headers().get("accept-language").next();
match raw_accept_language {
Some(raw_accept_language) => {
let accept_language_split = accept_language::parse(raw_accept_language);
let accept_language = accept_language_split.iter().filter_map(|al| parse_language_identifier(al).ok()).collect();
AcceptLanguage {
accept_language
}
}
None => AcceptLanguage {
accept_language: Vec::new()
}
}
}
}
}
impl<'a, 'r> FromRequest<'a, 'r> for AcceptLanguage {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Outcome::Success(impl_request_guard!(request))
}
}
impl<'a, 'r> FromRequest<'a, 'r> for &'a AcceptLanguage {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
Outcome::Success(request.local_cache(|| impl_request_guard!(request)))
}
}
impl AcceptLanguage {
pub fn get_first_region(&self) -> Option<&str> {
for locale in &self.accept_language {
let region = locale.get_region();
if region.is_some() {
return region;
}
}
None
}
pub fn get_first_language(&self) -> Option<&str> {
self.accept_language.iter().next().map(|locale| locale.get_language())
}
pub fn get_first_language_region(&self) -> Option<(&str, Option<&str>)> {
if let Some(locale) = self.accept_language.iter().next() {
let language = locale.get_language();
let region = locale.get_region();
Some((language, region))
} else {
None
}
}
pub fn get_appropriate_language_region(
&self,
locales: &[LanguageIdentifier],
) -> Option<(&str, Option<&str>)> {
let mut filtered_language = None;
for locale in &self.accept_language {
let language = locale.get_language();
for t_locale in locales {
let t_language = t_locale.get_language();
if language == t_language {
let region = locale.get_region();
let t_region = t_locale.get_region();
if region == t_region {
return Some((language, region));
} else if filtered_language.is_none() {
filtered_language = Some((language, None));
}
}
}
}
filtered_language
}
}