/* Copyright (C) 2009-2016 Parallel Realities This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. */ #include "i18n.h" char *getTranslatedString(char *); void setLanguage(char *, char *); void cleanupLanguage(void); static int hashCode(char *); static void put(char *, char *); static void initTable(void); static HashTable table; void setLanguage(char *applicationName, char *languageCode) { char language[MAX_DESCRIPTION_LENGTH], c[MAX_LINE_LENGTH]; char **key, **value; #ifndef _WIN32 char *lang; #endif int i, swap; FILE *fp; MOHeader header; MOEntry *original, *translation; #if DEV == 1 int read; #endif initTable(); language[0] = '\0'; if (languageCode == NULL) { #ifdef _WIN32 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, c, MAX_LINE_LENGTH); if (c[0] != '\0') { STRNCPY(language, c, MAX_DESCRIPTION_LENGTH); GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, c, MAX_LINE_LENGTH); if (c[0] != '\0') { strncat(language, "_", MAX_DESCRIPTION_LENGTH - strlen(language) - 1); strncat(language, c, MAX_DESCRIPTION_LENGTH - strlen(language) - 1); } } #else if ((lang = getenv("LC_ALL")) || (lang = getenv("LC_CTYPE")) || (lang = getenv("LANG"))) { STRNCPY(language, lang, MAX_DESCRIPTION_LENGTH); } #endif } else { STRNCPY(language, languageCode, MAX_DESCRIPTION_LENGTH); } strtok(language, "."); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Locale is %s", language); sprintf(c, "%s/%s/LC_MESSAGES/%s.mo", LOCALE_DIR, language, applicationName); #if DEV == 1 printf("Opening %s\n", c); #endif fp = fopen(c, "rb"); if (fp == NULL) { #if DEV == 1 printf("Failed to open %s/%s/LC_MESSAGES/%s.mo\n", LOCALE_DIR, language, applicationName); #endif if (strstr(language, "_") == NULL) { return; } strtok(language, "_"); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Language is %s", language); sprintf(c, "%s/%s/LC_MESSAGES/%s.mo", LOCALE_DIR, language, applicationName); #if DEV == 1 printf("Opening %s\n", c); #endif fp = fopen(c, "rb"); if (fp == NULL) { #if DEV == 1 printf("Failed to open %s/%s/LC_MESSAGES/%s.mo\n", LOCALE_DIR, language, applicationName); #endif return; } } fread(&header, sizeof(header), 1, fp); swap = header.magicNumber == 0x950412de ? 0 : 1; if (swap) { header.stringCount = SDL_Swap32(header.stringCount); header.originalOffset = SDL_Swap32(header.originalOffset); header.translationOffset = SDL_Swap32(header.translationOffset); } original = malloc(sizeof(MOEntry) * header.stringCount); translation = malloc(sizeof(MOEntry) * header.stringCount); if (original == NULL || translation == NULL) { printf("Failed to allocate %d bytes for translation strings\n", (int)sizeof(MOEntry) * header.stringCount); exit(1); } #if DEV == 1 printf("MO file has %d entries\n", header.stringCount); #endif fseek(fp, header.originalOffset, SEEK_SET); key = malloc(sizeof(char *) * header.stringCount); value = malloc(sizeof(char *) * header.stringCount); if (key == NULL || value == NULL) { printf("Failed to allocate a whole %d bytes for translation strings\n", (int)sizeof(char *) * header.stringCount); exit(1); } for (i=0;inext = NULL; table.bucketCount[i] = 0; } } static void put(char *key, char *value) { Bucket *bucket, *newBucket; unsigned int hash = hashCode(key); #if DEV == 1 printf("%s = %d\n", key, hash); #endif bucket = table.bucket[hash]; while (bucket->next != NULL) { bucket = bucket->next; } newBucket = malloc(sizeof(Bucket)); if (newBucket == NULL) { printf("Failed to allocate a whole %d bytes for a HashTable bucket\n", (int)sizeof(Bucket)); exit(1); } newBucket->key = malloc(strlen(key) + 1); newBucket->value = malloc(strlen(value) + 1); if (newBucket->key == NULL || newBucket->value == NULL) { printf("Failed to allocate a whole %d bytes for a translation\n", (int)strlen(newBucket->key) + 1); exit(1); } STRNCPY(newBucket->key, key, strlen(key) + 1); STRNCPY(newBucket->value, value, strlen(value) + 1); newBucket->next = NULL; bucket->next = newBucket; table.bucketCount[hash]++; } char *getTranslatedString(char *key) { Bucket *bucket; unsigned int hash = hashCode(key); bucket = table.bucket[hash]->next; for (;bucket!=NULL;bucket=bucket->next) { if (strcasecmp(key, bucket->key) == 0) { return strlen(bucket->value) == 0 ? key : bucket->value; } } return key; } void cleanupLanguage() { int i; Bucket *bucket, *p, *q; for (i=0;inext;p!=NULL;p=q) { free(p->key); free(p->value); q = p->next; free(p); } free(bucket); } table.bucket = NULL; }