我同意K0pernikus的观点,因为您的解决方案无法很好地扩展。您可以在不到一个小时的时间内自己编写一个简单的翻译库,然后对其进行测试,看看它是否能够满足您的需要。
想法是让语言文件中没有任何逻辑。您只需调用所需的文件。库中包含关于哪种语言、文件、翻译键等的所有逻辑。
我将保持它非常简单,并简化为一个文件;当然,实际的翻译也需要存储在一个文件中。
目录结构:
-
/语言环境/英语/消息。php
-
/语言环境/fr/消息。php
-
翻译php
(这是主库文件,需要包含在每页中)
在每个
messages.php
需要返回数组的文件
翻译键
以及他们各自的翻译。转换键是您将在视图中使用的键。对于更大的应用程序,这些文件将变得更大,有数百或数千行。如果您打算保留这个自主开发的解决方案,则需要实现缓存。尽管如此,我有数百个翻译的文件,没有注意到任何显著的性能下降。
<?php
// en
return array(
'applicationName' => 'Matt\'s Marvelous Mysteries',
...
<?php
// fr
return array(
'applicationName' => 'Les merveilleux mystères de Matt',
...
接下来,您需要一个库来阅读这些翻译并将实际的翻译文本返回给您。该文件可以是助手函数的集合,也可以是成熟的OOP系统。
为了简单起见,下面是一组帮助器方法,可以完成工作。它不实现参数化替换,您可以通过
t()
接受第二个论点,但这是另一次完全不同的话题。
这里的主要方法是
t()
。它非常简单,可以接受单个
翻译键
.例如。
applicationName
或
greeting
。
首先,它试图确定使用哪种语言。它按优先级顺序执行:URL、会话、浏览器、回退。
-
它首先尝试通过查找
名为的查询字符串参数
lang
。如果你仔细想想,这是有道理的,因为用户打算通过单击
链接显示“英语”或“法语”。
-
如果在URL中找不到,则继续检查
在会话中。同样,如果它在那里找到它,它就会使用它。
-
如果它在URL或会话中都没有找到它,那么它会检查
请求的浏览器/标题。
-
最后,如果在这三个位置中的任何一个都没有找到它,那么它就会掉下来
返回中指定的默认语言
$defaultLanguage
。
一旦找到一种语言,它就会将其放入会话中,这样下一个请求就不需要再次进行所有这些操作。它还加载适当的
消息。php
基于发现的语言的文件。
最后,一旦找到语言并将正确的文件加载到内存中,它就会搜索给定的
$key
并返回相应的翻译。如果
$键
未找到,则只返回给定的
$键
这将显示在您的视图中,因此您知道出现了严重错误,需要开始调试。
<?php
/**
* Performs the actual translation based on the given key. This is the method that is used
* in the actual views to translate a message.
*
* @param $key
* @return mixed
* @throws Exception
*/
function t($key)
{
$language = getLanguage();
$messages = require "{$_SERVER['DOCUMENT_ROOT']}/locale/{$language}/messages.php";
return (array_key_exists($key, $messages))
? $messages[$key]
: $key;
}
/**
* Returns the language as defined by either the URL, session, or browser setting.
* If a language could not be determined, or is not in a list of supported languages, the default
* language passed in to this method will be returned.
*
* @param string $defaultLanguage
* @return string
*/
function getLanguage($defaultLanguage = 'en')
{
$language = null;
if (isset($_GET['lang'])) {
$language = $_GET['lang'];
} elseif (isset($_SESSION['LANG'])) {
$language = $_SESSION['LANG'];
} else {
$language = getLanguageFromBrowser($defaultLanguage);
}
// If the language given to us is not in our list of supported languages, use the default language.
if (!isset($language) || !in_array($language, getSupportedLanguages())) {
$language = $defaultLanguage;
}
// Store the current language to the session for future use.
$_SESSION['LANG'] = $language;
return $language;
}
/**
* Returns the language that the client's browser is set to use. If we're unable to
* determine a language from the browser this will return the default language passed
* in.
*
* @param string $defaultLanguage
* @return int|string
*/
function getLanguageFromBrowser($defaultLanguage = 'en')
{
$languages = [];
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
// break up string into pieces (languages and q factors)
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
if (count($lang_parse[1])) {
// create a list like "en" => 0.8
$languages = array_combine($lang_parse[1], $lang_parse[4]);
// set default to 1 for any without q factor
foreach ($languages as $lang => $val) {
if ($val === '') $languages[$lang] = 1;
}
// sort list based on value
arsort($languages, SORT_NUMERIC);
}
}
$supportedLanguages = getSupportedLanguages();
foreach ($languages as $locale => $weighting) {
// We're dealing with locale: Ex. en-US
if (preg_match("/[a-z]{2}-[A-Z]{2}/", $locale)) {
$browserLanguage = substr($locale, 0, 2);
} else {
// Probably dealing with a language: Ex. en
$browserLanguage = $locale;
}
if (in_array($browserLanguage, $supportedLanguages)) {
return $browserLanguage;
}
}
return $defaultLanguage;
}
/**
* Returns an array of languages this web application supports.
*
* @return array
*/
function getSupportedLanguages()
{
return [
'en',
'fr'
];
}
要使用它,请将这些方法保存到名为
translator.php
然后将该文件包含在您要使用翻译的每个页面中。
示例:
<?php
session_start();
require_once('translator.php');
// Output your language switcheroo-gadget
if (getLanguage() === 'en') {
echo '<a href="' . $_SERVER['PHP_SELF'] . '?lang=fr">French</a>';
} else {
echo '<a href="' . $_SERVER['PHP_SELF'] . '?lang=en">English</a>';
}
// Your code... blah blah
// Ahh.. Finally, a translation!
echo '<h1>' . t('applicationName') . '</h1>';
编辑
我要说的最后一件事是,有一个关于本地化、国际化(通常缩写为i18n)的完整世界,您可以了解它。
在我的示例中,我简单地将其称为语言,但人们通常将其称为语言环境,但这具有不同的含义和语法。例如,en\u CA与en\u US和en\u GB之间存在差异;他们都是英语,但有地区差异。
echo t('salutation');