Как встраивать многоязычные файлы *.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).

Ответ 4

Используйте эту программу, она работает со мной: EXEPack

Вам просто нужно делать вручную каждый раз, когда вы компилируете, не уверен, есть ли командный инструмент.