Локалізаціязастосунку
Локалізаціязастосунку
Symfony,Завдякиміжнароднійаудитob娱乐下载оріїякніколираніше,можеоброблятиінтернаціоналізацію(i18n)ілокалізацію(l10n)зкоробки。Локалізаціязастосунку——ценетількиперекладінтерфейсу,алеймножини,форматуваннядатийвалюти,URL-адрестощо。
ІнтернаціоналізаціяURL-адрес
Першимкрокомдоінтернаціоналізаціївеб-сайтуєінтернаціоналізаціяURL-адрес。Приперекладіінтерфейсувеб-сайтуURL-адресамаєвідрізнятисязалежновідлокалі,щобладнатизкешамиHTTP(ніколиневикористовуйтетусамуURL-адресуйнезберігайтелокальусесії)。
Використовуйтеспеціальнийпараметрмаршруту_locale
,щобпосилатисяналокальумаршрутах:
1 2 3 4 5 6 7 8 9 10 11
- - - / src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -28 7 + 28 7 @@类ConferenceController扩展AbstractController) {}- #[路线(“/”,名字:“主页”))+ #[路线(“/ {_locale} /”,名字:“主页”))公共函数指数(ConferenceRepository ConferenceRepository美元):响应{返回$ this - >渲染(会议/ index . html。嫩枝”,(
НаголовнійсторінцілокальтепервстановлюєтьсязсерединизалежновідURL-адреси;наприклад,якщовиперейдетедо/ fr /
- - - - - -$请求- > getLocale ()
повертаєfr
。
Оскількиви、ймовірнонезможетеперекластивмістувсіхдопустимихлокалях,обмежтесятими,яківихочетепідтримувати:
1 2 3 4 5 6 7 8 9 10 11
- - - / src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -28 7 + 28 7 @@类ConferenceController扩展AbstractController) {}- #[路线(“/ {_locale} /”,名字:“主页”))+ #[路线(' / {_locale < en | fr >} / ',名字:“主页”))公共函数指数(ConferenceRepository ConferenceRepository美元):响应{返回$ this - >渲染(会议/ index . html。嫩枝”,(
Коженпараметрмаршрутуможебутиобмеженийрегулярнимвиразомвсередині<
>
。Маршрут主页
зараззбігаєтьсятількитоді,колипараметром_locale
є在
чиfr
。Спробуйтеперейтидо/ es /
404年,вимаєтеотриматиоскількижоденмаршрутнезбігається。
Оскількимибудемовикористовуватитусамувимогумайжеувсіхмаршрутах,перемістімоїївпараметрконтейнера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- - - / config / services.yaml+ + + b / config / services.yaml@@ 9 6 + 9 7 @@参数:admin_email:“% env(字符串:默认值:default_admin_email: admin_email) %”default_base_url: router.request_context“http://127.0.0.1”。base_url:“% env(默认值:default_base_url: SYMob娱乐下载FONY_DEFAULT_ROUTE_URL) % '+ app.supported_locales:“en | fr”服务:#在* *文件默认配置服务- - - / src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -28 7 + 28 7 @@类ConferenceController扩展AbstractController) {}- #[路线(' / {_locale < en | fr >} / ',名字:“主页”))+ #【路线(' / {_locale < %应用。supported_locales % >} /”,名字:“主页”)公共函数指数(ConferenceRepository ConferenceRepository美元):响应{返回$ this - >渲染(会议/ index . html。嫩枝”,(
Додаваннямовиможназдійснитишляхомоновленняпараметруapp.supported_languages
。
ДодайтетойсамийпрефіксмаршрутулокалідоіншихURL-адрес:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
- - - / src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -36 7 + 36 7 @@类ConferenceController延伸AbstractController]) - > setSharedMaxAge (3600);}- #[路线(“/ conference_header”,名字:“conference_header”))+ #【路线(' / {_locale < %应用。supported_locales % >} / conference_header”,名字:“conference_header”)公共函数conferenceHeader (ConferenceRepository ConferenceRepository美元):响应{返回$ this - >渲染(会议/ header.html。嫩枝”,[@@ -44 7 + 44 7 @@类ConferenceController延伸AbstractController]) - > setSharedMaxAge (3600);}- #[路线(“/会议/{蛞蝓}”,名字:“会议”))+ #【路线(' / {_locale < %应用。supported_locales % >} /会议/{蛞蝓}”,名字:“会议”)公共函数显示(请求请求美元,美元会议,会议
Мивжемайжезавершили。Унасбільшенемаємаршруту,якийзбігаєтьсяз/
。Додаймойогоназадізробімоперенаправленняна/ en /
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- - - / src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -28年6 + 28日12 @@类ConferenceController扩展AbstractController) {}+ #(路线(“/”))+公共职能indexNoLocale():反应+ {+ $ this - > redirectToRoute返回(“主页”,(“_locale”= >“en”));+}+#(路线(' / {_locale < %应用。supported_locales % >} /”,名字:“主页”)]公共函数指数(ConferenceRepository ConferenceRepository美元):反应{
Тепер,коливсіосновнімаршрутивраховуютьособливостілокалі,звернітьувагу,щоствореніURL-адресинасторінкахавтоматичновраховуютьпоточнулокаль。
Додаванняперемикачалокалі
Щобдозволитикористувачамперемикатисязлокалізазамовчуванням在
наіншу,додаймоперемикачушапку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
- - - /模板/ base.html.twig+ + + b /模板/ base.html.twig6 + 34 @@ -34年,16 @@李管理< / > < / >+ <李类= " nav-item拉" >+ < class = " nav-link dropdown-toggle " href = " # " id =“dropdown-language”角色=“按钮”+ data-bs-toggle =“下拉”aria-haspopup = " true " aria-expanded =“false”>+英语+ < / >+ < ul类= "下拉菜单dropdown-menu-right”aria-labelledby = " dropdown-language " >+ <李> < class = " dropdown-item " href = "{{路径(“主页”,{_locale:“en”})}} " > < / > < /李>英语+ <李> < class = " dropdown-item " href = "{{路径(“主页”,{_locale:“fr”})}} " > < / > < /李>法语+ < / ul >李+ < / >< / ul > < / div > < / div >
Дляперемиканнянаіншулокальмиявнопередаємопараметрмаршруту_locale
уфункцію路径()
。
Оновітьшаблон,щобвідобразитиім'япоточноїлокалізамістьжорсткозакодованого“英语”:
1 2 3 4 5 6 7 8 9 10 11
- - - /模板/ base.html.twig+ + + b /模板/ base.html.twig@@ -37年,37岁的7 + 7 @@<李class = " nav-item拉" > < class = " nav-link dropdown-toggle " href = " # " id =“dropdown-language”角色=“按钮”data-bs-toggle =“下拉”aria-haspopup = " true " aria-expanded =“false”>- - - - - -英语+ {{app.request.locale | locale_name (app.request.locale)}}< / > < ul类= "下拉菜单dropdown-menu-right”aria-labelledby = " dropdown-language " > <李> < class = " dropdown-item " href = "{{路径(“主页”,{_locale:“en”})}} " > < / > < /李>英语
应用程序
——цеглобальназмінна树枝,якадаєдоступдопоточногозапиту。Щобперетворитилокальучитабельнийрядок,мивикористовуємофільтр树枝locale_name
。
Залежновідлокалі,ім'ялокалінезавждипишетьсязвеликоїлітери。Щобналежнимчиномпрописуватифрази,нампотрібенфільтр,якийвраховуєUnicode,якцепередбаченокомпонентомSymfony字符串ійогоob娱乐下载реалізацією枝:
1
美元ob娱乐下载symfony作曲家点播树枝/ string-extra
1 2 3 4 5 6 7 8 9 10 11
- - - /模板/ base.html.twig+ + + b /模板/ base.html.twig@@ -37年,37岁的7 + 7 @@<李class = " nav-item拉" > < class = " nav-link dropdown-toggle " href = " # " id =“dropdown-language”角色=“按钮”data-bs-toggle =“下拉”aria-haspopup = " true " aria-expanded =“false”>- {{app.request.locale | locale_name (app.request.locale)}}+ {{app.request.locale | locale_name (app.request.locale) | u。标题}}< / > < ul类= "下拉菜单dropdown-menu-right”aria-labelledby = " dropdown-language " > <李> < class = " dropdown-item " href = "{{路径(“主页”,{_locale:“en”})}} " > < / > < /李>英语
Тепервиможетеперемикатисязфранцузькоїнаанглійськузадопомогоюперемикачаівесьінтерфейсдоситьдобреадаптується:
Перекладінтерфейсу
Перекладкожноїокремоїфразинавеликомувеб-сайтіможебутивиснажливим,але,нащастя,нанашомувеб-сайтієтількикількаповідомлень。Почнімозусіхфразнаголовнійсторінці:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31
- - - /模板/ base.html.twig+ + + b /模板/ base.html.twig7 @@ @@ -20年7 + 20日<导航类= "导航navbar-expand-xl navbar-light bg-light”> < div class = "容器mt-4 mb-3”> < class = " navbar-brand我pr-2 " href = "{{路径(主页)}}" >- & # 128217;会议留言板+ & # 128217;{{“会议留言板”|反式}}< / > <按钮类= " navbar-toggler border-0 " type = "按钮" data-bs-toggle =“崩溃”data-bs-target = " # header-menu " aria-controls =“navbarSupportedContent aria-expanded”=“false”aria-label = "显示/隐藏导航" >- - - /模板/会议/ index.html.twig+ + + b /模板/会议/ index.html.twig@@ 4、7 + 4,7 @@{%块体%}< h2类= " mb-5 " >——给你的反馈!+{{'给你的反馈!“|反式}}< / h2 >{%在会议|行批处理(4)%}7 @@ @@ -21年7 + 21日< a href = "{{路径(“会议”,{蛞蝓:会议。蛞蝓})}}”class = " btn btn-sm btn-primary stretched-link " >——视图+{{‘视图’|反式}}< / > < / div > < / div >
Фільтр树枝反式
шукаєперекладданогозначеннявпоточнійлокалі。Якщойогонезнайдено,вінповертаєзначеннялокалізазамовчуванням,якценалаштованов配置/包/ translation.yaml
:
1 2 3 4 5 6
框架:default_locale:在翻译:default_path:' % kernel.project_dir % /翻译'回退:- - - - - -在
Звернітьувагу,що“вкладкаперекладунапанеліінструментіввеб-налагодженнясталачервоною:
Цеговоритьнампротещо3повідомленнященеперекладені。
Натиснітьна“вкладкущобвивестисписоквсіхповідомлень,дляякихSymfonyнезнаob娱乐下载йшовперекладу:
Наданняперекладів
Яквимоглибачитив配置/包/ translation.yaml
,перекладизберігаютьсявкореневомукаталозі翻译/
,якийбулостворенодлянасавтоматично。
Замістьтогощобстворюватифайлиперекладувручну,використовуйтекоманду翻译:提取
:
1
美元ob娱乐下载symfony控制台翻译:提取fr -力-域=消息
Цякомандагенеруєфайлперекладу(прапорець——力
)длялокаліfr
ідомену消息
。Домен消息
(міститьвсіповідомленнязастосунку,завиняткомтих,якінадходятьвідсамогоSymfony,ob娱乐下载наприклад,помилкивалідаціїчибезпеки。
Відредагуйтефайл翻译/消息+ intl-icu.fr.xlf
іперекладітьповідомленнянафранцузькумову。Винерозмовляєтефранцузькою吗?Дозвольтеменідопомогтивам:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- - - /翻译/消息+ intl-icu.fr.xlf+ + + + intl-icu.fr.xlf b /翻译/消息15 @@ @@ 7日15 + 7,<身体> < trans-unit id = " eOy4.6V " resname = "会议留言板" > <源>会议留言板源> < /- <目标> __Conference留言板目标> < /+ <目标>里弗d ' or倒会议目标> < /< / trans-unit > < trans-unit id = " LNAVleg " resname = "给你的反馈!> <源>给你反馈! > < /来源——<目标> __Give你反馈! < /目标>+ <目标> Donnez你们认为! < /目标>< / trans-unit > < trans-unit id =“3 mg5paf”resname =“视图”> <源>视图> < /来源- <目标> __View目标> < /+ <目标>选择目标> < /< / trans-unit > < /身体> < /文件>
Звернітьувагу,щоминебудемоперекладативсішаблони,аленесоромтесяробитице:
Перекладформ
МіткиформавтоматичновідображаютьсяSymfob娱乐下载ony,задопомогоюсистемиперекладу。Перейдітьнасторінкуконференціїйнатиснітьнавкладку“翻译”напанеліінструментіввеб-налагодження;вимаєтепобачитивсімітки,щоготовідоперекладу:
Локалізаціядат
Якщовиперемкнетенафранцузькумовуйперейдетенавеб-сторінкуконференції,щоміститьдеякікоментарі——випомітите,щодатикоментарівавтоматичнолокалізуються。Цепрацює,томущомивикористовувалифільтр树枝format_datetime
,якийвраховуєособливостілокалі({{发表评论。createdAt | format_datetime(“媒介”,“短”)}}
)。
Локалізаціяпрацюєдлядатчасу(format_time
),валют(format_currency
)ічисел(format_number
)загалом(відсоткитривалістьпропис,…)。
Перекладмножини
Управліннямножинамивперекладахєоднимізосновнихджерелбільшзагальноїпроблемивиборуперекладунаосновіумови。
Насторінціконференціїмивідображаємокількістькоментарів:有两个评论
。Для1коментарямивідображаємо有1的评论
,щонеправильно。Змінітьшаблондляперетворенняреченнявповідомлення,щоперекладається:
1 2 3 4 5 6 7 8 9 10 11
- - - /模板/会议/ show.html.twig+ + + b /模板/会议/ show.html.twig7 + 44 @@ -44年,7 @@< / div > < / div > {% endfor %}——< div >有{{评论|长度}}评论。< / div >+ < div > {{“nb_of_comments”|反式({长度数:评论|})}}< / div >{%如果先前> = 0%}< a href = "{{路径(“会议”,{蛞蝓:会议。蛞蝓,抵消:以前})之前}}" > < / > {% endif %}
Дляцьогоповідомленнямивикористовувалиіншустратегіюперекладу。Замістьтогощобзберегтианглійськуверсіювшаблоні,мизамінилиїїунікальнимідентифікатором。Цястратегіякращепрацюєдляскладнихівеликихобсягівтексту。
Оновітьфайлперекладу,додавшиновеповідомлення:
1 2 3 4 5 6 7 8 9 10 11 12 13
- - - /翻译/消息+ intl-icu.fr.xlf+ + + + intl-icu.fr.xlf b /翻译/消息10 @@ @@ -17年6 + 17日<源>会议留言板< /源> <目标>里弗d ' or倒会议< /目标> < / trans-unit >+ < trans-unit id = " Dg2dPd6“resname = " nb_of_comments " >+ <源> nb_of_comments源> < /+ <目标>{数、复数、= 0{没有commentaire。{1 commentaire} = 1。}other {# commentaires.}}< /span>+ < / trans-unit >< /身体> < /文件> < / xliff >
Мищенезакінчили,оскількитепернампотрібнонадатиперекладнаанглійськумову。Створітьфайл翻译/消息+ intl-icu.en.xlf
:
Оновленняфункціональнихтестів
Незабудьтеоновитифункціональнітести,щобврахуватизміниURL-адресізмісту:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37
- - - /测试/控制器/ ConferenceControllerTest.php+ + + b /测试/控制器/ ConferenceControllerTest.php@@ -11 7 + 11 7 @@类ConferenceControllerTest WebTestCase延伸公共函数testIndex(){$客户=静态:createClient ();-客户- >请求(‘得到’,‘/’);+ $客户- >请求(‘得到’,' / en / ');$ this - > assertResponseIsSuccessful ();$ this - > assertSelectorTextContains (h2,给你反馈);@@ -20 7 + 20 7 @@类ConferenceControllerTest WebTestCase延伸公共函数testCommentSubmission(){$客户=静态:createClient ();-客户- >请求(‘得到’,' /会议/阿姆斯特丹- 2019 ');+ $客户- >请求(‘得到’,‘/ en /会议/阿姆斯特丹- 2019);$客户- > submitForm(‘提交’,‘comment_form(作者)”= >“法”,“comment_form[文本]= >从自动化功能测试的一些反馈,@@ -41年7 + 41,7 @@类ConferenceControllerTest WebTestCase延伸公共函数testConferencePage(){$客户=静态:createClient ();-履带=美元客户- >请求(‘得到’,‘/’);+ $履带= $客户- >请求(‘得到’,' / en / ');$ this - > assertCount(2 $履带- >过滤器(h4));@@ -50 50 6 + 6 @@类ConferenceControllerTest延伸WebTestCase $ this - > assertPageTitleContains(阿姆斯特丹);$ this - > assertResponseIsSuccessful ();$ this - > assertSelectorTextContains (h2,阿姆斯特丹2019);- $ this - > assertSelectorExists (“div:包含(“有1评论”)');+ $ this - > assertSelectorExists (“div:包含(“有一个评论”)');}}