Introduction
In the ever-evolving landscape of infrastructure management, the demand for efficient, scalable, and reliable solutions has never been higher. As organizations increasingly embrace cloud-native architectures and adopt Infrastructure as Code (IaC) principles, the role of infrastructure professionals has expanded, presenting new challenges in the development and maintenance of infrastructure configurations.
The Challenges Faced by Infrastructure Professionals
Enter Infra Copilot
What is Infra Copilot?
In response to these challenges, Leveraging GitHub Copilot to generate infra code specifically for infrastructure professionals—Infra Copilot. Infra Copilot is helping to revolutionize the way infrastructure is written, addressing the pain points experienced by professionals in the field.
The Significance of Infra Copilot
Infra Copilot in Action
Prerequisites
1.Install visual studio code latest version - https://code.visualstudio.com/download
Below is the PowerShell code generated using VS Code & GitHub Copilot. It demonstrates how to create a simple Azure VM.
We're employing a straightforward prompt with #, with the underlying code automatically generated within the VS Code editor.
Another example to create azure vm with vm scale set with minimum and maximum number of instance count. Prompt used with # in below example.
The PowerShell script generated above can be executed either from the local system or from the Azure Portal Cloud Shell. Similarly, we can create Terraform and devops code using this Infra Copilot.
Conclusion
In conclusion, Infra Copilot emerges as a game-changer in the realm of infrastructure as code, alleviating the challenges faced by professionals and ushering in a new era of efficiency and collaboration. As we wrap up our exploration of Infra Copilot's capabilities, the preceding examples have provided insight into its features, supported technologies, and practical applications. This comprehensive guide aims to equip infrastructure professionals with the knowledge to enhance their IaC workflows effectively.
Coté interviews Jana Werner, Enterprise Transformation Lead EMEA, from Amazon Web Services (AWS). How can you start small changes to make big changes? That's the premise of Jana Werner's organization transformation card game. Sure, it's not really a "game," but each question is meant to help nudge management and executives a little closer to changing how they operate. Many of the ideas come from Amazon thinking, but many of the are also just the type of common sense that's too often uncommonly practiced. Coté interviews her about some of the cards, but, more importantly, the thinking, management philosophy, the life-style behind the cards.
Here's the text of the all the cards:
Mechanism
Culture
Organisation
Leadership
Special Guest: Jana Werner.
In this article, we will learn how to localize Blazor applications using resource files.
The solution shown in this article works for Blazor Server and the new Blazor Web App project template of .NET 8. However, it does not work for WebAssembly projects.
You can access the code used in this example on GitHub.
We’re going to implement localization for a Blazor web application. It will allow us to translate the web app into multiple languages.
The completed project will look like this. It contains a language selector on the top right and displays the menu options on the left as well as the content of the Home page in the selected language.
Since we’re using .NET, we don’t have to reinvent the wheel. Our solution builds on top of the Microsoft.Extensions.Localization package.
In a newly created Blazor project based on .NET 8’s single project Blazor Web App project template, we install the package.
Next, we open the Program.cs file and add the required services to the service container.
builder.Services.AddLocalization();
We also need to set up the localization middleware on the application host. I suggest setting it up right after the builder.Build()
call to make sure that the localization middleware runs as early as possible.
string[] supportedCultures = ["en-US", "de-CH"];
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
We need to configure the UseRequestLocalization
method with a RequestLocalizationOptions
object. We use collection initializers and add en-US
and de-CH
as cultures. We then use the array to populate the required options.
We create a Locales
folder that will contain our translated texts. Inside this folder, we create a new resource file and name it Resources.resx
.
The resource system in .NET works with a custom tool. We need to open the file properties in the Solution Explorer and set the PublicResXFileCodeGenerator
as the custom tool.
It comes with Visual Studio and should be installed out of the box. When we save the file, a designer file should be generated in the background. Whenever we add a resource to the dictionary and save the file, the designer file should be regenerated.
Hint: Sometimes, the designer file won’t be generated. You can either unload and reload the project in Visual Studio or restart Visual Studio. Most of the time, this will fix the issue. Otherwise, you might want to restart your computer.
Let’s add the resources we need for this demo application.
Next, we want to specify the culture of this resource file in its file name. We rename it from Resources.resx
to Resources.en-US.resx
. I learned that if we create the file with this name from the beginning, we have even more issues with the designer file generation.
We also create another resource file and name it Resources.de-CH.resx
where we will store the German translations.
Now, we’re ready to use the localized strings in our Blazor application.
In the Home
page component, we replace the file content with the following code:
@page "/"
@using Microsoft.Extensions.Localization
@using BlazorLocalization.Locales;
@using System.Globalization
@inject IStringLocalizer<Resources> localizer
<PageTitle>@localizer["Home"]</PageTitle>
@Thread.CurrentThread.CurrentCulture;
@Thread.CurrentThread.CurrentUICulture;
<h1>@localizer["HomeTitle"]</h1>
@localizer["HomeText"]
We need a few using statements providing access to the Localization
namespace as well as our Resources
class containing the localized strings.
Hint: We can also move the using statements into the
_Imports.razor
file. It will allow us to access the classes within these namespaces without explicitly adding a using statement in each component.
Next, we use the inject directive to create an instance of the generic IStringLocalizer
class. We provide our Resources
class as the generic type argument.
The localizer
exposes an indexer, providing us access to the translated strings. We use the following syntax to access the value in the HomeTitle
token:
@localizer["HomeTitle"]
Accessing translated strings using the string localizer is straightforward.
We also want to use the string localizer in the NavMenu
component to translate the menu items. We use the following code in the NavMenu.razor
file:
@using Microsoft.Extensions.Localization
@using BlazorLocalization.Locales;
@using System.Globalization
@inject IStringLocalizer<Resources> localizer
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">Blazor Localization</a>
</div>
</div>
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> @localizer["MenuHome"]
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> @localizer["MenuCounter"]
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="weather">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> @localizer["MenuWeather"]
</NavLink>
</div>
</nav>
</div>
Again, we have a few using statements, and we use the indexer of the localizer
variable of the generic type IStringLocalizer
with the Resources
class as its type argument.
Now that we have the translated texts in our resources files and know how to access the information in Blazor components, we want to be able to change cultures from within the Blazor application.
We create a new component in the Layouts
folder, and name it CultureSelector
, and insert the following code:
@inject NavigationManager Navigation
@using System.Globalization
<div>
<select @bind="Culture">
<option value="en-US">English</option>
<option value="de-CH">German</option>
</select>
</div>
@code
{
protected override void OnInitialized()
{
Culture = CultureInfo.CurrentCulture;
}
private CultureInfo Culture
{
get
{
return CultureInfo.CurrentCulture;
}
set
{
if (CultureInfo.CurrentCulture != value)
{
var uri = new Uri(Navigation.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var cultureEscaped = Uri.EscapeDataString(value.Name);
var uriEscaped = Uri.EscapeDataString(uri);
var fullUri = $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}";
Navigation.NavigateTo(fullUri, forceLoad: true);
}
}
}
}
The component template uses an HTML select
element that renders a dropdown including a list of all available cultures.
In the code section, we initialize the current culture using the CultureInfo
class. We also implement a Culture
property that we bind to the select element in the template code. It contains a simple getter and a more advanced setter.
In the setter, we check whether the selected value is different from the current culture. If that is true, we build an URI including the culture value and trigger an internal page navigation using the NavigationManager
.
Make sure to provide true to the forceLoad
argument to ensure that the internal navigation will be executed.
Whenever we select a different culture in the CultureSelector
component, an internal page navigation should happen. However, we haven’t implemented the target page yet.
Let’s add a new Controllers folder in the root folder and create an empty MVC controller named CultureController
for the basis of the following controller implementation.
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
namespace BlazorLocalization.Controllers;
[Route("[controller]/[action]")]
public class CultureController : Controller
{
public IActionResult Set(string culture, string redirectUri)
{
if (culture != null)
{
var requestCulture = new RequestCulture(culture, culture);
var cookieName = CookieRequestCultureProvider.DefaultCookieName;
var cookieValue = CookieRequestCultureProvider.MakeCookieValue(requestCulture);
HttpContext.Response.Cookies.Append(cookieName, cookieValue);
}
return LocalRedirect(redirectUri);
}
}
We implement a Set
method that accepts two parameters. It has a culture and a redirectUri argument, both of type string
.
If the provided culture isn’t null, we create a new instance of the built-in RequestCulture
object and provide the instances as the value of a cookie.
When using the Localization
NuGet package installed at the beginning, we can choose from different options, how to change the culture. Using cookies is one of the simplest solutions, and it has worked great for me so far.
At the end of the method, we need to make sure that we append the created cookie to the response of our HTTP request and execute the redirect to the redirectUri
.
To make the Blazor application aware of the newly implemented controller, we need to register the services handling ASP.NET Core Controllers in the Program.cs
file.
We add the following line after the AddLocalization
call:
builder.Services.AddControllers();
And we also need to add the following middleware registration on the web application host:
app.MapControllers();
The order doesn’t matter much, but I usually register the controllers before the MapRazorComponent<App>()
registration.
The Microsoft.Extensions.Localization
NuGet package provides us with types that allow us to implement localization with a few lines of code and well-known .NET tools, such as resource files.
Make sure to register the required services in the Program.cs
file, and you should be good to go pretty quickly.
If you want to have more type safety when accessing the localized strings, you could also implement an enum
containing the keys of the resource files and use the enum
instead of magic strings when using the indexer of the IStringLocalizer
interface.
If you want to learn more about Blazor development, you can watch my free Blazor Crash Course on YouTube. And stay tuned to the Telerik blog for more Blazor Basics.
In this article, we will look at how we create In-Memory Zip files in C#. Previously, we discussed how to create and read Zip files in .NET in our Working With Zip Files in C#/.NET article, so we recommend taking a look at that to familiarize yourself with working with Zip files. Let’s delve in. […]
The post How to Create a Zip File in Memory In C# appeared first on Code Maze.