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 }