Toolbelt.Blazor.I18nText

repository·master·Indexed 43 days ago

https://github.com/jsakamoto/toolbelt.blazor.i18ntext

A localization library for Blazor Web Apps that replaces standard .resx files with simple JSON or CSV files. It utilizes C# source generators to provide strongly-typed 'Text Table' classes for IntelliSense and easy maintenance. Features include support for SSR via cookie persistence, configurable fallback languages, and an I18nText service for managing current language settings.

Tokens
2.9K
Snippets
12
Records
12
Agent score
55%

What's inside Toolbelt.Blazor.I18nText

  1. Create localized text source files

    master

    Create an i18ntext folder in your project root. Inside, add localized text source files for each language using either JSON or CSV formats.

    Requirements:

    • Files must be encoded in UTF-8.
    • JSON format: Must be a simple key-value object.
    • CSV format: Must be a 2-column file without a header row.

    Naming Convention: The filename must follow the pattern: <Text Table Name>.<Language Code>.{json|csv}.

    Example: For a Text Table named MyText in English, use MyText.en.json or MyText.en.csv.

    {
      "Key1": "Localized text 1",
      "Key2": "Localized text 2"
    }
    Key1,Localized text 1
    Key2,Localized text 2
  2. Configure the I18nText service in Program.cs

    master

    Register the I18nText service in your Program.cs.

    Persistence Settings:

    • If your app uses SSR (Server-Side Rendering) or Server-side Pre-rendering, you must use PersistanceLevel.Cookie to maintain language settings across requests.
    • For apps without SSR, you can use PersistanceLevel.Session or other options.

    Middleware for SSR/Pre-rendering: If using cookies or SSR, you must also configure and use the RequestLocalization middleware.

    // 1. Register the service
    using Toolbelt.Blazor.Extensions.DependencyInjection;
    
    builder.Services.AddI18nText(
        options => options.PersistenceLevel = PersistanceLevel.Cookie);
    
    // 2. Configure RequestLocalization (Required for SSR/Cookies)
    builder.Services.Configure<RequestLocalizationOptions>(options =>
    {
        var supportedCultures = new[] { "en", "ja" };
        options.DefaultRequestCulture = new("en");
        options.AddSupportedCultures(supportedCultures);
        options.AddSupportedUICultures(supportedCultures);
    });
    
    var app = builder.Build();
    
    // 3. Use the middleware
    app.UseRequestLocalization();
  3. Use a Text Table in a Blazor component

    master

    To use localized text in a .razor component:

    1. Inject the Toolbelt.Blazor.I18nText.I18nText service.
    2. Declare a field for your generated Text Table class (e.g., MyText). Note that the namespace is <your_project_namespace>.I18nText.
    3. In OnInitializedAsync, call GetTextTableAsync<T>(this) to populate the table.
    4. Access text via properties (for IntelliSense) or the indexer (for dynamic keys).
    @inject Toolbelt.Blazor.I18nText.I18nText I18nText
    
    <h1>@MyText.HelloWorld</h1>
    <p>@MyText["DynamicKey"]</p>
    
    @code {
        private I18nText.MyText MyText = new();
    
        protected override async Task OnInitializedAsync()
        {
            MyText = await I18nText.GetTextTableAsync<I18nText.MyText>(this);
        }
    }
  4. Build the project to generate Typed Text Tables

    master

    The library uses a C# source generator to create a "Typed Text Table class" based on your source files.

    • Visual Studio IDE: The source generator works automatically in the background; you usually do not need to build explicitly.
    • dotnet CLI: Use dotnet watch to automatically recompile the source generator whenever you update your .json or .csv files.
    dotnet watch
  5. Disable JavaScript file cache busting

    master

    The library appends a version query string to its JavaScript file URL to prevent browsers from using cached versions when the library is updated.

    .NET 8 and 9

    Cache busting is always enabled and cannot be disabled.

    .NET 10 or later

    You can disable the version query string by setting the TOOLBELT_BLAZOR_I18NTEXT_JSCACHEBUSTING environment variable to 0 in your Program.cs.

    Note for Blazor WebAssembly: When publishing a Blazor WebAssembly app, the environment variable is ignored because published standalone apps do not include import map entries for NuGet package JavaScript files. To disable cache busting in published Blazor WebAssembly apps, you must set the ToolbeltBlazorI18nTextJavaScriptCacheBusting MSBuild property to false in your .csproj file.

    // Program.cs
    // Disable appending a version query string for the i18n text library's JavaScript file.
    Environment.SetEnvironmentVariable("TOOLBELT_BLAZOR_I18NTEXT_JSCACHEBUSTING", "0");
    <!-- Project file (.csproj) for Blazor WebAssembly -->
    <PropertyGroup>
      <ToolbeltBlazorI18nTextJavaScriptCacheBusting>false</ToolbeltBlazorI18nTextJavaScriptCacheBusting>
    </PropertyGroup>
  6. Configure I18nTextOptions

    master

    Use I18nTextOptions during service registration to control how the language is initialized, persisted, and how resources are fetched.

    Persistence Settings

    Control where the selected language is stored using the PersistenceLevel property. This determines the behavior of the default PersistCurrentLanguageAsync implementation.

    ValueDescription
    NoneThe language code will not persist anywhere.
    SessionThe language code will persist in the web browser's session storage. (Default)
    SessionAndLocalThe language code will persist in both session and local storage.
    CookieThe language code will persist in the web browser's cookie storage.
    PersistentCookieThe language code will persist in cookies with a long expiration date.
    NOTE

    If your Blazor app uses SSR (Server-Side Rendering), use PersistanceLevel.Cookie to ensure language settings are maintained across SSR areas.

    Blazor WebAssembly Specifics

    If you are using Blazor WebAssembly, you can configure how the service fetches JSON resource files via an HttpClient:

    • HttpClientName: Specifies the name of the HttpClient used to fetch JSON files. Defaults to "Toolbelt.Blazor.I18nText.HttpClient".
    • ConfigureHttpClient: A delegate used to configure the named HttpClient created from IHttpClientFactory. If set to null, the service will not register a named HttpClient to DI.
    services.AddI18nText(options => {
        options.PersistenceLevel = PersistanceLevel.Cookie;
        options.HttpClientName = "MyCustomClient";
        options.ConfigureHttpClient = (sp, client) => {
            client.BaseAddress = new Uri("https://api.example.com/");
        };
    });
  7. Configure the fallback language

    master

    The fallback language is determined at compile time. By default, the fallback language is set to en. To use a different language as the fallback, add the <I18nTextFallBackLanguage> MSBuild property to your project file (.csproj) and set it to your desired language code.

    <PropertyGroup>
      <I18nTextFallBackLanguage>fr</I18nTextFallBackLanguage>
    </PropertyGroup>
  8. Manage current language with I18nText service

    master

    The I18nText service (namespace Toolbelt.Blazor.I18nText) is the primary interface for managing the application's current language.

    • GetCurrentLanguageAsync(): Returns the current language code (e.g., detected from browser settings or previously set via SetCurrentLanguageAsync).
    • SetCurrentLanguageAsync(string langCode): Changes the current language code. By default, this value is stored in the browser's session storage so it can be restored when the app is reloaded.
    • ChangeLanguage: An event (EventHandler<I18nTextChangeLanguageEventArgs>) that is invoked after the language has changed, but before the component state has updated.
    // Example: Changing language in a component
    await i18nText.SetCurrentLanguageAsync("fr-FR");
    
    // Example: Getting current language
    string currentLang = await i18nText.GetCurrentLanguageAsync();
  9. Register the I18nText service with AddI18nText()

    master

    To use the internationalization features in your Blazor application, you must register the I18nText service into the .NET Core Dependency Injection (DI) system using the AddI18nText() extension method. You can optionally provide an Action<I18nTextOptions> to customize the service behavior during registration.

    // Register with default configuration
    services.AddI18nText();
    
    // Register with custom configuration
    services.AddI18nText(options => {
        // Customize options here
    });
  10. Retrieve localized text with GetTextTableAsync<T>()

    master

    To access your localized strings, use the GetTextTableAsync<T>(ComponentBase component) method.

    • Type Parameter T: This must be the class auto-generated from your localized text source files during the build process.
    • Automatic Refresh: When you call SetCurrentLanguageAsync(...), the I18nText service automatically calls StateHasChanged() on the component passed as the first argument. This ensures the UI refreshes immediately with the new language's text.

    Fields within the returned T object are populated from the JSON resource file corresponding to the current language code.

    // Inside a Blazor component
    protected override async Task OnInitializedAsync() 
    {
        // T is your auto-generated class
        textTable = await I18nText.GetTextTableAsync<MyTextTable>(this);
    }
    
    // In the markup
    <p>@textTable.WelcomeMessage</p>