<?php
/**
 * Internationalization code for DAVAdmin. Some ideas where taken from
 * Joomla CMS http://www.joomla.org/.
 *
 * @author Jan Dittberner <jan@dittberner.info>
 * @version $Id$
 * @license GPL
 * @package DAVAdmin
 *
 * Copyright (c) 2007 Jan Dittberner
 *
 * This file is part of DAVAdmin.
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */

/**
 * Gets the language data for supported languages.
 *
 * @return array associative array of language descriptions at index 0
 * and associative array of language to default country mappings at
 * index 1
 */
function get_language_data() {
  static $supportedLanguages = array();
  static $defaultCountry = array();

  if (empty($supportedLanguages)) {
    /* English */
    $supportedLanguages['en']['US']['description'] = 'English (US)';
    $supportedLanguages['en']['GB']['description'] = 'English (UK)';
    $defaultCountry['en'] = 'US';

    /* German */
    $supportedLanguages['de']['DE']['description'] = 'Deutsch';
    $defaultCountry['de'] = 'DE';
  }

  return array($supportedLanguages, $defaultCountry);
}

/**
 * Sets the locale for the given LC_* constant in $category to $locale
 * or a matching replacement.
 *
 * @param int $category one of the LC_* constants that PHP's setlocale
 * function accepts
 * @param string $locale locale name with or without country
 * specification and with or without character set name
 * @return string|boolean the locale actually set or FALSE if no
 * locale could be set at all
 */
function _setlocale($category, $locale) {
  if (($ret = setlocale($category, $locale)) !== false) {
    return $ret;
  }
  /* Try just selecting the language */
  if (($i = strpos($locale, '_')) !== false
      && ($ret = setlocale($category, substr($locale, 0, $i))) !== false) {
    return $ret;
  } else if (($i = strpos($locale, '_')) === false) {
    list($languages, $defcountries) = get_language_data();
    $locale = $locale . "_" . $defcountries[$locale];
    if (($ret = setlocale($category, substr($locale, 0, $i))) !== false) {
      return $ret;
    }
  }
  /*
   * Try appending some character set names; some systems (like FreeBSD)
   * need this. Some require a format with hyphen (eg. Gentoo) and others
   * without (eg. FreeBSD).
   */
  foreach (array('UTF-8', 'UTF8', 'utf8',
                 'ISO8859-1', 'ISO8859-2', 'ISO8859-5', 'ISO8859-7',
                 'ISO8859-9', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-5',
                 'ISO-8859-7', 'ISO-8859-9', 'ISO-8859-15',
                 'EUC', 'Big5') as $charset) {
    if (($ret = setlocale($category, $locale . '.' . $charset)) !== false) {
      return $ret;
    }
  }
  return false;
}

/**
 * Gets a supported language code. If $fallback is true en_US is
 * returned as a last resort.
 *
 * @param string $code the language code which should be tested
 * @param boolean $fallback if set to true (default) always return a
 * valid language code
 * @return string|boolean language code with country specification or
 * false if $fallback is set to false and language code is not
 * supported
 */
function _get_supported_language_code($code, $fallback = true) {
  static $supportedLanguages;
  static $defaultCountry;
  if (!isset($supportedLanguages)) {
    list($supportedLanguages, $defaultCountry) = get_language_data();
  }

  list ($language, $country) = preg_split('/[-_]/', "${code}_");
  $country = strtoupper($country);
  if ((empty($country) || !isset($supportedLanguages[$language][$country]))
      && isset($defaultCountry[$language])) {
    /* Use default country if none specified or particular country not
     * supported */
    $country = $defaultCountry[$language];
  }
  if (isset($supportedLanguages[$language][$country])) {
    return "${language}_${country}";
  }

  if ($fallback) {
    return 'en_US';
  } else {
    return null;
  }
}

/**
 * Negotiate the locale based on the value of
 * $_SERVER['HTTP_ACCEPT_LANGUAGE'].
 *
 * @return string language code string or null
 */
function _http_negotiate_locale() {
  $accepted = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
  if (!empty($accepted)) {
    foreach(explode(",", $accepted) as $code) {
      $languageCode = _get_supported_language_code($code, false);
      if (isset($languageCode)) {
        return $languageCode;
      }
    }
  }
  return null;
}

// start the session
session_start();
$project = "davadmin";

// set the language based on a GET-Parameter.
if (isset($_GET["language"])) {
  $languageCode = _get_supported_language_code($_GET["language"], false);
  if (isset($languageCode)) {
    $_SESSION["language"] = $languageCode;
  }
}
// if the current session has a language use it, negotiate from
// HTTP-Header otherwise
if ($_SESSION["language"]) {
  $language = $_SESSION["language"];
} else {
  $language = _http_negotiate_locale();
  $_SESSION["language"] = $language;
}
putenv(sprintf("LANG=%s", $_SESSION["language"]));
putenv(sprintf("LANGUAGE=%s", $_SESSION["language"]));
$_SESSION["locale"] = _setlocale(LC_ALL, $_SESSION["language"]);
// bind text domain for normal code
bindtextdomain($project,
               realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR .
                        ".." . DIRECTORY_SEPARATOR . "po"));
// bind text domain for JavaScript code
bindtextdomain($project . "js",
               realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR .
                        ".." . DIRECTORY_SEPARATOR . "po"));
// set the default text domain to project name
textdomain($project);
?>