Skip to content

Commit ff75e85

Browse files
committed
add localizations
1 parent d126613 commit ff75e85

8 files changed

+538
-5
lines changed

src/card.rs

Lines changed: 139 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,16 @@ pub struct Card {
9191
#[serde(skip_serializing_if = "Option::is_none")]
9292
pub preferred_languages: Option<HashMap<String, LanguagePref>>,
9393
/// The calendaring resources of the entity represented by the Card, such as to look up free-busy information.
94-
/// Not localized.
94+
/// Localized by [`localize_calendars`]
9595
#[serde(skip_serializing_if = "Option::is_none")]
9696
pub calendars: Option<HashMap<String, Calendar>>,
9797
/// The scheduling addresses by which the entity may receive calendar scheduling invitations.
98-
/// Not localized.
98+
/// Localized by [`localize_scheduling_addresses`]
9999
#[serde(skip_serializing_if = "Option::is_none")]
100100
pub scheduling_addresses: Option<HashMap<String, SchedulingAddress>>,
101101
/// Localizations provide language-specific alternatives for existing property values and SHOULD NOT add new properties.
102-
/// Not localized.
102+
/// Not localized
103+
/// This is a special case, the localization is done by the [`crate::Card::get_localized`] method.
103104
#[serde(skip_serializing_if = "Option::is_none")]
104105
localizations: Option<HashMap<String, HashMap<String, Value>>>,
105106
/// The memorable dates and events for the entity represented by the Card.
@@ -287,10 +288,16 @@ impl Card {
287288
localize_links(&mut localized_card, key, value)?;
288289
} else if key.starts_with("directories") {
289290
localize_directories(&mut localized_card, key, value)?;
291+
} else if key.starts_with("calendars") {
292+
localize_calendars(&mut localized_card, key, value)?;
293+
} else if key.starts_with("schedulingAddresses") {
294+
localize_scheduling_addresses(&mut localized_card, key, value)?;
290295
}
291296
}
292297
// remove localizations of the localized card
293298
localized_card.localizations = None;
299+
// set the language of the localized card
300+
localized_card.language = Some(lang);
294301
Ok(localized_card)
295302
}
296303
}
@@ -867,3 +874,132 @@ fn localize_directories(card: &mut Card, key: &str, value: &Value) -> Result<(),
867874
}
868875
Ok(())
869876
}
877+
878+
/// Localize the [`crate::Calendar`]
879+
fn localize_calendars(card: &mut Card, key: &str, value: &Value) -> Result<(), String> {
880+
if key == "calendars" {
881+
card.calendars = serde_json::from_value(value.clone()).ok();
882+
return Ok(());
883+
}
884+
let calendars = match &mut card.calendars {
885+
Some(calendars) => calendars,
886+
None => &mut HashMap::new(),
887+
};
888+
let key = key.replace("calendars", "");
889+
if key.is_empty() {
890+
let Ok(calendars_map) = serde_json::from_value::<HashMap<String, Calendar>>(value.clone())
891+
else {
892+
return Err("Invalid value".into());
893+
};
894+
*calendars = calendars_map;
895+
card.calendars = Some(calendars.clone());
896+
return Ok(());
897+
}
898+
let key = remove_first(&key);
899+
let keys = key.split("/").collect::<Vec<&str>>();
900+
let Some(idx_key) = keys.first() else {
901+
return Err("Invalid calendars key".into());
902+
};
903+
let idx_key = idx_key.to_string();
904+
let key = key.replace(&idx_key, "");
905+
if key.is_empty() {
906+
let Ok(calendar) = serde_json::from_value::<Calendar>(value.clone()) else {
907+
return Err("Invalid value".into());
908+
};
909+
calendars.insert(idx_key, calendar);
910+
card.calendars = Some(calendars.clone());
911+
return Ok(());
912+
}
913+
let key = remove_first(&key);
914+
let Some(calendar) = calendars.get_mut(&idx_key) else {
915+
return Err(format!("calendars key '{}' not found", idx_key));
916+
};
917+
println!("{:?}", key);
918+
if key == "uri" {
919+
let Ok(uri) = serde_json::from_value(value.clone()) else {
920+
return Err("Invalid value".into());
921+
};
922+
calendar.uri = uri;
923+
} else if key == "contexts" {
924+
let Ok(contexts_map) = serde_json::from_value(value.clone()) else {
925+
return Err("Invalid value".into());
926+
};
927+
calendar.contexts = contexts_map;
928+
} else if key == "pref" {
929+
let Ok(pref) = serde_json::from_value(value.clone()) else {
930+
return Err("Invalid value".into());
931+
};
932+
calendar.pref = pref;
933+
} else if key == "label" {
934+
let Ok(label) = serde_json::from_value(value.clone()) else {
935+
return Err("Invalid value".into());
936+
};
937+
calendar.label = label;
938+
}
939+
Ok(())
940+
}
941+
942+
/// Localize the [`crate::SchedulingAddress`]
943+
fn localize_scheduling_addresses(card: &mut Card, key: &str, value: &Value) -> Result<(), String> {
944+
if key == "schedulingAddresses" {
945+
card.scheduling_addresses = serde_json::from_value(value.clone()).ok();
946+
return Ok(());
947+
}
948+
let scheduling_addresses = match &mut card.scheduling_addresses {
949+
Some(scheduling_addresses) => scheduling_addresses,
950+
None => &mut HashMap::new(),
951+
};
952+
let key = key.replace("schedulingAddresses", "");
953+
if key.is_empty() {
954+
let Ok(scheduling_addresses_map) =
955+
serde_json::from_value::<HashMap<String, SchedulingAddress>>(value.clone())
956+
else {
957+
return Err("Invalid value".into());
958+
};
959+
*scheduling_addresses = scheduling_addresses_map;
960+
card.scheduling_addresses = Some(scheduling_addresses.clone());
961+
return Ok(());
962+
}
963+
let key = remove_first(&key);
964+
let keys = key.split("/").collect::<Vec<&str>>();
965+
let Some(idx_key) = keys.first() else {
966+
return Err("Invalid schedulingAddresses key".into());
967+
};
968+
let idx_key = idx_key.to_string();
969+
let key = key.replace(&idx_key, "");
970+
if key.is_empty() {
971+
let Ok(scheduling_address) = serde_json::from_value::<SchedulingAddress>(value.clone())
972+
else {
973+
return Err("Invalid value".into());
974+
};
975+
scheduling_addresses.insert(idx_key, scheduling_address);
976+
card.scheduling_addresses = Some(scheduling_addresses.clone());
977+
return Ok(());
978+
}
979+
let key = remove_first(&key);
980+
let Some(scheduling_address) = scheduling_addresses.get_mut(&idx_key) else {
981+
return Err(format!("schedulingAddresses key '{}' not found", idx_key));
982+
};
983+
if key == "uri" {
984+
let Ok(uri) = serde_json::from_value(value.clone()) else {
985+
return Err("Invalid value".into());
986+
};
987+
scheduling_address.uri = uri;
988+
} else if key == "contexts" {
989+
let Ok(contexts_map) = serde_json::from_value(value.clone()) else {
990+
return Err("Invalid value".into());
991+
};
992+
scheduling_address.contexts = contexts_map;
993+
} else if key == "pref" {
994+
let Ok(pref) = serde_json::from_value(value.clone()) else {
995+
return Err("Invalid value".into());
996+
};
997+
scheduling_address.pref = pref
998+
} else if key == "label" {
999+
let Ok(label) = serde_json::from_value(value.clone()) else {
1000+
return Err("Invalid value".into());
1001+
};
1002+
scheduling_address.label = label;
1003+
}
1004+
Ok(())
1005+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"@type": "Card",
3+
"version": "1.0",
4+
"uid": "1234",
5+
"calendars": {
6+
"calA": {
7+
"kind": "calendar",
8+
"uri": "webcal://calendar.example.com/calA.ics",
9+
"label": "Calendar A"
10+
},
11+
"project-a": {
12+
"kind": "freeBusy",
13+
"uri": "https://calendar.example.com/busy/project-a",
14+
"pref": 1
15+
}
16+
},
17+
"localizations": {
18+
"en": {
19+
"calendars": {
20+
"calA": {
21+
"kind": "calendar",
22+
"uri": "webcal://calendar.example.com/en.ics"
23+
},
24+
"project-a": {
25+
"kind": "freeBusy",
26+
"uri": "https://busy.com",
27+
"label": "Busy"
28+
}
29+
}
30+
}
31+
}
32+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"@type": "Card",
3+
"version": "1.0",
4+
"uid": "1234",
5+
"calendars": {
6+
"calA": {
7+
"kind": "calendar",
8+
"uri": "webcal://calendar.example.com/calA.ics",
9+
"label": "Calendar A"
10+
},
11+
"project-a": {
12+
"kind": "freeBusy",
13+
"uri": "https://calendar.example.com/busy/project-a",
14+
"pref": 1
15+
}
16+
},
17+
"localizations": {
18+
"en": {
19+
"calendars/calA": {
20+
"kind": "calendar",
21+
"uri": "webcal://calendar.example.com/en.ics"
22+
},
23+
"calendars/project-a": {
24+
"kind": "freeBusy",
25+
"uri": "https://busy.com",
26+
"label": "Busy"
27+
}
28+
}
29+
}
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"@type": "Card",
3+
"version": "1.0",
4+
"uid": "1234",
5+
"calendars": {
6+
"calA": {
7+
"kind": "calendar",
8+
"uri": "webcal://calendar.example.com/calA.ics",
9+
"label": "Calendar A"
10+
},
11+
"project-a": {
12+
"kind": "freeBusy",
13+
"uri": "https://calendar.example.com/busy/project-a",
14+
"pref": 1
15+
}
16+
},
17+
"localizations": {
18+
"en": {
19+
"calendars/calA/kind": "calendar",
20+
"calendars/calA/uri": "webcal://calendar.example.com/en.ics",
21+
"calendars/project-a/kind": "freeBusy",
22+
"calendars/project-a/uri": "https://busy.com",
23+
"calendars/project-a/label": "Busy"
24+
}
25+
}
26+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"@type": "Card",
3+
"version": "1.0",
4+
"uid": "1234",
5+
"schedulingAddresses": {
6+
"sched1": {
7+
"uri": "mailto:janedoe@example.com",
8+
"label": "Jane Doe"
9+
}
10+
},
11+
"localizations": {
12+
"en": {
13+
"schedulingAddresses": {
14+
"sched1": {
15+
"uri": "mailto:",
16+
"label": "Jane Doe english"
17+
}
18+
}
19+
}
20+
}
21+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"@type": "Card",
3+
"version": "1.0",
4+
"uid": "1234",
5+
"schedulingAddresses": {
6+
"sched1": {
7+
"uri": "mailto:janedoe@example.com",
8+
"label": "Jane Doe"
9+
}
10+
},
11+
"localizations": {
12+
"en": {
13+
"schedulingAddresses/sched1": {
14+
"uri": "mailto:",
15+
"label": "Jane Doe english"
16+
}
17+
}
18+
}
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"@type": "Card",
3+
"version": "1.0",
4+
"uid": "1234",
5+
"schedulingAddresses": {
6+
"sched1": {
7+
"uri": "mailto:janedoe@example.com",
8+
"label": "Jane Doe"
9+
}
10+
},
11+
"localizations": {
12+
"en": {
13+
"schedulingAddresses/sched1/uri": "mailto:",
14+
"schedulingAddresses/sched1/label": "Jane Doe english"
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)