Как встраивать многоязычные файлы *.resx(или *.resources) в один EXE?
Существует множество учебных пособий по созданию многоязычных файлов RESX и способам создания спутниковых сборок с помощью AL.exe, но я не нашел рабочего примера, как вставлять файлы RESX/Resources/satellite-DLL в один файл EXE и распространять целое многоязычное приложение как таковое EXE.
Я попытался использовать файл ilmerge.exe, но похоже, что он не работает для нескольких DLL с одинаковым именем (библиотеки культурных спутников имеют одинаковые имена, изначально проживающие в разных поддиреках, названных в честь культуры).
Я также не знаю, как создать экземпляр ResourceManager для работы со встроенными ресурсами.
Мои цели - включить динамическое переключение между закрытым, заранее определенным набором языков. Мне нужен класс/метод, который получит строку культуры (т.е. "De-DE" ), имя ресурса (т.е. "CancelText" ) и вернет переведенный текст на основе встроенного resx/resource/dll.
Я использую VS2008, обратите внимание, какие настройки для "действия сборки" необходимы в файле свойств resx/resource files. Образец рабочего кода или ссылка на учебный проект будут лучшими.
Ответы
Ответ 1
Мое решение: программа содержит только один файл ресурсов языка по умолчанию (resx). Все остальные языки скомпилированы из .resx в .resources и внедрены в качестве файла ресурсов. Важный! Я изменил расширение, потому что ".resources" распознается как специальный тип ресурса, поэтому мои французские файлы называются "PIAE.LangResources.fr".
Вот простой код для извлечения переведенной строки (ее нужно улучшить с помощью кеширования значений из ресурса):
internal static string GetString(string str, string lang)
{
if (string.IsNullOrEmpty(str)) throw new ArgumentNullException("empty language query string");
if (string.IsNullOrEmpty(lang)) throw new ArgumentNullException("no language resource given");
// culture-specific file, i.e. "LangResources.fr"
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PIAE.LangResources."+lang);
// resource not found, revert to default resource
if (null == stream)
{
stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PIAE.Properties.LangResources.resources");
}
ResourceReader reader = new ResourceReader(stream);
IDictionaryEnumerator en= reader.GetEnumerator();
while (en.MoveNext())
{
if (en.Key.Equals(str))
{
return en.Value.ToString();
}
}
// string not translated, revert to default resource
return LangResources.ResourceManager.GetString(str);
}
Ответ 2
Вы не нашли его, потому что это не так, как работает среда .NET..NET ожидает, что спутниковые библиотеки DLL в специально названном месте (каталоги iow, названные в честь языка ресурсов, которые он содержит, например, de
, de-DE
, chs
,...). Если вы этого не сделаете,.NET не сможет применить свою магию (чтобы автоматически выбрать правильный ресурс в соответствии с текущей культурой пользовательского интерфейса: Thread.CurrentThread.CurrentUICulture
).
Ответ 3
Я использовал подход GetString
выше. Статья Не удается загрузить ресурс манифеста с помощью GetManifestResourceStream(), описывает, как правильно получить ваш ресурс в качестве объекта потока. После этого все сработало.
Ответ 4
Используйте эту программу, она работает со мной: EXEPack
Вам просто нужно делать вручную каждый раз, когда вы компилируете, не уверен, есть ли командный инструмент.
Ответ 5
Я использовал ресурс для встраивания отсюда: https://github.com/MarcStan/Resource.Embedder Не может быть проще.