Why does your C# application need internationalization?
\nImagine: you wrote a cool note management service. Everything works, the interface is clean, users are happy. But only Russian-speaking ones. As soon as you enter the US or German market, the project stalls. Not because the code is bad, but because the button «Сохранить» doesn't turn into «Save», and the message «Ошибка ввода» scares foreigners.
\nThis is the localization problem. In the .NET world, its solution is called C# internationalization (or i18n — from the word "internationalization", where 18 is the number of letters between i and n). If you use C# and the .NET platform (Core, 5/6/7/8/9), you already have a powerful toolkit under the hood to make your application multilingual. In this article, we'll break it down in practice: from simple resources to changing the language "on the fly".
\n\nBasics: what is culture and neutral language
\nBefore writing code, let's understand the terms. In .NET, two key classes from the System.Globalization namespace are responsible for localization:
- \n
- CultureInfo — an object describing language and regional standards (e.g.,
ru-RU,en-US,de-DE). \n - CurrentUICulture — the current culture of the user interface. The system uses this when searching for translations. \n
- CurrentCulture — the format for dates, numbers, currency. This can also be changed, but for translations, the first one is important. \n
In C# applications, we typically use resource files (.resx). These are XML files that store strings, images, and other data tied to a specific culture. For example:
\n- \n
Messages.resx— default strings (usually English). \n Messages.ru.resx— Russian translation. \n Messages.de.resx— German translation. \n
When the application starts, .NET automatically selects the file matching the current UICulture. If there is no exact match, it uses the neutral (base) file.
Creating your first resource file in Visual Studio
\nLet's say we have a console application or an ASP.NET Core project. Let's add a Resources folder and inside it, a file Strings.resx. Fill it in:
Name | Value\n-------------|-------------------\nWelcomeMsg | Welcome to our app!\nGoodbyeMsg | Goodbye!\n\nNow create Strings.ru.resx:
Name | Value\n-------------|-------------------\nWelcomeMsg | Добро пожаловать в наше приложение!\nGoodbyeMsg | До свидания!\n\nNote: key names must match. After saving, Visual Studio will automatically generate a Strings class with access to the strings via static properties.
Programmatic language switching
\nFor C# internationalization to work, you need to set the desired culture at the start of the application (e.g., in Main or Startup). Here's how it looks:
using System.Globalization;\nusing System.Threading;\n\n// Set the Russian interface language\nCultureInfo culture = new CultureInfo("ru-RU");\nThread.CurrentThread.CurrentUICulture = culture;\nThread.CurrentThread.CurrentCulture = culture; // for date/number formats\n\n// Now access the resources\nConsole.WriteLine(Strings.WelcomeMsg); // Outputs: Добро пожаловать в наше приложение!\n\nIf you want to allow the user to switch the language "on the fly" (without restarting), simply call these lines again after changing the culture. In ASP.NET Core, middleware is used for this:
\napp.UseRequestLocalization(new RequestLocalizationOptions\n{\n DefaultRequestCulture = new RequestCulture("en-US")