Skip to content

Commit 6a8de9a

Browse files
committed
feat: Support X-Ubuntu-Gettext-Domain
1 parent d670986 commit 6a8de9a

File tree

2 files changed

+92
-43
lines changed

2 files changed

+92
-43
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "freedesktop-desktop-entry"
3-
version = "0.3.3"
3+
version = "0.4.0"
44
authors = ["Michael Aaron Murphy <[email protected]>"]
55
edition = "2018"
66
homepage = "https://codeberg.org/mmstick/freedesktop-desktop-entry"
@@ -14,5 +14,6 @@ maintenance = { status = "passively-maintained" }
1414

1515
[dependencies]
1616
dirs = "3"
17+
gettext-rs = { version = "0.7", features = ["gettext-system"]}
1718
memchr = "2"
1819
thiserror = "1"

src/lib.rs

Lines changed: 90 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ extern crate thiserror;
44
mod iter;
55

66
pub use self::iter::Iter;
7-
7+
use std::borrow::Cow;
88
use std::collections::BTreeMap;
99
use std::path::{Path, PathBuf};
1010

@@ -27,38 +27,52 @@ pub struct DesktopEntry<'a> {
2727
pub appid: &'a str,
2828
pub groups: Groups<'a>,
2929
pub path: &'a Path,
30+
pub ubuntu_gettext_domain: Option<&'a str>,
3031
}
3132

3233
impl<'a> DesktopEntry<'a> {
33-
pub fn action_entry(&self, action: &str, key: &str, locale: Option<&str>) -> Option<&'a str> {
34+
pub fn action_entry(&'a self, action: &str, key: &str) -> Option<&'a str> {
35+
let group = self
36+
.groups
37+
.get(["Desktop Action ", action].concat().as_str());
38+
39+
Self::entry(group, key)
40+
}
41+
42+
pub fn action_entry_localized(
43+
&'a self,
44+
action: &str,
45+
key: &str,
46+
locale: Option<&str>,
47+
) -> Option<Cow<'a, str>> {
3448
let group = self
3549
.groups
3650
.get(["Desktop Action ", action].concat().as_str());
3751

38-
Self::localized_entry(group, key, locale)
52+
Self::localized_entry(self.ubuntu_gettext_domain, group, key, locale)
3953
}
4054

41-
pub fn action_exec(&self, action: &str) -> Option<&'a str> {
42-
self.action_entry(action, "Exec", None)
55+
pub fn action_exec(&'a self, action: &str) -> Option<&'a str> {
56+
self.action_entry(action, "Exec")
4357
}
4458

45-
pub fn action_name(&self, action: &str, locale: Option<&str>) -> Option<&'a str> {
46-
self.action_entry(action, "Name", locale)
59+
pub fn action_name(&'a self, action: &str, locale: Option<&str>) -> Option<Cow<'a, str>> {
60+
self.action_entry_localized(action, "Name", locale)
4761
}
4862

49-
pub fn actions(&self) -> Option<&'a str> {
50-
self.desktop_entry("Actions", None)
63+
pub fn actions(&'a self) -> Option<&'a str> {
64+
self.desktop_entry("Actions")
5165
}
5266

53-
pub fn categories(&self) -> Option<&'a str> {
54-
self.desktop_entry("Categories", None)
67+
pub fn categories(&'a self) -> Option<&'a str> {
68+
self.desktop_entry("Categories")
5569
}
5670

57-
pub fn comment(&self, locale: Option<&str>) -> Option<&'a str> {
58-
self.desktop_entry("Comment", locale)
71+
pub fn comment(&'a self, locale: Option<&str>) -> Option<Cow<'a, str>> {
72+
self.desktop_entry_localized("Comment", locale)
5973
}
6074

61-
pub fn decode<'b>(path: &'b Path, input: &'b str) -> Result<DesktopEntry<'b>, DecodeError> {
75+
pub fn decode(path: &'a Path, input: &'a str) -> Result<DesktopEntry<'a>, DecodeError> {
6276
let appid = path
6377
.file_stem()
6478
.ok_or(DecodeError::AppID)?
@@ -69,6 +83,8 @@ impl<'a> DesktopEntry<'a> {
6983

7084
let mut active_group = "";
7185

86+
let mut ubuntu_gettext_domain = None;
87+
7288
for mut line in input.lines() {
7389
line = line.trim();
7490
if line.is_empty() || line.starts_with('#') {
@@ -101,6 +117,11 @@ impl<'a> DesktopEntry<'a> {
101117
}
102118
}
103119

120+
if key == "X-Ubuntu-Gettext-Domain" {
121+
ubuntu_gettext_domain = Some(value);
122+
continue;
123+
}
124+
104125
groups
105126
.entry(active_group)
106127
.or_insert_with(Default::default)
@@ -114,74 +135,93 @@ impl<'a> DesktopEntry<'a> {
114135
appid,
115136
groups,
116137
path,
138+
ubuntu_gettext_domain,
117139
})
118140
}
119141

120-
pub fn desktop_entry(&self, key: &str, locale: Option<&str>) -> Option<&'a str> {
121-
Self::localized_entry(self.groups.get("Desktop Entry"), key, locale)
142+
pub fn desktop_entry(&'a self, key: &str) -> Option<&'a str> {
143+
Self::entry(self.groups.get("Desktop Entry"), key)
144+
}
145+
146+
pub fn desktop_entry_localized(
147+
&'a self,
148+
key: &str,
149+
locale: Option<&str>,
150+
) -> Option<Cow<'a, str>> {
151+
Self::localized_entry(
152+
self.ubuntu_gettext_domain,
153+
self.groups.get("Desktop Entry"),
154+
key,
155+
locale,
156+
)
122157
}
123158

124-
pub fn exec(&self) -> Option<&'a str> {
125-
self.desktop_entry("Exec", None)
159+
pub fn exec(&'a self) -> Option<&'a str> {
160+
self.desktop_entry("Exec")
126161
}
127162

128-
pub fn icon(&self) -> Option<&'a str> {
129-
self.desktop_entry("Icon", None)
163+
pub fn icon(&'a self) -> Option<&'a str> {
164+
self.desktop_entry("Icon")
130165
}
131166

132-
pub fn id(&self) -> &str {
167+
pub fn id(&'a self) -> &str {
133168
self.appid
134169
}
135170

136-
pub fn keywords(&self) -> Option<&'a str> {
137-
self.desktop_entry("Keywords", None)
171+
pub fn keywords(&'a self) -> Option<Cow<'a, str>> {
172+
self.desktop_entry_localized("Keywords", None)
138173
}
139174

140-
pub fn mime_type(&self) -> Option<&'a str> {
141-
self.desktop_entry("MimeType", None)
175+
pub fn mime_type(&'a self) -> Option<&'a str> {
176+
self.desktop_entry("MimeType")
142177
}
143178

144-
pub fn name(&self, locale: Option<&str>) -> Option<&'a str> {
145-
self.desktop_entry("Name", locale)
179+
pub fn name(&'a self, locale: Option<&str>) -> Option<Cow<'a, str>> {
180+
self.desktop_entry_localized("Name", locale)
146181
}
147182

148-
pub fn no_display(&self) -> bool {
183+
pub fn no_display(&'a self) -> bool {
149184
self.desktop_entry_bool("NoDisplay")
150185
}
151186

152-
pub fn only_show_in(&self) -> Option<&'a str> {
153-
self.desktop_entry("OnlyShowIn", None)
187+
pub fn only_show_in(&'a self) -> Option<&'a str> {
188+
self.desktop_entry("OnlyShowIn")
154189
}
155190

156-
pub fn prefers_non_default_gpu(&self) -> bool {
191+
pub fn prefers_non_default_gpu(&'a self) -> bool {
157192
self.desktop_entry_bool("PrefersNonDefaultGPU")
158193
}
159194

160-
pub fn startup_notify(&self) -> bool {
195+
pub fn startup_notify(&'a self) -> bool {
161196
self.desktop_entry_bool("StartupNotify")
162197
}
163198

164-
pub fn terminal(&self) -> bool {
199+
pub fn terminal(&'a self) -> bool {
165200
self.desktop_entry_bool("Terminal")
166201
}
167202

168-
pub fn type_(&self) -> Option<&'a str> {
169-
self.desktop_entry("Type", None)
203+
pub fn type_(&'a self) -> Option<&'a str> {
204+
self.desktop_entry("Type")
205+
}
206+
207+
fn desktop_entry_bool(&'a self, key: &str) -> bool {
208+
self.desktop_entry(key).map_or(false, |v| v == "true")
170209
}
171210

172-
fn desktop_entry_bool(&self, key: &str) -> bool {
173-
self.desktop_entry(key, None).map_or(false, |v| v == "true")
211+
fn entry(group: Option<&'a KeyMap<'a>>, key: &str) -> Option<&'a str> {
212+
group.and_then(|group| group.get(key)).map(|key| key.0)
174213
}
175214

176215
fn localized_entry(
177-
group: Option<&KeyMap<'a>>,
216+
ubuntu_gettext_domain: Option<&'a str>,
217+
group: Option<&'a KeyMap<'a>>,
178218
key: &str,
179219
locale: Option<&str>,
180-
) -> Option<&'a str> {
220+
) -> Option<Cow<'a, str>> {
181221
group.and_then(|group| group.get(key)).and_then(|key| {
182222
locale
183-
.and_then(|locale| match key.1.get(locale) {
184-
Some(value) => Some(*value),
223+
.and_then(|locale| match key.1.get(locale).cloned() {
224+
Some(value) => Some(value),
185225
None => {
186226
if let Some(pos) = locale.find('_') {
187227
key.1.get(&locale[..pos]).cloned()
@@ -190,7 +230,9 @@ impl<'a> DesktopEntry<'a> {
190230
}
191231
}
192232
})
193-
.or(Some(key.0))
233+
.map(Cow::Borrowed)
234+
.or_else(|| ubuntu_gettext_domain.map(|domain| Cow::Owned(dgettext(domain, key.0))))
235+
.or(Some(Cow::Borrowed(key.0)))
194236
})
195237
}
196238
}
@@ -249,3 +291,9 @@ pub fn default_paths() -> Vec<(PathSource, PathBuf)> {
249291
(PathSource::System, PathBuf::from("/usr/share/applications")),
250292
]
251293
}
294+
295+
fn dgettext(domain: &str, message: &str) -> String {
296+
use gettextrs::{setlocale, LocaleCategory};
297+
setlocale(LocaleCategory::LcAll, "");
298+
gettextrs::dgettext(domain, message)
299+
}

0 commit comments

Comments
 (0)