通过会话的多种语言,两个目录
multiple language via session, two directories
所以我刚开始在我的新工作上进行 Web 开发,这意味着我只有 php 的非常基础的知识,我的 html、css 和 js 知识要好得多。
我正在尝试通过 php 会话构建一个基本的多语言网站,但我无法让它按我想要的方式工作。
我有一个 index.php 文件和另外两个名为 EN 和 DE 的文件夹,其中有 Englisch.html 和 Deutsch.html 文件。 html 文件只包含一些文本,我的目标是在我的站点顶部有两个按钮(或类似按钮),分别称为 EN 和 DE,它们可以切换会话以包含所述文件夹中的文件并显示文本下方如果每种语言有多个文件,按钮并在每一页上保留语言切换功能。默认情况下,我希望语言为英语,因此首先加载 Englisch.html。
我猜想我需要在每个 html 文件上创建一个 if else 语句来检查会话,例如:if session EN include Englisch.html elseif session DE include Deutsch.html,以及index.php 我不知何故需要为会话设置参数,例如:startSession EN include Englisch.html startSession DE include Deutsch.html ?
我不知道我离我有多远以及任何帮助,特别是实际的代码示例将不胜感激。我希望这足以准确描述我的问题。
您尝试的解决方案将在长期 运行 中给您带来麻烦。
在不同语言的不同文件之间切换似乎是一个简单的解决方案,但假设您的网站变得更加动态,而不是您想要处理的 *.html 文件 *.php 文件,然后需要在每个本地化文件中具有相同的逻辑。它不能很好地扩展。
我推荐使用翻译库,有很多可用的,我在 symfony's translation 上取得了很好的成功,您也可以将其包含在任何 php 项目中。
然后翻译成:
$translatedString = $translator->trans("My content");
然后可以在 yaml 文件中维护翻译,并根据语言环境选择正确的语言,每个未翻译的字符串将默认为英语。
现在,只要您的逻辑发生变化,您就需要在一个地方进行调整。
我同意 K0pernikus 的观点,因为您的解决方案无法很好地扩展。您可以在一个小时内自己编写一个简单的翻译库,然后您可以对其进行测试,看看它是否足够健壮,可以满足您的需求。
想法是让语言文件中没有任何逻辑。您只需调用您需要的文件。关于语言、文件、翻译密钥等的所有逻辑都包含在您的库中。
我会将其简化为一个文件;当然,实际的翻译也都需要存储在一个文件中。
目录结构:
- /locale/en/messages.php
- /locale/fr/messages.php
- translator.php(这是主库文件,每页都需要包含)
在每个 messages.php
文件中,您需要 return 一组 翻译键 及其各自的翻译。翻译键是您将在视图中使用的键。对于较大的应用程序,这些文件将变得很大,包含数百或数千行。如果您打算保留此 home-grown 解决方案,则需要实施缓存。也就是说,我有包含数百个翻译的文件,并且没有发现任何重大的性能影响。
<?php
// en
return array(
'applicationName' => 'Matt\'s Marvelous Mysteries',
...
<?php
// fr
return array(
'applicationName' => 'Les merveilleux mystères de Matt',
...
接下来,您需要一个图书馆来阅读这些翻译和 return 实际的翻译文本给您。该文件可以只是辅助函数的集合或 full-blown OOP 系统。
为简单起见,这里是完成工作的一组辅助方法。它没有实现参数化替换,您可以通过使 t()
接受第二个参数来相对轻松地添加该功能,但这是另一个完全不同的主题。
这里的主要方法是t()
。它非常简单,接受一个 翻译密钥 。前任。 applicationName
或 greeting
。
首先,它会尝试确定要使用的语言。它按优先级顺序执行此操作:URL、会话、浏览器、回退。
- 它首先尝试通过查找从 URL 中获取 language/locale
名为
lang
的查询字符串参数。如果您考虑一下,这是有道理的,因为用户打算通过单击
link 即 "English" 或 "French".
- 如果在 URL 中没有找到,它会继续检查一个
在会话中。同样,如果它在那里找到它,它就会使用它。
- 如果它既没有在 URL 中也没有在会话中找到它,那么它会检查
browser/headers 来自请求。
- 最后,如果在这 3 个位置中的任何一个都找不到它,那么它就会掉落
回到
$defaultLanguage
. 中指定的默认语言
一旦找到一种语言,它就会将其放入会话中,这样下一个请求就不需要再次经历所有这些。它还会根据发现的语言加载适当的 messages.php
文件。
最后,一旦找到语言并将正确的文件加载到内存中,它就会搜索给定的 $key
和 returns 适当的翻译。如果未找到 $key
,那么它只是 returns 给定的 $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');
所以我刚开始在我的新工作上进行 Web 开发,这意味着我只有 php 的非常基础的知识,我的 html、css 和 js 知识要好得多。 我正在尝试通过 php 会话构建一个基本的多语言网站,但我无法让它按我想要的方式工作。 我有一个 index.php 文件和另外两个名为 EN 和 DE 的文件夹,其中有 Englisch.html 和 Deutsch.html 文件。 html 文件只包含一些文本,我的目标是在我的站点顶部有两个按钮(或类似按钮),分别称为 EN 和 DE,它们可以切换会话以包含所述文件夹中的文件并显示文本下方如果每种语言有多个文件,按钮并在每一页上保留语言切换功能。默认情况下,我希望语言为英语,因此首先加载 Englisch.html。 我猜想我需要在每个 html 文件上创建一个 if else 语句来检查会话,例如:if session EN include Englisch.html elseif session DE include Deutsch.html,以及index.php 我不知何故需要为会话设置参数,例如:startSession EN include Englisch.html startSession DE include Deutsch.html ? 我不知道我离我有多远以及任何帮助,特别是实际的代码示例将不胜感激。我希望这足以准确描述我的问题。
您尝试的解决方案将在长期 运行 中给您带来麻烦。
在不同语言的不同文件之间切换似乎是一个简单的解决方案,但假设您的网站变得更加动态,而不是您想要处理的 *.html 文件 *.php 文件,然后需要在每个本地化文件中具有相同的逻辑。它不能很好地扩展。
我推荐使用翻译库,有很多可用的,我在 symfony's translation 上取得了很好的成功,您也可以将其包含在任何 php 项目中。
然后翻译成:
$translatedString = $translator->trans("My content");
然后可以在 yaml 文件中维护翻译,并根据语言环境选择正确的语言,每个未翻译的字符串将默认为英语。
现在,只要您的逻辑发生变化,您就需要在一个地方进行调整。
我同意 K0pernikus 的观点,因为您的解决方案无法很好地扩展。您可以在一个小时内自己编写一个简单的翻译库,然后您可以对其进行测试,看看它是否足够健壮,可以满足您的需求。
想法是让语言文件中没有任何逻辑。您只需调用您需要的文件。关于语言、文件、翻译密钥等的所有逻辑都包含在您的库中。
我会将其简化为一个文件;当然,实际的翻译也都需要存储在一个文件中。
目录结构:
- /locale/en/messages.php
- /locale/fr/messages.php
- translator.php(这是主库文件,每页都需要包含)
在每个 messages.php
文件中,您需要 return 一组 翻译键 及其各自的翻译。翻译键是您将在视图中使用的键。对于较大的应用程序,这些文件将变得很大,包含数百或数千行。如果您打算保留此 home-grown 解决方案,则需要实施缓存。也就是说,我有包含数百个翻译的文件,并且没有发现任何重大的性能影响。
<?php
// en
return array(
'applicationName' => 'Matt\'s Marvelous Mysteries',
...
<?php
// fr
return array(
'applicationName' => 'Les merveilleux mystères de Matt',
...
接下来,您需要一个图书馆来阅读这些翻译和 return 实际的翻译文本给您。该文件可以只是辅助函数的集合或 full-blown OOP 系统。
为简单起见,这里是完成工作的一组辅助方法。它没有实现参数化替换,您可以通过使 t()
接受第二个参数来相对轻松地添加该功能,但这是另一个完全不同的主题。
这里的主要方法是t()
。它非常简单,接受一个 翻译密钥 。前任。 applicationName
或 greeting
。
首先,它会尝试确定要使用的语言。它按优先级顺序执行此操作:URL、会话、浏览器、回退。
- 它首先尝试通过查找从 URL 中获取 language/locale
名为
lang
的查询字符串参数。如果您考虑一下,这是有道理的,因为用户打算通过单击 link 即 "English" 或 "French". - 如果在 URL 中没有找到,它会继续检查一个 在会话中。同样,如果它在那里找到它,它就会使用它。
- 如果它既没有在 URL 中也没有在会话中找到它,那么它会检查 browser/headers 来自请求。
- 最后,如果在这 3 个位置中的任何一个都找不到它,那么它就会掉落
回到
$defaultLanguage
. 中指定的默认语言
一旦找到一种语言,它就会将其放入会话中,这样下一个请求就不需要再次经历所有这些。它还会根据发现的语言加载适当的 messages.php
文件。
最后,一旦找到语言并将正确的文件加载到内存中,它就会搜索给定的 $key
和 returns 适当的翻译。如果未找到 $key
,那么它只是 returns 给定的 $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');