W przypadku wielokrotnego użytku etykiety macOS przyjmuj lokalizowalne komunikaty jako LocalizedStringResource, zachowaj osobną ścieżkę verbatim: dla tekstu dosłownego i pozostaw interpolację bez zmian aż do lokalizacji. W tym samouczku zbudujemy taki kontrakt dla licznika elementów na komputerze i osobno sprawdzimy ekstrakcję oraz wyświetlanie.

Jakie gwarancje powinien zapewniać wielokrotnego użytku interfejs tekstowy?

Załóżmy, że aplikacja na Maca potrzebuje zwięzłego podsumowania pokazującego liczbę elementów i syntetyczną etykietę kolekcji, taką jak Sample Set. Wielokrotnego użytku komponent musi rozróżniać trzy rodzaje danych wejściowych: komunikat utworzony przez aplikację, który wymaga tłumaczenia, istniejący klucz lokalizacyjny SwiftUI oraz tekst, który musi pojawić się dokładnie w przekazanej postaci.

Apple zaleca LocalizedStringResource do reprezentowania i przekazywania lokalizowalnych ciągów znaków przez niestandardowe widoki i inny kod Swift. W aktualnych wytycznych pokazano właściwości niestandardowych widoków tego typu wyświetlane za pomocą Text. Projektując nowy komponent, użyj tego typu jako głównego kontraktu dla komunikatów. Przygotowywanie tekstu aplikacji do tłumaczenia.

Poniższa tabela decyzyjna przedstawia projekt API wynikający z udokumentowanych zachowań. Jawne etykiety argumentów pozwalają ocenić intencje wywołującego bez polegania na dwóch konkurujących ze sobą, nieopisanych przeciążeniach przyjmujących ciągi znaków.

Intencja wywołującego Proponowany punkt wejścia Ścieżka renderowania
Przekazanie tłumaczalnego komunikatu z opcjonalnym kontekstem SummaryLabel(localized:) Text(resource)
Przekazanie klucza SwiftUI, także z interpolacją SwiftUI SummaryLabel(key:) Text(key, tableName:bundle:)
Wyświetlenie dokładnej etykiety SummaryLabel(verbatim:) Text(verbatim:)
Przekazanie tekstu złożonego już przez wywołującego SummaryLabel(text:) Zachowanie przekazanego Text

Zachowaj LocalizedStringKey do dyspozycji, gdy komponent konkretnie potrzebuje kluczowego mechanizmu SwiftUI. Apple dokumentuje, że literał ciągu znaków przekazany bezpośrednio do Text tworzy klucz lokalizacyjny, a zmienna typu String zwykle trafia ścieżką, która pomija lokalizację. Opakowanie przyjmujące wyłącznie String zmienia więc znaczenie wywołań, które na pierwszy rzut oka wyglądają podobnie. LocalizedStringKey.

Zbuduj kompletny komponent z jawnymi punktami wejścia

Użyj projektu aplikacji SwiftUI na macOS w Xcode 26 lub nowszym, ustawiając dla tego przykładu docelową wersję macOS 26. Zastąp wygenerowane deklaracje aplikacji i widoku zawartości kompletnym programem poniżej; w docelowym module pozostaw tylko jedną deklarację @main. Wszystkie etykiety i liczby są syntetyczne. Kod sprawdzono pod kątem zgodności z udokumentowanymi API, ale nie skompilowano go tutaj, ponieważ w tym środowisku nie ma kompilatora Swift.

import Foundation
import SwiftUI

struct SummaryLabel: View {
    private let text: Text

    init(localized resource: LocalizedStringResource) {
        text = Text(resource)
    }

    init(
        key: LocalizedStringKey,
        tableName: String? = nil,
        bundle: Bundle? = nil,
        comment: StaticString? = nil
    ) {
        text = Text(
            key,
            tableName: tableName,
            bundle: bundle,
            comment: comment
        )
    }

    init(verbatim value: String) {
        text = Text(verbatim: value)
    }

    init(text: Text) {
        self.text = text
    }

    var body: some View {
        text
            .font(.callout)
            .padding(8)
    }
}

struct ContentView: View {
    @State private var itemCount = 2
    private let collectionLabel = "Sample Set"

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Stepper(value: $itemCount, in: 0...12) {
                Text("Item count")
            }

            SummaryLabel(
                localized: LocalizedStringResource(
                    "summary.item-count",
                    defaultValue: "\(itemCount) items",
                    comment: "Summary below the item-count control. The integer is the number of items."
                )
            )

            SummaryLabel(
                key: "Collection: \(collectionLabel)"
            )

            SummaryLabel(verbatim: collectionLabel)

            SummaryLabel(
                text: Text(
                    "Preview",
                    comment: "Heading for a preview of the current item selection."
                ).bold()
            )
        }
        .padding(20)
        .frame(minWidth: 320)
    }
}

@main
struct TextContractDemoApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Inicjalizator zasobu celowo oddziela stabilny klucz summary.item-count od jego domyślnego komunikatu, \(itemCount) items. Apple dokumentuje dla tego inicjalizatora statyczny klucz, lokalizowalną wartość domyślną, tabelę, ustawienia regionalne, pakiet oraz komentarz dla tłumacza. Wartość domyślna jest używana, gdy klucza brakuje w określonej tabeli. Inicjalizator LocalizedStringResource.

Inicjalizator verbatim: zapewnia równie jasną gwarancję: wyświetla przekazany ciąg znaków bez lokalizacji. Działa zarówno z argumentem będącym literałem, jak i ze zmienną. Użyj tej ścieżki dla syntetycznej etykiety kolekcji, gdy wyświetlana treść ma zachować dokładną pisownię. Text.init(verbatim:).

Punkt wejścia text: pozwala wywołującemu utworzyć lokalizowany lub stylizowany tekst przed przekazaniem go do komponentu. Komponent dodaje wspólną typografię i odstępy, a wywołujący nadal wybiera semantykę komunikatu. Przekazanie Text jest wyjściem awaryjnym, więc komponent, który musi wymuszać węższy kontrakt, może pominąć ten inicjalizator.

Czym różnią się ekstrakcja i formatowanie w czasie działania?

Traktuj lokalizację jako dwa osobne sprawdzenia. Podczas kompilacji Xcode wykrywa w kodzie źródłowym wyrażenia lokalizowalne i aktualizuje katalog ciągów znaków. Podczas wykonywania aplikacja rozwiązuje komunikat i podstawia jego argumenty. Sesja Apple poświęcona katalogom ciągów znaków wyraźnie opisuje rozpoznawanie literałów używanych do tworzenia LocalizedStringResource w miejscu wywołania niestandardowego widoku. Wskazuje też ustawienie kompilacji Use Compiler to Extract Swift Strings. Wykrywanie katalogów ciągów znaków.

Interpolacja musi dotrzeć do typu uwzględniającego lokalizację, zanim stanie się zwykłym, gotowym ciągiem znaków. Apple wyjaśnia, że konstruktor interpolacji SwiftUI przechowuje oddzielnie klucz formatujący i wartości argumentów, dzięki czemu lokalizacja może nastąpić przed podstawieniem. Przekształcenie już interpolowanego String w klucz nie pozwala odtworzyć pierwotnych, typowanych argumentów. Co nowego w Swift.

Poniższy fragment diagnostyczny pokazuje tę różnicę; nie jest drugą aplikacją. Wszystkie użyte w nim wartości są zdefiniowane lokalnie.

import SwiftUI

let count = 2

// Ordinary String interpolation has already produced "2 items".
let completed: String = "\(count) items"
let exactDisplay = Text(completed)

// Looks up the completed value as a key.
// This does not restore a count placeholder.
let completedValueLookup = Text(LocalizedStringKey(completed))

// Preserves localization-aware interpolation from the beginning.
let messageKey: LocalizedStringKey = "\(count) items"
let interpolatedDisplay = Text(messageKey)

Utworzenie LocalizedStringKey ze zmiennej jest udokumentowanym sposobem zażądania wyszukiwania w czasie działania. Przydaje się, gdy zmienna celowo zawiera znany klucz. Nie gwarantuje jednak, że Xcode wyodrębni do katalogu każdą możliwą wartość tej zmiennej. Utrzymuj zamierzone klucze dynamiczne jawnie albo używaj deklaracji literałów zasobów dla skończonego zbioru komunikatów należących do aplikacji. Zachowanie wyszukiwania i wartości zapasowej opisano w Text.init(_:tableName:bundle:comment:).

Zachowaj cały komunikat, łącznie z interpunkcją i pozycjami symboli zastępczych, w jednym wyrażeniu lokalizowalnym. W tym przykładzie pozostaw Collection: \(collectionLabel) w całości. Złożenie gotowego komunikatu z osobno rozwiązanych fragmentów przerzuciłoby na wywołującego odpowiedzialność za ich kolejność i odstępy.

Dodaj katalog i skonfiguruj obsługę liczby mnogiej

Najpierw dodaj katalog ciągów znaków przez File > New > File from Template, wybierz String Catalog i nadaj mu nazwę Localizable. Następnie wybierz Product > Build. Apple dokumentuje, że kompilacja wypełnia katalog na podstawie lokalizowalnych interfejsów API i aktualizuje go, gdy zmieniają się komunikaty w kodzie źródłowym. Lokalizowanie i różnicowanie tekstu za pomocą katalogu ciągów znaków.

W przykładzie sprawdź wpis summary.item-count i jego interpolowaną liczbę całkowitą. Kliknij wpis z wciśniętym klawiszem Control i wybierz Vary by Plural. W angielskiej lokalizacji źródłowej ustaw formę One na %lld item, a Other na %lld items, zachowując symbol zastępczy liczby całkowitej dostarczony przez Xcode. Dodając inne lokalizacje, dodaj wymagane formy; kategorie liczby mnogiej zależą od języka. Lokalizowanie i różnicowanie tekstu za pomocą katalogu ciągów znaków.

Interpolacja przekazuje liczbę, ale sama nie tworzy formy pojedynczej. W samouczku Apple pokazano dodawanie wariantów liczby mnogiej do katalogu oraz wybieranie przez system pasującego wariantu w czasie działania. Dlatego pomyślna kompilacja i wyodrębniony komunikat to tylko część weryfikacji. Ćwiczenie z przewodnikiem: odkrywanie lokalizacji w Xcode.

Po skonfigurowaniu źródłowych form liczby mnogiej użyj tej krótkiej macierzy kryteriów akceptacji. Są to oczekiwane wyniki przykładowego programu, a nie rezultaty faktycznego uruchomienia.

Sprawdzenie Oczekiwany wynik
Skompiluj i sprawdź summary.item-count Jeden wpis komunikatu z podstawianą liczbą całkowitą
Ustaw liczbę na 0 0 items
Ustaw liczbę na 1 1 item
Ustaw liczbę na 2 2 items
Sprawdź wiersz z dokładną etykietą Sample Set pozostaje tekstem dosłownym
Sprawdź komunikat kolekcji Etykieta jest argumentem w ramach całego komunikatu

Diagnozuj osobno brakujące wpisy i nieprawidłowe wyświetlanie

Jeśli komunikatu brakuje w katalogu, najpierw sprawdź typ źródłowy. Parametr String mógł zatrzeć lokalizowalne wyrażenie, zanim dotarło do komponentu. Sprawdź, do którego celu przypisano katalog, skompiluj schemat zawierający miejsce wywołania i zweryfikuj ustawienie Use Compiler to Extract Swift Strings. Apple opisuje ekstrakcję jako proces dotyczący bieżącego schematu i platformy, sprawdź więc konfigurację, która faktycznie kompiluje komunikat. Wykrywanie katalogów ciągów znaków.

Jeśli wpis istnieje, ale aplikacja wyświetla klucz lub tekst zapasowy, sprawdź konfigurację wyszukiwania. Inicjalizator Text oparty na kluczu przeszukuje określoną tabelę i pakiet; pominięte wartości wskazują domyślną tabelę i główny pakiet. Brak klucza lub tabeli powoduje wyświetlenie tekstowej reprezentacji klucza. Czytelny tekst zapasowy może więc maskować niekompletne wyszukiwanie. Text.init(_:tableName:bundle:comment:).

Przenosząc komponent do frameworka lub pakietu, zdecyduj, gdzie będą znajdować się komunikaty. Komunikaty należące do komponentu wymagają pakietu jego zasobów; zasoby należące do wywołującego powinny zachować przekazane informacje o wyszukiwaniu. Aktualne wytyczne Apple pozwalają przekazać #bundle do interfejsów API lokalizacji, aby wskazać pakiet zawierający dany cel. Nazwane tabele również wymagają odpowiadających im katalogów. Przygotowywanie tekstu aplikacji do tłumaczenia.

Nie zakładaj też, że każda interpolacja akceptowana przez SwiftUI jest obsługiwana również przez zasób Foundation. LocalizedStringKey ma własne metody interpolacji, w tym warianty oparte na formacie i formaterze. Wybierz typ komunikatu przed złożeniem wyrażenia i sprawdź obsługiwane operacje interpolacji, gdy argument nie kompiluje się. LocalizedStringKey.StringInterpolation.

Wielokrotnego użytku komponent tekstowy jest gotowy, gdy wywołujący mogą jasno wyrazić swoje zamiary i zweryfikować oba etapy: kompilacja tworzy właściwy komunikat w katalogu, a uruchomiona aplikacja na Macu wyświetla poprawnie podstawioną wartość, formę liczby mnogiej lub dokładną etykietę. Przy każdej zmianie komponentu zachowaj te sprawdzenia jako część kontraktu API.

Źródła