@@ -92,16 +92,16 @@ def preferred_locales(request, path_locale = nil)
9292 return locales . to_a
9393 end
9494
95- # Infer preferred locales from the request host .
95+ # Infer preferred locales from the request authority .
9696 # @parameter request [Utopia::Request] The application request.
97- # @yields {|locale| ...} Each locale whose host pattern matches the request host .
97+ # @yields {|locale| ...} Each locale whose host pattern matches the request authority .
9898 # @returns [Hash] The configured host mappings.
9999 def host_preferred_locales ( request )
100- http_host = request . host . to_s
100+ authority = request . authority . to_s
101101
102- # Yield all hosts which match the incoming http_host :
102+ # Yield all hosts which match the incoming authority :
103103 @hosts . each do |pattern , locale |
104- if http_host [ pattern ]
104+ if authority [ pattern ]
105105 yield locale
106106 end
107107 end
@@ -111,16 +111,34 @@ def host_preferred_locales(request)
111111 # @parameter request [Utopia::Request] The application request.
112112 # @returns [Array(Utopia::Request, String | Nil)] The request and extracted locale.
113113 def extract_path_locale ( request )
114- path = Path [ request . path_info ]
114+ path = request . url . path
115115
116- if request_locale = @all_locales . patterns [ path . first ]
117- # Remove the localization prefix:
118- path . delete_at ( 0 )
119-
120- return request . with ( path_info : path . to_s ) , request_locale
121- else
116+ # Localization prefixes only apply to absolute application paths:
117+ unless path . absolute?
122118 return request , nil
123119 end
120+
121+ if segment = path . segments [ 1 ]
122+ # Decode only the component which may contain the locale:
123+ component = Protocol ::URL ::Encoding ::System . unescape ( segment )
124+
125+ if request_locale = @all_locales . patterns [ component ]
126+ # Remove the locale while preserving all other encoded segments:
127+ segments = path . segments . dup
128+ segments . delete_at ( 1 )
129+
130+ # Preserve the absolute root when the locale was the only component:
131+ if segments == [ "" ]
132+ segments << ""
133+ end
134+
135+ path = Protocol ::URL ::Path . new ( nil , segments )
136+
137+ return request . with ( path : path ) , request_locale
138+ end
139+ end
140+
141+ return request , nil
124142 end
125143
126144 # Parse the locales preferred by the browser.
@@ -147,8 +165,8 @@ def browser_preferred_locales(request)
147165 # @returns [Boolean] Whether the path is eligible for localization.
148166 def localized? ( request )
149167 # Ignore requests which match the ignored paths:
150- path_info = request . path_info
151- return false if @ignore . any? { |pattern | path_info [ pattern ] != nil }
168+ path = request . url . path . encoded
169+ return false if @ignore . any? { |pattern | path [ pattern ] != nil }
152170
153171 return true
154172 end
0 commit comments