Как использовать локализацию в C # - PullRequest
250 голосов
/ 17 июля 2009

Я просто не могу заставить работать локализацию.

У меня есть библиотека классов. Теперь я хочу создать resx файлы там и вернуть некоторые значения, основанные на культуре потоков.

Как я могу это сделать?

Ответы [ 8 ]

539 голосов
/ 17 июля 2009
  • Добавьте файл ресурсов в свой проект (вы можете назвать его «strings.resx»), выполнив следующие действия:
    Щелкните правой кнопкой мыши Свойства в проекте, выберите Добавить - > Новый элемент ... в контекстном меню, затем в списке Элементы Visual C # выберите "Файл ресурсов" и назовите его strings.resx.
  • Добавьте строку resouce в файл resx и дайте ей хорошее имя (пример: назовите ее «Hello» и присвойте ей значение «Hello»)
  • Сохранить файл ресурсов ( примечание: это будет файл ресурсов по умолчанию , так как он не имеет двухбуквенного кода языка)
  • Добавьте ссылки на вашу программу: System.Threading и System.Globalization

Запустите этот код:

Console.WriteLine(Properties.strings.Hello);

Должно быть напечатано «Hello».

Теперь добавьте новый файл ресурсов с именем "strings.fr.resx" (обратите внимание на часть "fr"; она будет содержать ресурсы на французском языке). Добавьте строковый ресурс с тем же именем, что и в strings.resx, но со значением на французском языке (Name = "Hello", Value = "Salut"). Теперь, если вы запустите следующий код, он должен напечатать Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(Properties.strings.Hello);

В результате система будет искать ресурс для "fr-FR". Он не найдет его (поскольку мы указали «fr» в вашем файле »). Затем он обратится к проверке« fr », которую он находит (и использует).

Следующий код выведет «Hello»:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);

Это потому, что он не находит никаких ресурсов "en-US", а также нет ресурса "en", поэтому он вернется к значению по умолчанию, которое мы добавили с самого начала.

При необходимости вы можете создавать файлы с более конкретными ресурсами (например, strings.fr-FR.resx и strings.fr-CA.resx для французского во Франции и Канаде соответственно). В каждый такой файл вам нужно будет добавить ресурсы для тех строк, которые отличаются от ресурса, к которому он будет возвращен. Таким образом, если текст одинаков во Франции и Канаде, вы можете поместить его в strings.fr.resx, а строки, отличающиеся на канадском французском языке, могут перейти в strings.fr-CA.resx.

37 голосов
/ 17 июля 2009

Это довольно просто, на самом деле. Создайте новый файл ресурсов, например Strings.resx. Установите Access Modifier на Public. Используйте соответствующий шаблон файла, чтобы Visual Studio автоматически сгенерировал класс средства доступа (в данном случае имя будет Strings). Это ваш язык по умолчанию.

Теперь, когда вы хотите добавить, скажем, немецкую локализацию, добавьте локализованный файл resx. Это будет обычно Strings.de.resx в этом случае. Если вы хотите добавить дополнительную локализацию, скажем, для Австрии, вы дополнительно создадите Strings.de-AT.resx.

Теперь создайте строку - скажем, строку с именем HelloWorld. В вашем Strings.resx добавьте эту строку со значением «Hello, world!». В Strings.de.resx добавьте «Привет, Welt!». И в Strings.de-AT.resx добавить «Servus, Welt!». Вот и все.

Теперь у вас есть этот сгенерированный класс Strings, и у него есть свойство с геттером HelloWorld. При получении этого свойства загрузится "Servus, Welt!" когда в качестве локали используется de-AT, «Привет, Welt!», когда в качестве локали используется любая другая локаль (включая de-DE и de-CH), и «Hello, World!», если в качестве локали используется что-нибудь еще отсутствует в локализованной версии, менеджер ресурсов будет автоматически идти вверх по цепочке, от самого специализированного к инвариантному ресурсу.

Вы можете использовать класс ResourceManager для большего контроля над тем, как именно вы загружаете вещи. Сгенерированный класс Strings также использует его.

15 голосов
/ 20 сентября 2012

В дополнение к отличному ответу @Fredrik Mörk на строки, чтобы добавить локализацию в форму , сделайте следующее:

  • Установите для свойства "Localizable" значение true
  • Измените свойство Language формы на нужный вам язык (из приятного выпадающего списка, в котором все они включены)
  • Переведите элементы управления в эту форму и переместите их в случае необходимости (вставьте эти действительно длинные полные французские предложения!)

Редактировать: Эта статья MSDN о локализации Windows Forms не является той, которую я связал, но может пролить больше света, если это необходимо. (старый забрали)

14 голосов
/ 18 июля 2012

Отличный ответ Ф.Мёрка. Но если вы хотите обновить перевод или добавить новые языки после выпуска приложения, вы застряли, потому что вам всегда нужно перекомпилировать его для создания resources.dll.

Вот решение вручную скомпилировать ресурс dll. Он использует средства resgen.exe и al.exe (устанавливаются вместе с SDK).

Скажем, у вас есть файл ресурсов Strings.fr.resx, вы можете скомпилировать dll ресурсов с помощью следующего пакета:

resgen.exe /compile Strings.fr.resx,WpfRibbonApplication1.Strings.fr.resources 
Al.exe /t:lib /embed:WpfRibbonApplication1.Strings.fr.resources /culture:"fr" /out:"WpfRibbonApplication1.resources.dll"
del WpfRibbonApplication1.Strings.fr.resources
pause

Обязательно сохраните исходное пространство имен в именах файлов (здесь «WpfRibbonApplication1»)

9 голосов
/ 28 ноября 2016

Исправление и уточнение @ Фредрик Мёрк ответ.

  • Добавить strings.resx файл ресурсов в ваш проект (или другое имя файла)
  • Установите Access Modifier на Public (в открытой вкладке strings.resx файл)
  • Добавить строку resouce в файл resx: (пример: имя Hello, значение Hello)
  • Сохранить файл ресурса

Visual Studio автоматически генерирует соответствующий класс strings, который фактически помещается в strings.Designer.cs. Класс находится в том же пространстве имен, в котором вы ожидаете разместить только что созданный файл .cs.

Этот код всегда печатает Hello, потому что это ресурс по умолчанию, а ресурсы для конкретного языка недоступны:

Console.WriteLine(strings.Hello);

Теперь добавьте новый языковой ресурс:

  • Добавить strings.fr.resx (для французского)
  • Добавить строку с тем же именем, что и ранее, но с другим значением: (имя Hello, значение Salut)

Следующий код печатает Salut:

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
Console.WriteLine(strings.Hello);

Какой ресурс используется, зависит от Thread.CurrentThread.CurrentUICulture. Он устанавливается в зависимости от языковой настройки Windows UI или может быть установлен вручную, как в этом примере. Узнайте больше об этом здесь .

Вы можете добавить ресурсы для конкретной страны, такие как strings.fr-FR.resx или strings.fr-CA.resx.

Используемая строка определяется в следующем порядке приоритета:

  • Из ресурса, специфичного для страны, например strings.fr-CA.resx
  • Из конкретного языкового ресурса, например strings.fr.resx
  • По умолчанию strings.resx

Обратите внимание, что языковые ресурсы генерируют спутниковых сборок .

Также узнайте, чем CurrentCulture отличается от CurrentUICulture здесь .

0 голосов
/ 08 июня 2019

ResourceManager и .resx немного грязные.

Вы можете использовать Lexical.Localization ¹, который позволяет встраивать значения по умолчанию и значения, специфичные для культуры, в код и расширяться во внешних файлах локализации для других культур (например, .json или .resx).

public class MyClass
{
    /// <summary>
    /// Localization root for this class.
    /// </summary>
    static ILine localization = LineRoot.Global.Type<MyClass>();

    /// <summary>
    /// Localization key "Ok" with a default string, and couple of inlined strings for two cultures.
    /// </summary>
    static ILine ok = localization.Key("Success")
            .Text("Success")
            .fi("Onnistui")
            .sv("Det funkar");

    /// <summary>
    /// Localization key "Error" with a default string, and couple of inlined ones for two cultures.
    /// </summary>
    static ILine error = localization.Key("Error")
            .Format("Error (Code=0x{0:X8})")
            .fi("Virhe (Koodi=0x{0:X8})")
            .sv("Sönder (Kod=0x{0:X8})");

    public void DoOk()
    {
        Console.WriteLine( ok );
    }

    public void DoError()
    {
        Console.WriteLine( error.Value(0x100) );
    }
}

¹ (я хранитель этой библиотеки)

0 голосов
/ 13 мая 2015

В моем случае

[assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]

в AssemblyInfo.cs препятствовал нормальной работе.

0 голосов
/ 11 февраля 2015

В дополнение к @ Eric Bole-Feysot ответ:

Благодаря спутниковым сборкам локализация может быть создана на основе файлов .dll / .exe . Таким образом:

  • исходный код (проект VS) может быть отделен от языкового проекта,
  • добавление нового языка не требует перекомпиляции проекта,
  • перевод может быть выполнен даже конечным пользователем.

Существует мало известный инструмент под названием LSACreator (бесплатный для некоммерческого использования или покупки), который позволяет создавать локализацию на основе файлов .dll / .exe. Фактически, внутри (в каталоге языкового проекта) он создает / управляет локализованными версиями файлов resx и компилирует сборку аналогично описанному @ Eric Bole-Feysot .

...