【问题标题】:localization of web.sitemap using a resx file in other project在其他项目中使用 resx 文件对 web.sitemap 进行本地化
【发布时间】:2010-08-03 08:58:49
【问题描述】:

我正在开发一个 Web 应用程序,并且我正在使用文化信息本地化。 我的应用程序的所有本地化资源都在另一个仅包含资源 (resx) 文件的项目中。使用此架构是因为我有其他应用程序使用相同的资源。

我现在的问题是 web.sitemap 的本地化。目前我在项目中有一个指向 web.sitemap 的 resx 文件,我使用以下语法引用它

title='$Resources:SiteMapRes,CLIPS_LIST'
description='$Resources:SiteMapRes,CLIPS_LIST

问题是当我使用其他项目中包含的资源时,这种方法不起作用。

有人知道如何解决我的问题吗?

最好的问候,

何塞

【问题讨论】:

    标签: localization web.sitemap


    【解决方案1】:

    站点地图使用默认的本地化提供程序来调用包含在站点地图节点中的本地化表达式。默认提供程序不允许通过表达式设置外部程序集。 改变这种行为的唯一方法是创建您自己的本地化提供程序。 This 文章展示了如何做到这一点。设置您自己的提供程序后,您可以使用这样的表达式从外部程序集中访问资源:

    提供程序的实际实现并不像您将在文章中看到的那样困难。

    问候, 罗宾

    【讨论】:

      【解决方案2】:

      我将采用的方法是切换到外部 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多