Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Mer information om värdeförslaget för att lokalisera din app finns i Globalisering och lokalisering.
Om du vill att appen ska ha stöd för olika visningsspråk och du har strängliteraler i koden eller XAML-markerings- eller apppaketmanifestet flyttar du dessa strängar till en resursfil (.resw). Du kan sedan göra en översatt kopia av resursfilen för varje språk som appen stöder.
Hårdkodade strängliteraler kan visas i imperativ kod eller i XAML-markering, till exempel som textegenskapen för en TextBlock. De kan också visas i manifestkällfilen för apppaketet (den Package.appxmanifest
-filen), till exempel som värdet för Display Name på fliken Program i Visual Studio Manifest Designer. Flytta dessa strängar till en resursfil (.resw) och ersätt de hårdkodade strängliteralerna i din app och i manifestet med referenser till resursidentifierare.
Till skillnad från bildresurser, där endast en bildresurs finns i en bildresursfil, finns flera strängresurser i en strängresursfil. En strängresursfil är en resursfil (.resw) och du skapar vanligtvis den här typen av resursfil i en \Strings-mapp i projektet. Bakgrund om hur du använder kvalificerare i namnen på dina resursfiler (.resw) finns i Anpassa dina resurser för språk, skala och andra kvalificerare.
Lagra strängar i en resursfil
Ange appens standardspråk.
- När lösningen är öppen i Visual Studio öppnar du
Package.appxmanifest
. - På fliken Program bekräftar du att standardspråket har angetts korrekt (till exempel "en" eller "en-US"). De återstående stegen förutsätter att du har angett standardspråket till "en-US".
Anmärkning
Du måste minst ange strängresurser som är lokaliserade för det här standardspråket. Det är de resurser som läses in om det inte går att hitta någon bättre matchning för användarens önskade språk eller visningsspråkinställningar.
- När lösningen är öppen i Visual Studio öppnar du
Skapa en resursfil (.resw) för standardspråket.
- Under projektnoden skapar du en ny mapp och ger den
Strings
namnet . - Under
Strings
skapar du en ny undermapp och ger denen-US
namnet . - Under
en-US
skapar du en ny resursfil (.resw) (under XAML-filtyperna i dialogrutan Lägg till nytt objekt ) och bekräftar att den heterResources.resw
.
Anmärkning
Om du har .NET-resursfiler (.resx) som du vill överföra, se Portera XAML och användargränssnitt.
- Under projektnoden skapar du en ny mapp och ger den
Öppna
Resources.resw
och lägg till dessa strängresurser.Strings/en-US/Resources.resw
I det här exemplet är "Greeting" en strängresursidentifierare som du kan referera till från din kod, som vi kommer att visa. För identifieraren "Greeting" tillhandahålls en sträng för en textegenskap och en sträng tillhandahålls för en width-egenskap. "Greeting.Text" är ett exempel på en egenskapsidentifierare eftersom den motsvarar en egenskap för ett gränssnittselement. Du kan också till exempel lägga till "Greeting.Foreground" i kolumnen Namn och ange värdet "Red". Identifieraren "Farväl" är en enkel strängresursidentifierare. Den har inga underegenskaper och kan läsas in från imperativ kod, som vi kommer att visa. Kolumnen Kommentar är en bra plats för att ge alla särskilda instruktioner till översättare.
Eftersom vi i det här exemplet har en enkel post för strängresursidentifierare med namnet "Farväl" kan vi inte heller ha egenskapsidentifierare baserade på samma identifierare. Att lägga till "Farewell.Text" skulle därför orsaka ett Duplicate Entry-fel när du bygger
Resources.resw
.Resursidentifierare är skiftlägesokänsliga och måste vara unika per resursfil. Se till att använda meningsfulla resursidentifierare för att tillhandahålla ytterligare kontext för översättare. Och ändra inte resursidentifierarna när strängresurserna har skickats för översättning. Lokaliseringsteam använder resursidentifieraren för att spåra tillägg, borttagningar och uppdateringar i resurserna. Ändringar i resursidentifierare – som även kallas "resursidentifierare skiftar" – kräver att strängarna omöversätts, eftersom det verkar som om strängarna har tagits bort och andra har lagts till.
Referera till en strängresursidentifierare från XAML
Du använder ett x:Uid-direktiv för att associera en kontroll eller ett annat element i din markering med en strängresursidentifierare.
<TextBlock x:Uid="Greeting"/>
Under körning laddas \Strings\en-US\Resources.resw
in (eftersom det för tillfället är den enda resursfilen i projektet).
x:Uid-direktivet för TextBlock initierar en sökning för att hitta egenskapsidentifierare inuti Resources.resw
som innehåller strängresursidentifieraren "Greeting". Egenskapsidentifierarna "Greeting.Text" och "Greeting.Width" hittas och deras värden tillämpas på TextBlock, vilket översidosätter alla värden som anges lokalt i markeringen. Värdet "Greeting.Foreground" skulle också ha tillämpats om du hade lagt till det. Men endast egenskapsidentifierare används för att ange egenskaper för XAML-markeringselement, så att ställa in x:Uid på "Farväl" på denna TextBlock skulle inte ha någon effekt.
Resources.resw
innehåller strängresursidentifieraren "Farväl", men den innehåller inga egenskapsidentifierare för den.
När du tilldelar en strängresursidentifierare till ett XAML-element ska du vara säker på att alla egenskapsidentifierare för identifieraren är lämpliga för XAML-elementet. Om du till exempel anger x:Uid="Greeting"
på en TextBlock kommer "Greeting.Text" att lösas eftersom typen TextBlock har en Text-egenskap. Men om du anger x:Uid="Greeting"
en knapp orsakar "Greeting.Text" ett körningsfel eftersom knapptypen inte har någon textegenskap. En lösning för det fallet är att skapa en egenskapsidentifierare med namnet "ButtonGreeting.Content" och ställa in x:Uid="ButtonGreeting"
på knappen.
I stället för att ange Bredd från en resursfil vill du förmodligen tillåta att kontroller ändrar storlek på innehåll dynamiskt.
Obs För kopplade egenskaperbehöver du en särskild syntax i kolumnen Namn i en .resw-fil. Om du till exempel vill ange ett värde för den AutomationProperties.Name kopplade egenskapen för identifieraren "Hälsning" anger du det i kolumnen Namn.
Greeting.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name
Referera till en strängresursidentifierare från kod
Du kan uttryckligen läsa in en strängresurs baserat på en enkel strängresursidentifierare.
Anmärkning
Om du har ett anrop till någon GetForCurrentView- metod som kan köras på en bakgrunds-/arbetstråd, se till att skydda det anropet med ett if (Windows.UI.Core.CoreWindow.GetForCurrentThread() != null)
test. Att anropa GetForCurrentView från en bakgrunds-/arbetstråd resulterar i undantaget "<typename> kanske inte skapas på trådar som inte har en CoreWindow."
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");
auto resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() };
myXAMLTextBlockElement().Text(resourceLoader.GetString(L"Farewell"));
auto resourceLoader = Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView();
this->myXAMLTextBlockElement->Text = resourceLoader->GetString("Farewell");
Du kan använda samma kod inifrån ett UWP-klassbibliotek (.NET Native) eller ett UWP Windows Runtime Component-projekt (.NET Native). Vid körning läses resurserna i appen som är värd för biblioteket in. Vi rekommenderar att ett bibliotek läser in resurser från appen som är värd för den, eftersom appen sannolikt kommer att ha en högre grad av lokalisering. Om ett bibliotek behöver tillhandahålla resurser bör det ge värdappen möjlighet att ersätta dessa resurser som indata.
Om ett resursnamn är segmenterat (det innehåller "."-tecken), ersätts punkter med snedstreck ("/") i resursnamnet. Egenskapsidentifierare innehåller till exempel punkter; så du skulle behöva göra denna ersättning för att ladda in en av dem från koden.
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Fare/Well"); // <data name="Fare.Well" ...> ...
Om du är osäker kan du använda MakePri.exe för att dumpa appens PRI-fil. Varje resurss uri
visas i den dumpade filen.
<ResourceMapSubtree name="Fare"><NamedResource name="Well" uri="ms-resource://<GUID>/Resources/Fare/Well">...
Hänvisa till en strängresursidentifierare från manifestet för app-paketet
Appens paketmanifest är Package.appxmanifest
-filen i ditt projekt. Den innehåller metadata om din app, till exempel dess namn, beskrivning och funktioner. Du kan lokalisera strängar i manifestet med hjälp av en resursfil (.resw) och referera till strängresursidentifierare i manifestet.
Öppna apppaketets manifestkällfil (
Package.appxmanifest
filen), där appens som standard uttrycksDisplay name
som en strängliteral.Om du vill skapa en lokaliserad version av strängen öppnar
Resources.resw
du och lägger till en ny strängresurs med namnet "AppDisplayName" och värdet "Adventure Works Cycles".Ersätt strängliteralen för Visningsnamn med en referens till strängresursidentifieraren som du just har skapat ("AppDisplayName"). Du använder
ms-resource
URI-schemat (Uniform Resource Identifier) för att göra detta.Upprepa den här processen för varje sträng i manifestet som du vill lokalisera. Till exempel appens korta namn (som du kan konfigurera för att visas på appens panel på Start). En lista över alla objekt i apppaketmanifestet som du kan lokalisera finns i Localizable manifest items (Localizable manifest items).
Lokalisera strängresurserna
Nästa steg är att skapa en översatt kopia av resursfilen (.resw) för varje språk som appen stöder. Du kan sedan översätta strängarna i dessa filer.
Skapa en kopia av resursfilen (.resw) för ett annat språk.
- Under "Strängar" skapar du en ny undermapp och ger den namnet "de-DE" för Deutsch (Deutschland).
Not För mappnamnet kan du använda valfri BCP-47-språktagg. Mer information om språkkvalificeraren och en lista över vanliga språktaggar finns i Anpassa dina resurser för språk, skala och andra kvalificerare . - Skapa en kopia av
Strings/en-US/Resources.resw
iStrings/de-DE
mappen.
- Under "Strängar" skapar du en ny undermapp och ger den namnet "de-DE" för Deutsch (Deutschland).
Översätt strängarna.
- Öppna
Strings/de-DE/Resources.resw
och översätta värdena i kolumnen Värde. Du behöver inte översätta kommentarerna.
Strings/de-DE/Resources.resw
- Öppna
Om du vill kan du upprepa steg 1 och 2 för ytterligare ett språk.
Strings/fr-FR/Resources.resw
Testa din app
Testa appen för standardvisningsspråket. Du kan sedan ändra visningsspråket i Inställningar>Tid och Språkområde>och språkspråk> och testa appen igen. Titta på strängar i användargränssnittet och även i skalet (till exempel din titelrad, som är ditt visningsnamn, och det korta namnet på dina paneler).
Notera Om ett mappnamn som matchar inställningen för visningsspråk kan hittas, läses resursfilen in i den mappen. Annars sker tillbakagång, med slutpunkt i resurserna för appens standardspråk.
Dela in strängar i flera resursfiler
Du kan behålla alla dina strängar i en enda resursfil (resw) eller så kan du dela in dem i flera resursfiler. Du kanske till exempel vill behålla dina felmeddelanden i en resursfil, apppaketets manifeststrängar i en annan och dina användargränssnittssträngar i en tredje. Så här skulle mappstrukturen se ut i så fall.
Om du vill begränsa en referens för strängresursidentifierare till en viss fil lägger du bara till /<resources-file-name>/
före identifieraren. Markeringsexemplet nedan förutsätter att ErrorMessages.resw
det innehåller en resurs vars namn är "PasswordTooWeak.Text" och vars värde beskriver felet.
<TextBlock x:Uid="/ErrorMessages/PasswordTooWeak"/>
Du behöver bara lägga till /<resources-file-name>/
före strängresursidentifieraren för resursfiler förutomResources.resw
. Det beror på att "Resources.resw" är standardfilnamnet, så det är vad som antas om du utelämnar ett filnamn (som vi gjorde i de tidigare exemplen i det här avsnittet).
Kodexemplet nedan förutsätter att ErrorMessages.resw
det innehåller en resurs vars namn är "MismatchedPasswords" och vars värde beskriver felet.
Anmärkning
Om du har ett anrop till någon GetForCurrentView- metod som kan köras på en bakgrunds-/arbetstråd, se till att skydda det anropet med ett if (Windows.UI.Core.CoreWindow.GetForCurrentThread() != null)
test. Att anropa GetForCurrentView från en bakgrunds-/arbetstråd resulterar i undantaget "<typename> kanske inte skapas på trådar som inte har en CoreWindow."
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("ErrorMessages");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("MismatchedPasswords");
auto resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView(L"ErrorMessages") };
myXAMLTextBlockElement().Text(resourceLoader.GetString(L"MismatchedPasswords"));
auto resourceLoader = Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView("ErrorMessages");
this->myXAMLTextBlockElement->Text = resourceLoader->GetString("MismatchedPasswords");
Om du skulle flytta din "AppDisplayName"-resurs från Resources.resw
och till ManifestResources.resw
, skulle du i apppaketmanifestet ändra ms-resource:AppDisplayName
till ms-resource:/ManifestResources/AppDisplayName
.
Om ett resursfilnamn är segmenterat (det innehåller "." tecken) lämnar du punkterna i namnet när du refererar till det. Ersätt inte punkter med snedstreck ("/"), som man skulle göra för ett resursnamn.
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("Err.Msgs");
Om du är osäker kan du använda MakePri.exe för att dumpa appens PRI-fil. Varje resurss uri
visas i den dumpade filen.
<ResourceMapSubtree name="Err.Msgs"><NamedResource name="MismatchedPasswords" uri="ms-resource://<GUID>/Err.Msgs/MismatchedPasswords">...
Läs in en sträng för ett visst språk eller en annan kontext
Standardvärdet ResourceContext (hämtat från ResourceContext.GetForCurrentView) innehåller ett kvalificerarvärde för varje kvalificerarnamn som representerar standardkontexten för körning (med andra ord inställningarna för den aktuella användaren och datorn). Resursfiler (.resw) matchas – baserat på kvalificerarna i deras namn – mot kvalvärdena i den körmiljön.
Men det kan finnas tillfällen när du vill att din app ska åsidosätta systeminställningarna och vara tydlig med språk, skala eller annat kvalificerarvärde som ska användas när du letar efter en matchande resursfil som ska läsas in. Du kanske till exempel vill att användarna ska kunna välja ett alternativt språk för knappbeskrivningar eller felmeddelanden.
Du kan göra det genom att konstruera en ny ResourceContext (i stället för att använda standardvärdet), åsidosätta dess värden och sedan använda kontextobjektet i dina strängsökningar.
var resourceContext = new Windows.ApplicationModel.Resources.Core.ResourceContext(); // not using ResourceContext.GetForCurrentView
resourceContext.QualifierValues["Language"] = "de-DE";
var resourceMap = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap.GetSubtree("Resources");
this.myXAMLTextBlockElement.Text = resourceMap.GetValue("Farewell", resourceContext).ValueAsString;
Att använda Kvalifieringsvärden som i kodexemplet ovan fungerar för alla attribut. För det specifika fallet med "Language" kan du göra så här i stället.
resourceContext.Languages = new string[] { "de-DE" };
För samma effekt på global nivå kan du åsidosätta kvalificerarvärdena i standardvärdet ResourceContext. Men i stället rekommenderar vi att du anropar ResourceContext.SetGlobalQualifierValue. Du anger värden en gång med ett anrop till SetGlobalQualifierValue och sedan tillämpas dessa värden på standardvärdet ResourceContext varje gång du använder det för sökningar.
Windows.ApplicationModel.Resources.Core.ResourceContext.SetGlobalQualifierValue("Language", "de-DE");
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");
Vissa kvalificerare har en systemdataleverantör. I stället för att anropa SetGlobalQualifierValue kan du i stället justera providern via sitt eget API. Den här koden visar till exempel hur du anger PrimaryLanguageOverride.
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "de-DE";
Uppdatera strängar som svar på ändringshändelser för kvalificerande värde
Din körande app kan svara på ändringar i systeminställningarna som påverkar kvalificeringsvärdena i standard-ResourceContext. Någon av dessa systeminställningar anropar mapchanged-händelsen på ResourceContext.QualifierValues.
Som svar på den här händelsen kan du läsa in strängarna från standardinställningen ResourceContext.
public MainPage()
{
this.InitializeComponent();
...
// Subscribe to the event that's raised when a qualifier value changes.
var qualifierValues = Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().QualifierValues;
qualifierValues.MapChanged += new Windows.Foundation.Collections.MapChangedEventHandler<string, string>(QualifierValues_MapChanged);
}
private async void QualifierValues_MapChanged(IObservableMap<string, string> sender, IMapChangedEventArgs<string> @event)
{
var dispatcher = this.myXAMLTextBlockElement.Dispatcher;
if (dispatcher.HasThreadAccess)
{
this.RefreshUIText();
}
else
{
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => this.RefreshUIText());
}
}
private void RefreshUIText()
{
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");
}
Läsa in strängar från ett UWP-klassbibliotek eller en UWP Windows Runtime-komponent
Strängresurserna för ett refererat UWP-klassbibliotek (.NET Native) eller UWP Windows Runtime Component (.NET Native) läggs vanligtvis till i en undermapp av paketet där de ingår under byggprocessen. Resursidentifieraren för en sådan sträng har vanligtvis formatet LibraryName/ResourcesFileName/ResourceIdentifier.
Ett bibliotek kan hämta en ResourceLoader för sina egna resurser. Följande kod illustrerar till exempel hur antingen ett bibliotek eller en app som refererar till den kan hämta en ResourceLoader för bibliotekets strängresurser.
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("ContosoControl/Resources");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("exampleResourceName");
För en UWP Windows Runtime-komponent (.NET Native), om standardnamnområdet är segmenterat (det innehåller "." tecken), använder du punkter i resurskartans namn.
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("Contoso.Control/Resources");
Du behöver inte göra det för ett UWP-klassbibliotek (.NET Native). Om du är osäker kan du ange MakePri.exe kommandoradsalternativ för att dumpa komponenten eller bibliotekets PRI-fil. Varje resurss uri
visas i den dumpade filen.
<NamedResource name="exampleResourceName" uri="ms-resource://Contoso.Control/Contoso.Control/ReswFileName/exampleResourceName">...
Läsa in strängar från andra paket
Resurserna för ett apppaket hanteras och nås via paketets egna ResourceMap- som är tillgängliga från den aktuella ResourceManager-. I varje paket kan olika komponenter ha egna ResourceMap-underträd, som du kan komma åt via ResourceMap.GetSubtree.
Ett ramverkspaket kan komma åt sina egna resurser med en absolut resursidentifierares URI. Se även URI-scheman.
Ladda strängar i uppackade program
Från och med Windows version 1903 (uppdatering maj 2019) kan uppackade program också utnyttja resurshanteringssystemet.
Skapa bara UWP-användarkontroller/-bibliotek och lagra alla strängar i en resursfil. Du kan sedan referera till en strängresursidentifierare från XAML, referera till en strängresursidentifierare från kod eller läsa in strängar från ett UWP-klassbibliotek eller en UWP Windows Runtime-komponent.
Om du vill använda resurser i uppackade program bör du göra några saker:
Använd GetForViewIndependentAnvänd i stället för GetForCurrentView- när du löser resurser från kod eftersom det inte finns någon aktuell vy i uppackade scenarier. Följande undantag uppstår om du anropar GetForCurrentView i uppackade scenarier: Resurskontexter kan inte skapas på trådar som inte har en CoreWindow.
Använd MakePri.exe för att manuellt generera appens resources.pri-fil.
Kör
makepri new /pr <PROJECTROOT> /cf <PRICONFIG> /of resources.pri
<PRICONFIG> måste utelämna avsnittet "<paketering>" så att alla resurser paketeras i en enda resources.pri-fil. Om du använder standardkonfigurationsfilenMakePri.exe som skapats av createconfig måste du ta bort avsnittet "<paketering>" manuellt när den har skapats.
<PRICONFIG> måste innehålla alla relevanta indexerare som krävs för att sammanfoga alla resurser i projektet till en enda resources.pri-fil. StandardkonfigurationsfilenMakePri.exe som skapats av createconfig innehåller alla indexerare.
Om du inte använder standardkonfigurationen kontrollerar du att PRI-indexeraren är aktiverad (granska standardkonfigurationen för hur du gör detta) för att sammanfoga PRIs som finns från UWP-projektreferenser, NuGet-referenser och så vidare, som finns i projektroten.
Anmärkning
Genom att utelämna
/IndexName
och om projektet inte har ett appmanifest, ställs IndexName/root-namnområdet för PRI-filen automatiskt in på Application, vilket körtiden förstår för applikationer som inte är paketerade (detta tar bort det tidigare starka beroendet av paket-ID). När du anger resurs-URI:er refererar ms-resource:/// till att utelämna rotnamnområdet och antar då Program som rotnamnområde för icke-paketerade appar (eller så kan du uttryckligen ange Program som i ms-resource://Application/).
Kopiera PRI-filen till utdatakatalogen för .exe
Kör .exe
Anmärkning
Resource Management System använder systemets visningsspråk i stället för användarens föredragna språklista när du löser resurser baserat på språk i uppackade appar. Listan över användar föredragna språk används endast för UWP-appar.
Viktigt!
Du måste återskapa PRI-filer manuellt när resurser ändras. Vi rekommenderar att du använder ett skript efter bygget som hanterar kommandotMakePri.exe och kopierar utdata för resources.pri till katalogen .exe.
Viktiga API:er
- ApplicationModel.Resources.ResourceLoader
- ResourceContext.SetGlobalQualifierValue
- Kartan Har Ändrats