Какие существуют подходы к локализации приложения?

Локализация приложения — это процесс адаптации интерфейса, текста, форматов дат, валют и других культурных аспектов под различные языки и регионы. В Xamarin и Xamarin.Forms для локализации используются стандартные .NET-механизмы на базе ресурсных файлов (RESX), а также платформенные инструменты. Локализация обеспечивает удобство использования приложения пользователями, говорящими на разных языках, и играет важную роль в международных и коммерческих проектах.

Основные подходы к локализации в Xamarin.Forms

  1. Использование .resx-файлов (ресурсных файлов) с переводами.

  2. Использование платформенных инструментов локализации на Android и iOS.

  3. Настройка определения и переключения текущей культуры.

  4. Возможность динамической локализации — смены языка во время работы приложения (с дополнительными настройками).

  5. Поддержка форматирования по культуре: чисел, дат, валют.

1. Создание ресурсных файлов (RESX)

Ресурсные файлы — это файлы формата .resx, содержащие пары ключ-значение, где:

  • ключ — идентификатор текста (WelcomeMessage)

  • значение — текст на конкретном языке (Добро пожаловать, Welcome, Willkommen и т.д.)

Структура:

Resources/
├── AppResources.resx (по умолчанию, например русский)
├── AppResources.en.resx (английский)
├── AppResources.es.resx (испанский)

Добавить можно через Visual Studio:

  • Щёлкните правой кнопкой по проекту → Add → New Item... → Resources File

  • Назовите AppResources.resx, затем скопируйте и добавьте версии для других языков (AppResources.fr.resx и т.д.)

2. Доступ к строкам из C#

string welcome = AppResources.WelcomeMessage;

Чтобы получить доступ к нужной локализации, нужно установить культуру.

3. Установка культуры (CultureInfo)

Для установки текущей культуры используется CultureInfo из пространства имён System.Globalization.

Пример установки культуры:

Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");
Thread.CurrentThread.CurrentCulture = new CultureInfo("en");

Для Xamarin.Forms лучше использовать глобальную установку при запуске приложения.

4. Реализация ILocalize через DependencyService

Чтобы получить текущую культуру устройства, нужно создать интерфейс ILocalize:

public interface ILocalize
{
CultureInfo GetCurrentCultureInfo();
}

Android:

\[assembly: Dependency(typeof(Localize_Android))\]
namespace MyApp.Droid
{
public class Localize_Android : ILocalize
{
public CultureInfo GetCurrentCultureInfo()
{
var androidLocale = Java.Util.Locale.Default;
var netLocale = androidLocale.ToString().Replace("\_", "-");
return new CultureInfo(netLocale);
}
}
}

iOS:

\[assembly: Dependency(typeof(Localize_iOS))\]
namespace MyApp.iOS
{
public class Localize_iOS : ILocalize
{
public CultureInfo GetCurrentCultureInfo()
{
var iosLocale = NSLocale.PreferredLanguages\[0\];
return new CultureInfo(iosLocale.Replace("\_", "-"));
}
}
}

Применение:

var ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = ci;

5. Локализация в XAML

Чтобы использовать ресурсы в XAML, нужно их подключить как xmlns.

Пример подключения ресурсов:

xmlns:resx="clr-namespace:MyApp.Resources"

Использование:

<Label Text="{x:Static resx:AppResources.WelcomeMessage}" />

Если используется x:Static не поддерживаемый в XAML версии Xamarin.Forms, можно использовать Binding через LocalizationResourceManager.

6. Альтернативный подход: LocalizationResourceManager

Чтобы упростить локализацию в XAML, можно использовать LocalizationResourceManager, как часть собственного INotifyPropertyChanged класса, позволяющего менять язык динамически.

Пример:

public class LocalizationResourceManager : INotifyPropertyChanged
{
public static LocalizationResourceManager Instance { get; } = new LocalizationResourceManager();
public string this\[string text\]
{
get => AppResources.ResourceManager.GetString(text, AppResources.Culture);
}
public void SetCulture(CultureInfo culture)
{
AppResources.Culture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
}
public event PropertyChangedEventHandler PropertyChanged;
}

И в XAML:

<Label Text="{Binding Source={x:Static res:LocalizationResourceManager.Instance}, Path=\[WelcomeMessage\]}" />

7. Переключение языка во время работы приложения

Чтобы язык приложения можно было сменить вручную (например, через настройки), необходимо:

  1. Сохранить выбранный язык в Preferences.

  2. При загрузке приложения — применять сохранённый язык.

  3. Повторно применять SetCulture(...) и обновлять интерфейс.

Пример смены языка:

LocalizationResourceManager.Instance.SetCulture(new CultureInfo("es"));

8. Локализация платформенных элементов

На Android и iOS есть платформенные элементы, которые не управляются через RESX. Для них:

Android:

  • Файлы находятся в Resources/values/strings.xml, values-es/strings.xml и т.д.

  • Их можно использовать в платформенной части или через Custom Renderers.

iOS:

  • Используется Localizable.strings, добавляемый в Resources.

Пример:

"WelcomeMessage" = "Bienvenido";

9. Локализация форматов данных

Культура влияет на:

  • Формат даты и времени

  • Формат чисел (разделители, валюты)

  • Формат отображения текста (направление, региональные различия)

Пример:

DateTime now = DateTime.Now;
string formatted = now.ToString("D", CultureInfo.CurrentCulture);

10. Поддержка RTL (Right-to-Left)

Для языков с письмом справа налево (арабский, иврит):

  • Установите FlowDirection:
<StackLayout FlowDirection="RightToLeft">
...
</StackLayout>
  • Xamarin.Forms 4.0+ поддерживает FlowDirection глобально:
Application.Current.MainPage.FlowDirection = FlowDirection.RightToLeft;

11. Тестирование локализации

  • Эмулируйте разные языки на устройствах или эмуляторах.

  • Используйте App Resources и ключи, чтобы видеть, какой текст загружается.

  • Не хардкодьте строки в XAML и C#.

12. Советы по организации локализации

  • Используйте одинаковые ключи во всех .resx.

  • Для длинных строк используйте многострочные значения в .resx.

  • Храните строки для ошибок, сообщений, заголовков — всё в ресурсах.

  • Для каждого языка создавайте отдельный .resx (AppResources.fr.resx и т.п.)

  • Можно использовать сторонние сервисы для перевода .resx файлов (POEditor, Crowdin).

13. Локализация в .NET MAUI

В MAUI подход схожий, но LocalizationResourceManager включён в CommunityToolkit.Maui, что упрощает реализацию. Большая часть кода из Xamarin переносится с минимальными изменениями.