1 | //! Macros that translate the message and then replace placeholders in it. |
2 | |
3 | /// This is an implementation detail for counting arguments in the gettext macros. Don't call this directly. |
4 | #[macro_export ] |
5 | #[doc (hidden)] |
6 | macro_rules! count_args { |
7 | () => { 0 }; |
8 | ($_e: expr $(, $rest: expr)*) => { 1 + $crate::count_args!($($rest),*) } |
9 | } |
10 | |
11 | /// This is an implementation detail for replacing arguments in the gettext macros. Don't call this directly. |
12 | #[macro_export ] |
13 | #[doc (hidden)] |
14 | macro_rules! freplace { |
15 | ($format:expr, $($args:expr),+ $(,)?) => {{ |
16 | let mut parts = $format.split("{}" ); |
17 | debug_assert_eq!(parts.clone().count() - 1, $crate::count_args!($($args),*), "Argument count has to match number of format directives ({{}})" ); |
18 | |
19 | let mut output = parts.next().unwrap_or_default().to_string(); |
20 | $( |
21 | output += &format!("{}{}" , $args, &parts.next().expect("Argument count has to match number of format directives ({})" )); |
22 | )* |
23 | output |
24 | }}; |
25 | } |
26 | |
27 | /// Like [`gettext`], but allows for formatting. |
28 | /// |
29 | /// It calls [`gettext`] on `msgid`, and then replaces each occurrence of `{}` with the next value |
30 | /// out of `args`. |
31 | /// |
32 | /// [`gettext`]: fn.gettext.html |
33 | #[macro_export ] |
34 | macro_rules! gettext { |
35 | ($msgid:expr, $($args:expr),+ $(,)?) => {{ |
36 | let format = $crate::gettext($msgid); |
37 | $crate::freplace!(format, $($args),*) |
38 | }}; |
39 | } |
40 | |
41 | /// Like [`dgettext`], but allows for formatting. |
42 | /// |
43 | /// It calls [`dgettext`] on `domainname` and `msgid`, and then replaces each occurrence of `{}` |
44 | /// with the next value out of `args`. |
45 | /// |
46 | /// [`dgettext`]: fn.dgettext.html |
47 | #[macro_export ] |
48 | macro_rules! dgettext { |
49 | ($domainname:expr, $msgid:expr, $($args:expr),+ $(,)?) => {{ |
50 | let format = $crate::dgettext($domainname, $msgid); |
51 | $crate::freplace!(format, $($args),*) |
52 | }}; |
53 | } |
54 | |
55 | /// Like [`dcgettext`], but allows for formatting. |
56 | /// |
57 | /// It calls [`dcgettext`] on `domainname`, `category`, and `msgid`, and then replaces each |
58 | /// occurrence of `{}` with the next value out of `args`. |
59 | /// |
60 | /// [`dcgettext`]: fn.dcgettext.html |
61 | #[macro_export ] |
62 | macro_rules! dcgettext { |
63 | ($domainname:expr, $category:expr, $msgid:expr, $($args:expr),+ $(,)?) => {{ |
64 | let format = $crate::dcgettext($domainname, $msgid, $category); |
65 | $crate::freplace!(format, $($args),*) |
66 | }}; |
67 | } |
68 | |
69 | /// Like [`ngettext`], but allows for formatting. |
70 | /// |
71 | /// It calls [`ngettext`] on `msgid`, `msgid_plural`, and `n`, and then replaces each occurrence of |
72 | /// `{}` with the next value out of `args`. |
73 | /// |
74 | /// [`ngettext`]: fn.ngettext.html |
75 | #[macro_export ] |
76 | macro_rules! ngettext { |
77 | ($msgid:expr, $msgid_plural:expr, $n:expr, $($args:expr),+ $(,)?) => {{ |
78 | let format = $crate::ngettext($msgid, $msgid_plural, $n); |
79 | $crate::freplace!(format, $($args),*) |
80 | }} |
81 | } |
82 | |
83 | /// Like [`dngettext`], but allows for formatting. |
84 | /// |
85 | /// It calls [`dngettext`] on `domainname`, `msgid`, `msgid_plural`, and `n`, and then replaces |
86 | /// each occurrence of `{}` with the next value out of `args`. |
87 | /// |
88 | /// [`dngettext`]: fn.dngettext.html |
89 | #[macro_export ] |
90 | macro_rules! dngettext { |
91 | ($domainname:expr, $msgid:expr, $msgid_plural:expr, $n:expr, $($args:expr),+ $(,)?) => {{ |
92 | let format = $crate::dngettext($domainname, $msgid, $msgid_plural, $n); |
93 | $crate::freplace!(format, $($args),*) |
94 | }} |
95 | } |
96 | |
97 | /// Like [`dcngettext`], but allows for formatting. |
98 | /// |
99 | /// It calls [`dcngettext`] on `domainname`, `category`, `msgid`, `msgid_plural`, and `n`, and then |
100 | /// replaces each occurrence of `{}` with the next value out of `args`. |
101 | /// |
102 | /// [`dcngettext`]: fn.dcngettext.html |
103 | #[macro_export ] |
104 | macro_rules! dcngettext { |
105 | ($domainname:expr, $category:expr, $msgid:expr, $msgid_plural:expr, $n:expr, $($args:expr),+ $(,)?) => {{ |
106 | let format = $crate::dcngettext($domainname, $msgid, $msgid_plural, $n, $category); |
107 | $crate::freplace!(format, $($args),*) |
108 | }} |
109 | } |
110 | |
111 | /// Like [`pgettext`], but allows for formatting. |
112 | /// |
113 | /// It calls [`pgettext`] on `msgctxt` and `msgid`, and then replaces each occurrence of `{}` with |
114 | /// the next value out of `args`. |
115 | /// |
116 | /// [`pgettext`]: fn.pgettext.html |
117 | #[macro_export ] |
118 | macro_rules! pgettext { |
119 | ($msgctxt:expr, $msgid:expr, $($args:expr),+ $(,)?) => {{ |
120 | let format = $crate::pgettext($msgctxt, $msgid); |
121 | $crate::freplace!(format, $($args),*) |
122 | }} |
123 | } |
124 | |
125 | /// Like [`npgettext`], but allows for formatting. |
126 | /// |
127 | /// It calls [`npgettext`] on `msgctxt`, `msgid`, `msgid_plural`, and `n`, and then replaces each |
128 | /// occurrence of `{}` with the next value out of `args`. |
129 | /// |
130 | /// [`npgettext`]: fn.npgettext.html |
131 | #[macro_export ] |
132 | macro_rules! npgettext { |
133 | ($msgctxt:expr, $msgid:expr, $msgid_plural:expr, $n:expr, $($args:expr),+ $(,)?) => {{ |
134 | let format = $crate::npgettext($msgctxt, $msgid, $msgid_plural, $n); |
135 | $crate::freplace!(format, $($args),*) |
136 | }} |
137 | } |
138 | |
139 | #[cfg (test)] |
140 | mod test { |
141 | use crate::*; |
142 | |
143 | #[test ] |
144 | fn test_gettext_macro() { |
145 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
146 | |
147 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
148 | textdomain("hellorust" ).unwrap(); |
149 | |
150 | assert_eq!(gettext!("Hello, {}!" , "world" ), "Hello, world!" ); |
151 | assert_eq!( |
152 | gettext!("Hello, {} {}!" , "small" , "world" ), |
153 | "Hello, small world!" |
154 | ); |
155 | } |
156 | |
157 | #[test ] |
158 | fn test_ngettext_macro() { |
159 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
160 | |
161 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
162 | textdomain("hellorust" ).unwrap(); |
163 | |
164 | assert_eq!( |
165 | ngettext!("Singular {}!" , "Multiple {}!" , 2, "Worlds" ), |
166 | "Multiple Worlds!" |
167 | ); |
168 | } |
169 | |
170 | #[test ] |
171 | fn test_pgettext_macro() { |
172 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
173 | |
174 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
175 | textdomain("hellorust" ).unwrap(); |
176 | |
177 | assert_eq!("Hello, world!" , pgettext!("context" , "Hello, {}!" , "world" )); |
178 | } |
179 | |
180 | #[test ] |
181 | fn test_npgettext_macro() { |
182 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
183 | |
184 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
185 | textdomain("hellorust" ).unwrap(); |
186 | |
187 | assert_eq!( |
188 | "Multiple Worlds!" , |
189 | npgettext!("context" , "Singular {}!" , "Multiple {}!" , 2, "Worlds" ) |
190 | ); |
191 | } |
192 | |
193 | #[test ] |
194 | fn test_dgettext_macro() { |
195 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
196 | |
197 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
198 | |
199 | assert_eq!( |
200 | "Hello, world!" , |
201 | dgettext!("hellorust" , "Hello, {}!" , "world" ) |
202 | ); |
203 | } |
204 | |
205 | #[test ] |
206 | fn test_dcgettext_macro() { |
207 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
208 | |
209 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
210 | |
211 | assert_eq!( |
212 | "Hello, world!" , |
213 | dcgettext!("hellorust" , LocaleCategory::LcAll, "Hello, {}!" , "world" ) |
214 | ); |
215 | } |
216 | |
217 | #[test ] |
218 | fn test_dcngettext_macro() { |
219 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
220 | |
221 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
222 | |
223 | assert_eq!( |
224 | "Singular World" , |
225 | dcngettext!( |
226 | "hellorust" , |
227 | LocaleCategory::LcAll, |
228 | "Singular {}" , |
229 | "Multiple {}" , |
230 | 1, |
231 | "World" |
232 | ) |
233 | ) |
234 | } |
235 | |
236 | #[test ] |
237 | fn test_dngettext_macro() { |
238 | setlocale(LocaleCategory::LcAll, "en_US.UTF-8" ); |
239 | |
240 | bindtextdomain("hellorust" , "/usr/local/share/locale" ).unwrap(); |
241 | |
242 | assert_eq!( |
243 | "Singular World!" , |
244 | dngettext!("hellrust" , "Singular {}!" , "Multiple {}!" , 1, "World" ) |
245 | ) |
246 | } |
247 | } |
248 | |