Хорошего дня,
Мне нужен Route-RegExp на основе языка клиента для веб-сайта.
Должно быть так:
Relative URL / Route:
/(No-Language) -> /?lng=(someDefaultLanguage)
/(No-Language)/ -> /?lng=(someDefaultLanguage)
/lngCode/page -> /page/?lng=lngCode
/lngCode/page/ -> /page/?lng=lngCode
/lngCode/pageL1/pageL2 -> /pageL1/pageL2/?lng=lngCode
/language/page?param=Value -> /page/?lng=lngCode¶m=Value
(Обратите внимание на косую черту в некоторых строках)
Древовидная структура … ну бесконечно 🙂
Есть случаи с одним и несколькими URL-параметрами.
Я абсолютно не волшебник регулярных выражений, я справился с этим результатом в … часах:
/^\/([a-z]{2})(?:(.*[^\?])|^$)((?:[\/\?]).*|^$)/
Пожалуйста, не спрашивайте меня, что я пытался направить туда. Я оооочень новый для регулярных выражений.
заранее спасибо
—
Изменить для уточнения (я надеюсь):
По сути, это концепция: (Это внутренняя маршрутизация, без перенаправления, если я не упомянул.)
Параметр языка (как стиль каталога) должен быть взят из 1-го URL и присоединен как реальный параметр с именем «lng». Каталог-параметр должен исчезнуть.
Если уже есть другие параметры, их также необходимо присоединить (? /&-дело).
Если язык не указан (= язык по умолчанию), в URL отсутствует параметр каталога style. Было бы неплохо, если бы еще можно было присоединить параметр? Lng = en.
Примеры:
localhost/blogpage/coolentry (default language)
localhost/de/blogpage/coolentry
localhost/es/blogpage/coolentry
localhost/blogpage/ -> localhost/blogpage/?lng=en
localhostde/de/blogpage/ -> localhost/blogpage/?lng=de
localhost/blogpage/coolentry/ -> localhost/blogpage/coolentry/?lng=en
localhost/de/blogpage/coolentry/ -> localhost/blogpage/coolentry/?lng=de
localhost/de/blogpage/coolentry/?entryPage=1 -> localhost/blogpage/coolentry/?lng=de&entryPage=1
Он всегда маршрутизируется с реальным языковым параметром.
Я также отредактировал первый пост, в нем была запутанная опечатка.
Извините за задержку @hcm.
Ну, я должен сказать тебе. Я потратил 10 минут на написание оригинального регулярного выражения.
Протестировано в Perl, все отлично работает.
Затем я отправляю его в онлайн-тестер php и получаю сообщение об ошибке «Предупреждение о неопределенном смещении».
Захватывать группы 2,3,4 необязательно, поэтому я делаю (?: ( capture ) )?
но php такой беспорядок
вы can't even test for undefined group
.
Обновить
@hcm — Хорошо, разобрался. Эти онлайн-тестеры не переводят CRLF в LF.
Поэтому при использовании многострочного режима $
является границей перед новой строкой или концом строки.
^
после новой строки или начала строки, что не проблема.
Так, $
не будет соответствовать до CR только перед LF. Обходной путь, вероятно, использует
\R
любая конструкция разрыва строки, но это не граница, это фактический характер.
Что я сделал, чтобы вылечить это использовать (?: $ | (?= \r) )
вне утверждений и
(?: $ | \r )
внутри утверждения. Это излечивает все проблемы.
После прочтения вашего сообщения я изменил регулярное выражение, чтобы каждая часть была необязательной, но
по-прежнему позиционный.
4 необязательные части заключаются в следующем.
1. Перед кодом языка.
2. Код Ланга.
3. После кода ланга.
4. Параметры.
Ни одна часть не будет перебивать другую.
Все ведущие /
‘ы взяты из каждой части (не часть матча),
в то время как внутренние косые черты остаются на месте.
Осталось только создать новый URL, как вы хотите.
Дайте мне знать, как это получается или если вам нужно немного подправить.
Код PHP:
// Go to this website:
// http://writecodeonline.com/php/
// Cut & paste this into the code box, hit run.
$text = '
invalid
/
/de
/de/coolentry
localhost/
localhost/blogpage
localhost/blogpage/
localhost/blogpage/de/
/localhost/blogpage/coolentry/famous invalid
/root/blog/page/cool/entry/?entryPage=1&var1=A&var2=B
localhost/blogpage/coolentry/
localhost/blogpage/de/coolentry/
localhost/blogpage/de/coolentry/
localhost/blogpage/de/coolentry/?entryPage=1
localhost/blogpage/coolentry/?entryPage=2
';
$str = preg_replace_callback('~^(?![^\S\r\n]*(?:\r|$))(?|(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$)))/?((?:(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$))|\?|/[^\S\r\n]*(?:\r|$))\S)*)|())(?|/([a-z]{2})(?=/|[^\S\r\n]*(?:\r|$))|())(?|/((?:(?!/[^\S\r\n]*(?:\r|$))[^?\s])+)|())(?|/\?((?:(?!/[^\S\r\n]*(?:\r|$))\S)*)|())/?[^\S\r\n]*(?:$|(?=\r))~m',
function( $matches )
{
///////////////// URL //////////////////
$url = '';
// Before lang code -- Group 1
if ( $matches[1] != '' ) {
$url .= '/' . $matches[1];
}
// After lang code -- Group 3
if ( $matches[3] != '' ) {
$url .= '/' . $matches[3];
}
///////////////// PARAMS //////////////////
$params = '/?lng=';
// Lang code -- Group 2
if ( $matches[2] != '' ) {
$params .= $matches[2];
}
else {
$params .= 'en'; // No lang given, set default
}
// Other params
if ( $matches[4] != '') {
$params .= '&' . $matches[4];
}
///////////////// Check there is a Url //////////////////
if ( $url == '' ) { // No url given, set a default
$url = '/language'; // 'language', 'localhost', etc...
}
///////////////// Put the pieces back together //////////////////
$NewURL = $url . $params;
return $NewURL;
},
$text);
print $str;
выход:
invalid
/language/?lng=en
/language/?lng=de
/coolentry/?lng=de
/localhost/?lng=en
/localhost/blogpage/?lng=en
/localhost/blogpage/?lng=en
/localhost/blogpage/?lng=de
/localhost/blogpage/coolentry/famous invalid
/root/blog/page/cool/entry/?lng=en&entryPage=1&var1=A&var2=B
/localhost/blogpage/coolentry/?lng=en
/localhost/blogpage/coolentry/?lng=de
/localhost/blogpage/coolentry/?lng=de
/localhost/blogpage/coolentry/?lng=de&entryPage=1
/localhost/blogpage/coolentry/?lng=en&entryPage=2
Regex
# '~^(?![^\S\r\n]*(?:\r|$))(?|(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$)))/?((?:(?!/[a-z]{2}[^\S\r\n]*(?:/|(?:\r|$))|\?|/[^\S\r\n]*(?:\r|$))\S)*)|())(?|/([a-z]{2})(?=/|[^\S\r\n]*(?:\r|$))|())(?|/((?:(?!/[^\S\r\n]*(?:\r|$))[^?\s])+)|())(?|/\?((?:(?!/[^\S\r\n]*(?:\r|$))\S)*)|())/?[^\S\r\n]*(?:$|(?=\r))~m'
^ # BOL
(?! # Not a blank line, remove to generate a total default url
[^\S\r\n]*
(?: \r | $ )
)
(?| # BEFORE lang code
(?!
/ [a-z]{2} [^\S\r\n]* # not lang code
(?:
/
| (?: \r | $ )
)
)
/? # strip leading '/'
( # (1 start)
(?:
(?!
/ [a-z]{2} [^\S\r\n]* # not lang code
(?:
/
| (?: \r | $ )
)
|
\? # not parms
|
/ [^\S\r\n]* # not final slash
(?: \r | $ )
)
\S
)*
) # (1 end)
|
( ) # (1)
)
(?| # LANG CODE
/ # strip leading '/'
( [a-z]{2} ) # (2)
(?=
/
| [^\S\r\n]*
(?: \r | $ )
)
|
( ) # (2)
)
(?| # AFTER lang code
/ # strip leading '/'
( # (3 start)
(?:
(?! # not final slash
/ [^\S\r\n]*
(?: \r | $ )
)
[^?\s] # not parms
)+
) # (3 end)
|
( ) # (3)
)
(?| # PARAMETERS
/ \? # strip leading '/?'
( # (4 start)
(?:
(?! # not final slash
/ [^\S\r\n]*
(?: \r | $ )
)
\S
)*
) # (4 end)
|
( ) # (4)
)
/?
[^\S\r\n]* # EOL
(?:
$
| (?= \r )
)
Других решений пока нет …