1 module tagion.basic.Message;
2 
3 import std.format;
4 import std.json;
5 import tagion.basic.Types : FileExtension;
6 import tagion.basic.Version;
7 import tagion.basic.basic : EnumText;
8 
9 enum name_list = [
10         "TAGION", /// Name of the tagion environment variable pointing to the tagion directory 
11         "TAGION_LANG", /// Tagion language
12         "language", /// Language
13         "languages", /// Path for the translation language files 
14         "tabel", /// Translation table
15         "tagion", /// Name of the product
16         "en", /// Default language
17         "new_en", /// Just a new language name used when the default exists
18     ];
19 
20 mixin(EnumText!("Names", name_list));
21 
22 /++
23  this function works like the std.format except if the language translation table is loaded
24  the text is translated via this table
25 +/
26 @safe
27 struct Message {
28     immutable(string[string]) translation;
29     string opCall(Args...)(string fmt, lazy Args args) pure const {
30         if (translation.length is 0) {
31             return format(fmt, args);
32         }
33         version (UPDATE_MESSAGE_TABLE) {
34             if (!fmt in translation) {
35                 translation[fmt] = fmt;
36             }
37         }
38         return format(translation.get(fmt, fmt), args);
39     }
40 }
41 
42 //__gshared  string[string] translation;
43 
44 static immutable Message message;
45 
46 import std.algorithm : each;
47 import std.file : exists, mkdirRecurse, fread = read, tempDir, fwrite = write;
48 import std.path;
49 import std.process : environment;
50 import std.stdio;
51 
52 static if (not_unittest) {
53     /++
54  This generates the message translation table
55  If the version flag UPDATE_MESSAGE_TABEL is set then the default translation tabel
56  is generated and a json file is written, which then can be edited for other language support
57 +/
58 
59     string get_lang_path() {
60         return buildPath(environment.get(Names.TAGION, tempDir), Names.languages);
61     }
62 
63     version (none) shared static this() {
64         immutable lang_file = buildPath(get_lang_path, environment.get(Names.TAGION_LANG, Names.en))
65             .setExtension(FileExtension.json);
66         if (lang_file.exists) {
67             const text = lang_file.fread;
68         }
69         auto json = lang_file.parseJSON;
70         string[string] translation;
71         foreach (string from, ref to; json.object) {
72             translation[from] = to.get!string;
73         }
74         message.translation = cast(immutable) translation;
75     }
76 
77     version (WRITE_MESSAGE_TABLE) {
78         shared static ~this() {
79             JSONValue result;
80             result[Names.language] = Names.en;
81             JSONValue tabel;
82             message.translation.byKey
83                 .each!(fmt => tabel[fmt] = fmt);
84             result[Names.tabel] = tabel;
85             immutable text = result.toPrettyString;
86             immutable lang_path = get_lang_path;
87             auto lang_file = buildPath(lang_path, Names.en).setExtension(FileExtension.json);
88             if (!(Names.TAGION in environment)) {
89                 stderr.writeln("Environment %s was not defined", Names.TAGION);
90             }
91             writefln("path '%s'", lang_path);
92             writefln("Language file stored in '%s'", lang_file);
93             if (!lang_path.exists) {
94                 lang_path.mkdirRecurse;
95             }
96             if (lang_file.exists) {
97                 lang_file = buildPath(lang_path, Names.new_en).setExtension(FileExtension.json);
98             }
99             lang_file.fwrite(text);
100         }
101     }
102 }