Share via


Resources verpakken en implementeren in .NET-apps

Toepassingen zijn afhankelijk van .NET Framework Resource Manager, vertegenwoordigd door de ResourceManager klasse, om gelokaliseerde resources op te halen. In Resource Manager wordt ervan uitgegaan dat een hub- en spoke-model wordt gebruikt voor het verpakken en implementeren van resources. De hub is de hoofdassembly die de niet-lokale uitvoerbare code en de resources voor één cultuur bevat, de neutrale of standaardcultuur. De standaardcultuur is de terugvalcultuur voor de toepassing; het is de cultuur waarvan de resources worden gebruikt als gelokaliseerde resources niet kunnen worden gevonden. Elke spoke maakt verbinding met een satellietassembly die de resources voor één cultuur bevat, maar bevat geen code.

Dit model heeft verschillende voordelen:

  • U kunt incrementeel resources toevoegen voor nieuwe culturen nadat u een toepassing hebt geïmplementeerd. Omdat de daaropvolgende ontwikkeling van cultuurspecifieke resources een aanzienlijke hoeveelheid tijd kan vergen, kunt u hiermee uw hoofdtoepassing eerst vrijgeven en op een later tijdstip cultuurspecifieke resources leveren.
  • U kunt de satellietassembly's van een toepassing bijwerken en wijzigen zonder de toepassing opnieuw te compileren.
  • Een toepassing moet alleen die satellietassembly's laden die de resources bevatten die nodig zijn voor een bepaalde cultuur. Dit kan het gebruik van systeembronnen aanzienlijk verminderen.

Er zijn echter ook nadelen voor dit model:

  • U moet meerdere sets resources beheren.
  • De initiële kosten voor het testen van een toepassing nemen toe, omdat u verschillende configuraties moet testen. Houd er rekening mee dat het op lange termijn eenvoudiger en goedkoper is om één kerntoepassing met meerdere satellieten te testen, dan om verschillende parallelle internationale versies te testen en te onderhouden.

Naamconventies voor resources

Wanneer u de resources van uw toepassing inpakt, moet u deze een naam geven met behulp van de resourcenaamconventies die de algemene taalruntime verwacht. De runtime identificeert een resource op basis van de naam van de cultuur. Elke cultuur krijgt een unieke naam. Dit is meestal een combinatie van een cultuurnaam met twee letters, kleine letters die aan een taal zijn gekoppeld en, indien nodig, een subcultuurnaam met twee letters die aan een land of regio zijn gekoppeld. De naam van de subcultuur volgt de cultuurnaam, gescheiden door een streepje (-). Voorbeelden zijn ja-JP voor Japans zoals gesproken in Japan, en-US voor Engels zoals gesproken in de Verenigde Staten, de-DE voor Duits zoals gesproken in Duitsland of de-AT voor Duits zoals gesproken in Oostenrijk. Zie de kolom Taaltag in de lijst met taal-/regionamen die worden ondersteund door Windows. Cultuurnamen volgen de standaard die is gedefinieerd door BCP 47.

Notitie

Er zijn enkele uitzonderingen voor de tweeletterige cultuurnamen, zoals zh-Hans voor Chinees (vereenvoudigd).

Zie Resourcebestanden maken en Satellietassembly's maken voor meer informatie.

Het terugvalproces voor resources

Het hub- en spoke-model voor het verpakken en implementeren van resources maakt gebruik van een terugvalproces om de juiste resources te vinden. Als een toepassing een gelokaliseerde resource aanvraagt die niet beschikbaar is, zoekt de algemene taalruntime in de hiërarchie van culturen naar een geschikte terugvalresource die het meest overeenkomt met de aanvraag van de gebruiker en genereert een uitzondering alleen als laatste redmiddel. Op elk niveau van de hiërarchie, als er een geschikte resource wordt gevonden, wordt deze door de runtime gebruikt. Als de resource niet wordt gevonden, wordt de zoekopdracht voortgezet op het volgende niveau.

Als u de opzoekprestaties wilt verbeteren, past u het NeutralResourcesLanguageAttribute kenmerk toe op uw hoofdassembly en geeft u dit door aan de naam van de neutrale taal die met uw hoofdassembly werkt.

Terugvalproces voor .NET Framework-resources

Het terugvalproces van .NET Framework-resources omvat de volgende stappen:

Tip

Mogelijk kunt u het <configuratie-element relativeBindForResources> gebruiken om het terugvalproces van resources te optimaliseren en het proces waarmee de runtime test voor resourceassembly's. Zie Het terugvalproces voor resources optimaliseren voor meer informatie.

  1. De runtime controleert eerst de globale assemblycache op een assembly die overeenkomt met de aangevraagde cultuur voor uw toepassing.

    De globale assemblycache kan resourceassembly's opslaan die worden gedeeld door veel toepassingen. Hierdoor hoeft u geen specifieke sets resources op te nemen in de mapstructuur van elke toepassing die u maakt. Als de runtime een verwijzing naar de assembly vindt, zoekt deze de assembly naar de aangevraagde resource. Als de vermelding in de assembly wordt gevonden, wordt de aangevraagde resource gebruikt. Als de vermelding niet wordt gevonden, wordt de zoekopdracht voortgezet.

  2. De runtime controleert vervolgens de map van de momenteel uitgevoerde assembly voor een submap die overeenkomt met de aangevraagde cultuur. Als de submap wordt gevonden, zoekt de submap naar een geldige satellietassembly voor de aangevraagde cultuur. De runtime doorzoekt vervolgens de satellietassembly voor de aangevraagde resource. Als de resource in de assembly wordt gevonden, wordt deze gebruikt. Als de resource niet wordt gevonden, wordt de zoekopdracht voortgezet.

  3. De runtime voert vervolgens een query uit op Windows Installer om te bepalen of de satellietassembly op aanvraag moet worden geïnstalleerd. Als dat het het volgende is, wordt de installatie verwerkt, de assembly geladen en wordt deze of de aangevraagde resource doorzocht. Als de resource in de assembly wordt gevonden, wordt deze gebruikt. Als de resource niet wordt gevonden, wordt de zoekopdracht voortgezet.

  4. De runtime genereert de AppDomain.AssemblyResolve gebeurtenis om aan te geven dat de satellietassembly niet kan worden gevonden. Als u ervoor kiest om de gebeurtenis af te handelen, kan uw gebeurtenishandler een verwijzing retourneren naar de satellietassembly waarvan de resources worden gebruikt voor de zoekactie. Anders wordt de gebeurtenis-handler geretourneerd null en wordt de zoekopdracht voortgezet.

  5. De runtime doorzoekt de globale assemblycache opnieuw, deze keer voor de bovenliggende assembly van de aangevraagde cultuur. Als de bovenliggende assembly bestaat in de globale assemblycache, zoekt de runtime de assembly naar de aangevraagde resource.

    De bovenliggende cultuur wordt gedefinieerd als de juiste terugvalcultuur. Overweeg ouders als terugvalkandidaten, omdat het verstrekken van een resource de voorkeur verdient om een uitzondering te genereren. Met dit proces kunt u ook resources opnieuw gebruiken. U moet alleen een bepaalde resource op het bovenliggende niveau opnemen als de onderliggende cultuur de aangevraagde resource niet hoeft te lokaliseren. Als u bijvoorbeeld satellietassembly's levert voor en (neutraal Engels), en-GB (Engels zoals gesproken in het Verenigd Koninkrijk) en en-US (Engels zoals gesproken in de Verenigde Staten), zou de en satelliet de gemeenschappelijke terminologie bevatten en kunnen de en-GB en en-US satellieten alleen onderdrukkingen bieden voor alleen de termen die verschillen.

  6. De runtime controleert vervolgens de map van de momenteel uitgevoerde assembly om te zien of deze een bovenliggende map bevat. Als er een bovenliggende map bestaat, zoekt de runtime de map naar een geldige satellietassembly voor de bovenliggende cultuur. Als de assembly wordt gevonden, zoekt de runtime de assembly naar de aangevraagde resource. Als de resource wordt gevonden, wordt deze gebruikt. Als de resource niet wordt gevonden, wordt de zoekopdracht voortgezet.

  7. De runtime voert vervolgens een query uit op windows Installer om te bepalen of de bovenliggende satellietassembly op aanvraag moet worden geïnstalleerd. Als dat het het volgende is, wordt de installatie verwerkt, de assembly geladen en wordt deze of de aangevraagde resource doorzocht. Als de resource in de assembly wordt gevonden, wordt deze gebruikt. Als de resource niet wordt gevonden, wordt de zoekopdracht voortgezet.

  8. De runtime genereert de AppDomain.AssemblyResolve gebeurtenis om aan te geven dat er geen geschikte terugvalresource kan worden gevonden. Als u ervoor kiest om de gebeurtenis af te handelen, kan uw gebeurtenishandler een verwijzing retourneren naar de satellietassembly waarvan de resources worden gebruikt voor de zoekactie. Anders wordt de gebeurtenis-handler geretourneerd null en wordt de zoekopdracht voortgezet.

  9. De runtime doorzoekt vervolgens bovenliggende assembly's, zoals in de vorige drie stappen, door veel potentiële niveaus. Elke cultuur heeft slechts één bovenliggend element, dat wordt gedefinieerd door de CultureInfo.Parent eigenschap, maar een bovenliggend element kan een eigen bovenliggend element hebben. Het zoeken naar bovenliggende culturen stopt wanneer de eigenschap van Parent een cultuur terugkeert CultureInfo.InvariantCulture; voor terugval van resources wordt de invariante cultuur niet beschouwd als een bovenliggende cultuur of een cultuur die resources kan hebben.

  10. Als de cultuur die oorspronkelijk is opgegeven en alle ouders zijn doorzocht en de resource nog steeds niet wordt gevonden, wordt de resource voor de standaardcultuur (terugval) gebruikt. Normaal gesproken worden de resources voor de standaardcultuur opgenomen in de hoofdtoepassingsassembly. U kunt echter een waarde opgeven voor Satellite de eigenschap van het LocationNeutralResourcesLanguageAttribute kenmerk om aan te geven dat de ultieme terugvallocatie voor resources een satellietassembly is in plaats van de hoofdassembly.

    Notitie

    De standaardresource is de enige resource die kan worden gecompileerd met de hoofdassembly. Tenzij u een satellietassembly opgeeft met behulp van het NeutralResourcesLanguageAttribute kenmerk, is dit de ultieme terugval (laatste bovenliggende). Daarom raden we u aan altijd een standaardset resources op te nemen in uw hoofdassembly. Hiermee voorkomt u dat uitzonderingen worden gegenereerd. Door een standaardresource op te geven, geeft u een terugval op voor alle resources en zorgt u ervoor dat ten minste één resource altijd aanwezig is voor de gebruiker, zelfs als het niet cultureel specifiek is.

  11. Als de runtime ten slotte geen resource voor een standaardcultuur (terugval) vindt, wordt er een MissingManifestResourceException of MissingSatelliteAssemblyException meer uitzonderingen gegenereerd om aan te geven dat de resource niet kan worden gevonden.

Stel dat de toepassing een resource aanvraagt die is gelokaliseerd voor Spaans (Mexico) (de es-MX cultuur). De runtime zoekt eerst in de algemene assemblycache naar de assembly die overeenkomt es-MX, maar vindt deze niet. De runtime doorzoekt vervolgens de map van de assembly die momenteel wordt uitgevoerd voor een es-MX map. Als dat niet lukt, zoekt de runtime opnieuw in de globale assemblycache naar een bovenliggende assembly die de juiste terugvalcultuur weerspiegelt, es in dit geval (Spaans). Als de bovenliggende assembly niet wordt gevonden, zoekt de runtime alle mogelijke niveaus van bovenliggende assembly's naar de es-MX cultuur totdat er een bijbehorende resource wordt gevonden. Als een resource niet wordt gevonden, gebruikt de runtime de resource voor de standaardcultuur.

Het terugvalproces voor .NET Framework-resources optimaliseren

Onder de volgende omstandigheden kunt u het proces optimaliseren waarmee de runtime zoekt naar resources in satellietassembly's:

  • Satellietassembly's worden geïmplementeerd op dezelfde locatie als de codeassembly. Als de codeassembly is geïnstalleerd in de Global Assembly Cache, worden satellietassembly's ook geïnstalleerd in de globale assemblycache. Als de codeassembly is geïnstalleerd in een map, worden satellietassembly's geïnstalleerd in cultuurspecifieke mappen van die map.

  • Satellietassembly's worden niet op aanvraag geïnstalleerd.

  • De toepassingscode verwerkt de AppDomain.AssemblyResolve gebeurtenis niet.

U optimaliseert de test voor satellietassembly's door het <element relativeBindForResources> op te slaan en het kenmerk true ervan enabled in te stellen in het toepassingsconfiguratiebestand, zoals wordt weergegeven in het volgende voorbeeld.

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

De geoptimaliseerde test voor satellietassembly's is een opt-in-functie. Dat wil gezegd, volgt de runtime de stappen die worden beschreven in het terugvalproces van de resource, tenzij het <element relativeBindForResources> aanwezig is in het configuratiebestand van de toepassing en het enabled kenmerk is ingesteld op true. Als dit het geval is, wordt het proces voor het testen van een satellietassembly als volgt gewijzigd:

  • De runtime gebruikt de locatie van de bovenliggende codeassembly om de satellietassembly te testen. Als de bovenliggende assembly is geïnstalleerd in de globale assemblycache, wordt de runtime in de cache uitgevoerd, maar niet in de map van de toepassing. Als de bovenliggende assembly is geïnstalleerd in een toepassingsmap, wordt de runtime in de toepassingsmap uitgevoerd, maar niet in de globale assemblycache.

  • Tijdens de runtime wordt geen query uitgevoerd op Windows Installer voor installatie op aanvraag van satellietassembly's.

  • Als de test voor een bepaalde resourceassembly mislukt, wordt de gebeurtenis niet gegenereerd door de AppDomain.AssemblyResolve runtime.

Terugvalproces voor .NET Core-resources

Het terugvalproces voor .NET Core-resources omvat de volgende stappen:

  1. De runtime probeert een satellietassembly te laden voor de aangevraagde cultuur.

    • Controleert de map van de momenteel uitgevoerde assembly voor een submap die overeenkomt met de aangevraagde cultuur. Als de submap wordt gevonden, zoekt de submap naar een geldige satellietassembly voor de aangevraagde cultuur en wordt deze geladen.

      Notitie

      Op besturingssystemen met hoofdlettergevoelige bestandssystemen (dat wil gezegd, Linux en macOS), is de submap van de cultuurnaam zoeken hoofdlettergevoelig. De naam van CultureInfo.Name de submap moet exact overeenkomen met het hoofdlettergebruik (bijvoorbeeld es ).es-MX

      Notitie

      Als de programmeur een aangepaste assemblybelastingcontext heeft afgeleid van AssemblyLoadContext, is de situatie ingewikkeld. Als de uitvoerassembly in de aangepaste context is geladen, laadt de runtime de satellietassembly in de aangepaste context. De details vallen buiten het bereik van dit document. Zie AssemblyLoadContext.

    • Als er geen satellietassembly is gevonden, wordt de AssemblyLoadContextAssemblyLoadContext.Resolving gebeurtenis gegenereerd om aan te geven dat de satellietassembly niet kan worden gevonden. Als u ervoor kiest om de gebeurtenis af te handelen, kan uw gebeurtenishandler een verwijzing naar de satellietassembly laden en retourneren.

    • Als er nog steeds geen satellietassembly is gevonden, zorgt AssemblyLoadContext ervoor dat het AppDomain een AppDomain.AssemblyResolve gebeurtenis activeert om aan te geven dat de satellietassembly niet kan worden gevonden. Als u ervoor kiest om de gebeurtenis af te handelen, kan uw gebeurtenishandler een verwijzing naar de satellietassembly laden en retourneren.

  2. Als er een satellietassembly wordt gevonden, zoekt de runtime deze naar de aangevraagde resource. Als de resource in de assembly wordt gevonden, wordt deze gebruikt. Als de resource niet wordt gevonden, wordt de zoekopdracht voortgezet.

    Notitie

    Om een resource in de satellietassembly te vinden, zoekt de runtime naar het resourcebestand dat door de ResourceManager huidige is CultureInfo.Nameaangevraagd. In het resourcebestand wordt gezocht naar de aangevraagde resourcenaam. Als een van beide niet wordt gevonden, wordt de resource behandeld als niet gevonden.

  3. De runtime doorzoekt vervolgens de bovenliggende cultuurassembly's door een groot aantal mogelijke niveaus, telkens wanneer stap 1 & 2 wordt herhaald.

    De bovenliggende cultuur wordt gedefinieerd als een geschikte terugvalcultuur. Overweeg ouders als terugvalkandidaten, omdat het verstrekken van een resource de voorkeur verdient om een uitzondering te genereren. Met dit proces kunt u ook resources opnieuw gebruiken. U moet alleen een bepaalde resource op het bovenliggende niveau opnemen als de onderliggende cultuur de aangevraagde resource niet hoeft te lokaliseren. Als u bijvoorbeeld satellietassembly's levert voor en (neutraal Engels), en-GB (Engels zoals gesproken in het Verenigd Koninkrijk) en en-US (Engels zoals gesproken in de Verenigde Staten), bevat de en satelliet de gemeenschappelijke terminologie en de en-GB satellieten en-US bieden alleen onderdrukkingen voor die termen die verschillen.

    Elke cultuur heeft slechts één bovenliggend element, dat wordt gedefinieerd door de CultureInfo.Parent eigenschap, maar een bovenliggend element kan een eigen bovenliggend element hebben. Het zoeken naar bovenliggende culturen stopt wanneer de eigenschap van Parent een cultuur terugkeert CultureInfo.InvariantCulture. Voor terugval van resources wordt de invariante cultuur niet beschouwd als een bovenliggende cultuur of een cultuur die resources kan hebben.

  4. Als de cultuur die oorspronkelijk is opgegeven en alle ouders zijn doorzocht en de resource nog steeds niet wordt gevonden, wordt de resource voor de standaardcultuur (terugval) gebruikt. Normaal gesproken worden de resources voor de standaardcultuur opgenomen in de hoofdtoepassingsassembly. U kunt echter een waarde voor Satellite de Location eigenschap opgeven om aan te geven dat de ultieme terugvallocatie voor resources een satellietassembly is in plaats van de hoofdassembly.

    Notitie

    De standaardresource is de enige resource die kan worden gecompileerd met de hoofdassembly. Tenzij u een satellietassembly opgeeft met behulp van het NeutralResourcesLanguageAttribute kenmerk, is dit de ultieme terugval (laatste bovenliggende). Daarom raden we u aan altijd een standaardset resources op te nemen in uw hoofdassembly. Hiermee voorkomt u dat uitzonderingen worden gegenereerd. Door een standaardresourcebestand op te slaan, geeft u een terugval op voor alle resources en zorgt u ervoor dat ten minste één resource altijd aanwezig is voor de gebruiker, zelfs als het niet cultureel specifiek is.

  5. Als de runtime ten slotte geen resourcebestand voor een standaardcultuur (terugval) vindt, wordt er een MissingManifestResourceException of MissingSatelliteAssemblyException een uitzondering gegenereerd om aan te geven dat de resource niet kan worden gevonden. Als het resourcebestand wordt gevonden, maar de aangevraagde resource niet aanwezig is, wordt de aanvraag geretourneerd null.

Ultieme terugval naar satellietassemblage

U kunt eventueel resources uit de hoofdassembly verwijderen en opgeven dat de runtime de ultieme terugvalbronnen moet laden uit een satellietassembly die overeenkomt met een specifieke cultuur. Als u het terugvalproces wilt beheren, gebruikt u de NeutralResourcesLanguageAttribute(String, UltimateResourceFallbackLocation) constructor en geeft u een waarde op voor de UltimateResourceFallbackLocation parameter die aangeeft of Resource Manager de terugvalresources uit de hoofdassembly of uit een satellietassembly moet extraheren.

In het volgende .NET Framework-voorbeeld wordt het NeutralResourcesLanguageAttribute kenmerk gebruikt om de terugvalbronnen van een toepassing op te slaan in een satellietassembly voor de Franse (fr) taal. Het voorbeeld bevat twee op tekst gebaseerde resourcebestanden die één tekenreeksresource met de naam Greetingdefiniëren. De eerste, resources.fr.txt, bevat een Franse taalresource.

Greeting=Bon jour!

De tweede, resources, ru.txt, bevat een Russische taalresource.

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

Deze twee bestanden worden gecompileerd naar .resources-bestanden door Resource File Generator (resgen.exe) uit te voeren vanaf de opdrachtregel. Voor de Franse taalresource is de opdracht:

resgen.exe resources.fr.txt

Voor de Russische taalresource is de opdracht:

resgen.exe resources.ru.txt

De .resources-bestanden worden als volgt ingesloten in dynamische koppelingsbibliotheken door Assembly Linker (al.exe) uit te voeren vanaf de opdrachtregel voor de Franse taalresource:

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

en voor de Russische taalresource als volgt:

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

De broncode van de toepassing bevindt zich in een bestand met de naam Example1.cs of Example1.vb. Het bevat het NeutralResourcesLanguageAttribute kenmerk om aan te geven dat de standaardtoepassingsresource zich in de submap bevindt. Er wordt een instantie van Resource Manager gemaakt, de waarde van de Greeting resource opgehaald en weergegeven in de 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

U kunt vervolgens de C#-broncode als volgt compileren vanaf de opdrachtregel:

csc Example1.cs

De opdracht voor de Visual Basic-compiler is vergelijkbaar:

vbc Example1.vb

Omdat er geen resources zijn ingesloten in de hoofdassembly, hoeft u niet te compileren met behulp van de /resource switch.

Wanneer u het voorbeeld uitvoert vanuit een systeem waarvan de taal iets anders is dan Russisch, wordt de volgende uitvoer weergegeven:

Bon jour!

Voorgesteld alternatief voor verpakking

Met tijd- of budgetbeperkingen kunt u mogelijk geen set resources maken voor elke subcultuur die door uw toepassing wordt ondersteund. In plaats daarvan kunt u één satellietassembly maken voor een bovenliggende cultuur die alle gerelateerde subculturen kunnen gebruiken. U kunt bijvoorbeeld één Engelse satellietassembly (en) opgeven die wordt opgehaald door gebruikers die regiospecifieke Engelse resources aanvragen en één Duitse satellietassembly (de) voor gebruikers die regiospecifieke Duitse resources aanvragen. Aanvragen voor Duits zoals gesproken in Duitsland (de-DE), Oostenrijk (de-AT) en Zwitserland (de-CH) zouden bijvoorbeeld terugvallen op de Duitse satellietassembly (de). De standaardbronnen zijn de laatste terugval en moeten daarom de resources zijn die door het merendeel van de gebruikers van uw toepassing worden aangevraagd, dus kies deze resources zorgvuldig. Met deze aanpak worden resources geïmplementeerd die minder cultureel specifiek zijn, maar die de lokalisatiekosten van uw toepassing aanzienlijk kunnen verminderen.

Zie ook