aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authornikrou <nikrou@piwigo.org>2010-03-02 14:54:22 +0000
committernikrou <nikrou@piwigo.org>2010-03-02 14:54:22 +0000
commit2e890e9597da29346a1fbe0db45f48e4a2be86e7 (patch)
treef189c8320f38340bc3d7a94d799e05e0587d95cb /include
parent35694a636ef34dba5384e1a530b837208b9e55f9 (diff)
Feature 1451 : localization with gettext
Use php-gettext (developpement version rev43, because of php5.3) as fallback Use native language (english) instead of key for translation Keep directory en_UK for english customization Need some refactoring for plurals Todo : managing plugins in the same way git-svn-id: http://piwigo.org/svn/trunk@5021 68402e56-0260-453c-a942-63ccdbb3a9ee
Diffstat (limited to '')
-rw-r--r--include/calendar_base.class.php4
-rw-r--r--include/common.inc.php8
-rw-r--r--include/functions.inc.php72
-rw-r--r--include/functions_category.inc.php8
-rw-r--r--include/functions_comment.inc.php6
-rw-r--r--include/functions_html.inc.php12
-rw-r--r--include/functions_mail.inc.php2
-rw-r--r--include/functions_notification.inc.php2
-rw-r--r--include/functions_user.inc.php14
-rw-r--r--include/menubar.inc.php36
-rw-r--r--include/php-gettext/gettext.inc.php418
-rw-r--r--include/php-gettext/gettext.php408
-rw-r--r--include/php-gettext/streams.php167
-rw-r--r--include/picture_comment.inc.php6
-rw-r--r--include/section_init.inc.php16
-rw-r--r--include/ws_functions.inc.php2
16 files changed, 1102 insertions, 79 deletions
diff --git a/include/calendar_base.class.php b/include/calendar_base.class.php
index ee1fe7bea..02fa9451d 100644
--- a/include/calendar_base.class.php
+++ b/include/calendar_base.class.php
@@ -95,7 +95,7 @@ class CalendarBase
}
elseif ('any' === $date_component )
{
- $label = l10n('calendar_any');
+ $label = l10n('All');
}
return $label;
}
@@ -192,7 +192,7 @@ class CalendarBase
array( 'start' )
);
$nav_bar_datas[]=array(
- 'LABEL' => l10n('calendar_any'),
+ 'LABEL' => l10n('All'),
'URL' => $url
);
}
diff --git a/include/common.inc.php b/include/common.inc.php
index 124625e4d..814eaaf40 100644
--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -173,19 +173,19 @@ if (isset($user['internal_status']['guest_must_be_guest'])
and
$user['internal_status']['guest_must_be_guest'] === true)
{
- $header_msgs[] = l10n('guest_must_be_guest');
+ $header_msgs[] = l10n('Bad status for user "guest", using default status. Please notify the webmaster.');
}
if ($conf['gallery_locked'])
{
- $header_msgs[] = l10n('gallery_locked_message');
+ $header_msgs[] = l10n('The gallery is locked for maintenance. Please, come back later.');
if ( script_basename() != 'identification' and !is_admin() )
{
set_status_header(503, 'Service Unavailable');
@header('Retry-After: 900');
header('Content-Type: text/html; charset='.get_pwg_charset());
- echo '<a href="'.get_absolute_root_url(false).'identification.php">'.l10n('gallery_locked_message').'</a>';
+ echo '<a href="'.get_absolute_root_url(false).'identification.php">'.l10n('The gallery is locked for maintenance. Please, come back later.').'</a>';
echo str_repeat( ' ', 512); //IE6 doesn't error output if below a size
exit();
}
@@ -203,7 +203,7 @@ if ($conf['check_upgrade_feed'])
if (is_adviser())
{
- $header_msgs[] = l10n('adviser_mode_enabled');
+ $header_msgs[] = l10n('Adviser mode enabled');
}
if (count($header_msgs) > 0)
diff --git a/include/functions.inc.php b/include/functions.inc.php
index 765f17c51..fed1d3f5c 100644
--- a/include/functions.inc.php
+++ b/include/functions.inc.php
@@ -30,6 +30,7 @@ include_once( PHPWG_ROOT_PATH .'include/functions_html.inc.php' );
include_once( PHPWG_ROOT_PATH .'include/functions_tag.inc.php' );
include_once( PHPWG_ROOT_PATH .'include/functions_url.inc.php' );
include_once( PHPWG_ROOT_PATH .'include/functions_plugins.inc.php' );
+include_once( PHPWG_ROOT_PATH .'include/php-gettext/gettext.inc.php' );
//----------------------------------------------------------- generic functions
function get_extra_fields($order_by_fields)
@@ -39,7 +40,7 @@ function get_extra_fields($order_by_fields)
$order_by_fields
);
if (!empty($fields))
- {
+ {
$fields = ','.$fields;
}
return $fields;
@@ -173,7 +174,7 @@ function mkgetdir($dir, $flags=MKGETDIR_DEFAULT)
umask($umask);
if ($mkd==false)
{
- !($flags&MKGETDIR_DIE_ON_ERROR) or fatal_error( "$dir ".l10n('no_write_access'));
+ !($flags&MKGETDIR_DIE_ON_ERROR) or fatal_error( "$dir ".l10n('no write access'));
return false;
}
if( $flags&MKGETDIR_PROTECT_HTACCESS )
@@ -189,7 +190,7 @@ function mkgetdir($dir, $flags=MKGETDIR_DEFAULT)
}
if ( !is_writable($dir) )
{
- !($flags&MKGETDIR_DIE_ON_ERROR) or fatal_error( "$dir ".l10n('no_write_access'));
+ !($flags&MKGETDIR_DIE_ON_ERROR) or fatal_error( "$dir ".l10n('no write access'));
return false;
}
return true;
@@ -213,7 +214,7 @@ function mkget_thumbnail_dir($dirname, &$errors)
if (! mkgetdir($tndir, MKGETDIR_NONE) )
{
array_push($errors,
- '['.$dirname.'] : '.l10n('no_write_access'));
+ '['.$dirname.'] : '.l10n('no write access'));
return false;
}
return $tndir;
@@ -620,7 +621,7 @@ function redirect_html( $url , $msg = '', $refresh_time = 0)
if (empty($msg))
{
- $msg = nl2br(l10n('redirect_msg'));
+ $msg = nl2br(l10n('Redirection...'));
}
$refresh = $refresh_time;
@@ -866,16 +867,28 @@ function get_name_from_file($filename)
* @param string key
* @return string
*/
-function l10n($key)
+function l10n($key, $textdomain='messages')
{
- global $lang, $conf;
+ global $user;
- if ($conf['debug_l10n'] and !isset($lang[$key]) and !empty($key))
+ if (empty($user['language']))
{
- trigger_error('[l10n] language key "'.$key.'" is not defined', E_USER_WARNING);
+ $locale = $GLOBALS['language'];
+ }
+ else
+ {
+ $locale = $user['language'];
}
- return isset($lang[$key]) ? $lang[$key] : $key;
+ T_setlocale(LC_ALL, $locale.'.UTF-8');
+
+ // Specify location of translation tables
+ T_bindtextdomain($textdomain, "./language");
+
+ // Choose domain
+ T_textdomain($textdomain);
+
+ return T_gettext($key);
}
/**
@@ -887,18 +900,35 @@ function l10n($key)
* @param decimal value
* @return string
*/
-function l10n_dec($singular_fmt_key, $plural_fmt_key, $decimal)
+function l10n_dec($singular_fmt_key, $plural_fmt_key,
+ $decimal, $textdomain='messages')
{
- global $lang_info;
-
- return
- sprintf(
- l10n((
- (($decimal > 1) or ($decimal == 0 and $lang_info['zero_plural']))
- ? $plural_fmt_key
- : $singular_fmt_key
- )), $decimal);
+ global $user;
+
+ if (empty($user['language']))
+ {
+ $locale = $GLOBALS['language'];
+ }
+ else
+ {
+ $locale = $user['language'];
+ }
+
+ T_setlocale(LC_ALL, $locale.'.UTF-8');
+
+ // Specify location of translation tables
+ T_bindtextdomain($textdomain, "./language");
+
+ // Choose domain
+ T_textdomain($textdomain);
+
+ return sprintf(T_ngettext($singular_fmt_key,
+ $plural_fmt_key,
+ $decimal),
+ $decimal
+ );
}
+
/*
* returns a single element to use with l10n_args
*
@@ -1435,7 +1465,7 @@ function get_icon($date, $is_child_date = false)
if (!isset($cache['get_icon']['title']))
{
$cache['get_icon']['title'] = sprintf(
- l10n('elements posted during the last %d days'),
+ l10n('images posted during the last %d days'),
$user['recent_period']
);
}
diff --git a/include/functions_category.inc.php b/include/functions_category.inc.php
index d35114ca3..c0f9aee1e 100644
--- a/include/functions_category.inc.php
+++ b/include/functions_category.inc.php
@@ -286,9 +286,9 @@ function get_category_preferred_image_orders()
return trigger_event('get_category_preferred_image_orders',
array(
- array(l10n('default_sort'), '', true),
+ array(l10n('Default'), '', true),
array(l10n('Average rate'), 'average_rate DESC', $conf['rate']),
- array(l10n('most_visited_cat'), 'hit DESC', true),
+ array(l10n('Most visited'), 'hit DESC', true),
array(l10n('Creation date'), 'date_creation DESC', true),
array(l10n('Post date'), 'date_available DESC', true),
array(l10n('File name'), 'file ASC', true),
@@ -297,7 +297,7 @@ function get_category_preferred_image_orders()
'rank ASC',
('categories' == @$page['section'] and !isset($page['flat']) and !isset($page['chronology_field']) )
),
- array( l10n('permissions'), 'level DESC', is_admin() )
+ array( l10n('Permissions'), 'level DESC', is_admin() )
));
}
@@ -479,7 +479,7 @@ function get_display_images_count($cat_nb_images, $cat_count_images, $cat_count_
//no descendant categories or descendants do not contain images
if (! $short_message)
{
- $display_text.= ' '.l10n('images_available_cpl');
+ $display_text.= ' '.l10n('in this category');
}
}
else
diff --git a/include/functions_comment.inc.php b/include/functions_comment.inc.php
index c4f021edf..a35c8ad60 100644
--- a/include/functions_comment.inc.php
+++ b/include/functions_comment.inc.php
@@ -103,7 +103,7 @@ SELECT COUNT(*) AS user_exists
$row = pwg_db_fetch_assoc( pwg_query( $query ) );
if ( $row['user_exists'] == 1 )
{
- array_push($infos, l10n('comment_user_exists') );
+ array_push($infos, l10n('This login is already used by another user') );
$comment_action='reject';
}
}
@@ -140,7 +140,7 @@ SELECT id FROM '.COMMENTS_TABLE.'
AND author_id = '.$comm['author_id'];
if ( pwg_db_num_rows( pwg_query( $query ) ) > 0 )
{
- array_push( $infos, l10n('comment_anti-flood') );
+ array_push( $infos, l10n('Anti-flood system : please wait for a moment before trying to post another comment') );
$comment_action='reject';
}
}
@@ -268,7 +268,7 @@ SELECT id FROM '.COMMENTS_TABLE.'
AND author_id = '.$comm['author_id'];
if ( pwg_db_num_rows( pwg_query( $query ) ) > 0 )
{
- //?? array_push( $infos, l10n('comment_anti-flood') );
+ //?? array_push( $infos, l10n('Anti-flood system : please wait for a moment before trying to post another comment') );
$comment_action='reject';
}
}
diff --git a/include/functions_html.inc.php b/include/functions_html.inc.php
index 4be5ef077..70ffe48a5 100644
--- a/include/functions_html.inc.php
+++ b/include/functions_html.inc.php
@@ -292,9 +292,9 @@ function access_denied()
if ( isset($user) and !is_a_guest() )
{
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
- echo '<div style="text-align:center;">'.l10n('access_forbiden').'<br>';
- echo '<a href="'.get_root_url().'identification.php">'.l10n('identification').'</a>&nbsp;';
- echo '<a href="'.make_index_url().'">'.l10n('home').'</a></div>';
+ echo '<div style="text-align:center;">'.l10n('You are not authorized to access the requested page').'<br>';
+ echo '<a href="'.get_root_url().'Identification.php">'.l10n('Identification').'</a>&nbsp;';
+ echo '<a href="'.make_index_url().'">'.l10n('Home').'</a></div>';
echo str_repeat( ' ', 512); //IE6 doesn't error output if below a size
exit();
}
@@ -399,7 +399,7 @@ $btrace_msg
function get_tags_content_title()
{
global $page;
- $title = count($page['tags']) > 1 ? l10n('Tags') : l10n('Tag');
+ $title = count($page['tags']) > 1 ? l10n('Tag') : l10n('Tag');
$title.= ' ';
for ($i=0; $i<count($page['tags']); $i++)
@@ -414,7 +414,7 @@ function get_tags_content_title()
)
)
.'" title="'
- .l10n('See elements linked to this tag only')
+ .l10n('See images linked to this tag only')
.'">'
.$page['tags'][$i]['name']
.'</a>';
@@ -431,7 +431,7 @@ function get_tags_content_title()
)
)
.'" style="border:none;" title="'
- .l10n('remove this tag')
+ .l10n('remove this tag from the list')
.'"><img src="'
.get_root_url().get_themeconf('icon_dir').'/remove_s.png'
.'" alt="x" style="vertical-align:bottom;" class="button">'
diff --git a/include/functions_mail.inc.php b/include/functions_mail.inc.php
index 3220d592e..c550d6857 100644
--- a/include/functions_mail.inc.php
+++ b/include/functions_mail.inc.php
@@ -646,7 +646,7 @@ function pwg_mail($to, $args = array())
'VERSION' => $conf['show_version'] ? PHPWG_VERSION : '',
'PHPWG_URL' => PHPWG_URL,
- 'TITLE_MAIL' => urlencode(l10n('title_send_mail')),
+ 'TITLE_MAIL' => urlencode(l10n('A comment on your site')),
'MAIL' => get_webmaster_mail_address()
));
diff --git a/include/functions_notification.inc.php b/include/functions_notification.inc.php
index 77416db01..4daff6496 100644
--- a/include/functions_notification.inc.php
+++ b/include/functions_notification.inc.php
@@ -529,7 +529,7 @@ function get_html_description_recent_post_date($date_detail)
.l10n_dec('%d new element', '%d new elements', $date_detail['nb_elements'])
.' ('
.'<a href="'.make_index_url(array('section'=>'recent_pics')).'">'
- .l10n('recent_pics_cat').'</a>'
+ .l10n('Recent pictures').'</a>'
.')'
.'</li><br>';
diff --git a/include/functions_user.inc.php b/include/functions_user.inc.php
index bed0c7962..d48c55f53 100644
--- a/include/functions_user.inc.php
+++ b/include/functions_user.inc.php
@@ -47,7 +47,7 @@ function validate_mail_address($user_id, $mail_address)
if ( !preg_match( $regex, $mail_address ) )
{
- return l10n('reg_err_mail_address');
+ return l10n('mail address must be like xxx@yyy.eee (example : jack@altern.org)');
}
if (defined("PHPWG_INSTALLED") and !empty($mail_address))
@@ -61,7 +61,7 @@ where upper('.$conf['user_fields']['email'].') = upper(\''.$mail_address.'\')
list($count) = pwg_db_fetch_row(pwg_query($query));
if ($count != 0)
{
- return l10n('reg_err_mail_address_dbl');
+ return l10n('a user use already this mail address');
}
}
}
@@ -86,7 +86,7 @@ WHERE LOWER(".stripslashes($conf['user_fields']['username']).") = '".strtolower(
if ($count > 0)
{
- return l10n('reg_err_login5');
+ return l10n('this login is already used');
}
}
}
@@ -98,19 +98,19 @@ function register_user($login, $password, $mail_address,
if ($login == '')
{
- array_push($errors, l10n('reg_err_login1'));
+ array_push($errors, l10n('Please, enter a login'));
}
if (preg_match('/^.* $/', $login))
{
- array_push($errors, l10n('reg_err_login2'));
+ array_push($errors, l10n('login mustn\'t end with a space character'));
}
if (preg_match('/^ .*$/', $login))
{
- array_push($errors, l10n('reg_err_login3'));
+ array_push($errors, l10n('login mustn\'t start with a space character'));
}
if (get_userid($login))
{
- array_push($errors, l10n('reg_err_login5'));
+ array_push($errors, l10n('this login is already used'));
}
$mail_error = validate_mail_address(null, $mail_address);
if ('' != $mail_error)
diff --git a/include/menubar.inc.php b/include/menubar.inc.php
index 35fdb8750..0a9800d9b 100644
--- a/include/menubar.inc.php
+++ b/include/menubar.inc.php
@@ -148,16 +148,16 @@ function initialize_menu()
$block->data['favorites'] =
array(
'URL' => make_index_url(array('section' => 'favorites')),
- 'TITLE' => l10n('favorite_cat_hint'),
- 'NAME' => l10n('favorite_cat')
+ 'TITLE' => l10n('display my favorites pictures'),
+ 'NAME' => l10n('My favorites')
);
}
$block->data['most_visited'] =
array(
'URL' => make_index_url(array('section' => 'most_visited')),
- 'TITLE' => l10n('most_visited_cat_hint'),
- 'NAME' => l10n('most_visited_cat')
+ 'TITLE' => l10n('display most visited pictures'),
+ 'NAME' => l10n('Most visited')
);
if ($conf['rate'])
@@ -165,31 +165,31 @@ function initialize_menu()
$block->data['best_rated'] =
array(
'URL' => make_index_url(array('section' => 'best_rated')),
- 'TITLE' => l10n('best_rated_cat_hint'),
- 'NAME' => l10n('best_rated_cat')
+ 'TITLE' => l10n('display best rated items'),
+ 'NAME' => l10n('Best rated')
);
}
$block->data['random'] =
array(
'URL' => get_root_url().'random.php',
- 'TITLE' => l10n('random_cat_hint'),
- 'NAME' => l10n('random_cat'),
+ 'TITLE' => l10n('display a set of random pictures'),
+ 'NAME' => l10n('Random pictures'),
'REL'=> 'rel="nofollow"'
);
$block->data['recent_pics'] =
array(
'URL' => make_index_url(array('section' => 'recent_pics')),
- 'TITLE' => l10n('recent_pics_cat_hint'),
- 'NAME' => l10n('recent_pics_cat'),
+ 'TITLE' => l10n('display most recent pictures'),
+ 'NAME' => l10n('Recent pictures'),
);
$block->data['recent_cats'] =
array(
'URL' => make_index_url(array('section' => 'recent_cats')),
- 'TITLE' => l10n('recent_cats_cat_hint'),
- 'NAME' => l10n('recent_cats_cat'),
+ 'TITLE' => l10n('display recently updated categories'),
+ 'NAME' => l10n('Recent categories'),
);
@@ -204,8 +204,8 @@ function initialize_menu()
'chronology_view' => 'calendar'
)
),
- 'TITLE' => l10n('calendar_hint'),
- 'NAME' => l10n('calendar'),
+ 'TITLE' => l10n('display each day with pictures, month per month'),
+ 'NAME' => l10n('Calendar'),
'REL'=> 'rel="nofollow"'
);
$block->template = 'menubar_specials.tpl';
@@ -230,7 +230,7 @@ function initialize_menu()
// search link
$block->data['search'] =
array(
- 'TITLE'=>l10n('hint_search'),
+ 'TITLE'=>l10n('search'),
'NAME'=>l10n('Search'),
'URL'=> get_root_url().'search.php',
'REL'=> 'rel="search"'
@@ -239,15 +239,15 @@ function initialize_menu()
// comments link
$block->data['comments'] =
array(
- 'TITLE'=>l10n('hint_comments'),
- 'NAME'=>l10n('comments'),
+ 'TITLE'=>l10n('See last users comments'),
+ 'NAME'=>l10n('Comments'),
'URL'=> get_root_url().'comments.php',
);
// about link
$block->data['about'] =
array(
- 'TITLE' => l10n('about_page_title'),
+ 'TITLE' => l10n('About Piwigo'),
'NAME' => l10n('About'),
'URL' => get_root_url().'about.php',
);
diff --git a/include/php-gettext/gettext.inc.php b/include/php-gettext/gettext.inc.php
new file mode 100644
index 000000000..69d4d7c2a
--- /dev/null
+++ b/include/php-gettext/gettext.inc.php
@@ -0,0 +1,418 @@
+<?php
+/*
+ Copyright (c) 2005 Steven Armstrong <sa at c-area dot ch>
+ Copyright (c) 2009 Danilo Segan <danilo@kvota.net>
+
+ Drop in replacement for native gettext.
+
+ This file is part of PHP-gettext.
+
+ PHP-gettext 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.
+
+ PHP-gettext 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 PHP-gettext; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+/*
+LC_CTYPE 0
+LC_NUMERIC 1
+LC_TIME 2
+LC_COLLATE 3
+LC_MONETARY 4
+LC_MESSAGES 5
+LC_ALL 6
+*/
+
+
+// LC_MESSAGES is not available if php-gettext is not loaded
+// while the other constants are already available from session extension.
+if (!defined('LC_MESSAGES')) {
+ define('LC_MESSAGES', 5);
+}
+
+require('streams.php');
+require('gettext.php');
+
+
+// Variables
+
+global $text_domains, $default_domain, $LC_CATEGORIES, $EMULATEGETTEXT, $CURRENTLOCALE;
+$text_domains = array();
+$default_domain = 'messages';
+$LC_CATEGORIES = array('LC_CTYPE', 'LC_NUMERIC', 'LC_TIME', 'LC_COLLATE', 'LC_MONETARY', 'LC_MESSAGES', 'LC_ALL');
+$EMULATEGETTEXT = 0;
+$CURRENTLOCALE = '';
+
+/* Class to hold a single domain included in $text_domains. */
+class domain {
+ var $l10n;
+ var $path;
+ var $codeset;
+}
+
+// Utility functions
+
+/**
+ * Return a list of locales to try for any POSIX-style locale specification.
+ */
+function get_list_of_locales($locale) {
+ /* Figure out all possible locale names and start with the most
+ * specific ones. I.e. for sr_CS.UTF-8@latin, look through all of
+ * sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr.
+ */
+ $locale_names = array();
+ $lang = NULL;
+ $country = NULL;
+ $charset = NULL;
+ $modifier = NULL;
+ if ($locale) {
+ if (preg_match("/^(?P<lang>[a-z]{2,3})" // language code
+ ."(?:_(?P<country>[A-Z]{2}))?" // country code
+ ."(?:\.(?P<charset>[-A-Za-z0-9_]+))?" // charset
+ ."(?:@(?P<modifier>[-A-Za-z0-9_]+))?$/", // @ modifier
+ $locale, $matches)) {
+
+ if (isset($matches["lang"])) $lang = $matches["lang"];
+ if (isset($matches["country"])) $country = $matches["country"];
+ if (isset($matches["charset"])) $charset = $matches["charset"];
+ if (isset($matches["modifier"])) $modifier = $matches["modifier"];
+
+ if ($modifier) {
+ if ($country) {
+ if ($charset)
+ array_push($locale_names, "${lang}_$country.$charset@$modifier");
+ array_push($locale_names, "${lang}_$country@$modifier");
+ } elseif ($charset)
+ array_push($locale_names, "${lang}.$charset@$modifier");
+ array_push($locale_names, "$lang@$modifier");
+ }
+ if ($country) {
+ if ($charset)
+ array_push($locale_names, "${lang}_$country.$charset");
+ array_push($locale_names, "${lang}_$country");
+ } elseif ($charset)
+ array_push($locale_names, "${lang}.$charset");
+ array_push($locale_names, $lang);
+ }
+
+ // If the locale name doesn't match POSIX style, just include it as-is.
+ if (!in_array($locale, $locale_names))
+ array_push($locale_names, $locale);
+ }
+ return $locale_names;
+}
+
+/**
+ * Utility function to get a StreamReader for the given text domain.
+ */
+function _get_reader($domain=null, $category=5, $enable_cache=true) {
+ global $text_domains, $default_domain, $LC_CATEGORIES;
+ if (!isset($domain)) $domain = $default_domain;
+ if (!isset($text_domains[$domain]->l10n)) {
+ // get the current locale
+ $locale = _setlocale(LC_MESSAGES, 0);
+ $bound_path = isset($text_domains[$domain]->path) ?
+ $text_domains[$domain]->path : './';
+ $subpath = $LC_CATEGORIES[$category] ."/$domain.mo";
+
+ $locale_names = get_list_of_locales($locale);
+ $input = null;
+ foreach ($locale_names as $locale) {
+ $full_path = $bound_path . $locale . "/" . $subpath;
+ if (file_exists($full_path)) {
+ $input = new FileReader($full_path);
+ break;
+ }
+ }
+
+ if (!array_key_exists($domain, $text_domains)) {
+ // Initialize an empty domain object.
+ $text_domains[$domain] = new domain();
+ }
+ $text_domains[$domain]->l10n = new gettext_reader($input,
+ $enable_cache);
+ }
+ return $text_domains[$domain]->l10n;
+}
+
+/**
+ * Returns whether we are using our emulated gettext API or PHP built-in one.
+ */
+function locale_emulation() {
+ global $EMULATEGETTEXT;
+ return $EMULATEGETTEXT;
+}
+
+/**
+ * Checks if the current locale is supported on this system.
+ */
+function _check_locale() {
+ global $EMULATEGETTEXT;
+ return !$EMULATEGETTEXT;
+}
+
+/**
+ * Get the codeset for the given domain.
+ */
+function _get_codeset($domain=null) {
+ global $text_domains, $default_domain, $LC_CATEGORIES;
+ if (!isset($domain)) $domain = $default_domain;
+ return (isset($text_domains[$domain]->codeset))? $text_domains[$domain]->codeset : ini_get('mbstring.internal_encoding');
+}
+
+/**
+ * Convert the given string to the encoding set by bind_textdomain_codeset.
+ */
+function _encode($text) {
+ $source_encoding = mb_detect_encoding($text);
+ $target_encoding = _get_codeset();
+ if ($source_encoding != $target_encoding) {
+ return mb_convert_encoding($text, $target_encoding, $source_encoding);
+ }
+ else {
+ return $text;
+ }
+}
+
+
+
+
+// Custom implementation of the standard gettext related functions
+
+/**
+ * Returns passed in $locale, or environment variable $LANG if $locale == ''.
+ */
+function _get_default_locale($locale) {
+ if ($locale == '') // emulate variable support
+ return getenv('LANG');
+ else
+ return $locale;
+}
+
+/**
+ * Sets a requested locale, if needed emulates it.
+ */
+function _setlocale($category, $locale) {
+ global $CURRENTLOCALE, $EMULATEGETTEXT;
+ if ($locale === 0) { // use === to differentiate between string "0"
+ if ($CURRENTLOCALE != '')
+ return $CURRENTLOCALE;
+ else
+ // obey LANG variable, maybe extend to support all of LC_* vars
+ // even if we tried to read locale without setting it first
+ return _setlocale($category, $CURRENTLOCALE);
+ } else {
+ if (function_exists('setlocale')) {
+ $ret = setlocale($category, $locale);
+ if (($locale == '' and !$ret) or // failed setting it by env
+ ($locale != '' and $ret != $locale)) { // failed setting it
+ // Failed setting it according to environment.
+ $CURRENTLOCALE = _get_default_locale($locale);
+ $EMULATEGETTEXT = 1;
+ } else {
+ $CURRENTLOCALE = $ret;
+ $EMULATEGETTEXT = 0;
+ }
+ } else {
+ // No function setlocale(), emulate it all.
+ $CURRENTLOCALE = _get_default_locale($locale);
+ $EMULATEGETTEXT = 1;
+ }
+ // Allow locale to be changed on the go for one translation domain.
+ global $text_domains, $default_domain;
+ unset($text_domains[$default_domain]->l10n);
+ return $CURRENTLOCALE;
+ }
+}
+
+/**
+ * Sets the path for a domain.
+ */
+function _bindtextdomain($domain, $path) {
+ global $text_domains;
+ // ensure $path ends with a slash ('/' should work for both, but lets still play nice)
+ if (substr(php_uname(), 0, 7) == "Windows") {
+ if ($path[strlen($path)-1] != '\\' and $path[strlen($path)-1] != '/')
+ $path .= '\\';
+ } else {
+ if ($path[strlen($path)-1] != '/')
+ $path .= '/';
+ }
+ if (!array_key_exists($domain, $text_domains)) {
+ // Initialize an empty domain object.
+ $text_domains[$domain] = new domain();
+ }
+ $text_domains[$domain]->path = $path;
+}
+
+/**
+ * Specify the character encoding in which the messages from the DOMAIN message catalog will be returned.
+ */
+function _bind_textdomain_codeset($domain, $codeset) {
+ global $text_domains;
+ $text_domains[$domain]->codeset = $codeset;
+}
+
+/**
+ * Sets the default domain.
+ */
+function _textdomain($domain) {
+ global $default_domain;
+ $default_domain = $domain;
+}
+
+/**
+ * Lookup a message in the current domain.
+ */
+function _gettext($msgid) {
+ $l10n = _get_reader();
+ //return $l10n->translate($msgid);
+ return _encode($l10n->translate($msgid));
+}
+/**
+ * Alias for gettext.
+ */
+function __($msgid) {
+ return _gettext($msgid);
+}
+/**
+ * Plural version of gettext.
+ */
+function _ngettext($single, $plural, $number) {
+ $l10n = _get_reader();
+ //return $l10n->ngettext($single, $plural, $number);
+ return _encode($l10n->ngettext($single, $plural, $number));
+}
+
+/**
+ * Override the current domain.
+ */
+function _dgettext($domain, $msgid) {
+ $l10n = _get_reader($domain);
+ //return $l10n->translate($msgid);
+ return _encode($l10n->translate($msgid));
+}
+/**
+ * Plural version of dgettext.
+ */
+function _dngettext($domain, $single, $plural, $number) {
+ $l10n = _get_reader($domain);
+ //return $l10n->ngettext($single, $plural, $number);
+ return _encode($l10n->ngettext($single, $plural, $number));
+}
+
+/**
+ * Overrides the domain and category for a single lookup.
+ */
+function _dcgettext($domain, $msgid, $category) {
+ $l10n = _get_reader($domain, $category);
+ //return $l10n->translate($msgid);
+ return _encode($l10n->translate($msgid));
+}
+/**
+ * Plural version of dcgettext.
+ */
+function _dcngettext($domain, $single, $plural, $number, $category) {
+ $l10n = _get_reader($domain, $category);
+ //return $l10n->ngettext($single, $plural, $number);
+ return _encode($l10n->ngettext($single, $plural, $number));
+}
+
+
+
+// Wrappers to use if the standard gettext functions are available, but the current locale is not supported by the system.
+// Use the standard impl if the current locale is supported, use the custom impl otherwise.
+
+function T_setlocale($category, $locale) {
+ return _setlocale($category, $locale);
+}
+
+function T_bindtextdomain($domain, $path) {
+ if (_check_locale()) return bindtextdomain($domain, $path);
+ else return _bindtextdomain($domain, $path);
+}
+function T_bind_textdomain_codeset($domain, $codeset) {
+ // bind_textdomain_codeset is available only in PHP 4.2.0+
+ if (_check_locale() and function_exists('bind_textdomain_codeset')) return bind_textdomain_codeset($domain, $codeset);
+ else return _bind_textdomain_codeset($domain, $codeset);
+}
+function T_textdomain($domain) {
+ if (_check_locale()) return textdomain($domain);
+ else return _textdomain($domain);
+}
+function T_gettext($msgid) {
+ if (_check_locale()) return gettext($msgid);
+ else return _gettext($msgid);
+}
+function T_($msgid) {
+ if (_check_locale()) return _($msgid);
+ return __($msgid);
+}
+function T_ngettext($single, $plural, $number) {
+ if (_check_locale()) return ngettext($single, $plural, $number);
+ else return _ngettext($single, $plural, $number);
+}
+function T_dgettext($domain, $msgid) {
+ if (_check_locale()) return dgettext($domain, $msgid);
+ else return _dgettext($domain, $msgid);
+}
+function T_dngettext($domain, $single, $plural, $number) {
+ if (_check_locale()) return dngettext($domain, $single, $plural, $number);
+ else return _dngettext($domain, $single, $plural, $number);
+}
+function T_dcgettext($domain, $msgid, $category) {
+ if (_check_locale()) return dcgettext($domain, $msgid, $category);
+ else return _dcgettext($domain, $msgid, $category);
+}
+function T_dcngettext($domain, $single, $plural, $number, $category) {
+ if (_check_locale()) return dcngettext($domain, $single, $plural, $number, $category);
+ else return _dcngettext($domain, $single, $plural, $number, $category);
+}
+
+
+
+// Wrappers used as a drop in replacement for the standard gettext functions
+
+if (!function_exists('gettext')) {
+ function bindtextdomain($domain, $path) {
+ return _bindtextdomain($domain, $path);
+ }
+ function bind_textdomain_codeset($domain, $codeset) {
+ return _bind_textdomain_codeset($domain, $codeset);
+ }
+ function textdomain($domain) {
+ return _textdomain($domain);
+ }
+ function gettext($msgid) {
+ return _gettext($msgid);
+ }
+ function _($msgid) {
+ return __($msgid);
+ }
+ function ngettext($single, $plural, $number) {
+ return _ngettext($single, $plural, $number);
+ }
+ function dgettext($domain, $msgid) {
+ return _dgettext($domain, $msgid);
+ }
+ function dngettext($domain, $single, $plural, $number) {
+ return _dngettext($domain, $single, $plural, $number);
+ }
+ function dcgettext($domain, $msgid, $category) {
+ return _dcgettext($domain, $msgid, $category);
+ }
+ function dcngettext($domain, $single, $plural, $number, $category) {
+ return _dcngettext($domain, $single, $plural, $number, $category);
+ }
+}
+
+?>
diff --git a/include/php-gettext/gettext.php b/include/php-gettext/gettext.php
new file mode 100644
index 000000000..f11da2e27
--- /dev/null
+++ b/include/php-gettext/gettext.php
@@ -0,0 +1,408 @@
+<?php
+/*
+ Copyright (c) 2003, 2009 Danilo Segan <danilo@kvota.net>.
+ Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
+
+ This file is part of PHP-gettext.
+
+ PHP-gettext 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.
+
+ PHP-gettext 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 PHP-gettext; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+/**
+ * Provides a simple gettext replacement that works independently from
+ * the system's gettext abilities.
+ * It can read MO files and use them for translating strings.
+ * The files are passed to gettext_reader as a Stream (see streams.php)
+ *
+ * This version has the ability to cache all strings and translations to
+ * speed up the string lookup.
+ * While the cache is enabled by default, it can be switched off with the
+ * second parameter in the constructor (e.g. whenusing very large MO files
+ * that you don't want to keep in memory)
+ */
+class gettext_reader {
+ //public:
+ var $error = 0; // public variable that holds error code (0 if no error)
+
+ //private:
+ var $BYTEORDER = 0; // 0: low endian, 1: big endian
+ var $STREAM = NULL;
+ var $short_circuit = false;
+ var $enable_cache = false;
+ var $originals = NULL; // offset of original table
+ var $translations = NULL; // offset of translation table
+ var $pluralheader = NULL; // cache header field for plural forms
+ var $total = 0; // total string count
+ var $table_originals = NULL; // table for original strings (offsets)
+ var $table_translations = NULL; // table for translated strings (offsets)
+ var $cache_translations = NULL; // original -> translation mapping
+
+
+ /* Methods */
+
+
+ /**
+ * Reads a 32bit Integer from the Stream
+ *
+ * @access private
+ * @return Integer from the Stream
+ */
+ function readint() {
+ if ($this->BYTEORDER == 0) {
+ // low endian
+ $input=unpack('V', $this->STREAM->read(4));
+ return array_shift($input);
+ } else {
+ // big endian
+ $input=unpack('N', $this->STREAM->read(4));
+ return array_shift($input);
+ }
+ }
+
+ function read($bytes) {
+ return $this->STREAM->read($bytes);
+ }
+
+ /**
+ * Reads an array of Integers from the Stream
+ *
+ * @param int count How many elements should be read
+ * @return Array of Integers
+ */
+ function readintarray($count) {
+ if ($this->BYTEORDER == 0) {
+ // low endian
+ return unpack('V'.$count, $this->STREAM->read(4 * $count));
+ } else {
+ // big endian
+ return unpack('N'.$count, $this->STREAM->read(4 * $count));
+ }
+ }
+
+ /**
+ * Constructor
+ *
+ * @param object Reader the StreamReader object
+ * @param boolean enable_cache Enable or disable caching of strings (default on)
+ */
+ function gettext_reader($Reader, $enable_cache = true) {
+ // If there isn't a StreamReader, turn on short circuit mode.
+ if (! $Reader || isset($Reader->error) ) {
+ $this->short_circuit = true;
+ return;
+ }
+
+ // Caching can be turned off
+ $this->enable_cache = $enable_cache;
+
+ $MAGIC1 = "\x95\x04\x12\xde";
+ $MAGIC2 = "\xde\x12\x04\x95";
+
+ $this->STREAM = $Reader;
+ $magic = $this->read(4);
+ if ($magic == $MAGIC1) {
+ $this->BYTEORDER = 1;
+ } elseif ($magic == $MAGIC2) {
+ $this->BYTEORDER = 0;
+ } else {
+ $this->error = 1; // not MO file
+ return false;
+ }
+
+ // FIXME: Do we care about revision? We should.
+ $revision = $this->readint();
+
+ $this->total = $this->readint();
+ $this->originals = $this->readint();
+ $this->translations = $this->readint();
+ }
+
+ /**
+ * Loads the translation tables from the MO file into the cache
+ * If caching is enabled, also loads all strings into a cache
+ * to speed up translation lookups
+ *
+ * @access private
+ */
+ function load_tables() {
+ if (is_array($this->cache_translations) &&
+ is_array($this->table_originals) &&
+ is_array($this->table_translations))
+ return;
+
+ /* get original and translations tables */
+ $this->STREAM->seekto($this->originals);
+ $this->table_originals = $this->readintarray($this->total * 2);
+ $this->STREAM->seekto($this->translations);
+ $this->table_translations = $this->readintarray($this->total * 2);
+
+ if ($this->enable_cache) {
+ $this->cache_translations = array ();
+ /* read all strings in the cache */
+ for ($i = 0; $i < $this->total; $i++) {
+ $this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
+ $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
+ $this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
+ $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
+ $this->cache_translations[$original] = $translation;
+ }
+ }
+ }
+
+ /**
+ * Returns a string from the "originals" table
+ *
+ * @access private
+ * @param int num Offset number of original string
+ * @return string Requested string if found, otherwise ''
+ */
+ function get_original_string($num) {
+ $length = $this->table_originals[$num * 2 + 1];
+ $offset = $this->table_originals[$num * 2 + 2];
+ if (! $length)
+ return '';
+ $this->STREAM->seekto($offset);
+ $data = $this->STREAM->read($length);
+ return (string)$data;
+ }
+
+ /**
+ * Returns a string from the "translations" table
+ *
+ * @access private
+ * @param int num Offset number of original string
+ * @return string Requested string if found, otherwise ''
+ */
+ function get_translation_string($num) {
+ $length = $this->table_translations[$num * 2 + 1];
+ $offset = $this->table_translations[$num * 2 + 2];
+ if (! $length)
+ return '';
+ $this->STREAM->seekto($offset);
+ $data = $this->STREAM->read($length);
+ return (string)$data;
+ }
+
+ /**
+ * Binary search for string
+ *
+ * @access private
+ * @param string string
+ * @param int start (internally used in recursive function)
+ * @param int end (internally used in recursive function)
+ * @return int string number (offset in originals table)
+ */
+ function find_string($string, $start = -1, $end = -1) {
+ if (($start == -1) or ($end == -1)) {
+ // find_string is called with only one parameter, set start end end
+ $start = 0;
+ $end = $this->total;
+ }
+ if (abs($start - $end) <= 1) {
+ // We're done, now we either found the string, or it doesn't exist
+ $txt = $this->get_original_string($start);
+ if ($string == $txt)
+ return $start;
+ else
+ return -1;
+ } else if ($start > $end) {
+ // start > end -> turn around and start over
+ return $this->find_string($string, $end, $start);
+ } else {
+ // Divide table in two parts
+ $half = (int)(($start + $end) / 2);
+ $cmp = strcmp($string, $this->get_original_string($half));
+ if ($cmp == 0)
+ // string is exactly in the middle => return it
+ return $half;
+ else if ($cmp < 0)
+ // The string is in the upper half
+ return $this->find_string($string, $start, $half);
+ else
+ // The string is in the lower half
+ return $this->find_string($string, $half, $end);
+ }
+ }
+
+ /**
+ * Translates a string
+ *
+ * @access public
+ * @param string string to be translated
+ * @return string translated string (or original, if not found)
+ */
+ function translate($string) {
+ if ($this->short_circuit)
+ return $string;
+ $this->load_tables();
+
+ if ($this->enable_cache) {
+ // Caching enabled, get translated string from cache
+ if (array_key_exists($string, $this->cache_translations))
+ return $this->cache_translations[$string];
+ else
+ return $string;
+ } else {
+ // Caching not enabled, try to find string
+ $num = $this->find_string($string);
+ if ($num == -1)
+ return $string;
+ else
+ return $this->get_translation_string($num);
+ }
+ }
+
+ /**
+ * Sanitize plural form expression for use in PHP eval call.
+ *
+ * @access private
+ * @return string sanitized plural form expression
+ */
+ function sanitize_plural_expression($expr) {
+ // Get rid of disallowed characters.
+ $expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);
+
+ // Add parenthesis for tertiary '?' operator.
+ $expr .= ';';
+ $res = '';
+ $p = 0;
+ for ($i = 0; $i < strlen($expr); $i++) {
+ $ch = $expr[$i];
+ switch ($ch) {
+ case '?':
+ $res .= ' ? (';
+ $p++;
+ break;
+ case ':':
+ $res .= ') : (';
+ break;
+ case ';':
+ $res .= str_repeat( ')', $p) . ';';
+ $p = 0;
+ break;
+ default:
+ $res .= $ch;
+ }
+ }
+ return $res;
+ }
+
+ /**
+ * Parse full PO header and extract only plural forms line.
+ *
+ * @access private
+ * @return string verbatim plural form header field
+ */
+ function extract_plural_forms_header_from_po_header($header) {
+ if (preg_match("/(^|\n)plural-forms: ([^\n]*)\n/i", $header, $regs))
+ $expr = $regs[2];
+ else
+ $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
+ return $expr;
+ }
+
+ /**
+ * Get possible plural forms from MO header
+ *
+ * @access private
+ * @return string plural form header
+ */
+ function get_plural_forms() {
+ // lets assume message number 0 is header
+ // this is true, right?
+ $this->load_tables();
+
+ // cache header field for plural forms
+ if (! is_string($this->pluralheader)) {
+ if ($this->enable_cache) {
+ $header = $this->cache_translations[""];
+ } else {
+ $header = $this->get_translation_string(0);
+ }
+ $expr = $this->extract_plural_forms_header_from_po_header($header);
+ $this->pluralheader = $this->sanitize_plural_expression($expr);
+ }
+ return $this->pluralheader;
+ }
+
+ /**
+ * Detects which plural form to take
+ *
+ * @access private
+ * @param n count
+ * @return int array index of the right plural form
+ */
+ function select_string($n) {
+ $string = $this->get_plural_forms();
+ $string = str_replace('nplurals',"\$total",$string);
+ $string = str_replace("n",$n,$string);
+ $string = str_replace('plural',"\$plural",$string);
+
+ $total = 0;
+ $plural = 0;
+
+ eval("$string");
+ if ($plural >= $total) $plural = $total - 1;
+ return $plural;
+ }
+
+ /**
+ * Plural version of gettext
+ *
+ * @access public
+ * @param string single
+ * @param string plural
+ * @param string number
+ * @return translated plural form
+ */
+ function ngettext($single, $plural, $number) {
+ if ($this->short_circuit) {
+ if ($number != 1)
+ return $plural;
+ else
+ return $single;
+ }
+
+ // find out the appropriate form
+ $select = $this->select_string($number);
+
+ // this should contains all strings separated by NULLs
+ $key = $single.chr(0).$plural;
+
+
+ if ($this->enable_cache) {
+ if (! array_key_exists($key, $this->cache_translations)) {
+ return ($number != 1) ? $plural : $single;
+ } else {
+ $result = $this->cache_translations[$key];
+ $list = explode(chr(0), $result);
+ return $list[$select];
+ }
+ } else {
+ $num = $this->find_string($key);
+ if ($num == -1) {
+ return ($number != 1) ? $plural : $single;
+ } else {
+ $result = $this->get_translation_string($num);
+ $list = explode(chr(0), $result);
+ return $list[$select];
+ }
+ }
+ }
+
+}
+
+?>
diff --git a/include/php-gettext/streams.php b/include/php-gettext/streams.php
new file mode 100644
index 000000000..3cdc1584e
--- /dev/null
+++ b/include/php-gettext/streams.php
@@ -0,0 +1,167 @@
+<?php
+/*
+ Copyright (c) 2003, 2005, 2006, 2009 Danilo Segan <danilo@kvota.net>.
+
+ This file is part of PHP-gettext.
+
+ PHP-gettext 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.
+
+ PHP-gettext 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 PHP-gettext; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+
+ // Simple class to wrap file streams, string streams, etc.
+ // seek is essential, and it should be byte stream
+class StreamReader {
+ // should return a string [FIXME: perhaps return array of bytes?]
+ function read($bytes) {
+ return false;
+ }
+
+ // should return new position
+ function seekto($position) {
+ return false;
+ }
+
+ // returns current position
+ function currentpos() {
+ return false;
+ }
+
+ // returns length of entire stream (limit for seekto()s)
+ function length() {
+ return false;
+ }
+};
+
+class StringReader {
+ var $_pos;
+ var $_str;
+
+ function StringReader($str='') {
+ $this->_str = $str;
+ $this->_pos = 0;
+ }
+
+ function read($bytes) {
+ $data = substr($this->_str, $this->_pos, $bytes);
+ $this->_pos += $bytes;
+ if (strlen($this->_str)<$this->_pos)
+ $this->_pos = strlen($this->_str);
+
+ return $data;
+ }
+
+ function seekto($pos) {
+ $this->_pos = $pos;
+ if (strlen($this->_str)<$this->_pos)
+ $this->_pos = strlen($this->_str);
+ return $this->_pos;
+ }
+
+ function currentpos() {
+ return $this->_pos;
+ }
+
+ function length() {
+ return strlen($this->_str);
+ }
+
+};
+
+
+class FileReader {
+ var $_pos;
+ var $_fd;
+ var $_length;
+
+ function FileReader($filename) {
+ if (file_exists($filename)) {
+
+ $this->_length=filesize($filename);
+ $this->_pos = 0;
+ $this->_fd = fopen($filename,'rb');
+ if (!$this->_fd) {
+ $this->error = 3; // Cannot read file, probably permissions
+ return false;
+ }
+ } else {
+ $this->error = 2; // File doesn't exist
+ return false;
+ }
+ }
+
+ function read($bytes) {
+ if ($bytes) {
+ fseek($this->_fd, $this->_pos);
+
+ // PHP 5.1.1 does not read more than 8192 bytes in one fread()
+ // the discussions at PHP Bugs suggest it's the intended behaviour
+ $data = '';
+ while ($bytes > 0) {
+ $chunk = fread($this->_fd, $bytes);
+ $data .= $chunk;
+ $bytes -= strlen($chunk);
+ }
+ $this->_pos = ftell($this->_fd);
+
+ return $data;
+ } else return '';
+ }
+
+ function seekto($pos) {
+ fseek($this->_fd, $pos);
+ $this->_pos = ftell($this->_fd);
+ return $this->_pos;
+ }
+
+ function currentpos() {
+ return $this->_pos;
+ }
+
+ function length() {
+ return $this->_length;
+ }
+
+ function close() {
+ fclose($this->_fd);
+ }
+
+};
+
+// Preloads entire file in memory first, then creates a StringReader
+// over it (it assumes knowledge of StringReader internals)
+class CachedFileReader extends StringReader {
+ function CachedFileReader($filename) {
+ if (file_exists($filename)) {
+
+ $length=filesize($filename);
+ $fd = fopen($filename,'rb');
+
+ if (!$fd) {
+ $this->error = 3; // Cannot read file, probably permissions
+ return false;
+ }
+ $this->_str = fread($fd, $length);
+ fclose($fd);
+
+ } else {
+ $this->error = 2; // File doesn't exist
+ return false;
+ }
+ }
+};
+
+
+?>
diff --git a/include/picture_comment.inc.php b/include/picture_comment.inc.php
index fd4b907bc..35f686453 100644
--- a/include/picture_comment.inc.php
+++ b/include/picture_comment.inc.php
@@ -58,13 +58,13 @@ if ( $page['show_comments'] and isset( $_POST['content'] ) )
switch ($comment_action)
{
case 'moderate':
- array_push( $infos, l10n('comment_to_validate') );
+ array_push( $infos, l10n('An administrator must authorize your comment before it is visible.') );
case 'validate':
- array_push( $infos, l10n('comment_added'));
+ array_push( $infos, l10n('Your comment has been registered'));
break;
case 'reject':
set_status_header(403);
- array_push($infos, l10n('comment_not_added') );
+ array_push($infos, l10n('Your comment has NOT been registered because it did not pass the validation rules') );
break;
default:
trigger_error('Invalid comment action '.$comment_action, E_USER_WARNING);
diff --git a/include/section_init.inc.php b/include/section_init.inc.php
index 2abe2e63b..f0c78357e 100644
--- a/include/section_init.inc.php
+++ b/include/section_init.inc.php
@@ -237,7 +237,7 @@ if ('categories' == $page['section'])
}
else
{
- $page['title'] = l10n('no_category');
+ $page['title'] = l10n('Home');
}
if
@@ -361,7 +361,7 @@ SELECT DISTINCT image_id'.get_extra_fields($conf['order_by']).'
array(
'items' => $search_result['items'],
'title' => '<a href="'.duplicate_index_url(array('start'=>0)).'">'
- .l10n('search_result').'</a>',
+ .l10n('Search results').'</a>',
)
);
}
@@ -375,7 +375,7 @@ SELECT DISTINCT image_id'.get_extra_fields($conf['order_by']).'
$page = array_merge(
$page,
array(
- 'title' => l10n('favorites')
+ 'title' => l10n('Favorites')
)
);
@@ -456,7 +456,7 @@ SELECT DISTINCT(id)'.get_extra_fields($conf['order_by']).'
$page,
array(
'title' => '<a href="'.duplicate_index_url(array('start'=>0)).'">'
- .l10n('recent_pics_cat').'</a>',
+ .l10n('Recent pictures').'</a>',
'items' => array_from_query($query, 'id'),
)
);
@@ -469,7 +469,7 @@ SELECT DISTINCT(id)'.get_extra_fields($conf['order_by']).'
$page = array_merge(
$page,
array(
- 'title' => l10n('recent_cats_cat'),
+ 'title' => l10n('Recent categories'),
)
);
}
@@ -494,7 +494,7 @@ SELECT DISTINCT(id), hit, file
$page,
array(
'title' => '<a href="'.duplicate_index_url(array('start'=>0)).'">'
- .$conf['top_number'].' '.l10n('most_visited_cat').'</a>',
+ .$conf['top_number'].' '.l10n('Most visited').'</a>',
'items' => array_from_query($query, 'id'),
)
);
@@ -520,7 +520,7 @@ SELECT DISTINCT(id), average_rate
$page,
array(
'title' => '<a href="'.duplicate_index_url(array('start'=>0)).'">'
- .$conf['top_number'].' '.l10n('best_rated_cat').'</a>',
+ .$conf['top_number'].' '.l10n('Best rated').'</a>',
'items' => array_from_query($query, 'id'),
)
);
@@ -543,7 +543,7 @@ SELECT DISTINCT(id)'.get_extra_fields($conf['order_by']).'
$page,
array(
'title' => '<a href="'.duplicate_index_url(array('start'=>0)).'">'
- .l10n('random_cat').'</a>',
+ .l10n('Random pictures').'</a>',
'items' => array_from_query($query, 'id'),
)
);
diff --git a/include/ws_functions.inc.php b/include/ws_functions.inc.php
index 8116a50b6..f97fcca35 100644
--- a/include/ws_functions.inc.php
+++ b/include/ws_functions.inc.php
@@ -562,7 +562,7 @@ SELECT DISTINCT image_id
switch ($comment_action)
{
case 'reject':
- array_push($infos, l10n('comment_not_added') );
+ array_push($infos, l10n('Your comment has NOT been registered because it did not pass the validation rules') );
return new PwgError(403, implode("\n", $infos) );
case 'validate':
case 'moderate':