Gettext - PHP - WSL Ubuntu 系统中的语言环境具有完整的代码,而浏览器具有较短的代码

Gettext - PHP - Locales in WSL Ubuntu system have complete codes while browser has short ones

我正在向我的网站添加本地化功能。 我正在根据以下模板从头开始创建该网站: https://www.w3schools.com/Css/css_rwd_templates.asp

这是一个没有本地化的简单模板。 相反,我将拥有一个管理本地化、cookie、语言更改等的网站。

我读了这个教程: https://www.toptal.com/php/build-multilingual-app-with-gettext 并且 https://blog.terresquall.com/2020/09/debugging-php-gettext/ 和其他页面。

现在我正在使用带有 WSL Ubuntu 系统的 Windows10 机器。 本地化代码有效,我在 HTML 页面的某个地方测试了 gettext 函数,安装了所有测试语言环境。

我正在使用教程中的代码并进行一些编辑:

<?php
echo phpversion();
if ( false === function_exists('gettext') ) {
    echo "You do not have the gettext library installed with PHP.";
    exit(1);
} else {echo "OK gettext";}
/**
 * Verifies if the given $locale is supported in the project
 * @param string $locale
 * @return bool
 */
function valid($locale) {
    return in_array($locale, ['en_US', 'en', 'pt_BR', 'it','es']);
}

//setting the source/default locale, for informational purposes

if (isset($_GET['lang']) && valid($_GET['lang'])) {
    // the locale can be changed through the query-string
    printf('the locale can be changed through the query-string - ');
    $lang = $_GET['lang'];    //you should sanitize this!
    setcookie('lang', $lang); //it's stored in a cookie so it can be reused
} elseif (isset($_COOKIE['lang']) && valid($_COOKIE['lang'])) {
    // if the cookie is present instead, let's just keep it
    printf(' if the cookie is present instead, let\'s just keep it - ');
    $lang = $_COOKIE['lang']; //you should sanitize this!
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
    // default: look for the languages the browser says the user accepts
    printf('default: look for the languages the browser says the user accepts - ');
    $langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
    array_walk($langs, function (&$lang) { $lang = strtr(strtok($lang, ';'), ['-' => '_']); });
    foreach ($langs as $browser_lang) {
        printf('LANGUAGE ACCEPTED=');
        printf($browser_lang);
        if (valid($browser_lang)) {
            $lang = $browser_lang;
            break;
        }
    }
}

//manually coded for testing purposes
$lang ="en_US.utf8"; //this works, while not setting it I get two-char language code like "it"
// here we define the global system locale given the found language
putenv("LANG=$lang");
printf("LANG=".$lang);
// this might be useful for date functions (LC_TIME) or money formatting (LC_MONETARY), for instance
$currentLocale = setlocale(LC_ALL, $lang);

// this will make Gettext look for ../locales/<lang>/LC_MESSAGES/main.mo
bindtextdomain('main', './locales');

// indicates in what encoding the file should be read
bind_textdomain_codeset('main', 'UTF-8');

// if your application has additional domains, as cited before, you should bind them here as well
//bindtextdomain('forum', '../locales');
//bind_textdomain_codeset('forum', 'UTF-8');


//$currentLocale = setlocale(LC_ALL, 0);
echo $LANG
//echo "Current Locale=".$currentLocale; 

?>

但是 我意识到来自浏览器的计算语言可以采用“it”、“en”、“es”这样的形式,因为浏览器设置允许使用它(以及更具体的 languages/locales,如 en_US ), Ubuntu 系统上的语言环境只有完整的语言代码,例如 en_US.utf8.

我还必须添加 .utf8 后缀,因为 Ubuntu 有那些语言环境但是 这当然只适用于支持 UTF-8 的语言。这是可能出现未翻译字符串的进一步原因。

我计划使用 key/values 对而不是默认的英语未翻译字符串。

如果我手动输入该值,则会发生翻译,而如果 $LANG 为“en”或浏览器设置了语言,我会得到未翻译的字符串。我在 Windows10 系统上用一些不同的浏览器测试了它。

我的想法是简单的语言是默认的,比如“en”、“es”、“it”,但这些“通用”语言似乎不作为语言环境出现。

如何从浏览器管理语言环境以使代码始终有效?

我想我只需要管理网站将支持的语言和区域设置,

注意处理必要的字符串,根据服务器列表中有效可用的区域设置标识符。

使用一些 'if' 条件足以创建正确的字符串,即使对于像 en、es、it 这样的通用语言也是如此。

只需要一些字符串连接。

示例:如果我想要通用英语语言支持,我会检查语言变量的前两个字母。

如果以'en'开头我选择en_GB.utf8

这只是最简单的情况。可以进行更精细的区域设置。

代码示例:

    $lang_prefix=substr( $lang, 0, 2 );
    switch ($lang_prefix)
    {
    case 'en':  $lang="en_GB.utf8";break;
    case 'it':  $lang="it_IT.utf8";break;
    default:    $lang="en_GB.utf8";
    }