6 #if defined(ECERE_BOOTSTRAP) || defined(ECERE_STATIC)
8 #if !defined(ECERE_BOOTSTRAP)
13 #ifndef ECERE_BOOTSTRAP
14 #define FileOpen FileOpenBuffered
17 static Map<String, Map<String, String>> moduleMaps { };
19 #define SWAP_DWORD(dword) ((((unsigned int)(dword) & 0x000000ff) << 24) \
20 | (((unsigned int)(dword) & 0x0000ff00) << 8) \
21 | (((unsigned int)(dword) & 0x00ff0000) >> 8) \
22 | (((unsigned int)(dword) & 0xff000000) >> 24))
24 public dllexport void LoadTranslatedStrings(String moduleName, char * name)
28 char fileName[MAX_LOCATION];
35 char genericLocale[256];
39 if(GetEnvironment("ECERE_LANGUAGE", language, sizeof(language)))
41 else if(GetEnvironment("LANGUAGE", language, sizeof(language)))
43 else if(GetEnvironment("LC_ALL", lcAll, sizeof(lcAll)))
45 else if(GetEnvironment("LC_MESSAGES", lcMessages, sizeof(lcMessages)))
47 else if(GetEnvironment("LANG", lang, sizeof(lang)))
54 if(language != locale)
55 strcpy(language, locale);
56 dot = strstr(language, ".");
59 // TODO: Try multiple languages defined in LANGUAGE
60 colon = strstr(language, ":");
63 if(!strcmpi(locale, "zh"))
64 strcpy(locale, "zh_CN");
70 strcpy(genericLocale, locale);
71 under = strchr(genericLocale, '_');
74 if(!strcmpi(genericLocale, "zh"))
75 strcpy(genericLocale, "zh_CN");
79 sprintf(fileName, "<:%s>locale/%s.mo", moduleName, locale);
81 sprintf(fileName, ":locale/%s.mo", locale);
82 f = FileOpen(fileName, read);
86 sprintf(fileName, "<:%s>locale/%s/LC_MESSAGES/%s.mo", moduleName, locale, name);
88 sprintf(fileName, ":locale/%s/LC_MESSAGES/%s.mo", locale, name);
89 f = FileOpen(fileName, read);
93 sprintf(fileName, "locale/%s/LC_MESSAGES/%s.mo", locale, name);
94 f = FileOpen(fileName, read);
98 sprintf(fileName, "/usr/share/locale/%s/LC_MESSAGES/%s.mo", locale, name);
99 f = FileOpen(fileName, read);
102 if(!f && locale && strcmpi(locale, genericLocale))
104 // Attempt with generic language
106 sprintf(fileName, "<:%s>locale/%s.mo", moduleName, genericLocale);
108 sprintf(fileName, ":locale/%s.mo", genericLocale);
109 f = FileOpen(fileName, read);
113 sprintf(fileName, "<:%s>locale/%s/LC_MESSAGES/%s.mo", moduleName, genericLocale, name);
115 sprintf(fileName, ":locale/%s/LC_MESSAGES/%s.mo", genericLocale, name);
116 f = FileOpen(fileName, read);
120 sprintf(fileName, "locale/%s/LC_MESSAGES/%s.mo", genericLocale, name);
121 f = FileOpen(fileName, read);
125 sprintf(fileName, "/usr/share/locale/%s/LC_MESSAGES/%s.mo", genericLocale, name);
126 f = FileOpen(fileName, read);
133 f.Read(&magic, sizeof(uint), 1);
134 if(magic == 0x950412de || magic == 0xde120495)
136 Map<String, String> textMap;
137 bool swap = magic != 0x950412de;
140 uint origStrings = 0, transStrings = 0;
141 uint hashingSize = 0, hashingOffset = 0;
143 f.Read(&revision, sizeof(uint), 1); if(swap) revision = SWAP_DWORD(revision);
144 f.Read(&numStrings, sizeof(uint), 1); if(swap) numStrings = SWAP_DWORD(numStrings);
145 f.Read(&origStrings, sizeof(uint), 1); if(swap) origStrings = SWAP_DWORD(origStrings);
146 f.Read(&transStrings, sizeof(uint), 1); if(swap) transStrings = SWAP_DWORD(transStrings);
147 f.Read(&hashingSize, sizeof(uint), 1); if(swap) hashingSize = SWAP_DWORD(hashingSize);
148 f.Read(&hashingOffset, sizeof(uint), 1); if(swap) hashingOffset = SWAP_DWORD(hashingOffset);
153 MapIterator<String, Map<String, String>> it { map = moduleMaps };
154 if(it.Index(name, false))
156 // TOFIX: delete moduleMaps[module];
158 moduleMaps[name] = textMap = { };
159 for(c = 0; c < numStrings; c++)
161 uint len = 0, offset = 0;
162 char * original = null, * translated = null;
164 f.Seek(origStrings + c*2*sizeof(uint), start);
165 f.Read(&len, sizeof(uint), 1); if(swap) len = SWAP_DWORD(len);
166 f.Read(&offset, sizeof(uint), 1); if(swap) offset = SWAP_DWORD(offset);
167 f.Seek(offset, start);
169 original = new byte[len + 1];
170 f.Read(original, 1, len + 1);
172 f.Seek(transStrings + c*2*sizeof(uint), start);
173 f.Read(&len, sizeof(uint), 1); if(swap) len = SWAP_DWORD(len);
174 f.Read(&offset, sizeof(uint), 1); if(swap) offset = SWAP_DWORD(offset);
175 f.Seek(offset, start);
177 translated = new byte[len + 1];
178 f.Read(translated, 1, len + 1);
182 MapIterator<String, String> it { map = textMap };
183 // TOFIX: Memory leak if the add fails
184 if(it.Index(original, false))
187 textMap[original] = translated;
197 printf("Invalid format while loading %s\n", fileName);
204 public dllexport void UnloadTranslatedStrings(String name)
206 MapIterator<String, Map<String, String>> it { map = moduleMaps };
207 if(it.Index(name, false))
210 moduleMaps.Delete(it.pointer);
214 public dllexport char * GetTranslatedString(String name, char * string, char * stringAndContext)
216 Map<String, String> textMap = moduleMaps ? moduleMaps[name] : null;
217 char * result = textMap ? textMap[stringAndContext ? stringAndContext : string] : string;
218 return (result && result[0]) ? result : string;