1 module i18n.tr;
2 import i18n.mo;
3 import i18n.culture;
4 import std.path;
5 import std.file : read;
6 import std.uni : toLower;
7 import std.format : format;
8 
9 package(i18n) {
10     struct TREntry {
11         string source;
12         string[] targets;
13         const(char)*[] cTargets;
14     }
15 }
16 
17 private {
18     MOFile* loadedLanguage;
19 
20     enum TLFormats {
21         none,
22         gettext
23     }
24 
25     TLFormats currentFormat = TLFormats.none;
26     TREntry[string] lookuptable;
27 }
28 
29 /**
30     Gets the name of the language
31 */
32 string i18nGetLanguageName(string file) {
33     import std.path : baseName, stripExtension;
34 
35     // Load language file
36     auto f = i18nMOLoad(cast(ubyte[])read(file));
37 
38     // Try to read language from LANG_NAME strid
39     string langName = f.i18nMOStr("LANG_NAME").dup;
40     destroy!false(f);
41 
42     // Not found? Then get (inaccurate) fallback name from internal list
43     if (langName == "LANG_NAME") langName = i18nGetCultureNativeLanguageEstimate(file.baseName.stripExtension);
44 
45     // Not found? Then get fallback from english name list
46     if (langName == "LANG_NAME") langName = i18nGetCultureLanguage(file.baseName.stripExtension);
47 
48     // Not found? Okay we give up, throw some text to know we don't know what the heck to do
49     if (!langName) return "<UNKNOWN LANGUAGE>";
50 
51     // Return whatever we got
52     return langName;
53 }
54 
55 /**
56     Clears currently loaded language
57 */
58 void i18nClearLanguage() {
59     lookuptable.clear();
60     loadedLanguage = null;
61 }
62 
63 /**
64     Loads a language
65 */
66 bool i18nLoadLanguage(string file) {
67 
68     // Empty path/null = unload
69     if (file.length == 0) {
70         i18nClearLanguage();
71         return true;
72     }
73 
74     // Actually load
75     lookuptable.clear();
76     switch(file.extension.toLower) {
77         case ".mo":
78             try {
79                 loadedLanguage = i18nMOLoad(cast(ubyte[])read(file));
80 
81                 lookuptable = i18nMOGenStrings(loadedLanguage);
82                 currentFormat = TLFormats.gettext;
83             } catch (Exception ex) {
84                 return false;
85             }
86             return true;
87         default: 
88             throw new Exception("i18n: Invalid file format %s".format(file.extension));
89     }
90 }
91 
92 /**
93     Returns D string translation of iText
94 */
95 string _(string iText) {
96     
97     // If in lookup table, return from lookup table
98     if (iText in lookuptable) 
99         return lookuptable[iText].targets[0];
100 
101     // Otherwise try just in case from file.
102     switch(currentFormat) {
103         case TLFormats.gettext:
104             if (loadedLanguage) return loadedLanguage.i18nMOStr(iText);
105             return iText;
106         default:
107             return iText;
108     }
109 }
110 
111 /**
112     Returns C string translation of iText
113 */
114 const(char)* __(string iText) {
115     import std.string : toStringz;
116     
117     // If in lookup table, return from lookup table
118     if (iText in lookuptable) 
119         return lookuptable[iText].cTargets[0];
120 
121     // Otherwise try just in case from file.
122     switch(currentFormat) {
123         case TLFormats.gettext:
124             if (loadedLanguage) return loadedLanguage.i18nMOStrC(iText);
125             return iText.toStringz;
126         default:
127             return iText.toStringz;
128     }
129 }