forked from mantisbt/mantisbt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlang_api.php
370 lines (308 loc) · 10.3 KB
/
lang_api.php
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
<?php
# MantisBT - A PHP based bugtracking system
# MantisBT 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.
#
# MantisBT 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 MantisBT. If not, see <http://www.gnu.org/licenses/>.
/**
* Language (Internationalization) API
*
* @package CoreAPI
* @subpackage LanguageAPI
* @copyright Copyright 2000 - 2002 Kenzaburo Ito - [email protected]
* @copyright Copyright 2002 MantisBT Team - [email protected]
* @link http://www.mantisbt.org
*
* @uses authentication_api.php
* @uses config_api.php
* @uses constant_inc.php
* @uses error_api.php
* @uses plugin_api.php
* @uses user_pref_api.php
*/
require_api( 'authentication_api.php' );
require_api( 'config_api.php' );
require_api( 'constant_inc.php' );
require_api( 'error_api.php' );
require_api( 'plugin_api.php' );
require_api( 'user_pref_api.php' );
# Cache of localization strings in the language specified by the last
# lang_load call
$g_lang_strings = array();
# stack for language overrides
$g_lang_overrides = array();
# To be used in custom_strings_inc.php :
$g_active_language = '';
/**
* Loads the specified language and stores it in $g_lang_strings, to be used by lang_get
* @param string $p_lang Name of Language to load.
* @param string $p_dir Directory Containing language file.
* @return void
*/
function lang_load( $p_lang, $p_dir = null ) {
global $g_lang_strings, $g_active_language;
$g_active_language = $p_lang;
if( isset( $g_lang_strings[$p_lang] ) && is_null( $p_dir ) ) {
return;
}
if( !lang_language_exists( $p_lang ) ) {
return;
}
if( $p_dir === null ) {
include_once( config_get_global( 'language_path' ) . 'strings_' . $p_lang . '.txt' );
} else {
if( is_file( $p_dir . 'strings_' . $p_lang . '.txt' ) ) {
include_once( $p_dir . 'strings_' . $p_lang . '.txt' );
}
}
# Allow overriding strings declared in the language file.
# custom_strings_inc.php can use $g_active_language.
# Include file multiple times to allow for overrides per language.
global $g_config_path;
if( file_exists( $g_config_path . 'custom_strings_inc.php' ) ) {
include( $g_config_path . 'custom_strings_inc.php' );
}
$t_vars = get_defined_vars();
foreach( array_keys( $t_vars ) as $t_var ) {
$t_lang_var = preg_replace( '/^s_/', '', $t_var );
if( $t_lang_var != $t_var ) {
$g_lang_strings[$p_lang][$t_lang_var] = $$t_var;
} else if( 'MANTIS_ERROR' == $t_var ) {
if( isset( $g_lang_strings[$p_lang][$t_lang_var] ) ) {
foreach( $$t_var as $t_key => $t_val ) {
$g_lang_strings[$p_lang][$t_lang_var][$t_key] = $t_val;
}
} else {
$g_lang_strings[$p_lang][$t_lang_var] = $$t_var;
}
}
}
}
/**
* Determine the preferred language
* @return string
*/
function lang_get_default() {
global $g_active_language;
$t_lang = false;
# Confirm that the user's language can be determined
if( function_exists( 'auth_is_user_authenticated' ) && auth_is_user_authenticated() ) {
$t_lang = user_pref_get_language( auth_get_current_user_id() );
}
# Otherwise fall back to default
if( !$t_lang ) {
$t_lang = config_get_global( 'default_language' );
}
if( $t_lang == 'auto' ) {
$t_lang = lang_map_auto();
}
# Remember the language
$g_active_language = $t_lang;
return $t_lang;
}
/**
* Auto Map Language from HTTP server data
* @return string
*/
function lang_map_auto() {
$t_lang = config_get_global( 'fallback_language' );
if( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
$t_accept_langs = explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] );
$t_auto_map = config_get_global( 'language_auto_map' );
# Expand language map
$t_auto_map_exp = array();
foreach( $t_auto_map as $t_encs => $t_enc_lang ) {
$t_encs_arr = explode( ',', $t_encs );
foreach( $t_encs_arr as $t_enc ) {
$t_auto_map_exp[trim( $t_enc )] = $t_enc_lang;
}
}
# Find encoding
foreach( $t_accept_langs as $t_accept_lang ) {
$t_tmp = explode( ';', mb_strtolower( $t_accept_lang ) );
if( isset( $t_auto_map_exp[trim( $t_tmp[0] )] ) ) {
$t_valid_langs = config_get( 'language_choices_arr' );
$t_found_lang = $t_auto_map_exp[trim( $t_tmp[0] )];
if( in_array( $t_found_lang, $t_valid_langs, true ) ) {
$t_lang = $t_found_lang;
break;
}
}
}
}
return $t_lang;
}
/**
* Ensures that a language file has been loaded.
* Also load the currently active plugin's strings, if there is one.
* @param string $p_lang The language name.
* @return void
*/
function lang_ensure_loaded( $p_lang ) {
global $g_lang_strings;
if( !isset( $g_lang_strings[$p_lang] ) ) {
lang_load( $p_lang );
}
# Load current plugin's strings
$t_plugin_current = plugin_get_current();
if( $t_plugin_current !== null ) {
lang_load( $p_lang, config_get_global( 'plugin_path' ) . $t_plugin_current . '/lang/' );
}
}
/**
* Check if the given language exists
*
* @param string $p_lang The language name.
* @return boolean
*/
function lang_language_exists( $p_lang ) {
$t_valid_langs = config_get( 'language_choices_arr' );
$t_valid = in_array( $p_lang, $t_valid_langs, true );
return $t_valid;
}
/**
* language stack implementation
* push a language onto the stack
* @param string $p_lang The language name.
* @return void
*/
function lang_push( $p_lang = null ) {
global $g_lang_overrides;
# If no specific language is requested, we'll
# try to determine the language from the users
# preferences
$t_lang = $p_lang;
if( null === $t_lang ) {
$t_lang = config_get_global( 'default_language' );
}
# don't allow 'auto' as a language to be pushed onto the stack
# The results from auto are always the local user, not what the
# override wants, unless this is the first language setting
if( ( 'auto' == $t_lang ) && ( 0 < count( $g_lang_overrides ) ) ) {
$t_lang = config_get_global( 'fallback_language' );
}
$g_lang_overrides[] = $t_lang;
# Remember the language
$g_active_language = $t_lang;
# make sure it's loaded
lang_ensure_loaded( $t_lang );
}
/**
* pop a language from the stack and return it
* @return string
*/
function lang_pop() {
global $g_lang_overrides;
return array_pop( $g_lang_overrides );
}
/**
* return value on top of the language stack
* return default if stack is empty
* @return string
*/
function lang_get_current() {
global $g_lang_overrides;
$t_count_overrides = count( $g_lang_overrides );
if( $t_count_overrides > 0 ) {
$t_lang = $g_lang_overrides[$t_count_overrides - 1];
} else {
$t_lang = lang_get_default();
}
return $t_lang;
}
/**
* Retrieves an internationalized string
* This function will return one of (in order of preference):
* 1. The string in the current user's preferred language (if defined)
* 2. The string in English
* Note: when $p_string is 'MANTIS_ERROR', the return value is an array of error messages.
* @param string $p_string The language string to retrieve.
* @param string $p_lang The language name.
* @return string|array
*/
function lang_get( $p_string, $p_lang = null ) {
global $g_lang_strings;
# If no specific language is requested, we'll try to
# determine the language from the users preferences
$t_lang = $p_lang;
if( null === $t_lang ) {
$t_lang = lang_get_current();
}
# Now we'll make sure that the requested language is loaded
lang_ensure_loaded( $t_lang );
# note in the current implementation we always return the same value
# because we don't have a concept of falling back on a language. The
# language files actually *contain* English strings if none has been
# defined in the correct language
# @todo thraxisp - not sure if this is still true. Strings from last language loaded
# may still be in memory if a new language is loaded.
if( lang_exists( $p_string, $t_lang ) ) {
return $g_lang_strings[$t_lang][$p_string];
} elseif( $t_lang != 'english' ) {
# If the string was not found in the foreign language, then retry with English.
return lang_get( $p_string, 'english' );
} else {
error_parameters( $p_string );
trigger_error( ERROR_LANG_STRING_NOT_FOUND, WARNING );
return '';
}
}
/**
* Check the language entry, if found return true, otherwise return false.
* @param string $p_string The language string to retrieve.
* @param string $p_lang The language name.
* @return boolean
*/
function lang_exists( $p_string, $p_lang ) {
global $g_lang_strings;
return( isset( $g_lang_strings[$p_lang] ) && isset( $g_lang_strings[$p_lang][$p_string] ) );
}
/**
* Get language:
* - If found, return the appropriate string (as lang_get()).
* - If not found, no default supplied, return the supplied string as is.
* - If not found, default supplied, return default.
* @param string $p_string The language string to retrieve.
* @param string $p_default The default value to return.
* @param string $p_lang The language name.
* @return string
*/
function lang_get_defaulted( $p_string, $p_default = null, $p_lang = null ) {
$t_lang = $p_lang;
if( null === $t_lang ) {
$t_lang = lang_get_current();
}
# Now we'll make sure that the requested language is loaded
lang_ensure_loaded( $t_lang );
if( lang_exists( $p_string, $t_lang ) ) {
return lang_get( $p_string );
} elseif( $t_lang != 'english' ) {
# If the string was not found in the foreign language, then retry with English.
return lang_get_defaulted( $p_string, $p_default, 'english' );
} else {
# English string was not found either, return the default,
# or the original string if no default was provided
return $p_default !== null ? $p_default : $p_string;
}
}
/**
* Maps current lang string to moment.js locale.
* @see https://github.com/moment/moment/tree/develop/locale
* @return string Two chars browser language code (e.g. 'de' for German)
*/
function lang_get_current_datetime_locale() {
$t_lang = lang_get_current();
# Lookup $g_language_auto_map by value and then return the first key
$t_auto_map = config_get_global( 'language_auto_map' );
$t_entry = array_search( $t_lang, $t_auto_map );
$t_key_arr = explode( ',', $t_entry );
return $t_key_arr[0];
}