W aplikacji na Maca z panelami należącymi do frameworków określ fallback na dwóch poziomach: jaki język wybiera każdy pakiet oraz jaki tekst zwraca każda wiadomość, gdy jej wyszukanie się nie powiedzie. Użyj angielskiej lokalizacji deweloperskiej i jawnych angielskich wartości domyślnych dla własnych wiadomości.
Ten przewodnik realizuje te założenia w prostym oknie pulpitu zawierającym etykietę należącą do aplikacji Workspace oraz etykietę należącą do frameworka Panel ready. Etykiety są przykładowe. Celem jest zapewnienie czytelności tych wiadomości w razie braku języka lub tłumaczenia, przy zachowaniu zwykłej lokalizacji, gdy tłumaczenia są dostępne.
Co powinny gwarantować zasady obsługi języka zapasowego?
Przyjmij następujące zasady dla wiadomości należących do aplikacji i frameworków: używaj dostępnej lokalizacji wybranej na podstawie dopasowania języków przez system; gdy żadna preferowana lokalizacja nie pasuje, używaj angielskiego jako języka deweloperskiego; a jeśli wyszukanie ciągu się nie powiedzie, zwracaj jego jawną angielską wartość domyślną. Każda wiadomość musi wskazywać pakiet i tabelę ciągów, do których należy.
Wybór języka uwzględnia preferowane języki użytkownika i dostępne lokalizacje. Brak języka pierwszego wyboru nie musi od razu oznaczać użycia angielskiego: najpierw może zostać dopasowany inny preferowany język. Zarchiwizowany przewodnik Apple dotyczący pakietów opisuje tę kolejność wyboru, a następnie wybór języka deweloperskiego, gdy nie pasuje żaden preferowany język. Bieżąca dokumentacja określa CFBundleDevelopmentRegion jako identyfikator języka zapasowego pakietu. Uzyskiwanie dostępu do zawartości pakietu, CFBundleDevelopmentRegion.
Korzystaj z poniższej tabeli decyzyjnej, określając oczekiwane wyniki. Rozdziela ona wybór zasobów od wyszukiwania wiadomości, zamiast traktować każdy brak tłumaczenia jako tę samą sytuację.
| Sytuacja | Zasady dla własnych wiadomości | Co sprawdzić |
|---|---|---|
| Dostępne jest tłumaczenie na preferowany język | Wyświetl to tłumaczenie | Pakiet, tabela i klucz |
| Pierwszy preferowany język jest niedostępny, ale pasuje inny preferowany język | Pozwól systemowi dopasować dostępny język lokalizacji | Kolejność preferencji i dostarczone zasoby |
| Nie pasuje żadna preferowana lokalizacja | Użyj angielskich zasobów deweloperskich pakietu | Język deweloperski i zasoby angielskie |
| Wybrane wyszukanie nie znajduje wiadomości | Zwróć jej jawną angielską wartość domyślną | defaultValue wiadomości |
| Wyszukanie w frameworku omyłkowo kieruje do pakietu aplikacji | Popraw argument pakietu | Własność zasobów |
| Istnieje tłumaczenie, ale zawiera nieodpowiedni tekst | Popraw tłumaczenie | Zawartość katalogu i weryfikacja |
Tabela łączy zasady wyboru zasobów Apple z udokumentowanym zachowaniem wartości domyślnej inicjalizatora Swift. Jest to zasada implementacyjna wyprowadzona z tych interfejsów API, a nie odrębna funkcja fallbacku w katalogach ciągów. Wyszukanie zakończone powodzeniem, które zwraca nieodpowiedni tekst, nie spełnia udokumentowanego warunku użycia wartości domyślnej inicjalizatora: niepowodzenia wyszukiwania. String.init(localized:defaultValue:table:bundle:locale:comment:).
Skonfiguruj angielskie zasoby źródłowe w każdym docelowym elemencie
W tym przykładzie użyj aktualnej wersji Xcode, aplikacji SwiftUI na macOS kierowanej na macOS 13 lub nowszy oraz docelowego elementu dynamicznego frameworka Swift o nazwie PanelKit, osadzonego w aplikacji. Połącz ten framework z aplikacją i osadź go w niej. Są to wymagania wstępne przykładowego projektu; nazwa frameworka nie wskazuje na istniejący produkt.
Ustaw angielski jako język deweloperski dla obu docelowych elementów i sprawdź, czy CFBundleDevelopmentRegion każdego zbudowanego pakietu ma wartość en. Dostarcz odpowiadające im angielskie zasoby źródłowe w obu docelowych elementach. Identyfikator języka deweloperskiego określa język zapasowy, ale nie dostarcza brakującej treści wiadomości. Apple dokumentuje en jako identyfikator języka angielskiego. CFBundleDevelopmentRegion.
Utwórz osobny katalog Localizable.xcstrings dla każdego docelowego elementu. W Xcode wybierz Plik > Nowy > Plik z szablonu, wybierz Katalog ciągów i nazwij go Localizable. Przypisz jeden katalog do aplikacji, a drugi do docelowego elementu frameworka. Rozdzielenie własności zasobów pozwala niezależnie zweryfikować każde wyszukanie. Apple opisuje proces tworzenia katalogu i obsługuje wiele katalogów. Lokalizowanie i dostosowywanie tekstu za pomocą katalogu ciągów.
Po dodaniu poniższego kodu wybierz Produkt > Buduj. Xcode wyodrębni z rozpoznanych wywołań lokalizowanych ciągów odpowiednie wpisy do katalogów. Potwierdź, że workspace.title pojawia się w katalogu aplikacji, a panel.ready w katalogu frameworka, z zamierzonymi angielskimi wartościami źródłowymi. Dodaj obsługiwane języki przyciskiem dodawania na pasku bocznym katalogu i wprowadź tłumaczenia odpowiednich wiadomości. Lokalizowanie i dostosowywanie tekstu za pomocą katalogu ciągów.
Kompletność katalogu i poprawność wyszukiwania w czasie działania wymagają osobnych kontroli. Przetłumaczony wpis w katalogu frameworka nie pomoże, jeśli wywołanie przeszukuje pakiet aplikacji. Apple wyraźnie zaleca, aby kod wczytujący ciągi spoza pakietu głównego przekazywał pakiet skojarzony z danym docelowym elementem. Przygotowywanie tekstu aplikacji do tłumaczenia.
Przypisz każdej wiadomości pakiet, klucz, tabelę i wartość domyślną
Użyj stabilnych przykładowych kluczy i czytelnych angielskich wartości domyślnych. Inicjalizator Swift przyjmujący defaultValue obsługuje klucz inny niż wyświetlany tekst źródłowy. Wartość domyślna jest zwracana, gdy wyszukanie zlokalizowanego ciągu w pakiecie się nie powiedzie. Parametr table wskazuje tabelę ciągów; pominięcie go wybiera Localizable. String.init(localized:defaultValue:table:bundle:locale:comment:).
Umieść wiadomości frameworka w frameworku
Dodaj ten kompletny plik źródłowy Swift do docelowego elementu dynamicznego frameworka PanelKit. Klasa znacznikowa jest zdefiniowana w tym docelowym elemencie, dzięki czemu Bundle(for:) wskazuje jego pakiet. Apple opisuje to podejście oparte na klasie jako alternatywę dla aktualnej makrofunkcji #bundle. Przygotowywanie tekstu aplikacji do tłumaczenia.
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."
)
}
}
Framework wyszukuje swoją wiadomość przed zwróceniem aplikacji wartości typu String. Wyznacza to wyraźną granicę własności: framework kontroluje klucz, tekst źródłowy, tabelę i pakiet zasobów. Aplikacja otrzymuje wynikowy tekst do wyświetlenia.
Wyświetl razem wiadomości aplikacji i frameworka
Zastąp wygenerowany plik punktu wejścia aplikacji tym kompletnym przykładem. Zakłada on, że połączony moduł frameworka nosi nazwę PanelKit i zawiera poprzedni plik. W docelowym elemencie aplikacji pozostaw tylko jeden punkt wejścia.
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)
}
}
}
Wyszukanie aplikacji jawnie używa .main, a wyszukanie frameworka korzysta z jego własnego pakietu zasobów. Oba podają angielskie wartości domyślne. Jest to zgodne z udokumentowanymi przez Apple parametrami wyboru pakietu i wartości domyślnej. Zbuduj i uruchom projekt w Xcode, aby zweryfikować pełną konfigurację docelowych elementów; przykłady nie zostały tutaj uruchomione. String.init(localized:defaultValue:table:bundle:locale:comment:).
W istniejącej implementacji korzystającej z Bundle.localizedString(forKey:value:table:) podaj niepusty, czytelny value, jeśli brakujący klucz ma zwracać czytelny tekst. Apple dokumentuje, że przy braku klucza zwracany jest sam klucz, gdy value jest pominięty lub pusty, a gdy jest niepusty, zwracane jest value. Klucz taki jak panel.ready wymaga więc jawnego tekstu zapasowego, jeśli ujawnienie tego identyfikatora naruszałoby zasady obsługi wiadomości. localizedString(forKey:value:table:).
Zdecyduj, czy frameworki mogą wybierać różne języki
Przekazanie prawidłowego pakietu określa, gdzie szukać. Konfiguracja mieszanych lokalizacji wpływa na to, jak wybór lokalizacji wiąże się z aplikacją zawierającą framework. Apple udostępnia wartość logiczną CFBundleAllowMixedLocalizations, wyświetlaną jako Zasoby z różnych lokalizacji mogą być łączone, do pobierania zlokalizowanych ciągów z frameworków. CFBundleAllowMixedLocalizations.
Wyjaśnienie tego zachowania na Swift Forums stwierdza, że włączenie tego klucza w pliku Info.plist aplikacji pozwala innym pakietom wybierać lokalizacje spoza zestawu obsługiwanego przez aplikację główną. Bez tego ustawienia pakiet główny ogranicza wybór pozostałych pakietów. To starsza dyskusja objaśniająca, która uzupełnia bieżącą dokumentację klucza Apple. Lokalizacja w Swift Package Manager.
W przypadku przykładowego okna zadbaj o zgodny zakres obsługiwanych języków w aplikacji i frameworku oraz o angielskie zasoby deweloperskie w obu. Na początku pozostaw niezależny wybór języka przez framework poza zakresem zasad. Jeśli zamiast tego zamierzasz pozwolić frameworkowi korzystać z dodatkowych tłumaczeń, ustaw wartość logiczną YES klucza CFBundleAllowMixedLocalizations w aplikacji i jawnie przetestuj tę konfigurację. Lokalizacja w Swift Package Manager.
Włączenie tego klucza nie dostarcza tłumaczenia ani wartości domyślnej dla brakującej wiadomości. Za te elementy nadal odpowiadają pliki zasobów i wywołania wyszukiwania. Podobnie wartość domyślna podana w Twoim wywołaniu określa wynik nieudanego wyszukania dla tego wywołania; nie ustanawia uniwersalnego angielskiego fallbacku dla każdego elementu sterującego systemu ani wiadomości frameworka.
Nie używaj argumentu locale tego inicjalizatora String do przełączania języka tłumaczenia. Apple wyraźnie dokumentuje, że steruje on lokalizacją interpolowanych wartości, takich jak liczby, i nie zmienia ustawień regionalnych używanych do wyszukiwania zlokalizowanego ciągu. W tym celu skorzystaj z obsługiwanej konfiguracji języka i mechanizmów testowych. String.init(localized:defaultValue:table:bundle:locale:comment:).
Testuj brakujące języki oddzielnie od brakujących wiadomości
Uruchamiaj kontrole lokalizacji przez Produkt > Schemat > Edytuj schemat. Wybierz Uruchom, otwórz Opcje, wybierz Język aplikacji, zamknij okno dialogowe i ponownie uruchom aplikację na Maca. Apple opisuje tę metodę testowania lokalizacji bez zmiany ustawień całego systemu. Podczas diagnozowania problemu dotyczącego wyłącznie języka nie zmieniaj ustawień regionu. Testowanie lokalizacji podczas uruchamiania aplikacji.
Użyj poniższej macierzy testów jako pomocy diagnostycznej dla projektu. Podczas kontroli routingu pakietów tymczasowo umieść różne angielskie znaczniki testowe, takie jak App translation sample i Framework translation sample, w obsługiwanej lokalizacji innej niż język źródłowy. To treści diagnostyczne, a nie tłumaczenia ani identyfikatory języków.
- Sprawdź działanie języka źródłowego. Uruchom aplikację z wybranym angielskim. Oczekuj
WorkspaceiPanel ready. - Sprawdź routing przetłumaczonych zasobów. Wybierz obsługiwaną lokalizację testową. Oczekuj różnych znaczników z obu katalogów, należących do odpowiednich docelowych elementów.
- Sprawdź wartość domyślną brakującej wiadomości. W tymczasowej edycji testowej zmień klucz wyszukiwania frameworka na
panel.ready.probe, pozostawdefaultValuebez zmian i nie umieszczaj wpisu testowego w katalogu. Jeśli wyszukanie się nie powiedzie, oczekujPanel ready. Następnie przywróć oryginalny klucz. - Sprawdź wybór nieobsługiwanego języka. Ustaw listę preferencji, na której nie ma żadnego obsługiwanego języka. Sprawdź, czy oba należące do aplikacji pakiety używają angielskich zasobów deweloperskich. Przetestuj także sytuację, w której po nieobsługiwanym języku pierwszego wyboru następuje język obsługiwany, ponieważ oczekiwany wynik jest wtedy inny.
- Sprawdź mieszaną lokalizację, jeśli jest włączona. Przetestuj język dostępny wyłącznie w frameworku. Zapisz zamierzone zachowanie i sprawdź, czy ustawienie mieszanych lokalizacji w aplikacji jest z nim zgodne.
Trzecia kontrola izoluje nieudane wyszukanie, a czwarta — dopasowanie języka. Samo testowanie nieprzetłumaczonego wiersza katalogu może zacierać te warunki, ponieważ wynikowa konfiguracja zasobów wpływa również na wyszukiwanie. Oczekiwany wynik dla brakującego klucza wynika z inicjalizatora Swift, a wybór preferowanego języka podlega zasadom dotyczącym pakietów. String.init(localized:defaultValue:table:bundle:locale:comment:), Uzyskiwanie dostępu do zawartości pakietu.
Gdy wyniki są inne, sprawdź faktyczny pakiet, do którego należy zasób. developmentLocalization zwraca wartość odpowiadającą CFBundleDevelopmentRegion; preferredLocalizations zwraca dostępne lokalizacje uporządkowane według preferencji językowych. Porównaj te właściwości dla Bundle.main i PanelText.resourceBundle. Pomagają one zdiagnozować konfigurację, ale ostatecznym sprawdzianem każdego wyszukania pozostają wyświetlane wiadomości. developmentLocalization, preferredLocalizations.
Dobrze zdefiniowane zasady obsługi języka zapasowego sprawiają, że każdy wynik da się wyjaśnić: wybrany język wynika z dopasowania w pakiecie, wiadomość pochodzi z należącej do niego tabeli, a nieudane wyszukanie zwraca jawny, czytelny tekst domyślny. Zastosuj te zasady do każdej własnej wiadomości aplikacji i frameworka, a następnie sprawdź je razem w oknie pulpitu, w którym zobaczą je użytkownicy.
Źródła
- Przygotowywanie tekstu aplikacji do tłumaczenia — Apple
- Lokalizowanie i dostosowywanie tekstu za pomocą katalogu ciągów — Apple
- CFBundleDevelopmentRegion — Apple
- String.init(localized:defaultValue:table:bundle:locale:comment:) — Apple
- localizedString(forKey:value:table:) — Apple
- CFBundleAllowMixedLocalizations — Apple
- Lokalizacja w Swift Package Manager — Swift Forums
- Testowanie lokalizacji podczas uruchamiania aplikacji — Apple
- developmentLocalization — Apple
- preferredLocalizations — Apple
- Uzyskiwanie dostępu do zawartości pakietu — Archiwum dokumentacji Apple