Jelajahi Sumber

Add Russian localization and fix Premium sidebar card layout for longer translations.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 1 bulan lalu
induk
melakukan
f88375dd9d

+ 1 - 0
App for Indeed.xcodeproj/project.pbxproj

@@ -110,6 +110,7 @@
 				sv,
 				ko,
 				"pt-BR",
+				ru,
 			);
 			mainGroup = 27D852772FB1D367008DF557;
 			minimizedProjectReferenceProxies = 1;

+ 7 - 1
App for Indeed/Services/AppLocalization.swift

@@ -19,6 +19,7 @@ enum AppLanguage: CaseIterable {
     case chineseTraditional
     case korean
     case portugueseBrazil
+    case russian
 
     var localeIdentifier: String {
         switch self {
@@ -42,6 +43,8 @@ enum AppLanguage: CaseIterable {
             return "ko"
         case .portugueseBrazil:
             return "pt-BR"
+        case .russian:
+            return "ru"
         }
     }
 
@@ -82,6 +85,9 @@ enum AppLanguage: CaseIterable {
         if lower.hasPrefix("pt") {
             return .portugueseBrazil
         }
+        if lower.hasPrefix("ru") {
+            return .russian
+        }
         for language in AppLanguage.allCases where preferred.hasPrefix(language.localeIdentifier) {
             return language
         }
@@ -177,7 +183,7 @@ private func translateTemplateNameByTokens(_ name: String, language: AppLanguage
     switch language {
     case .chineseSimplified, .chineseTraditional:
         return translated.joined()
-    case .arabic, .english, .french, .frenchCanada, .german, .korean, .portugueseBrazil, .swedish:
+    case .arabic, .english, .french, .frenchCanada, .german, .korean, .portugueseBrazil, .russian, .swedish:
         return translated.joined(separator: " ")
     }
 }

+ 1 - 1
App for Indeed/Services/CVTemplateFetchService.swift

@@ -49,7 +49,7 @@ final class CVTemplateFetchService {
             switch language {
             case .english:
                 return spacingRule
-            case .chineseTraditional, .chineseSimplified, .arabic, .french, .frenchCanada, .german, .korean, .portugueseBrazil, .swedish:
+            case .chineseTraditional, .chineseSimplified, .arabic, .french, .frenchCanada, .german, .korean, .portugueseBrazil, .russian, .swedish:
                 return spacingRule + " The app localizes these English keys client-side — do not use non-English script in `name`."
             }
         }

+ 1 - 1
App for Indeed/Services/TemplateNameTokenLexicon.swift

@@ -84,7 +84,7 @@ enum TemplateNameTokenLexicon {
             return fr
         case .swedish:
             return sv
-        case .korean, .portugueseBrazil:
+        case .korean, .portugueseBrazil, .russian:
             return [:]
         }
     }

+ 30 - 10
App for Indeed/Views/DashboardView.swift

@@ -89,6 +89,13 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
         static var settingsDivider: NSColor { AppDashboardTheme.settingsDivider }
     }
 
+    /// Sidebar content band (218pt sidebar minus 6pt edge insets on each side).
+    private static let sidebarProCardWidth: CGFloat = 206
+    private static let sidebarProCardInnerPadding: CGFloat = 14
+    private static var sidebarProCardInnerContentWidth: CGFloat {
+        sidebarProCardWidth - sidebarProCardInnerPadding * 2
+    }
+
     /// Multiline `NSTextField` often ignores `alignment` for wrapped runs; explicit paragraph alignment matches the title.
     private static func jobListingDescriptionAttributedString(_ plain: String) -> NSAttributedString {
         let paragraph = NSMutableParagraphStyle()
@@ -741,7 +748,7 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
               let upgradeDescription = sidebarUpgradeDescription,
               let upgradeButton = sidebarUpgradeButton else { return }
 
-        let descriptionWidth: CGFloat = 158
+        let descriptionWidth = Self.sidebarProCardInnerContentWidth
         if active {
             headline.stringValue = L("You're on Pro")
             upgradeDescription.stringValue = L("Manage billing, renewals, and plans in Premium.")
@@ -753,6 +760,11 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
             upgradeDescription.preferredMaxLayoutWidth = descriptionWidth
             upgradeButton.title = L("Try Pro")
         }
+        headline.preferredMaxLayoutWidth = descriptionWidth
+        headline.invalidateIntrinsicContentSize()
+        upgradeDescription.invalidateIntrinsicContentSize()
+        upgradeButton.invalidateIntrinsicContentSize()
+        sidebarUpgradeCard?.layoutSubtreeIfNeeded()
         updateFreeJobSearchQuotaLabel()
     }
 
@@ -3089,18 +3101,19 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
         eyebrowRow.spacing = 6
         eyebrowRow.alignment = .centerY
 
-        let headline = NSTextField(labelWithString: L("Upgrade to Pro"))
+        let innerContentWidth = Self.sidebarProCardInnerContentWidth
+        let headline = NSTextField(wrappingLabelWithString: L("Upgrade to Pro"))
         headline.font = .systemFont(ofSize: 16, weight: .bold)
         headline.textColor = Theme.primaryText
         headline.alignment = .center
+        headline.maximumNumberOfLines = 0
+        headline.lineBreakMode = .byWordWrapping
+        headline.preferredMaxLayoutWidth = innerContentWidth
 
         let upgradeDescription = NSTextField(wrappingLabelWithString: L("Unlimited AI matches, smart alerts, and interview prep—all in one place."))
         upgradeDescription.font = .systemFont(ofSize: 12, weight: .regular)
         upgradeDescription.textColor = Theme.secondaryText
         upgradeDescription.alignment = .center
-        // Sidebar content width is the fixed sidebar width minus horizontal edge insets; card must stay within that band.
-        let cardWidth: CGFloat = 186
-        let innerContentWidth = cardWidth - 28
         upgradeDescription.preferredMaxLayoutWidth = innerContentWidth
 
         let upgradeButton = HoverableButton(title: L("Try Pro"), target: self, action: #selector(didTapUpgradeToPro))
@@ -3109,11 +3122,16 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
         upgradeButton.font = .systemFont(ofSize: 13, weight: .bold)
         upgradeButton.contentTintColor = Theme.proCTAText
         upgradeButton.alignment = .center
+        upgradeButton.lineBreakMode = .byWordWrapping
         upgradeButton.wantsLayer = true
         upgradeButton.layer?.backgroundColor = Theme.proCTABackground.cgColor
         upgradeButton.layer?.cornerRadius = 8
         upgradeButton.translatesAutoresizingMaskIntoConstraints = false
-        upgradeButton.heightAnchor.constraint(equalToConstant: 32).isActive = true
+        if let cell = upgradeButton.cell as? NSButtonCell {
+            cell.wraps = true
+            cell.isScrollable = false
+        }
+        upgradeButton.heightAnchor.constraint(greaterThanOrEqualToConstant: 32).isActive = true
         upgradeButton.pointerCursor = true
         upgradeButton.hoverHandler = { [weak upgradeButton] hovering in
             upgradeButton?.layer?.backgroundColor = (hovering ? Theme.brandBlueHover : Theme.proCTABackground).cgColor
@@ -3128,18 +3146,20 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
         upgradeCard.addSubview(inner)
 
         NSLayoutConstraint.activate([
-            upgradeCard.widthAnchor.constraint(equalToConstant: cardWidth),
+            upgradeCard.widthAnchor.constraint(equalToConstant: Self.sidebarProCardWidth),
 
             accentBar.topAnchor.constraint(equalTo: upgradeCard.topAnchor),
             accentBar.leadingAnchor.constraint(equalTo: upgradeCard.leadingAnchor),
             accentBar.trailingAnchor.constraint(equalTo: upgradeCard.trailingAnchor),
             accentBar.heightAnchor.constraint(equalToConstant: 2),
 
-            inner.leadingAnchor.constraint(equalTo: upgradeCard.leadingAnchor, constant: 14),
-            inner.trailingAnchor.constraint(equalTo: upgradeCard.trailingAnchor, constant: -14),
+            inner.leadingAnchor.constraint(equalTo: upgradeCard.leadingAnchor, constant: Self.sidebarProCardInnerPadding),
+            inner.trailingAnchor.constraint(equalTo: upgradeCard.trailingAnchor, constant: -Self.sidebarProCardInnerPadding),
             inner.topAnchor.constraint(equalTo: accentBar.bottomAnchor, constant: 12),
-            inner.bottomAnchor.constraint(equalTo: upgradeCard.bottomAnchor, constant: -14),
+            inner.bottomAnchor.constraint(equalTo: upgradeCard.bottomAnchor, constant: -Self.sidebarProCardInnerPadding),
 
+            headline.widthAnchor.constraint(equalTo: inner.widthAnchor),
+            upgradeDescription.widthAnchor.constraint(equalTo: inner.widthAnchor),
             upgradeButton.widthAnchor.constraint(equalTo: inner.widthAnchor)
         ])
 

+ 365 - 0
App for Indeed/ru.lproj/Localizable.strings

@@ -0,0 +1,365 @@
+/* Localizable.strings (Russian) */
+
+// MARK: - Common
+"OK" = "OK";
+"Cancel" = "Отмена";
+"Delete" = "Удалить";
+"Remove" = "Убрать";
+"Dismiss" = "Закрыть";
+
+// MARK: - Launch Screen
+"AI-POWERED" = "НА ОСНОВЕ ИИ";
+"Find your perfect job with the power of AI." = "Найдите идеальную работу с помощью искусственного интеллекта.";
+"Starting up…" = "Запуск…";
+"Loading progress" = "Загрузка прогресса";
+
+// MARK: - Launch Status
+"Checking your Pro subscription…" = "Проверка подписки Pro…";
+"Loading premium plans from the App Store…" = "Загрузка премиум-планов из App Store…";
+"Preparing your job search workspace…" = "Подготовка рабочей области для поиска работы…";
+"Almost ready…" = "Почти готово…";
+
+// MARK: - Sidebar
+"Home" = "Главная";
+"Saved Jobs" = "Сохраненные вакансии";
+"CV Maker" = "Создание резюме";
+"Profile" = "Профиль";
+"Settings" = "Настройки";
+"Premium" = "Премиум";
+"Indeed" = "Indeed";
+"Open Indeed to search and apply for jobs" = "Откройте Indeed, чтобы искать и откликаться на вакансии";
+
+// MARK: - Dashboard / Home
+"Welcome" = "Добро пожаловать";
+"Send" = "Отправить";
+"Clear chat" = "Очистить чат";
+"Remove all messages and start a new conversation" = "Удалить все сообщения и начать новый разговор";
+"Ask for roles, skills, salary, or job descriptions..." = "Спросите о должностях, навыках, зарплате или описаниях вакансий...";
+"Ask AI" = "Спросить ИИ";
+"1 reply left" = "Остался 1 ответ";
+"Apply" = "Откликнуться";
+"Save" = "Сохранить";
+"Saved" = "Сохранено";
+"Remove from saved" = "Убрать из сохраненного";
+"Show more jobs" = "Показать больше вакансий";
+"This area is not available in the preview build. Use Home to search jobs." = "Эта область недоступна в предварительной сборке. Используйте Главную для поиска вакансий.";
+"Save jobs from Home to see them here." = "Сохраняйте вакансии на Главной, чтобы увидеть их здесь.";
+"No saved jobs yet. Search on Home, then tap Save on a listing." = "Пока нет сохраненных вакансий. Найдите на Главной, затем нажмите Сохранить в объявлении.";
+"Tell me what role you want and I will return job descriptions, key skills, and a quick fit summary." = "Скажите, какую должность вы хотите, и я верну описание вакансии, ключевые навыки и краткий анализ соответствия.";
+"1 saved position" = "1 сохраненная позиция";
+"Delete this profile?" = "Удалить этот профиль?";
+"Find roles similar to: " = "Найти должности, похожие на: ";
+"Find jobs at company: " = "Найти вакансии в компании: ";
+"Find jobs that require skill: " = "Найти вакансии, требующие навык: ";
+"match" = "совпадение";
+"matches" = "совпадений";
+
+// MARK: - Feature Shortcuts
+"Role" = "Должность";
+"Explore similar or better job roles" = "Изучить похожие или лучшие должности";
+"Company" = "Компания";
+"Find opportunities at other companies" = "Найти возможности в других компаниях";
+"Skill" = "Навык";
+"Match jobs that fit your skills" = "Подобрать вакансии, соответствующие вашим навыкам";
+
+// MARK: - Pro / Subscription
+"Upgrade to Pro" = "Перейти на Pro";
+"You're on Pro" = "Вы используете Pro";
+"Unlimited AI matches, smart alerts, and interview prep—all in one place." = "Неограниченные совпадения с ИИ, умные уведомления и подготовка к собеседованию — всё в одном месте.";
+"Manage billing, renewals, and plans in Premium." = "Управляйте оплатой, продлением и планами в разделе Премиум.";
+"Try Pro" = "Попробовать Pro";
+"Manage Subscription" = "Управление подпиской";
+"Premium Plans" = "Премиум-планы";
+"Unlock unlimited access to premium tools and boost your productivity." = "Откройте неограниченный доступ к премиум-инструментам и повысьте свою продуктивность.";
+"Continue with free plan" = "Продолжить с бесплатным планом";
+"Restore Purchase" = "Восстановить покупку";
+"You're subscribed" = "Вы подписаны";
+"Thank you — Pro features are now available." = "Спасибо — функции Pro теперь доступны.";
+"Pro" = "Pro";
+"Purchases restored" = "Покупки восстановлены";
+"Your subscription is active." = "Ваша подписка активна.";
+"No subscription found" = "Подписка не найдена";
+"There was nothing to restore for this Apple ID." = "Нечего восстанавливать для этого Apple ID.";
+"Something went wrong" = "Что-то пошло не так";
+"That subscription isn’t available from the App Store right now." = "Эта подписка сейчас недоступна в App Store.";
+"Unlimited AI job search on Home" = "Неограниченный поиск работы с ИИ на Главной";
+"Save jobs & open listings in-app" = "Сохранять вакансии и открывать объявления в приложении";
+"CV Maker, profiles & PDF export" = "Создание резюме, профили и экспорт в PDF";
+"Role, company & skill shortcuts" = "Быстрые ссылки на должности, компании и навыки";
+
+// MARK: - Paywall Plans
+"Weekly" = "Еженедельный";
+"Flexible and commitment-free" = "Гибкий и без обязательств";
+"Monthly" = "Ежемесячный";
+"Balanced for regular productivity" = "Сбалансированный для регулярной продуктивности";
+"Yearly" = "Годовой";
+"Best value for long-term users" = "Лучшая цена для постоянных пользователей";
+"/ week" = "/ неделя";
+"/ month" = "/ месяц";
+"/ year" = "/ год";
+"3 days free trial" = "3 дня бесплатно";
+"Perfect for short-term job hunts" = "Идеально для краткосрочного поиска работы";
+"Cancel anytime" = "Отмена в любое время";
+"Best for regular job seekers" = "Лучше всего для регулярных соискателей";
+"Priority support" = "Приоритетная поддержка";
+"Lowest effective monthly cost" = "Самая низкая эффективная месячная стоимость";
+"Ideal for long-term use" = "Идеально для долгосрочного использования";
+
+// MARK: - Paywall Trust
+"Secure Payments" = "Безопасные платежи";
+"Your payment is 100% secure." = "Ваш платеж на 100% защищен.";
+"Cancel Anytime" = "Отмена в любое время";
+"No commitment, cancel anytime." = "Без обязательств, отмена в любое время.";
+"24/7 Support" = "Поддержка 24/7";
+"We're here to help you anytime." = "Мы всегда готовы помочь.";
+"Privacy First" = "Приватность прежде всего";
+"Your data is safe with us." = "Ваши данные в безопасности.";
+
+// MARK: - Settings
+"Appearance" = "Внешний вид";
+"Theme" = "Тема";
+"Language" = "Язык";
+"Share App" = "Поделиться приложением";
+"More Apps" = "Другие приложения";
+"About" = "О приложении";
+"Website" = "Сайт";
+"Support" = "Поддержка";
+"Terms of Use" = "Условия использования";
+"Privacy Policy" = "Политика конфиденциальности";
+"System" = "Системная";
+"Light" = "Светлая";
+"Dark" = "Темная";
+
+// MARK: - Profiles
+"Profiles" = "Профили";
+"Add new profile" = "Добавить новый профиль";
+"Create and manage CV profiles. Each profile stores your details on this Mac." = "Создавайте и управляйте профилями резюме. Каждый профиль хранит ваши данные на этом Mac.";
+"No profiles yet. Tap “Add new profile” to create your first one." = "Пока нет профилей. Нажмите «Добавить новый профиль», чтобы создать первый.";
+"Build CV" = "Создать резюме";
+"Edit" = "Редактировать";
+"Untitled profile" = "Профиль без названия";
+"No contact details yet" = "Контактные данные пока не добавлены";
+"← Profiles" = "← Профили";
+
+// MARK: - Profile Editor
+"Save Profile  →" = "Сохранить профиль →";
+"← All profiles" = "← Все профили";
+"New profile" = "Новый профиль";
+"Edit profile" = "Редактировать профиль";
+"Profile Name *" = "Название профиля *";
+"Marketing Director Profile" = "Профиль директора по маркетингу";
+"Personal Information" = "Личная информация";
+"Full Name *" = "Полное имя *";
+"John Doe" = "Иван Петров";
+"Email *" = "Эл. почта *";
+"john@example.com" = "ivan@example.ru";
+"Phone" = "Телефон";
+"+1 (555) 123-4567" = "+7 (495) 123-45-67";
+"Job Title *" = "Должность *";
+"Software Engineer" = "Инженер-программист";
+"Address" = "Адрес";
+"123 Main St, City, State, ZIP" = "ул. Тверская, д. 1, Москва, 125009";
+"Certificates / Rewards" = "Сертификаты / Награды";
+"List your certificates and awards..." = "Перечислите свои сертификаты и награды...";
+"Interests" = "Интересы";
+"List your interests and hobbies..." = "Перечислите свои интересы и хобби...";
+"Languages" = "Языки";
+"List languages you speak (e.g., English - Native, Spanish - Fluent)..." = "Перечислите языки, на которых вы говорите (напр., Русский — Родной, Английский — Свободно)...";
+"Career Summary" = "Краткое описание карьеры";
+"Brief overview of your professional background and key achievements..." = "Краткий обзор вашего профессионального опыта и ключевых достижений...";
+"Referral (Optional)" = "Рекомендация (необязательно)";
+"Referred by (Company/Person Name)" = "Рекомендовал(а) (Компания/Имя)";
+"If someone referred you for this job, enter their name or company here" = "Если кто-то порекомендовал вас на эту должность, укажите его имя или компанию";
+"Work Experience" = "Опыт работы";
+"Education" = "Образование";
+"+ Add Another" = "+ Добавить еще";
+"Complete required fields" = "Заполните обязательные поля";
+"Remove experience" = "Удалить опыт";
+"Remove education" = "Удалить образование";
+"Company Name *" = "Название компании *";
+"Duration *" = "Период *";
+"Description" = "Описание";
+"e.g., Software Engineer" = "напр., Инженер-программист";
+"e.g., Google" = "напр., Google";
+"e.g., Jan 2020 - Present" = "напр., янв. 2023 — наст. время";
+"Describe your responsibilities and achievements..." = "Опишите свои обязанности и достижения...";
+"Degree / program *" = "Степень / программа *";
+"Institution *" = "Учебное заведение *";
+"Year *" = "Год *";
+"e.g., BSc Computer Science" = "напр., Бакалавр компьютерных наук";
+"e.g., MIT" = "напр., МГУ";
+"e.g., 2020" = "напр., 2023";
+"Profile name" = "Название профиля";
+"Full Name" = "Полное имя";
+"Email" = "Эл. почта";
+"Job Title" = "Должность";
+
+// MARK: - CV Maker
+"Templates" = "Шаблоны";
+"Polished layouts with live previews — pick a style that fits your story." = "Отточенные макеты с живым предпросмотром — выберите стиль, который подходит вашей истории.";
+"Use Template & Select Profile  →" = "Использовать шаблон и выбрать профиль →";
+"All" = "Все";
+"No templates yet for this category." = "Пока нет шаблонов для этой категории.";
+"Pick a template" = "Выберите шаблон";
+"Select a template first, then choose a profile to continue." = "Сначала выберите шаблон, затем выберите профиль, чтобы продолжить.";
+"Fetching AI-curated templates…" = "Загрузка шаблонов, отобранных ИИ…";
+"Couldn’t load AI templates — showing the built-in gallery." = "Не удалось загрузить шаблоны ИИ — показываем встроенную галерею.";
+"Design-Based" = "По дизайну";
+"Profession-Based" = "По профессии";
+"Professional" = "Профессиональный";
+"Modern" = "Современный";
+"Creative" = "Креативный";
+"Minimal" = "Минималистичный";
+"Executive" = "Для руководителей";
+"ATS layout" = "ATS-макет";
+"Sidebar left" = "Боковая панель слева";
+"Sidebar right" = "Боковая панель справа";
+
+// MARK: - CV Preview
+"CV preview" = "Предпросмотр резюме";
+"Export PDF…" = "Экспорт PDF…";
+"Layout matches the CV Maker thumbnail for this template. Export a PDF that matches what you see here (fonts, columns, colours, and rules)." = "Макет соответствует миниатюре Создания резюме для этого шаблона. Экспортируйте PDF, соответствующий тому, что вы видите здесь (шрифты, колонки, цвета и линии).";
+"The résumé could not be rendered to PDF (empty output). Try scrolling the preview so it lays out, then export again." = "Не удалось преобразовать резюме в PDF (пустой вывод). Попробуйте прокрутить предпросмотр, чтобы оно выстроилось, затем экспортируйте снова.";
+"Couldn’t save PDF" = "Не удалось сохранить PDF";
+"Your name" = "Ваше имя";
+"Professional headline" = "Профессиональный заголовок";
+"Experience" = "Опыт";
+"Highlights" = "Основные моменты";
+"Summary" = "Резюме";
+"Contact" = "Контакты";
+"Skills" = "Навыки";
+"Tools" = "Инструменты";
+"Languages & more" = "Языки и другое";
+"Certificates" = "Сертификаты";
+"Referrals" = "Рекомендации";
+"Professional Summary" = "Профессиональное резюме";
+"Selected Experience" = "Избранный опыт";
+"Core Competencies" = "Ключевые компетенции";
+"Impact" = "Вклад";
+"Add contact in your profile" = "Добавьте контакт в профиль";
+"Add contact details in your profile" = "Добавьте контактные данные в профиль";
+"Add a career summary or interests in your profile to populate this column." = "Добавьте краткое описание карьеры или интересы в профиль, чтобы заполнить эту колонку.";
+"CV" = "Резюме";
+"Open to relocation" = "Готов к переезду";
+"STRENGTHS" = "СИЛЬНЫЕ СТОРОНЫ";
+"PORTFOLIO SNAPSHOT" = "СНИМОК ПОРТФОЛИО";
+"Close" = "Закрыть";
+"/ day" = "/ день";
+"/ %d days" = "/ %d дней";
+"/ %d weeks" = "/ %d недель";
+"/ %d months" = "/ %d месяцев";
+"/ %d years" = "/ %d лет";
+
+// MARK: - CV Template Names
+"Paper White" = "Белая бумага";
+"Swiss" = "Swiss";
+"Mono" = "Mono";
+"Airy" = "Воздушный";
+"Tabular" = "Табличный";
+"Facet" = "Фасет";
+"Corporate" = "Корпоративный";
+"Atlas" = "Атлас";
+"Ledger" = "Реестр";
+"Harbor" = "Гавань";
+"Clear Path" = "Ясный путь";
+"Pinstripe" = "Полоска";
+"Briefing" = "Брифинг";
+"Quorum" = "Кворум";
+"Docket" = "Реестр дел";
+"Conduit" = "Канал";
+"Principal" = "Принципал";
+"Charter" = "Хартия";
+"Vertex" = "Вершина";
+"Linea" = "Линия";
+"Prism" = "Призма";
+"Circuit" = "Схема";
+"North" = "Север";
+"Axis" = "Ось";
+"Marigold" = "Бархатцы";
+"Ember" = "Уголек";
+"Lattice" = "Решетка";
+"Bloom" = "Цветение";
+"Studio" = "Студия";
+"Kite" = "Воздушный змей";
+"Regent" = "Регент";
+"Monarch" = "Монарх";
+"Sterling" = "Стерлинг";
+"Summit" = "Вершина";
+"Estate" = "Поместье";
+"Chairman" = "Председатель";
+"Blue Ocean" = "Голубой океан";
+
+// MARK: - CV Demo Preview Content
+"Sarah Johnson" = "Екатерина Смирнова";
+"Senior Product Manager" = "Старший менеджер продукта";
+"Group PM, Consumer Growth & Activation" = "Групповой менеджер продукта, рост и активация потребителей";
+"Google · Mountain View, CA · 2019 – Present" = "Google · Москва · 2019 – настоящее время";
+"Stanford University" = "МГУ им. Ломоносова";
+"M.S. Management Science & Engineering" = "Магистр наук в области управления и инженерии";
+"2014 – 2016" = "2014 – 2016";
+"Mountain View, CA" = "Москва";
+"Product leader shipping roadmap, discovery, and analytics for high-scale consumer experiences." = "Лидер продукта, отвечающий за дорожную карту, поиск и аналитику для масштабного потребительского опыта.";
+"Defined multi-year platform strategy with exec stakeholders and quarterly OKRs." = "Определил многолетнюю стратегию платформы с исполнительным руководством и квартальными OKR.";
+"Partnered with engineering and design to launch experiments improving activation by 12%." = "Сотрудничал с инженерами и дизайнерами для запуска экспериментов, улучшивших активацию на 12%.";
+"Stood up quarterly business reviews with finance and GTM, aligning spend to north-star metrics." = "Организовал ежеквартальные обзоры бизнеса с финансами и GTM, согласовав расходы с ключевыми метриками.";
+"Presented roadmap shifts to the leadership team and translated trade-offs into clear investment asks." = "Представил изменения дорожной карты руководству и перевел компромиссы в четкие запросы на инвестиции.";
+"Figma · SQL · Amplitude · Jira · BigQuery" = "Figma · SQL · Amplitude · Jira · BigQuery";
+"Product Strategy" = "Стратегия продукта";
+"A/B Testing" = "A/B тестирование";
+"Roadmapping" = "Планирование дорожной карты";
+"CONTACT" = "КОНТАКТЫ";
+"SKILLS" = "НАВЫКИ";
+"PROFILE" = "ПРОФИЛЬ";
+"EXPERIENCE" = "ОПЫТ";
+"EDUCATION" = "ОБРАЗОВАНИЕ";
+"SUMMARY" = "РЕЗЮМЕ";
+"PROFESSIONAL SUMMARY" = "ПРОФЕССИОНАЛЬНОЕ РЕЗЮМЕ";
+"SELECTED EXPERIENCE" = "ИЗБРАННЫЙ ОПЫТ";
+"CORE COMPETENCIES" = "КЛЮЧЕВЫЕ КОМПЕТЕНЦИИ";
+"TOOLS" = "ИНСТРУМЕНТЫ";
+"IMPACT" = "ВКЛАД";
+
+// MARK: - Job Browser
+"Go to Indeed home" = "Перейти на главную Indeed";
+
+// MARK: - Errors
+"We couldn't reach the server. Check your internet connection and try again." = "Не удается подключиться к серверу. Проверьте подключение к интернету и повторите попытку.";
+"The search was cancelled. Try again when you're ready." = "Поиск был отменен. Попробуйте снова, когда будете готовы.";
+"The request was cancelled. Try again when you're ready." = "Запрос был отменен. Попробуйте снова, когда будете готовы.";
+"Something went wrong while searching. Please try again in a moment." = "Во время поиска произошла ошибка. Повторите попытку через минуту.";
+"Job search is unavailable." = "Поиск работы недоступен.";
+"We couldn't complete your purchase. Please try again." = "Не удалось завершить покупку. Повторите попытку.";
+"We couldn't restore your purchases. Please try again." = "Не удалось восстановить покупки. Повторите попытку.";
+"Purchase was cancelled." = "Покупка была отменена.";
+"This subscription isn't available in your App Store region." = "Эта подписка недоступна в вашем регионе App Store.";
+"Purchases aren't allowed on this account or device." = "Покупки не разрешены для этой учетной записи или устройства.";
+"This introductory offer isn't available for your account." = "Это вводное предложение недоступно для вашей учетной записи.";
+"The purchase couldn't be verified. Please try again." = "Не удалось подтвердить покупку. Повторите попытку.";
+"We couldn't save the PDF. Try again or choose a different folder." = "Не удалось сохранить PDF. Повторите попытку или выберите другую папку.";
+"We don't have permission to save to that folder. Choose another location or grant access." = "У нас нет разрешения на сохранение в эту папку. Выберите другое место или предоставьте доступ.";
+"This disk is read-only. Choose another folder to save your PDF." = "Этот диск доступен только для чтения. Выберите другую папку для сохранения PDF.";
+"The disk is full. Free up space, then try again." = "Диск заполнен. Освободите место и повторите попытку.";
+
+// MARK: - Alerts
+"This profile will be removed from this Mac." = "Этот профиль будет удален с этого Mac.";
+
+// MARK: - Format Strings
+"Loading %@" = "Загрузка %@";
+"Loading %@. %@" = "Загрузка %@. %@";
+"Starting %@…" = "Запуск %@…";
+"%d replies left" = "Осталось %d ответов";
+"%d saved positions" = "%d сохраненных позиций";
+"“%@” will be removed from this Mac." = "«%@» будет удален с этого Mac.";
+"%@ isn’t available yet" = "%@ еще недоступен";
+"I couldn't find new matches for “%@”. Try a different angle or a more specific keyword." = "Не удалось найти новые совпадения для «%@». Попробуйте другой подход или более конкретное ключевое слово.";
+"No jobs found for “%@”. Try another title, skill, company, or location." = "Не найдено вакансий для «%@». Попробуйте другую должность, навык, компанию или местоположение.";
+"Here are %d more %@ for “%@”." = "Вот еще %d %@ для «%@».";
+"Found %d %@ for “%@”. Tap Apply to open the listing or Save to revisit later." = "Найдено %d %@ для «%@». Нажмите Откликнуться, чтобы открыть объявление, или Сохранить, чтобы вернуться позже.";
+"Get %@" = "Получить %@";
+"You chose the “%@” template. Tap Build CV on a profile to preview your résumé with that layout." = "Вы выбрали шаблон «%@». Нажмите Создать резюме в профиле, чтобы предварительно просмотреть свое резюме с этим макетом.";
+"Experience %d" = "Опыт %d";
+"Education %d" = "Образование %d";
+"Please fill in: %@." = "Пожалуйста, заполните: %@.";
+
+// MARK: - Multi-line
+"Add your Mac App Store IDs in the target’s build settings:\n• AppStoreAppID — numeric app ID from App Store Connect\n• AppStoreDeveloperID — numeric developer ID (for your other apps page)" = "Добавьте свои идентификаторы Mac App Store в настройки сборки цели:\n• AppStoreAppID — числовой идентификатор приложения из App Store Connect\n• AppStoreDeveloperID — числовой идентификатор разработчика (для страницы с вашими другими приложениями)";