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

C# 如何在单个EXE中嵌入多语言*.resx(或*.resources)文件?,c#,internationalization,embed,embedded-resource,C#,Internationalization,Embed,Embedded Resource,有很多教程介绍如何创建多语言RESX文件以及如何使用AL.exe创建附属程序集,但我还没有找到如何在单个exe文件中嵌入RESX/Resources/satellite DLL文件并将整个多语言应用程序作为exe分发的工作示例 我尝试使用ilmerge.exe,但它似乎不适用于具有相同名称的多个DLL(区域性卫星DLL具有相同的名称,最初位于以区域性命名的不同子目录中) 我也不知道如何创建ResourceManager实例来处理嵌入式资源 我的目标是在封闭的、预定义的语言集之间实现动态切换。我需

有很多教程介绍如何创建多语言RESX文件以及如何使用AL.exe创建附属程序集,但我还没有找到如何在单个exe文件中嵌入RESX/Resources/satellite DLL文件并将整个多语言应用程序作为exe分发的工作示例

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

我也不知道如何创建ResourceManager实例来处理嵌入式资源

我的目标是在封闭的、预定义的语言集之间实现动态切换。我需要一个类/方法,该类/方法将获取区域性字符串(即“de de”)、资源名称(即“CancelText”)并返回基于嵌入式resx/resource/dll的翻译文本


我使用的是VS2008,请注意在resx/resource files属性表中需要“build action”的设置。工作代码示例或教程项目的链接是最好的。

您没有找到它,因为它不是.NET framework的工作方式。NET希望卫星DLL位于特定的命名位置(iow目录以其包含的资源的语言命名。例如,
de
de
chs
,…)。如果您不这样做,.NET将无法应用其魔力(即根据当前UI区域性自动选择正确的资源:
Thread.CurrentThread.CurrentUICulture
)。

我的解决方案:程序只包含一个默认语言资源文件(resx)。所有其他语言都从.resx编译到.resources,并作为资源文件嵌入。重要!我更改了扩展名,因为“.resources”被认为是一种特殊类型的资源,所以我的法语文件名为“PIAE.LangResources.fr”

下面是检索转换字符串的简单代码(应该通过缓存资源中的值来改进):


我使用了上面的
GetString
方法。本文描述了如何将资源作为流对象正确检索。之后,一切正常。

使用此程序,它与我一起工作:


每次编译时,您只需手动执行,不确定是否有命令工具。

对我来说没关系,我可以自己传递适当的区域性-但我分发小型工具,我绝对不想添加任何子目录/DLL。只有一个EXE,即使.NET framework在这里没有什么帮助。+1,我们使用类似的方法。如果你想避免使用附属程序集,.net强迫你重新发明轮子,这是很痛苦的。在我看来,这是一个非常糟糕的设计决策。很好的方法。我只是想补充一点,读者可以使用
资源集
,以便于按名称检索值。我知道重新激活这样一个旧线程令人毛骨悚然,但我很想知道您是否已经解决了问题,如果是,如何解决?到目前为止,您是否仍在使用您的方法(您在下面给出的答案)?我正在VS 2012中从事一个类似的项目,希望将我的语言资源DLL合并到主汇编/exe文件中,同时仍使用ResourceManager在德语和英语之间切换。谢谢@塞巴斯蒂安:我没有探索任何其他方法,如果你找到更好的方法,请分享
    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);
    }