<?php
/**
*/

$g_app_root = realpath(dirname(__FILE__));
define('G_APP_ROOT', $g_app_root);
define('G_VHOST', $_SERVER['SERVER_NAME']);

// languages for home
// $langs = array() is now in /_nav/lib.php

// TODO (rda) define fallback languages for each language
// for instance, pt-br could fallback on pt and pt on pt-br (but without
// a cycle) then on es, etc.
$i18n_fallback_rules = array(
    'pt-br' => 'pt',
    'pt'    => 'pt-br'
);

$domains_lang = array(
    'mageia.fr' => 'fr',
    'mageia.it' => 'it',
    'mageia.ro' => 'ro',
);

require_once ('_nav/lib.php');

/**
 * Redirect to a localized path, depending on incoming TLD.
 * Only manages redirections to main home path.
 *
 * @param string  $tld
 * @param array   $domains_lang
 * @param string  $vhost
 *
 * @return void
*/
function tld_redirect($tld, $domains_lang, $vhost)
{
    domain_redirect('mageia.' . $tld, $domains_lang, $vhost);
}

/**
 * Redirect to a localized path, depending on incoming full domain.
 * Only manages redirections to main home path.
 *
 * @param string  $host
 * @param array   $domains_lang
 * @param string  $vhost
 *
 * @return void
*/
function domain_redirect($host, $domains_lang, $vhost)
{
    $host = str_replace('www.', '', $host);

    if (array_key_exists($host, $domains_lang)) {
        $path = $domains_lang[$host] . '/';
        header ('HTTP/1.1 301 Moved Permanently');
    } else {
        $path = '?langs';
    }
    header(sprintf('Location: %s://%s/%s', 'https', $vhost, $path));
    die;
}


/**
 * Redirect to a localized path, after browser Accept-Language prefs.
 * Return the path.
 * Do not exit the process.
 *
 * @param array $langs list of languages
 * @param string $page optional path to which we want to redirect
 * @param string $default_locale
 * @param string $force_accept_language replace remote browser HTTP_ACCEPT_LANGUAGE request header
 * @param boolean $do_redirect
 *
 * @return string
*/
function relocate($langs, $page = '', $default_locale = 'en', $force_accept_language = null, $do_redirect = true)
{
    require_once 'localeDetection.class.php';

    $locale = new ChooseLocale(array_keys($langs), $force_accept_language);
    $locale->setDefaultLocale($default_locale);

    $relocate = sprintf('/%s/%s', $locale->getCompatibleLocale(), $page);
    $relocate = str_replace('//', '/', $relocate);

    if ('cli' != PHP_SAPI && $do_redirect) {
        header('Location: ' . $relocate);
        die;
    }

    return $relocate;
}


/**
 * Create string pt_br from string pt-br and alike but leave the rest as is
 * Return string.
 * Do not exit the process.
 *
 * @param string $locale which we want to change
 * @param boolean $version_of_locale_uppercase optional, true if we want second part in uppercase (pt_BR)
 *
 * @return string
*/
function locale_hyphen_underscore($locale, $version_of_locale_uppercase = false)
{
    preg_match("/(..)(-)(..)/", $locale, $parsed_locale);
    if(isset($parsed_locale[3])) {
        return $parsed_locale[1] . '_' . ($version_of_locale_uppercase ? strtoupper($parsed_locale[3]) : $parsed_locale[3]);
    } else {
        return $locale;
    }
}


/**
 * Create string pt-br from string pt_br or pt_BR and alike but leave the rest as is
 * Return string.
 * Do not exit the process.
 *
 * @param string $locale which we want to change
 *
 * @return string
*/
function locale_underscore_to_hyphen($locale)
{
    preg_match("/(..)(_)(..)/", $locale, $parsed_locale);
    if(isset($parsed_locale[3])) {
        return $parsed_locale[1] . '-' . strtolower($parsed_locale[3]);
    } else {
        return $locale;
    }
}


/**
 * Returns sanitized specified $_GET variable by name if it exists and strip tags from it
 *
 * @param string name of a $_GET vaiable
 *
 * @return string sanitized string, empty on empty string or on error in filtering
*/
function get_sane_string($str){
    return (string) filter_input(INPUT_GET, $str, FILTER_SANITIZE_STRING);
}


/**
*/
function show_langs($langs)
{
    header('Content-Type: text/html; charset=utf-8');
    $count = count($langs);
    $s = <<<S
<!DOCTYPE html>
<html lang="en">
<head>
    <charset="utf-8">
    <meta name="robots" content="noindex,nosnippet">
    <title>Mageia</title>
</head>
<body>
<p><a href="/">Mageia.org</a> is currently available in {$count} languages:</p>
<ul>
S;
    foreach ($langs as $k => $v) {
        $s .= sprintf('<li><a href="/%s/" hreflang="%s">%s</a></li>',
            $k, $k, $v);
    }
    echo $s, '</ul><hr />',
        '<p>If you would like to help improving this Web site or its translations, ',
        'check out our <a href="/langs/report.php">translation report page</a> ',
        '<a href="https://wiki.mageia.org/en/Web_team">Web</a> and ',
        '<a href="https://wiki.mageia.org/en/Internationalisation_Team_(i18n)">localization</a> teams!</p>',
        '<p>Your browser Accept-Language is: ', $_SERVER['HTTP_ACCEPT_LANGUAGE'], '.</p>',
        '<hr /></body></html>';
}


/**
 * Class regrouping basic methods for i18n strings in their current forms.
 *
*/
class i18n
{
    /**
     * @param string $request_uri
     *
     * @return string
    */
    public static function get_language_from_url($request_uri)
    {
        $l = explode('/', $request_uri);
        return $l[1];
    }

    /**
     * Return language strings in $strings that match $lang,
     * and merge with pre-loaded strings matching $fallback_lang.
     *
     * @param array  $strings array('fr' => array(strings...), 'en' => array(...))
     * @param string $lang
     * @param string $fallback_lang
     *
     * @return array
    */
    public static function get_strings($strings, $lang, $fallback_rules = null)
    {
        $use_lang = self::get_fallback_language($lang, array_keys($strings), $fallback_rules);

        return array_merge($strings['en'], $strings[$use_lang]);
    }

    /**
     * Return a language we know we have support for, or a fallback language.
     *
     * Important note: this is supposed to be used only once in a row; do not
     * chain this method over itself as you may end up with an infinite loop
     * (depends on $fallback_rules contents).
     *
     * TODO (rda) implement this into an object, so we can check several langs
     * in a row for a same document, with several fallback hops, without a cycle.
     *
     * @param string $lang language we wish to use
     * @param array  $known_langs list of languages we support
     * @param mixed  $fallback_rules
     *
     * @return string
    */
    public static function get_fallback_language($lang, $known_langs, $fallback_rules = null)
    {
        $ret = 'en';

        if (in_array($lang, $known_langs)) {
            $ret = $lang;
        }
        else {
            if (is_string($fallback_rules)) {
                $ret = $fallback_rules;
            }
            elseif (is_array($fallback_rules)
                && array_key_exists($lang, $fallback_rules)) {

                $ret = $fallback_rules[$lang];
            }

            if (!in_array($ret, $known_langs))
                $ret = 'en';
        }

        return $ret;
    }

    /**
     * Get a translated string to output.
     *
     * Use it when you need to capture the string to output.
     *
     * Examples:
     *
     * echo _t("Hello."), _t("How are you?");
     *
     *
     * @param string $s     string to localize
     * @param array  $opt   translated strings list
     * @param string $post  string suffix. Useful to prevent non-breaking lines.
     *
     * @return null|string
    */
    public static function _t($s = null, $opt = null, $post = ' ')
    {
        return self::_d($s, $opt) . $post;
    }

    /**
     * Lookup for translated string for $s
     * in global array $_t (yes, ugly)
     * OR in $opt param.
     *
     * $_t or $opt is the list of string for the current locale.
     *
     * Use it when you need to get the exact, char-specific translation text.
     *
     * Examples:
     *
     * _d('http://mageia.org/en/');
     * _d('http://blog.mageia.org/en/feed');
     *
     * @param string $s
     * @param array $opt
     *
     * @return string
     *
     * FIXME Yes, it's terribly wrong/evil to rely on an unknown global $_t.
     * Solution? rethink the whole i18n thing in an integrated one.
    */
    public static function _d($s = null, $opt = null)
    {
        if ($s == '')
            return null;

        if (!is_null($opt)) {
            $_t = $opt;
        } else {
            global $_t;
        }

        $ret = array_key_exists($s, $_t) ? $_t[$s] : $s;

        return trim(str_replace(array('{ok}', '{OK}', '{Ok}', '{oK}'), '', $ret));
    }

    /**
     * Output a localized string $s, with optional $args.
     *
     * Use it when you need to just output a string.
     *
     * Examples:
     *
     * _e("Hello");
     * _e("Hello %d %d", array(1, 2));
     *
     * @param string $s
     * @param array  $args
     *
     * @return null
    */
    public static function _e($s = null, $args = null)
    {
        if (is_array($args))
            echo vsprintf(_t($s), $args);
        else
            echo self::_t($s);
    }

    /**
     * Output a localized string $s, sprintf'ed with $args, HTML-wrapped in $tag.
     *
     * Use it when you need to wrap your text is HTML, and this is faster.
     *
     * Examples:
     *
     * _h("Hello");
     * _h("Hello %s", array("Alice"));
     * _h("Title", null, "h1");
     *
     * @param string $s string to echo
     * @param array  $args optional params to $s
     * @param string $tag optional tag to wrap $s into
     *
     * @return null
    */
    public static function _h($s, $args = null, $tag = 'p')
    {
        $s = self::_t($s);
        $s = is_array($args) ? vsprintf($s, $args) : $s;

        $close_tag = explode(' ', $tag);
        $close_tag = array_shift($close_tag);

        echo sprintf('<%s>%s</%s>', $tag, $s, $close_tag);
    }

    /**
     * Get all locales from given file.
     *
     * @param string $file
     * @param string $return_duplicates optional switch
     *
     * @return array
    */
    public static function _lang_return($file, $return_duplicates = false)
    {
        $strings = array();

        if (file_exists($file)) {
            $f = file($file);

            foreach ($f as $k => $v) {

                $C = substr($v, 0, 1);
                if ($C === '#') continue;

                if ($C === ';' && !empty($f[$k+1])) {
                    $j = trim(substr($v, 1));
                    $j = str_replace(array("\'", "\""), array("'", '"'), $j);
                    if ($return_duplicates && !empty($strings[$j])) {
	                    $duplicates[] = $j;
                    }
                    $strings[$j] = trim($f[$k+1]);
                }
            }
            if (!empty($duplicates)) {
	            $strings['duplicates'] = $duplicates;
            }
        }

        return $strings;
    }

    /**
     * Load requested $locale, from $domain lang file, into global $_t array.
     *
     * @param string $locale
     * @param string $domain
     *
     * @return boolean
     *
     * @todo use i18n::get_fallback_language() or eq.
    */
    public static function _lang_load($locale, $domain)
    {
        if ($locale == 'en')
            return true;

        $lang_file = sprintf('%s/langs/%s/%s.%s.lang', G_APP_ROOT, $locale, $domain, $locale);

        if (file_exists($lang_file)) {

            global $_t;
            if (!isset($_t) || !is_array($_t))
                $_t = array();

            $_t = array_merge($_t, self::_lang_return($lang_file));

            return true;
        }

        return false;
    }

}

// shorthand helpers, to make legacy calls work.
function _t($s = null, $opt = null, $post = ' ') { return i18n::_t($s, $opt, $post); }
function _d($s = null, $opt = null)              { return i18n::_d($s, $opt); }
function _e($s = null, $args = null)             { return i18n::_e($s, $args); }
function _h($s = null, $args = null, $tag = 'p') { return i18n::_h($s, $args, $tag); }

function _lang_load($locale, $domain) { return i18n::_lang_load($locale, $domain); }

/**
 * Create dictionary from gettext file
 * Return array.
 * Do not exit the process.
 *
 * @param string $locale from which we want to create dictionary
 * @param mixed $name_of_translation string for one gettext filename or array for more
 *
 * @return array
*/
function read_translation_file($locale, $name_of_translation)
{
    if(is_array($name_of_translation)) {
        $dictionary = array();
        foreach($name_of_translation as $single_filename) {
            $dictionary = array_merge($dictionary, read_translation_file($locale, $single_filename));
        }
        return $dictionary;
    } else {
        if ($name_of_translation == '../_nav/langs/en') {
            $path_filename = '/_nav/langs/' . $locale . '.po';
        } else {
            $path_filename = '/langs/' . $locale . '/' . $name_of_translation . '.po';
        }
        if ($locale == 'en') {
            $path_filename .= 't';
        }
        $dictionary_from_file = phpmo_parse_po_file(G_APP_ROOT . $path_filename);
        if (is_array($dictionary_from_file)) {
			return $dictionary_from_file;
        } else {
			return array(); // in case of missing l10n file or it's parsing error
        }
    }
}

/**
 * Returns a translated string from global $dictionary
 * it can append space if needed
 *
 * Note that it trims {ok} for translations equal to original too.
 *
 * Use it when you need to capture the string to output.
 *
 * Examples:
 * echo _r("Hello!", ' ') . _r("How are you?")
 * which should return translated: Hello! How are you?
 *
 * @param string $string_for_translation which we want to translate
 * @param string $sufix append (usually space)
 *
 * @return string translated to current locale
*/
function _r($string_for_translation, $sufix = '')
{
    global $dictionary;
    $escapeded_string = str_replace(array('"'), array('\\"'), $string_for_translation);
    if(!empty($dictionary[$escapeded_string][0][0])) {
        $find    = array('\\"', '\n', '  ', '{ok}', '{OK}', '{Ok}', '{oK}');
        $replace = array('"','<br>', ' ');
        $prepared_string = trim(str_replace($find, $replace, $dictionary[$escapeded_string][0][0]));
    }
    if(empty($prepared_string)) {
        $prepared_string = $string_for_translation;
    }
    if(!empty($sufix)) {
        $prepared_string .= $sufix;
    }
    return $prepared_string;
}

/**
 * Higher level function for _r() to echo a translated string from global $dictionary
 * used also to wrap the translation with HTML tags
 * it can also append space if needed
 *
 * Examples:
 *_g("How are you?")
 * will just echo translation
 *
 * _g('Download Mageia %d!', array(5), 'a href="" style="color: blue;"')
 * OR for only one member of array:
 * _g('Download Mageia %s!', 5, 'a href="" style="color: blue;"')
 * will both echo blue link
 *
 * _g("Hey there.", null, ' '); _g("How are you?")
 * will just echo translation: Hey there. How are you?
 *
 * Return boolean.
 * Do not exit the process.
 *
 * @param string $string_for_translation which we want to translate
 * @param array OR string  $args for vsprintf/sprintf
 * @param string $tag_or_space HTML tag or space to append
 *
 * @return null
*/
function _g($string_for_translation, $args = null, $tag_or_space = '')
{
    $translated_string = _r($string_for_translation);
    if(!is_null($args)) {
        if(is_array($args)) {
            $translated_string = vsprintf($translated_string, $args);
        } else {
            $translated_string = sprintf($translated_string, $args);
        }
    }
    if(!empty($tag_or_space) && $tag_or_space != ' ') {
        $tag_or_space_w_args = explode(' ', $tag_or_space);
        $close_tag  = array_shift($tag_or_space_w_args);
        echo sprintf('<%s>%s</%s>', $tag_or_space, $translated_string, $close_tag);
    } else {
        echo $translated_string . $tag_or_space;
    }
}