Template wizardry and its cost

Bastiaan Veelo Bastiaan at Veelo.net
Mon Jun 20 08:37:13 UTC 2022


Two years ago 
[[1]](https://forum.dlang.org/post/mailman.2526.1585832475.31109.digitalmars-d@puremagic.com), [[2]](https://forum.dlang.org/post/mailman.4770.1596218284.31109.digitalmars-d-announce@puremagic.com), H. S. Teoh presented an ingenious proof of concept for a gettext-like system that automatically extracts translatable strings for i18n purposes:

```d
	class Language { ... }
	Language curLang = ...;

	version(extractStrings) {
		private int[string] translatableStrings;
		string[] getTranslatableStrings() {
			return translatableStrings.keys;
		}
	}

	string gettext(string str)() {
		version(extractStrings) {
			static struct StrInjector {
				static this() {
					translatableStrings[str]++;
				}
			}
		}
		return curLang.translate(str);
	}

	...
	auto myFunc() {
		...
		writeln(gettext!"Some translatable message");
		...
	}
```

> The gettext function uses a static struct to inject a static 
> ctor into the program that inserts all translatable strings 
> into a global AA. Then, when compiled with 
> -version=extractStrings, this will expose the function 
> getTranslatableStrings that returns a list of all translatable 
> strings.  Voila! No need for a separate utility to parse source 
> code to discover translatable strings; this does it for you 
> automatically. :-)
>
> It could be made more fancy, of course, like having a function 
> that parses the current l10n files and doing a diff between 
> strings that got deleted / added / changed, and generating a 
> report to inform the translator which strings need to be 
> updated.  This is guaranteed to be 100% reliable since the 
> extracted strings are obtained directly from actual calls to 
> gettext, rather than a 3rd party parser that may choke over 
> uncommon syntax / unexpected formatting.
>
> D is just *this* awesome.

I find this marvellous, and played with it over the weekend. It 
works brilliantly. I got it to integrate neatly in Dub projects, 
made it compatible with GNU gettext so that existing translation 
services and editors can be used ([Poedit](https://poedit.net/) 
is awesome, thank you 
[mofile](https://code.dlang.org/packages/mofile)).

But I don't think I'll go through with it this way. My problem is 
the template instantiation for every individual translatable 
string literal. I'd like to think the consequences are 
insignificant, but in large code bases I fear they won't be. And 
the issue is that only for `version(extractStrings)` the string 
needs to be a template argument, otherwise you'd want it to be an 
ordinary function argument. Maybe this is possible to achieve 
with string mixins, but probably not without getting much more 
verbose.

I am ready to be amazed with more wizardry, or to be convinced 
not to worry because inlining or something (it doesn't inline). 
Until then, I am thinking an external tool based on `libdparse` 
or dmd-as-a-library is probably the better approach; however 
awesome D is :-)

-- Bastiaan.


More information about the Digitalmars-d mailing list