Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
498 views
in Technique[技术] by (71.8m points)

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

I am adding the localization feature to my website. I am creating that website from scratch, based on a template from: https://www.w3schools.com/Css/css_rwd_templates.asp

It is a simple template without localization. Instead I am going to have a website that manages localization, cookies, change of language, and so on.

I read this tutorial: https://www.toptal.com/php/build-multilingual-app-with-gettext and also https://blog.terresquall.com/2020/09/debugging-php-gettext/ and other pages.

Now I am using a Windows10 machine with WSL Ubuntu system. The localization code works, I tested the gettext functions in some place of the HTML page, all test locales being installed.

I am using the code from the tutorial with some editing:

<?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; 

?>

But I realized that the computed language from the browser can be in the form like "it","en","es" because it is allowed from the browser settings (along with more specific languages/locales like en_US), where the locales on the Ubuntu system instead have only complete language codes, like en_US.utf8.

I also have to add the .utf8 suffix because Ubuntu has those locales but this would work only for languages if they support UTF-8 of course. It's a further cause of possible untranslated string appearing.

I am planning to have key/values pairs instead of english untranslated strings as default.

If I put that value manually the translation happens, while if the $LANG is "en" or the browser sets the languageI get the untranslated strings. I tested it with some different browsers on the Windows10 system.

My idea is that simple languages are default, like "en", "es", "it" but these "general" languages seem to be not present as locales.

How to manage the locale from the browser so the code always works?

question from:https://stackoverflow.com/questions/65952567/gettext-php-locales-in-wsl-ubuntu-system-have-complete-codes-while-browser-h

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I think I just have to manage the languages and locales that are going to be supported on the website,

caring about handling the necessary strings, according to what locales identifiers are effectively available from the listing on the server.

Using some 'if' conditions is enough to create the correct strings, even for generic languages like en, es, it.

Just some string concatenation is needed.

Example: if I want to have generic english language support, I check the first two letters of the language variable.

If it starts with 'en' I choose en_GB.utf8

This is just the simplest case. More refined locale settings are possible.

Code sample:

    $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";
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...