I believe I'm running into some issues when trying to get valet to play nice with Craft's localization - https://craftcms.com/docs/localization-guide
I'm using the multiple locale folders in the /public webroot but when trying to access these pages I'm getting a 404.
In my specific example i've got:
public/index.php
public/au/index.php
public/us/index.php
The second two files have their respective:
$craftPath = '../../craft';
define('CRAFT_LOCALE', 'en_au');
Just wondering if anyone has some ideas how we might update the driver to support this or to look at a custom Caddy rewrite rule to get it working (https://forum.caddyserver.com/t/craftcms-locale-rewrites-with-valet/728 had posted over there before I realised that valet has official support for Craft)
Hey @danethomas thanks for the report! I am happy to try and fix this but I'm not a Craft user, so it would be super helpful if you share a small Craft repo with me that has the localization stuff setup already that I can use to troubleshoot.
Hey @danethomas and @adamwathan
I had a similar problem and this is the code that solved it for my setup (which is domain.com/de for example, it was a quickie and i'm sure it needs some refinement.
The gotchas are that you might get problems with Sections that are two characters long and you need to to add a / at the end of the url on the homepage.
It tests on a translations folder in the $sitePath, maybe you have to adjust it.
<?php
class CraftMultiLangValetDriver extends ValetDriver
{
/**
* Determine if the driver serves the request.
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return bool
*/
public function serves($sitePath, $siteName, $uri)
{
if (is_dir($sitePath . '/craft') && is_dir($sitePath . '/translations')) {
return true;
}
return false;
}
/**
* Determine if the incoming request is for a static file.
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return string|false
*/
public function isStaticFile($sitePath, $siteName, $uri)
{
if ($this->isActualFile($staticFilePath = $sitePath.'/public'.$uri)) {
return $staticFilePath;
}
return false;
}
/**
* Get the fully resolved path to the application's front controller.
*
* @param string $sitePath
* @param string $siteName
* @param string $uri
* @return string
*/
public function frontControllerPath($sitePath, $siteName, $uri)
{
$pattern = '/^\/([a-z]{2})\/(.*)/';
$match = preg_match($pattern, $uri);
if($match) {
$uriElements = explode("/", $uri);
$_SERVER['SCRIPT_FILENAME'] = $sitePath.'/public/'.$uriElements[1].'/index.php';
$_SERVER['SERVER_NAME'] = $_SERVER['HTTP_HOST'];
$_SERVER['SCRIPT_NAME'] = $uriElements[1].'index.php';
$_SERVER['DOCUMENT_ROOT'] = $sitePath.'/public';
$site = $sitePath.'/public/'.$uriElements[1].'/index.php';
} else {
$_SERVER['SCRIPT_FILENAME'] = $sitePath.'/public/index.php';
$_SERVER['SERVER_NAME'] = $_SERVER['HTTP_HOST'];
$_SERVER['SCRIPT_NAME'] = '/index.php';
$site = $sitePath.'/public/index.php';
}
return $site;
}
}
Hope it helps.
Apologies for the delay @adamwathan and I appreciate the help. Have been away for a week but I'll try and get up a repo shortly for you to look at.
Edit, have just seen your post @martinherweg so I will also check that out as well.
Ok a quick update - after adding the custom driver this seems to resolve the issue for me.
The gotchas are that you might get problems with Sections that are two characters long and you need to to add a / at the end of the url on the homepage.
I can see this being a problem. Keen to explore something a little more robust or hearing some thoughts from your @adamwathan on how this might end up being supported out of the box.
I'm also using 2 letter region codes for my folders but not everyone will be. My setup is:
public/
index.php
au/
index.php
ca/
index.php
gb/
index.php
us/
index.php
Could make sense to read the siteUrl environment array to work out the variable localized paths.
I think it's much better to be explicit about which locales it should match, instead of having a generic regex pattern.
I've done this in my installation:
public function frontControllerPath($sitePath, $siteName, $uri)
{
// Default index path
$indexPath = $sitePath.'/public/index.php';
$scriptName = '/index.php';
// Check if the first URL segment matches any of the defined locales
$locales = ['en', 'nb', ..];
$parts = explode('/', $uri);
if (count($parts) > 1 && in_array($parts[1], $locales)) {
$indexPath = $sitePath.'/public/'. $parts[1] .'/index.php';
$scriptName = $parts[1] . '/index.php';
}
$_SERVER['SCRIPT_FILENAME'] = $indexPath;
$_SERVER['SERVER_NAME'] = $_SERVER['HTTP_HOST'];
$_SERVER['SCRIPT_NAME'] = $scriptName;
return $indexPath;
}
Does this make sense to you?
It does make sense @sjelfull - not convinced that's going to be a solution for Valet moving forward though if they do want to update the default CraftCMS driver.
@danethomas Not sure what you mean there? Are you talking about people modifying their local CraftCMS driver?
My idea is that all locales that Craft has built-in would be listed in the $locales array. Theoretically that means most people wouldn't have to modify anything.
This of course assumes "most people" only would use a domain.dev/xx setup, while theoretically you could go wild.
Maybe we also could add support for subdomains too? Something like en.domain.dev, fr.domain.dev?
Yeah I was just wondering if there's a way that custom locales could be
supported in the default driver (I'm not sure there is, due to the way
locales can be configured in Craft).
I'm ok creating and editing a custom driver but it just adds another step
in our setup process.
On Thu., 13 Oct. 2016 at 6:37 pm Fred Calsen [email protected]
wrote:
@danethomas https://github.com/danethomas Not sure what you mean there?
Are you talking about people modifying their local CraftCMS driver?My idea is that all locales that Craft has built-in would be listed in the
$locales array. Theoretically that means most people wouldn't have to
modify anything.This of course assumes "most people" only would use a domain.dev/xx
setup, while theoretically you could go wild.Maybe we also could add support for subdomains too? Something like
en.domain.dev, fr.domain.dev?—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/laravel/valet/issues/179#issuecomment-253437871, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAE6AGqbZM8KdfsoYXXK9qVhaRbZmsWfks5qzd_MgaJpZM4KJnkr
.
Actually, I intended the above example to be a pull request for the default driver.
It should work out of the box with some typical setups and all locales that Craft currently supports.
Ah right of course, can just extend your $locales array to include all of
the supported locales 👍
On Thu., 13 Oct. 2016 at 6:47 pm Fred Calsen [email protected]
wrote:
Actually, I intended the above example to be a pull request for the
default driver.It should work out of the box with some typical setups and all locales
that Craft currently supports.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/laravel/valet/issues/179#issuecomment-253439696, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAE6AAc2x1hOpD5xlo-bYNFM_e1H6COPks5qzeIHgaJpZM4KJnkr
.
I had to add a leading / to the $scriptname to get your solution to work @sjelfull
$scriptName = $parts[1] . '/index.php'; changed to $scriptName = '/' . $parts[1] . '/index.php';
Cool. Here is a complete list of locales that Craft currently supports:
<?php
$locales = [
'ar',
'ar_sa',
'bg',
'bg_bg',
'ca_es',
'cs',
'cy_gb',
'da',
'da_dk',
'de',
'de_at',
'de_ch',
'de_de',
'el',
'el_gr',
'en',
'en_as',
'en_au',
'en_bb',
'en_be',
'en_bm',
'en_bw',
'en_bz',
'en_ca',
'en_dsrt',
'en_dsrt_us',
'en_gb',
'en_gu',
'en_gy',
'en_hk',
'en_ie',
'en_in',
'en_jm',
'en_mh',
'en_mp',
'en_mt',
'en_mu',
'en_na',
'en_nz',
'en_ph',
'en_pk',
'en_sg',
'en_shaw',
'en_tt',
'en_um',
'en_us',
'en_us_posix',
'en_vi',
'en_za',
'en_zw',
'en_zz',
'es',
'es_cl',
'es_es',
'es_mx',
'es_us',
'es_ve',
'et',
'fi',
'fi_fi',
'fil',
'fr',
'fr_be',
'fr_ca',
'fr_ch',
'fr_fr',
'fr_ma',
'he',
'hr',
'hr_hr',
'hu',
'hu_hu',
'id',
'id_id',
'it',
'it_ch',
'it_it',
'ja',
'ja_jp',
'ko',
'ko_kr',
'lt',
'lv',
'ms',
'ms_my',
'nb',
'nb_no',
'nl',
'nl_be',
'nl_nl',
'nn',
'nn_no',
'no',
'pl',
'pl_pl',
'pt',
'pt_br',
'pt_pt',
'ro',
'ro_ro',
'ru',
'ru_ru',
'sk',
'sl',
'sr',
'sv',
'sv_se',
'th',
'th_th',
'tr',
'tr_tr',
'uk',
'vi',
'zh',
'zh_cn',
'zh_tw',
];
I compiled all the wisdom in this thread to a working multi-locale driver for Craft, see this gist. I'm partial to Fred's idea about being explicit with the possible locales, so that's what I'm using. Working great so far.
@mmikkel If you don't mind, could you submit a pull request?
Most helpful comment
I compiled all the wisdom in this thread to a working multi-locale driver for Craft, see this gist. I'm partial to Fred's idea about being explicit with the possible locales, so that's what I'm using. Working great so far.