Reputation: 19
I have a web application with radzen blazor studio. I added localization to the application. So it added CulturePicker.Razor
page and CulturePicker.cs
class.
This was the CulturePicker.cs
class
<RadzenDropDown @bind-Value="@culture" TValue="string" Data="@(new [] { new { Text = "العربية (المملكة العربية السعودية)", Value = "ar-SA"}, new { Text = "English", Value = "en" } })"
TextProperty="Text" ValueProperty="Value" Change="@ChangeCulture" />
and this is the [Change="@ChangeCulture"]
method
protected void ChangeCulture()
{
var redirect = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, UriFormat.UriEscaped);
var query = $"?culture={Uri.EscapeDataString(culture)}&redirectUri={redirect}";
NavigationManager.NavigateTo("Culture/SetCulture" + query, forceLoad: true);
}
What I need is when the user changes the culture (language) the layout of the page (direction) change from RTL and LTR
Upvotes: 0
Views: 168
Reputation: 1
Not sure if the original poster found a solution, but here is what I use for the same situation, and it works for me. It is configured to set the text direction based on the value of the culture cookie.
First, in the App.razor file, at the start of the code section, declare a string property called TextDirection, and set the value to match the direction of the text of the default website culture, so in my case, the default is en-IE so it is set to ltr:
private string TextDirection { get; set; } = "ltr";
Next, against the html opening tag, set the dir value to the previously created property
<html lang="en" dir="@TextDirection">
Finally, you need to add some logic to the OnInitialized method. Inside the if (HttpContext != null) logic, you need to declare a string to hold the text direction you will be setting the page to, default it to the default culture text direction. Next, you need to look for the .AspNetCore.Culture cookie and grab the value, it is does not exist, set it to the default culture of the website in this format - "c=en-IE|uic=en-IE". You then need to extract the culture from the cookie value into another variable, then, if the culture is rtl, set the text direction variable to rtl. Lastly, compare the text direction variable to the text direction property, and if they are different, set the property to the value of the variable:
protected override void OnInitialized()
{
base.OnInitialized();
if (HttpContext != null)
{
string cultureTextDir = "ltr";
var cookieCulture = HttpContext.Request.Cookies[".AspNetCore.Culture"] ?? "c=en-IE|uic=en-IE";
string culture = cookieCulture.Split('|').FirstOrDefault(part => part.StartsWith("c="))?.Substring(2);
if (culture == "ar-AE")
{
cultureTextDir = "rtl";
}
if (TextDirection != cultureTextDir)
{
TextDirection = cultureTextDir;
}
var theme = HttpContext.Request.Cookies["BlankTemplateTheme"];
if (!string.IsNullOrEmpty(theme))
{
ThemeService.SetTheme(theme, false);
}
}
}
If the culture cookie doesn't exist, then the default value is used. So, as long as you set the default values correctly, this should work. Also to note, in my example I check if the culture is ar-AE (United Arab Emirates) and if it is, the test direction is set to rtl, you can replace this with whatever logic you see fit for determining the text direction of the culture.
Below is the full page for reference:
@inject NavigationManager NavigationManager
<!DOCTYPE html>
<html lang="en" dir="@TextDirection">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="@NavigationManager.BaseUri" />
<RadzenTheme @rendermode="@InteractiveServer" Theme="software" />
<link rel="stylesheet" href="css/site.css" />
<link rel="icon" href="favicon.ico" />
<HeadOutlet @rendermode="@(new InteractiveServerRenderMode(prerender: false))" />
</head>
<body>
<Routes @rendermode="@(new InteractiveServerRenderMode(prerender: false))" />
<script src="_framework/blazor.web.js"></script>
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
</body>
</html>
@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; }
[Inject]
private ThemeService ThemeService { get; set; }
private string TextDirection { get; set; } = "ltr";
protected override void OnInitialized()
{
base.OnInitialized();
if (HttpContext != null)
{
string cultureTextDir = "ltr";
var cookieCulture = HttpContext.Request.Cookies[".AspNetCore.Culture"] ?? "c=en-IE|uic=en-IE";
string culture = cookieCulture.Split('|').FirstOrDefault(part => part.StartsWith("c="))?.Substring(2);
if (culture == "ar-AE")
{
cultureTextDir = "rtl";
}
if (TextDirection != cultureTextDir)
{
TextDirection = cultureTextDir;
}
var theme = HttpContext.Request.Cookies["BlankTemplateTheme"];
if (!string.IsNullOrEmpty(theme))
{
ThemeService.SetTheme(theme, false);
}
}
}
}
Hope this helps.
Upvotes: 0
Reputation: 16031
See my update below. I think it's somewhat ugly but it might be a workaround as it really work. I create a js method in App.razor component, which will call a .Net method. In the .Net method, it will change the direction of body element. Then when the culture dropdown option changed, it will change the direction to rlt, then a navigation will apply the change so that you will see it's chagned. If there's no navigation, you need to call SetRTL()
method as well. I tried to use StateHasChanged()
but it can't make the chagne applied. I tried to use Cascading parameter but I failed. I trust there will be a better solution but I've tried my best.
protected async Task ChangeCulture()
{
await JS.InvokeVoidAsync("SetRtl");
// SetRTL();
_navigation.NavigateTo("/counter" + query, forceLoad: true);
}
<body dir="@CurrentDirection">
<Routes />
<script src="_framework/blazor.web.js"></script>
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
<script>
window.SetRtl = () => {
DotNet.invokeMethodAsync('BlazorWebAppRadzen', 'changeDirection');
}
</script>
</body>
</html>
@code{
public static string CurrentDirection = "ltr";
[JSInvokable]
public static void changeDirection()
{
CurrentDirection = "rtl";
}
}
==============================
Firstly, I found radzen-blazor-components-v5 already support rtl appearence, the document mentioned
One of the most significant updates in this major version is the introduction of the highly anticipated Right-to-Left (RTL) support. All Radzen Blazor Components now fully support RTL direction .... To enable it, just add dir=”rtl” attribute to the html tag in your layout.
Following this action plan, I found this case which could work well in blazor app, no matter we used Radzen or not. I had a test with a new .net 8 blazor web app and adding codes below in Whether.razor component and it worked. You can also add the methods into your ChangeCulture
method.
@page "/weather"
@attribute [StreamRendering]
@rendermode InteractiveServer
@inject IJSRuntime JS
<PageTitle>Weather</PageTitle>
<h1>Change Direction</h1>
<button @onclick=SetRTL>
RTL
</button>
<button @onclick=SetLTR>
LTR
</button>
@code {
void SetDIR(string direction)
{
if (JS is IJSInProcessRuntime sr)
sr.InvokeVoid("document.body.setAttribute", "dir", direction);
else
JS.InvokeVoidAsync("document.body.setAttribute", "dir", direction);
}
void SetRTL() => SetDIR("rtl");
void SetLTR() => SetDIR("ltr");
}
Then I also found this sample using Radzen ThemeService
. It requires to inject @inject ThemeService ThemeService
and call ThemeService.SetRightToLeft({true/false});
to change the view.
Upvotes: 0