PHP (SQL) 中的网站语言翻译

Posted

技术标签:

【中文标题】PHP (SQL) 中的网站语言翻译【英文标题】:Website language translation in PHP (SQL) 【发布时间】:2020-07-09 11:42:21 【问题描述】:

我想在我的网站中实现语言翻译。为此在我的数据库中创建了一个表“翻译”:

id | de    | en    | other languages    
1  | Hallo | Hello | ...

基于此,我在标题中添加了以下查询:

 if ($user['language'] == 'de') 
        // Select prepared PDO 
        $statement = $pdo->prepare("SELECT id, de FROM translations");
        $result = $statement->execute(array());
        $text = $statement->fetch();
    

if .... other languages

我想根据用户语言显示文本翻译。我想知道我现在是否可以使用一个简单的 php echo 方法。如上所述,我在表格中有可用的翻译,但最简单的方法是呼应它吗?

例如。当前状态:

<h4 class="...">Hallo</h4>

带有翻译的新状态(当然它不起作用):

<h4 class="..."><?php echo $text['en'] ?></h4>

所以我缺少的是一种简单的方法来将 id(行)寻址到该文本输出,在该示例中为“1”。

作为一种可能的方法,我找到了这个例子:

<?php
$age=array("Peter"=>"35");
echo "Peter is " . $age['Peter'] . " years old.";
?>

我认为我可以使用它,并且从文本大小来看它看起来很有效。但我不确定如何修改上面表格的查询。最好是我可以做一些类似的事情:

echo $text['1']

它会显示文本输出:“Hallo”。以防万一:

echo $text['2']

它将显示“Hello”。

你觉得这个方法怎么样?您能帮我修改我的查询以使此方法正常工作吗?

非常感谢!

【问题讨论】:

【参考方案1】:

根据您在我的第一个答案下的问题,我决定添加另一个解决方案 - 没有功能等更容易。

使用 fetchAll 在单个查询中获取所有翻译:

$statement = $pdo->prepare("SELECT id, de, en FROM translations");
$result = $statement->execute();
$textsRaw = $statement->fetchAll();

您的$textsRaw 将如下所示:

$textsRaw = [ 
  ['id' => 1, 'de' => 'Hallo', 'en' => 'Hello'],
  ['id' => 2, 'de' => 'auf Wiederschauen', 'en' => 'Good bye'],
];

现在我们将$textsRaw 转换为结构更简单的$texts

$texts = [];
foreach ($textsRaw as $text) 
  $texts[$text['id']] = $text[$user['language']];

现在$texts 看起来像这样:

$texts = [1 => 'Hello', '2' => 'Good bye'];

如果你有这个,那么翻译就这么简单:

echo $texts[1];
echo $texts[2];

如果您访问不存在的翻译 id,您将收到正常的 php 通知:PHP Notice: Undefined offset: 3 in ....php on line ...

【讨论】:

太棒了!这运行良好,但功能不符合我的要求!我很欣赏这个答案:) 非常感谢!在之前的文章中,您建议不要使用 ID 作为指示符,以便稍后在源代码中获得更好的概览。我同意你的看法。以后或多或少真的很难找到一些东西,或者我需要评论每个文本回声。我想我会实施某种关键字以获得更好的概述。我现在可以自己使用您的代码示例来做到这一点!再次感谢! 虽然这可行,但请注意:这是一种缓慢且资源密集的方式,难以长期维护。只要您使用它,这将在实施和维护方面很慢:) @Martijn 不是。请考虑此线程中的其他信息。它在解决方案的简单性和效率之间进行权衡。这也取决于页面上有多少翻译。在 1 个查询中获取 300 个翻译,而每个请求为每个翻译获取 50 个查询?我仍然建议获取所有内容并将其缓存到文件/redis 或其他任何内容(如果它开始成为问题),但这超出了问题的范围。请注意,作者希望避免使用函数。还有“这实施起来会很慢”——你能详细说明一下吗? 当然。现在是 300 个翻译,但如果您的网站增长到 1000 或 2000 个怎么办?一些额外的页面可能会这样做。或者,如果您现在存储每种语言的页面内容,而不是一些小的翻译,该怎么办?将所有内容推入数组不是一个好计划,而且是一种浪费,因为您现在在内存中拥有所有语言而不是 1。这也总是加载 all 翻译,即使您说只需要联系页面。另外,循环遍历所有数据?那会让一切变得更糟:) 老实说,IMO 不想使用函数并不是一个原因。然后学习这些,函数是您可以学习的最基本的东西之一。甚至有人认为比数据库技能更重要【参考方案2】:

我曾经这样解决过,我不想选择所有数据,因为我认为那会浪费资源。我想出的解决方案是(IMO)非常优雅:

有一个变量表示其中的语言,例如$language = 'NL'。然后,在选择中使用:

SELECT description_$language as description FROM example

如果您获取它,您可以简单地以您想要的语言使用$result['description'] :)

这需要您的查询最少的努力。您可以使用['title', 'description'] 作为输入创建一个函数,该函数以查询中的格式返回它,这样可以使您的查询更小:

function langCols($columns)
    $lang = 'NL'; // implement your language logic here
    $transColumns = array_map(function(string $column)
        return $column .'_'.$lang.' AS '.$column;
    , $columns);
    
    return implode(', ', $transColumns);

请注意,这是我的情况的解决方案,但只需最少的努力,它就应该满足您的需求

【讨论】:

感谢您查看此内容。我将使用 Blahy 的解决方案,因为这没有“功能”并且在我的技能水平上我认为如果更喜欢功能,也可以使用您的解决方案。确实,完整的获取可能会导致高资源假设,但在我的情况下,我说的是最大。 300 行。如果我的服务器反应时间因此而显示一些不好的结果,我将检查函数方法。 不用函数也可以,用查询就行了。 另外,如果您认为有用,请随时投票 :)【参考方案3】:

使用 fetchAll 在单个查询中获取所有翻译:

$statement = $pdo->prepare("SELECT id, de, en FROM translations");
$result = $statement->execute();
$texts = $statement->fetchAll();

您的$texts 将如下所示:

$texts = [ 
  ['id' => 1, 'de' => 'Hallo', 'en' => 'Hello'],
  ['id' => 2, 'de' => 'auf Wiederschauen', 'en' => 'Good bye'],
];

现在你不能用简单的 echo 构造来做到这一点,但你可以像这样定义函数:

function t(int $key): string 
  global $texts;
  global $user;

  $translationTexts = array_filter($texts, function(array $text) use ($key, $user)  return $text['id'] === $key; );

  if (count($translationTexts) !== 1) 
    throw new Exception('Unknown text key: '.$key);
  

  return reset($translationTexts)[$user['language']];

现在,无论您想翻译哪里,都可以:echo t(1);echo t(2); 并根据用户语言输出翻译,例如:

$user = ['language' => 'en'];

echo t(1);
echo t(2);

$user = ['language' => 'de'];

echo t(1);
echo t(2);

然后输出:

Hello
Good bye
Hallo
auf Wiederschauen

如果你使用一些不存在的翻译 id,比如t(3);,你会得到例外:PHP Fatal error: Uncaught Exception: Unknown text key: 3

最好有翻译服务/类,但我认为这个简单的版本更适合初学者。

您还可以考虑使用其中一种语言作为翻译键(甚至引入新列作为翻译键),这样它就更具描述性:echo t('hello') - 这比echo t(1) 在源代码中更容易跟踪.

【讨论】:

谢谢你!我尝试运行代码,但出现错误:Fatal error: Uncaught Exception: Unknown text key: 50 in C:\xampp\htdocs\Auditmanager\2.php:99 Stack trace: #0 C:\xampp\htdocs\Auditmanager\2.php(105): t(50) #1 main thrown in C:\xampp\htdocs\Auditmanager\2.php on line 99 查询正在运行。我已经检查了 print_r。看起来 tehre 是该功能的问题。老实说,我对解决该问题的功能知之甚少。您是否发现了一些错误或需要更多信息?顺便说一句:id 50 在表中可用。 函数中有时会从文本切换到文本正常吗? @MischaMilivojeBakic 也许你有 2 行 id 为 50?看起来你要么没有 id 50 的行(翻译),要么你有多个 @MischaMilivojeBakic 看看我的新答案——也许对你来说会更清楚。如果翻译 id 50 的问题仍然存在 - 发布 $texts 的内容

以上是关于PHP (SQL) 中的网站语言翻译的主要内容,如果未能解决你的问题,请参考以下文章

小议网站本地化中的正则表达式

PHP防注入

PHP网站中的安全策略:SQL注入、XSS攻击和二阶SQL注入

谈谈PHP网站的防SQL注入

网站翻译[关闭]

在网页加载时将网站翻译成任何特定语言