Localization support for the Website service (#10)
This PR contains the work done to introduce server-side localization support to the **Website** service so the landing and error pages are served in the visitor's negotiated language, backed by a new reusable Localization package. To provide further details about the work: * Created the _Localization_ package — a bundle-bound `Localize` method and a `LanguageList` type. * Language negotiation — `NegotiateLanguage` method picks the best supported language from the request's _Accept-Language_ header (falling back to the default); the `LocalizationMiddleware` middleware resolves it per request and stores it on a new `LocalizedRequestContext` / `WebsiteRequestContext` context. * Localized responses — `LocalizedHTMLCollectionResponse` pre-renders each page once per language and caches the bytes (with `Content-Language` + `Vary: Accept-Language`), reused by the `RootController` controller and `NotFoundMiddleware` middleware. * The `CachedHTMLResponse` response gained custom-header support. * Localized pages — the `IndexPage` and `ErrorPage` pages now resolve their strings via `Localize` method; * Added `Localizable.xcstrings` catalogs. * Wired the `LocalizationMiddleware` middlewaer into the router. Reviewed-on: rock-n-code/loud-amsterdam#10 Co-authored-by: Javier Cicchelli <javier@rock-n-code.com> Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit is contained in:
@@ -1,13 +1,36 @@
|
||||
import Elementary
|
||||
import Foundation
|
||||
import Localization
|
||||
|
||||
/// The website's landing page.
|
||||
/// The website's landing page, with its text localized to a given locale.
|
||||
struct IndexPage: HTMLDocument, Sendable {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The locale the page content is localized to.
|
||||
private let locale: Locale
|
||||
|
||||
/// Resolves the page's text from the bundled String Catalog for the page's ``locale``.
|
||||
private let localize: Localize
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a landing page localized to the given locale.
|
||||
/// - Parameter locale: the locale the page content is localized to.
|
||||
init(
|
||||
locale: Locale
|
||||
) {
|
||||
self.locale = locale
|
||||
self.localize = .init(bundle: .module)
|
||||
}
|
||||
|
||||
// MARK: Document
|
||||
|
||||
/// The page's content.
|
||||
/// The page's content: a localized greeting followed by the app script.
|
||||
var body: some HTML {
|
||||
p { "Hello world! This is HTML5 Boilerplate." }
|
||||
p {
|
||||
localize("index.greeting", locale: locale)
|
||||
}
|
||||
script(.src("/js/app.js")) {}
|
||||
}
|
||||
|
||||
@@ -52,14 +75,15 @@ struct IndexPage: HTMLDocument, Sendable {
|
||||
)
|
||||
}
|
||||
|
||||
/// The document language.
|
||||
/// The document language, derived from the page's locale and falling back to the default language.
|
||||
var lang: String {
|
||||
"en"
|
||||
locale.language.languageCode?.identifier
|
||||
?? LanguageList(bundle: .module).default
|
||||
}
|
||||
|
||||
/// The document title.
|
||||
/// The localized document title.
|
||||
var title: String {
|
||||
"Index page"
|
||||
localize("index.title", locale: locale)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user