Template wizardry and its cost
Bastiaan Veelo
Bastiaan at Veelo.net
Tue Jun 21 09:06:40 UTC 2022
On Tuesday, 21 June 2022 at 02:35:28 UTC, Steven Schveighoffer
wrote:
> structs can be functors:
That was one of the things I tried, but I missed this bit:
> ```d
> this(string s1, string s2) { // this is unfortunately
> necessary
> _str = s1;
> _strpl = s2;
> }
> ```
[...]
> I will say, I find this line... reprehensible ;)
I left my dirty laundry out in the hopes it would trigger you ;-)
Thanks for the rinse, it looks great!
> But.... I don't see any actual translation happening in the
> plural/singular form?
That's because the counting needs to be done on the translated
string. Fixed below.
Thanks Steve, looks like I'll be releasing my first Dub package
soonish.
-- Bastiaan.
```d
--- app.d
import gettext;
import std.stdio;
void main()
{
foreach (n; 0 .. 3)
writeln(tr!("one goose.", "%d geese.")(n));
}
--- gettext.d
import std;
private @safe struct TranslatableString
{
string _str;
string get()
{
return gettext(_str);
}
alias get this;
}
private @safe struct Strplusarg {
this(string s) {
fmt = s;
auto fs = countFormatSpecifiers(fmt);
assert(fs == 0 || fs == 1, "Invalid number of
specifiers"); // bonus sanity check
hasArg = fs == 1;
}
string fmt;
bool hasArg;
}
private @safe struct TranslatableStringPlural
{
string _str, _strpl;
this(string s1, string s2) { // this is unfortunately
necessary
_str = s1;
_strpl = s2;
}
string opCall(int n)
{
auto f = Strplusarg(ngettext(_str, _strpl, n));
return f.hasArg ? format(f.fmt, n) : f.fmt;
}
}
template tr(string singular, string plural = null)
{
static if (plural == null)
enum tr = TranslatableString(singular);
else
enum tr = TranslatableStringPlural(singular, plural);
}
@safe: private:
int countFormatSpecifiers(string fmt) pure
{
static void ns(const(char)[] arr) {} // the simplest output
range
auto nullSink = &ns;
int count = 0;
auto f = FormatSpec!char(fmt);
while (f.writeUpToNextSpec(nullSink))
count++;
return count;
}
// Translation happens here:
string gettext(string str)
{
return str;
}
string ngettext(string singular, string plural, int n)
{
return n == 1 ? singular : plural;
}
```
0 geese.
one goose.
2 geese.
More information about the Digitalmars-d
mailing list