<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bonzer Web]]></title><description><![CDATA[Bonzer Web]]></description><link>https://bonzer-web.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 08 Sep 2026 02:41:14 GMT</lastBuildDate><atom:link href="https://bonzer-web.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Implement Localization in Blazor (.NET 8) with English and Arabic Support]]></title><description><![CDATA[Localization is not a “nice-to-have” feature anymore. If your Blazor application targets users in multiple regions, hardcoded UI text will become technical debt very quickly.
In this article, I’ll walk through a clean and production-ready approach to...]]></description><link>https://bonzer-web.hashnode.dev/how-to-implement-localization-in-blazor-net-8-with-english-and-arabic-support</link><guid isPermaLink="true">https://bonzer-web.hashnode.dev/how-to-implement-localization-in-blazor-net-8-with-english-and-arabic-support</guid><category><![CDATA[blazor-web-app]]></category><category><![CDATA[blazor server app]]></category><category><![CDATA[localization]]></category><category><![CDATA[Blazor]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Mohsin Afzal]]></dc:creator><pubDate>Thu, 18 Dec 2025 08:19:06 GMT</pubDate><content:encoded><![CDATA[<p>Localization is not a “nice-to-have” feature anymore. If your Blazor application targets users in multiple regions, hardcoded UI text will become technical debt very quickly.</p>
<p>In this article, I’ll walk through a <strong>clean and production-ready approach</strong> to implementing localization in a Blazor Web Application using <strong>.NET 8</strong>, with support for <strong>English (en-US)</strong> and <strong>Arabic (ar-SA)</strong>.</p>
<p>This setup is simple, scalable, and suitable for real-world projects.</p>
<h3 id="heading-what-this-guide-covers">What This Guide Covers</h3>
<ul>
<li><p>Resource-based localization using <code>.resx</code> files</p>
</li>
<li><p>Switching UI culture at runtime</p>
</li>
<li><p>Persisting the selected culture using cookies</p>
</li>
<li><p>Handling Arabic calendars correctly</p>
</li>
<li><p>Using shared resources across components</p>
</li>
</ul>
<h3 id="heading-step-1-create-localization-resources">Step 1: Create Localization Resources</h3>
<p>Start by creating a folder named <strong>Resources</strong>.</p>
<p>Inside it, add the following files:</p>
<ul>
<li><p><code>SharedResource.cs</code> (empty marker class)</p>
</li>
<li><p><code>SharedResource.en-US.resx</code></p>
</li>
<li><p><a target="_blank" href="http://SharedResource.ar"><code>SharedResource.ar</code></a><code>-SA.resx</code></p>
</li>
</ul>
<p>The <code>SharedResource</code> class is used to group common localized strings across the application.</p>
<h3 id="heading-example-resource-entry">Example Resource Entry</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Key</td><td>en-US</td><td>ar-SA</td></tr>
</thead>
<tbody>
<tr>
<td>WelcomeText</td><td>Welcome to the Localization Example</td><td>مرحبًا بك في مثال الترجمة</td></tr>
</tbody>
</table>
</div><p>Important rule:<br />👉 <strong>Keys must be identical across all language files</strong>.</p>
<hr />
<h3 id="heading-step-2-configure-localization-in-programcs">Step 2: Configure Localization in Program.cs</h3>
<p>Register localization services:</p>
<pre><code class="lang-csharp">builder.Services.AddLocalization();
</code></pre>
<p>Define supported cultures and configure middleware:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> enCulture = <span class="hljs-keyword">new</span> CultureInfo(<span class="hljs-string">"en-US"</span>)
{
    DateTimeFormat = { Calendar = <span class="hljs-keyword">new</span> GregorianCalendar() }
};

<span class="hljs-keyword">var</span> arCulture = <span class="hljs-keyword">new</span> CultureInfo(<span class="hljs-string">"ar-SA"</span>)
{
    DateTimeFormat = { Calendar = <span class="hljs-keyword">new</span> UmAlQuraCalendar() }
};

<span class="hljs-keyword">var</span> supportedCultures = <span class="hljs-keyword">new</span>[] { enCulture, arCulture };

app.UseRequestLocalization(options =&gt;
{
    options.DefaultRequestCulture =
        <span class="hljs-keyword">new</span> RequestCulture(enCulture);

    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
});
</code></pre>
<p>This ensures correct date formatting and UI behavior for both cultures.</p>
<hr />
<h3 id="heading-step-3-persist-culture-selection-using-cookies">Step 3: Persist Culture Selection Using Cookies</h3>
<p>Blazor does not persist culture changes by default. To handle this, we store the selected culture in a cookie.</p>
<p>Create a JavaScript file named <strong>localization.js</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setCultureCookie</span>(<span class="hljs-params">culture</span>) </span>{
    <span class="hljs-built_in">document</span>.cookie =
        <span class="hljs-string">`.AspNetCore.Culture=c=<span class="hljs-subst">${culture}</span>|uic=<span class="hljs-subst">${culture}</span>;path=/;max-age=2592000`</span>;
    location.reload();
}
</code></pre>
<p>This ensures the selected culture survives page reloads and navigation.</p>
<hr />
<h3 id="heading-step-4-inject-the-localizer-globally">Step 4: Inject the Localizer Globally</h3>
<p>To avoid repeating injections in every component, add this to <strong>_Imports.razor</strong>:</p>
<pre><code class="lang-plaintext">@inject IStringLocalizer&lt;SharedResource&gt; Localizer
</code></pre>
<p>Now the localizer is available across all Razor components.</p>
<hr />
<h3 id="heading-step-5-switch-language-from-the-ui">Step 5: Switch Language from the UI</h3>
<p>In <strong>MainLayout.razor</strong>, inject JavaScript runtime and add a toggle button:</p>
<pre><code class="lang-plaintext">@inject IJSRuntime JSRuntime

&lt;button @onclick="ToggleCulture"&gt;
    @Localizer["ToggleLanguage"]
&lt;/button&gt;

@code {
    private async Task ToggleCulture()
    {
        var currentCulture =
            CultureInfo.CurrentCulture.Name;

        var newCulture =
            currentCulture == "en-US"
                ? "ar-SA"
                : "en-US";

        await JSRuntime.InvokeVoidAsync(
            "setCultureCookie",
            newCulture);
    }
}
</code></pre>
<p>This provides a simple and predictable way to switch languages.</p>
<h2 id="heading-step-6-use-localized-text-in-components">Step 6: Use Localized Text in Components</h2>
<p>Example usage in <strong>Home.razor</strong>:</p>
<pre><code class="lang-plaintext">&lt;h1&gt;@Localizer["Welcome"]&lt;/h1&gt;
&lt;p&gt;@Localizer["ExampleText"]&lt;/p&gt;
</code></pre>
<p>All UI text now comes from centralized resource files.</p>
<h2 id="heading-source-code">Source Code</h2>
<p>The complete working example is available on GitHub:</p>
<p><a target="_blank" href="https://github.com/mafzal88/BlazorLocalization">👉 [GitHub Repository Link]</a></p>
<p>You can clone it, run it, and adapt it to your own projects.</p>
<hr />
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>This approach keeps localization:</p>
<ul>
<li><p>Centralized</p>
</li>
<li><p>Easy to maintain</p>
</li>
<li><p>Scalable for additional languages</p>
</li>
</ul>
<p>If you’re building multilingual Blazor applications, setting this up early will save you from painful refactoring later.</p>
]]></content:encoded></item></channel></rss>