"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "mrbs-1.9.4/web/language.inc" between
mrbs-1.9.4.tar.gz and mrbs-1.10.0.tar.gz

About: MRBS is a web application for booking meeting rooms or other resources (using PHP and MySQL/pgsql).

language.inc  (mrbs-1.9.4):language.inc  (mrbs-1.10.0)
<?php <?php
namespace MRBS; namespace MRBS;
// Note that we are using \MRBS\Locale because \Locale has some bugs in it (and also // Note that we are using \MRBS\Locale because \Locale has some bugs in it (and also
// isn't always installed). // isn't always installed).
use IntlDateFormatter;
use PHPMailer\PHPMailer\PHPMailer;
require_once "functions.inc"; require_once "functions.inc";
// A map of browser locale aliases // A map of browser locale aliases
$lang_aliases = array $lang_aliases = array
( (
'no' => 'nb', // Not all operating systems will accept a locale of 'no ' 'no' => 'nb', // Not all operating systems will accept a locale of 'no '
'sh' => 'sr-latn-rs', 'sh' => 'sr-latn-rs',
); );
// Map non-standard language codes used by flatpickr onto BCP 47 language tags // Map non-standard language codes used by flatpickr onto BCP 47 language tags
skipping to change at line 163 skipping to change at line 166
// that best fits the config settings and the user's browser preferences. Then it // that best fits the config settings and the user's browser preferences. Then it
// finds a language that best fits the locale, subject to any overriding config settings. // finds a language that best fits the locale, subject to any overriding config settings.
// //
// Locales will also be needed for third party JavaScript libraries such as date pickers. // Locales will also be needed for third party JavaScript libraries such as date pickers.
// MRBS tries to find the best match for these depending on the localisations av ailable // MRBS tries to find the best match for these depending on the localisations av ailable
// for the library. This may sometimes mean that the locale for the library, e g the // for the library. This may sometimes mean that the locale for the library, e g the
// datepicker, is different from the main locale. But this is probably better than // datepicker, is different from the main locale. But this is probably better than
// trying to find a locale that is available on the server and has a translation available // trying to find a locale that is available on the server and has a translation available
// in MRBS and has localisations available in all the third party libraries. // in MRBS and has localisations available in all the third party libraries.
language_debug('HTTP_ACCEPT_LANGUAGE: ' . $server['HTTP_ACCEPT_LANGUAGE']); $http_accept_language = $server['HTTP_ACCEPT_LANGUAGE'] ?? '';
language_debug("HTTP_ACCEPT_LANGUAGE: $http_accept_language");
// Translate languages in the header string to their aliases // Translate languages in the header string to their aliases
if (isset($server['HTTP_ACCEPT_LANGUAGE'])) if (isset($server['HTTP_ACCEPT_LANGUAGE']))
{ {
$aliased_header = alias_header($server['HTTP_ACCEPT_LANGUAGE'], $lang_aliases) ; $aliased_header = alias_header($server['HTTP_ACCEPT_LANGUAGE'], $lang_aliases) ;
} }
else else
{ {
$aliased_header = null; $aliased_header = null;
} }
language_debug('$aliased_header: ' . $aliased_header); language_debug('$aliased_header: ' . $aliased_header);
skipping to change at line 298 skipping to change at line 303
$locale = Locale::acceptFromHttp($header); $locale = Locale::acceptFromHttp($header);
} }
// If there aren't any browser preferences, use English // If there aren't any browser preferences, use English
else else
{ {
$locale = 'en'; $locale = 'en';
} }
// Convert it to BCP 47 format (eg convert 'en_US' to 'en-US') // Convert it to BCP 47 format (eg convert 'en_US' to 'en-US')
$locale = convert_to_BCP47($locale); $locale = convert_to_BCP47($locale);
$have_locale = true;
} }
return $locale; return $locale;
} }
// Returns a simple array of BCP 47 language tags in decreasing order of prefere nce. This // Returns a simple array of BCP 47 language tags in decreasing order of prefere nce. This
// is designed for use with third party libraries (eg datepickers, datatables) w here the // is designed for use with third party libraries (eg datepickers, datatables) w here the
// locale used by MRBS, and given by get_mrbs_locale(), may not be available. S o this function // locale used by MRBS, and given by get_mrbs_locale(), may not be available. S o this function
// returns as wide a list of languages as possible, in the hope that one of them may be // returns as wide a list of languages as possible, in the hope that one of them may be
// supported by the third party library. // supported by the third party library.
skipping to change at line 395 skipping to change at line 401
$available_languages = get_langtags(MRBS_ROOT . '/lang', 'lang.'); $available_languages = get_langtags(MRBS_ROOT . '/lang', 'lang.');
$lang = Locale::lookup($available_languages, $locale, false, $default_lang uage_tokens); $lang = Locale::lookup($available_languages, $locale, false, $default_lang uage_tokens);
} }
} }
return $lang; return $lang;
} }
// Returns a version of the Accept-Language request HTTP header with language // Returns a version of the Accept-Language request HTTP header with language
// strings substituted for their aliases // strings substituted for their aliases
function alias_header($header, array $aliases) function alias_header(string $header, array $aliases) : string
{ {
if (!empty($aliases)) if (!empty($aliases))
{ {
$patterns = array(); $patterns = array();
$replacements = array(); $replacements = array();
foreach ($aliases as $key => $value) foreach ($aliases as $key => $value)
{ {
$patterns[] = "/(?<=^|,)($key)(?=,|;|$)/i"; $patterns[] = "/(?<=^|,)($key)(?=,|;|$)/i";
$replacements[] = $value; $replacements[] = $value;
skipping to change at line 418 skipping to change at line 424
$header = preg_replace($patterns, $replacements, $header); $header = preg_replace($patterns, $replacements, $header);
} }
return $header; return $header;
} }
// Returns a sorted associative array of acceptable language qualifiers, indexed // Returns a sorted associative array of acceptable language qualifiers, indexed
// by language, given an Accept-Language header string. // by language, given an Accept-Language header string.
// If $translate_wildcard is set then the wildcard language identifier ('*') is // If $translate_wildcard is set then the wildcard language identifier ('*') is
// translated to a standard language - we use 'en'. // translated to a standard language - we use 'en'.
function get_qualifiers($header, $translate_wildcard=false) function get_qualifiers(?string $header, bool $translate_wildcard=false) : array
{ {
$result = array(); $result = array();
if (!empty($header)) if (!empty($header))
{ {
$lang_specifiers = explode(',', $header); $lang_specifiers = explode(',', $header);
foreach ($lang_specifiers as $specifier) foreach ($lang_specifiers as $specifier)
{ {
unset($weight); unset($weight);
skipping to change at line 474 skipping to change at line 480
} }
arsort($result, SORT_NUMERIC); arsort($result, SORT_NUMERIC);
return $result; return $result;
} }
// Returns a string of acceptable languages, sorted in decreasing order of prefe rence // Returns a string of acceptable languages, sorted in decreasing order of prefe rence
// If $translate_wildcard is set then the wildcard language identifier ('*') is // If $translate_wildcard is set then the wildcard language identifier ('*') is
// translated to a standard language - we use 'en'. // translated to a standard language - we use 'en'.
function get_browser_langs($header, $translate_wildcard=false) function get_browser_langs(?string $header, bool $translate_wildcard=false) : ar ray
{ {
return array_keys(get_qualifiers($header, $translate_wildcard)); return array_keys(get_qualifiers($header, $translate_wildcard));
} }
// Gets all the language tags in a directory where the filenames are of the form at // Gets all the language tags in a directory where the filenames are of the form at
// $prefix . $lang . $suffix. Returns an array. // $prefix . $lang . $suffix. Returns an array.
function get_langtags($dir, $prefix='', $suffix='') function get_langtags($dir, $prefix='', $suffix='')
{ {
$result = array(); $result = array();
skipping to change at line 715 skipping to change at line 721
} }
} }
function get_charset() function get_charset()
{ {
return 'utf-8'; return 'utf-8';
} }
function get_mail_charset() function get_mail_charset()
{ {
return 'utf-8'; return PHPMailer::CHARSET_UTF8;
} }
function get_csv_charset() function get_csv_charset()
{ {
global $csv_charset; global $csv_charset;
if (empty($csv_charset)) if (empty($csv_charset))
{ {
return get_charset(); return get_charset();
} }
else else
skipping to change at line 761 skipping to change at line 767
break; break;
} }
} }
// Get a vocab item, in UTF-8 // Get a vocab item, in UTF-8
// Takes additional parameters as for sprintf() // Takes additional parameters as for sprintf()
// //
// [Maybe in the future we should switch to using the MessageFormatter // [Maybe in the future we should switch to using the MessageFormatter
// class as it is more powerful. However the Intl extension isn't present // class as it is more powerful. However the Intl extension isn't present
// in all PHP installations and so the class would have to be emulated] // in all PHP installations and so the class would have to be emulated]
function get_vocab($tag) function get_vocab(string $tag) : string
{ {
global $vocab; global $vocab;
// Return the tag itself if we can't find a vocab string // Return the tag itself if we can't find a vocab string
if (!isset($vocab[$tag])) if (!isset($vocab[$tag]))
{ {
return $tag; return $tag;
} }
$args = func_get_args(); $args = func_get_args();
$args[0] = $vocab[$tag]; $args[0] = $vocab[$tag];
return call_user_func_array('sprintf', $args); return call_user_func_array('sprintf', $args);
} }
// Same as get_vocab(), but uses the mailing language // Same as get_vocab(), but uses the mailing language
function get_mail_vocab($tag) function get_mail_vocab(string $tag) : string
{ {
global $vocab, $mail_settings; global $vocab, $mail_settings;
static $mail_vocab = null; static $mail_vocab = null;
if (!isset($mail_vocab)) if (!isset($mail_vocab))
{ {
$web_vocab = $vocab; // Save $vocab before it gets overwritten $web_vocab = $vocab; // Save $vocab before it gets overwritten
set_vocab($mail_settings['admin_lang']); set_vocab($mail_settings['admin_lang']);
$mail_vocab = $vocab; $mail_vocab = $vocab;
skipping to change at line 806 skipping to change at line 812
} }
$args = func_get_args(); $args = func_get_args();
$args[0] = $mail_vocab[$tag]; $args[0] = $mail_vocab[$tag];
$result = call_user_func_array('sprintf', $args); $result = call_user_func_array('sprintf', $args);
return str_replace('&nbsp;', ' ', $result); return str_replace('&nbsp;', ' ', $result);
} }
// Get localised booking type name // Get localised booking type name
function get_type_vocab($type) function get_type_vocab(string $type) : string
{ {
return get_vocab("type.$type"); return get_vocab("type.$type");
} }
// Get localized field name for a user defined table column // Get localized field name for a user defined table column
// Looks for a tag of the format tablename.columnname (where tablename is // Looks for a tag of the format tablename.columnname (where tablename is
// stripped of the table prefix) and if can't find a string for that tag will // stripped of the table prefix) and if can't find a string for that tag will
// return the column name // return the column name
function get_loc_field_name($table, $name) function get_loc_field_name(string $table, string $name) : string
{ {
global $vocab; global $vocab;
// Get the qualified prefix $tag = get_table_short_name($table) . ".$name";
$full_prefix = _tbl('');
// Strip the prefix, if any, off the table name
if (utf8_strpos($table, $full_prefix) === 0)
{
$tag = utf8_substr($table, utf8_strlen($full_prefix));
}
else
{
$tag = $table;
}
// Add on the field name
$tag .= "." . $name;
// Then if there's a string in the vocab array for $tag use that, // If there's a string in the vocab array for $tag use that,
// otherwise just use the fieldname // otherwise just use the fieldname
return (isset($vocab[$tag])) ? get_vocab($tag) : $name; return (isset($vocab[$tag])) ? get_vocab($tag) : $name;
} }
// optionally switch to a new locale, switching back at the end. // Format a local time/date according to locale settings, returning the
// $temp_locale can either be a string or an array of locales. // result as a UTF-8 string. This function is based on strftime()
function utf8_strftime($format, $time, $temp_locale=null) // $time can be an int or a float (union type declarations not supported until P
{ HP 8.0)
// $locale can either be a string or an array of locales. If $locale
// is not set then the current locale is used.
function date_formatter_strftime(string $format, $time, $locale)
{
// Cast $time to an integer because we're going to use it in strftime() and da
te(), both
// of which expect integers and will otherwise throw an E_DEPRECATED error in
PHP 8.1
$time = (int) $time;
$server_os = System::getServerOS(); $server_os = System::getServerOS();
// Set the temporary locale. Note that $temp_locale could be an array of loca les, // Set the temporary locale. Note that $temp_locale could be an array of loca les,
// so we need to find out which locale actually worked. // so we need to find out which locale actually worked.
if (!empty($temp_locale)) if (!empty($locale))
{ {
$old_locale = setlocale(LC_TIME, '0'); $old_locale = setlocale(LC_TIME, '0');
$new_locale = setlocale(LC_TIME, $temp_locale); $new_locale = setlocale(LC_TIME, $locale);
} }
elseif ($server_os == "windows") elseif ($server_os == "windows")
{ {
// If we are running Windows we have to set the locale again in case another script // If we are running Windows we have to set the locale again in case another script
// running in the same process has changed the locale since we first set it. See the // running in the same process has changed the locale since we first set it. See the
// warning on the PHP manual page for setlocale(): // warning on the PHP manual page for setlocale():
// //
// "The locale information is maintained per process, not per thread. If you are // "The locale information is maintained per process, not per thread. If you are
// running PHP on a multithreaded server API like IIS or Apache on Windows, you may // running PHP on a multithreaded server API like IIS or Apache on Windows, you may
// experience sudden changes in locale settings while a script is running, t hough // experience sudden changes in locale settings while a script is running, t hough
skipping to change at line 896 skipping to change at line 897
$ampm = date('a', $time); $ampm = date('a', $time);
} }
$format = preg_replace('/%p/', $ampm, $format); $format = preg_replace('/%p/', $ampm, $format);
} }
$result = strftime($format, $time); $result = strftime($format, $time);
$result = System::utf8ConvertFromLocale($result, $new_locale); $result = System::utf8ConvertFromLocale($result, $new_locale);
// Restore the original locale // Restore the original locale
if (!empty($temp_locale)) if (!empty($locale))
{ {
setlocale(LC_TIME, $old_locale); setlocale(LC_TIME, $old_locale);
} }
return $result; return $result;
} }
// Converts a single strftime() format character into an equivalent
// pattern for use with IntlDateFormatter.
// See https://www.php.net/manual/en/function.strftime.php and
// https://unicode-org.github.io/icu/userguide/format_parse/datetime/
function get_equivalent_pattern(string $format, string $locale) : string
{
$map = array(
// Day
'a' => 'ccc',
'A' => 'cccc',
'd' => 'dd',
'e' => 'd',
'j' => 'D', // not an exact equivalent: 'j' has leading zeros
// 'u' not supported
// 'w' not supported
// Week
// 'U' not supported
// 'V' not supported
// 'W' not supported
// Month
'b' => 'LLL',
'B' => 'LLLL',
'h' => 'LLL',
'm' => 'LL',
// Year
// 'C' not supported
// 'g' not supported
// 'G' not supported
'y' => 'yy',
'Y' => 'y',
// Time
'H' => 'HH',
'k' => 'H',
'I' => 'hh',
// 'l' not supported
'M' => 'mm',
'p' => 'a', // not an exact equivalent
'P' => 'a', // not an exact equivalent
'r' => 'hh:mm:ss a',
'R' => 'HH:mm',
'S' => 'ss',
'T' => 'HH:mm:ss',
// 'X' see below
'z' => 'Z',
'Z' => 'z',
// Time and Date Stamps
// 'c' see below
'D' => 'LL/dd/yy',
'F' => 'y-LL-dd'
// 's' not supported
// 'x' see below
);
// The simple case - there's a near equivalent
if (isset($map[$format]))
{
return $map[$format];
}
// More complicated cases - the pattern is locale dependent
switch ($format)
{
case 'X':
$date_type = IntlDateFormatter::NONE;
$time_type = IntlDateFormatter::MEDIUM;
break;
case 'c':
$date_type = IntlDateFormatter::MEDIUM;
$time_type = IntlDateFormatter::LONG;
break;
case 'x':
$date_type = IntlDateFormatter::SHORT;
$time_type = IntlDateFormatter::NONE;
break;
default:
throw new \Exception("Cannot convert format '%$format'");
break;
}
$formatter = new IntlDateFormatter(
$locale,
$date_type,
$time_type
);
return $formatter->getPattern();
}
// Convert a strftime() format, which can contain a mixture of formatters and te
xt,
// into an IntlDateFormatter pattern
function format_convert(string $format, string $locale) : string
{
// Trivial case
if (!isset($format) || ($format === ''))
{
return $format;
}
// Split the string, which may contain multibyte characters, into an array and
// then iterate through the array
$chars = preg_split('//u', $format, -1, PREG_SPLIT_NO_EMPTY);
$char = current($chars);
$text = '';
$result = '';
do
{
if ($char == '%')
{
if (false === ($next_char = next($chars)))
{
trigger_error("Badly formed format '$format'", E_USER_NOTICE);
}
elseif (in_array($next_char, array('n', 't', '%')))
{
// Escaped characters
switch ($next_char)
{
case 'n':
$text_char = "\n";
break;
case 't':
$text_char = "\t";
break;
case '%':
$text_char = '%';
break;
}
$text .= $text_char;
}
else
{
// It's a format character
// If there's a text string outstanding then append that to the result
if ($text !== '')
{
// Don't need to escape characters outside ['a'..'z'] and ['A'..'Z'] b
ut it's simpler to do so
$result .= "'$text'";
$text = '';
}
// Followed by the ICU equivalent of the format character
$result .= get_equivalent_pattern($next_char, $locale);
}
}
else
{
$text .= ($char == "'") ? "''" : $char; // Escape single quotes
}
} while (false !== ($char = next($chars)));
// Add any remaining text
if ($text !== '')
{
// Don't need to escape characters outside ['a'..'z'] and ['A'..'Z'] but it'
s simpler to do so
$result .= "'$text'";
}
return $result;
}
// Format a local time/date according to locale settings, returning the
// result as a UTF-8 string. This function is based on IntlDateFormatter.
// $time can be an int or a float (union type declarations not supported until P
HP 8.0)
// $locale can either be a string or an array of locales, but if an array
// then only the first is used.
// If $locale is not set then the current locale is used.
function date_formatter_intl(string $format, $time, $locale=null) : string
{
if (!isset($locale))
{
$locale = get_mrbs_locale();
}
if (is_array($locale))
{
$locale = $locale[0];
}
$pattern = format_convert($format, $locale);
$formatter = new IntlDateFormatter(
$locale,
IntlDateFormatter::FULL,
IntlDateFormatter::FULL,
null,
null,
$pattern
);
return $formatter->format($time);
}
// Format a local time/date according to locale settings, returning the
// result as a UTF-8 string.
// $time can be an int or a float (union type declarations not supported until P
HP 8.0)
// $locale can either be a string or an array of locales. If $locale
// is not set then the current locale is used.
function utf8_strftime(string $format, $time, $locale=null) : string
{
// strftime() is deprecated from PHP 8.1, so we use IntlDateFormatter
// if we can.
// TODO: This solution just translates strftime formats into the nearest
// TODO: equivalent IntlDateFormatter patterns. However it would be better
// TODO: to rewrite MRBS so that IntlDateFormatter patterns are used if
// TODO: as they are more flexible and better suited to reflecting locales.
if (class_exists('IntlDateFormatter'))
{
return date_formatter_intl($format, $time, $locale);
}
else
{
return date_formatter_strftime($format, $time, $locale);
}
}
// UTF-8 compatible substr function obtained from a contribution by // UTF-8 compatible substr function obtained from a contribution by
// "frank at jkelloggs dot dk" in the PHP online manual for substr() // "frank at jkelloggs dot dk" in the PHP online manual for substr()
function utf8_substr_old($str, $start, $length=null) function utf8_substr_old($str, $start, $length=null)
{ {
preg_match_all("/./su", $str, $ar); preg_match_all("/./su", $str, $ar);
return join("", array_slice($ar[0], $start, $length)); return join("", array_slice($ar[0], $start, $length));
} }
// UTF-8 compatible substr function // UTF-8 compatible substr function
function utf8_substr($str, $start, $length=null) function utf8_substr(string $str, int $start, ?int $length=null)
{ {
if (!isset($length)) if (!isset($length))
{ {
// We cannot set $length to PHP_INT_MAX because there is a bug (#42101) // We cannot set $length to PHP_INT_MAX because there is a bug (#42101)
// in mb_substr() when using PHP_INT_MAX on 64 bit Linux systems. See // in mb_substr() when using PHP_INT_MAX on 64 bit Linux systems. See
// https://bugs.php.net/bug.php?id=42101. Note also that passing NULL // https://bugs.php.net/bug.php?id=42101. Note also that passing NULL
// for the length in mb_substr() causes mb_substr to use a length of 0. // for the length in mb_substr() causes mb_substr to use a length of 0.
// See the user contributed notes on the PHP mb_substr() manual page. // See the user contributed notes on the PHP mb_substr() manual page.
$length = utf8_strlen($str); $length = utf8_strlen($str);
} }
 End of changes. 19 change blocks. 
31 lines changed or deleted 260 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)