33namespace CodeZero \LocalizedRoutes ;
44
55use Illuminate \Support \Collection ;
6+ use Illuminate \Support \Facades \App ;
7+ use Illuminate \Support \Facades \Config ;
8+ use Illuminate \Support \Facades \Request ;
69use Illuminate \Support \Facades \Route ;
710use Illuminate \Support \Facades \URL ;
811
@@ -23,33 +26,106 @@ public function __construct()
2326 $ this ->route = Route::current ();
2427 }
2528
29+ /**
30+ * Generate a localized URL for the current request.
31+ *
32+ * @param string|null $locale
33+ * @param mixed $parameters
34+ * @param bool $absolute
35+ *
36+ * @return string
37+ */
38+ public function generateFromRequest ($ locale = null , $ parameters = null , $ absolute = true )
39+ {
40+ return ($ this ->isDefault404 () || $ this ->isNonLocalizedFallback404 ())
41+ ? $ this ->generateFromUrl ($ locale , $ parameters , $ absolute )
42+ : $ this ->generateFromRoute ($ locale , $ parameters , $ absolute );
43+ }
44+
2645 /**
2746 * Check if the current route is localized.
2847 *
2948 * @return bool
3049 */
3150 public function isLocalized ()
3251 {
33- return $ this ->route && $ this ->route ->getAction ('localized-routes-locale ' );
52+ return $ this ->routeExists () && $ this ->route ->getAction ('localized-routes-locale ' ) !== null ;
3453 }
3554
3655 /**
37- * Generate a localized URL for the current request.
56+ * Check if the current request is a default 404.
57+ * Default 404 requests will not have a Route.
58+ *
59+ * @return bool
60+ */
61+ protected function isDefault404 ()
62+ {
63+ return ! $ this ->routeExists ();
64+ }
65+
66+ /**
67+ * Check if the current request is a non localized fallback 404 route.
68+ * If a fallback route is used as a 404, we expect it to be named '404'.
69+ *
70+ * @return bool
71+ */
72+ protected function isNonLocalizedFallback404 ()
73+ {
74+ return $ this ->routeExists () && $ this ->route ->isFallback && $ this ->route ->getName () === '404 ' ;
75+ }
76+
77+ /**
78+ * Check if the current Route exists.
79+ * Default 404 requests will not have a Route.
80+ *
81+ * @return bool
82+ */
83+ protected function routeExists ()
84+ {
85+ return $ this ->route !== null ;
86+ }
87+
88+ /**
89+ * Generate a localized version of a URL.
3890 *
3991 * @param string|null $locale
4092 * @param mixed $parameters
4193 * @param bool $absolute
4294 *
4395 * @return string
4496 */
45- public function generateFromRequest ($ locale = null , $ parameters = null , $ absolute = true )
97+ protected function generateFromUrl ($ locale = null , $ parameters = null , $ absolute = true )
4698 {
47- // Route does not exist (default 404)
48- if ( ! $ this ->route ) {
49- return URL ::current ();
99+ $ locale = $ locale ?: App::getLocale ();
100+ $ supportedLocales = $ this ->getSupportedLocales ();
101+ $ locales = $ this ->getLocaleKeys ($ supportedLocales );
102+ $ domains = $ this ->getCustomDomains ($ supportedLocales );
103+ $ currentUrl = Request::fullUrl ();
104+ $ urlParts = parse_url ($ currentUrl );
105+
106+ if ($ domains !== null ) {
107+ $ urlParts ['host ' ] = $ domains [$ locale ] ?? $ urlParts ['host ' ];
108+ }
109+
110+ if ($ domains === null ) {
111+ $ currentPath = $ urlParts ['path ' ] ?? '' ;
112+ $ slugs = explode ('/ ' , trim ($ currentPath , '/ ' ));
113+ $ localeSlug = $ slugs [0 ] ?? '' ;
114+
115+ if (in_array ($ localeSlug , $ locales )) {
116+ $ slugs [0 ] = $ locale ;
117+ } else {
118+ array_unshift ($ slugs , $ locale );
119+ }
120+
121+ if ($ slugs [0 ] === Config::get ('localized-routes.omit_url_prefix_for_locale ' )) {
122+ $ urlParts [0 ] = '' ;
123+ } else {
124+ $ urlParts ['path ' ] = '/ ' . join ('/ ' , $ slugs );
125+ }
50126 }
51127
52- return $ this -> generateFromRoute ( $ locale , $ parameters , $ absolute );
128+ return $ urlParts [ ' scheme ' ] . ' :// ' . $ urlParts [ ' host ' ] . ( $ urlParts [ ' port ' ] ?? '' ) . ( $ urlParts [ ' path ' ] ?? '' );
53129 }
54130
55131 /**
@@ -80,4 +156,55 @@ protected function generateFromRoute($locale = null, $parameters = null, $absolu
80156
81157 return route ($ this ->route ->getName (), $ parameters , $ absolute , $ locale );
82158 }
159+
160+ /**
161+ * Get the custom domains from the supported locales configuration.
162+ *
163+ * @return array|null
164+ */
165+ protected function getCustomDomains (array $ locales )
166+ {
167+ return $ this ->hasCustomDomains ($ locales ) ? $ locales : null ;
168+ }
169+
170+ /**
171+ * Get the locale keys from the supported locales configuration.
172+ *
173+ * @param array $locales
174+ *
175+ * @return array
176+ */
177+ protected function getLocaleKeys (array $ locales )
178+ {
179+ return $ this ->hasCustomDomains ($ locales ) ? array_keys ($ locales ) : $ locales ;
180+ }
181+
182+ /**
183+ * Check if custom domains are configured.
184+ *
185+ * @param array $locales
186+ *
187+ * @return bool
188+ */
189+ protected function hasCustomDomains (array $ locales )
190+ {
191+ $ keys = array_keys ($ locales );
192+
193+ if (empty ($ locales ) || is_numeric ($ keys [0 ])) {
194+ return false ;
195+ }
196+
197+ return true ;
198+ }
199+
200+ /**
201+ * Get the supported locales and not the custom domains.
202+ *
203+ * @return array
204+ */
205+ protected function getSupportedLocales ()
206+ {
207+ return Config::get ('localized-routes.supported-locales ' , []);
208+
209+ }
83210}
0 commit comments