Я просто не могу заставить локализацию работать.
У меня есть библиотека классов. Теперь я хочу создать там файлы resx и вернуть некоторые значения на основе культуры потоков.
Как я могу это сделать?
Я просто не могу заставить локализацию работать.
У меня есть библиотека классов. Теперь я хочу создать там файлы resx и вернуть некоторые значения на основе культуры потоков.
Как я могу это сделать?
strings.resx
.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.
Это довольно просто, на самом деле. Создайте новый файл ресурсов, например Strings.resx
. Установите Access Modifier
в Public
. Используйте шаблон apprioriate, поэтому Visual Studio автоматически создаст класс доступа (в этом случае имя будет Strings
). Это ваш язык по умолчанию.
Теперь, когда вы хотите добавить, скажем, немецкую локализацию, добавить локализованный файл resx. В этом случае это будет обычно Strings.de.resx
. Если вы хотите добавить дополнительную локализацию, скажем, в Австрию, вы также создадите Strings.de-AT.resx
.
Теперь перейдите к созданию строки - скажем, строку с именем HelloWorld
. В Strings.resx
добавьте эту строку со значением "Hello, world!". В Strings.de.resx
добавьте "Hallo, Welt!". И в Strings.de-AT.resx
добавьте "Servus, Welt!". Это пока.
Теперь у вас есть сгенерированный класс Strings
, и он имеет свойство с getter HelloWorld
. Приобретение этого свойства будет загружать "Servus, Welt!" когда ваш язык де-AT, "Hallo, Welt!, когда ваш язык - это любой другой язык (включая de-DE и de-CH) и" Hello, World! ", когда ваш язык - это что-то еще. Если строка отсутствует в локализованной версии, диспетчер ресурсов будет автоматически перемещаться по цепочке от наиболее специализированного к инвариантному ресурсу.
Вы можете использовать класс ResourceManager
для большего контроля над тем, как именно вы загружаете вещи. Созданный класс Strings
также использует его.
Кроме @Fredrik Mörk отличный ответ на строки, чтобы добавить локализацию в форму, сделайте следующее:
"Localizable"
значение true
Language
формы на нужный вам язык (из приятного выпадающего списка)Изменение: Эта статья MSDN по локализации Windows Forms не является той, которую я связал, но может пролить больше света, если это необходимо. (старый был забран)
Отличный ответ Ф.Мёрка. Но если вы хотите обновить перевод или добавить новые языки после того, как приложение будет выпущено, вы застряли, потому что вам всегда приходится перекомпилировать его для генерации файла 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" )
Исправление и проработка ответа @Fredrik Mörk.
strings.resx
в ваш проект (или другое имя файла)Access Modifier
значение Public
(на открытой вкладке файла strings.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
здесь.
В дополнение к ответу @Eric Bole-Feysot:
Благодаря сборкам спутников локализация может быть создана на основе файлов .dll/.exe. Таким образом:
Существует мало известный инструмент LSACreator (бесплатный для некоммерческого использования или вариант покупки), который позволяет создавать локализацию на основе на .dll/.exe. Фактически, внутренне (в каталоге проекта языка) он создает/управляет локализованными версиями файлов resx и компилирует сборку аналогично описанному @Eric Bole-Feysot.
В моем случае
[assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]
в AssemblyInfo.cs помешало всем работать как обычно.
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) );
}
}
¹ (я хранитель этой библиотеки)