Translation
Learn how to translate your Spiderly app using JSON files and IStringLocalizer.
Overview
Spiderly uses a runtime, JSON-based translation system powered by .NET's IStringLocalizer. Translation files are flat key-value JSON files stored in your project, and IStringLocalizer is automatically injected into all generated services and controllers.
Key features:
- JSON files in
Backend\YourAppName.Shared\Translations\named by language tag (e.g.,en.json,sr-Latn-RS.json) - Automatic injection — generated services and controllers receive
IStringLocalizervia constructor injection - Graceful fallback — if no translations are configured, the app still works (keys are returned as-is)
Registration
Enable translations in your Program.cs using the SpiderlyBuilder:
services.AddSpiderly<YourDbContext>(spiderly =>
{
spiderly.UsePostgreSQL(); // or UseSQLServer()
// Enable the built-in JSON file-based localizer
spiderly.UseTranslations();
// Set the default culture (English by default)
spiderly.UseCulture("sr-Latn-RS");
});UseTranslations
Two overloads are available:
spiderly.UseTranslations()— Registers the built-inJsonStringLocalizer, which loads{culture}.jsonfiles from theTranslationsdirectory at runtime.spiderly.UseTranslations<TLocalizer>()— Registers a customIStringLocalizerimplementation (e.g., database-backed translations).
If neither is called, Spiderly registers a PassthroughStringLocalizer that returns the key itself as the value — so the app works without any translation configuration.
UseCulture
// Single language:
spiderly.UseCulture("sr-Latn-RS");
// Multiple languages (first = default):
spiderly.UseCulture("sr-Latn-RS", "en");When multiple cultures are provided, per-request culture resolution is enabled via:
Accept-Languageheader- Query string:
?culture=sr-Latn-RS - Cookie
Translation Keys
Spiderly uses the following key conventions for entities and properties:
Entity Keys
| Key pattern | Purpose | Example |
|---|---|---|
{EntityName} | Singular name (forms, labels) | "Product" |
{EntityName}List | Plural name (table titles) | "ProductList" |
{EntityName}ExcelExportName | Excel export filename | "ProductExcelExportName" |
Property Keys
| Key pattern | Purpose | Example |
|---|---|---|
{PropertyName} | Input labels, validation messages | "Name", "CreatedAt" |
When you run spiderly init, the CLI seeds an en.json file with framework keys (Name, Description, CreatedAt, ModifiedAt, etc.). You only need to add translations for your own entities and properties.
Example
Given this entity:
public class UserExtended : BusinessObject<long>
{
public string Email { get; set; }
}Create Backend\YourAppName.Shared\Translations\en.json:
{
"Email": "Email address",
"UserExtended": "User",
"UserExtendedExcelExportName": "Users",
"UserExtendedList": "Users"
}And Backend\YourAppName.Shared\Translations\sr-Latn-RS.json:
{
"Email": "Email adresa",
"UserExtended": "Korisnik",
"UserExtendedExcelExportName": "Korisnici",
"UserExtendedList": "Korisnici"
}Adding a New Language
Create a new file, e.g., Backend\YourAppName.Shared\Translations\de.json, add your translations, and register the culture:
spiderly.UseCulture("en", "sr-Latn-RS", "de");Using Translations in Backend Code
IStringLocalizer is automatically injected into all generated services and controllers. In your custom code, inject it via the constructor:
public class ProductService
{
private readonly IStringLocalizer _localizer;
public ProductService(IStringLocalizer localizer)
{
_localizer = localizer;
}
public string GetProductLabel()
{
// Returns translated value, or the key itself if not found
return _localizer.Translate("Product");
}
}Helper Extensions
Spiderly provides two extension methods on IStringLocalizer:
| Method | Description |
|---|---|
_localizer.Translate(key) | Returns the translated value, or the key itself if not found |
_localizer.GetExcelTranslation(excelKey, pluralKey) | Tries the Excel-specific key first, falls back to the plural key |
// Translate a key
string label = _localizer.Translate("Product");
// Excel filename with fallback
string filename = _localizer.GetExcelTranslation("ProductExcelExportName", "ProductList");
// Returns "Proizvodi" if ProductExcelExportName has a translation,
// otherwise falls back to the ProductList translationExcel Export
The ExcelService.FillReportTemplateAsync method accepts IStringLocalizer for translating column headers. Generated Excel export endpoints automatically pass the injected localizer:
return File(
fileContent,
SettingsProvider.Current.ExcelContentType,
Uri.EscapeDataString($"{_localizer.GetExcelTranslation("ProductExcelExportName", "ProductList")}.xlsx")
);The {EntityName}ExcelExportName key controls the filename. If left empty, it falls back to {EntityName}List. If that's also empty, the key is used as-is.
FluentValidation Integration
When translations are enabled, FluentValidation automatically uses IStringLocalizer to resolve property display names. For example, if "BirthDate" is translated to "Birth Date", validation messages will say "Birth Date is required" instead of "BirthDate is required".
This is handled by the generated TranslatePropertiesConfiguration class — no manual setup needed.
Changing Default Language
To change the default language, call UseCulture() in your builder (see Registration). Then update the Angular frontend in Frontend\src\app\app.config.ts to match:
provideTransloco({
config: {
availableLangs: ['sr-Latn-RS'],
defaultLang: 'sr-Latn-RS',
reRenderOnLangChange: true,
},
loader: SpiderlyTranslocoLoader
}),Custom Frontend Translations
You only need to add custom frontend translations if your app supports multiple languages. If you're only using a single language, you can simply use hardcoded strings.
Add a Translation Key-Value Pair
Open the appropriate language file under Frontend\src\assets\i18n folder, for example: en.json.
Then, add a new key-value entry like this anywhere in the file: "KeyForTranslation": "Translated text".
You can now reference this key in your TypeScript or HTML files.
Use Translation in TypeScript (.ts)
Inject the TranslocoService and use its translate method:
// ... other imports
import { TranslocoService } from '@jsverse/transloco';
@Component({
templateUrl: './your.component.html',
})
export class YourComponent {
constructor(
// ... other injections
private translocoService: TranslocoService
) {}
ngOnInit() {
const translatedText = this.translocoService.translate('KeyForTranslation');
}
}Use Translation in HTML (.html)
Add TranslocoDirective into Angular component imports:
@Component({
templateUrl: './your.component.html',
imports: [
// ... other imports
TranslocoDirective,
],
})
export class YourComponent {
// ...
}Use the directive with Angular's *transloco syntax:
<ng-container *transloco="let t">
{{t('KeyForTranslation')}}
</ng-container>Custom Backend Translations
You only need to add custom backend translations if your app supports multiple languages. If you're only using a single language, you can simply use hardcoded strings.
To use custom backend translations, add your keys to the JSON translation files and resolve them with IStringLocalizer:
// Add to en.json: "YourExceptionKey": "Your exception message."
// Add to sr-Latn-RS.json: "YourExceptionKey": "Vaša poruka o grešci."
throw new Exception(_localizer.Translate("YourExceptionKey"));Spiderly automatically resolves the correct translation based on the active culture.