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

Posted

技术标签:

【中文标题】如何在单个 EXE 中嵌入多语言 *.resx(或 *.resources)文件?【英文标题】:How to embed multilanguage *.resx (or *.resources) files in single EXE? 【发布时间】:2010-12-20 01:53:33 【问题描述】:

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

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

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

我的目标是在封闭的、预定义的语言集之间实现动态切换。我需要获取文化字符串(即“de-DE”)、资源名称(即“CancelText”)并根据 embedded resx/resource/dll 返回翻译文本的类/方法。

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

【问题讨论】:

我知道重新激活这样一个旧线程令人毛骨悚然,但我很想知道您是否解决了问题,如果解决了,如何解决?到目前为止,您是否仍在使用您的方法(您在下面给出的答案)?我正在 VS 2012 中进行类似的项目,并希望将我的语言资源 DLL 组合到主程序集/exe 文件中,同时仍使用 ResourceManager 在德语和英语之间切换。谢谢! @Sebastian 我没有探索任何其他方式,如果你找到更好的方式请分享 【参考方案1】:

我使用了上面的GetString 方法。文章Can't load a manifest resource with GetManifestResourceStream() 描述了如何正确地将您的资源检索为流对象。之后,一切正常。

【讨论】:

【参考方案2】:

使用这个程序,它适用于我:EXEPack

每次编译都需要手动做,不知道有没有命令工具。

【讨论】:

【参考方案3】:

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

【讨论】:

+1,我们使用类似的方法。如果您想避免附属程序集,.net 会迫使您重新发明***,这很痛苦。一个非常糟糕的设计决定,IMO。 不错的方法。只是想补充一点,ResourceSet 可以在阅读器周围使用,以便更轻松地按名称检索值。【参考方案4】:

您没有找到它,因为它不是 .NET 框架的工作方式。 .NET 期望附属 DLL 位于特定命名的位置(iow 目录以其包含的资源的语言命名。例如,dede-DEchs,...)。如果你不这样工作,.NET 将无法应用它的魔力(即根据当前的 UI 文化自动选择正确的资源:@​​987654324@)。

【讨论】:

对我来说没关系,我可以自己传递适当的文化 - 但我分发小工具,我绝对不想添加任何子目录/dll。只有一个 EXE,即使 .NET 框架在这里带来的帮助不大。

以上是关于如何在单个 EXE 中嵌入多语言 *.resx(或 *.resources)文件?的主要内容,如果未能解决你的问题,请参考以下文章

MVC4多语言支持

是否可以在 Xamarin iOS/Android 中使用定义 PCL 的 RESX 文件来支持多语言?

深入Resource实现多语言支持的应用详解

如何为多语言版ASP网站添加一个中文版语言?

WPF 实现多语言支持

如何在 javascript 文件中使用 resx 文件。 .net 核心 3.1 mvc