如何将多语言的*.resx(或*.resources)文件嵌入单个EXE中?

22

有很多教程介绍如何创建多语言的RESX文件和如何使用AL.exe创建卫星程序集,但我没有找到可行的示例来将RESX/资源/卫星DLL文件嵌入单个EXE文件中,并将整个多语言应用作为此类EXE文件分发。

我尝试使用ilmerge.exe,但似乎它不适用于具有相同名称的多个DLL(文化卫星DLL具有相同的名称,最初位于以文化命名的不同子目录中)。

我也不知道如何创建ResourceManager实例以使用嵌入式资源。

我的目标是启用在预定义的一组语言之间进行动态切换。我需要一个获取区域设置字符串(例如"de-DE"),资源名称(例如"CancelText")并基于嵌入式resx/资源/DLL返回已翻译文本的类/方法。

我正在使用VS2008,请注意在resx/资源文件属性表中需要什么构建操作设置。最好提供工作代码示例或链接到教程项目。


2
我知道重新激活这样一个古老的线程有点可怕,但我很想知道你是否解决了你的问题,如果是的话,是如何解决的?直到今天,你还在使用你下面给出的答案吗?我正在VS 2012上开展类似的项目,并希望将我的语言资源DLL合并到主程序/ exe文件中,同时仍然使用ResourceManager在德语和英语之间切换。谢谢! - Sebastian
@Sebastian 我没有探索其他方法,请分享如果你找到更好的方法。 - tomash
4个回答

10

我的解决方案:程序只包含一个默认语言的资源文件(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);
    }

8
+1, 我们采用了类似的方法。很遗憾,如果你想避免使用卫星程序集,.NET 强制你重新发明轮子。这是一个非常糟糕的设计决策,我个人认为。 - Heinzi
不错的方法。只想补充一下,可以在读取器周围使用ResourceSet,以使按名称检索值更加容易。 - Julien Lebosquain

6
您没有找到它,是因为这不是.NET框架的工作方式。.NET期望卫星DLL位于特定命名位置(即目录根据其包含的资源语言命名。例如:dede-DEchs等)。如果您不按照这种方式工作,.NET将无法应用其魔力(自动选择正确的资源,根据当前UI文化:Thread.CurrentThread.CurrentUICulture)。

4
没问题,我可以自己传递适当的文化 - 但是我分发小工具,绝对不想添加任何子目录/动态链接库。只有一个EXE文件,即使.NET框架在这里提供了一些帮助。 - tomash

-1

使用这个程序,它对我有效:EXEPack

每次编译时您只需要手动操作,不确定是否有命令工具可用。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接