Rask
Rask
v0.23.1-alpha.0.496
You're reading the Rask v0.23.1-alpha.0.496 guides. Updated .View source
All guides

Localization

Ship your app in more than one language: dates and numbers in the visitor's format, text in their language, and <html lang> that tells the truth.

Every scaffolded app already ships one language, English, listed in appsettings.json under Rask:Cultures. Adding a second is an entry in the list that is already there:

{
  "Rask": {
    "Cultures": [ "en", "hu" ]   // the first is the default; add one to ship another
  }
}

The object form takes the other settings beside the list: "Cultures": { "SupportedCultures": [ "en", "hu" ], "DefaultCulture": "hu" }.

The first entry is the default a visitor falls back to. That list is where languages are configured — there is no CLI flag for it, because the file is where the answer lives and stays (#854). In the environment it is one variable per entry (Rask__Cultures__0=en).

A configureCulture callback on AddRask still works and runs after the section. The list is appended to rather than replaced, so a language added in code joins the configured ones:

builder.Services.AddRask(configureCulture: c => c.SupportedCultures.Add("hu"));

A browser (WebAssembly) app lists them in the same section, read by its build — see WebAssembly apps.

Until you add a second, nothing changes: <html lang="en">, no dir attribute, and no cost on the render path.

How a visitor's language is chosen

Order Source Notes
1 ?culture=hu An explicit act. Also remembered, so a shared link sticks
2 the culture cookie A choice they made earlier
3 Accept-Language / navigator.languages What their browser says they read
4 your first SupportedCultures entry The default

A request for a language you ship in another region still works: hu-HU is served by hu, and hu is served by a supported hu-HU. A language you do not ship falls through to the default rather than being honoured.

The language is settled before the first render, on both hosts. That matters more than it sounds: by the time script could read navigator.language, the page has already painted — and if it painted in the wrong language the visitor would watch it change.

Why the URL has no language in it

/products/42 is the same page for everyone. That is a deliberate trade:

  • a pasted link works for whoever opens it, in their language
  • the router, the generated Url() / Go() helpers and every route value stay culture-neutral
  • nothing in your app has to thread a culture through link generation

The cost is that you do not get per-language URLs for search engines. If you need those, you need more than a prefix — canonical tags, hreflang pairs, and a sitemap per language — which is a different feature with a different design, not a switch to flip.

Rask reads and writes ASP.NET's own .AspNetCore.Culture cookie, in ASP.NET's own format. So an app that also calls UseRequestLocalization() for its non-Rask endpoints, or that shares a host with MVC, agrees with them rather than holding a second, conflicting preference.

It is deliberately readable from script — the WASM host reads it before the runtime boots, to stamp lang/dir on the document — so it carries a language tag and never anything else.

A choice made with Set is written by Rask.Web.CookieCulturePersistence, through document.cookie (Document.SetCookie), so it is remembered over plain HTTP too. Both hosts register it, so there is nothing to write; register your own IRaskCulturePersistence first to store the choice elsewhere.

Translating your text

Put a catalog per language in Resources/:

// Resources/Strings.en.json — the neutral catalog defines which keys exist
{
  "AppTitle": "Welcome",
  "Greeting": "Hello, {name}!",
  "Home": { "Title": "Dashboard" }
}
// Resources/Strings.hu.json
{
  "AppTitle": "Üdvözöljük",
  "Greeting": "Szia, {name}!",
  "Home": { "Title": "Irányítópult" }
}

They compile into real members:

Div[
    H1[Strings.Home.Title],
    P[Strings.Greeting(user.Name)]
]

A typo is a compile error. Strings.Greetng(...) is CS0117 and the wrong number of arguments is CS1501 — at the call site, before anything runs. Nothing renders a bare key to a user.

A string is text wherever a child goes: P[Strings.Greeting(name)], a bare child, Text.Value(...) and Text[Strings.Greeting(name)] all render the same encoded words.

Placeholders

{name} takes object?. {count:int} makes it typed. {price:decimal:C} adds a format specifier, applied in the visitor's culture.

Names, not positions, because other languages reorder arguments:

{ "M": "{a} then {b}" }     // en
{ "M": "{b} majd {a}" }     // hu — fine, the same names

What is not fine is a different set of names: that throws FormatException when a Hungarian visitor first sees the string, so it is RASK051, an error at build time.

Counts

A count is dynamic, so "write two keys and pick one" breaks the moment a language has three categories — and Polish, Russian, Czech and Arabic all do. Write a plural set:

{ "Cart": { "$plural": "count", "one": "{count} item", "other": "{count} items" } }
Span[Strings.Cart(basket.Count)]

Each language supplies the categories it distinguishes:

// Resources/Strings.pl.json — Polish, and correctly no "other"
{ "Cart": { "$plural": "n", "one": "{n} plik", "few": "{n} pliki", "many": "{n} plików" } }

Polish integers never select other; CLDR routes the residual to many. A language whose grammar Rask does not carry is a build error naming it — better than silently applying English rules and shipping text that reads as broken to every native speaker.

Missing translations

A key you have not translated yet is a warning (RASK052) and falls back to the neutral text, so the page still works. Gate a release on complete translations by promoting it:

# .editorconfig
dotnet_diagnostic.RASK052.severity = error

Or silence it with = none while translation is in progress.

The same values, four languages

Fixed sample values and an explicit CultureInfo per call — a demo that read the ambient culture would reformat every other demo on this page.

CultureFormatsDemo.cs
using System.Globalization;

namespace Rask.Site.Features.Localization;

/// <summary>
///     The same three values, formatted for four languages side by side.
/// </summary>
/// <remarks>
///     <para>
///         Two rules make this demo safe to snapshot, and both are load-bearing:
///     </para>
///     <para>
///         <b>Fixed sample values, never <c>DateTime.Now</c>.</b> Every registered demo's markup
///         skeleton is committed as a golden file, and the guide page is screenshotted — a value that
///         moves would make both go stale on a schedule rather than when something actually changed.
///     </para>
///     <para>
///         <b>An explicit <c>CultureInfo</c> per call, never an assignment to
///         <c>CultureInfo.CurrentCulture</c>.</b> A guide page mounts many demos in one render; setting
///         the ambient culture here would reformat every other demo on the page, and the golden would
///         record it.
///     </para>
/// </remarks>
public sealed partial class CultureFormatsDemo : Component
{
    private static readonly DateTimeOffset Sample = new(2026, 3, 14, 15, 9, 26, TimeSpan.Zero);
    private const decimal Price = 1234.56m;
    private const double Ratio = 0.4567;

    private static readonly string[] Languages = ["en-US", "hu-HU", "de-DE", "ar-EG"];

    protected override Component Render()
    {
        // A runtime built without culture data formats everything identically, which would make this
        // table look broken rather than instructive. Say so instead of showing four identical columns.
        if (!Rask.Core.Globalization.RaskCultureResolver.IsGlobalizationSupported)
        {
            return Ui.Callout.Warning.Icon(Ui.IconName.ExclamationCircle)[
                Ui.CalloutText["This build runs with ", Code["InvariantGlobalization"], ", so every culture formats identically. Set ", Code["<RaskGlobalization>true</RaskGlobalization>"], " to ship ICU — see the WASM section of this guide."]
            ];
        }

        return Ui.Table[
            Ui.TableColumns[
                Ui.TableColumn["Language"],
                Ui.TableColumn["Date"],
                Ui.TableColumn["Money"],
                Ui.TableColumn["Percent"]
            ],
            // The enumerable is passed straight in: a `..` spread does not bind against the chain's
            // children indexer.
            Ui.TableRows[Languages.Select(Row)]
        ];
    }

    private static Component Row(string tag)
    {
        var culture = CultureInfo.GetCultureInfo(tag);

        // The tag goes in a data attribute, never a class: the golden records tag names and sorted
        // class tokens, so a culture in a class would bake the sample data into the snapshot.
        return Ui.TableRow.Data("culture", tag)[
            Ui.TableCell[Code[tag]],
            Ui.TableCell[Sample.ToString("d", culture)],
            Ui.TableCell[Price.ToString("C", culture)],
            Ui.TableCell[Ratio.ToString("P1", culture)]
        ];
    }
}
Live result
Language
Date
Money
Percent
en-US3/14/2026$1,234.5645.7%
hu-HU2026. 03. 14.1 235 Ft45,7%
de-DE14.03.20261.234,56 €45,7 %
ar-EG14‏‏/3‏‏/20261٬234٫56 ج.م.‏45٫7٪؜

Reading the culture in a component

public sealed partial class Receipt : Component
{
    protected override Component Render() =>
        Div[
            P[Total.ToString("C", Culture)],
            P[IssuedOn.ToString("d", Culture)]
        ];
}

Culture is the visitor's, for formatting. UICulture is the language their text is in. IsRightToLeft answers the layout question.

Reading any of them tells the render cache this component depends on the culture, so a language switch repaints it. That is why you should read Culture rather than CultureInfo.CurrentCulture — the ambient value is pinned to the same culture during a render, so it formats correctly, but the cache cannot see that you read it.

What stays culture-neutral, on purpose

These are wire formats, not display formats, and they do not follow the visitor:

  • <input type="date"> and type="number" values — the HTML5 wire format is fixed, and the browser localizes the display itself
  • route values and generated URLs
  • reconciliation keys, DOM event payloads, and anything else crossing the socket

If you are formatting a value to send somewhere rather than to show someone, pass CultureInfo.InvariantCulture explicitly.

Switching language at runtime

public sealed partial class LanguageMenu(IRaskCulture culture) : Component
{
    protected override Component Render() =>
        Select.OnChange(e => culture.Set(e.Value ?? "en"))[
            culture.Supported.Select(c => Option.Value(c.Name)[c.NativeName])
        ];
}

Set switches the session, remembers the choice, and repaints. No reload.

No template scaffolds this, deliberately (#854). A new project starts with English in Rask:Cultures; adding a language is another entry there. That is the whole configuration surface — there is no --culture flag, because a flag would only restate what the file already says, and it would say it once at scaffold time while the file goes on being the truth.

Where a language control belongs in your chrome is a different question, and it is a design decision about your app rather than wiring — the same line the styling decisions sit on. So a scaffolded app negotiates language correctly out of the box, and a visitor can be sent to a language by link, but there is no affordance for choosing one until you add the component above.

That is worth stating rather than leaving to be discovered: negotiation working end to end reads very much like a switcher being present somewhere. RaskCultureNegotiator.TrySelect is kept separate from Negotiate precisely so an explicit pick is honoured regardless of UseQueryString, which is what keeps the menu above at ten lines instead of a feature.

When no culture is configured

Culture support is off until SupportedCultures has an entry, and "off" means English: <html lang="en">, and every date and number formatted in en. Both hosts keep that promise to the first HTML they send:

  • Server: the first response and every live render run in the server process's culture — the same one, so a page never changes language once it is live. Set the process culture (or configure a language) if that is not the one you want; UseRequestLocalization() reaches only the first response, never the socket, so it is not a way to pick one.
  • WebAssembly: the .NET runtime starts in the browser's locale and the prerender in the publishing machine's, neither of which is the page's. So the host pins CultureInfo.CurrentCulture, CurrentUICulture and both thread defaults to en before the first render, and the prerender does the same before the first page. A Hungarian browser therefore reads "October 2026", as the baked page did, rather than "2026. október" under English labels. Without ICU (RaskGlobalization off) the pin is the invariant culture, which is what such an app formats in anyway.

To format in the visitor's language, configure it — Rask:Cultures, or host.UseCulture(c => …) — and the session's culture takes over: the browser is pinned to the negotiated culture before the first render, and the prerender bakes every page in the app's default culture, <html lang> included, whatever the publishing machine's locale.

Right-to-left

A right-to-left culture emits dir="rtl" on <html>; everything else emits no dir at all, because left-to-right is HTML's default. Use logical CSS properties (margin-inline-start, not margin-left) and the layout follows.

WebAssembly apps

A browser app has no configuration at run time, so its build reads Rask:Cultures instead, from:

App File
wasm (standalone) wwwroot/appsettings.json
wasm-hosted the host's appsettings.json — the ONE list both halves use
// wwwroot/appsettings.json — published with the app, so anyone can read it: no secrets here
{
  "Rask": {
    "Cultures": [ "en", "hu" ]
  }
}

The list is baked into the bundle and in force before the first render and in the prerender, and host.UseCulture(c => …) in Program.cs still adds to it, or sets the rest of the options. Because the build reads it, a change needs a rebuild, and an environment variable on a hosted app's server (Rask__Cultures__1=hu) reaches the server half only. Another file is named with <RaskAppSettings>path/to/appsettings.json</RaskAppSettings>.

The cookie and the query key are the ones the options name (CookieName, QueryKey), on both hosts.

WASM and ICU

A WASM app needs culture data (ICU) to format a language, and it is the one part of this feature you can measure on the download. So the build ships it when Rask:Cultures names a language other than English, and not otherwise: English is what a runtime without culture data formats in anyway, so the "en" a new app starts with costs nothing, and adding "hu" turns ICU on with no other edit.

To decide yourself — a language added only in code, with UseCulture — set the property:

<RaskGlobalization>true</RaskGlobalization>

false under a non-English list is obeyed, with a build warning, since every language would then format as English.

Measured on the WASM showcase, publishing the same trimmed app with and without it:

raw brotli (what a host serves)
without ICU 12.44 MB 3.28 MB
with ICU 16.36 MB 4.33 MB
cost +3.92 MB +1.05 MB (+32%)

Re-measured for #853 and still right: +3.90 MB raw / +1.06 MB brotli (+33%) on the current tree. The figures were always the cost of the shards — see below — which is what has shipped all along.

Roughly a third of that is the icudt*.dat files themselves; the rest is a larger dotnet.native.wasm and System.Private.CoreLib, because turning globalization on brings back runtime code that invariant mode trims away. That is why it follows the list rather than being on for every browser app; on server the runtime already carries ICU and it costs nothing.

Without it every culture formats identically and only the invariant culture resolves — and because Rask's resolver refuses to let a culture pose as supported when the data isn't there, an app that configures languages without ICU starts with an empty supported-language list and says so once at startup rather than once per render.

Translated text works either way — lookup is keyed on a language tag rather than a CultureInfo, so an app can ship three languages with no ICU at all. Only date/number formatting falls back.

The prerender bakes with the culture data the bundle ships. An English-only app has no ICU, so in the browser "en" formats with the invariant culture's data — 03/14/2026, 2026 March, ¤1,234.50 — while the publishing machine has real English (3/14/2026, March 2026, $1,234.50). So the prerender of an app built with InvariantGlobalization runs without culture data too, and the baked page is the one the browser then renders: <html lang="en"> and the English strings stay; only the formatting is the invariant culture's. Turn ICU on (Rask:Cultures with another language, or RaskGlobalization) and both bake and browser format with real culture data.

One property covers all three halves of this, because each default is a trap on its own:

  • PredefinedCulturesOnly otherwise stays true, and CultureInfo.GetCultureInfo("hu-HU") throws rather than falling back
  • the runtime otherwise has no culture data at all, so no named culture resolves

What ships, and the one thing to know about it

A globalized WASM publish carries three reduced ICU shards, not one full icudt.dat:

icudt_EFIGS.<hash>.dat    English, French, Italian, German, Spanish
icudt_CJK.<hash>.dat      Chinese, Japanese, Korean
icudt_no_CJK.<hash>.dat   everything else — including Hungarian, and English

The runtime loads one of them, chosen at boot, and it chooses from the visitor's browser (navigator.languages[0]) rather than from the languages your app ships. So a second language works for a visitor whose browser is already set to it, and an en+hu app opened in an English browser loads EFIGS — which has no Hungarian. With PredefinedCulturesOnly=false, hu-HU then resolves, does not throw, and formats dates in English.

Known limitation, tracked in #853. Rask set WasmIncludeFullIcu intending to ship full ICU and avoid this; the SDK's property is WasmIncludeFullIcuData, so it was never read. Correcting the spelling turns out not to help either: that property is honoured only by the WasmAppBuilder bundle path, and a Rask app publishes through Microsoft.NET.Sdk.WebAssembly, whose pipeline has no ICU handling of its own. Measured — publishing with the property true and false produces byte-identical output.

If your app ships more than one language and its speakers may arrive with a different browser language, be aware of this. A single-language app is unaffected.

Translating the framework's own text

Rask draws a little text of its own — the pager's "Showing 1 to 10 of 13 results", a select's "No results found", a date picker's "Select a date", the names a screen reader hears for a close button. Every one of them is a RaskString key with its English beside it in the code, and is looked up in this order:

  1. your app's Resources/RaskStrings.{culture}.json, if it has the key
  2. the UI kit's own translation — Rask.Ui ships Hungarian (hu) beside its English
  3. the English

So an app that lists hu in SupportedCultures gets a Hungarian pager, select, date picker, editor toolbar and data grid with no catalog of its own, and a language switch repaints them like any other text. The kit's translations apply only to the languages your app says it ships — an app with no SupportedCultures keeps the English whatever the server's or the browser's language is. Month and weekday names, dates and numbers are not in any catalog: they come from the culture.

Adding a language, or changing a word

The reserved catalog is an ordinary JSON file whose keys are RaskString members. Write the keys you want and leave the rest: anything you have not translated falls through to the kit's own translation, then to the English.

// Resources/RaskStrings.hu.json — the kit already speaks Hungarian. This overrides two of its words.
{
  "ConfirmLeaveStay": "Nem",
  "ConfirmLeaveLeave": "Igen"
}
// Resources/RaskStrings.de.json — a language the kit does not ship: the pager and the form controls.
{
  "PaginationSummary": "{0}–{1} von {2} Ergebnissen",
  "PaginationPrevious": "« Zurück",
  "PaginationNext": "Weiter »",

  "SelectEmpty": "Keine Ergebnisse",
  "SelectLoading": "Wird geladen…",
  "SelectSearchPlaceholder": "Suchen…",
  "SelectSearchClear": "Suche leeren",
  "SelectClear": "Auswahl aufheben",
  "SelectSelectedSuffix": "ausgewählt",

  "DatePickerPlaceholder": "Datum wählen",
  "DatePickerRangePlaceholder": "Zeitraum wählen",
  "DatePickerConfirm": "Übernehmen",
  "DatePickerCancel": "Abbrechen",
  "CalendarToday": "Heute",
  "PickerPreviousMonth": "Vorheriger Monat",
  "PickerNextMonth": "Nächster Monat",

  "TimePickerPlaceholder": "Uhrzeit wählen",
  "PickerClear": "Löschen",

  "InputClear": "Eingabe löschen",
  "InputCopy": "In die Zwischenablage kopieren",
  "InputTogglePassword": "Passwort ein- oder ausblenden",
  "InputChooseFile": "Datei auswählen",
  "InputChooseFiles": "Dateien auswählen",
  "InputNoFile": "Keine Datei ausgewählt",

  "ModalClose": "Dialog schließen"
}

No neutral file: the framework's English lives in its own code. A misspelled key is a build error (RASK051) listing the valid names.

A text that carries values numbers them — {0}, {1}, {2} — so a translation puts them in its own order, and may give one a .NET format: the Hungarian pager is "{2} találatból {0}–{1}.", and "{2:N0}" would group the total's thousands. The values are written in the visitor's culture. Asking for a value the text does not carry ({3} in the pager's summary), or naming one ({total}), is a build error too. There are no plural forms here: none of these texts changes with its number in English, and a count stands before a singular in Hungarian.

The kit's own Hungarian is the same kind of file, src/Rask.Ui/Resources/RaskStrings.hu.json, compiled by the same generator. A component library of your own ships translations for the framework texts it draws the same way — the file, and <RaskStringsLibrary>true</RaskStringsLibrary> in its project, which registers them a layer under the app's catalog instead of in its place.

Every key

What each key says in English, and where it is drawn. A component's own props still win where it has them — Ui.Select.Empty("…"), Ui.DatePicker.Placeholder("…"), Ui.ConfirmLeave.Stay("…"): the catalog is what they say when you set nothing.

Key Where English
PickerPreviousMonth Calendar Previous month
PickerNextMonth Calendar Next month
PickerHour Time picker Hour
PickerMinute Time picker Minute
PickerSecond — (nothing reads it today) Second
PickerClear Time picker Clear
NotFoundTitle Not-found page Page not found
NotFoundBody Not-found page No route is registered for {0}.
NotFoundBackHome Not-found page Back to home
ErrorHeading Error page Something went wrong
ErrorTryAgain Error page Try again
ErrorReload Error page Reload this page
PaginationSummary Pagination Showing {0} to {1} of {2} results
PaginationPrevious Pagination « Previous
PaginationNext Pagination Next »
TableEmpty Table drawn from a query No results.
CalendarToday Calendar Today
DatePickerPlaceholder Date picker Select a date
DatePickerRangePlaceholder Date picker Select a date range
DatePickerConfirm Date picker Select date
DatePickerCancel Date picker Cancel
DatePickerMonth Date picker Month
DatePickerDay Date picker Day
DatePickerYear Date picker Year
DatePickerMonthPlaceholder Date picker mm
DatePickerDayPlaceholder Date picker dd
DatePickerYearPlaceholder Date picker yyyy
DateRangePresetToday Date picker Today
DateRangePresetYesterday Date picker Yesterday
DateRangePresetThisWeek Date picker This Week
DateRangePresetLastWeek Date picker Last Week
DateRangePresetLast7Days Date picker Last 7 Days
DateRangePresetThisMonth Date picker This Month
DateRangePresetLastMonth Date picker Last Month
DateRangePresetThisQuarter Date picker This Quarter
DateRangePresetLastQuarter Date picker Last Quarter
DateRangePresetThisYear Date picker This Year
DateRangePresetLastYear Date picker Last Year
DateRangePresetLast14Days Date picker Last 14 Days
DateRangePresetLast30Days Date picker Last 30 Days
DateRangePresetLast3Months Date picker Last 3 Months
DateRangePresetLast6Months Date picker Last 6 Months
DateRangePresetYearToDate Date picker Year to Date
DateRangePresetTomorrow Date picker Tomorrow
DateRangePresetNextWeek Date picker Next Week
DateRangePresetNext7Days Date picker Next 7 Days
DateRangePresetNextMonth Date picker Next Month
DateRangePresetNextQuarter Date picker Next Quarter
DateRangePresetNextYear Date picker Next Year
DateRangePresetNext14Days Date picker Next 14 Days
DateRangePresetNext30Days Date picker Next 30 Days
DateRangePresetNext3Months Date picker Next 3 Months
DateRangePresetNext6Months Date picker Next 6 Months
DateRangePresetAllTime Date picker All Time
DateRangePresetCustom Date picker Custom
SelectLoading Select Loading...
SelectEmpty Select No results found
SelectSearchPlaceholder Select Search...
SelectSearchClear Select Clear command input
SelectClear Select Clear selected
SelectSelectedSuffix Select selected
TimePickerPlaceholder Time picker Select a time
TimePickerMeridiem Time picker AM/PM
TimePickerHourPlaceholder Time picker hh
TimePickerMinutePlaceholder Time picker mm
EditorLabel Editor Rich text editor
EditorToolbar Editor Formatting
EditorBold Editor Bold
EditorItalic Editor Italic
EditorStrike Editor Strikethrough
EditorUnderline Editor Underline
EditorBullet Editor Bullet list
EditorOrdered Editor Ordered list
EditorBlockquote Editor Blockquote
EditorCode Editor Code
EditorHighlight Editor Highlight
EditorSubscript Editor Subscript
EditorSuperscript Editor Superscript
EditorUndo Editor Undo
EditorRedo Editor Redo
EditorLink Editor Insert link
EditorUnlink Editor Unlink
EditorAlign Editor Align
EditorAlignLeft Editor Left
EditorAlignCenter Editor Center
EditorAlignRight Editor Right
EditorHeading Editor Styles
EditorHeadingText Editor Text
EditorHeading1 Editor Heading 1
EditorHeading2 Editor Heading 2
EditorHeading3 Editor Heading 3
InputClear Input Clear input
InputCopy Input Copy to clipboard
InputTogglePassword Input Toggle password visibility
InputChooseFile Input Choose file
InputChooseFiles Input Choose files
InputNoFile Input No file chosen
ModalClose Modal Close modal
ConfirmLeaveStay Confirm leave Stay
ConfirmLeaveLeave Confirm leave Leave
OtpCharacter OTP input Character {0} of {1}
SliderRangeStart Slider {0} start range
SliderRangeEnd Slider {0} end range
SidebarToggle Sidebar Toggle sidebar
SidebarSearch Sidebar Search
CommandEmpty Command No results found
FileItemRemove File upload Remove file
ValidationRequired Validation This field is required.
ValidationWholeNumber Validation Enter a whole number.
ValidationNumber Validation Enter a number.
ValidationNumberRange Validation The number is out of range.
ValidationDate Validation Enter a valid date.
ValidationTime Validation Enter a valid time.
FormSaveFailed Form The save failed. Please try again.
ErrorReference Error page The problem has been recorded. If it keeps happening, quote this reference: {0}
HandlerFailed Toast That did not work. Please try again.
ErrorTitle Error page Application error
CarouselRole Carousel carousel
CarouselLabel Carousel Items
CarouselSlideRole Carousel slide
CarouselSlideLabel Carousel {0} of {1}
CarouselPrevious Carousel Previous slide
CarouselNext Carousel Next slide
CarouselIndicators Carousel Choose slide to display
CarouselShowSlide Carousel Show slide {0}
PhoneChangeCountry Phone Change country
ConnectionReconnecting Reconnect overlay Reconnecting…
ConnectionOffline Reconnect overlay You're offline — waiting to reconnect…
ConnectionStillTrying Reconnect overlay Still trying to reconnect…
ConnectionRetry Reconnect overlay Retry now
ConnectionReload Reconnect overlay Reload
ConnectionUpdating Reconnect overlay Updating…
ConnectionAuthenticating Reconnect overlay Authenticating…
ConnectionSessionTimedOut Reconnect overlay Your session timed out. Reload to continue.
CommandClear Command Clear command input
CommandClose Command Close command modal
HandlerForbidden Toast You do not have permission to do that.
PageForbidden Page You do not have permission to view this page.
ConfirmHeading Confirm Confirm
ConfirmYes Confirm Yes
ConfirmNo Confirm No
PdfPageNumber PDF foot (Rask.Pdf) {0} / {1}
Filters Filters Filters
FiltersClear Filters Clear filters
FiltersClearAll Filters Clear all
FiltersClose Filters Close
FilterRemove Filters Remove filter {0}
ColorPickerOpen Color picker Open color picker
ColorPickerOpenWith Color picker Open color picker, {0}
ColorPickerInput Color picker Color
ColorPickerPlaceholder Color picker Enter a color
ColorPickerArea Color picker Saturation and brightness
ColorPickerAreaRole Color picker 2D color picker
ColorPickerAreaValue Color picker Saturation {0}%, brightness {1}%
ColorPickerHue Color picker Hue
ColorPickerOpacity Color picker Opacity
ColorPickerValue Color picker Color value
ColorPickerSwatches Color picker Color swatches
ColorPickerSelected Color picker {0} selected
ColorPickerDropper Color picker Pick a color from the screen
ColorPickerClear Color picker Clear color
ColorPickerCancel Color picker Cancel
ColorPickerSelect Color picker Select
ValidationColor Validation Enter a valid color.
ColorSwatchRed Color picker Red
ColorSwatchOrange Color picker Orange
ColorSwatchAmber Color picker Amber
ColorSwatchYellow Color picker Yellow
ColorSwatchGreen Color picker Green
ColorSwatchTeal Color picker Teal
ColorSwatchSky Color picker Sky
ColorSwatchIndigo Color picker Indigo
ColorSwatchPurple Color picker Purple
ColorSwatchPink Color picker Pink
ColorSwatchRose Color picker Rose
ColorSwatchOrangeLight Color picker Orange light
ColorSwatchAmberLight Color picker Amber light
ColorSwatchLime Color picker Lime
ColorSwatchEmerald Color picker Emerald
ColorSwatchCyan Color picker Cyan
ColorSwatchIndigoLight Color picker Indigo light
ColorSwatchVioletLight Color picker Violet light
ColorSwatchPinkLight Color picker Pink light
ColorSwatchRoseLight Color picker Rose light
ColorSwatchStone Color picker Stone
ColorSwatchSlate Color picker Slate
ColorSwatchBlack Color picker Black
ColorSwatchWhite Color picker White
DatePickerConfirmRange Date picker Select range
DatePickerPresetsPlaceholder Date picker Choose predefined range...

Docker

The scaffolded image is Debian-based (mcr.microsoft.com/dotnet/aspnet) and ships ICU, so nothing to do. If you switch to an Alpine base, set InvariantGlobalization=false and install icu-libs — a container without them formats every culture identically.

See also

Confirm