Lokalizacja aplikacji
Lokalizacja aplikacji
Dzięki użytkownikom z całegoświata, Sob娱乐下载ymfony od początku istnienia jest w stanie poradzićsobie z internacjonalizacją(i18n)我lokalizacją(l10n) od新法提案阿宝zainstalowaniu frameworka。Lokalizacja aplikacji,聂tylko tłumaczenie interfejsu,啤酒także uwzględnienie liczby mnogiej tłumaczonych rzeczownikow, formatowania dat我walut adresow URL我wiele więcej。
Internacjonalizacja adresow URL
Pierwszym krokiem做internacjonalizacji strony internetowej jest internacjonalizacja adresow URL。Podczas tłumaczenia interfejsu strony internetowej这URL powinien byćinny国防后勤局każdego miejsca,赎wspołgrałz pamięciąpodręcznąHTTP (nigdy聂przechowuj adresu URL razem z kodem języka w sesji)。
Użyj specjalnego parametru trasy (ang。路线),_locale
,赎odnieśćsięlokalizacji w trasach:
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。嫩枝”,(
Kod języka (ang。地区)na stronie głownej jest teraz ustawiany wewnętrznie w zależności od adresu URL;na przykład, jeśli trafisz/ fr /
,$请求- > getLocale ()
zwracafr
。
Ponieważprawdopodobnie聂będziesz w stanie przetłumaczyćtreści na wszystkie dostępne języki, ogranicz siętych, ktore chcesz obsługiwać:
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。嫩枝”,(
Każdy parametr trasy może byćograniczony wyrażeniem regularnym wewnątrz<
oraz>
。Trasa主页
pasuje tylko wtedy, gdy parametr_locale
jest ustawiony na在
滑fr
。Podaj URL/ es /
404年,dostaniesz błąd ponieważżadna trasa聂została dopasowana做wyrażenia regularnego。
Ponieważna prawie wszystkich trasach będziemy stosować十sam wymog przenieśmy我做parametru kontenera:
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。嫩枝”,(
Język można dodaćpoprzez modyfikacjęparametruapp.supported_languages
。
Dodaj十山姆prefiks trasy国防后勤局danego kraju做innych adresow 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 % >} /会议/{蛞蝓}”,名字:“会议”)公共函数显示(请求请求美元,美元会议,会议
Prawie skończyliśmy。聂mamy jużtrasy, ktora pasowałaby做/
。Dodajmy jąz powrotem我przekierujmy na/ 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美元):反应{
Teraz, gdy wszystkie głowne trasy biorąpod uwagęobecne ustawienia regionalne, należy zauważyć,że wygenerowane adresy URL na斯特罗纳克automatycznie uwzględniająkod języka。
Dodawanie przełącznika ustawieńregionalnych (ang。语言环境)
偿umożliwićużytkownikom przejście z domyślnego kodu języka (ang。语言环境)在
na inny, dodajmy przełącznik w nagłowku:
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 >
偿przełączyćsięna inny kod języka (ang。语言环境),przekazujemy parametr_locale
trasy做funkcji路径()
。
Zaktualizuj szablon,赎wyświetlićaktualnąnazwęjęzyka zamiast zakodowanego na sztywno“英语”:
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”})}} " > < / > < /李>英语
应用程序
jest globalnązmiennąbiblioteki树枝,ktora umożliwia dostęp做bieżącegożądania (ang。请求)。偿przekonwertowaćnazwęobecnej lokalizacji czytelnej国防后勤局użytkownika到处做,używamy filtralocale_name
。
W zależności od języka nazwa聂zawsze jest zapisana wielkimi literami。做poprawnej zmiany wielkości升w zdaniu potrzebny jest filtr, ktory uwzględnia Unicode。Zapewnia komponent Symob娱乐下载fony字符串我jego implementacja w Twigu:
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”})}} " > < / > < /李>英语
Teraz można zmienićjęzyk z francuskiego na angielski咱pomocąprzełącznika,一个cały interfejsładnie siędostosowuje:
Tłumaczenie interfejsu
Tłumaczenie każdego zdania na dużej stronie internetowej może byćżmudne,啤酒na szczęście u nas jest tylko kilka wiadomości。Zacznijmy od wszystkich zdańna stronie głownej:
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 >
Filtr反式
biblioteki树枝wyszukuje tłumaczenie podanego tekstu na bieżącąlokalizację。Jeśli聂zostanie znalezione, powroci wartości zdomyślnej lokalizacjiskonfigurowanej w配置/包/ translation.yaml
:
1 2 3 4 5 6
框架:default_locale:在翻译:default_path:' % kernel.project_dir % /翻译'回退:- - - - - -在
Zauważ,że na pasku narzędzi做debugowania zakładka tłumaczeńzmieniła kolor na czerwony:
jest sygnał,że trzy wiadomości聂zostały jeszcze przetłumaczone。
Kliknij na zakładkę,赎wyświetlićlistęwszystkich wiadomości,国防后勤局ktorych Symfonob娱乐下载y聂znalazłtłumaczenia:
Dostarczanie tłumaczeń
木菠萝można było zauważyćw配置/包/ translation.yaml
,tłumaczenia sąprzechowywane w katalogu翻译/
,ktory zostałutworzony automatycznie。
Zamiast tworzyćpliki tłumaczeńręcznie, użyj polecenia翻译:提取
:
1
美元ob娱乐下载symfony控制台翻译:提取fr -力-域=消息
Polecenie, generuje plik tłumaczeń(flaga——力
)国防后勤局kodu językafr
我domeny消息
,ktora zawiera wszystkie wiadomości związane zaplikacją,啤酒鹿角的第二叉tych, ktore dostarcza Sob娱乐下载ymfony——takich木菠萝związane z walidacją滑błędami bezpieczeństwa。
Edytuj plik翻译/消息+ intl-icu.fr.xlf
我przetłumacz zawarte w nim teksty na język francuski。聂mowisz阿宝francusku吗?Pozwolże Ci pomogę:
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 > < /身体> < /文件>
Zauważ,że聂przetłumaczyłem wszystkich szablonow,啤酒możesz przejąćpałeczkę:
Tłumaczenie formularzy
Etykiety formularzy sąautomatycznie wyświetlane przez Sob娱乐下载ymfony tłumaczeńpoprzez系统。Przejdźna stronękonferencji我kliknij na zakładkęTłumaczenie“na pasku narzędzi debugowania;wszystkie etykiety powinny byćgotowe tłumaczenia:
Ustawienia regionalne dat
Jeżeli przełączysz się我wejdziesz na na francuski stronękonferencji, na ktorej sąjużjakieśkomentarze, zauważysz,że daty tych komentarzy sąautomatycznie dostosowane做ustawieńregionalnych użytkownika。十mechanizm działa dzięki dostępnemu w Twigu filtrowiformat_datetime
,ktory bierze pod uwagęustawienia regionalne ({{发表评论。createdAt | format_datetime(“媒介”,“短”)}}
)。
Lokalizacja działa国防后勤局dat czasu (format_time
),walut (format_currency
)我liczb (format_number
)w wielu formach (procenty czas trwania, zapis słowny我wiele innych)。
Tłumaczenie liczby mnogiej
Zarządzanie liczbąmnogąw tłumaczeniach jest jednym z przypadkow bardziej ogolnego problemu wyboru tłumaczenia w oparciu o warunki。
Na stronie konferencji wyświetlana jest liczba komentarzy:有两个评论
。国防后勤局jednego komentarza wyświetlamy有1的评论
,jest błędne。Zmodyfikuj szablon,赎przekonwertowaćzdanie na komunikat tłumaczenia:
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 %}
W tym celu zastosowaliśmy innąstrategiętłumaczenia。Zamiast zachowaćwersjęangielskąw szablonie zastąpiliśmy jąunikalnym identyfikatorem。助教strategia lepiej sprawdza sięw przypadku tekstow skomplikowanych我długich。
Zaktualizuj plik tłumaczenia poprzez dodanie nowej wiadomości:
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 >
Jeszcze聂skończyliśmy, ponieważmusimy teraz zadbaćo tłumaczenie na język angielski。Utworz plik翻译/消息+ intl-icu.en.xlf
:
Aktualizowanie testow funkcjonalnych
聂zapomnij zaktualizowaćtestow funkcjonalnych,赎brały pod uwagęzmiany adresow URL我treści:
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:包含(“有一个评论”)');}}