打包和部署 .NET 应用中的资源Packaging and Deploying Resources in .NET Apps

应用程序依靠 .NET Framework Resource Manager(由 ResourceManager 类表示)来检索已本地化的资源。Applications rely on the .NET Framework Resource Manager, represented by the ResourceManager class, to retrieve localized resources. Resource Manager 假定使用中枢轮辐式模型来打包和部署资源。The Resource Manager assumes that a hub and spoke model is used to package and deploy resources. 中枢即主程序集,包含不可本地化的可执行代码和单个区域性(称作非特定区域性或默认区域性)的资源。The hub is the main assembly that contains the nonlocalizable executable code and the resources for a single culture, called the neutral or default culture. 默认区域性是应用程序的回退区域性;如果找不到已本地化的资源,则使用默认区域性的资源。The default culture is the fallback culture for the application; it is the culture whose resources are used if localized resources cannot be found. 每条轮辐均连接到一个附属程序集,该附属程序集包含单个区域性的资源,但不包含任何代码。Each spoke connects to a satellite assembly that contains the resources for a single culture, but does not contain any code.

此模型有以下优点:There are several advantages to this model:

  • 部署应用程序后,可针对新区域性以增量方式添加资源。You can incrementally add resources for new cultures after you have deployed an application. 因为特定于区域性资源的后续开发可能需要大量时间,这使你能够先发布主要应用程序,并在以后发布特定于区域性的资源。Because subsequent development of culture-specific resources can require a significant amount of time, this allows you to release your main application first, and deliver culture-specific resources at a later date.
  • 可更新和更改应用程序的附属程序集,无需重新编译应用程序。You can update and change an application's satellite assemblies without recompiling the application.
  • 应用程序只需加载那些包含特定区域性所需资源的附属程序集。An application needs to load only those satellite assemblies that contain the resources needed for a particular culture. 这可显著减少系统资源的使用。This can significantly reduce the use of system resources.

但是,该模型也有以下缺点:However, there are also disadvantages to this model:

  • 必须管理多组资源。You must manage multiple sets of resources.
  • 测试应用程序的初始成本增加,因为必须测试多种配置。The initial cost of testing an application increases, because you must test several configurations. 请注意,从长远角度看,测试使用多个附属程序集测试多个核心应用程序会比测试并维护多个并行国际版本更轻松,成本更低。Note that in the long term it will be easier and less expensive to test one core application with several satellites, than to test and maintain several parallel international versions.

资源命名约定Resource naming conventions

在打包应用程序的资源时,必须使用公共语言运行时所要求的资源命名约定对其进行命名。When you package your application's resources, you must name them using the resource naming conventions that the common language runtime expects. 运行时可按其区域性名称标识资源。The runtime identifies a resource by its culture name. 每个区域性均被赋予唯一名称,通常是与语言相关的两个小写字母的区域性名称和必要情况下,与国家或地区相关的两个大写子母的区域性名称的组合。Each culture is given a unique name, which is usually a combination of a two-letter, lowercase culture name associated with a language and, if required, a two-letter, uppercase subculture name associated with a country or region. 子区域性名称跟在区域性名称后,以短划线 (-) 隔开。The subculture name follows the culture name, separated by a dash (-). 例如:ja-JP 表示日本日语,en-US 表示美国英语,de-DE 表示德国德语,de-AT 表示奥地利德语。Examples include ja-JP for Japanese as spoken in Japan, en-US for English as spoken in the United States, de-DE for German as spoken in Germany, or de-AT for German as spoken in Austria. 请参阅 Windows 支持的语言/区域名称列表中的“语言标记”列。See the Language tag column in the list of language/region names supported by Windows. 列名遵循 BCP 47 定义的标准。Culture names follow the standard defined by BCP 47.

备注

两个字母的区域性名称有一些例外,如中文(简体) zh-HansThere are some exceptions for the two-letter culture names, such as zh-Hans for Chinese (Simplified).

备注

有关创建资源文件的信息,请参阅创建资源文件创建附属程序集For information about creating resource files, see Creating Resource Files and Creating Satellite Assemblies.

资源回退进程The Resource Fallback Process

用于打包和部署资源的中枢轮辐式模型可使用回退过程来定位相应的资源。The hub and spoke model for packaging and deploying resources uses a fallback process to locate appropriate resources. 如果应用程序请求不可用的已本地化资源,则公共语言运行时会在区域性层次结构中查找与用户应用程序请求最匹配的合适回退资源,并且只在最后迫不得已的情况下才引发异常。If an application requests a localized resource that is unavailable, the common language runtime searches the hierarchy of cultures for an appropriate fallback resource that most closely matches the user's application's request, and throws an exception only as a last resort. 如果在层次结构的任意级别找到了合适的资源,运行时就会使用该资源。At each level of the hierarchy, if an appropriate resource is found, the runtime uses it. 如果未找到资源,则将继续在下一级别中搜索。If the resource is not found, the search continues at the next level.

若要提高查找性能,可将 NeutralResourcesLanguageAttribute 属性应用到主程序集,并向其传递将与主程序集一起使用的非特定语言的名称。To improve lookup performance, apply the NeutralResourcesLanguageAttribute attribute to your main assembly, and pass it the name of the neutral language that will work with your main assembly.

.NET Framework 资源回退进程.NET Framework resource fallback process

.NET Framework 资源回退进程包含以下步骤:The .NET Framework resource fallback process involves the following steps:

提示

还可以使用 <relativeBindForResources > 配置元素来优化资源回退过程和运行时针对资源程序集探测所依据的。You may be able to use the <relativeBindForResources> configuration element to optimize the resource fallback process and the process by which the runtime probes for resource assemblies. 有关详细信息,请参阅 优化资源回退进程一节。For more information, see the Optimizing the Resource Fallback Process section.

  1. 运行时首先检查全局程序集缓存,找到与为应用程序请求的区域性匹配的程序集。The runtime first checks the global assembly cache for an assembly that matches the requested culture for your application.

    全局程序集缓存可存储由许多应用程序共享的资源程序集。The global assembly cache can store resource assemblies that are shared by many applications. 这使你无需在创建的每个应用程序的目录结构中包括特定的资源集。This frees you from having to include specific sets of resources in the directory structure of every application you create. 如果运行时找到了对程序集的引用,它将搜索程序集,查找请求的资源。If the runtime finds a reference to the assembly, it searches the assembly for the requested resource. 如果在程序集中找到了该项,则使用请求的资源。If it finds the entry in the assembly, it uses the requested resource. 如果找不到该项,将继续搜索。If it doesn't find the entry, it continues the search.

  2. 接下来,运行时将检查当前正在执行程序集的目录,查找与请求的区域性匹配的子目录。The runtime next checks the directory of the currently executing assembly for a subdirectory that matches the requested culture. 如果找到该子目录,它将搜索该子目录以找到请求的区域性的有效附属程序集。If it finds the subdirectory, it searches that subdirectory for a valid satellite assembly for the requested culture. 然后,运行时将搜索附属程序集,寻找请求的资源。The runtime then searches the satellite assembly for the requested resource. 如果在程序集中找到该资源,则使用它。If it finds the resource in the assembly, it uses it. 如果找不到该资源,将继续搜索。If it doesn't find the resource, it continues the search.

  3. 接下来,运行时将查询 Windows Installer,以确定是否要按需安装附属程序集。The runtime next queries the Windows Installer to determine whether the satellite assembly is to be installed on demand. 如果是,它将处理安装,加载程序集,以及搜索它或搜索请求的资源。If so, it handles the installation, loads the assembly, and searches it or the requested resource. 如果在程序集中找到该资源,则使用它。If it finds the resource in the assembly, it uses it. 如果找不到该资源,将继续搜索。If it doesn't find the resource, it continues the search.

  4. 运行时引发 AppDomain.AssemblyResolve 事件以指示找不到附属程序集。The runtime raises the AppDomain.AssemblyResolve event to indicate that it is unable to find the satellite assembly. 如果选择对事件进行处理,事件处理程序可以返回对其资源将用于查找的附属程序集的引用。If you choose to handle the event, your event handler can return a reference to the satellite assembly whose resources will be used for the lookup. 否则,事件处理程序将返回 null,搜索继续。Otherwise, the event handler returns null and the search continues.

  5. 接下来,运行时将再次搜索全局程序集缓存,这次是为了请求的区域性的父程序集。The runtime next searches the global assembly cache again, this time for the parent assembly of the requested culture. 如果全局程序集缓存中存在父程序集,运行时将搜索程序集,寻找请求的资源。If the parent assembly exists in the global assembly cache, the runtime searches the assembly for the requested resource.

    父区域性被定义为合适的回退区域性。The parent culture is defined as the appropriate fallback culture. 将父区域性视为回退候选项,因为提供任何资源都比引发异常更可取。Consider parents as fallback candidates, because providing any resource is preferable to throwing an exception. 此过程还允许重复使用资源。This process also allows you to reuse resources. 仅当子无需本地化所请求的资源时,才应在父级别包含特定资源。You should include a particular resource at the parent level only if the child culture doesn't need to localize the requested resource. 例如,如果提供 en(非特定英语)的附属程序集:en-GB(英国英语)和 en-US(美国英语),则 en 附属程序集应包含公共术语,并且 en-GBen-US 附属程序集可能只对那些不同的术语提供替代项。For example, if you supply satellite assemblies for en (neutral English), en-GB (English as spoken in the United Kingdom), and en-US (English as spoken in the United States), the en satellite would contain the common terminology, and the en-GB and en-US satellites could provide overrides for only those terms that differ.

  6. 接下来,运行时将检查当前正在执行程序集的目录,查看是否包含父目录。The runtime next checks the directory of the currently executing assembly to see if it contains a parent directory. 如果存在父目录,则运行时将搜索该目录,寻找父区域性的有效附属程序集。If a parent directory exists, the runtime searches the directory for a valid satellite assembly for the parent culture. 如果找到该程序集,运行时将搜索程序集,寻找请求的资源。If it finds the assembly, the runtime searches the assembly for the requested resource. 如果找到该资源,则使用它。If it finds the resource, it uses it. 如果找不到该资源,将继续搜索。If it doesn't find the resource, it continues the search.

  7. 接下来,运行时将查询 Windows Installer,以确定是否要按需安装父级附属程序集。The runtime next queries the Windows Installer to determine whether the parent satellite assembly is to be installed on demand. 如果是,它将处理安装,加载程序集,以及搜索它或搜索请求的资源。If so, it handles the installation, loads the assembly, and searches it or the requested resource. 如果在程序集中找到该资源,则使用它。If it finds the resource in the assembly, it uses it. 如果找不到该资源,将继续搜索。If it doesn't find the resource, it continues the search.

  8. 运行时引发 AppDomain.AssemblyResolve 事件以指示找不到合适的回退资源。The runtime raises the AppDomain.AssemblyResolve event to indicate that it is unable to find an appropriate fallback resource. 如果选择对事件进行处理,事件处理程序可以返回对其资源将用于查找的附属程序集的引用。If you choose to handle the event, your event handler can return a reference to the satellite assembly whose resources will be used for the lookup. 否则,事件处理程序将返回 null,搜索继续。Otherwise, the event handler returns null and the search continues.

  9. 接下来,如前前面三个步骤所述,运行时将通过许多可能的级别搜索父程序集。The runtime next searches parent assemblies, as in the previous three steps, through many potential levels. 每个区域性只有一个父区域性(由 CultureInfo.Parent 属性定义),但一个父区域性可能还有其自己的父区域性。Each culture has only one parent, which is defined by the CultureInfo.Parent property, but a parent might have its own parent. 如果区域性的 Parent 属性返回 CultureInfo.InvariantCulture,父区域性搜索将停止;对于资源回退,固定区域性不被视为父区域性,也不被视为具有资源的区域性。The search for parent cultures stops when a culture's Parent property returns CultureInfo.InvariantCulture; for resource fallback, the invariant culture is not considered a parent culture or a culture that can have resources.

  10. 如果区域性是最初指定的,且已搜索所有父级,但仍未找到资源,则使用默认(回退)区域性的资源。If the culture that was originally specified and all parents have been searched and the resource is still not found, the resource for the default (fallback) culture is used. 通常,默认区域性的资源包含在主应用程序集中。Typically, the resources for the default culture are included in the main application assembly. 但是,可指定 NeutralResourcesLanguageAttribute 特性的 Location 属性的值为 Satellite,以指定资源的最终回退位置是附属程序集,而不是主程序集。However, you can specify a value of Satellite for the Location property of the NeutralResourcesLanguageAttribute attribute to indicate that the ultimate fallback location for resources is a satellite assembly, rather than the main assembly.

    备注

    默认资源是唯一可与主程序集一起编译的资源。The default resource is the only resource that can be compiled with the main assembly. 除非通过使用 NeutralResourcesLanguageAttribute 属性指定附属程序集,否则为最终回退(最终父级)。Unless you specify a satellite assembly by using the NeutralResourcesLanguageAttribute attribute, it is the ultimate fallback (final parent). 因此,建议在主程序集中始终包含一组默认资源。Therefore, we recommend that you always include a default set of resources in your main assembly. 这有助于防止引发异常。This helps prevent exceptions from being thrown. 通过包含默认资源文件,可为所有资源提供回退,并确保始终向用户呈现至少一种资源,即使该资源不是特定于区域性的。By including a default resource, file you provide a fallback for all resources and ensure that at least one resource is always present for the user, even if it is not culturally specific.

  11. 最后,如果运行时找不到默认(回退)区域性的资源,将引发 MissingManifestResourceExceptionMissingSatelliteAssemblyException 异常,指示找不到该资源。Finally, if the runtime doesn't find a resource for a default (fallback) culture, a MissingManifestResourceException or MissingSatelliteAssemblyException exception is thrown to indicate that the resource could not be found.

例如,假定应用程序请求本地化为墨西哥西班牙语(es-MX 区域性)所需的资源。For example, suppose the application requests a resource localized for Spanish (Mexico) (the es-MX culture). 运行时将首先搜索全局程序集缓存,寻找匹配 es-MX 的程序集,但找不到。The runtime first searches the global assembly cache for the assembly that matches es-MX, but doesn't find it. 然后,运行时将搜索当前正在执行的程序集,寻找 es-MX 目录。The runtime then searches the directory of the currently executing assembly for an es-MX directory. 如果失败,运行时将再次搜索全局程序集缓存,寻找反映相应回退区域性的父程序集 — 在本例中为 es(西班牙语)。Failing that, the runtime searches the global assembly cache again for a parent assembly that reflects the appropriate fallback culture — in this case, es (Spanish). 如果找不到父程序集,运行时将针对 es-MX 区域性搜索父程序集的所有可能级别,直到它找到对应的资源。If the parent assembly is not found, the runtime searches all potential levels of parent assemblies for the es-MX culture until it finds a corresponding resource. 如果找不到资源,运行时将使用默认区域性的资源。If a resource isn't found, the runtime uses the resource for the default culture.

优化 .NET Framework 资源回退进程Optimizing the .NET Framework Resource Fallback Process

在下列情况下,可以按运行时搜索附属程序集中的资源所依据的内容优化进程Under the following conditions, you can optimize the process by which the runtime searches for resources in satellite assemblies

  • 附属程序集部署在与代码程序集相同的位置。Satellite assemblies are deployed in the same location as the code assembly. 如果代码程序集安装在全局程序集缓存中,则附属程序集也会安装到全局程序集缓存中。If the code assembly is installed in the Global Assembly Cache, satellite assemblies are also installed in the global assembly cache. 如果代码程序集安装在一个目录中,则附属程序集安装在该目录的特定于区域性的文件夹中。If the code assembly is installed in a directory, satellite assemblies are installed in culture-specific folders of that directory.

  • 附属程序集不会按需进行安装。Satellite assemblies are not installed on demand.

  • 应用程序代码不会处理 AppDomain.AssemblyResolve 事件。Application code does not handle the AppDomain.AssemblyResolve event.

可通过在应用程序配置文件中包含 <relativeBindForResources> 元素并将其 enabled 属性设为 true,优化附属程序集探测,如下例所示。You optimize the probe for satellite assemblies by including the <relativeBindForResources> element and setting its enabled attribute to true in the application configuration file, as shown in the following example.

<configuration>
   <runtime>
      <relativeBindForResources enabled="true" />
   </runtime>
</configuration>

优化的附属程序集探测是选择加入功能。The optimized probe for satellite assemblies is an opt-in feature. 也就是说,运行时遵循资源回退进程中记录的步骤,除非 <relativeBindForResources> 元素位于应用程序的配置文件中,并且其 enabled 属性已设为 trueThat is, the runtime follows the steps documented in The Resource Fallback Process unless the <relativeBindForResources> element is present in the application's configuration file and its enabled attribute is set to true. 如果出现这种情况,附属程序集探测过程将进行如下修改:If this is the case, the process of probing for a satellite assembly is modified as follows:

  • 运行时使用父代码程序集位置来探测附属程序集。The runtime uses the location of the parent code assembly to probe for the satellite assembly. 如果父程序集安装在全局程序集缓存中,则运行时在缓存,而不是在应用程序的目录中探测。If the parent assembly is installed in the global assembly cache, the runtime probes in the cache but not in the application's directory. 如果父程序集安装在应用程序目录中,则运行时在应用程序目录,而不是在全局程序集缓存中探测。If the parent assembly is installed in an application directory, the runtime probes in the application directory but not in the global assembly cache.

  • 运行时不会查询 Windows Installer,寻找附属程序集的按需安装。The runtime doesn't query the Windows Installer for on-demand installation of satellite assemblies.

  • 如果特定资源程序集探测失败,运行时将不会引发 AppDomain.AssemblyResolve 事件。If the probe for a particular resource assembly fails, the runtime does not raise the AppDomain.AssemblyResolve event.

.NET Core 资源回退进程.NET Core resource fallback process

.NET Core 资源回退进程包含以下步骤:The .NET Core resource fallback process involves the following steps:

  1. 运行时尝试加载请求的区域性的附属程序集。The runtime attempts to load a satellite assembly for the requested culture.

    • 检查当前正在执行程序集的目录,查找与请求的区域性匹配的子目录。Checks the directory of the currently executing assembly for a subdirectory that matches the requested culture. 如果找到该子目录,它将搜索该子目录以找到请求的区域性的有效附属程序集并加载该程序集。If it finds the subdirectory, it searches that subdirectory for a valid satellite assembly for the requested culture and loads it.

      备注

      在具有区分大小写的文件系统(即 Linux 和 macOS)的操作系统上,区域性名称子目录搜索区分大小写。On operating systems with case-sensitive file systems (that is, Linux and macOS), the culture name subdirectory search is case-sensitive. 子目录名称必须与 CultureInfo.Name 的大小写完全匹配(例如,eses-MX)。The subdirectory name must exactly match the case of the CultureInfo.Name (for example, es or es-MX).

      备注

      如果程序员从 AssemblyLoadContext 派生了自定义程序集加载上下文,则情况会很复杂。If the programmer has derived a custom assembly load context from AssemblyLoadContext, the situation is complicated. 如果将正在执行程序集加载到自定义上下文中,则运行时会将附属程序集加载到自定义上下文中。If the executing assembly was loaded into the custom context, the runtime loads the satellite assembly into the custom context. 相关详细信息超出了本文档所涉及的范围。The details are out of scope for this document. 请参阅AssemblyLoadContextSee AssemblyLoadContext.

    • 如果未找到附属程序集,AssemblyLoadContext 引发 AssemblyLoadContext.Resolving 事件以指示找不到附属程序集。If a satellite assemble has not been found, the AssemblyLoadContext raises the AssemblyLoadContext.Resolving event to indicate that it is unable to find the satellite assembly. 如果选择对事件进行处理,事件处理程序可以加载引用并返回对附属程序集的引用。If you choose to handle the event, your event handler can load and return a reference to the satellite assembly.

    • 如果仍未找到附属程序集,则 AssemblyLoadContext 会导致 AppDomain 触发 AppDomain.AssemblyResolve 事件以指示找不到附属程序集。If a satellite assembly still has not been found, the AssemblyLoadContext causes the AppDomain to trigger an AppDomain.AssemblyResolve event to indicate that it is unable to find the satellite assembly. 如果选择对事件进行处理,事件处理程序可以加载引用并返回对附属程序集的引用。If you choose to handle the event, your event handler can load and return a reference to the satellite assembly.

  2. 如果找到附属程序集,则运行时将搜索请求的资源的附属程序集。If a satellite assembly is found, the runtime searches it for the requested resource. 如果在程序集中找到该资源,则使用它。If it finds the resource in the assembly, it uses it. 如果找不到该资源,将继续搜索。If it doesn't find the resource, it continues the search.

    备注

    要在附属程序集中查找资源,运行时将搜索 ResourceManager 为当前 CultureInfo.Name 请求的资源文件。To find a resource within the satellite assembly, the runtime searches for the resource file requested by the ResourceManager for the current CultureInfo.Name. 在资源文件中,它搜索所请求的资源名称。Within the resource file it searches for the requested resource name. 如果找不到上述任何一个,则资源将被视为未找到。If either is not found, the resource is treated as not found.

  3. 接下来,运行时通过许多潜在级别搜索父区域性程序集,每次均重复步骤 1 和 2。The runtime next searches the parent culture assemblies through many potential levels, each time repeating steps 1 & 2.

    父区域性被定义为合适的回退区域性。The parent culture is defined as an appropriate fallback culture. 将父区域性视为回退候选项,因为提供任何资源都比引发异常更可取。Consider parents as fallback candidates, because providing any resource is preferable to throwing an exception. 此过程还允许重复使用资源。This process also allows you to reuse resources. 仅当子无需本地化所请求的资源时,才应在父级别包含特定资源。You should include a particular resource at the parent level only if the child culture doesn't need to localize the requested resource. 例如,如果提供 en(非特定英语)的附属程序集:en-GB(英国英语)和 en-US(美国英语),则 en 附属程序集应包含公共术语,并且 en-GBen-US 附属程序集只对那些不同的术语提供替代项。For example, if you supply satellite assemblies for en (neutral English), en-GB (English as spoken in the United Kingdom), and en-US (English as spoken in the United States), the en satellite contains the common terminology, and the en-GB and en-US satellites provides overrides for only those terms that differ.

    每个区域性只有一个父区域性(由 CultureInfo.Parent 属性定义),但一个父区域性可能还有其自己的父区域性。Each culture has only one parent, which is defined by the CultureInfo.Parent property, but a parent might have its own parent. 当区域性的 Parent 属性返回 CultureInfo.InvariantCulture 时,父区域性搜索将停止。The search for parent cultures stops when a culture's Parent property returns CultureInfo.InvariantCulture. 对于资源回退,固定区域性不被视为父区域性,也不被视为具有资源的区域性。For resource fallback, the invariant culture is not considered a parent culture or a culture that can have resources.

  4. 如果区域性是最初指定的,且已搜索所有父级,但仍未找到资源,则使用默认(回退)区域性的资源。If the culture that was originally specified and all parents have been searched and the resource is still not found, the resource for the default (fallback) culture is used. 通常,默认区域性的资源包含在主应用程序集中。Typically, the resources for the default culture are included in the main application assembly. 但是,可指定 Location 属性的值为 Satellite,以指示资源的最终回退位置是附属程序集,而不是主程序集。However, you can specify a value of Satellite for the Location property to indicate that the ultimate fallback location for resources is a satellite assembly rather than the main assembly.

    备注

    默认资源是唯一可与主程序集一起编译的资源。The default resource is the only resource that can be compiled with the main assembly. 除非通过使用 NeutralResourcesLanguageAttribute 属性指定附属程序集,否则为最终回退(最终父级)。Unless you specify a satellite assembly by using the NeutralResourcesLanguageAttribute attribute, it is the ultimate fallback (final parent). 因此,建议在主程序集中始终包含一组默认资源。Therefore, we recommend that you always include a default set of resources in your main assembly. 这有助于防止引发异常。This helps prevent exceptions from being thrown. 通过包含默认资源文件,可为所有资源提供回退,并确保始终向用户呈现至少一种资源,即使该资源不是特定于区域性的。By including a default resource file, you provide a fallback for all resources and ensure that at least one resource is always present for the user, even if it is not culturally specific.

  5. 最后,如果运行时找不到默认(回退)区域性的资源文件,将引发 MissingManifestResourceExceptionMissingSatelliteAssemblyException 异常,指示找不到该资源。Finally, if the runtime doesn't find a resource file for a default (fallback) culture, a MissingManifestResourceException or MissingSatelliteAssemblyException exception is thrown to indicate that the resource could not be found. 如果找到资源文件但是请求的资源不存在,则请求返回 nullIf the resource file is found but the requested resource is not present the request returns null.

最终回退到附属程序集Ultimate Fallback to Satellite Assembly

可选择从主程序集中删除资源,并指定运行时应加载对应于特定区域性的附属程序集中的最终回退资源。You can optionally remove resources from the main assembly and specify that the runtime should load the ultimate fallback resources from a satellite assembly that corresponds to a specific culture. 若要控制回退进程,请使用 NeutralResourcesLanguageAttribute.NeutralResourcesLanguageAttribute(String, UltimateResourceFallbackLocation) 构造函数并提供 UltimateResourceFallbackLocation 参数的值,用于指定 Resource Manager 是应从主程序集还是应从附属程序集中提取回退资源。To control the fallback process, you use the NeutralResourcesLanguageAttribute.NeutralResourcesLanguageAttribute(String, UltimateResourceFallbackLocation) constructor and supply a value for the UltimateResourceFallbackLocation parameter that specifies whether Resource Manager should extract the fallback resources from the main assembly or from a satellite assembly.

下面的 .NET Framework 示例使用 NeutralResourcesLanguageAttribute 属性将应用程序回退资源存储在法语 (fr) 语言的附属程序集中。The following .NET Framework example uses the NeutralResourcesLanguageAttribute attribute to store an application's fallback resources in a satellite assembly for the French (fr) language. 本示例介绍了两个基于文本的资源文件,这两个文件用于定义名为 Greeting 的单个字符串资源。The example has two text-based resource files that define a single string resource named Greeting. 第一个文件 resources.fr.txt 包含法语资源。The first, resources.fr.txt, contains a French language resource.

Greeting=Bon jour!

第二个文件 resources.ru.txt 包含俄语资源。The second, resources,ru.txt, contains a Russian language resource.

Greeting=Добрый день

从命令行运行资源文件生成器 (Resgen.exe) 可将这两个文件编译为 .resources 文件。These two files are compiled to .resources files by running the resource file generator (Resgen.exe) from the command line. 对于法语资源,命令为:For the French language resource, the command is:

resgen.exe resources.fr.txtresgen.exe resources.fr.txt

对于俄语资源,命令为:For the Russian language resource, the command is:

resgen.exe resources.ru.txtresgen.exe resources.ru.txt

对于法语资源,从命令行运行程序集连接器 (Al.exe),将 .resources 文件嵌入动态链接库,如下所示:The .resources files are embedded into dynamic link libraries by running assembly linker (Al.exe) from the command line for the French language resource as follows:

al /t:lib /embed:resources.fr.resources /culture:fr /out:fr\Example1.resources.dllal /t:lib /embed:resources.fr.resources /culture:fr /out:fr\Example1.resources.dll

而对于俄语资源,则为如下所示:and for the Russian language resource as follows:

al /t:lib /embed:resources.ru.resources /culture:ru /out:ru\Example1.resources.dllal /t:lib /embed:resources.ru.resources /culture:ru /out:ru\Example1.resources.dll

应用程序源代码位于名为 Example1.cs 或 Example1.vb 的文件中。The application source code resides in a file named Example1.cs or Example1.vb. 它包括 NeutralResourcesLanguageAttribute 属性,以指示默认应用程序资源位于 fr 子目录中。It includes the NeutralResourcesLanguageAttribute attribute to indicate that the default application resource is in the fr subdirectory. 它可实例化 Resource Manager,检索 Greeting 资源的值,并将其显示到控制台。It instantiates the Resource Manager, retrieves the value of the Greeting resource, and displays it to the console.

using System;
using System.Reflection;
using System.Resources;

[assembly:NeutralResourcesLanguage("fr", UltimateResourceFallbackLocation.Satellite)]

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("resources", 
                                               typeof(Example).Assembly);
      string greeting = rm.GetString("Greeting");
      Console.WriteLine(greeting); 
   }
}
Imports System.Reflection
Imports System.Resources

<Assembly:NeutralResourcesLanguage("fr", UltimateResourceFallbackLocation.Satellite)>
Module Example
   Public Sub Main()
      Dim rm As New ResourceManager("resources", GetType(Example).Assembly)
      Dim greeting As String = rm.GetString("Greeting")
      Console.WriteLine(greeting) 
   End Sub
End Module

然后,可以从命令行编译 C# 源代码,如下所示:You can then compile C# source code from the command line as follows:

csc Example1.cs

用于 Visual Basic 编译器的命令十分相似:The command for the Visual Basic compiler is very similar:

vbc Example1.vb

由于没有嵌入在主程序集中的资源,因此无需使用 /resource 切换进行编译。Because there are no resources embedded in the main assembly, you do not have to compile by using the /resource switch.

当从不是俄语的任何系统运行示例时,它将显示以下输出:When you run the example from a system whose language is anything other than Russian, it displays the following output:

Bon jour!

建议的打包替代项Suggested Packaging Alternative

由于时间或预算约束,可能无法为应用程序支持的每个子区域性均创建一组资源。Time or budget constraints might prevent you from creating a set of resources for every subculture that your application supports. 但可以为所有相关子区域性可用的父区域性创建单个附属程序集。Instead, you can create a single satellite assembly for a parent culture that all related subcultures can use. 例如,可以提供单个英语附属程序集 (en),请求特定于区域的英语资源的用户将检索该程序集,并且为请求特定于区域的德语资源的用户创建单个德语附属程序集 (de)。For example, you can provide a single English satellite assembly (en) that is retrieved by users who request region-specific English resources, and a single German satellite assembly (de) for users who request region-specific German resources. 例如,对德国德语 (de-DE)、奥地利德语 (de-AT) 和瑞士德语 (de-CH) 的请求均会回退到德语附属程序集 (de)。For example, requests for German as spoken in Germany (de-DE), Austria (de-AT), and Switzerland (de-CH) would fall back to the German satellite assembly (de). 默认资源是最终回退资源,因而应是大多数应用程序用户将请求的资源,因此应仔细选择这些资源。The default resources are the final fallback and therefore should be the resources that will be requested by the majority of your application's users, so choose these resources carefully. 此方法可部署区域性特定性较低,但可显著减少应用程序本地化成本的资源。This approach deploys resources that are less culturally specific, but can significantly reduce your application's localization costs.

请参阅See also