Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

171 lines (149 sloc) 4.633 kb
#include <string>
#include <iostream>
#include <boost/unordered_map.hpp>
#include "stdint.h"
#include "filesystem.hpp"
#include "module.hpp"
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif
#ifdef TARGET_OS_HARMATTAN
#include <gconf/gconf-client.h>
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef TARGET_BLACKBERRY
#include "bps/bps.h"
#include "bps/locale.h"
#include <sstream>
#endif
namespace {
//header structure of the MO file format, as described on
//http://www.gnu.org/software/hello/manual/gettext/MO-Files.html
struct mo_header {
uint32_t magic;
uint32_t version;
uint32_t number; // number of strings
uint32_t o_offset; // offset of original string table
uint32_t t_offset; // offset of translated string table
};
//the original and translated string table consists of
//a number of string length / file offset pairs:
struct mo_entry {
uint32_t length;
uint32_t offset;
};
//hashmap to map original to translated strings
typedef boost::unordered_map<std::string, std::string> map;
map hashmap;
std::string locale;
}
namespace i18n {
const std::string& tr(const std::string& msgid) {
//do not attempt to translate empty strings ("") since that returns metadata
if (msgid.empty())
return msgid;
map::iterator it = hashmap.find (msgid);
if (it != hashmap.end())
return it->second;
//if no translated string was found, return the original
return msgid;
}
const std::string& get_locale() {
return locale;
}
void init() {
#ifdef _WIN32
{
char c[1024];
GetLocaleInfoA(LOCALE_USER_DEFAULT,LOCALE_SISO639LANGNAME,c,1024);
if(c[0]!='\0'){
locale=c;
GetLocaleInfoA(LOCALE_USER_DEFAULT,LOCALE_SISO3166CTRYNAME,c,1024);
if(c[0]!='\0') locale+=std::string("_")+c;
}
}
#endif
#ifdef __APPLE__
CFArrayRef localeIDs = CFLocaleCopyPreferredLanguages();
if (localeIDs)
{
CFStringRef localeID = (CFStringRef)CFArrayGetValueAtIndex(localeIDs, 0);
char tmp[16];
if (CFStringGetCString(localeID, tmp, 16, kCFStringEncodingUTF8))
locale = std::string(tmp);
CFRelease(localeIDs);
}
#endif
#if defined(TARGET_OS_HARMATTAN)
std::cerr << "Get GConf default client\n";
GConfClient *gconf = gconf_client_get_default();
locale = std::string(gconf_client_get_string(gconf, "/meegotouch/i18n/region", NULL));
#elif defined(TARGET_BLACKBERRY)
char *language = 0;
char *country = 0;
if (BPS_SUCCESS == locale_get(&language, &country) && language!= NULL && country != NULL) {
std::stringstream ss;
ss << language << "_" << country;
locale = ss.str();
bps_free(language);
bps_free(country);
}
#else
char *cstr = getenv("LANG");
if (cstr != NULL)
locale = cstr;
if (locale.size() < 2)
{
cstr = getenv("LC_ALL");
if (cstr != NULL)
locale = cstr;
}
if (locale == "zh-Hans") locale = "zh_CN"; //hack to make it work on iOS
if (locale == "zh-Hant") locale = "zh_TW";
#endif
//strip the charset part of the country and language code,
//e.g. "pt_BR.UTF8" --> "pt_BR"
size_t found = locale.find(".");
if (found != std::string::npos) {
locale = locale.substr(0, found);
}
if (locale.size() < 2)
return;
std::string filename = "./locale/" + locale + "/LC_MESSAGES/frogatto.mo";
found = locale.find("@");
if (!sys::file_exists(module::map_file(filename)) && found != std::string::npos) {
locale = locale.substr(0, found);
filename = "./locale/" + locale + "/LC_MESSAGES/frogatto.mo";
}
//strip the country code, e.g. "de_DE" --> "de"
found = locale.find("_");
if (!sys::file_exists(module::map_file(filename)) && found != std::string::npos) {
locale = locale.substr(0, found);
filename = "./locale/" + locale + "/LC_MESSAGES/frogatto.mo";
}
if (!sys::file_exists(module::map_file(filename)))
return;
const std::string content = sys::read_file(module::map_file(filename));
size_t size = content.size();
if (size < sizeof(mo_header))
return;
mo_header* header = (mo_header*) content.c_str();
if (header->magic != 0x950412de ||
header->version != 0 ||
header->o_offset + 8*header->number > size ||
header->t_offset + 8*header->number > size)
return;
mo_entry* original = (mo_entry*) (content.c_str() + header->o_offset);
mo_entry* translated = (mo_entry*) (content.c_str() + header->t_offset);
for (int i = 0; i < header->number; ++i) {
if (original[i].offset + original[i].length > size ||
translated[i].offset + translated[i].length > size)
return;
const std::string msgid = content.substr(original[i].offset, original[i].length);
const std::string msgstr = content.substr(translated[i].offset, translated[i].length);
hashmap[msgid] = msgstr;
}
}
}
Jump to Line
Something went wrong with that request. Please try again.