Skip to content

feat(i18n): add Russian locale#793

Open
bubelov wants to merge 1 commit intomainfrom
translate-ru
Open

feat(i18n): add Russian locale#793
bubelov wants to merge 1 commit intomainfrom
translate-ru

Conversation

@bubelov
Copy link
Collaborator

@bubelov bubelov commented Mar 5, 2026

It's not perfect but that's a solid start

Summary by CodeRabbit

Release Notes

  • New Features
    • Russian language support is now available. Users can select Russian from the language switcher in the footer to experience the full interface in Russian.

@netlify
Copy link

netlify bot commented Mar 5, 2026

Deploy Preview for btcmap ready!

Name Link
🔨 Latest commit 4e2e527
🔍 Latest deploy log https://app.netlify.com/projects/btcmap/deploys/69a985e23a9c6d0008db89c4
😎 Deploy Preview https://deploy-preview-793--btcmap.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 57 (🔴 down 38 from production)
Accessibility: 97 (no change from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 98 (🔴 down 1 from production)
PWA: 90 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

Adds Russian language support to the application by introducing locale registration in the i18n system, extending the footer language-switcher UI with a new Russian button, and providing comprehensive Russian translations for all user-facing text throughout the application.

Changes

Cohort / File(s) Summary
Footer Language Switcher
src/components/layout/Footer.svelte
Adds a new RU language button that toggles the locale to 'ru', mirrors existing EN/PT/BG button styling, includes ARIA labels, and disables itself when Russian is active.
i18n Configuration
src/lib/i18n/index.ts
Registers Russian ('ru') as a supported locale, updates SUPPORTED_LOCALES constant, and extends initial locale detection to recognize browser language preference for Russian.
Russian Translations
src/lib/i18n/locales/ru.json
Introduces comprehensive Russian translation file with 1097 lines covering UI text across all application modules including home, navigation, search, categories, maps, merchants, payments, dashboards, leaderboards, communities, forms, and support sections.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • PR #701: Adds Russian locale support and RU button in the same location (i18n registration and footer language-switcher), indicating potential duplicate or related localization work
  • PR #709: Modifies i18n system and locale resources, suggesting overlapping localization infrastructure changes
  • PR #771: Updates footer language-switcher and i18n locale configuration, indicating related changes to language support

Suggested reviewers

  • escapedcat

Poem

🐰 Whiskers twitch with joy so bright,
Russian words now set just right!
Buttons click and locales flow,
From Moscow to the web we go! 🌍✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is minimally informative and largely incomplete, lacking required template sections like issue reference, detailed change description, screenshots, and context. Expand the description to include a related issue reference, detailed explanation of changes made (new locale file, SUPPORTED_LOCALES update, UI button), and any relevant context about completeness.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(i18n): add Russian locale' accurately summarizes the main change—adding Russian language support to the i18n system.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch translate-ru

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review
Copy link
Contributor

Review Summary by Qodo

Add Russian locale support with translations and language switcher

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add Russian locale support with 1097 translation strings
• Register Russian language in i18n configuration
• Add Russian language switcher button to footer
• Implement browser language detection for Russian
Diagram
flowchart LR
  A["i18n Configuration"] -->|register| B["Russian Locale"]
  B -->|lazy load| C["ru.json Translation File"]
  D["Browser Language Detection"] -->|detect ru| B
  E["Footer Component"] -->|add button| F["Russian Language Switcher"]
  F -->|switch to| B
Loading

Grey Divider

File Changes

1. src/lib/i18n/locales/ru.json Localization +1097/-0

Add complete Russian locale translation file

• Add comprehensive Russian translation file with 1097 strings
• Cover all UI sections including home, navigation, search, categories, merchant details, payments,
 boosts, comments, forms, and more
• Include translations for error messages, success messages, warnings, and accessibility labels
• Provide Russian translations for community features, leaderboards, and administrative functions

src/lib/i18n/locales/ru.json


2. src/lib/i18n/index.ts Configuration +3/-1

Register Russian locale and enable language detection

• Register Russian locale with lazy loading from ./locales/ru.json
• Add "ru" to SUPPORTED_LOCALES constant array
• Add Russian language detection in getInitialLocale() function to check for navigator.language
 starting with "ru"

src/lib/i18n/index.ts


3. src/components/layout/Footer.svelte ✨ Enhancement +14/-0

Add Russian language switcher to footer

• Add Russian language button next to Bulgarian language button
• Include separator span between Bulgarian and Russian buttons
• Implement click handler to switch language to 'ru'
• Add proper styling classes and aria-label for accessibility
• Set disabled state when Russian locale is already active

src/components/layout/Footer.svelte


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Mar 5, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Missing RU switch translation 🐞 Bug ✓ Correctness
Description
The new RU footer button uses footer.switchToRussian for its aria-label, but that key is missing
from existing locales (en/pt-BR/bg). This will likely render a raw key string as the aria-label
(accessibility regression) for most users.
Code

src/components/layout/Footer.svelte[R108-114]

+			<span class="text-body dark:text-white/50"> / </span>
+			<button
+				type="button"
+				on:click={() => switchLanguage('ru')}
+				disabled={$locale === 'ru'}
+				aria-label={$_('footer.switchToRussian')}
+				class="
Evidence
Footer introduces a new RU button whose aria-label depends on footer.switchToRussian. i18n is
configured with fallbackLocale: "en", but en.json (and pt-BR.json/bg.json) do not define
switchToRussian, so there is no available translation in current or fallback locales.

src/components/layout/Footer.svelte[108-121]
src/lib/i18n/index.ts[37-41]
src/lib/i18n/locales/en.json[307-320]
src/lib/i18n/locales/pt-BR.json[295-308]
src/lib/i18n/locales/bg.json[305-318]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A new RU language switch button uses `$_(&#x27;footer.switchToRussian&#x27;)` for `aria-label`, but `switchToRussian` is missing from non-Russian locale JSON files. This causes the aria-label to fall back to a raw key string, harming accessibility.

## Issue Context
`svelte-i18n` is configured with `fallbackLocale: &#x27;en&#x27;`. If the key is missing in the current locale and in `en`, the UI will not have a meaningful aria-label.

## Fix Focus Areas
- src/lib/i18n/locales/en.json[307-320]
- src/lib/i18n/locales/pt-BR.json[295-308]
- src/lib/i18n/locales/bg.json[305-318]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. RU country names fallback 🐞 Bug ✓ Correctness
Description
After enabling ru as a supported UI locale, country name localization will still fall back to the
provided (likely English/OSM) names because getCountryName only maps/loads en, pt-BR, and bg
locales.
Code

src/lib/i18n/index.ts[R7-10]

+register("ru", () => import("./locales/ru.json"));

-export const SUPPORTED_LOCALES = ["en", "pt-BR", "bg"] as const;
+export const SUPPORTED_LOCALES = ["en", "pt-BR", "bg", "ru"] as const;
Evidence
The PR makes ru a supported locale and registers it for UI translations. Country list UIs pass the
current $locale into getCountryName, but getCountryName maps locales through localeMap which
does not include ru, so it falls back to en behavior and returns the unlocalized fallback name.

src/lib/i18n/index.ts[4-10]
src/routes/countries/[section]/components/CountryCard.svelte[13-18]
src/lib/countryNames.ts[5-9]
src/lib/countryNames.ts[32-36]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
With `ru` now supported for UI translations, country names shown via `getCountryName(...)` will not be localized to Russian because `localeMap`/`localeLoaders` do not include `ru`.

## Issue Context
Country list and country pages pass the current `$locale` into `getCountryName`. For `ru`, `getCountryName` falls back to English behavior and returns the fallback name.

## Fix Focus Areas
- src/lib/countryNames.ts[5-21]
- src/lib/countryNames.test.ts[6-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +108 to +114
<span class="text-body dark:text-white/50"> / </span>
<button
type="button"
on:click={() => switchLanguage('ru')}
disabled={$locale === 'ru'}
aria-label={$_('footer.switchToRussian')}
class="
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Missing ru switch translation 🐞 Bug ✓ Correctness

The new RU footer button uses footer.switchToRussian for its aria-label, but that key is missing
from existing locales (en/pt-BR/bg). This will likely render a raw key string as the aria-label
(accessibility regression) for most users.
Agent Prompt
## Issue description
A new RU language switch button uses `$_('footer.switchToRussian')` for `aria-label`, but `switchToRussian` is missing from non-Russian locale JSON files. This causes the aria-label to fall back to a raw key string, harming accessibility.

## Issue Context
`svelte-i18n` is configured with `fallbackLocale: 'en'`. If the key is missing in the current locale and in `en`, the UI will not have a meaningful aria-label.

## Fix Focus Areas
- src/lib/i18n/locales/en.json[307-320]
- src/lib/i18n/locales/pt-BR.json[295-308]
- src/lib/i18n/locales/bg.json[305-318]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@escapedcat
Copy link
Contributor

Long words breaking our design
image

But it's better than nothing and we can think about how to solve this.
Either for now just wrap it differently or a more complex solution.
I think wrapping can be a good first step for now.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/i18n/locales/ru.json`:
- Line 536: Replace the misspelled and spacing errors in ru.json: change
"обьединяйтесь" to "объединяйтесь" in the value for the "description" entry that
currently contains "Возьмите на себя поддержку локальных данных и помогите
стимулировать распространение биткойна. Присоединяйтесь, добавляйте бизнес,
обьединяйтесь."; also remove the extra space in the hyphenated phrase "биткоин-
дружественными" (make it "биткоин-дружественными") wherever that exact string
appears. Search for those exact substrings in src/lib/i18n/locales/ru.json and
update the JSON values accordingly, ensuring punctuation and encoding remain
valid.
- Around line 1-1097: Locale parity check found two discrepancies: add the
missing translation key "dashboard.totalAreas" to ru.json with an appropriate
Russian string (matching the en.json meaning) and remove the extra key
"footer.switchToRussian" from ru.json so the keys match en.json; update the
"dashboard" object to include "totalAreas" and delete "footer.switchToRussian"
to restore parity and avoid runtime fallback/inconsistency issues.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b5cd45f-63c1-486d-8d15-160e2d73d9ac

📥 Commits

Reviewing files that changed from the base of the PR and between 2b601aa and 4e2e527.

📒 Files selected for processing (3)
  • src/components/layout/Footer.svelte
  • src/lib/i18n/index.ts
  • src/lib/i18n/locales/ru.json

Comment on lines +1 to +1097
{
"home": {
"hero": "Открытый каталог мест принимающих оплату биткойнами.",
"openMap": "Открыть карту",
"addLocation": "Добавить место",
"description": "Мы используем {osmLink} для отметки мест, принимающих биткоин, и отображаем эти точки в наших удобных приложениях.",
"openSource": "Наши приложения и базовые данные полностью бесплатны и открыты для совместной поддержки и сторонних интеграций.",
"hashtag": "#SPEDN ✊",
"roadsAlt": "Карта дорог",
"openWebAppAria": "Открыть веб-приложение",
"downloadForAria": "Скачать для {type}",
"mobileExampleAlt": "Пример мобильного приложения"
},
"nav": {
"maps": "Карты",
"apps": "Приложения",
"stats": "Статистика",
"areas": "Зоны",
"maintain": "Волонтерам",
"wiki": "Вики",
"blog": "Блог",
"supportUs": "Поддержать нас",
"menu": "Меню",
"merchantMap": "Карта мест",
"communityMap": "Карта сообществ",
"dashboard": "Ключевые индикаторы",
"taggerLeaderboard": "Рейтинг редакторов",
"communityLeaderboard": "Рейтинг сообществ",
"countryLeaderboard": "Рейтинг стран",
"addLocation": "Добавить место",
"addCommunity": "Добавить сообщество",
"becomeTagger": "Стать редактором",
"openTickets": "Открытые заявки",
"taggingActivity": "Активность редакторов",
"taggingIssues": "Открытые задачи",
"communities": "Сообщества",
"countries": "Страны"
},
"search": {
"placeholderWorldwide": "Поиск по всему миру...",
"placeholderNearby": "Поиск поблизости...",
"searching": "Поиск...",
"noResults": "Результатов не найдено",
"noResultsFor": "Результатов не найдено по запросу \"{query}\"",
"prompt": "Поиск торговцев по названию",
"resultsCount": "{count} результат(ов)",
"showingNearest": "Показано ближайших: {count}",
"zoomIn": "Приблизьте карту для просмотра списка",
"zoomInDetail": "Приблизьте карту чтобы увидеть список точек",
"showAll": "Показать все",
"clear": "Очистить поиск",
"noVisible": "В текущем окне нет видимых точек",
"worldwide": "По всему миру",
"nearby": "Поблизости",
"switchToWorldwide": "Переключиться на поиск по всему миру",
"filterResults": "Фильтровать ближайшие результаты",
"placeholder": "Поиск...",
"ariaLabel": "Поиск в рейтинге",
"enablePreciseDistances": "Включить точные расстояния",
"dismissLocationPrompt": "Закрыть запрос местоположения",
"locationPermissionDenied": "Доступ к геолокации запрещён. Включите его в настройках браузера.",
"locationUnavailable": "Не удалось определить ваше местоположение. Попробуйте ещё раз.",
"locationEnabled": "Местоположение включено. Сортировка по расстоянию."
},
"categories": {
"all": "Все",
"restaurants": "Рестораны",
"shopping": "Магазины",
"groceries": "Продукты",
"coffee": "Кафе",
"atms": "Банкоматы",
"hotels": "Отели",
"beauty": "Салоны красоты",
"filter": "Фильтр по категории",
"noMatches": "Нет результатов в этой категории"
},
"mapControls": {
"fullScreen": "Полный экран",
"goToHome": "На главную страницу",
"addLocation": "Добавить место",
"communityMap": "Карта сообщества",
"merchantMap": "Карта торговцев",
"dataRefreshAvailable": "Доступно обновление данных",
"support": "Поддержать",
"supportWithSats": "Поддержать сатоши",
"zoomIn": "Приблизить",
"zoomOut": "Отдалить",
"locate": "Показать моё местоположение",
"boostAlt": "Буст",
"fullScreenAlt": "Полный экран",
"locateAlt": "Показать моё местоположение",
"goToHomeAlt": "На главную страницу",
"addLocationAlt": "Добавить место",
"communityMapAlt": "Карта сообщества",
"merchantMapAlt": "Карта торговцев",
"dataRefreshAlt": "Доступно обновление данных"
},
"merchant": {
"navigate": "Проложить маршрут",
"edit": "Редактировать",
"share": "Поделиться",
"call": "Позвонить",
"email": "Email",
"website": "Веб-сайт",
"pay": "Послать деньги",
"showTags": "Показать теги",
"tagIssues": "Проблемы с тегами",
"viewOSM": "Открыть на OSM",
"socialX": "X",
"socialInstagram": "Instagram",
"socialFacebook": "Facebook",
"viewDetails": "Посмотреть полностью",
"comments": "Комментарии",
"commentsCount": "Комментарии ({count})",
"unknown": "Неизвестно",
"distanceAway": "{distance} от вас",
"deletedBanner": "Это место было удалено.",
"deletedNotice": "Это место было удалено с BTC Map и скорее всего больше не принимает биткоины.",
"deletedDetail": "Данные ниже устарели и приведены только для справки.",
"merchantName": "Название торговца",
"address": "Адрес",
"openingHours": "Часы работы",
"location": "Местоположение {name}",
"activity": "Активность {name}",
"communities": "Сообщества {name}"
},
"verification": {
"lastSurveyed": "Последняя проверка",
"verified": "Подтверждено",
"outdated": "Устарело",
"notSurveyed": "Это место нужно проверить!",
"verifyLocation": "Подтвердить местоположение",
"verifiedTooltip": "Подтверждено в течение последнего года",
"outdatedTooltip": "Устарело, пожалуйста, проверьте снова",
"helpImprove": "Помогите улучшить данные для всех",
"surveyedBy": "Проверено участниками сообщества BTC Map"
},
"payment": {
"methods": "Способы оплаты",
"accepted": "Принимаемые платежи",
"onchain": "Ончейн",
"onchainAccepted": "Ончейн принимается",
"onchainNotAccepted": "Ончейн не принимается",
"onchainUnknown": "Ончейн неизвестно",
"lightning": "Lightning",
"lightningAccepted": "Lightning принимается",
"lightningNotAccepted": "Lightning не принимается",
"lightningUnknown": "Lightning неизвестно",
"lightningContactless": "Lightning бесконтактный",
"contactlessAccepted": "Бесконтактный Lightning принимается",
"contactlessNotAccepted": "Бесконтактный Lightning не принимается",
"contactlessUnknown": "Бесконтактный Lightning неизвестно",
"thirdPartyRequired": "Требуется стороннее приложение"
},
"boost": {
"title": "Буст",
"boosted": "Пробустовано",
"boostAction": "Бустнуть",
"extend": "Продлить",
"boosting": "Бустим...",
"expires": "Буст истекает",
"isBoosted": "Буст активен!",
"improveVisibility": "Бустните это место, чтобы сделать его более заметным на карте.",
"locations": "Места с активным бустом",
"boostLocation": "Бустнуть место",
"description": "Сделайте это место заметным на карте (оранжевым), выделите в результатах поиска и добавьте на карту бустов!",
"seeHowItLooks": "Посмотреть как это выглядит",
"starAlt": "Звезда",
"boostedPinAlt": "Бустнутая точка",
"boostedMerchant": "Бустнутое место",
"feeNote": "Комиссия используется для поддержки проекта BTC Map и продолжения его разработки.",
"boostFor1Month": "Бустнуть на 1 месяц",
"boostForNMonths": "Бустнуть на {time} месяцев",
"duration1Month": "1 месяц",
"durationNMonths": "{time} месяцев",
"thankYou": "Спасибо за поддержку {name} и BTC Map!",
"thisLocation": "это место",
"boostedUntil": "Это место будет продвигаемо до",
"shareOnTwitter": "Поделиться в Twitter",
"shareEncourage": "Поделиться поддержкой может вдохновить других сделать то же 🥰",
"invoiceDescription1": "Бустнуть это место на <strong>1 месяц <br /> {sats} сатоши</strong>",
"invoiceDescriptionN": "Бустнуть это место на <strong>{time} месяцев <br /> {sats} сатоши</strong>",
"finalizeError": "Не удалось завершить буст, свяжитесь с BTC Map.",
"invalidDuration": "Неверная длительность буста",
"invalidMerchantId": "Неверный идентификатор торговца",
"twitterShareText": "Я только что забустил {name} на @btcmap"
},
"invoicePayment": {
"scanOrClick": "Сканируйте или нажмите для оплаты через Lightning",
"invoiceLabel": "Счёт",
"protocolAlt": "Протокол Lightning"
},
"commentAdd": {
"title": "Добавить комментарий",
"pleaseEnterComment": "Пожалуйста, введите комментарий",
"anonymousNote": "Все комментарии анонимны. Мы собираем небольшую комиссию в сатоши как меру защиты от спама.",
"currentFee": "Текущая комиссия: 500 сатоши",
"yourComment": "Ваш комментарий",
"submitButton": "Комментарий",
"publishNote": "Ваш комментарий будет опубликован после подтверждения оплаты.",
"close": "Закрыть",
"thankYou": "Спасибо за ваш комментарий!",
"published": "Ваш комментарий опубликован!"
},
"tip": {
"label": "Чаевые",
"labelWithUser": "Чаевые для {user}"
},
"status": {
"loading": "Загрузка...",
"loadingMap": "Загрузка карты...",
"loadingPlaces": "Загрузка мест...",
"initializing": "Инициализация...",
"initializingMarkers": "Инициализация меток...",
"loadingPlacesInView": "Загрузка мест в поле зрения...",
"downloading": "Загрузка данных мест...",
"processing": "Обработка данных мест...",
"complete": "Готово!",
"preparing": "Подготовка карты...",
"finalizing": "Завершение...",
"merging": "Объединение обновлений...",
"checkingUpdates": "Проверка обновлений...",
"loadingTiles": "Загрузка тайлов..."
},
"mapDrawer": {
"back": "Назад",
"closeMerchantDetails": "Закрыть детали места",
"expandDrawer": "Развернуть панель",
"collapseDrawer": "Свернуть панель",
"merchantDetails": "Детали места",
"viewBoost": "Буст",
"viewDetails": "Детали",
"swipeUpForDetails": "Смахните вверх для деталей",
"swipeDownToClose": "Смахните вниз для закрытия"
},
"map": {
"bitcoinMerchantMapTitle": "Биткоин карта"
},
"info": {
"contact": "Контакты",
"hours": "Часы работы",
"noActivity": "Нет активности для отображения.",
"loadMore": "Загрузить ещё",
"viewOnMainMap": "Посмотреть на основной карте",
"noCommunity": "Это место не является частью известных нам сообществ, но вы можете {createLink} свое или сообщить нам об уже существующих.",
"created": "создать",
"loadingCommunities": "Загрузка сообществ..."
},
"comments": {
"title": "Комментарии",
"add": "Добавить комментарий",
"none": "Пока нет комментариев.",
"beFirst": "Пока нет комментариев. Будьте первым!",
"view": "Посмотреть комментарии",
"shareThoughts": "Поделитесь своими мыслями об этом месте."
},
"errorPage": {
"title": "BTC Map - Ошибка",
"home": "Главная",
"tryAgain": "Пожалуйста, попробуйте снова или свяжитесь с нами.",
"logoAlt": "Логотип"
},
"errors": {
"searchUnavailable": "Поиск временно недоступен",
"loadFailed": "Не удалось загрузить ближайшие места",
"notFound": "Место не найдено",
"loadError": "Не удалось загрузить места со статического CDN.",
"updateError": "Не удалось обновить места из API, используются кэшированные данные.",
"captchaFetch": "Не удалось получить капчу, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"noLocationSelected": "Пожалуйста, выберите местоположение...",
"noPaymentMethod": "Пожалуйста, выберите хотя бы один способ оплаты...",
"formSubmission": "Ошибка отправки формы, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"locationSearch": "Не удалось выполнить поиск местоположений, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"mapView": "Не удалось установить вид карты на указанные координаты, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"mapViewCachedCoords": "Не удалось установить вид карты на кэшированные координаты, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"merchantDetailsLoadError": "Ошибка загрузки деталей торговца. Пожалуйста, попробуйте снова.",
"boostLoadError": "Не удалось загрузить информацию о бусте. Пожалуйста, попробуйте снова.",
"fullscreenError": "Ошибка при попытке включить полноэкранный режим: {message} ({name})"
},
"success": {
"locationSelected": "Местоположение выбрано!",
"linkCopied": "Ссылка скопирована в буфер обмена!"
},
"warning": {
"noLocations": "Местоположения не найдены, пожалуйста, измените запрос."
},
"aria": {
"logoAlt": "Логотип BTC Map",
"avatarAlt": "Аватар",
"close": "Закрыть",
"closeMerchantList": "Закрыть список торговцев",
"openMenu": "Открыть меню",
"clearSearch": "Очистить поиск",
"focusSearch": "Фокус на поиске",
"previousPage": "Предыдущая страница",
"nextPage": "Следующая страница",
"loading": "Загрузка",
"submitting": "Отправка",
"filterByCategory": "Фильтр по категории",
"switchMode": "Переключить режим поиска",
"togglePanel": "Переключить панель списка торговцев",
"merchantList": "Список торговцев",
"merchantListItem": "Элемент списка торговцев",
"selectCategory": "Выберите категорию",
"searchInput": "Поиск биткоин мест"
},
"footer": {
"switchToEnglish": "Переключиться на английский",
"switchToPortuguese": "Переключиться на португальский",
"switchToBulgarian": "Переключиться на болгарский",
"switchToRussian": "Переключиться на русский",
"aboutUs": "О нас",
"media": "Медиа",
"license": "Лицензия",
"privacy": "Конфиденциальность",
"bitcoinForBusiness": "Биткоин для бизнеса",
"status": "Статус",
"analytics": "Аналитика",
"whitePaper": "White Paper",
"cypherpunks": "Киберпанки"
},
"meta": {
"countries": "Страны",
"countriesLeaderboard": "Рейтинг стран",
"addLocation": "Добавить место",
"addCommunity": "Добавить сообщество",
"communityMap": "Карта сообщества",
"communities": "Сообщества",
"communitiesLeaderboard": "Рейтинг сообществ",
"merchant": "Место",
"country": "Страна",
"community": "Сообщество",
"supertagger": "Редактор"
},
"communityMap": {
"viewCommunity": "Посмотреть сообщество",
"pageTitle": "Карта сообщества",
"organization": "Организация",
"sponsor": "Спонсор BTC Map",
"supporter": "Сторонник",
"avatarAlt": "Иконка сообщества",
"communityIconTitle": "Иконка сообщества",
"communityNameTitle": "Название сообщества",
"communityPageTitle": "Страница сообщества"
},
"taggerOnboarding": {
"nameLabel": "Имя",
"emailLabel": "Email",
"namePlaceholder": "Ваше имя",
"emailPlaceholder": "ваш@email.com",
"loadingForm": "Загрузка формы...",
"refreshCaptcha": "Обновить капчу",
"submittingApplication": "Отправка заявки...",
"submitButton": "Отправить заявку",
"captchaPlaceholder": "Пожалуйста, введите текст с капчи.",
"honeyPlaceholder": "Горшочек мёда.",
"successType": "Заявка",
"successMessage": "Спасибо за интерес к становлению редактором! Мы рассмотрим вашу заявку, и наша команда свяжется с вами по указанному email. Напишите на hello@btcmap.org, если есть любые вопросы."
},
"profileActivity": {
"location": "Местоположение",
"action": "Действие",
"date": "Дата",
"noResults": "Результатов не найдено.",
"activityTitle": "Активность редактора {name}"
},
"taggerProfile": {
"osmProfile": "Профиль OSM",
"totalTags": "Всего правок",
"created": "Создано",
"updated": "Обновлено",
"deleted": "Удалено",
"chartCreated": "Создано",
"chartUpdated": "Обновлено",
"chartDeleted": "Удалено",
"chartLabel": "Типы правок",
"mappingSince": "Активен с",
"defaultName": "Редактор BTC Map"
},
"forms": {
"optional": "(необязательно)",
"submit": "Отправить",
"loading": "Загрузка...",
"success": "Успешно!",
"merchantName": "Название места",
"category": "Категория",
"website": "Веб-сайт",
"phone": "Телефон",
"openingHours": "Часы работы",
"notes": "Заметки",
"contact": "Публичный контакт",
"captcha": "Защита от ботов",
"captchaCaseSensitive": "(с учётом регистра)",
"submitLocation": "Отправить место",
"submitReport": "Отправить отчёт",
"selectLocation": "Выбрать местоположение",
"locationSelected": "Местоположение выбрано!",
"searchButton": "Поиск 🔍",
"address": "Адрес",
"honeyPlaceholder": "Горшочек мёда.",
"captchaPlaceholder": "Пожалуйста, введите текст с капчи."
},
"addLocation": {
"hero": "Принимаете биткоин? Добро пожаловать на карту!",
"businessOwner": "Если вы владелец бизнеса, пожалуйста, прочитайте наши",
"bestPractices": "советы для бизнеса",
"guide": ".",
"heading": "Добавим за вас",
"description": "Заполните следующую форму, и один из добровольцев-участников сообщества добавит ваше место на карту.",
"tooltip": "Все добавления выполняются на добровольной основе, поэтому мы не можем гарантировать, когда ваше место будет добавлено.",
"merchantNamePlaceholder": "Рога и Копыта",
"noLocationError": "Пожалуйста, выберите местоположение...",
"latitude": "Широта",
"longitude": "Долгота",
"addressLabel": "Адрес (необязательно)",
"addressTooltip": "Все места должны иметь физическое местоположение. При желании введите адрес. Сервисы без фиксированного местоположения не могут быть отображены на карте.",
"addressPlaceholder": "2100 Freedom Drive...",
"categoryPlaceholder": "Ресторан и т.д.",
"paymentMethodsLegend": "Выберите принимаемые способы оплаты",
"paymentMethodError": "Пожалуйста, исправьте...",
"onchainLabel": "Ончейн",
"lightningLabel": "Lightning",
"nfcLabel": "Lightning (бесконтактный)",
"websitePlaceholder": "https://bitcoin.org",
"phonePlaceholder": "Номер",
"hoursPlaceholder": "Пн-Пт 08:30-20:00",
"notesPlaceholder": "Пожалуйста, добавьте дополнительные детали здесь, такие как контакты, соцсети и т.д.",
"dataSourceLabel": "Источник данных",
"dataSourcePlaceholder": "Пожалуйста, выберите опцию",
"dataSourceOwner": "Я владелец бизнеса",
"dataSourceCustomer": "Я посетил как клиент",
"dataSourceOther": "Другой способ",
"dataSourceOtherPrompt": "Как вы проверили эту информацию? Пожалуйста, предоставьте как можно больше деталей.",
"dataSourceOtherPlaceholder": "Местные знания, онлайн и т.д.",
"contactDescription": "Если у нас есть вопросы, мы свяжемся с вами, чтобы успешно добавить это место. Чтобы ускорить процесс, проверьте папку со спамом на случай, если письмо попадёт туда.",
"contactPlaceholder": "hello@btcmap.org",
"captchaPlaceholder": "Пожалуйста, введите текст с капчи.",
"supertaggerHeading": "Самостоятельно",
"supertaggerDescription": "Вносите изменения напрямую в OSM - как 😎 профи. Кому нужны формы.",
"supertaggerImageAlt": "редактор",
"supertaggerWikiButton": "См. инструкции в Вики",
"formSuccessType": "Место",
"formSuccessText": "Мы проверим вашу информацию и добавим её как можно скорее."
},
"formSuccess": {
"submittedTitle": "{type} отправлено!",
"monitorProgress": "Вы также можете отслеживать прогресс вашей заявки здесь:",
"issueLink": "Заявка #{issue}",
"submitAnother": "Отправить ещё {type}"
},
"verifyLocation": {
"hero": "Помогите улучшить данные для всех.",
"heading": "Верификация",
"subheading": "(Убедитесь, что информация всё ещё актуальна, и обновите её в противном случае.)",
"descriptionPart1": "Пожалуйста, заполните следующую форму, и один из добровольцев-участников сообщества обновит это место на карте. Знаете ли вы, что вы можете обновить эти данные самостоятельно на",
"osmLinkText": "OpenStreetMap",
"descriptionPart2": "? Вы можете посмотреть нашу",
"wikiLinkText": "Вики",
"descriptionPart3": "для получения дополнительных инструкций.",
"tooltip": "ПРИМЕЧАНИЕ: Из-за очереди запросов и выполнения обновлений на добровольной основе, обновление этого места может занять несколько недель. Рекомендуется обновить место напрямую в OpenStreetMap, если вы хотите увидеть изменения на карте сразу.",
"loadingPlaceholder": "Загрузка места...",
"merchantNamePlaceholder": "Название места",
"currentInfoLabel": "Текущая информация верна",
"currentInfoDescription": "Установите этот флажок, если вы проверили, что существующие данные актуальны.",
"outdatedLabel": "Устаревшая информация",
"ifApplicable": "(Если применимо)",
"outdatedPlaceholder": "Укажите, какая информация неверна, и обновлённую информацию об этом месте",
"verifyLabel": "Как вы это проверили?",
"verifyPlaceholder": "Пожалуйста, предоставьте дополнительную информацию здесь",
"successType": "Отчёт",
"successMessage": "Спасибо, что нашли время заполнить этот отчёт. Мы проверим вашу информацию и обновим её как можно скорее."
},
"dashboard": {
"hero": "Панель управления",
"totalMerchants": "Всего торговых точек",
"recentlyVerified": "Недавно подтверждено",
"totalExchanges": "Всего обменников",
"period7d": "7Д",
"period1m": "1М",
"period3m": "3М",
"period6m": "6М",
"periodYtd": "ГОД",
"period1y": "1Г",
"periodAll": "ВСЁ",
"verifiedLabel": "Недавно подтверждённые торговые точки",
"totalLabel": "Всего торговцев",
"merchantsNote": "*Торговые точки, принимающие любой способ оплаты биткоин.",
"verifiedNote": "*Торговые точки с тегом survey:date, check_date или check_date:currency:XBT младше одного года.",
"tagsNotePart1": "*Более подробная информация о тегах доступна",
"tagsNoteLink": "здесь",
"tagsNotePart2": "."
},
"leaderboard": {
"taggerHero": "Рейтинг теггеров",
"joinButton": "Присоединиться",
"loadingData": "Загрузка данных рейтинга",
"loadingPeriod": "Загрузка данных за {period}...",
"failedToLoad": "Не удалось загрузить рейтинг:",
"noData": "Нет данных",
"periodLabel": "Период",
"periodAria": "Выберите период рейтинга",
"period3Months": "Последние 3 месяца",
"period6Months": "Последние 6 месяцев",
"period12Months": "Последние 12 месяцев",
"periodAllTime": "За всё время",
"noResults": "Результатов не найдено.",
"position": "Позиция",
"name": "Имя",
"total": "Всего",
"created": "Создано",
"updated": "Обновлено",
"deleted": "Удалено",
"tip": "Чаевые",
"grade": "Оценка",
"verified": "Проверено",
"sortPosition": "Сортировать по позиции",
"sortTotal": "Сортировать по общему числу правок",
"sortCreated": "Сортировать по созданным правкам",
"sortUpdated": "Сортировать по обновлённым правкам",
"ultimateSupertaggerAlt": "Лучший редактор",
"tableAria": "Таблица рейтинга редакторов",
"sortByCurrentlyAscending": "Сортировать по {column}, сейчас по возрастанию",
"sortByCurrentlyDescending": "Сортировать по {column}, сейчас по убыванию",
"sortByCurrentlyUnsorted": "Сортировать по {column}, сейчас без сортировки",
"itemsPerPage": "Элементов на странице",
"show": "Показать {pageSize}",
"firstPage": "Перейти на первую страницу",
"previousPage": "Перейти на предыдущую страницу",
"nextPage": "Перейти на следующую страницу",
"lastPage": "Перейти на последнюю страницу",
"page": "Страница",
"of": "из"
},
"communities": {
"hero": "Присоединяйтесь к сообществу BTC Map.",
"description": "Возьмите на себя поддержку локальных данных и помогите стимулировать распространение биткойна. Присоединяйтесь, добавляйте бизнес, обьединяйтесь.",
"leaderboardHero": "Лучшие сообщества",
"leaderboardDescription": "Сообщества поддерживают свои локальные наборы данных. Они также помогают добавлять новые места.",
"directory": "Справочник",
"addCommunity": "Добавить сообщество",
"viewMap": "Посмотреть карту сообщества",
"leaderboard": "Рейтинг",
"byContinent": "Сообщества по континентам",
"totalLocations": "Всего местоположений",
"verifiedLocations": "Подтверждённые местоположения"
},
"addCommunityForm": {
"hero": "Воздействуйте локально!",
"heading": "Добавить сообщество",
"description": "Пожалуйста, заполните эту форму, чтобы отправить заявку на создание сообщества. Это отличный способ увеличить распространение биткоина в вашем районе, повеселиться и, возможно, завести новых друзей.",
"tooltip": "ПРИМЕЧАНИЕ: BTC Map - бесплатный проект с открытым исходным кодом, управляемый волонтёрами. Каждая заявка на сообщество проверяется вручную для обеспечения качества. Добавление сообщества может занять несколько недель.",
"criteriaHeading": "Критерии",
"criteria1": "только биткоин",
"criteria2": "должна быть географическая область, а не одна точка",
"criteria3": "будьте готовы взять на себя управление локальными данными",
"criteria4": "старайтесь добавлять новые места в вашем районе",
"locationLabel": "Выберите местоположение",
"locationHint": "Поиск области и выбор варианта из результатов.",
"locationSelected": "Местоположение выбрано!",
"locationError": "Пожалуйста, выберите местоположение...",
"locationPlaceholder": "Эль-Сонте, Сальвадор",
"nameLabel": "Название сообщества",
"namePlaceholder": "Биткоин Остров Филиппины",
"iconLabel": "URL иконки",
"iconOptional": "(необязательно)",
"iconHint": "Мы используем аватар из вашей социальной ссылки или флаг страны, где находится ваше сообщество, если иконка не предоставлена.",
"iconPlaceholder": "https://static.btcmap.org/images/communities/iom.svg",
"lightningLabel": "Lightning чаевые",
"lightningHint": "Если вы хотите иметь возможность получать сатоши, вы можете добавить",
"lightningAddress": "Lightning адрес",
"lightningOr": "или",
"lightningLnurl": "LNURL-pay",
"lightningSuffix": "строку.",
"lightningPlaceholder": "btcmap@zbd.gg",
"socialsLabel": "Социальные сети",
"socialsHint": "Вы должны предоставить хотя бы один способ связи для присоединения к вашему сообществу.",
"socialsPlaceholder": "Веб-сайт, Nostr, Telegram, Meetup и т.д.",
"contactLabel": "Публичный контакт",
"contactHint": "Способ связи с лидером сообщества, если у нас есть вопросы.",
"contactPlaceholder": "например, hello@btcmap.org",
"notesLabel": "Заметки",
"notesHint": "Является ли это сообщество частью организации? Хотите ли вы ассоциировать себя с конкретным языком? И т.д.",
"notesPlaceholder": "Немецкоязычные - часть Einundzwanzig.",
"captchaLabel": "Защита от ботов",
"captchaCaseSensitive": "(с учётом регистра)",
"captchaPlaceholder": "Пожалуйста, введите текст с капчи.",
"honeyPlaceholder": "Горшочек мёда.",
"submitButton": "Отправить сообщество",
"successType": "Сообщество",
"successMessage": "Спасибо за инициативу создать биткоин сообщество. Мы проверим вашу информацию и свяжемся, если потребуются дополнительные детали.",
"captchaFetchError": "Не удалось получить капчу, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"formSubmitError": "Ошибка отправки формы, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"searchError": "Не удалось выполнить поиск местоположений, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"noLocationsWarning": "Местоположения не найдены, пожалуйста, измените запрос.",
"locationSelectedToast": "Местоположение выбрано!",
"breadcrumbCommunities": "Сообщества",
"breadcrumbAdd": "Добавить"
},
"maintain": {
"merchantName": "Название места",
"description": "Описание",
"view": "Посмотреть",
"edit": "Редактировать",
"help": "Помощь",
"noTaggingIssues": "Нет проблем с тегами!",
"noTaggingIssuesModal": "Нет проблем с тегами!",
"add": "Добавить",
"verify": "Подтвердить",
"community": "Сообщество",
"noAddTickets": "Нет открытых заявок на добавление.",
"noVerifyTickets": "Нет открытых заявок на подтверждение.",
"noCommunityTickets": "Нет открытых заявок сообщества.",
"ticketsTooltip": "Заявки доступны всем от наших простых форм! Любой может помочь добавить или подтвердить заявки в OpenStreetMap.",
"ticketsSubheading": "Заявки доступны всем от наших простых форм! Любой может помочь добавить или подтвердить заявки о местах и проверять сообщества.",
"taggingInstructionsIntro": "Более подробную информацию о том, как принять участие, можно найти в наших",
"taggingInstructionsLink": "Инструкциях по теггингу торговцев",
"underMaintenance": "Заявки в настоящее время находятся на обслуживании.",
"viewOnGitea": "Посмотреть заявки непосредственно на Gitea.",
"viewAllOnGitea": "Посмотреть все открытые заявки на",
"giteaLinkText": "Gitea",
"opened": "открыто",
"by": "от",
"avatarAlt": "аватар",
"dataUpdatedNote": "*Данные обновляются каждые 10 минут.",
"errorFetching": "Ошибка получения заявок. Пожалуйста, попробуйте снова или свяжитесь с поддержкой BTC Map.",
"couldNotLoadTickets": "Не удалось загрузить открытые заявки, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"issueMissingIcon": "Иконка отсутствует",
"issueNotVerified": "Дата последней проверки отсутствует",
"issueOutdated": "Устарело, требуется повторная проверка",
"issueOutdatedSoon": "Скоро устареет, требуется повторная проверка",
"issueInvalidTagValue": "Значение тега неправильно отформатировано ({code})",
"issueMisspelledTagName": "Ошибка в названии тега ({code})"
},
"areaStats": {
"population": "Население",
"asOf": "на",
"area": "Площадь",
"totalLocations": "Всего местоположений",
"recentlyVerified": "Недавно подтверждённые местоположения",
"recentlyVerifiedTooltip": "Местоположения, подтверждённые в течение года.",
"recentlyVerifiedLabel": "Недавно подтверждено",
"outdated": "Устарело",
"locations": "Местоположения",
"recentlyVerifiedPercent": "Процент недавнего подтверждения",
"totalLocationsLabel": "Всего местоположений",
"chartsTitle": "Графики",
"defaultAreaName": "Район BTC Map",
"locationsNote": "*Местоположения, принимающие любой способ оплаты биткоинами.",
"verifiedNote": "*Местоположения с тегом survey:date, check_date или check_date:currency:XBT менее одного года назад.",
"tagsInfo": "*Более подробная информация о тегах доступна",
"here": "здесь",
"chartDataNote": "*Данные графиков обновляются каждые 24 часа."
},
"activityPage": {
"heading": "Активность",
"hero": "Наши редакторы не спят. Они бодрствуют всю ночь, добавляя теги. Мир, который мы хотим, - на расстоянии одного тега.",
"cta": "Вы тоже можете стать легендой теггинга! Чего вы ждёте?",
"getTaggin": "Начните тегать!",
"latestSupertaggers": "Последние редакторы"
},
"areaHighlights": {
"boostedMerchants": "Продвигаемые места",
"noBoosted": "Нет продвигаемых мест в этом районе.",
"latestAdded": "Последние добавленные",
"noLatest": "Нет последних добавлений в этом районе. Вы можете",
"addNewMerchant": "добавить новое место",
"now": "сейчас!"
},
"areaActivity": {
"supertaggers": "Редакторы",
"loadMore": "Загрузить ещё",
"noSupertaggers": "Нет редакторов для отображения.",
"activity": "Активность",
"noActivity": "Нет активности для отображения.",
"atomFeeds": "Atom ленты",
"newPlaces": "Новые места",
"newComments": "Новые комментарии"
},
"area": {
"sections": {
"merchants": "Места",
"stats": "Статистика",
"activity": "Активность",
"maintain": "Поддержка"
},
"defaultName": "Район BTC Map",
"viewOnCommunityMap": "Посмотреть на карте сообщества",
"verifiedOverYearAgo": "Проверено более года назад",
"verified": "Проверено",
"notRecentlyVerified": "Давно не проверялось",
"verifyCommunity": "Подтвердить сообщество",
"errorLoadingData": "Ошибка загрузки данных. Пожалуйста, попробуйте позже.",
"loadingData": "Загрузка данных...",
"dataWithin24Hours": "Данные появятся в течение 24 часов.",
"taggingIssues": "Проблемы редактирования {name}",
"openTickets": "Открытые заявки {name}"
},
"areaTickets": {
"typeAdd": "Добавить",
"typeVerify": "Подтвердить",
"typeCommunity": "Сообщество",
"tooltip": "Заявки доступны всем от наших простых форм! Любой может помочь добавить или подтвердить заявки в OpenStreetMap.",
"noAddTickets": "Нет открытых заявок на добавление.",
"noVerifyTickets": "Нет открытых заявок на подтверждение.",
"noCommunityTickets": "Нет открытых заявок сообщества.",
"maintenanceMessage": "Заявки в настоящее время находятся на обслуживании. ",
"viewOnGitea": "Посмотреть заявки на Gitea",
"errorMessage": "Ошибка получения заявок. Пожалуйста, попробуйте снова или свяжитесь с поддержкой BTC Map.",
"loadError": "Не удалось загрузить открытые заявки, пожалуйста, попробуйте снова или свяжитесь с BTC Map."
},
"verifyCommunity": {
"title": "Подтвердить информацию о сообществе",
"description": "Помогите нам поддерживать точность данных сообщества, подтвердив информацию ниже.",
"communityName": "Название сообщества",
"accurateLabel": "Текущая информация верна",
"accurateHint": "Установите этот флажок, если вы проверили, что существующие данные актуальны.",
"updatesLabel": "Требуются обновления",
"ifApplicable": "(Если применимо)",
"updatesPlaceholder": "Опишите, какую информацию нужно обновить (контактные ссылки, описание и т.д.)",
"verifyLabel": "Как вы это проверили?",
"verifyPlaceholder": "Я посетил их веб-сайт, был на митапе, связался напрямую и т.д.",
"botProtection": "Защита от ботов",
"caseSensitive": "(с учётом регистра)",
"captchaPlaceholder": "Пожалуйста, введите текст с капчи.",
"honeyPlaceholder": "Горшочек мёда.",
"submitReport": "Отправить отчёт",
"successType": "Отчёт",
"successMessage": "Спасибо за подтверждение информации о сообществе. Мы рассмотрим ваш отчёт и обновим его как можно скорее."
},
"areaLeaderboard": {
"communityLeaderboard": "Рейтинг сообществ",
"countryLeaderboard": "Рейтинг стран",
"noData": "Нет данных",
"noResults": "Результатов не найдено.",
"position": "Позиция",
"name": "Имя",
"sortByPosition": "Сортировать по позиции",
"total": "Всего",
"totalLocations": "Всего местоположений",
"sortByTotal": "Сортировать по общему числу местоположений",
"verified": "Подтверждено",
"verifiedLocations": "Подтверждённые местоположения",
"sortByVerified": "Сортировать по подтверждённым местоположениям",
"grade": "Оценка",
"sortByGrade": "Сортировать по оценке",
"positionCalc": "Позиция рассчитывается следующим образом:",
"primaryCalc": "Основной: Всего местоположений минус 5-кратное количество устаревших точек.",
"secondaryCalc": "Вторичный: Общее количество точек.",
"locationsNote": "Местоположения включают банкоматы.",
"totalTooltip": "Все местоположения включая банкоматы",
"verifiedTooltip": "Местоположения, подтверждённые за последний год",
"tableAria": "Таблица рейтинга",
"totalTooltipInfo": "Информация о всех местоположениях",
"verifiedTooltipInfo": "Информация о подтверждённых местоположениях",
"gradeTooltipInfo": "Информация о метрике оценки",
"viewDetails": "Посмотреть детали {name}",
"loadingAreaInfo": "Загрузка информации о районе"
},
"issuesTable": {
"searchPlaceholder": "Поиск...",
"merchantName": "Название места",
"description": "Описание",
"view": "Посмотреть",
"edit": "Редактировать",
"help": "Помощь",
"noTaggingIssues": "Нет проблем с тегами!",
"noResults": "Результатов не найдено.",
"page": "Страница",
"of": "из",
"showCount": "Показать {count}",
"issueTypeMissingIcon": "Иконка отсутствует",
"issueTypeNotVerified": "Дата последней проверки отсутствует",
"issueTypeOutdated": "Устарело, требуется повторная проверка",
"issueTypeOutdatedSoon": "Скоро устареет, требуется повторная проверка",
"issueTypeInvalidTag": "Значение тега неправильно отформатировано ({code})",
"issueTypeMisspelledTag": "Ошибка в названии тега ({code})"
},
"taggingIssues": {
"heading": "Проблемы теггинга",
"subheading": "Внесите вклад в ГЛАВНУЮ карту, решая проблемы теггинга!",
"descriptionPart1": "Более подробную информацию о том, как принять участие, можно найти на странице ",
"linkText": "Инструкции по теггингу",
"descriptionPart2": " в Вики.",
"tableTitle": "Глобальные проблемы"
},
"countries": {
"hero": "Распространение биткоина по странам.",
"description": "Ваша страна? Ваша карта!",
"viewLeaderboard": "Посмотреть рейтинг",
"viewDirectory": "Посмотреть справочник",
"leaderboardHero": "Лучшие страны",
"leaderboardDescription": "Аналитика распространения биткоина по всему миру!",
"leaderboard": "Рейтинг",
"africa": "Африка",
"asia": "Азия",
"europe": "Европа",
"northAmerica": "Северная Америка",
"oceania": "Океания",
"southAmerica": "Южная Америка"
},
"gradeDisplay": {
"ariaLabel": "{grade} из 5 звёзд",
"ariaLabelWithPercentage": "{grade} из 5 звёзд, {percentage}% актуально"
},
"badges": {
"title": "Значки",
"intro": "Вы можете заработать значки за свой вклад в BTC Map, которые будут отображаться на вашем профиле. Есть идея для значка? Дайте нам знать!",
"achievements": "Достижения",
"contributions": "Вклады",
"achievement": {
"geyserTournament": {
"title": "Турнир Geyser",
"desc": "Участие в событии супертеггеров 2023"
},
"topTagger": {
"title": "Лучший теггер",
"desc": "#1 в рейтинге"
},
"podium": {
"title": "Подиум",
"desc": "В топ-3 рейтинга"
},
"highRank": {
"title": "Высокий ранг",
"desc": "В топ-10 рейтинга"
},
"ogSupertagger": {
"title": "OG Супертеггер",
"desc": "Внёс вклад в BTC Map в первые 3 месяца"
},
"lightningJunkie": {
"title": "Lightning Junkie",
"desc": "Добавил кнопку чаевых на свой профиль"
},
"helloWorld": {
"title": "Hello World",
"desc": "Добавил аватар на свой профиль"
},
"demolitionSpecialist": {
"title": "Специалист по сносу",
"desc": "Большинство ваших вкладов - удаления"
},
"updateMaxi": {
"title": "Update Maxi",
"desc": "Большинство ваших вкладов - обновления"
},
"creator": {
"title": "Создатель",
"desc": "Большинство ваших вкладов - создания"
},
"supporter": {
"title": "Сторонник",
"desc": "Сделал ежегодное пожертвование в BTC Map"
}
},
"contribution": {
"hyperbitcoinisation": {
"title": "Гипербиткоинизация",
"desc": "21M"
},
"pizzaTime": {
"title": "Время пиццы",
"desc": "10K"
},
"godly": {
"title": "Божественный",
"desc": "7777"
},
"shadow": {
"title": "Тень",
"desc": "5000"
},
"whitepaper": {
"title": "Whitepaper",
"desc": "3110"
},
"winston": {
"title": "Уинстон",
"desc": "1984"
},
"whale": {
"title": "Кит",
"desc": "1000"
},
"infinity": {
"title": "Бесконечность",
"desc": "821"
},
"legend": {
"title": "Легенда",
"desc": "500"
},
"chancellor": {
"title": "Канцлер",
"desc": "301"
},
"sha": {
"title": "SHA",
"desc": "256"
},
"noBailouts": {
"title": "Без Bailouts",
"desc": "210"
},
"supertagger": {
"title": "Супертеггер",
"desc": "100"
},
"ath": {
"title": "ATH",
"desc": "69"
},
"longestChain": {
"title": "Самая длинная цепь",
"desc": "51"
},
"satoshi": {
"title": "Сатоши",
"desc": "21"
},
"heartbeat": {
"title": "Пульс",
"desc": "10"
},
"segwit": {
"title": "Segwit",
"desc": "4"
},
"wholeTagger": {
"title": "Целый теггер",
"desc": "1"
}
}
},
"apps": {
"hero": "Находите места на любой платформе.",
"subheading": "Мы представлены на любом устройстве и ОС.",
"googlePlayNote": "Примечание: Нет варианта в Google Play из-за их чрезмерных требований KYC для разработчиков.",
"official": "Официальные",
"community": "Сообщество"
},
"media": {
"title": "Медиа",
"intro": "Медиа-материалы доступны бесплатно для рекламных целей.",
"brandColors": "Цвета бренда",
"assets": "Активы",
"downloadAll": "Скачать всё",
"brand": "Бренд",
"promotional": "Рекламные",
"team": "Команда",
"assetNames": {
"appScreenshot": "Скриншот приложения",
"btcmapLogo": "Логотип BTC Map",
"shadowySupertagger": "Теневой супертеггер",
"shadowySupertaggerLeader": "Теневой супертеггер - Лидер",
"activityFeed": "Лента активности",
"addCommunity": "Добавить сообщество",
"addLocation": "Добавить место",
"communities": "Сообщества",
"countries": "Страны",
"downloadApps": "Скачать приложения",
"earnBadges": "Заработать значки",
"main": "Главная",
"map": "Карта",
"merchant": "Торговец",
"statsDashboard": "Панель статистики",
"supertaggerLeaderboard": "Рейтинг супертеггеров",
"supertaggerProfile": "Профиль супертеггера",
"supportUs": "Поддержите нас",
"topCommunities": "Лучшие сообщества",
"topCountries": "Лучшие страны",
"verifyLocations": "Подтвердить местоположения",
"igor": "Игорь",
"karnage": "Карнаж",
"nathanDay": "Нейтан Дей",
"secondl1ght": "secondl1ght"
}
},
"supportUs": {
"title": "Поддержите нас",
"hero": "Помогите разместить биткоин на карте.",
"intro": "BTCMap.org - волонтерский проект с открытым исходным кодом (FOSS). Мы полагаемся на пожертвования и спонсорство для продолжения работы.",
"appreciate": "Мы очень ценим любую поддержку.",
"donate": {
"scanOrClick": "Сканируйте или нажмите для пожертвования",
"onchain": "Ончейн",
"lightning": "Lightning",
"protocolAlt": "протокол"
},
"supporters": {
"heading": "Наши удивительные сторонники",
"becomeSponsor": "Стать спонсором"
},
"node": {
"heading": "Откройте канал Lightning для нас"
},
"applyHere": "Подать заявку здесь",
"qrError": "Не удалось сгенерировать QR, пожалуйста, попробуйте снова или свяжитесь с BTC Map.",
"qrLoadError": "Не удалось загрузить генератор QR. Пожалуйста, попробуйте снова."
},
"privacyPolicy": {
"title": "Политика конфиденциальности",
"intro": "Мы не собираем вашу личную информацию.",
"readMore": "Пожалуйста, читайте дальше для получения дополнительных деталей.",
"forms": {
"heading": "Формы",
"intro": "Что происходит, когда вы отправляете форму на нашем веб-сайте:",
"item1": "Автоматически создаётся задача в нашем репозитории {btcmapDataLink}, содержащая информацию из формы.",
"item2": "Автоматически отправляется сообщение в наш {matrixLink}.",
"item3": "Если заявка действительна, она добавляется в {osmLink} участником BTC Map и появится в наших приложениях.",
"item4": "Некоторые данные, включая сообщества, не хранятся в OpenStreetMap, а в базе данных BTC Map.",
"referPolicies": "Пожалуйста, ознакомьтесь с политиками конфиденциальности каждой из этих третьих сторон, чтобы понять, как там используется ваша информация.",
"agreePublic": "Отправляя информацию через одну из наших форм, вы соглашаетесь с тем, что эта информация будет использоваться публично.",
"doNotSubmit": "Не отправляйте личную или частную информацию.",
"xHandleBefore": "Если вы укажете X-Handle, мы можем опубликовать о вашей заявке с",
"xHandleAfter": "аккаунта X."
},
"analytics": {
"heading": "Аналитика",
"intro": "Мы используем уважающую конфиденциальность аналитику от {netlifyLink} и самостоятельно размещённый экземпляр {umamiLink} для отслеживания статистики использования с течением времени и улучшения пользовательского опыта.",
"noCookies": "Эта аналитика не использует файлы cookies или трекеры. Личная идентифицируемая информация не включена. Все данные анонимны и соответствуют {gdprLink}.",
"readMore": "Ниже приведены ссылки для получения дополнительной информации о Netlify Analytics:"
},
"cookies": {
"heading": "Cookies",
"intro": "Мы не используем cookies."
},
"ipProtection": {
"heading": "Как защитить свой IP в интернете",
"intro": "Хорошей практикой является защита вашего публичного IP-адреса при сёрфинге в интернете. Два наиболее распространённых способа сделать это:",
"item1": "Использовать VPN-сервис, такой как {mullvadLink}.",
"item2": "Использовать браузер {torLink}."
},
"changes": {
"heading": "Изменения в этой политике конфиденциальности",
"lastUpdated": "Эта политика конфиденциальности последний раз обновлялась: 10 июля 2023 г."
},
"contact": {
"heading": "Свяжитесь с нами",
"intro": "Если у вас есть вопросы или отзывы о нашей политике конфиденциальности, свяжитесь с нами по адресу {contactLink} или на любой из наших социальных платформ."
},
"links": {
"githubPrivacy": "Политика конфиденциальности GitHub",
"discordPrivacy": "Политика конфиденциальности Discord",
"osmPrivacy": "Политика конфиденциальности OpenStreetMap",
"netlifyAnalytics": "Netlify Analytics",
"netlifyDocsAnalytics": "Netlify Docs - Analytics",
"netlifyDocsHowAnalytics": "Netlify Docs - How Analytics Works"
}
},
"aboutUs": {
"title": "О нас",
"description": "BTC Map - бесплатный проект с открытым исходным кодом, поддерживаемый волонтёрами-биткоинерами и биткоин- дружественными торговцами по всему миру.",
"merchants": {
"heading": "Места",
"intro": "Места - сердце BTC Map. Эти бизнесы первыми идут вперёд в парадигматическом сдвиге. Любой торговец, принимающий биткоин, может быть размещён на BTC Map.",
"acceptBitcoin": "Принимаете биткоин?",
"getListed": "Добавляйтесь на BTC Map"
},
"supertaggers": {
"heading": "Редакторы",
"intro": "Редакторы - это люди, которые поддерживают этот проект. Это волонтёры, которые самоотверженно тратят время на обновление информации. Без них BTC Map не был бы устойчивым!",
"topLabel": "Наши лучшие редакторы",
"viewLeaderboard": "Посмотреть рейтинг"
},
"communities": {
"heading": "Сообщества",
"intro": "Биткоин-сообщества помогают стимулировать глобальное распространение биткойна, привлекая новых локальных пользователей.",
"addPrompt": "Не видите своё сообщество?",
"addLink": "Добавьте его на BTC Map",
"seeAll": "Посмотреть все сообщества"
},
"integrations": {
"heading": "Интеграции",
"communityLabel": "Интеграции сообщества",
"communitySub": "Проекты, использующие BTC Map",
"projectLabel": "Интеграции проекта",
"projectSub": "BTC Map использует эти проекты",
"reachOut": "Если вы заинтересованы в интеграции с нами, пожалуйста,",
"reachOutLink": "свяжитесь с нами",
"supporter": "Сторонник",
"more": "Ещё!"
},
"contributors": {
"heading": "Контрибьюторы",
"intro": "Любой может внести свой вклад в BTC Map многими различными способами. Если вы хотите присоединиться, пожалуйста, не стесняйтесь!"
},
"coreTeam": {
"heading": "Основная команда",
"igorBio": "Игорь - давний биткоинер, маппер и цифровой кочевник, живущий за границей. Он создал BTC Map как Android-приложение, и проект с тех пор приобрёл всемирный импульс. Теперь он также поддерживает всю инфраструктуру проекта.",
"nathanBio": "Нейтан - предприниматель в сфере технологий, превратившийся в простого участника. Он собрал основную команду для ускорения разработки приложений. Построив, продав, инвестировав и консультируя технологические бизнесы на протяжении многих лет, теперь он сосредоточен на биткоине, создании BTCMap.org, gamertron.net и обучении детей биткоину.",
"secondl1ghtBio": "Самостоятельно изучивший веб-разработку, secondl1ght нырнул с головой в биткоин- rabbit hole и оставил свою карьеру в фиато, чтобы полностью сосредоточиться на биткоин-разработке. Он создал и поддерживает веб-приложение BTC Map, а также зашифрованное приложение для обмена сообщениями Cipherchat и работает над инструментами Lightning Network в Amboss Technologies.",
"karnageBio": "Карнаж - ведущий дизайнер веб-приложения и создатель бренда BTC Map. Он внёс вклад во многие известные биткоин-проекты с открытым исходным кодом. Его миссия - помочь основателям стартапов добиться успеха, и он создаёт продукты для достижения этой цели. Пиксельно-точный дизайн продукта каждый раз. Доведите до релиза."
},
"avatarAlt": "аватар"
}
}
Copy link

@coderabbitai coderabbitai bot Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
import json
import re
from pathlib import Path

base = Path("src/lib/i18n/locales")
files = ["en.json", "pt-BR.json", "bg.json", "ru.json"]

def flatten(obj, prefix=""):
    out = {}
    if isinstance(obj, dict):
        for k, v in obj.items():
            key = f"{prefix}.{k}" if prefix else k
            out.update(flatten(v, key))
    else:
        out[prefix] = obj
    return out

loaded = {}
for f in files:
    p = base / f
    if p.exists():
        loaded[f] = json.loads(p.read_text(encoding="utf-8"))

if "en.json" not in loaded or "ru.json" not in loaded:
    raise SystemExit("Missing en.json or ru.json")

en = flatten(loaded["en.json"])
for fname, data in loaded.items():
    flat = flatten(data)
    missing = sorted(set(en) - set(flat))
    extra = sorted(set(flat) - set(en))

    print(f"\n== {fname} ==")
    print(f"missing keys vs en: {len(missing)}")
    for k in missing[:30]:
        print(f"  - {k}")

    print(f"extra keys vs en: {len(extra)}")
    for k in extra[:30]:
        print(f"  + {k}")

    mismatches = []
    for k in set(en).intersection(flat):
        if isinstance(en[k], str) and isinstance(flat[k], str):
            en_vars = set(re.findall(r"\{([a-zA-Z0-9_]+)\}", en[k]))
            cur_vars = set(re.findall(r"\{([a-zA-Z0-9_]+)\}", flat[k]))
            if en_vars != cur_vars:
                mismatches.append((k, sorted(en_vars), sorted(cur_vars)))

    print(f"placeholder mismatches vs en: {len(mismatches)}")
    for k, a, b in mismatches[:30]:
        print(f"  * {k}: en={a}, {fname}={b}")
PY

Repository: teambtcmap/btcmap.org

Length of output: 2758


Locale parity check reveals issues in ru.json that need correction.

Verification found:

  • Missing key: dashboard.totalAreas (exists in en.json but not in ru.json) — could cause runtime fallback issues if referenced
  • Extra key: footer.switchToRussian (in ru.json but not in en.json) — inconsistent with en.json structure

While placeholder coverage is correct (0 mismatches), these key discrepancies should be resolved to maintain consistency across locales and prevent potential runtime issues.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/i18n/locales/ru.json` around lines 1 - 1097, Locale parity check
found two discrepancies: add the missing translation key "dashboard.totalAreas"
to ru.json with an appropriate Russian string (matching the en.json meaning) and
remove the extra key "footer.switchToRussian" from ru.json so the keys match
en.json; update the "dashboard" object to include "totalAreas" and delete
"footer.switchToRussian" to restore parity and avoid runtime
fallback/inconsistency issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bubelov wanna address these comments? This one and the other one

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@escapedcat nah, missing key was added later, it can be added in a follow up direct push (no need to bother anyone with prs if no real code is affected). ".switchToRussian" is probably a no op in ru.json and ъ is used interchangeably with ь unless you're a silver age poet or something

},
"communities": {
"hero": "Присоединяйтесь к сообществу BTC Map.",
"description": "Возьмите на себя поддержку локальных данных и помогите стимулировать распространение биткойна. Присоединяйтесь, добавляйте бизнес, обьединяйтесь.",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix user-facing Russian copy typos.

Line 536 has a typo (обьединяйтесьобъединяйтесь), and Line 1053 has an extra space in a hyphenated phrase (биткоин- дружественными).

✏️ Proposed text fix
-		"description": "Возьмите на себя поддержку локальных данных и помогите стимулировать распространение биткойна. Присоединяйтесь, добавляйте бизнес, обьединяйтесь.",
+		"description": "Возьмите на себя поддержку локальных данных и помогите стимулировать распространение биткойна. Присоединяйтесь, добавляйте бизнес, объединяйтесь.",
...
-		"description": "BTC Map - бесплатный проект с открытым исходным кодом, поддерживаемый волонтёрами-биткоинерами и биткоин- дружественными торговцами по всему миру.",
+		"description": "BTC Map - бесплатный проект с открытым исходным кодом, поддерживаемый волонтёрами-биткоинерами и биткоин-дружественными торговцами по всему миру.",

Also applies to: 1053-1053

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/i18n/locales/ru.json` at line 536, Replace the misspelled and spacing
errors in ru.json: change "обьединяйтесь" to "объединяйтесь" in the value for
the "description" entry that currently contains "Возьмите на себя поддержку
локальных данных и помогите стимулировать распространение биткойна.
Присоединяйтесь, добавляйте бизнес, обьединяйтесь."; also remove the extra space
in the hyphenated phrase "биткоин- дружественными" (make it
"биткоин-дружественными") wherever that exact string appears. Search for those
exact substrings in src/lib/i18n/locales/ru.json and update the JSON values
accordingly, ensuring punctuation and encoding remain valid.

@bubelov
Copy link
Collaborator Author

bubelov commented Mar 5, 2026

Yeah language switch won't scale for sure, we'll need a drop down. I didn't test it though because it did auto detect the locale. It's useful for debugging language-related design issues though

@dadofsambonzuki
Copy link
Member

I think we're in drop down territory now.

@escapedcat
Copy link
Contributor

I think we're in drop down territory now.

Alright, let it break. I'll do a follow up to come up with a good solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants