Grails - языковой префикс в отображениях URL
Привет, у меня возникли проблемы с отображением языка. То, как я хочу, чтобы это работало, заключается в том, что язык закодирован в URL, как /appname/de/mycontroller/ что угодно
Если вы перейдете в /appname/mycontroller/action, он должен проверить ваш сеанс и, если нет сеанса, выбрать язык в зависимости от предпочтений браузера и перенаправить на сайт с префиксом языка. Если у вас есть сессия, то он будет отображаться на английском языке. Английский не имеет префикса en (чтобы сделать его сложнее).
Итак, я создал сопоставления, как это:
class UrlMappings {
static mappings = {
"/$lang/$controller/$action?/$id?"{
constraints {
lang(matches:/pl|en/)
}
}
"/$lang/store/$category" {
controller = "storeItem"
action = "index"
constraints {
lang(matches:/pl|en/)
}
}
"/$lang/store" {
controller = "storeItem"
action = "index"
constraints {
lang(matches:/pl|en/)
}
}
"/$controller/$action?/$id?"{
lang="en"
constraints {
}
}
"/store/$category" {
lang="en"
controller = "storeItem"
action = "index"
}
"/store" {
lang="en"
controller = "storeItem"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
}
Он не полностью работает, и языки на данный момент жестко запрограммированы. Я думаю, что сделал что-то не так. Некоторые обратные отображения работают, но некоторые не добавляют язык.
Если я использую тег ссылки и передаю params:[lang:'pl'], то это работает, но если я добавлю params:[lang:'pl', page:2], то это не так. Во втором случае и язык, и номер страницы становятся параметрами в строке запроса. Что еще хуже, они не влияют на локаль, поэтому страница отображается на английском языке.
Может ли кто-нибудь указать мне на документацию, каковы правила обратного отображения или, что еще лучше, как правильно реализовать такой языковой префикс?
СПАСИБО
2 ответа
Самая большая проблема, с которой вам приходится иметь дело, это отсутствие префикса для английского языка. Большая часть твоего картографирования кажется совершенно нормальной. Я бы порекомендовал вам работать с именованными сопоставлениями.
Но сначала я бы порекомендовал вам поработать с фильтрами для установки языкового параметра для каждого пользователя.
def filters = {
languageCheck(controller: '*', action: '*') {
before = {
if( params.lang == null) {
redirect( controller: params.controller, action: params.action, params:[ "lang": request.locale.language.toString() ] + params )
}
}
}
}
Если пользователь с отсутствующим языковым параметром входит на ваш сайт, язык устанавливается фильтром, и он перенаправляется на контроллер с языковым параметром. Будьте осторожны, если вы используете платформу безопасности, которая также перенаправляет. Вы можете перенаправить только один раз. В этом случае вы должны исключить эти URL или контроллеры из фильтра.
Теперь посмотрим на вашу проблему с отображением. Начиная с Grails 1.2 существуют так называемые сопоставления именованных URL. Например
name storeCategory: "/$lang/store/$category" {
controller = "storeItem"
action = "index"
constraints {
lang(matches:/pl|en/)
}
}
Внутри вашего GSP вы можете ссылаться на ваше именованное отображение с помощью
<g:link mapping="storeCategory" params="[lang:'en', category:'new']">Category</g:link>
Это должно решить вашу проблему. Вы можете найти все об именованных отображениях в Справочнике Grails
Я хотел бы добавить следующее: если у вас есть дополнительные параметры, которые должны быть добавлены с помощью? Param = value, у вас будут проблемы, если вы не добавите их явно в ваши преобразования URL. Это связано с тем, что распознаватель сопоставления URL-адресов учитывает параметры контроллера и действия как параметры со специальным значением и сопоставляет только сопоставления, которые имеют точно такой же набор параметров для создания ссылок.
Однако, когда вы используете нумерацию страниц, у вас будут проблемы.
Поэтому в дополнение к вышесказанному сделайте следующее:
class LangAwareUrlMappingsHolderFactoryBean extends UrlMappingsHolderFactoryBean {
@Override
public UrlMappingsHolder getObject() throws Exception {
def obj = super.object
obj.DEFAULT_CONTROLLER_PARAMS = [UrlMapping.CONTROLLER, UrlMapping.ACTION, "lang"] as Set
obj
}
}
И настроить ресурсы.
"org.grails.internal.URL_MAPPINGS_HOLDER"(LangAwareUrlMappingsHolderFactoryBean) { bean ->
bean.lazyInit = true
}
И вы получите
/en/controller/action?offset=10
вместо
/controller/action?offset=10&lang=en