BstTranslations 10.0.18

BstTranslations

Property-based translation system for ASP.NET Core. You define one C# class with one property per translatable string; values are loaded per culture from a backing store you control, with localizable DataAnnotations validators and an enum-translation attribute.

Setup

1. Implement ITranslation

A persisted translation row. Bring your own EF entity:

using BstTranslations.Models.Contracts;

public class Translation : ITranslation {
    public int Id { get; set; }
    public string Name { get; set; }
    public string DefaultValue { get; set; }
    public DateTimeOffset ValueUpdateTime { get; set; }

    public string ValuePt { get; set; }
    public string ValueEn { get; set; }

    public string GetValueForCulture(string cultureCode) => cultureCode switch {
        "en" => ValueEn,
        _    => ValuePt ?? DefaultValue
    };
}

2. Implement ITranslationsManager

Loads/persists translations from your storage (DB, file, etc.):

public class TranslationsManager : ITranslationsManager {
    public Task<List<ITranslation>> GetTranslations() { ... }
    public Task<ITranslation> GetTranslationByName(string name) { ... }
    public Task<ITranslation> AddTranslation(string name, string value = null) { ... }
}

3. Subclass BaseTranslationsService

One property per translation key. The default value passed to T(...) is what gets stored if the key doesn't exist yet:

public class AppTranslations(IHttpContextAccessor ctx, IServiceScopeFactory sf)
    : BaseTranslationsService(ctx, sf) {

    public HtmlString Welcome              => T("Bem-vindo");
    public HtmlString GreetingWithName     => T("Olá, {0}!");
    public HtmlString Required_Field       => T("Este campo é obrigatório");
}

4. Register

// BstLogger must already be registered.
services.AddTranslationsService<AppTranslations, TranslationsManager>(singleton: true);

singleton: true uses an in-memory cache shared across requests; false reloads per scope.

Usage

Translate in views/services

@inject AppTranslations T

<h1>@T.Welcome</h1>
<p>@T.GreetingWithName.Params(user.Name)</p>

Params() (from BstTranslations.Extensions) does string.Format on an HtmlString.

The culture is read from the culture route value (/{culture}/...). Override at runtime:

T.SetCulture("en");
T.SetDynamicCulture(true); // re-read culture from route on every T(...) call

Localizable validators

Use the Localizable* variants and pass the property name of the translation, not a literal message:

using BstTranslations.DataAnnotations.LocalizableValidators;

public class RegisterDto {
    [LocalizableRequired(nameof(AppTranslations.Required_Field))]
    [LocalizableMaxLength(50, nameof(AppTranslations.MaxLength_50))]
    public string Name { get; set; }

    [LocalizableEmailAddress(nameof(AppTranslations.Invalid_Email))]
    public string Email { get; set; }

    [LocalizableMinLength(8, nameof(AppTranslations.Password_TooShort))]
    public string Password { get; set; }

    [LocalizableCompare(nameof(Password), nameof(AppTranslations.Passwords_DoNotMatch))]
    public string PasswordConfirmation { get; set; }
}

The provided IValidationAttributeAdapterProvider resolves the property name to the current translation, both server-side and in jquery.validate unobtrusive output.

Enum translations

using BstTranslations.DataAnnotations;

public enum OrderStatus {
    [EnumWithTranslation(nameof(AppTranslations.Status_Pending))]   Pending,
    [EnumWithTranslation(nameof(AppTranslations.Status_Shipped))]   Shipped,
    [EnumWithTranslation(nameof(AppTranslations.Status_Delivered))] Delivered
}

@T.GetEnumTranslation(order.Status)

Sync translation keys to storage

TranslationsHelper.GetTranslationObjects reflects every property on your translations service into ITranslation rows so you can seed/upsert your store:

var rows = TranslationsHelper
    .GetTranslationObjects<AppTranslations, Translation>(appTranslations);
// upsert rows via your TranslationsManager / DbContext

Call T.UpdateTranslations() to refresh the in-memory cache (singleton mode) after changes.

No packages depend on BstTranslations.

.NET 10.0

Version Downloads Last updated
10.0.19 14 14/06/2026
10.0.18 5 05/06/2026
10.0.17 4 05/06/2026
10.0.16 3 05/06/2026
10.0.15 27 17/05/2026
10.0.14 10 03/05/2026
10.0.13 8 23/04/2026
10.0.12 9 16/04/2026
10.0.11 19 06/04/2026
10.0.10 9 20/03/2026
10.0.9 7 20/03/2026
10.0.8 9 20/03/2026
10.0.7 7 20/03/2026
10.0.6 25 11/03/2026
10.0.5 19 10/02/2026
10.0.4 11 28/01/2026
10.0.3 11 28/01/2026
10.0.2 28 12/12/2025
10.0.1 21 11/11/2025
9.2.4 17 06/11/2025
9.2.3 14 31/10/2025
9.2.2 12 20/10/2025
9.2.1 12 20/10/2025
9.2.0 14 15/10/2025
9.1.9 15 24/09/2025
9.1.8 25 06/09/2025
9.1.7 16 26/07/2025
9.1.6 18 15/07/2025
9.1.5 19 12/06/2025
9.1.4 51 19/05/2025
9.1.3 21 14/05/2025
9.1.2 30 09/04/2025
9.1.1 34 22/03/2025
9.1.0 20 19/03/2025
9.0.9 21 19/03/2025
9.0.8 19 19/03/2025
9.0.7 27 08/03/2025
9.0.6 19 05/03/2025
9.0.5 32 13/02/2025
9.0.4 20 12/02/2025
9.0.3 32 28/01/2025
9.0.2 26 23/01/2025
9.0.1 25 16/12/2024