Localization

Smartstore is an application where different languages can be easily downloaded and activated in the admin area. Over 30 languages are available for download in the backend via Configuration > Regional Settings > Languages. Activated languages are displayed in the frontend as well as in the backend. Administrators can edit translations in the back office or import and export XML packages.

Overview

Smartstore ships with a database-driven localization system that covers UI strings and entity properties. Each request is assigned a working language determined from the user preference, current store or route culture.

Languages

ILanguageService manages configured languages. The current language is available from the work context:

var language = _workContext.WorkingLanguage;

Key members of ILanguageService include:

  • IsMultiLanguageEnvironment(storeId) – detect if a store has more than one published language.

  • GetAllLanguages(includeHidden, storeId, tracked) / GetAllLanguagesAsync(...) – load all languages, optionally scoped to a store and including hidden ones.

  • IsPublishedLanguage(idOrSeoCode, storeId) / IsPublishedLanguageAsync(...) – check whether a language with the given ID or SEO code is published.

  • GetMasterLanguageSeoCode(storeId) / GetMasterLanguageSeoCodeAsync(...) – return the SEO code of the first active language.

  • GetMasterLanguageId(storeId) / GetMasterLanguageIdAsync(...) – return the ID of the first active language.

Resource strings

Text resources live in the LocaleStringResource table and can be retrieved through ILocalizationService or the T helper in controllers and views:

Annotating models

Attach the LocalizedDisplay attribute to model properties so labels pull their text from the resource table. By convention the resource key matches the property name:

Decorating the class with LocalizedDisplay lets you provide a prefix so the properties can use shorter keys:

Display hints

To show a tooltip next to a label, create a second resource with the .Hint suffix or specify it inline:

Enumerations

Values of enums are localized under the Enums namespace. Use Html.GetLocalizedEnumSelectList to populate a <select> element:

Localizing entities

Entity types that support translations implement ILocalizedEntity. Each property that should be translated must be annotated with [LocalizedProperty] so the framework can persist and display language-specific values:

LocalizedPropertyAttribute marks a property as translatable. The system scans these attributes to render language tabs in the admin UI, include fields in import/export packages, and detect changes for cache invalidation. Setting Translatable = false keeps the property in the metadata but hides it from the translation interface.

Entities can additionally be decorated with LocalizedEntityAttribute to provide a custom key group or filter predicate for tooling and import/export routines.

Use ILocalizedEntityService to read and store per-language values:

Descriptors and batch loading

A plugin for translations can gather text without querying individual modules. The ILocalizedEntityDescriptorProvider exposes metadata for every type that implements ILocalizedEntity. Each descriptor lists the entity's key group and all properties marked with [LocalizedProperty] or contributed by LocalizedSettingsLoader and LocalizedCookieInfoLoader.

ILocalizedEntityLoader uses these descriptors to load only the localizable properties for a given entity type. It supports paging so large data sets can be processed in small batches:

LocalizedProperty metadata

The LocalizedProperty table now carries audit information and translation metadata:

Property
Purpose

IsHidden

Marks master-language records that should not appear in the UI; translation plugins set this to true to hide redundant source text.

CreatedOnUtc, CreatedBy, UpdatedOnUtc, UpdatedBy

Filled by audit hooks; plugins that update records should set UpdatedOnUtc and UpdatedBy to keep their author information.

TranslatedOnUtc

Timestamp of the last translation. Entries with a null or older value can be picked up in the next translation run.

MasterChecksum

Hash of the source text used for the translation. If the hash changes the target value must be retranslated.

Tracking changes

To keep master texts in sync, a translation plugin can register an AsyncDbSaveHook<ILocalizedEntity>. The hook watches for changes to localized properties and either inserts missing LocalizedProperty rows or clears TranslatedOnUtc when a value is modified. This allows incremental translation sessions that only handle entities which actually changed.

Process large translation jobs in batches, detach entities between saves and use async/await for all I/O operations to reduce memory pressure and improve throughput.

Module localization

Modules bundle resource files and register them during installation. See the localizing modules guide for details.

Adding resources via migrations

When the core or a module introduces new text resources, they can be added through a FluentMigrator migration. Implement ILocaleResourcesProvider and IDataSeeder<SmartDbContext> on the migration, call MigrateLocaleResourcesAsync in SeedAsync, and use LocaleResourcesBuilder to insert or update keys:

During migrations these resource entries are merged into LocaleStringResource for all languages.

Last updated

Was this helpful?