Так что я только начал веб-разработку на своей новой работе, то есть у меня есть только базовые знания php, мои знания html, css и js намного лучше.
Я пытаюсь создать базовый многоязычный сайт с помощью php-сессий, но я просто не могу заставить его работать так, как я хочу.
У меня есть файл index.php и еще две папки с именами EN и DE, в которых у меня есть файл Englisch.html и файл Deutsch.html. HTML-файлы содержат только некоторый текст, и моя цель состоит в том, чтобы в верхней части моего сайта были две кнопки (или аналогичные), называемые EN и DE, которые переключают сеанс для включения файлов в указанные папки и отображают текст под кнопками и сохраняют функция переключения языка на каждой странице, если у меня было более одного файла на язык. По умолчанию я хочу, чтобы язык был английским, поэтому сначала загрузите Englisch.html.
Я предполагаю, что мне нужно создать оператор if else для каждого html-файла, который проверяет сессию, примерно так: если сессия EN включает Englisch.html elseif сессия DE включает Deutsch.html, а в index.php мне как-то нужно установить параметры для сеанса примерно такие: startSession EN include Englisch.html startSession DE include Deutsch.html?
Я понятия не имею, как далеко я нахожусь, и любая помощь, особенно актуальные примеры кода, будет принята с благодарностью. Надеюсь, это достаточно точно описало мою проблему.
Я согласен с K0pernikus в том, что ваше решение не будет хорошо масштабироваться. Вы можете написать простую библиотеку переводов менее чем за час, а затем протестировать ее, чтобы убедиться, что она будет достаточно надежной для ваших нужд.
Идея состоит в том, чтобы иметь языковые файлы без какой-либо логики. Вы просто называете файл, который вам нужен. Вся логика о том, какой язык, файл, ключ перевода и т. Д. Содержится в вашей библиотеке.
Я сделаю это очень простым и простым файлом; Конечно, каждый реальный перевод должен быть тоже сохранен в файле.
Структура каталогов:
Внутри каждого messages.php
файл, который вам нужно вернуть массив ключи перевода и их соответствующий перевод. Ключи перевода — это то, что вы будете использовать в своих представлениях. Эти файлы станут большими с сотнями или тысячами строк для больших приложений. Если вы намерены сохранить это собственное решение, вам необходимо внедрить кэширование. При этом у меня есть файлы с сотнями переводов, и я не замечаю значительного снижения производительности.
<?php
// en
return array(
'applicationName' => 'My name is Dank',
...
<?php
// fr
return array(
'applicationName' => 'je m\'appelle Dank',
...
Затем вам нужна библиотека, чтобы прочитать эти переводы и вернуть вам текст перевода. Этот файл может быть просто набором вспомогательных функций или полноценным классом ООП. Для простоты, вот коллекция вспомогательных методов, которые выполняют свою работу. Он не реализует параметризованную замену, и вы можете относительно легко добавить эту функцию, сделав t()
принять второй аргумент, но это совсем другая тема для другого времени.
Основной метод здесь t()
, Это очень просто и принимает один ключ перевода. Ex. applicationName
или же greeting
,
Предостережение — я написал эту логику довольно поспешно в прошлом году и не извиняюсь, если она не работает для вас.
Во-первых, он пытается определить, какой язык использовать. Это происходит в последовательности приоритетов: URL, сеанс, браузер, резерв.
lang
, Если вы думаете об этом, то$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($_REQUEST['lang'])) {
$language = $_REQUEST['lang'];
} elseif (isset($_SESSION['LANG'])) {
$language = $_SESSION['LANG'];
} else {
$language = getLanguageFromBrowser('en');
}
// 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');
Ваша попытка решения в конечном итоге укусит вас.
Может показаться, что это простое решение для переключения между разными файлами для разных языков, но при этом предполагается, что ваш сайт становится более динамичным, вместо файлов * .html, которые вы хотите иметь дело с файлами * .php, и тогда вам понадобится та же логика внутри каждого из ваших локализованных файлов. Это не хорошо масштабируется.
Я рекомендую использовать переводную библиотеку, есть много доступных, у меня был хороший успех перевод Symfony, что вы также можете включить в любой проект PHP.
Тогда перевод становится:
$translatedString = $translator->trans("My content");
И тогда перевод можно сохранить в файлах yaml, и в зависимости от локали будет выбран правильный язык, и каждая непереведенная строка будет по умолчанию установлена на английский.
И теперь, когда ваша логика меняется, она находится в одном месте, где вам нужно ее адаптировать.