mupen64plus-oldsvn/main/translate.c

302 lines
7 KiB
C

/***************************************************************************
translate.c - Handles multilanguage support
----------------------------------------------------------------------------
Began : Sun Nov 17 2002
Copyright : (C) 2002 by blight
Email : blight@Ashitaka
****************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "translate.h"
#include "main.h"
#include "util.h"
#include "config.h"
#include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <iconv.h>
#include <errno.h>
// types
typedef struct
{
char *orig; // original, english string
char *trans; // translated string to find entry
} translation_t;
typedef struct
{
char *name;
list_t translations;
} language_t;
// globals
static list_t g_LanguageList = NULL;
static language_t *g_Language = NULL;
// static functions
static language_t *
tr_load_language( const char *filename )
{
FILE *f;
language_t *lang;
translation_t *trans;
char line[2048];
char iso[200];
char *iso_start;
size_t inbytes;
char utf8[1024];
char *utf8_start;
size_t outbytes;
char *p, *p2;
iconv_t cd;
int i;
f = fopen( filename, "r" );
if( !f )
return NULL;
if((cd = iconv_open("UTF-8", "ISO-8859-1")) == (iconv_t)-1)
{
fclose(f);
perror(NULL);
return NULL;
}
lang = (language_t *)malloc( sizeof( language_t ) );
memset( lang, 0, sizeof( language_t ) );
while( !feof( f ) )
{
if( !fgets( line, 2048, f ) )
continue;
trim( line );
if( line[0] == ';' || line[0] == '\0' )
continue;
if( line[0] == '[' && line[strlen(line)-1] == ']' )
{
// convert language name to UTF-8
strcpy(iso, line + 1);
iso[strlen(iso)-1] = '\0';
iso_start = iso;
inbytes = strlen(iso);
utf8_start = utf8;
outbytes = 1024;
memset(utf8, 0, sizeof(utf8));
iconv(cd, &iso_start, &inbytes, &utf8_start, &outbytes);
// store language name
lang->name = malloc(strlen(utf8) + 1);
strcpy(lang->name, utf8);
continue;
}
p = strchr( line, '=' );
if( p )
{
// replace "\\n" by '\n'
while( (p2 = strstr( line, "\\n" )) )
{
*p2 = '\n'; // replace '\\' by '\n'
p2++;
for ( i = 0; i < strlen(p2); ++i )
p2[i] = p2[i+1];
}
p = strchr( line, '=' ); // line may have changed
*p = '\0'; p++;
trim( line );
trim( p );
if( strlen( line ) == 0 || strlen( p ) == 0 )
continue;
// convert translated string to UTF-8
iso_start = p;
inbytes = strlen(p);
utf8_start = utf8;
outbytes = 1024;
memset(utf8, 0, sizeof(utf8));
iconv(cd, &iso_start, &inbytes, &utf8_start, &outbytes);
// save translation data
trans = (translation_t *)malloc(sizeof(translation_t));
trans->orig = strdup( line );
trans->trans = malloc(strlen(utf8) + 1);
strcpy(trans->trans, utf8);
list_append(&(lang->translations), trans);
continue;
}
}
iconv_close(cd);
fclose(f);
return lang;
}
void
tr_delete_languages(void)
{
language_t *lang;
translation_t *trans;
list_node_t *lang_node,
*trans_node;
// free current list
list_foreach(g_LanguageList, lang_node)
{
lang = (language_t *)lang_node->data;
list_foreach(lang->translations, trans_node)
{
trans = (translation_t *)trans_node->data;
free(trans->orig);
free(trans->trans);
free(trans);
}
list_delete(&(lang->translations));
free(lang->name);
free(lang);
}
list_delete(&g_LanguageList);
}
// functions
static void
tr_load_languages( void )
{
language_t *lang;
char langdir[PATH_MAX], filename[PATH_MAX];
const char *p;
DIR *dir;
struct dirent *de;
// delete any existing list
tr_delete_languages();
// list languages
snprintf(langdir, PATH_MAX, "%slang/", get_installpath());
dir = opendir(langdir);
if(!dir)
return;
while((de = readdir(dir)))
{
p = strrchr(de->d_name, '.');
if(!p)
continue;
if(strcmp(p, ".lng"))
continue;
snprintf(filename, PATH_MAX, "%s%s", langdir, de->d_name);
lang = tr_load_language(filename);
if(lang)
{
list_append(&g_LanguageList, lang);
}
}
closedir(dir);
}
void tr_init(void)
{
list_t langList;
list_node_t *node;
char *language;
const char *confLang;
// read in language file data
tr_load_languages();
// set language based on config file
langList = tr_language_list();
confLang = config_get_string( "Language", "English" );
list_foreach(langList, node)
{
language = (char *)node->data;
if(!strcasecmp(language, confLang))
tr_set_language(language);
}
// free language name list
list_delete(&langList);
}
list_t
tr_language_list( void )
{
language_t *lang;
list_node_t *node;
list_t list = NULL;
list_foreach(g_LanguageList, node)
{
lang = (language_t *)node->data;
list_append(&list, lang->name);
}
return list;
}
int
tr_set_language(const char *name)
{
language_t *lang;
list_node_t *node;
list_foreach(g_LanguageList, node)
{
lang = (language_t *)node->data;
if(!strcasecmp(name, lang->name))
{
g_Language = lang;
return 0;
}
}
g_Language = NULL;
return -1;
}
const char *
tr( const char *text )
{
list_node_t *node;
translation_t *trans;
const char *ret = text;
if( g_Language )
{
list_foreach(g_Language->translations, node)
{
trans = (translation_t *)node->data;
if(!strcasecmp(text, trans->orig))
{
ret = trans->trans;
break;
}
}
}
return ret;
}