我同意 K0pernikus 的观点,即您的解决方案无法很好地扩展。您可以在不到一个小时的时间内自己编写一个简单的翻译库,然后您可以对其进行测试,看看它是否足以满足您的需求。
这个想法是让语言文件中没有任何逻辑。您只需调用所需的文件。关于哪种语言、文件、翻译键等的所有逻辑都包含在您的库中。
我会保持非常简单,只写一个文件;当然,实际的翻译也需要存储在一个文件中。
目录结构:
- /locale/en/messages.php
- /locale/fr/messages.php
-
translator.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、会话、浏览器、回退。
- 它首先尝试通过查找从 URL 获取语言/区域设置
一个名为
lang 的查询字符串参数。如果您考虑一下,这是有道理的,因为用户打算通过单击
显示“英语”或“法语”的链接。
- 如果在 URL 中没有找到一个,它会继续检查是否有一个
在会话中。同样,如果它在那里找到它,它就会使用它。
- 如果在 URL 和会话中都没有找到它,那么它会检查
来自请求的浏览器/标头。
- 最后,如果在这 3 个位置中的任何一个都找不到它,那么它会掉下来
返回到
$defaultLanguage 中指定的默认语言。
一旦找到一种语言,它就会将其放入会话中,这样下一个请求就不需要再经历所有这些了。它还会根据发现的语言加载适当的messages.php 文件。
最后,一旦找到语言并将正确的文件加载到内存中,它就会搜索给定的$key 并返回适当的翻译。如果找不到$key,那么它只会返回给定的$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_CA 与 en_US 和 en_GB 有区别;所有这些都是英语,但有地区差异。
echo t('salutation');