about summary refs log tree commit diff
path: root/src/game/localization.cpp
blob: cf637effd8aff2956fee04652f8e094d78373d9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

#include "localization.hpp"
#include <base/tl/algorithm.hpp>

extern "C" {
#include <engine/e_linereader.h>
}

static unsigned str_hash(const char *str)
{
	unsigned hash = 5381;
	for(; *str; str++)
		hash = ((hash << 5) + hash) + (*str); /* hash * 33 + c */
	return hash;
}

const char *localize(const char *str)
{
	const char *new_str = localization.find_string(str_hash(str));
	return new_str ? new_str : str;
}

LOC_CONSTSTRING::LOC_CONSTSTRING(const char *str)
{
	default_str = str;
	hash = str_hash(default_str);
	version = -1;
}

void LOC_CONSTSTRING::reload()
{
	version = localization.version();
	const char *new_str = localization.find_string(hash);
	current_str = new_str;
	if(!current_str)
		current_str = default_str;
}

LOCALIZATIONDATABASE::LOCALIZATIONDATABASE()
{
	current_version = 0;
}

void LOCALIZATIONDATABASE::add_string(const char *org_str, const char *new_str)
{
	STRING s;
	s.hash = str_hash(org_str);
	s.replacement = new_str;
	strings.add(s);
}

bool LOCALIZATIONDATABASE::load(const char *filename)
{
	// empty string means unload
	if(filename[0] == 0)
	{
		strings.clear();
		return true;
	}
	
	LINEREADER lr;
	IOHANDLE io = io_open(filename, IOFLAG_READ);
	if(!io)
		return false;
	
	dbg_msg("localization", "loaded '%s'", filename);
	strings.clear();
	
	linereader_init(&lr, io);
	char *line;
	while((line = linereader_get(&lr)))
	{
		if(!str_length(line))
			continue;
			
		if(line[0] == '#') // skip comments
			continue;
			
		char *replacement = linereader_get(&lr);
		if(!replacement)
		{
			dbg_msg("", "unexpected end of file");
			break;
		}
		
		if(replacement[0] != '=' || replacement[1] != '=' || replacement[2] != ' ')
		{
			dbg_msg("", "malform replacement line for '%s'", line);
			continue;
		}

		replacement += 3;
		localization.add_string(line, replacement);
	}
	
	current_version++;
	return true;
}

const char *LOCALIZATIONDATABASE::find_string(unsigned hash)
{
	STRING s;
	s.hash = hash;
	sorted_array<STRING>::range r = ::find_binary(strings.all(), s);
	if(r.empty())
		return 0;
	return r.front().replacement;
}

LOCALIZATIONDATABASE localization;