# developer Lightning Web Runtime (lwr-node) - Full Documentation # @lwrjs/i18n The [i18n API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization) lets you add internationalization support to your Lightning Web Runtime on Node.js (LWR-JS) application. Based on a user's locale, you can use this package to: - Translate strings into different languages - Load different content on a page - Translate user-inputted text ## Set Supported Locales in lwr.config.json For LWR-JS, you have to format your locales as [UTS Locale Identifiers](https://www.unicode.org/reports/tr35/tr35-59/tr35.html#Identifiers). A locale identifier has the structure `language-region-script`. The `language` value is required while `region` and `script` are optional. For example, the `en-US` identifier refers to English (`en`) spoken in the United States (`US`). The `en` identifier only refers to English without a specific geographical region. To set which locales your application supports, create an `i18n` section in `lwr.config.json` and add a subsection called `locales`. To set the default locale for your site's content, create a `defaultLocale` subsection and set it to a single locale. ``` { "i18n": { // These are all the locales you want to support in your application "locales": [{ "id": "en-US" }, { "id": "fr" }, { "id": "nl-NL", "fallback": "fr" }], // This is the default locale you want to be used when visiting // a non-locale prefixed path e.g. `/hello` "defaultLocale": "en-US" } } ``` ## Handle Locales with URI Patterns To implement the locale rules that you created in [Set Supported Locales in lwr.config.json](#set-supported-locales-in-lwrconfigjson), you have to set up a URI pattern for handling locales. With LWR-JS, you can choose from path prefix routing and custom routing. ### Routing with Path Prefixes Path prefix routing adds locale information to the user's URL. To use path prefix routing in your site, add `"uriPattern": "path-prefix"` to the `i18n` section of `lwr.config.json`. For example, let's say the site `MyExampleSite` uses the following `i18n` configuration. ``` { "i18n": { // Supported locales: en-US, fr, nl-NL "locales": [{ "id": "en-US" }, { "id": "fr" }, { "id": "nl-NL", "fallback": "fr" }], "defaultLocale": "en-US", // Use path prefix routing "uriPattern": "path-prefix" }, "routes": [ { "id": "blog", "path": "/blog", "rootComponent": "demo/blog" } ] } ``` This site's URL is `https://myexamplesite.com`. It has the route `/blog`, which supports these URLs. - `https://myexamplesite.com/blog` - `https://myexamplesite.com/fr/blog` - `https://myexamplesite.com/nl-nl/blog` Although the `MyExampleSite` website registers each route with the default locale prefix, users that try to access those URLs (like `https://myexamplesite.com/en-us/blog`) get redirected to that URL without the prefix (`https://myexamplesite.com/blog`). ### Custom Locale Routing If you don't set `uriPattern` in `lwr.config.json`, you have to use the `:locale` token in your `routes` configuration to define how URLs represent localized pages. Here's an example of a config file for a site with a `/blog` route that uses custom URI routing. ``` { "i18n": { // Supported locales: en-US, fr, nl-NL "locales": [{ "id": "en-US" }, { "id": "fr" }, { "id": "nl-NL", "fallback": "fr" }], "defaultLocale": "en-US" // "path-prefix" isn't set }, "routes": [ { "id": "blog", "path": "/blog", "rootComponent": "demo/blog" }, // `blog-localized` sets up URL path for a dynamic locale value { "id": "blog-localized", "path": ":locale/blog", "rootComponent": "demo/blog" } ] } ``` ## Access Locales with API Calls If you want your API calls to have access to locale information, the following objects have a `locale` property that you can reference. ### page The page information object (`page`) includes a locale property that you can use in your [template](https://developer.salesforce.com/docs/platform/lwr/guide/lwr-templates.md). ``` ``` ### SsrRequestContext The `SsrRequestContext` object also contains the `locale` property. When a component is server-side rendered (SSRed), LWR-JS calls the [`getServerData()`](https://developer.salesforce.com/docs/platform/lwr/guide/lwr-enable-ssr-site.md#load-data-during-ssr) hook. This function returns public properties to the component. ``` export async function getServerData(context: SsrRequestContext): Promise { // This is called to fetch data when the component is SSRed const topic = context.params.topic; const locale = context.locale; const response = await fetch( `https://www.googleapis.com/books/v1/volumes?q=subject:${topic}&langRestrict=${locale}`, ); const data = await response.json(); return { props: { data, ...context.params } }; } ``` ### lwr/environment Only in LWR-JS, the `lwr/environment` module contains the current locale in the `locale` value. `locale` doesn't get populated within the Salesforce platform, but you can import it like this: ``` import { locale } from 'lwr/environment'; ``` # @lwrjs/security [HTTP security headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#security) guard your site against malicious code injections and cross-site scripting (XSS) attacks. You can implement security headers for your LWR site on a route-by-route basis using the `@lwrjs/security` package. `@lwrjs/security` exposes a [default route handler](#default-route-handler) and a [security wrapper](#security-wrappers), both of which apply a set of default security headers. To customize these headers, modify the corresponding header configuration objects. ## Usage To add this package to your project, run `npm install @lwrjs/security` on the command line. Implement this package for a route via the default handler or a security wrapper. ## Default Route Handler The `@lwrjs/security` route handler matches the [RouteHandlerFunction](https://developer.salesforce.com/docs/platform/lwr/guide/lwr-routing-server.md#route-handler-functions) interface. ``` type RouteHandler = (ViewRequest, HandlerContext) => Promise; ``` It's exposed as the default export. ``` export { default } from '@lwrjs/security'; ``` To use the default handler for a route, set `@lwrjs/security` as the route handler in `lwr.config.json`. ``` { "routes": [ { "id": "home", "path": "/", "rootComponent": "examples/example", "routeHandler": "@lwrjs/security", }, ] } ``` To modify a security header in the default route handler, set the corresponding header configuration object in the `routeHandler` section. You can disable a header by setting its configuration object to `false`. For more information about default headers and header configuration, skip ahead to [Headers](#headers). ``` "routeHandler": ["@lwrjs/security", { "contentSecurityPolicy": "default-src 'self';base-uri 'self'; script-src 'self'", "referrerPolicy": false, "xXSSProtection": false }] ``` ## Security Wrappers The `@lwrjs/security` route handler wrapper `secure()` applies security headers to an existing route handler. The wrapper is exposed as a named export. It takes a route handler as an argument and returns a promise. ``` type RouteHandlerWrapper = (RouteHandlerFunction) => Promise; ``` `RouteHandlerReturnType` can be a `ViewResponse` or `ViewDefinitionResponse`. Each type of promise applies headers as follows: - **ViewDefinitionResponse** - applies the default security headers with inline resource hashing. - **ViewResponse** (HTML content) - applies the default security headers without resource hashing. - **ViewResponse** (non-HTML content) - doesn't apply headers. For example, this `routeHandler.ts` file passes the `routeHandler` into `secure()`. Since the `headers` section is empty, only the default headers are used. ``` import type { ViewDefinitionResponse } from '@lwrjs/types'; import { secure } from '@lwrjs/security'; function routeHandler(): ViewDefinitionResponse { return { // programmatically define the view configuration view: { rootComponent: 'example/home' }, // set response headers headers: {}, }; } export default secure(routeHandler); ``` To modify a header for the default handler, configure the corresponding header configuration object in the route handler file. You can disable a header by setting its configuration object to `false`. ``` headers: { "contentSecurityPolicy": "default-src 'self';base-uri 'self'; script-src 'self'", "referrerPolicy": false, "xXSSProtection": false }, ``` ## Headers The default route handler and security wrapper automatically enable the following security headers. ### Content-Security-Policy The `Content-Security-Policy` header directs your site to load content from only approved sources. For a list of acceptable formats for source values, see [CSP Source Values](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#sources). These are the default directives for the `Content-Security-Policy` header. | Directive | Description | Default Source Value | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | | `default-src` | Set the default source value for all directives that don't have a value. | `'self'` | | `base-uri` | Set approved sources that load content in the page's `` element. | `'self'` | | `font-src` | Set approved sources that provide fonts. | `'self' https: data:;` | | `form-action` | Set approved sources that a form can send information to. | `'self'` | | `frame-ancestors` | Set approved sources that can embed your page (the current frame) into a container like `` on their site. | `'self'` | | `img-src` | Set approved sources of images and icons. | `'self' data:;` | | `object-src` | Set approved sources of `` and `` elements. | `'none'` | | `script-src` | Set approved sources of JavaScript code for elements like `