Introduction
In today’s globalized digital ecosystem, web applications and APIs must cater to users across multiple countries, cultures, and languages. Whether you’re building a content management system, an e-commerce site, or a customer support portal, multi-language (or localization) support is no longer optional — it’s essential.
In this article, we’ll learn how to handle multi-language content in REST APIs using ASP.NET Core, with clear examples, architecture workflow, and best practices to maintain clean, scalable localization logic.
What is Multi-Language Content Handling?
Multi-language content handling means your API can serve the same data in different languages based on user preferences or system configuration.
For example
GET /api/products/101?lang=en
→ { "id": 101, "name": "Wireless Mouse" }
GET /api/products/101?lang=fr
→ { "id": 101, "name": "Souris sans fil" }
The key goal is to separate content from language, making the system easy to scale and maintain.
Technical Workflow (Flowchart)
flowchart TD
A[Client Request with 'lang' Parameter] --> B[API Middleware Detects Language]
B --> C[Load Language Resource (DB or JSON file)]
C --> D[Fetch Content in Preferred Language]
D --> E[Fallback to Default Language if Not Found]
E --> F[Return Localized JSON Response]
Approaches for Multi-Language Content
There are two common strategies to handle multi-language content in APIs:
1. Database Localization
You store content in multiple languages in the database.
Example Table
| ProductId | Language | Name | Description |
|---|
| 101 | en | Wireless Mouse | Ergonomic mouse design |
| 101 | fr | Souris sans fil | Souris ergonomique |
Pros
Cons
Slightly complex queries
Needs proper caching
2. File-Based Localization (Resource Files)
For static text (like labels, validation messages, etc.), use .resx or JSON resource files.
Example
/Resources
├── SharedResources.en.json
├── SharedResources.fr.json
SharedResources.en.json
{"Welcome": "Welcome to our application!","Logout": "Logout"}
SharedResources.fr.json
{"Welcome": "Bienvenue dans notre application!","Logout": "Se déconnecter"}
Step-by-Step Implementation in ASP.NET Core
Step 1: Add Localization Dependencies
Add this package to your project:
dotnet add package Microsoft.Extensions.Localization
Step 2: Configure Localization in Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[] { "en", "fr", "de", "hi" };
options.SetDefaultCulture("en");
options.AddSupportedCultures(supportedCultures);
options.AddSupportedUICultures(supportedCultures);
});
builder.Services.AddControllers();
var app = builder.Build();
var localizationOptions = app.Services.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(localizationOptions.Value);
app.MapControllers();
app.Run();
Step 3: Create a Resource File
Create a folder named Resources and add the following files:
HomeController.en.resx
| Name | Value |
|---|
| WelcomeMessage | Welcome to the API! |
HomeController.fr.resx
| Name | Value |
|---|
| WelcomeMessage | Bienvenue sur l'API! |
Step 4: Use Localizer in Controller
using Microsoft.Extensions.Localization;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly IStringLocalizer<HomeController> _localizer;
public HomeController(IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
}
[HttpGet("welcome")]
public IActionResult GetWelcomeMessage()
{
var message = _localizer["WelcomeMessage"];
return Ok(new { message });
}
}
Now call the API with header:
Accept-Language: fr
Response:
{"message": "Bienvenue sur l'API!"}
Step 5: Multi-Language Content from Database
If your content is dynamic (e.g., product names), structure your database like this:
CREATE TABLE Product (
Id INT PRIMARY KEY,
DefaultName NVARCHAR(200)
);
CREATE TABLE ProductTranslation (
ProductId INT,
LanguageCode NVARCHAR(10),
Name NVARCHAR(200),
Description NVARCHAR(1000)
);
Sample Query
SELECT p.Id,
ISNULL(pt.Name, p.DefaultName) AS Name
FROM Product p
LEFT JOIN ProductTranslation pt
ON p.Id = pt.ProductId AND pt.LanguageCode = @Lang
Handling Fallback Languages
Always include a fallback mechanism if a translation doesn’t exist.
Example in C#:
string localizedText = translations.FirstOrDefault(t => t.Language == lang)?.Text
?? translations.FirstOrDefault(t => t.Language == "en")?.Text;
Combining API + Angular Frontend
Angular sends a lang parameter or Accept-Language header.
API reads it and sends localized content.
Angular translates UI labels using ngx-translate while data (from API) comes already localized.
Angular Service Example
getProductDetails(id: number, lang: string): Observable<Product> {
return this.http.get<Product>(`/api/products/${id}?lang=${lang}`);
}
Performance Optimization Tips
Cache Translations
Use IMemoryCache or Redis for frequent translations.
Batch Translations
Load all localized fields in one query.
Avoid Overfetching
Only return localized fields required by the frontend.
Async Resource Loading
When using .resx, preload resource dictionaries asynchronously.
Common Accessibility and Localization Audit Checklist
| Area | Description |
|---|
| Content Separation | Text is not hardcoded in API responses |
| Default Language | System falls back to English or configured language |
| UTF-8 Support | Database and API both handle UTF-8 encoding |
| Dynamic Localization | API can handle runtime changes in preferred language |
| Header-Based Language | Supports Accept-Language header |
Conclusion
Implementing multi-language content handling in your ASP.NET Core REST APIs not only improves user experience but also opens your product to a global audience.
With resource-based localization for static text and database-driven translations for dynamic content, you can build a flexible, scalable architecture that supports any number of languages. Combine this with caching, proper culture handling, and smart fallbacks — and your API will be truly international-ready.