【问题标题】:MVC Site Map Provider and localizationMVC 站点地图提供程序和本地化
【发布时间】:2023-04-02 02:17:01
【问题描述】:

我今天发现对于我的网站,我可以使用从 Github 为 MVC3 下载的 SiteMap 提供程序,因为我的 Web 应用程序是 MVC3。

情况如下,我的应用程序是多语言的。我有一个单独的库,其中包含所有资源。然后将此库添加到我当前的项目中,并在我需要的任何地方使用这些资源文件。

现在我已经实现了站点地图提供程序:

  <mvcSiteMapNode title="$resources:Base,Home" controller="Home" action="Index" enableLocalization="true">
    <mvcSiteMapNode title="Search" controller="Search" action="Index"/>
    <mvcSiteMapNode title="Contact" controller="Contact" action="Index"/>
    <mvcSiteMapNode title="About" controller="Home" action="About"/>
  </mvcSiteMapNode>

但是当我运行它时,我得到了一个错误,因为它找不到带有 key home 的资源。我认为这是因为它在应用程序之外但在一个单独的库中。

那么我如何指向位于单独项目中的资源文件?

【问题讨论】:

  • 您在哪里定义了您的资源?你定义这些资源的类名是什么?

标签: c# asp.net-mvc asp.net-mvc-3 resources mvcsitemapprovider


【解决方案1】:

我将采用的方法是切换到外部 DI,然后实现一个自定义 IStringLocalizer 类,该类可以从另一个程序集读取资源。这是一个工作示例。我也在 GitHub 上创建了demo application

using System;
using System.Collections.Specialized;
using System.Resources;

namespace MvcSiteMapProvider.Globalization
{
    public class ResourceManagerStringLocalizer
        : IStringLocalizer
    {
        public ResourceManagerStringLocalizer(
            ResourceManager resourceManager
            )
        {
            if (resourceManager == null)
                throw new ArgumentNullException("resourceManager");
            this.resourceManager = resourceManager;
        }
        protected readonly ResourceManager resourceManager;

        /// <summary>
        /// Gets the localized text for the supplied attributeName.
        /// </summary>
        /// <param name="attributeName">The name of the attribute (as if it were in the original XML file).</param>
        /// <param name="value">The current object's value of the attribute.</param>
        /// <param name="enableLocalization">True if localization has been enabled, otherwise false.</param>
        /// <param name="classKey">The resource key from the ISiteMap class.</param>
        /// <param name="implicitResourceKey">The implicit resource key.</param>
        /// <param name="explicitResourceKeys">A <see cref="T:System.Collections.Specialized.NameValueCollection"/> containing the explicit resource keys.</param>
        /// <returns></returns>
        public virtual string GetResourceString(string attributeName, string value, bool enableLocalization, string classKey, string implicitResourceKey, NameValueCollection explicitResourceKeys)
        {
            if (attributeName == null)
            {
                throw new ArgumentNullException("attributeName");
            }

            if (enableLocalization)
            {
                string result = string.Empty;
                if (explicitResourceKeys != null)
                {
                    string[] values = explicitResourceKeys.GetValues(attributeName);
                    if ((values == null) || (values.Length <= 1))
                    {
                        result = value;
                    }
                    else if (this.resourceManager.BaseName.Equals(values[0]))
                    {
                        try
                        {
                            result = this.resourceManager.GetString(values[1]);
                        }
                        catch (MissingManifestResourceException)
                        {
                            if (!string.IsNullOrEmpty(value))
                            {
                                result = value;
                            }
                        }
                    }
                }
                if (!string.IsNullOrEmpty(result))
                {
                    return result;
                }
            }
            if (!string.IsNullOrEmpty(value))
            {
                return value;
            }

            return string.Empty;
        }
    }
}

然后您可以将其注入您的 DI 配置模块(显示了结构图示例,但任何 DI 容器都可以)。

首先,您需要通过将 IStringLocalizer 接口添加到 excludeTypes 变量中来指定不自动注册它。

var excludeTypes = new Type[] {
// Use this array to add types you wish to explicitly exclude from convention-based  
// auto-registration. By default all types that either match I[TypeName] = [TypeName] or 
// I[TypeName] = [TypeName]Adapter will be automatically wired up as long as they don't 
// have the [ExcludeFromAutoRegistrationAttribute].
//
// If you want to override a type that follows the convention, you should add the name 
// of either the implementation name or the interface that it inherits to this list and 
// add your manual registration code below. This will prevent duplicate registrations 
// of the types from occurring. 

// Example:
// typeof(SiteMap),
// typeof(SiteMapNodeVisibilityProviderStrategy)
    typeof(IStringLocalizer)
};

然后提供 ResourceManagerStringLocalizer(及其依赖项)的显式注册。

// Configure localization

// Fully qualified namespace.resourcefile (.resx) name without the extension
string resourceBaseName = "SomeAssembly.Resources.Resource1";

// A reference to the assembly where your resources reside.
Assembly resourceAssembly = typeof(SomeAssembly.Class1).Assembly;

// Register the ResourceManager (note that this is application wide - if you are 
// using ResourceManager in your DI setup already you may need to use a named 
// instance or SmartInstance to specify a specific object to inject)
this.For<ResourceManager>().Use(() => new ResourceManager(resourceBaseName, resourceAssembly));

// Register the ResourceManagerStringLocalizer (uses the ResourceManger)
this.For<IStringLocalizer>().Use<ResourceManagerStringLocalizer>();

那么这只是适当地指定资源的问题。您需要以 Base Name 开头(在本例中为 SomeAssembly.Resources.Resource1),然后将资源的键指定为第二个参数。

<mvcSiteMapNode title="$resources:SomeAssembly.Resources.Resource1,ContactTitle" controller="Home" action="Contact"/>

请注意,正确设置 BaseName 是使其正常工作的关键。请参阅以下 MSDN 文档:http://msdn.microsoft.com/en-us/library/yfsz7ac5(v=vs.110).aspx

【讨论】:

    【解决方案2】:

    我觉得应该是这样的:

    假设你:

    ProjectName=MyProject

    文件夹,其中包含 resources:LanguageFiles

    ,其中资源定义:消息传递

    那么。

    我相信应该是这样的。我不确定,但可能对你有用:

    `title=@MyProject.LanguageFiles.Messaging.Home'
    

    (假设 Home 是 Messaging 类中定义的资源)

    【讨论】:

    • 我试过这个: 但没有成功
    • 包含资源文件的项目的名称称为 Resources,其中我有一个名为 Base 的 .resx 文件,它具有 Home 键
    • 项目名称应该是主 MVC 项目,如果您包含多个项目,则设置为 StarUp 项目
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多