@@ -42,6 +42,18 @@ pub(crate) struct HtmlShell {
42
42
/// Code to be inserted into the shell after the Perseus contents of the
43
43
/// page. This is designed to be modified by plugins.
44
44
pub after_content : Vec < String > ,
45
+ /// The locale to be used for this page, which will be set in the `lang`
46
+ /// attribute on `<html>`.
47
+ ///
48
+ /// **IMPORTANT:** This *does* use `xx-XX` for denoting the locale of an
49
+ /// app not using i18n, but, if this value is set, no interpolation will
50
+ /// be performed. For apps that do use i18n, manually setting the `lang`
51
+ /// attribute in teh index view may lead to unpredictable errors (as
52
+ /// interpolation will nonetheless be performed, leading to conflicts).
53
+ ///
54
+ /// Note that `xx-XX` will be automatically set for locale redirection
55
+ /// pages, preventing interpolation.
56
+ pub locale : String ,
45
57
/// The ID of the element into which we'll interpolate content.
46
58
root_id : String ,
47
59
/// The path prefix to use.
@@ -178,6 +190,8 @@ impl HtmlShell {
178
190
content : "" . into ( ) ,
179
191
root_id : root_id. into ( ) ,
180
192
path_prefix : path_prefix. into ( ) ,
193
+ // Assume until we know otherwise
194
+ locale : "xx-XX" . to_string ( ) ,
181
195
}
182
196
}
183
197
@@ -187,12 +201,17 @@ impl HtmlShell {
187
201
/// translator can be derived on the client-side. These are provided in
188
202
/// a window variable to avoid page interactivity requiring a network
189
203
/// request to get them.
204
+ ///
205
+ /// This needs to know what the locale is so it can set the HTML `lang`
206
+ /// attribute for improved SEO.
190
207
pub ( crate ) fn page_data (
191
208
mut self ,
192
209
page_data : & PageData ,
193
210
global_state : & TemplateState ,
211
+ locale : & str ,
194
212
translations : & str ,
195
213
) -> Self {
214
+ self . locale = locale. to_string ( ) ;
196
215
// Interpolate a global variable of the state so the app shell doesn't have to
197
216
// make any more trips The app shell will unset this after usage so it
198
217
// doesn't contaminate later non-initial loads Error pages (above) will
@@ -249,6 +268,7 @@ impl HtmlShell {
249
268
/// Further, this will preload the Wasm binary, making redirection snappier
250
269
/// (but initial load slower), a tradeoff that generally improves UX.
251
270
pub ( crate ) fn locale_redirection_fallback ( mut self , redirect_url : & str ) -> Self {
271
+ self . locale = "xx-XX" . to_string ( ) ;
252
272
// This will be used if JavaScript is completely disabled (it's then the site's
253
273
// responsibility to show a further message)
254
274
let dumb_redirect = format ! (
@@ -316,8 +336,13 @@ impl HtmlShell {
316
336
error_page_data : & ServerErrorData ,
317
337
error_html : & str ,
318
338
error_head : & str ,
339
+ locale : Option < String > , // For internal convenience
319
340
translations_str : Option < & str > ,
320
341
) -> Self {
342
+ if let Some ( locale) = locale {
343
+ self . locale = locale. to_string ( ) ;
344
+ }
345
+
321
346
let error = serde_json:: to_string ( error_page_data) . unwrap ( ) ;
322
347
let state_var = format ! (
323
348
"window.__PERSEUS_INITIAL_STATE = `error-{}`;" ,
@@ -394,12 +419,19 @@ impl fmt::Display for HtmlShell {
394
419
. replace ( & html_to_replace_double, & html_replacement)
395
420
. replace ( & html_to_replace_single, & html_replacement) ;
396
421
422
+ // Finally, set the `lang` tag if we should
423
+ let final_shell = if self . locale != "xx-XX" {
424
+ new_shell. replace ( "<html" , & format ! ( r#"<html lang="{}""# , self . locale) )
425
+ } else {
426
+ new_shell
427
+ } ;
428
+
397
429
// And minify everything
398
430
// Because this is run on live requests, we have to be fault-tolerant (if we
399
431
// can't minify, we'll fall back to unminified)
400
- let minified = match minify ( & new_shell , true ) {
432
+ let minified = match minify ( & final_shell , true ) {
401
433
Ok ( minified) => minified,
402
- Err ( _) => new_shell ,
434
+ Err ( _) => final_shell ,
403
435
} ;
404
436
405
437
f. write_str ( & minified)
0 commit comments