通过会话多语言,两个目录

Posted

技术标签:

【中文标题】通过会话多语言,两个目录【英文标题】:multiple language via session, two directories 【发布时间】:2018-09-20 05:50:34 【问题描述】:

所以我刚开始在我的新工作中进行 web 开发,这意味着我只有非常基本的 php 知识,我的 html、css 和 js 知识要好得多。 我正在尝试通过 php 会话构建一个基本的多语言站点,但我无法让它按照我想要的方式工作。 我有一个 index.php 文件和另外两个名为 EN 和 DE 的文件夹,其中有 Englisch.html 和 Deutsch.html 文件。 html 文件只包含一些文本,我的目标是在我的网站顶部有两个按钮(或类似按钮),称为 EN 和 DE,它们切换会话以将文件包含在所述文件夹中并显示按钮下方的文本并保留如果每种语言有一个以上的文件,则每个页面上的语言切换功能。默认情况下,我希望语言为英语,因此首先加载Englisch.html。 我猜我需要在每个检查会话的html文件上创建一个if else语句,例如:如果会话EN包含Englisch.html elseif会话DE包含Deutsch.html,并且在index.php上我需要设置会话的参数类似于: startSession EN 包括 Englisch.html startSession DE 包括 Deutsch.html 吗? 我不知道我离我有多远,任何帮助,尤其是实际的代码示例将不胜感激。我希望这足以准确地描述我的问题。

【问题讨论】:

天哪,我怎么看书!到目前为止你尝试了什么? 请避开文字墙。话虽如此,您的问题有点宽泛,基本上要求提供有关如何实现国际化的教程,因此很可能会被关闭。 ***.com/help/how-to-ask 该死的,我无法粘贴我上次尝试的代码,太长了,但我可以发布我使用的网站 @joko “各种各样的事情”不是一个有用的限定词。具体说明您尝试了什么、您的痛点是什么以及您的预期行为是什么,最好是通过一个代码示例来展示您的确切问题。 【参考方案1】:

我同意 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()。它非常简单,只接受一个翻译键。前任。 applicationNamegreeting

首先,它尝试确定使用哪种语言。它按优先级顺序执行此操作: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');

【讨论】:

感谢您的回答!有趣的是,由于大学的一些广告,我在看到这篇文章之前就开始以类似的方式做这件事,这非常有帮助!我希望可能有一个更简单的解决方案,尽管我不必重写几乎每个文件并且有一个额外的语言文件副本,我可以在其中定义所选语言会话的数组。如果可以只包含指向所选会话所需文件路径的链接,似乎会容易得多。哦,好吧,至少如果我们想对文件进行更改,我们不必为每个语言文件做两次.再次感谢! 我刚刚意识到实际上可能有一种方法可以做到这一点,但是如果我们想更改网站的逻辑和功能,因为必须做两次,这会带来更多的困难,所以它肯定会让如您所说,将逻辑文件和文本文件分开更有意义。【参考方案2】:

从长远来看,你尝试的解决方案会咬你一口。

在不同语言的不同文件之间切换似乎是一个简单的解决方案,但假设您的网站变得更加动态,而不是您想要处理 *.php 文件的 *.html 文件,然后需要有每个本地化文件中的逻辑相同。它不能很好地扩展。

我推荐使用翻译库,有很多可用的,我使用symfony's translation 取得了很好的成功,您也可以将其包含在任何 php 项目中。

那么翻译就变成了:

$translatedString = $translator->trans("My content");

然后可以在 yaml 文件中维护翻译,并根据语言环境选择正确的语言,每个未翻译的字符串将默认为英语。

而现在,每当你的逻辑发生变化时,它就在你需要调整的地方。

【讨论】:

感谢您的回答!我现在以非常相似的方式做到了。

以上是关于通过会话多语言,两个目录的主要内容,如果未能解决你的问题,请参考以下文章

Codeigniter:如何使用数据库和用户会话数据构建多语言网站?

做一个友好的多语言网站

google多语言通信框架gRPC

App多语言实现

算法461. 汉明距离(多语言实现)

QML程序实现动态切换多语言(ListModel/ListElement中的文本的多语言处理)