Issues (1963)

html/inc/translation.inc (8 issues)

1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2008 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19
$lang_language_dir = "../languages/";
20
$lang_translations_dir = "translations/";
21
$lang_prj_translations_dir = "project_specific_translations/";
22
$lang_compiled_dir = "compiled/";
23
$lang_log_level = 1;
24
25
// Get a list of compiled languages by scanning the compiled/ dir
26
// @returns A list of languages that have been compiled
27
//
28
function get_supported_languages() {
29
    global $lang_language_dir, $lang_compiled_dir;
30
    $list = array();
31
    if (!is_dir($lang_language_dir.$lang_compiled_dir)) {
32
        echo "\"".$lang_language_dir.$lang_compiled_dir."\" is not a directory. Please consult the documentation for correctly setting up the translation system.";
33
        exit;
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
34
    }
35
    $dh = opendir($lang_language_dir.$lang_compiled_dir);
36
    if (!$dh) die("can't open language dir");
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
$dh is of type resource, thus it always evaluated to false.
Loading history...
37
38
    while ($file = readdir($dh)) {
39
        if (substr($file, -7) != ".po.inc") continue;
40
        if (is_numeric(substr($file, 0, 5))) continue;
41
        $list[] = substr($file, 0, -7);
42
    }
43
    return $list;
44
}
45
46
// generate PHP files defining translation arrays.
47
// For example, the file "ca.po.inc" would contain entries of the form
48
// $language_lookup_array["ca"]["Default"] = "Defecte";
49
//
50
// Append to these files if they already exist
51
// (this may get done for both generic and project-specific translations)
52
//
53
// @param langdir The language base directory
54
// @param transdir The location of the .po files to compile relative to langdir
55
// @param compdir The output location relative to langdir
56
//
57
function build_translation_array_files($langdir, $transdir, $compdir) {
58
59
    // Run through each language and compile their lookup arrays.
60
    //
61
    if (!is_dir($langdir.$transdir)) {
0 ignored issues
show
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
62
        //debug("$info_dir not found or is not a directory");
63
    }
64
    $dh = opendir($langdir.$transdir);
65
    if (!$dh) die("can't open translation dir");
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
$dh is of type resource, thus it always evaluated to false.
Loading history...
66
    while (($file = readdir($dh)) !== false) {
67
        if ($file==".." || $file==".") {
68
            continue;
69
        }
70
        // only do files ending in .po
71
        if (substr($file,-3) != ".po"){
72
            //debug("File $file with unknown extension found in $info_dir");
73
            continue;
74
        }
75
        language_log(
76
            "-------------Compiling $transdir$file------------", 0
77
        );
78
        $language = parse_po_file($langdir.$transdir.$file);
79
        if (!$language){
80
            language_log(
81
                "WARNING: Could not parse language ".$file
82
            );
83
            continue;
84
        }
85
        $path = $langdir.$compdir.$file.".inc";
86
        if (file_exists($path)) {
87
            $fh = fopen($path, "a");
88
        } else {
89
            $fh = fopen($path, "w");
90
            fwrite($fh, "<?php\n");
91
        }
92
        if (!$fh) {
93
            language_log(
94
                "ERROR: could not access $langdir $compdir - please check permissions", 2
95
            );
96
            exit;
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
97
        }
98
        foreach ($language as $key => $value){
99
            if ($value !== "") {
100
                // Skip if the msgstr is empty
101
                fwrite($fh, "\$language_lookup_array[\"".str_replace("\"", "\\\"", substr($file,0,-3))."\"][\"".$key."\"] = \"".$value."\";\n");
102
            }
103
        }
104
        // don't write \?\> - may append
105
106
        fclose($fh);
107
    }
108
    closedir($dh);
109
}
110
111
// Parses a gettext .po-file into an associative PHP array.
112
// @param file The file to parse
113
// checking for inconsistencies if needed.
114
//
115
function parse_po_file($file) {
116
    $translation_file = file($file);
117
    $first_entry = true;
118
    $current_token_text="";
119
    $current_token ="";
120
    $parsing_token = false;
121
    $parsing_text = false;
122
    $size = sizeof($translation_file);
123
    $output = array();
124
    for ($i=0; $i<$size; $i++){
125
        $entry = trim($translation_file[$i]);
126
        //echo "line $i: $entry\n";
127
        if (substr($entry, 0, 1)=="#") {
128
            continue;
129
        } elseif (strpos($entry, "msgid") !== false) {
130
            if (!$first_entry){
131
                //If this is not the first, save the previous entry
132
                $output[$current_token]=$current_token_text;
133
            }
134
            $current_token = get_po_line($entry, $file);
135
            $current_token_text="";
136
            $parsing_token = true;
137
            $parsing_text = false;
138
            $first_entry=false;
139
        } elseif (strpos($entry, "msgstr") !== false) {
140
            $current_token_text = get_po_line($entry, $file);
141
            $parsing_token = false;
142
            $parsing_text = true;
143
        } elseif ($parsing_token) {
144
            $current_token .= get_po_line($entry, $file);
145
        } elseif ($parsing_text) {
146
            $current_token_text .= get_po_line($entry, $file);
147
        }
148
    }
149
150
    // Get the last token
151
    //
152
    if ($current_token && $current_token_text){
153
        $output[$current_token] = $current_token_text;
154
    }
155
    return $output;
156
}
157
158
159
// Returns the contents of a line (ie removes "" from start and end)
160
//
161
function get_po_line($line, $file) {
162
    $start = strpos($line, '"')+1;
163
    $stop = strrpos($line, '"');
164
    $x = substr($line, $start, $stop-$start);
165
    $n = preg_match("/[^\\\\]\"/", $x);
166
    if ($n) {
167
        echo "ERROR - MISMATCHED QUOTES IN $file: $line\n";
168
        return "";
169
    }
170
    return $x;
171
}
172
173
//////////  EVERYTHING BEFORE HERE IS FOR ops/update_translations.php,
174
//////////  AND SHOULD BE MOVED TO A SEPARATE FILE
175
176
// Translate string
177
//
178
function tra($text /* ...arglist... */) {
179
    global $language_lookup_array, $languages_in_use;
180
181
    // Find the string in the user's language
182
    //
183
    foreach ($languages_in_use as $language){
184
        if (isset($language_lookup_array[$language][$text])) {
185
            $text = $language_lookup_array[$language][$text];
186
            break;
187
        } else if ($language=="en"){
188
            // This language is defined in the code and is always available
189
            break;
190
        }
191
    }
192
193
    // Replace relevant substrings with given arguments.
194
    // Use strtr to avoid problems if an argument contains %n.
195
    $replacements = array();
196
    for ($i=1; $i<func_num_args(); $i++){
197
        $replacements["%".$i] = func_get_arg($i);
198
    }
199
200
    return strtr($text, $replacements);
201
}
202
203
function tr_specific($text, $language) {
204
    global $lang_language_dir, $lang_compiled_dir, $language_lookup_array;
205
    $file_name = $lang_language_dir.$lang_compiled_dir.$language.".po.inc";
206
    if (file_exists($file_name)) {
207
        require_once($file_name);
208
        $text = $language_lookup_array[$language][$text];
209
    }
210
    return $text;
211
}
212
213
function language_log($message, $loglevel=0) {
214
    global $lang_log_level;
215
    $msg = "";
216
    if ($loglevel==0) $msg = "[ Debug    ]";
217
    if ($loglevel==1) $msg = "[ Warning  ]";
218
    if ($loglevel==2) $msg = "[ CRITICAL ]";
219
220
    if ($loglevel >= $lang_log_level){
221
        echo gmdate("Y-m-d H:i:s", time())." ".$msg." ".$message."\n";
222
    }
223
}
224
225
// Make a list of languages which the user prefers
226
// (by looking at cookies and browser settings)
227
// cookies have highest priority.
228
229
if (isset($_COOKIE['lang'])){
230
    $language_string = $_COOKIE['lang'].",";
231
} else {
232
    $language_string = '';
233
}
234
if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) {
235
    $language_string .= strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
236
}
237
238
// Find out which language to use by iterating through list
239
// The list is comma-separated, so split it into an array of the following type:
240
//        Array (
241
//    [0] => da
242
//    [1] => en-us;q=0.7
243
//    [2] => en;q=0.3
244
//  )
245
246
$client_languages = explode(",", $language_string);
247
248
// A language is either defined as primary-secondary or primary.
249
// It can also have a quality attribute set,
250
// which orders the languages in a user preferred ordering.
251
// Since this is usally the same order as the array indices
252
// we just ignore this attribute (TODO: don't ignore this attribute)
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
253
// A missing quality attribute means q=1
254
255
$languages_in_use = array();
256
257
// Loop over languages that the client requests
258
//
259
$size = sizeof($client_languages);
260
for ($i=0; $i<$size; $i++) {
261
    if ((strlen($client_languages[$i])>2)
262
        && (substr($client_languages[$i], 2, 1) == "_" || substr($client_languages[$i], 2, 1) == "-")
263
    ){
264
        // If this is defined as primary-secondary, represent it as xx_YY
265
        //
266
        $language = substr(
267
            $client_languages[$i], 0, 2)."_".strtoupper(substr($client_languages[$i], 3, 2)
268
        );
269
270
        // And also check for the primary language
271
        //
272
        $language2 = substr($client_languages[$i], 0, 2);
273
    } else {
274
        // else just use xx
275
        //
276
        $language = substr($client_languages[$i], 0, 2);
277
        $language2 = null;
278
    }
279
280
    // if main language is english, look no further
281
    //
282
    if ((count($languages_in_use)==0) && ($language == 'en' || $language2 == 'en')) {
283
        break;
284
    }
285
286
    // If we have a translation for the language, include it
287
    //
288
    $file_name = $lang_language_dir.$lang_compiled_dir.$language.".po.inc";
289
    if (file_exists($file_name)) {
290
        if (!in_array($language, $languages_in_use)){
291
            require_once($file_name);
292
            $languages_in_use[] = $language;
293
        }
294
    }
295
    if ($language2) {
296
        $file_name = $lang_language_dir.$lang_compiled_dir.$language2.".po.inc";
297
        if (file_exists($file_name)) {
298
            if (!in_array($language2, $languages_in_use)){
299
                require_once($file_name);
300
                $languages_in_use[] = $language2;
301
            }
302
        }
303
    }
304
}
305
306
$GLOBALS['languages_in_use'] = $languages_in_use;   // for Drupal
307
308
?>
309