Site icon AppTractor

Сделайте приложение более персонализированным с Language Discovery

В современном взаимосвязанном мире предположение о том, что у пользователей есть один «основной язык», в корне неверно. Взять, к примеру, повседневную жизнь миллионов людей, например, инженера-программиста из Торонто, который пишет код на английском, читает техническую документацию на английском, но читает новости на испанском и пишет сообщения семье на французском.

Эти пользователи не вписываются в традиционную парадигму «выберите свой язык», доминирующую в современном дизайне приложений. Их языковая идентичность изменчива, контекстуальна и глубоко личная. Тем не менее, большинство приложений по-прежнему заставляют их просматривать алфавитные списки из сотен языков, возможно, довольствуясь английским просто потому, что его проще найти. Разрыв между нашей многоязычной реальностью и тем, как технологии обрабатывают языковые предпочтения, может представлять собой препятствие для по-настоящему инклюзивного опыта использования приложений.

Функция обнаружения языка в iOS 26 призвана изменить эту динамику, внедряя интеллектуальное контекстно-зависимое определение языка, которое понимает, как люди на самом деле используют свои устройства.

Текущий выбор языка

Ограничения традиционного выбора языка становятся очевидны, если рассмотреть техническую реализацию, с которой разработчики работают годами.

На самом деле, до iOS 26 языковые настройки были доступны через простой строковый API:

// iOS 18 and earlier
let userLanguages = Locale.preferredLanguages
print("User's languages:", userLanguages)

// Output: ["en-US", "es-MX", "fr-CA"]

Такой подход создавал несколько фундаментальных проблем. Во-первых, разработчики получали только базовые строковые идентификаторы без контекстной информации. Определение направления текста справа налево в языке, понимание правил наименования валют или календарных систем требовали дополнительных ручных поисков и жёстко запрограммированной логики.

Во-вторых, система полностью полагалась на ручную настройку пользователем. Пользователям приходилось явно добавлять языки в настройках, а затем вручную выбирать их в каждом приложении. Это создавало значительные трудности. Многие пользователи по умолчанию использовали английский язык, вместо того чтобы разбираться в сложных процессах настройки.

В-третьих, отсутствовал интеллектуальный уровень. Система не могла понять, что пользователь с настроенным на английский язык интерфейсом может фактически просматривать преимущественно арабский контент, или что кто-то с устройством, настроенным на французский, регулярно общается на испанском.

Распознавание языка в iOS 26

В iOS 26 представлена ​​интеллектуальная система, которая определяет языковые предпочтения пользователя посредством поведенческого анализа, а не требует явной настройки. Это представляет собой фундаментальный переход от распознавания языка пользователем к распознаванию языка системой.

Функция обнаружения языка Language Discovery анализирует реальные модели использования устройства с помощью машинного обучения на устройстве:

Для технической реализации iOS 26 предоставляет расширенные объекты локалей, содержащие подробную культурную и лингвистическую информацию:

class LanguageDiscoveryManager: ObservableObject {

    @Published var discoveredLanguages: [LocaleInfo] = []
    @Published var isLoading: Bool = false
    
    func discoverUserLanguages() {
        isLoading = true

        // Simulate a slight delay for demo purposes
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            let preferredLocales = self.getPreferredLocales()
            
            self.discoveredLanguages = preferredLocales.prefix(8).map { locale in
                LocaleInfo(
                    identifier: locale.identifier,
                    displayName: locale.localizedString(forIdentifier: locale.identifier) ?? "Unknown",
                    languageCode: locale.language.languageCode?.identifier ?? "",
                    regionCode: locale.region?.identifier ?? "",
                    numberingSystem: locale.numberingSystem.identifier,
                    isRTL: locale.language.characterDirection == .rightToLeft,
                    calendarIdentifier: String(describing: locale.calendar.identifier),
                    currencyCode: locale.currency?.identifier
                )
            }
            
            self.isLoading = false
        }
    }
    
     private func getPreferredLocales() -> [Locale] {
        return Locale.preferredLocales
    }
}

Этот менеджер демонстрирует, как Language Discovery преобразует простой разбор строк в глубокое понимание культурных особенностей. Каждый обнаруженный язык сопровождается подробными метаданными, которые обеспечивают культурно-адаптированное поведение приложений.

Новый API Locale.preferredLocales представляет собой не просто постепенное улучшение, а полное переосмысление того, как iOS работает с многоязычными пользователями.

В то время как старый API был основан на строках и требовал обширной ручной обработки, вынуждая разработчиков поддерживать жёстко заданные соответствия для культурных особенностей, новый API предоставляет всё необходимое для приложений, учитывающих культурные особенности (identifier, displayName, languageCode и т.д.).

Эта расширенная структура данных исключает необходимость догадываться и обеспечивает точный культурный контекст для каждого пользовательского предпочтения.

В качестве примера эффективного использования этой информации давайте определим комплексную модель данных:

struct LocaleInfo: Identifiable, Hashable {
    let id = UUID()
    let identifier: String
    let displayName: String
    let languageCode: String
    let regionCode: String
    let numberingSystem: String
    let isRTL: Bool
    let calendarIdentifier: String
    let currencyCode: String?
}

struct LanguageItem: Identifiable, Hashable {
    let id = UUID()
    let locale: Locale
    let isPreferred: Bool
    
    var displayName: String {
        locale.localizedString(forIdentifier: locale.identifier) ?? locale.identifier
    }
    
    var identifier: String {
        locale.identifier
    }
}

Эта модель учитывает не только языковые идентификаторы, но и полный культурный контекст, необходимый для уважительного и корректного поведения приложения.

Создание вашей первой функции обнаружения языка

Практическая реализация обнаружения языка включает создание интеллектуальных систем, которые отдают приоритет предпочтениям пользователя, обеспечивая при этом комплексную языковую поддержку.

Основной принцип интеллекта заключается в сопоставлении предпочтений пользователя с возможностями приложения:

class SmartLanguagePickerManager: ObservableObject {

    @Published var preferredLanguages: [LanguageItem] = []
    @Published var otherLanguages: [LanguageItem] = []
    @Published var selectedLocale: Locale?
    
    // Simulate a comprehensive list of app-supported languages
    let availableLocales: [Locale] = [
        Locale(identifier: "en-US"), // English (US)
        Locale(identifier: "en-GB"), // English (UK)
        Locale(identifier: "es-ES"), // Spanish (Spain)
        Locale(identifier: "es-MX"), // Spanish (Mexico)
        Locale(identifier: "fr-FR"), // French (France)
        Locale(identifier: "ar-SA"), // Arabic (Saudi Arabia)
        Locale(identifier: "ar-EG"), // Arabic (Egypt)
        Locale(identifier: "ar-LB"), // Arabic (Lebanon)
        Locale(identifier: "zh-CN"), // Chinese (Simplified)
        Locale(identifier: "ja-JP"), // Japanese
        Locale(identifier: "ko-KR"), // Korean
        Locale(identifier: "hi-IN"), // Hindi
        // Additional languages...
    ]
    
    func organizeLanguages() {
        let userPreferredLocales = getPreferredLocales()
        var matched: [LanguageItem] = []
        var remaining: [LanguageItem] = []
        
        for availableLocale in availableLocales {
            var isMatched = false
            
            // Check for matches with user preferences
            for preferredLocale in userPreferredLocales {
                if isLanguageMatch(available: availableLocale, preferred: preferredLocale) {
                    matched.append(LanguageItem(locale: availableLocale, isPreferred: true))
                    isMatched = true
                    break
                }
            }
            
            if !isMatched {
                remaining.append(LanguageItem(locale: availableLocale, isPreferred: false))
            }
        }
        // Sort remaining languages alphabetically
        remaining.sort { $0.displayName < $1.displayName }
        
        preferredLanguages = matched
        otherLanguages = remaining
    }
}

Алгоритм сопоставления демонстрирует глубокое понимание языковых отношений:

private func isLanguageMatch(available: Locale, preferred: Locale) -> Bool {
    // Exact match: en-US matches en-US
    if available.identifier == preferred.identifier {
        return true
    }
    
    // Language code match (e.g., en-US matches en-GB)
    if available.language.languageCode?.identifier == preferred.language.languageCode?.identifier {
        return true
    }
    
    return false
}

Эта логика учитывает, что пользователи, предпочитающие английский (США), также будут чувствовать себя комфортно с вариантами английского (Великобритания), демонстрируя понимание культурных особенностей, а не строгое соответствие строкам.

Реализация пользовательского интерфейса

Ниже представлена ​​реализация интерфейса, отражающая интеллектуальную приоритизацию:

struct SmartLanguagePickerView: View {

    @StateObject private var manager = SmartLanguagePickerManager()
    @State private var showingSelection = false
    
    var body: some View {
        NavigationView {
            List {
                Section {
                    Text("Languages matching your preferences appear first, followed by all other supported languages.")
                        .font(.caption)
                        .foregroundColor(.secondary)
                        .padding(.vertical, 4)
                } header: {
                    Text("Smart Language Selection")
                }
                
                // Prioritized user languages
                if !manager.preferredLanguages.isEmpty {
                    Section("Your Languages") {
                        ForEach(manager.preferredLanguages) { item in
                            LanguagePickerRow(
                                item: item,
                                isSelected: manager.selectedLocale?.identifier == item.identifier
                            ) {
                                manager.selectLanguage(item.locale)
                                showingSelection = true
                            }
                        }
                    }
                }
                
                // Comprehensive language support
                Section("Other Languages") {
                    ForEach(manager.otherLanguages) { item in
                        LanguagePickerRow(
                            item: item,
                            isSelected: manager.selectedLocale?.identifier == item.identifier
                        ) {
                            manager.selectLanguage(item.locale)
                            showingSelection = true
                        }
                    }
                }
            }
            .navigationTitle("Smart Picker")
            .onAppear {
                manager.organizeLanguages()
            }
        }
    }
}

Компонент языковой строки демонстрирует имеющуюся всестороннюю культурную информацию:

struct LanguageDiscoveryRow: View {
    let localeInfo: LocaleInfo
    
    var body: some View {
        VStack(alignment: .leading, spacing: 6) {
            HStack {
                Text(localeInfo.displayName)
                    .font(.headline)
                    .fontWeight(.medium)
                
                Spacer()
                
                // Automatic RTL detection and indication
                if localeInfo.isRTL {
                    Image(systemName: "arrow.left")
                        .foregroundColor(.blue)
                        .font(.caption)
                }
            }
            
            // Cultural context information
            HStack {
                Label(localeInfo.identifier, systemImage: "globe")
                    .font(.caption)
                    .foregroundColor(.secondary)
                
                Spacer()
                
                Text("•")
                    .foregroundColor(.secondary)
                
                Text(localeInfo.calendarIdentifier)
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
            
            // Comprehensive formatting information
            HStack {
                Text("Numbers: \(localeInfo.numberingSystem)")
                    .font(.caption2)
                    .foregroundColor(.secondary)
                
                if let currency = localeInfo.currencyCode {
                    Spacer()
                    Text("Currency: \(currency)")
                        .font(.caption2)
                        .foregroundColor(.secondary)
                }
            }
        }
        .padding(.vertical, 4)
    }
}

Эта реализация демонстрирует, как Language Discovery позволяет приложениям отображать не только названия языков, но и полный культурный контекст, включая направление текста, календарные системы, системы исчисления и информацию о валютах.

Визуальные индикаторы (например, стрелка RTL для арабского языка) предоставляют непосредственный контекст языковых характеристик, а подробная информация помогает пользователям точно понять, какие культурные традиции будут применяться.

Language Discovery представляет собой фундаментальную эволюцию в подходе технологий к многоязычным пользователям. Вместо того, чтобы рассматривать язык как простую настройку предпочтений, он рассматривает языковую идентичность как сложную, контекстуальную и глубоко личную. Этот переход от ручной интерпретации к богатым культурным данным, предоставляемым системой, обеспечивает более точный и уважительный многоязычный опыт.

Хотя примеры в этой статье демонстрируют базовую реализацию Language Discovery, технология обеспечивает сложный многоязычный опыт в различных категориях приложений. Например, приложения для покупок могут отображать цены в соответствующих валютах и ​​форматах, а финансовые приложения могут использовать правильные календарные системы для культур, не использующих исключительно григорианский календарь.

Внедряя Language Discovery в свои приложения, вы не просто добавляете функцию, вы участвуете в фундаментальном переходе к технологии, которая уважает и приветствует богатую языковую реальность нашего взаимосвязанного мира.

Источник

Exit mobile version