Symfony 6 中的翻译

huangapple go评论85阅读模式
英文:

Translation in Symfony 6

问题

摘要:多年不使用Symfony(最后版本为Symfony 2)后,我决定回到Symfony。我已安装了最新的维护版本Symfony 6.3。

我目前正在尝试解决现代框架中最基本的问题之一:翻译。

但无论我做什么,似乎都不起作用(意味着我在前端看不到翻译)。

以下是可能会对你有用的文件

config/packages/translation.yaml

framework:
    default_locale: en
    translator:
        default_path: '%kernel.project_dir%/translations'
        fallbacks:
            - en

translations/messages.fr.php

<?php

return [
    'Symfony is great' => "J'aime Symfony",
];

这部分看起来没问题,因为如果我提取翻译(fr;),则翻译会出现在导出日志中。所以我的问题真正出现在如何使这个翻译生效。

以下是我的主页(我仅用作语言选择器和测试语言切换过程)

<!DOCTYPE html>
<html>
	<head>
	    <meta charset="UTF-8">
	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	    <title>Language Selector</title>
	    <link rel="stylesheet" href="css/flag.css">
	</head>
	<body>
	    <div class="language-selector-top">
	    	<h1>Configuration</h1>
	    	Current Locale is : {{ app.request.locale }}
	    	Try to translate following {{ "Symfony is great"|trans }}
	    </div>
	    <div class="language-selector">
	        <div class="language-flag" data-lang="en_US">
	            <img src="images/usa.jpg" alt="USA Flag">
	            <div class="language-text">Configure my account in English !</div>
	        </div>
	        <div class="language-flag" data-lang="fr_FR">
	            <img src="images/french.png" alt="French Flag">
	            <div class="language-text">Configurer mon compte en Français !</div>
	        </div>
	        <div class="language-flag" data-lang="es_ES">
	            <img src="images/mexican.png" alt="Mexican Flag">
	            <div class="language-text">Configurar mi cuenta en Mexicano !</div>
	        </div>
	    </div>
	    <script src="js/flag.js"></script>
	</body>
</html>

单击国旗将触发一个预计会更改语言的ajax请求。

#[Route('/language/update')]
public function updateLanguage(Request $request):JsonResponse
{
    $previousLocale = $request->getLocale();
    $language = $request->get('language');

    // 根据选择的语言更新Symfony本地化
    //$this->localeSwitcher->setLocale($language);
    $request->setLocale($language);

    return new JsonResponse(
        [
            'oldLocale' => $previousLocale,
            'newLocale' => $language
        ]
    );
}

结果是,ajax返回以下控制台日志

{"oldLocale":"en","newLocale":"fr_FR"}

问题是,当页面重新加载时,语言似乎仍然保持为"en",因为没有任何内容被翻译。

flag.addEventListener('click', () => {
    const selectedLanguage = flag.getAttribute('data-lang');

    // 发送一个用于更新Symfony本地化的AJAX请求
    const xhr = new XMLHttpRequest();
    xhr.open('POST', '/language/update', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onreadystatechange = function () {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200) {
                // 成功更新语言后重新加载页面
                console.log(xhr.responseText);
                window.location.href = '/';
            } else {
                console.error('Failed to update language.');
            }
        }
    };
    xhr.send('language=' + encodeURIComponent(selectedLanguage));
});

感谢您的协助。

英文:

Summary : I'm going back to symfony after years not using it (last version was symfony 2). I've then installed the newest maintained version Symfony 6.3.

I'm currently trying to handle one of the most basics problem is nowadays framework : translations.

But whatever I'm doing it doesn't seems to work (meaning i don't see the translation in frontend).

Here are the files that could interest you

config/packages/translation.yaml

framework:
    default_locale: en
    translator:
        default_path: &#39;%kernel.project_dir%\translations&#39;
        fallbacks:
            - en

translations/messages.fr.php

&lt;?php

return [
    &#39;Symfony is great&#39; =&gt; &quot;J&#39;aime Symfony&quot;,
];

That part seems file cause if I extract the translation fr; the translations appears in the export log. So my issue is really on the how to make this translation effective.

Here is my homepage (that i'm using only as a language chooser and to test the language switching process)

&lt;!DOCTYPE html&gt;
&lt;html&gt;
	&lt;head&gt;
	    &lt;meta charset=&quot;UTF-8&quot;&gt;
	    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
	    &lt;title&gt;Language Selector&lt;/title&gt;
	    &lt;link rel=&quot;stylesheet&quot; href=&quot;css/flag.css&quot;&gt;
	&lt;/head&gt;
	&lt;body&gt;
	    &lt;div class=&quot;language-selector-top&quot;&gt;
	    	&lt;h1&gt;Configuration&lt;/h1&gt;
	    	Current Locale is : {{ app.request.locale }}
	    	Try to translate following {{ &quot;Symfony is great&quot;|trans }}
	    &lt;/div&gt;
	    &lt;div class=&quot;language-selector&quot;&gt;
	        &lt;div class=&quot;language-flag&quot; data-lang=&quot;en_US&quot;&gt;
	            &lt;img src=&quot;images/usa.jpg&quot; alt=&quot;USA Flag&quot;&gt;
	            &lt;div class=&quot;language-text&quot;&gt;Configure my account in English !&lt;/div&gt;
	        &lt;/div&gt;
	        &lt;div class=&quot;language-flag&quot; data-lang=&quot;fr_FR&quot;&gt;
	            &lt;img src=&quot;images/french.png&quot; alt=&quot;French Flag&quot;&gt;
	            &lt;div class=&quot;language-text&quot;&gt;Configurer mon compte en Fran&#231;ais !&lt;/div&gt;
	        &lt;/div&gt;
	        &lt;div class=&quot;language-flag&quot; data-lang=&quot;es_ES&quot;&gt;
	            &lt;img src=&quot;images/mexican.png&quot; alt=&quot;Mexican Flag&quot;&gt;
	            &lt;div class=&quot;language-text&quot;&gt;Configurar mi cuenta en Mexicano !&lt;/div&gt;
	        &lt;/div&gt;
	    &lt;/div&gt;
	    &lt;script src=&quot;js/flag.js&quot;&gt;&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;

Clicking to a flag will trigger an ajax that is supposed to change the language

    #[Route(&#39;/language/update&#39;)]
    public function updateLanguage(Request $request):JsonResponse
    {
        $previousLocale = $request-&gt;getLocale();
        $language = $request-&gt;get(&#39;language&#39;);


        // Update the Symfony locale based on the selected language
        //$this-&gt;localeSwitcher-&gt;setLocale($language);
        $request-&gt;setLocale($language);

        return new JsonResponse(
            [
                &#39;oldLocale&#39; =&gt; $previousLocale,
                &#39;newLocale&#39; =&gt; $language
            ]
        );
    }

As a result the ajax return me the following console log

> {"oldLocale":"en","newLocale":"fr_FR"}

The issue is that when the page is reloading the language seems to keep being "en" as nothing is translated at all.

     flag.addEventListener(&#39;click&#39;, () =&gt; {
        const selectedLanguage = flag.getAttribute(&#39;data-lang&#39;);

        // Send an AJAX request to update the Symfony locale
        const xhr = new XMLHttpRequest();
        xhr.open(&#39;POST&#39;, &#39;/language/update&#39;, true);
        xhr.setRequestHeader(&#39;Content-Type&#39;, &#39;application/x-www-form-urlencoded&#39;);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    // Reload the page after successful language update
                    console.log(xhr.responseText);
                    window.location.href = &#39;/&#39;;
                } else {
                    console.error(&#39;Failed to update language.&#39;);
                }
            }
        };
        xhr.send(&#39;language=&#39; + encodeURIComponent(selectedLanguage));
    });

Thanks for your assistance in the process.

答案1

得分: 0

imo,你需要将选定的区域设置存储在会话中,然后使用监听器(kernel.event_listener)来为每个请求从会话中设置区域设置。

请注意:Symfony本身具有LocaleListener(优先级为16,如果我记得正确的话),因此您的监听器必须具有更高的优先级。

示例:

#[Route('/language/update')]
public function updateLanguage(Request $request): JsonResponse
{
    $previousLocale = $request->getLocale();
    $language = $request->get('language'); // 应将参数重命名为locale
    
    $request->setLocale($language);

    $request->getSession()->set('locale', $language);

    return new JsonResponse([
        'oldLocale' => $previousLocale,
        'newLocale' => $language
    ]);
}
namespace App\Listener;

class LocaleListener
{
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();
        // en_US: 如果不存在,回退到默认区域设置
        $request->setLocale($request->getSession()->get('locale', 'en_US'));
    }
}

在services.yaml中:

App\Listener\LocaleListener:
    tags:
        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 17 }

如果你不想自己处理区域设置,也有一个捆绑包可用 https://github.com/lunetics-org/LocaleBundle

英文:

imo, you have to store the selected locale in the session then use a listener (kernel.event_listener) to set the locale from the session for each request

notice that: symfony itself has the LocaleListener (priority 16 iirc), so your listener has to have higher priority.

Example:

#[Route(&#39;/language/update&#39;)]
public function updateLanguage(Request $request):JsonResponse
{
    $previousLocale = $request-&gt;getLocale();
    $language = $request-&gt;get(&#39;language&#39;); // should rename the param to locale
     
    $request-&gt;setLocale($language);

    $request-&gt;getSession()-&gt;set(&#39;locale&#39;, $language);

    return new JsonResponse([
        &#39;oldLocale&#39; =&gt; $previousLocale,
        &#39;newLocale&#39; =&gt; $language
    ]);
}
namespace App\Listener;

class LocaleListener
{
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event-&gt;getRequest();
        // en_US: fallback to the default locale if it&#39;s not existed
        $request-&gt;setLocale($request-&gt;getSession()-&gt;get(&#39;locale&#39;, &#39;en_US&#39;));
    }
}

in services.yaml

App\Listener\LocaleListener:
    tags:
        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 17 }

In case you don't want to handle the locale stuff by yourself, there's a bundle for it https://github.com/lunetics-org/LocaleBundle

huangapple
  • 本文由 发表于 2023年8月10日 09:52:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872178.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定