För en Mac-app med paneler som ägs av ramverk definierar du reservlösningar på två nivåer: vilket språk varje paket väljer och vad varje meddelande returnerar när dess sökning misslyckas. Använd engelska som utvecklingslokalisering och uttryckliga engelska standardvärden för de meddelanden du ansvarar för.
Den här guiden implementerar det kontraktet för ett enkelt skrivbordsfönster med den appägda etiketten Workspace och den ramverksägda etiketten Panel ready. Etiketterna är syntetiska. Målet är att hålla dessa meddelanden läsbara när ett språk eller en översättning saknas, samtidigt som normal lokalisering bevaras när översättningar finns.
Vad ska reservlösningskontraktet utlova?
Anta följande kontrakt för appägda och ramverksägda meddelanden: använd en tillgänglig lokalisering som väljs genom systemets språkmatchning; använd engelska som utvecklingslokalisering när inget föredraget språk matchar; och returnera ett meddelandes uttryckliga engelska standardvärde om strängsökningen misslyckas. Varje meddelande måste ange vilket paket och vilken strängtabell det tillhör.
Språkvalet tar hänsyn till användarens föredragna språk och tillgängliga lokaliseringar. Om förstahandsvalet saknas betyder det inte nödvändigtvis att engelska visas direkt: ett annat föredraget språk kan matcha först. Apples arkiverade paketguide beskriver den urvalsordningen, följd av utvecklingslokaliseringen när inget föredraget språk matchar. Den aktuella dokumentationen definierar CFBundleDevelopmentRegion som paketets språkaidentifierare för reservlösning. Åtkomst till ett pakets innehåll, CFBundleDevelopmentRegion.
Använd följande beslutstabell när du definierar förväntade resultat. Den skiljer resursval från meddelandesökning i stället för att behandla alla saknade översättningar som samma villkor.
| Villkor | Kontrakt för meddelanden du ansvarar för | Vad du ska kontrollera |
|---|---|---|
| Ett föredraget språk har en tillgänglig översättning | Visa den översättningen | Paket, tabell och nyckel |
| Det första föredragna språket saknas, men ett annat föredraget språk matchar | Låt systemets språkmatchning välja den tillgängliga lokaliseringen | Preferensordning och medföljande resurser |
| Ingen föredragen lokalisering matchar | Använd paketets engelska utvecklingsresurser | Utvecklingsspråk och engelska resurser |
| Den valda sökningen inte hittar meddelandet | Returnera dess uttryckliga engelska standardvärde | Meddelandets defaultValue |
| En ramverkssökning riktas av misstag mot appaketet | Korrigera paketargumentet | Resursägarskap |
| En översättning finns men innehåller olämplig text | Korrigera översättningen | Kataloginnehåll och granskning |
Tabellen kombinerar Apples regler för resursval med det dokumenterade beteendet för standardvärden i Swift-initialiseraren. Det är en implementeringspolicy som härleds från dessa API:er, inte en separat reservlösningsfunktion i String Catalogs. En lyckad sökning med olämplig text uppfyller inte initialiserarens dokumenterade villkor för att använda standardvärdet: en misslyckad sökning. String.init(localized:defaultValue:table:bundle:locale:comment:).
Konfigurera engelska källresurser i varje ägande mål
I det här exemplet används en aktuell Xcode-installation, en macOS SwiftUI-app med målversion macOS 13 eller senare och ett inbäddat dynamiskt Swift-ramverksmål med namnet PanelKit. Länka och bädda in ramverket i appen. Detta är förutsättningar för exempelprojektet; ramverksnamnet identifierar inte en befintlig produkt.
Ange engelska som utvecklingsspråk för båda målen och kontrollera att varje byggt pakets CFBundleDevelopmentRegion motsvarar en. Tillhandahåll motsvarande engelska källresurser i båda målen. En utvecklingsspråkidentifierare beskriver reservspråket; den tillhandahåller inte saknat meddelandeinnehåll. Apple dokumenterar en som språkidentifieraren för engelska. CFBundleDevelopmentRegion.
Skapa en separat Localizable.xcstrings-katalog för varje mål. I Xcode väljer du File > New > File from Template, väljer String Catalog och namnger den Localizable. Tilldela en katalog till appmålet och den andra till ramverksmålet. Separat resursägarskap gör det möjligt att verifiera varje sökning oberoende. Apple dokumenterar arbetsflödet för att skapa kataloger och stöder flera kataloger. Lokalisera och variera text med en strängkatalog.
När du har lagt till koden nedan väljer du Product > Build. Xcode extraherar igenkända lokaliserbara anrop till katalogerna. Kontrollera att workspace.title finns i appkatalogen och panel.ready i ramverkskatalogen, med avsedda engelska källvärden. Lägg till språk som stöds med knappen för att lägga till i katalogens sidofält och ange översättningar för relevanta meddelanden. Lokalisera och variera text med en strängkatalog.
Katalogens fullständighet och korrektheten hos körningstidens sökningar kräver separata kontroller. En översatt post i ramverkskatalogen hjälper inte om ett anrop söker i appaketet. Apple instruerar uttryckligen kod som läser in strängar utanför huvudpaketet att skicka med paketet som hör till målet. Förbereda appens text för översättning.
Ge varje meddelande ett paket, en nyckel, en tabell och ett standardvärde
Använd stabila syntetiska nycklar och lättlästa engelska standardvärden. Swift-initialiseraren som accepterar defaultValue stöder en nyckel som skiljer sig från den visade källtexten. Standardvärdet returneras när sökningen efter den lokaliserade strängen i paketet misslyckas. Parametern table väljer strängtabellen; om den utelämnas används Localizable. String.init(localized:defaultValue:table:bundle:locale:comment:).
Lägg ramverksmeddelanden i ramverket
Lägg till den här kompletta Swift-källfilen i det dynamiska ramverksmålet PanelKit. Markörklassen definieras i det målet så att Bundle(for:) identifierar dess paket. Apple dokumenterar den här klassbaserade metoden som ett alternativ till det aktuella #bundle-makrot. Förbereda appens text för översättning.
import Foundation
private final class PanelBundleAnchor: NSObject {}
public enum PanelText {
public static var resourceBundle: Bundle {
Bundle(for: PanelBundleAnchor.self)
}
public static var ready: String {
String(
localized: "panel.ready",
defaultValue: "Panel ready",
table: "Localizable",
bundle: resourceBundle,
comment: "Status label above the framework panel."
)
}
}
Ramverket löser sitt meddelande innan det returnerar en String till appen. Det skapar en tydlig ägandegräns: ramverket styr nyckeln, källtexten, tabellen och resurspaketet. Appen får den färdiga visningstexten.
Visa appens och ramverkets meddelanden tillsammans
Ersätt appens genererade startpunktsfil med det här fullständiga exemplet. Det förutsätter att den länkade ramverksmodulen heter PanelKit och innehåller föregående fil. Behåll bara en startpunkt för appen i appmålet.
import Foundation
import SwiftUI
import PanelKit
@main
struct FallbackDemoApp: App {
var body: some Scene {
WindowGroup {
VStack(alignment: .leading, spacing: 12) {
Text(verbatim: String(
localized: "workspace.title",
defaultValue: "Workspace",
table: "Localizable",
bundle: .main,
comment: "Heading for the main workspace."
))
Text(verbatim: PanelText.ready)
}
.padding(24)
}
}
}
Appens sökning använder uttryckligen .main; ramverkssökningen använder sitt eget resurspaket. Båda anger engelska standardvärden. Detta följer Apples dokumenterade parametrar för paketval och standardvärde. Bygg och kör projektet i Xcode för att validera hela målets konfiguration; exemplen har inte körts här. String.init(localized:defaultValue:table:bundle:locale:comment:).
För en befintlig implementation som använder Bundle.localizedString(forKey:value:table:) anger du ett icke-tomt och läsbart value när du behöver ett läsbart resultat för en saknad nyckel. Apple dokumenterar att en saknad nyckel returnerar själva nyckeln när value saknas eller är tomt och returnerar value när det inte är tomt. En nyckel som panel.ready behöver därför en uttrycklig reservlösning om det skulle bryta mot meddelandekontraktet att visa den identifieraren. localizedString(forKey:value:table:).
Avgör om ramverk får välja olika språk
Att skicka rätt paket anger var sökningen ska göras. Konfigurationen för blandad lokalisering påverkar hur valet av lokalisering förhåller sig till den app som innehåller ramverket. Apple tillhandahåller den booleska inställningen CFBundleAllowMixedLocalizations, som visas som Localized resources can be mixed, för att hämta lokaliserade strängar från ramverk. CFBundleAllowMixedLocalizations.
Förklaringen av det här beteendet på Swift Forums säger att om nyckeln aktiveras i appens Info.plist kan andra paket välja lokaliseringar utöver dem som huvudappen stöder. Utan detta val begränsar huvudpaketet deras urval. Det här är en äldre förklarande diskussion som kompletterar Apples aktuella referens för nyckeln. Lokalisering i Swift Package Manager.
För exempelfönstret bör appen och ramverket helst ha stöd för samma språk, med engelska utvecklingsresurser i båda. Låt inte oberoende språkval för ramverket ingå i det första kontraktet. Om du i stället vill att ett ramverk ska kunna använda ytterligare översättningar anger du YES som booleskt värde för CFBundleAllowMixedLocalizations i appen och testar den konfigurationen uttryckligen. Lokalisering i Swift Package Manager.
Om du aktiverar den här nyckeln får du ingen översättning eller något standardvärde för saknade meddelanden. Det ansvaret ligger fortfarande hos resursfilerna och sökanropen. På samma sätt anger ett standardvärde i ditt eget anrop resultatet när just den sökningen misslyckas; det skapar inte en universell engelsk reservlösning för varje systemkontroll eller ramverksmeddelande.
Undvik att använda argumentet locale i den här String-initialiseraren som en växel för översättningsspråk. Apple dokumenterar uttryckligen att det styr lokaliseringen av interpolerade värden, exempelvis tal, och inte ändrar den region som används för att söka efter den lokaliserade strängen. Använd språkfigurationen och testkontrollerna som stöds för den här uppgiften. String.init(localized:defaultValue:table:bundle:locale:comment:).
Testa saknade språk separat från saknade meddelanden
Kör lokaliseringskontrollerna via Product > Scheme > Edit Scheme. Välj Run, öppna Options, välj ett App Language, stäng dialogrutan och kör Mac-appen igen. Apple dokumenterar det här arbetsflödet för att prova lokaliseringar utan att ändra inställningarna för hela systemet. Låt regionvalet vara oförändrat när du undersöker ett problem som bara gäller språket. Testa lokaliseringar när du kör appen.
Använd följande testmatris som ett projektspecifikt diagnostiskt hjälpmedel. För kontroller av paketstyrning använder du tillfälligt olika engelska testmarkörer, exempelvis App translation sample och Framework translation sample, i en lokaliseringsversion som stöds och inte är källversionen. Det här är diagnostisk text, inte översättningar eller språkidentifierare.
- Verifiera källbeteendet. Kör med engelska valt. Förvänta dig
WorkspaceochPanel ready. - Verifiera dirigering till översatta resurser. Välj testlokaliseringen som stöds. Förvänta dig de olika markörerna från de två ägande katalogerna.
- Verifiera standardvärdet för ett saknat meddelande. Ändra i en tillfällig teständring ramverkssökningens nyckel till
panel.ready.probe, låtdefaultValuevara oförändrad och se till att testposten inte tas med i testkatalogen. Förvänta digPanel readynär sökningen misslyckas. Återställ den ursprungliga nyckeln efteråt. - Verifiera val vid språk som inte stöds. Prova en preferenslista där inget språk som stöds matchar. Kontrollera att båda ägande paketen använder sina engelska utvecklingsresurser. Testa också ett språk som inte stöds som förstahandsval följt av ett språk som stöds, eftersom det fallet ger ett annat förväntat resultat.
- Verifiera blandad lokalisering om den är aktiverad. Prova ett språk som bara finns i ramverket. Anteckna det avsedda beteendet och testa appens inställning för blandad lokalisering mot detta.
Den tredje kontrollen isolerar en misslyckad sökning; den fjärde isolerar språkmatchningen. Om du bara testar en oöversatt katalograd kan dessa villkor blandas ihop, eftersom den resulterande resurskonfigurationen också påverkar sökningen. Det förväntade resultatet för en saknad nyckel kommer från Swift-initialiseraren, medan valet av föredraget språk följer paketreglerna. String.init(localized:defaultValue:table:bundle:locale:comment:), Åtkomst till ett pakets innehåll.
Om resultaten skiljer sig åt granskar du det faktiska ägande paketet. developmentLocalization rapporterar värdet som motsvarar CFBundleDevelopmentRegion; preferredLocalizations rapporterar tillgängliga lokaliseringar sorterade enligt språkinställningarna. Jämför dessa egenskaper för Bundle.main och PanelText.resourceBundle. De hjälper till att diagnostisera konfigurationen, men de visade meddelandena är den slutliga kontrollen av varje sökning. developmentLocalization, preferredLocalizations.
Med ett användbart reservlösningskontrakt går varje resultat att förklara: det valda språket kommer från paketmatchningen, meddelandet kommer från dess ägande tabell och en misslyckad sökning returnerar ett uttryckligt, läsbart standardvärde. Tillämpa reglerna på varje app- och ramverksmeddelande du ansvarar för och verifiera dem sedan tillsammans i skrivbordsfönstret där användarna ser dem.
Källor
- Förbereda appens text för översättning — Apple
- Lokalisera och variera text med en strängkatalog — Apple
- CFBundleDevelopmentRegion — Apple
- String.init(localized:defaultValue:table:bundle:locale:comment:) — Apple
- localizedString(forKey:value:table:) — Apple
- CFBundleAllowMixedLocalizations — Apple
- Lokalisering i Swift Package Manager — Swift Forums
- Testa lokaliseringar när du kör appen — Apple
- developmentLocalization — Apple
- preferredLocalizations — Apple
- Åtkomst till ett pakets innehåll — Apple Documentation Archive