summaryrefslogtreecommitdiffstats
path: root/inc/dictionary.inc.php
blob: ee196f5902fe06b588524cc75aac2ed356491f05 (plain) (blame)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
<?php

class Dictionary
{

	/**
	 * @var string[] Array of languages, numeric index, two letter CC as values
	 */
	private static $languages = false;
	/**
	 * @var array Array of languages, numeric index, values are ['name' => 'Language Name', 'cc' => 'xx']
	 */
	private static $languagesLong = false;
	private static $stringCache = array();

	public static function init()
	{
		self::$languages = array();
		foreach (glob('lang/??', GLOB_ONLYDIR) as $lang) {
			$lang = basename($lang);
			if ($lang === '..')
				continue;
			self::$languages[] = $lang;
		}

		//Changes the language in case there is a request to
		$lang = Request::get('lang');
		if ($lang !== false && in_array($lang, self::$languages)) {
			setcookie('lang', $lang, time() + 60 * 60 * 24 * 30 * 12);
			$url = Request::get('url');
			if ($url === false && isset($_SERVER['HTTP_REFERER']))
				$url = $_SERVER['HTTP_REFERER'];
			if ($url === false)
				$url = '?do=Main';
			Util::redirect($url);
		}

		//Default language
		$language = 'en';

		if (isset($_COOKIE['lang']) && in_array($_COOKIE['lang'], self::$languages)) {
			// Did user override language?
			$language = $_COOKIE['lang'];
		} else if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
			$langs = preg_split('/[,\s]+/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
			foreach ($langs as $lang) {
				$lang = substr($lang, 0, 2);
				if (in_array($lang, self::$languages)) {
					$language = $lang;
					break;
				}
			}
		}

		define('LANG', $language);
	}

	/**
	 * Get complete key=>value list for given module, file, language
	 *
	 * @param string $module Module name
	 * @param string $file Dictionary name
	 * @param string|false $lang Language CC, false === current language
	 * @return array assoc array mapping language tags to the translated strings
	 */
	public static function getArray($module, $file, $lang = false)
	{
		if ($lang === false)
			$lang = LANG;
		$path = Util::safePath("modules/{$module}/lang/{$lang}/{$file}.json");
		if (isset(self::$stringCache[$path]))
			return self::$stringCache[$path];
		if (!file_exists($path))
			return array();
		$content = file_get_contents($path);
		if ($content === false) { // File does not exist for language
			$content = '[]';
		}
		$json = json_decode($content, true);
		if (!is_array($json)) {
			$json = array();
		}
		return self::$stringCache[$path] = $json;
	}

	/**
	 * Translate a tag from a dictionary of a module. The current
	 * language will be used.
	 *
	 * @param string $moduleId The module in question
	 * @param string $file Dictionary name
	 * @param string $tag Tag name
	 * @param bool $returnTagOnMissing If true, the tag name enclosed in {{}} will be returned if the tag does not exist
	 * @return string|false The requested tag's translation, or false if not found and $returnTagOnMissing === false
	 */
	public static function translateFileModule($moduleId, $file, $tag, $returnTagOnMissing = false)
	{
		$strings = self::getArray($moduleId, $file);
		if (!isset($strings[$tag])) {
			if ($returnTagOnMissing) {
				return '{{' . $tag . '}}';
			}
			return false;
		}
		return $strings[$tag];
	}

	/**
	 * Translate a tag from a dictionary of the current module, using the current language.
	 *
	 * @param string $file Dictionary name
	 * @param string $tag Tag name
	 * @param bool $returnTagOnMissing If true, the tag name enclosed in {{}} will be returned if the tag does not exist
	 * @return string|false The requested tag's translation, or false if not found and $returnTagOnMissing === false
	 */
	public static function translateFile($file, $tag, $returnTagOnMissing = false)
	{
		if (!class_exists('Page') || Page::getModule() === false)
			return false; // We have no page - return false for now, as we're most likely running in api or install mode
		return self::translateFileModule(Page::getModule()->getIdentifier(), $file, $tag, $returnTagOnMissing);
	}

	/**
	 * Translate a tag from the current module's default dictionary, using the current language.
	 *
	 * @param string $tag Tag name
	 * @param bool $returnTagOnMissing If true, the tag name enclosed in {{}} will be returned if the tag does not exist
	 * @return string|false The requested tag's translation, or false if not found and $returnTagOnMissing === false
	 */
	public static function translate($tag, $returnTagOnMissing = false)
	{
		$string = self::translateFile('module', $tag);
		if ($string !== false)
			return $string;
		$string = self::translateFileModule('main', 'global-tags', $tag);
		if ($string !== false || !$returnTagOnMissing)
			return $string;
		return '{{' . $tag . '}}';
	}

	/**
	 * Translate the given message id, reading the given module's messages dictionary.
	 *
	 * @param string $module Module the message belongs to
	 * @param string $id Message id
	 * @return string|false
	 */
	public static function getMessage($module, $id)
	{
		$string = self::translateFileModule($module, 'messages', $id);
		if ($string === false) {
			return "($id) ({{0}}, {{1}}, {{2}}, {{3}})";
		}
		return $string;
	}

	/**
	 * Get translation of the given category.
	 *
	 * @param string $category
	 * @return string Category name, or some generic fallback to the given category id
	 */
	public static function getCategoryName($category)
	{
		if ($category === false) {
			return 'No Category';
		}
		if (!preg_match('/^(\w+)\.(.*)$/', $category, $out)) {
			return 'Invalid Category ID format: ' . $category;
		}
		$string = self::translateFileModule($out[1], 'categories', $out[2]);
		if ($string === false) {
			return "!!{$category}!!";
		}
		return $string;
	}

	/**
	 * Get all supported languages as array.
	 *
	 * @param boolean $withName true = return assoc array containing cc and name of all languages;
	 *		false = regular array containing only the ccs
	 * @return array List of languages
	 */
	public static function getLanguages($withName = false)
	{
		if (!$withName)
			return self::$languages;
		if (self::$languagesLong === false) {
			self::$languagesLong = array();
			foreach (self::$languages as $lang) {
				if (file_exists("lang/$lang/name.txt")) {
					$name = file_get_contents("lang/$lang/name.txt");
				}
				if (!isset($name) || $name === false) {
					$name = $lang;
				}
				self::$languagesLong[] = array(
					'cc' => $lang,
					'name' => $name
				);
			}
		}
		return self::$languagesLong;
	}

	/**
	 * Get name of language matching given language CC.
	 * Default to the CC if the language isn't known.
	 *
	 * @param string $langCC
	 * @return string
	 */
	public static function getLanguageName($langCC)
	{
		if (file_exists("lang/$langCC/name.txt")) {
			$name = file_get_contents("lang/$langCC/name.txt");
		}
		if (!isset($name) || $name === false) {
			$name = $langCC;
		}
		return $name;
	}

	/**
	 * Get an <img> tag for the given language. If there is no flag image,
	 * fall back to generating a .badge with the CC.
	 * If long mode is requested, returns the name of the language right next
	 * to the image, otherwise, it is just added as the title attribute.
	 *
	 * @param $caption bool with caption next to <img>
	 * @param $langCC string Language cc to get flag code for - defaults to current language
	 * @retrun string html code of img tag for language
	 */
	public static function getFlagHtml($caption = false, $langCC = false)
	{
		if ($langCC === false) {
			$langCC = LANG;
		}
		$flag = "lang/$langCC/flag.png";
		$name = htmlspecialchars(self::getLanguageName($langCC));
		if (file_exists($flag)) {
			$img = '<img alt="' . $name . '" title="' . $name . '" src="' . $flag . '"> ';
			if ($caption) {
				$img .= $name;
			}
		} else {
			$img = '<div class="badge" title="' . $name . '">' . $langCC . '</div>';
		}
		return $img;
	}

}

Dictionary::init();