ASP.NET MVC Урок 1-F / ASP.NET MVC Урок C
.pdf$63 1(7 09& ǻȘȖȒ & ǴȕȖȋȖȧȏȣȟȕȣȑ șȈȑȚtutorial
ASP*, .NET*
Цель урока. Научиться создавать многоязычные сайты. Структура БД. Ресурсы сайта. Определение языка. Переключение между языками. Работа в админке.
Проблемы многоязычного сайта
Итак, заказчик просит сделать сайт многоязычным, т.е. чтобы и порусски, и пофранцузки, и по английски. Это может быть как просто многоязычный блог, так и гостиничный сайт, сайт по работе с недвижимостью и многое другое.
Для начала определим, что же мы будем переводить:
Написание дат, сумм в зависимости от выбранной локализации. С этим справляется класс
System.Globalization
Встроенные ресурсы сайта — выдача ошибки («Поле не может быть пустым», «The field is required») и другие сообщения.
Не встроенные ресурсы, как то логотипы, изображения, jsлокализация элементов управления. Для переключения между ними необходимо знать текущее значение языка на странице.
Пользовательские значения.
Есть несколько вариантов решения этой задачи. Рассмотрим их.
Самое простое, что можно сделать, — это разные сайты. Нужен русский сайт — сделали. Нужен перевод, скопировали сайт, перевели все данные и всё. Этот вариант приемлем, когда сайт небольшой, всего несколько страниц, статичный и нет админки.
Разные БД. Сайт в зависимости от выбранной локализации подключается к одной или другой БД. Если необходимо добавить новый язык – то переводится вся БД и ресурсы сайта. Но БД могут быть разные, и статья, написанная на одном языке, не будет доступна для перевода на другой, плюс будет необходимость дублировать изображения, которые в принципе нет необходимости переводить.
Управление локализацией при работе с базой данных.
Сразу рассмотрим третий вариант и определим, как мы это организуем в приложении:
В адресе сайта теперь появляется параметр lang
Возможно, адрес будет иметь вид KWWS RXU VLWH FRP ^ODQJ` ^FRQWUROOHU` ^DFWLRQ`
Возможно, адрес будет иметь вид KWWS RXU VLWH FRP ^FRQWUROOHU` ^DFWLRQ`" ODQJ UX
Параметр lang – это ISO двухбуквенное определение языка (ru – русский, uk – украинский, cs – чешский)
Первым делом мы используем System.Globalization для правильного вывода дат Организуем внутренние ресурсы для вывода ошибки относительно заданных языков
Организуем таблицы в БД таким образом, чтобы для каждой записи существовал перевод необходимых полей.
Мы будем создавать 2 локализации – русскую и английскую, причем русская будет по умолчанию.
Routing
В DefaultAreaRegistration добавим обработка lang (/Areas/Default/DefaultAreaRegistration.cs):
FRQWH[W 0DS5RXWH
QDPHODQJ
XUO^ODQJ` ^FRQWUROOHU` ^DFWLRQ` ^LG`
GHIDXOWVQHZ^ FRQWUROOHU +RPHDFWLRQ ,QGH[LG 8UO3DUDPHWHU 2SWLRQDO `
FRQVWUDLQWVQHZ^ ODQJ # UX_HQ`
QDPHVSDFHVQHZ>@ ^/HVVRQ3URMHFW$UHDV 'HIDXOW &RQWUROOHUV`
FRQWH[W 0DS5RXWH
QDPHGHIDXOW
XUO^FRQWUROOHU` ^DFWLRQ` ^LG`
GHIDXOWVQHZ^ FRQWUROOHU +RPHDFWLRQ ,QGH[LG 8UO3DUDPHWHU 2SWLRQD O ODQJ UX`
QDPHVSDFHVQHZ>@ ^/HVVRQ3URMHFW$UHDV 'HIDXOW &RQWUROOHUV`
Итак, если строка у нас начинается с lang, то мы используем обработку маршрута “lang”. Обратите внимание на contstrains (ограничения), тут задается, что язык может быть только ru или en. Если это условие не исполняется, то мы переходим к следующей обработке маршрута –
“default”, где поумолчанию lang=ru.
Используем это для инициализации в DefaultController для смены культуры потока
(Thread.Current.CurrentCulture) (/Areas/Default/DefaultController.cs):
SXEOLF FODVV 'HIDXOW&RQWUROOHU %DVH&RQWUROOHU
^
SXEOLF VWULQJ&XUUHQW/DQJ&RGH ^JHW SURWHFWHG VHW`
SXEOLF/DQJXDJH &XUUHQW/DQJ ^JHW SURWHFWHG VHW`
SURWHFWHG RYHUULGH YRLG ,QLWLDOL]H6\VWHP :HE 5RXWLQJ 5HTXHVW&RQWH[W UHTXHVW&RQWH[W
^
LIUHTXHVW&RQWH[W +WWS&RQWH[W 5HTXHVW 8UO QXOO
^
+RVW1DPH UHTXHVW&RQWH[W +WWS&RQWH[W 5HTXHVW 8UO$XWKRULW\
`
LIUHTXHVW&RQWH[W 5RXWH'DWD 9DOXHV>ODQJ@ QXOO UHTXHVW&RQWH[W 5RXWH'DWD 9DOXH V>ODQJ@DV VWULQJ QXOO
^
&XUUHQW/DQJ&RGH UHTXHVW&RQWH[W 5RXWH'DWD 9DOXHV>ODQJ@DV VWULQJ
&XUUHQW/DQJ 5HSRVLWRU\ /DQJXDJHV )LUVW2U'HIDXOW S ! S &RGH &XUUHQW/DQJ&RG H
YDUFL QHZ&XOWXUH,QIR &XUUHQW/DQJ&RGH
7KUHDG &XUUHQW7KUHDG &XUUHQW8,&XOWXUH FL
7KUHDG &XUUHQW7KUHDG &XUUHQW&XOWXUH &XOWXUH,QIR &UHDWH6SHFLILF&XOWXUH FL 1DPH
`
EDVH,QLWLDOL]H UHTXHVW&RQWH[W
`
`
Естественно, в BaseController мы убираем инициализацию культуры потока через конфигурационный файл (/Controllers/BaseController.cs):
SURWHFWHG RYHUULGH YRLG ,QLWLDOL]H6\VWHP :HE 5RXWLQJ 5HTXHVW&RQWH[W UHTXHVW&RQWH[W
^
LIUHTXHVW&RQWH[W +WWS&RQWH[W 5HTXHVW 8UO QXOO
^
+RVW1DPH UHTXHVW&RQWH[W +WWS&RQWH[W 5HTXHVW 8UO$XWKRULW\
`
EDVH,QLWLDOL]H UHTXHVW&RQWH[W
`
Запускаем, и проверяем, как изменяется вывод даты:
Первый этап пройден. Переходим к управлению ресурсам сайта.
Ресурсы сайта
Ресурсы сайта – это все статические строки, которые надо перевести:
Наименования меню
Подсказки Выводы ошибок
На главной странице у нас таких строк четыре: роли, пользователи, вход и регистрация. Создадим ресурсные файлы:
Добавим папку Asp.net папку App_LocalResources:
Создадим в ней файлы GlobalRes.resx и GlobalRes.en.resx:
Добавляем в них наши строки, в GlobalRes – русский перевод, в GlobalRes.en – английский:
Enter |
Вход |
|
|
Register |
Регистрация |
|
|
Roles |
Роли |
|
|
Users |
Пользователи |
|
|
Открываем для GlobalRes свойства и устанавливаем следующие значения для полей
Build Action: Embedded Resource
Custom Tool: PublicResXFileCodeGenerator
Теперь добавим namespace LessonProject.App_LocalResources в Web.cofig в system.web.webPages.razor (Web.config):
V\VWHP ZHE ZHE3DJHV UD]RU!
SDJHV SDJH%DVH7\SH 6\VWHP :HE 0YF :HE9LHZ3DJH!
QDPHVSDFHV!
DGG QDPHVSDFH /HVVRQ3URMHFW +HOSHU!
DGG QDPHVSDFH /HVVRQ3URMHFW 7RROV!
DGG QDPHVSDFH /HVVRQ3URMHFW$SSB/RFDO5HVRXUFHV!
QDPHVSDFHV!
SDJHV!
V\VWHP ZHE ZHE3DJHV UD]RU!
Используем в UserLogin.cshtml (/Areas/Default/Views/Home/UserLogin.cshtml) и Index.cshtml ((/Areas/Default/Views/Home/Index.cshtml):
#PRGHO /HVVRQ3URMHFW 0RGHO 8VHU
#LI 0RGHO QXOO
^
OL!#0RGHO (PDLOOL!
OL!#+WPO$FWLRQ/LQN ȼɵɯɨɞ /RJRXW /RJLQOL!
`
HOVH
^
OL!VSDQ FODVV EWQ EWQ OLQN LG /RJLQ3RSXS!#*OREDO5HV (QWHUVSDQ!OL!
OL!#+WPO$FWLRQ/LQN *OREDO5HV 5HJLVWHU 5HJLVWHU 8VHUOL!
`
«
#^
9LHZ%DJ 7LWOH /HVVRQ3URMHFW
/D\RXW a$UHDV 'HIDXOW 9LHZV 6KDUHG B/D\RXW FVKWPO
`
K!/HVVRQ3URMHFWK!S!
#'DWH7LPH 1RZ 7R6WULQJ '
GLY FODVV PHQX!
D KUHI #8UO$FWLRQ ,QGH[ 5ROH QHZ^LG ` !#*OREDO5HV 5ROHVD!
#+WPO$FWLRQ/LQN *OREDO5HV 8VHUV ,QGH[ 8VHU
GLY!
S!
Запускаем, проверяем:
Перейдем к заданию сообщений валидации на примере LoginView:
Выделяем ErrorMessage для полей в ресурсные файлы (/App_LocalResources/GlobalRes.resx):
EnterEmail |
Введите email |
|
|
EnterPassword |
Введите пароль |
|
|
Задаем правила валидации в LoginView.cs (/Models/ViewModel/LoginView.cs):
SXEOLF FODVV /RJLQ9LHZ
^
>5HTXLUHG (UURU0HVVDJH5HVRXUFH7\SH W\SHRI*OREDO5HV (UURU0HVVDJH5HVRXUFH1DPH (QW HU(PDLO@
SXEOLF VWULQJ(PDLO ^JHW VHW`
>5HTXLUHG (UURU0HVVDJH5HVRXUFH7\SH W\SHRI*OREDO5HV (UURU0HVVDJH5HVRXUFH1DPH (QWHU3DVVZRUG@
SXEOLF VWULQJ3DVVZRUG ^JHW VHW`
SXEOLF ERRO,V3HUVLVWHQW ^JHW VHW`
`
Проверяем в страничной версии localhost/en/Login:
Но для popup входа эти предупреждения так и останутся на русском языке, потому, что мы для вызова popupблока используем url по умолчанию. Соответственно, задав параметр lang, мы сможем изменить это:
Добавим в ресурсы (/App_LocalResources/GlobalRes(.en).resx)CurrentLang = ru и CurrentLang = en
Выведем это в hiddenполе в _Layout.cshtml (/Areas/Default/Views/Shared/_Layout.cshtml):
ERG\!
#+WPO +LGGHQ&XUUHQW/DQJ*OREDO5HV &XUUHQW/DQJ
GLYFODVV QDYEDU QDYEDU IL[HG WRS!
Ⱦɨɛɚɜɢɦ ɷɬɨ ɜ DMD[ ɜɵɡɨɜɵ6FULSWVFRPPRQ MV BWKLV WKLV
WKLVORJLQ$MD[ /RJLQ$MD[
WKLVLQLW IXQFWLRQ
^
BWKLV ORJLQ$MD[ &XUUHQW/DQJYDO BWKLV ORJLQ$MD[
/RJLQ3RSXSFOLFNIXQFWLRQ^
BWKLV VKRZ3RSXS BWKLV ORJLQ$MD[ LQLW/RJLQ3RSXS
`
`
IXQFWLRQ LQLW/RJLQ3RSXSPRGDO ^
/RJLQ%XWWRQFOLFNIXQFWLRQ^
DMD[ ^
W\SH3267
XUO BWKLV ORJLQ$MD[
GDWD/RJLQ)RUPVHULDOL]H
Проверяем: