Mac ऐप में दोहराए गए संदेशों को समेकित करने के लिए, प्रत्येक साझा अर्थ को एक स्थानीयकरण कुंजी और एक Swift परिभाषा दें, फिर उस संदेश के हर स्थान पर उसी का उपयोग करें। इसके तर्क, बहुवचन नियम और अनुवादक के लिए संदर्भ साथ रखें; केवल अंग्रेज़ी पाठ का मेल पर्याप्त नहीं है।

यह मार्गदर्शिका उस Mac डेवलपर के लिए है जो SwiftUI और Interface Builder विंडो, दोनों में चयन सारांश का रखरखाव करता है। इसका ठोस उद्देश्य 2 items selected in Batch A. जैसे संदेशों को एकसमान रूप से दिखाना है, बिना XIB और Swift कोड में वाक्य के अलग-अलग टेम्पलेट बनाए रखे। नीचे दी गई सभी संख्याएँ और लेबल काल्पनिक हैं।

तय करें कि दोहराए गए कौन-से संदेश एक साथ रखे जाने चाहिए

कैटलॉग संपादित करने से पहले, संदेश का अनुबंध तय करें: वाक्य का अर्थ क्या है, वह कौन-से मान स्वीकार करता है और कहाँ दिखाई देता है। इस उदाहरण का अनुबंध है:

अनुबंध का तत्व परिभाषा
अर्थ नामित संग्रह में वर्तमान में चुनी गई वस्तुओं की संख्या
कुंजी selection.summary
तालिका Localizable
बंडल मुख्य ऐप बंडल
तर्क 1 चयन की संख्या बताने वाला Int64
तर्क 2 संग्रह का शाब्दिक लेबल, जैसे Batch A
रूपांतर चयन की संख्या से निर्धारित बहुवचन रूप
संदर्भ SwiftUI और AppKit लेबल में दिखने वाला पूरा स्थिति-वाक्य

समेकन की जाँच के लिए इस अनुबंध का उपयोग करें। दो स्थानों पर संदेश साझा किया जा सकता है, यदि उनका अर्थ, तर्क और व्याकरणिक भूमिका समान हों। चुनी गई वस्तुओं की संख्या और कुल वस्तुओं की संख्या अलग ही रहने चाहिए, भले ही दोनों अभी 2 items दिखाएँ। Select नाम के बटन के लिए भी अलग संदेश चाहिए, क्योंकि वह एक क्रिया व्यक्त करता है।

Apple, पाठ में अस्पष्टता दूर करने के लिए अलग-अलग डिफ़ॉल्ट मानों के साथ स्पष्ट कुंजियों का समर्थन करता है। इससे आप पठनीय स्रोत शब्दावली बनाए रखते हुए संदेश को उसके उद्देश्य के आधार पर नाम दे सकते हैं। टिप्पणी संदर्भ देती है; कुंजी प्रविष्टि की पहचान करती है। String का स्पष्ट-कुंजी वाला initializer।

तालिका और बंडल को भी लुकअप अनुबंध का हिस्सा मानें। किसी दूसरी तालिका में मौजूद कुंजी अलग लुकअप लक्ष्य होती है। Apple, table या tableName पैरामीटर के ज़रिए तालिका चुनने का दस्तावेज़ देता है और स्थानीयकरण योग्य पाठ को LocalizedStringResource के माध्यम से देने की सलाह देता है। इस उदाहरण में, हेल्पर और कैटलॉग को ऐप टारगेट में रखें और मुख्य बंडल का उपयोग करें। अपने ऐप के पाठ को अनुवाद के लिए तैयार करना।

एक्सट्रैक्शन और रनटाइम फ़ॉर्मैटिंग के बीच का अंतर समझें

एक्सट्रैक्शन Xcode बिल्ड के दौरान होता है: यह समर्थित स्थानीयकरण योग्य एक्सप्रेशन खोजता है और उनके स्रोत पाठ को कैटलॉग के साथ सिंक्रनाइज़ करता है। रनटाइम स्थानीयकरण तब होता है जब ऐप किसी संदेश को हल करता है और वास्तविक मान उसमें रखता है। कैटलॉग में प्रविष्टि मिलना यह साबित करता है कि एक्सट्रैक्शन ने उसे ढूँढ़ लिया; इससे यह साबित नहीं होता कि हर कंट्रोल उसे सही ढंग से दिखाता है।

Interface Builder का अपना संसाधन वर्कफ़्लो है। Apple, स्टोरीबोर्ड या XIB के साथ जोड़े गए कैटलॉग का दस्तावेज़ देता है, जबकि Swift स्रोत सामान्यतः Localizable तालिका में योगदान देता है। दस्तावेज़ित वर्कफ़्लो ऐसे क्रॉस-रिसोर्स उपनाम का वर्णन नहीं करता जो केवल दृश्य शब्दावली के मेल के कारण संदेशों को मिला दे। एक व्यावहारिक और समर्थित तरीका है कि इंटरफ़ेस लोड होने के बाद Swift से साझा स्थानीयकृत संदेश असाइन किया जाए। यह कार्यान्वयन Apple के दस्तावेज़ित API से निकला है। String Catalogs को जानें।

SwiftUI में भी स्थानीयकरण कुंजी के शाब्दिक मान और सामान्य स्ट्रिंग मान के बीच अंतर होता है। उदाहरण के लिए, Text("Summary") स्थानीयकरण का अनुरोध करता है, जबकि String वेरिएबल देने पर उसका मान बिना उस लुकअप के दिखता है। रनटाइम स्ट्रिंग को LocalizedStringKey में लपेटने से लुकअप का अनुरोध होता है, लेकिन इसे इस बात का प्रमाण नहीं समझना चाहिए कि एक्सट्रैक्शन ने उसके संभावित मान खोज लिए हैं। LocalizedStringKey।

इसलिए नीचे दिया गया डिज़ाइन, एक्सट्रैक्ट किया जा सकने वाला शाब्दिक पाठ एक ही हेल्पर में रखता है। यह संख्या और लेबल को LocalizedStringResource में साथ रखता है, फिर जहाँ पूरी स्ट्रिंग चाहिए वहाँ उस संसाधन को हल करता है। Apple इस संसाधन प्रकार को स्थानीयकरण लुकअप टालने का एक तरीका बताता है। यह macOS 13 और उसके बाद के संस्करणों में उपलब्ध है, जो इस उदाहरण का न्यूनतम टारगेट है। LocalizedStringResource।

Swift में साझा संदेश एक बार परिभाषित करें

SwiftUI का उपयोग करके macOS ऐप प्रोजेक्ट बनाएँ, उसका डिप्लॉयमेंट टारगेट macOS 13 या उसके बाद के संस्करण पर सेट करें और ऐप टारगेट में Localizable.xcstrings जोड़ें। मौजूदा Xcode दस्तावेज़ के अनुसार, इसे बनाने का तरीका है File > New > File from Template; string खोजें और String Catalog चुनें। स्ट्रिंग कैटलॉग से पाठ का स्थानीयकरण और रूपांतर।

जनरेट किए गए ऐप एंट्री पॉइंट को नीचे दिए गए पूरे प्रोग्राम से बदलें। मूल ऐप एंट्री पॉइंट हटाएँ, ताकि टारगेट में केवल एक @main घोषणा रहे। SwiftUI विंडो XIB से स्वतंत्र रूप से चलती है; अगले अनुभाग में मौजूदा Interface Builder लेबल को अनुकूलित करते समय शामिल AppKit सबक्लास का उपयोग किया जाएगा।

import AppKit
import Foundation
import SwiftUI

enum SelectionMessages {
    static func summary(
        count: Int64,
        collectionLabel: String
    ) -> LocalizedStringResource {
        LocalizedStringResource(
            "selection.summary",
            defaultValue: "\(count) items selected in \(collectionLabel).",
            table: "Localizable",
            comment: "Complete selection-status sentence used in SwiftUI and an AppKit label. Argument 1 is the selected-item count; argument 2 is a literal collection label. Pluralize by argument 1."
        )
    }
}

struct SelectionDemoView: View {
    private let counts: [Int64] = [0, 1, 2]
    private let collectionLabel = "Batch A"

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            ForEach(counts, id: \.self) { count in
                Text(String(localized: SelectionMessages.summary(
                    count: count,
                    collectionLabel: collectionLabel
                )))
            }
        }
        .padding(24)
        .frame(minWidth: 360, minHeight: 160)
    }
}

final class SelectionSummaryField: NSTextField {
    override func awakeFromNib() {
        super.awakeFromNib()
        // Synthetic initial state for the Interface Builder example.
        updateSelection(count: 2, collectionLabel: "Batch A")
    }

    func updateSelection(count: Int64, collectionLabel: String) {
        stringValue = String(localized: SelectionMessages.summary(
            count: count,
            collectionLabel: collectionLabel
        ))
    }
}

@main
struct SelectionDemoApp: App {
    var body: some Scene {
        WindowGroup {
            SelectionDemoView()
        }
    }
}

स्टैटिक कुंजी संदेश की पहचान करती है; इंटरपोलेट किया गया डिफ़ॉल्ट मान स्रोत वाक्य और रनटाइम तर्क देता है। initializer तालिका, बंडल और अनुवादक की टिप्पणी भी स्वीकार करता है। इसका डिफ़ॉल्ट बंडल मुख्य बंडल है। LocalizedStringResource का स्पष्ट-कुंजी वाला initializer।

Batch A लेबल, वाक्य में डाला गया नमूना पाठ है। यह दूसरी संदेश-कुंजी नहीं है। इस अंतर से संग्रह के लेबल, इंटरफ़ेस की बाकी शब्दावली से अलग रहते हैं। यदि आपका वास्तविक ऐप पहले से तय और अनुवादित संग्रह नामों का उपयोग करता है, तो यहाँ देने से पहले उन नामों को उनकी अपनी परिभाषाओं के ज़रिए स्थानीयकृत करें।

इस वाक्य को अलग-अलग स्थानीयकृत हिस्सों से न जोड़ें, जैसे संख्या, items selected in और लेबल। पूरा वाक्य अनुबंध में रखने से स्थानीयकरणकर्ताओं को एक ऐसी इकाई मिलती है जिसकी शब्दावली और तर्कों का क्रम साथ में बदला जा सकता है।

Interface Builder लेबल को उसी परिभाषा से जोड़ें

मौजूदा XIB या स्टोरीबोर्ड के लिए, सारांश के रूप में स्टैटिक NSTextField लेबल का उपयोग करें। इसकी कस्टम क्लास SelectionSummaryField और मॉड्यूल ऐप टारगेट पर सेट करें। डिज़ाइन-टाइम स्ट्रिंग मान से पुराना वाक्य हटाएँ, क्योंकि इस विशेष लेबल को अब साझा Swift परिभाषा से पाठ मिलता है।

इंटरफ़ेस लोड होने पर, सबक्लास super.awakeFromNib() को कॉल करता है और काल्पनिक शुरुआती सारांश असाइन करता है। Apple, awakeFromNib() को लोडिंग के बाद चलने वाले हुक के रूप में दस्तावेज़ित करता है, जहाँ आउटलेट और एक्शन कनेक्शन स्थापित हो चुके होते हैं; साथ ही, सुपरक्लास कार्यान्वयन को कॉल करना भी आवश्यक है। awakeFromNib()।

वास्तविक विंडो में, जब भी चयन बदले, कनेक्ट किए गए लेबल पर updateSelection(count:collectionLabel:) कॉल करें और वही मॉडल मान दें जो SwiftUI को दिए जाते हैं। काल्पनिक शुरुआती असाइनमेंट को विंडो के वास्तविक इनिशियलाइज़ेशन पथ से बदलें। लोडिंग के दौरान एक बार असाइन करने से बाद के चयन परिवर्तनों का पता नहीं चल सकता।

AppKit अडैप्टर stringValue सेट करता है, जो NSTextField का पाठ असाइन करने का दस्तावेज़ित तरीका है। इससे लेआउट Interface Builder में रहता है, जबकि संदेश का स्वामित्व Swift को मिलता है। पूरे वाक्य के लिए पर्याप्त चौड़ाई या रैपिंग की सुविधा रखें। NSTextField।

असंबंधित स्टैटिक इंटरफ़ेस पाठ को उसके मौजूदा संसाधन वर्कफ़्लो में रहने दें। यह बदलाव एक साझा संदेश से जुड़ा है; हर लेबल को Swift में ले जाना आवश्यक नहीं है। यह भी जाँचें कि कोई बाइंडिंग या कंट्रोलर का दूसरा असाइनमेंट बाद में सारांश को पुराने पाठ से बदल तो नहीं देता।

तर्क बदले बिना बहुवचन रूप कॉन्फ़िगर करें

Product > Build चुनें, Localizable.xcstrings खोलें और selection.summary खोजें। प्रविष्टि पर Control-क्लिक करें, Vary by Plural चुनें और यदि Xcode पूछे कि किस तर्क के आधार पर रूप बदलना है, तो संख्या वाला तर्क चुनें। Apple इंटरपोलेट किए गए संदेशों के लिए इस वर्कफ़्लो का दस्तावेज़ देता है। स्ट्रिंग कैटलॉग से पाठ का स्थानीयकरण और रूपांतर।

अंग्रेज़ी स्रोत स्थानीयकरण के लिए, एकवचन रूप में 1 item selected in Batch A. और दूसरे रूप में 2 items selected in Batch A. जैसे वाक्य दिखाएँ। Xcode द्वारा दिए गए दोनों तर्क प्लेसहोल्डर सुरक्षित रखें। किसी प्लेसहोल्डर को नमूना संख्या या लेबल से बदलने के बजाय उसके आसपास की शब्दावली संपादित करें।

काल्पनिक इनपुट बहुवचन कॉन्फ़िगरेशन के बाद अपेक्षित अंग्रेज़ी परिणाम
संख्या 0, लेबल Batch A 0 items selected in Batch A.
संख्या 1, लेबल Batch A 1 item selected in Batch A.
संख्या 2, लेबल Batch A 2 items selected in Batch A.
संख्या 2, लेबल Batch B 2 items selected in Batch B.

ये उदाहरणात्मक स्वीकृति-मामले हैं, मापे गए परिणाम नहीं। बहुवचन कॉन्फ़िगरेशन से पहले, हर संख्या के लिए डिफ़ॉल्ट स्रोत वाक्य में items ही रहता है। एक्सट्रैक्शन इंटरपोलेट किए गए संदेश को सुरक्षित रखता है; वह अपने आप व्याकरण ठीक नहीं करता।

आखिरी पंक्ति में बदलता हुआ लेबल समस्या का पता लगाने में उपयोगी है: यदि डिस्प्ले Batch A ही दिखाता रहे, तो हो सकता है किसी रूपांतर में नमूना मान हार्डकोड किया गया हो या कॉलर पुरानी स्थिति दे रहा हो। यदि लेबल गायब हो जाए, तो हेल्पर के सिग्नेचर बदलने से पहले रूपांतर के प्लेसहोल्डर जाँचें।

पुराने प्रविष्टियाँ हटाने से पहले हर डिस्प्ले पथ की जाँच करें

SwiftUI विंडो और वास्तविक Interface Builder विंडो की अलग-अलग जाँच करें। दोनों में समान संख्याएँ और लेबल इस्तेमाल करें। शुरुआती लोडिंग, चयन में बाद के बदलाव और Batch A Extended जैसे लंबे काल्पनिक लेबल की जाँच करें। पुष्टि करें कि शब्दावली दोनों में मेल खाती है और वाक्य पढ़ने योग्य बना रहता है।

हर समर्थित स्थानीयकरण के लिए, Product > Scheme > Edit Scheme चुनें, Run चुनें, Options खोलें और App Language सेट करें। ऐप फिर चलाएँ और दोनों डिस्प्ले पथ देखें। Apple, पूरे सिस्टम की भाषा बदले बिना स्थानीयकरणों की जाँच के लिए इन स्कीम सेटिंग्स का दस्तावेज़ देता है। ऐप चलाते समय स्थानीयकरणों की जाँच।

परिणाम गलत होने पर यह क्रम अपनाएँ:

  1. प्रविष्टि गायब है: पुष्टि करें कि कैटलॉग ऐप टारगेट का हिस्सा है और संबंधित स्कीम बिल्ड करें। जाँचें कि Use Compiler to Extract Swift Strings सक्षम है।
  2. स्रोत शब्दावली अनपेक्षित रूप से दिखती है: पठनीय फ़ॉलबैक पाठ को सफलता मानने से पहले कुंजी, तालिका, बंडल और अनुवाद जाँचें।
  3. केवल Interface Builder लेबल अलग है: उसकी कस्टम क्लास, मॉड्यूल, लोडिंग पथ और बाद के असाइनमेंट जाँचें।
  4. केवल बाद के मान अलग हैं: जाँचें कि दोनों इंटरफ़ेस को अपडेट किए गए मॉडल मान मिल रहे हैं।
  5. बहुवचन की शब्दावली गलत है: रूपांतर के लिए चुना गया संख्यात्मक तर्क और हर लागू रूप जाँचें।

Apple, कंपाइलर एक्सट्रैक्शन सेटिंग का दस्तावेज़ देता है और बताता है कि स्रोत में अब न मिलने वाली अनुवादित प्रविष्टियाँ Stale के रूप में चिह्नित रह सकती हैं। यह स्थिति सफ़ाई का संकेत है, इस बात का प्रमाण नहीं कि संसाधन उपयोग में नहीं है। प्रविष्टि और उसके अनुवाद हटाने से पहले पुराने इंटरफ़ेस असाइनमेंट और Swift कॉलर की जाँच करें। String Catalogs को जानें।

समेकन तब पूरा होता है जब दोनों इंटरफ़ेस एक ही परिभाषा से संदर्भ सहित वही संदेश प्राप्त करें, उसके तर्क जस के तस रहें और पुराने वाक्य टेम्पलेट का कोई कॉलर बाकी न हो। हेल्पर के साथ अनुबंध और स्वीकृति-मामले रखें, ताकि भविष्य में शब्दावली बदलते समय दोनों विंडो में साझा अर्थ सुरक्षित रहे।

स्रोत