Refactor: Migrate to Swift String Catalogs (.xcstrings) (#691)

* Automated update of relay data - Sun Sep 21 06:26:33 UTC 2025

* chore(l10n): add empty string catalogs

* chore(l10n): populate string catalogs from legacy resources

* test(l10n): add catalog guardrail suite

* chore(l10n): remove legacy localization files

* fix: Add localization resources to Package.swift targets

- Add .process("Localization") to bitchat target resources
- Add .process("Localization") to bitchatTests target resources
- Resolves Bundle.module resource loading for localization files
- Enables proper localization testing in Swift Package Manager builds

* feat: Add Korean localization and convert to UTF-8 format

Korean Language Support:
- Add complete Korean (ko) localization with 191 strings from PR #686
- Include all app strings: UI, features, system messages, alerts
- Include all share extension strings: status messages, errors
- Verified 100% translation coverage for Korean locale

UTF-8 Format Conversion:
- Convert 23,047 Unicode escape sequences to readable UTF-8 characters
- Transform \u sequences (e.g. \u0625\u063a\u0644\u0627\u0642) to native text (إغلاق)
- Improve maintainability across all 15 supported locales
- Preserve all existing translations while enhancing readability

Locales supported: en, ar, de, es, fr, he, id, it, ja, ko, ne, pt-BR, ru, uk, zh-Hans

* test: Enhance dynamic localization test framework

Dynamic Test Framework:
- Replace hardcoded locale tests with data-driven approach
- Add testLocalizationExpectedValues() for dynamic locale validation
- Add testConfiguredLocalesCompleteness() for coverage verification
- Tests now read configuration from PrimaryLocalizationKeys.json

Expanded Test Coverage:
- Increase from 14 to 33 key validations (135% increase)
- Add critical UI strings: common actions, app info, security, sharing
- Cover 364 total string validations across 15 locales
- Include Korean validation with native Korean expected values

Test Categories Added:
- Common UI: cancel, close, copy actions
- App Info: encryption, offline features, app name
- Bluetooth: permission and settings alerts
- Security: verification badges and actions
- Share Extension: all status and error messages
- Content Actions: accessibility and user actions

Maintains 100% test success rate across all supported locales.

* fix: Convert plural strings to correct xcstrings format

Three plural strings (content.accessibility.people_count,
location_channels.row_title, location_notes.header) were using
incorrect format causing runtime String(format:) errors.

Migrated from stringUnit.variations structure to proper
substitutions.variations format across all 14 languages.

* refactor(l10n): migrate to native String(localized:) APIs

Remove L10n.string wrapper in favor of Swift's native localization APIs.
Migrate 100+ localization call sites to use String(localized:) and String(localized:defaultValue:) with string interpolation.

- Update catalog to use interpolation syntax (\(var)) instead of format specifiers (%@)
- Migrate simple strings to String(localized:)
- Migrate strings with arguments to String(localized:defaultValue:) with interpolation
- Keep format strings for plural substitutions (String(format:locale:))
- Remove bitchat/Utils/Localization.swift

Net result: -407 insertions, +130 deletions across 15 files

* fix(l10n): correct interpolation to use format strings

Interpolation in String(localized:defaultValue:) doesn't work as expected -
the interpolation happens at the call site before localization lookup.

Convert dynamic strings to use String(format:String(localized:),args) pattern:
- Update catalog entries from \(var) syntax to %@ placeholders
- Wrap String(localized:) calls with String(format:locale:) for dynamic values
- Affects 17 strings across 6 files

This fixes UI showing literal "\(geohash)" text instead of actual values.

* chore(l10n): remove invalid catalog entries

Remove auto-extracted literal strings (@, #, ✔︎, @%@, bitchat/) that were
generated without proper localization structure. These caused test
decoding failures.

* fix(l10n): remove unused auto-extracted format string

Remove '%@/%@' key that was auto-extracted by Xcode but never used.
This key only existed in English causing locale parity test failures
across all 13 other languages.

Fixes locale parity tests - all 8 localization tests now pass with
only expected failures (incomplete translations in some locales).

* fix(l10n): copy format string to all locales for 100% completion

Add %@/%@ format string to all 14 non-English locales. Format strings
are locale-independent so using the same value everywhere is correct.

This brings all locales to 100% completion (189/189 strings) to prevent
Xcode from reporting incomplete translations when building.

* fix(l10n): prevent auto-extraction of UI literals

Use Text(verbatim:) for non-localizable UI elements:
- App branding ("bitchat/")
- Symbols (@, #, ✔︎)
- Dynamic usernames (@username)
- Count ratios (reached/total)

This prevents Xcode from auto-extracting these literals into the
String Catalog when building through Xcode GUI, which was causing
locales to show 96% completion instead of 100%.

* chore(l10n): remove auto-extracted UI literal entries

Delete 5 auto-extracted keys from catalog that are now using Text(verbatim:):
- @, #, ✔︎, %@, %@/%@

These were showing as stale/incomplete in Xcode causing 97% completion.
All locales now at 100% (188/188 strings).

* fix(l10n): prevent AttributedString from extracting @ symbol

Use string interpolation "\\(at)" instead of literal "@" in
AttributedString to prevent Xcode from auto-extracting it to the
String Catalog during build.

This was the last string causing locales to show 99% instead of 100%.

* fix(l10n): add %@ as non-translatable key in all locales

Mark %@ as non-translatable and add to all 15 locales with same value.
This prevents Xcode from showing incomplete translations when it
auto-extracts this format specifier during GUI builds.

All locales remain at 100% (189/189 strings).

* refactor: move Localizable.xcstrings to bitchat root

Move bitchat/Localization/Localizable.xcstrings to bitchat/ (after LaunchScreen)
and remove empty Localization directory.

* fix(test): update catalog path in localization tests

Update test paths from bitchat/Localization/Localizable.xcstrings to
bitchat/Localizable.xcstrings after moving the file.

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
Jonathan Boice
2025-09-29 13:31:59 -07:00
committed by GitHub
parent da2a12296e
commit 0f7bcf17ff
61 changed files with 20763 additions and 4003 deletions
+6
View File
@@ -37,6 +37,9 @@ let package = Package(
"LaunchScreen.storyboard",
"Services/Tor/C/"
],
resources: [
.process("Localization")
],
linkerSettings: [
.linkedLibrary("z")
]
@@ -56,6 +59,9 @@ let package = Package(
exclude: [
"Info.plist",
"README.md"
],
resources: [
.process("Localization")
]
)
]
-1
View File
@@ -72,7 +72,6 @@
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Services/TransportConfig.swift,
Utils/Localization.swift,
);
target = 57CA17A36A2532A6CFF367BB /* bitchatShareExtension */;
};
File diff suppressed because it is too large Load Diff
@@ -1,192 +0,0 @@
/*
Localizable.strings
Bitchat
Base English localization entries. Keep keys sorted alphabetically.
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "close";
"app_info.done" = "DONE";
"app_info.features.encryption.description" = "private messages encrypted with noise protocol";
"app_info.features.encryption.title" = "end-to-end encryption";
"app_info.features.extended_range.description" = "messages relay through peers, going the distance";
"app_info.features.extended_range.title" = "extended range";
"app_info.features.favorites.description" = "get notified when your favorite people join";
"app_info.features.favorites.title" = "favorites";
"app_info.features.geohash.description" = "geohash channels to chat with people in nearby regions over decentralized anonymous relays";
"app_info.features.geohash.title" = "local channels";
"app_info.features.mentions.description" = "use @nickname to notify specific people";
"app_info.features.mentions.title" = "mentions";
"app_info.features.offline.description" = "works without internet using Bluetooth low energy";
"app_info.features.offline.title" = "offline communication";
"app_info.features.title" = "FEATURES";
"app_info.how_to_use.change_channels" = "• tap #mesh to change channels";
"app_info.how_to_use.clear_chat" = "• triple-tap chat to clear";
"app_info.how_to_use.commands" = "• type / for commands";
"app_info.how_to_use.open_sidebar" = "• tap people icon for sidebar";
"app_info.how_to_use.set_nickname" = "• set your nickname by tapping it";
"app_info.how_to_use.start_dm" = "• tap a peer's name to start a DM";
"app_info.how_to_use.title" = "HOW TO USE";
"app_info.privacy.ephemeral.description" = "new peer ID generated regularly";
"app_info.privacy.ephemeral.title" = "ephemeral identity";
"app_info.privacy.no_tracking.description" = "no servers, accounts, or data collection";
"app_info.privacy.no_tracking.title" = "no tracking";
"app_info.privacy.panic.description" = "triple-tap logo to instantly clear all data";
"app_info.privacy.panic.title" = "panic mode";
"app_info.privacy.title" = "PRIVACY";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "private message security has not yet been fully audited. do not use for critical situations until this warning disappears.";
"app_info.warning.title" = "WARNING";
"common.cancel" = "cancel";
"common.close" = "close";
"common.copy" = "copy";
"common.ok" = "OK";
"common.toggle.off" = "off";
"common.toggle.on" = "on";
"common.unknown" = "unknown";
"content.accessibility.add_favorite" = "add to favorites";
"content.accessibility.available_nostr" = "available via Nostr";
"content.accessibility.back_to_main_chat" = "back to main chat";
"content.accessibility.connected_mesh" = "connected via mesh";
"content.accessibility.encryption_status" = "encryption status: %@";
"content.accessibility.location_channels" = "location channels";
"content.accessibility.location_notes" = "location notes for this place";
"content.accessibility.open_unread_private_chat" = "open unread private chat";
"content.accessibility.private_chat_header" = "private chat with %@";
"content.accessibility.reachable_mesh" = "reachable via mesh";
"content.accessibility.remove_favorite" = "remove from favorites";
"content.accessibility.send_hint_empty" = "enter a message to send";
"content.accessibility.send_hint_ready" = "double tap to send";
"content.accessibility.send_message" = "send message";
"content.accessibility.toggle_bookmark" = "toggle bookmark for #%@";
"content.accessibility.toggle_favorite_hint" = "double tap to toggle favorite status";
"content.accessibility.view_fingerprint_hint" = "tap to view encryption fingerprint";
"content.actions.block" = "block";
"content.actions.direct_message" = "direct message";
"content.actions.hug" = "hug";
"content.actions.mention" = "mention";
"content.actions.slap" = "slap";
"content.actions.title" = "actions";
"content.alert.bluetooth_required.off" = "bluetooth is turned off. please turn on bluetooth in settings to use bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat needs bluetooth permission to connect with nearby devices. please enable bluetooth access in settings.";
"content.alert.bluetooth_required.settings" = "settings";
"content.alert.bluetooth_required.title" = "bluetooth required";
"content.alert.bluetooth_required.unsupported" = "this device does not support bluetooth. bitchat requires bluetooth to function.";
"content.alert.screenshot.message" = "screenshots of location channels will reveal your location. think before sharing publicly.";
"content.alert.screenshot.title" = "heads up";
"content.commands.block" = "block or list blocked peers";
"content.commands.clear" = "clear chat messages";
"content.commands.favorite" = "add to favorites";
"content.commands.hug" = "send someone a warm hug";
"content.commands.message" = "send private message";
"content.commands.slap" = "slap someone with a trout";
"content.commands.unblock" = "unblock a peer";
"content.commands.unfavorite" = "remove from favorites";
"content.commands.who" = "see who's online";
"content.delivery.delivered_members" = "delivered to %1$d of %2$d members";
"content.delivery.delivered_to" = "delivered to %@";
"content.delivery.failed" = "failed: %@";
"content.delivery.read_by" = "read by %@";
"content.delivery.reason.blocked" = "user is blocked";
"content.delivery.reason.self" = "cannot message yourself";
"content.delivery.reason.send_error" = "send error";
"content.delivery.reason.unknown_recipient" = "unknown recipient";
"content.delivery.reason.unreachable" = "peer not reachable";
"content.header.people" = "PEOPLE";
"content.help.verification" = "verification: show my QR or scan a friend";
"content.input.message_placeholder" = "type a message...";
"content.input.nickname_placeholder" = "nickname";
"content.location.enable" = "enable location";
"content.message.copy" = "copy message";
"content.message.show_less" = "show less";
"content.message.show_more" = "show more";
"content.notes.location_unavailable" = "location unavailable";
"content.notes.title" = "notes";
"content.payment.cashu" = "pay via cashu";
"content.payment.lightning" = "pay via lightning";
"encryption.accessibility.establishing" = "establishing encryption";
"encryption.accessibility.failed" = "encryption failed";
"encryption.accessibility.not_encrypted" = "not encrypted";
"encryption.accessibility.secured" = "encrypted";
"encryption.accessibility.verified" = "encrypted and verified";
"encryption.status.establishing" = "sstablishing encryption...";
"encryption.status.failed" = "encryption failed";
"encryption.status.not_encrypted" = "not encrypted";
"encryption.status.secured" = "encrypted";
"encryption.status.verified" = "encrypted & verified";
"fingerprint.action.mark_verified" = "mark as verified";
"fingerprint.action.remove_verification" = "remove verification";
"fingerprint.badge.not_verified" = "⚠️ NOT VERIFIED";
"fingerprint.badge.verified" = "✓ VERIFIED";
"fingerprint.handshake_pending" = "not available - handshake in progress";
"fingerprint.message.verified" = "you have verified this person's identity.";
"fingerprint.message.verify_hint" = "compare these fingerprints with %@ using a secure channel.";
"fingerprint.their_label" = "their fingerprint:";
"fingerprint.title" = "security verification";
"fingerprint.your_label" = "your fingerprint:";
"geohash_people.action.block" = "block";
"geohash_people.action.unblock" = "unblock";
"geohash_people.none_nearby" = "nobody around...";
"geohash_people.tooltip.blocked" = "blocked in geohash";
"geohash_people.you_suffix" = " (you)";
"location_channels.action.open_settings" = "open settings";
"location_channels.action.remove_access" = "remove location access";
"location_channels.action.request_permissions" = "get location and my geohashes";
"location_channels.action.teleport" = "teleport";
"location_channels.bookmarked_section_title" = "bookmarked";
"location_channels.description" = "chat with people near you using geohash channels. only a coarse geohash is shared, never exact GPS. your IP address is hidden by routing all traffic over tor.";
"location_channels.error.invalid_geohash" = "invalid geohash";
"location_channels.loading_nearby" = "finding nearby channels…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "location permission denied. enable in settings to use location channels.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#location channels";
"location_channels.tor.subtitle" = "hides your IP for location channels. recommended: on.";
"location_channels.tor.title" = "tor routing";
"location_levels.block" = "block";
"location_levels.building" = "building";
"location_levels.city" = "city";
"location_levels.neighborhood" = "neighborhood";
"location_levels.province" = "province";
"location_levels.region" = "region";
"location_notes.action.dismiss" = "dismiss";
"location_notes.action.retry" = "retry";
"location_notes.description" = "add short permanent notes to this location for other visitors to find.";
"location_notes.empty_subtitle" = "be the first to add one for this spot.";
"location_notes.empty_title" = "no notes yet";
"location_notes.error.failed_to_send" = "failed to send note. %@";
"location_notes.error.no_relays" = "no geo relays available near this location. try again soon.";
"location_notes.loading_notes" = "loading notes…";
"location_notes.loading_recent" = "loading recent notes…";
"location_notes.no_relays_nearby" = "no geo relays nearby";
"location_notes.placeholder" = "add a note for this place";
"location_notes.relays_paused" = "geo relays unavailable; notes paused";
"location_notes.relays_retry_hint" = "notes rely on geo relays. check connection and try again.";
"mesh_peers.tooltip.new_messages" = "new messages";
"system.chat.blocked" = "cannot start chat with %@: person is blocked.";
"system.chat.requires_favorite" = "cannot start chat with %@: mutual favorite required for offline messaging.";
"system.common.user" = "user";
"system.dm.blocked_generic" = "cannot send message: person is blocked.";
"system.dm.blocked_recipient" = "cannot send message to %@: person is blocked.";
"system.dm.unreachable" = "cannot send message to %@ - peer is not reachable via mesh or nostr.";
"system.geohash.blocked" = "blocked %@ in geohash chats";
"system.geohash.unblocked" = "unblocked %@ in geohash chats";
"system.location.not_in_channel" = "cannot send: not in a location channel";
"system.location.send_failed" = "failed to send to location channel";
"system.tor.dev_bypass" = "development build: Tor bypass enabled.";
"system.tor.restarted" = "tor restarted. network routing restored.";
"system.tor.restarting" = "tor restarting to recover connectivity...";
"system.tor.started" = "tor started. routing all chats via tor for IP privacy.";
"system.tor.starting" = "starting tor...";
"verification.my_qr.accessibility_label" = "verification QR code";
"verification.my_qr.title" = "scan to verify me";
"verification.my_qr.unavailable" = "QR unavailable";
"verification.scan.paste_prompt" = "paste QR content to validate:";
"verification.scan.prompt_friend" = "scan a friend's QR";
"verification.scan.status.invalid" = "invalid or expired QR payload";
"verification.scan.status.no_peer" = "could not find matching peer";
"verification.scan.status.requested" = "verification requested for %@";
"verification.scan.validate" = "validate";
"verification.sheet.title" = "VERIFY";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d note</string>
<key>other</key>
<string>%d notes</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d person</string>
<key>other</key>
<string>%d people</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d person</string>
<key>other</key>
<string>%d people</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Arabic)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "إغلاق";
"app_info.done" = "تم";
"app_info.features.encryption.description" = "الرسائل الخاصة مشفرة ببروتوكول noise";
"app_info.features.encryption.title" = "تشفير طرف لطرف";
"app_info.features.extended_range.description" = "يُعاد تمرير الرسائل بين الأقران لتصل لمسافات أبعد";
"app_info.features.extended_range.title" = "نطاق ممتد";
"app_info.features.favorites.description" = "تلقَّ تنبيهات عندما ينضم أحباؤك";
"app_info.features.favorites.title" = "المفضلة";
"app_info.features.geohash.description" = "قنوات geohash للدردشة مع أشخاص قريبين عبر مرحلات لامركزية مجهولة";
"app_info.features.geohash.title" = "قنوات محلية";
"app_info.features.mentions.description" = "استخدم @nickname لتنبيه أشخاص محددين";
"app_info.features.mentions.title" = "إشارات";
"app_info.features.offline.description" = "يعمل بدون إنترنت باستخدام bluetooth منخفض الطاقة";
"app_info.features.offline.title" = "تواصل بدون اتصال";
"app_info.features.title" = "مزايا";
"app_info.how_to_use.change_channels" = "• اضغط #mesh لتغيير القناة";
"app_info.how_to_use.clear_chat" = "• اضغط الدردشة ثلاث مرات للمسح";
"app_info.how_to_use.commands" = "• اكتب / لعرض الأوامر";
"app_info.how_to_use.open_sidebar" = "• اضغط أيقونة الأشخاص لفتح الشريط الجانبي";
"app_info.how_to_use.set_nickname" = "• اضبط لقبك بلمسه";
"app_info.how_to_use.start_dm" = "• اضغط اسم القرين لبدء رسائل خاصة";
"app_info.how_to_use.title" = "طريقة الاستخدام";
"app_info.privacy.ephemeral.description" = "يُولد معرف قرين جديد بانتظام";
"app_info.privacy.ephemeral.title" = "هوية مؤقتة";
"app_info.privacy.no_tracking.description" = "لا خوادم أو حسابات أو جمع بيانات";
"app_info.privacy.no_tracking.title" = "لا تتبع";
"app_info.privacy.panic.description" = "اضغط الشعار ثلاث مرات لمسح كل البيانات فوراً";
"app_info.privacy.panic.title" = "وضع الذعر";
"app_info.privacy.title" = "خصوصية";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "أمان الرسائل الخاصة لم يتم تدقيقه بالكامل بعد. لا تستخدمها في الحالات الحرجة حتى يختفي هذا التحذير.";
"app_info.warning.title" = "تحذير";
"common.cancel" = "إلغاء";
"common.close" = "إغلاق";
"common.copy" = "نسخ";
"common.ok" = "موافق";
"common.toggle.off" = "إيقاف";
"common.toggle.on" = "تشغيل";
"common.unknown" = "غير معروف";
"content.accessibility.add_favorite" = "إضافة إلى المفضلة";
"content.accessibility.available_nostr" = "متاح عبر nostr";
"content.accessibility.back_to_main_chat" = "عودة إلى الدردشة الرئيسية";
"content.accessibility.connected_mesh" = "متصل عبر mesh";
"content.accessibility.encryption_status" = "حالة التشفير: %@";
"content.accessibility.location_channels" = "قنوات الموقع";
"content.accessibility.location_notes" = "ملاحظات الموقع لهذا المكان";
"content.accessibility.open_unread_private_chat" = "فتح دردشة خاصة غير مقروءة";
"content.accessibility.private_chat_header" = "دردشة خاصة مع %@";
"content.accessibility.reachable_mesh" = "قابل للوصول عبر mesh";
"content.accessibility.remove_favorite" = "إزالة من المفضلة";
"content.accessibility.send_hint_empty" = "أدخل رسالة للإرسال";
"content.accessibility.send_hint_ready" = "اضغط مرتين للإرسال";
"content.accessibility.send_message" = "إرسال رسالة";
"content.accessibility.toggle_bookmark" = "تبديل الإشارة لـ #%@";
"content.accessibility.toggle_favorite_hint" = "اضغط مرتين لتبديل حالة المفضلة";
"content.accessibility.view_fingerprint_hint" = "اضغط لمشاهدة بصمة التشفير";
"content.actions.block" = "حظر";
"content.actions.direct_message" = "رسالة مباشرة";
"content.actions.hug" = "عناق";
"content.actions.mention" = "ذكر";
"content.actions.slap" = "صفعة";
"content.actions.title" = "إجراءات";
"content.alert.bluetooth_required.off" = "bluetooth متوقف. فعّل bluetooth في الإعدادات لاستخدام bitchat.";
"content.alert.bluetooth_required.permission" = "تحتاج bitchat إلى إذن bluetooth للاتصال بالأجهزة القريبة. فعّل الوصول في الإعدادات.";
"content.alert.bluetooth_required.settings" = "الإعدادات";
"content.alert.bluetooth_required.title" = "مطلوب bluetooth";
"content.alert.bluetooth_required.unsupported" = "هذا الجهاز لا يدعم bluetooth. يحتاج bitchat إلى bluetooth للعمل.";
"content.alert.screenshot.message" = "لقطات قنوات الموقع تكشف موقعك. فكر قبل المشاركة علناً.";
"content.alert.screenshot.title" = "تنبيه";
"content.commands.block" = "حظر أو عرض المحظورين";
"content.commands.clear" = "مسح رسائل الدردشة";
"content.commands.favorite" = "إضافة للمفضلة";
"content.commands.hug" = "إرسال عناق دافئ";
"content.commands.message" = "إرسال رسالة خاصة";
"content.commands.slap" = "صفع شخص بسمكة تراوت";
"content.commands.unblock" = "إلغاء حظر قرين";
"content.commands.unfavorite" = "إزالة من المفضلة";
"content.commands.who" = "عرض من هو متصل";
"content.delivery.delivered_members" = "تم التسليم إلى %1$d من %2$d عضو";
"content.delivery.delivered_to" = "سُلّم إلى %@";
"content.delivery.failed" = "فشل: %@";
"content.delivery.read_by" = "قُرِئ بواسطة %@";
"content.delivery.reason.blocked" = "المستخدم محظور";
"content.delivery.reason.self" = "لا يمكن الإرسال لنفسك";
"content.delivery.reason.send_error" = "خطأ في الإرسال";
"content.delivery.reason.unknown_recipient" = "مستلم غير معروف";
"content.delivery.reason.unreachable" = "القرين غير متاح";
"content.header.people" = "أشخاص";
"content.help.verification" = "التحقق: عرض رمز qr الخاص بي أو مسح صديق";
"content.input.message_placeholder" = "اكتب رسالة...";
"content.input.nickname_placeholder" = "لقب";
"content.location.enable" = "تفعيل الموقع";
"content.message.copy" = "نسخ الرسالة";
"content.message.show_less" = "عرض أقل";
"content.message.show_more" = "عرض المزيد";
"content.notes.location_unavailable" = "الموقع غير متاح";
"content.notes.title" = "ملاحظات";
"content.payment.cashu" = "الدفع عبر cashu";
"content.payment.lightning" = "الدفع عبر lightning";
"encryption.accessibility.establishing" = "جار إعداد التشفير";
"encryption.accessibility.failed" = "فشل التشفير";
"encryption.accessibility.not_encrypted" = "غير مشفر";
"encryption.accessibility.secured" = "مشفر";
"encryption.accessibility.verified" = "مشفر ومُتحقق";
"encryption.status.establishing" = "جار إعداد التشفير...";
"encryption.status.failed" = "فشل التشفير";
"encryption.status.not_encrypted" = "غير مشفر";
"encryption.status.secured" = "مشفر";
"encryption.status.verified" = "مشفر ومُتحقق";
"fingerprint.action.mark_verified" = "وضع علامة تم التحقق";
"fingerprint.action.remove_verification" = "إزالة التحقق";
"fingerprint.badge.not_verified" = "⚠️ غير مُتحقق";
"fingerprint.badge.verified" = "✓ مُتحقق";
"fingerprint.handshake_pending" = "غير متاح - جار تنفيذ handshake";
"fingerprint.message.verified" = "لقد تحققت من هوية هذا الشخص.";
"fingerprint.message.verify_hint" = "قارن هذه البصمات مع %@ عبر قناة آمنة.";
"fingerprint.their_label" = "بصمتهم:";
"fingerprint.title" = "تحقق الأمان";
"fingerprint.your_label" = "بصمتك:";
"geohash_people.action.block" = "حظر";
"geohash_people.action.unblock" = "إلغاء الحظر";
"geohash_people.none_nearby" = "لا أحد قريب...";
"geohash_people.tooltip.blocked" = "محظور في geohash";
"geohash_people.you_suffix" = " (أنت)";
"location_channels.action.open_settings" = "فتح الإعدادات";
"location_channels.action.remove_access" = "إزالة صلاحية الموقع";
"location_channels.action.request_permissions" = "جلب موقعي و geohash";
"location_channels.action.teleport" = "انتقال فوري";
"location_channels.bookmarked_section_title" = "محفوظ";
"location_channels.description" = "تحدث مع أشخاص قريبين عبر قنوات geohash. نشارك geohash تقريبي فقط، وليس gps الدقيق. يتم إخفاء عنوان ip لأن كل المرور يمر عبر tor.";
"location_channels.error.invalid_geohash" = "geohash غير صالح";
"location_channels.loading_nearby" = "جار البحث عن قنوات قريبة…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "تم رفض إذن الموقع. فعّله في الإعدادات لاستخدام قنوات الموقع.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#قنوات الموقع";
"location_channels.tor.subtitle" = "يخفي ip لقنوات الموقع. الموصى به: تشغيل.";
"location_channels.tor.title" = "توجيه tor";
"location_levels.block" = "مربع";
"location_levels.building" = "مبنى";
"location_levels.city" = "مدينة";
"location_levels.neighborhood" = "حي";
"location_levels.province" = "مقاطعة";
"location_levels.region" = "منطقة";
"location_notes.action.dismiss" = "إغلاق";
"location_notes.action.retry" = "إعادة المحاولة";
"location_notes.description" = "أضف ملاحظات قصيرة دائمة لهذا المكان ليجدها الآخرون.";
"location_notes.empty_subtitle" = "كن أول من يضيف هنا.";
"location_notes.empty_title" = "لا توجد ملاحظات بعد";
"location_notes.error.failed_to_send" = "تعذر إرسال الملاحظة. %@";
"location_notes.error.no_relays" = "لا توجد مرحلات جغرافية قريبة من هذا المكان. حاول لاحقاً.";
"location_notes.loading_notes" = "جار تحميل الملاحظات…";
"location_notes.loading_recent" = "جار تحميل الملاحظات الحديثة…";
"location_notes.no_relays_nearby" = "لا مرحلات جغرافية قريبة";
"location_notes.placeholder" = "أضف ملاحظة لهذا المكان";
"location_notes.relays_paused" = "المرحلات الجغرافية غير متاحة؛ الملاحظات متوقفة";
"location_notes.relays_retry_hint" = "الملاحظات تعتمد على المرحلات الجغرافية. تحقق من الاتصال ثم أعد المحاولة.";
"mesh_peers.tooltip.new_messages" = "رسائل جديدة";
"system.chat.blocked" = "لا يمكن بدء دردشة مع %@: المستخدم محظور.";
"system.chat.requires_favorite" = "لا يمكن بدء دردشة مع %@: يجب أن تكونا مفضلين متبادلين للتشغيل بدون اتصال.";
"system.common.user" = "مستخدم";
"system.dm.blocked_generic" = "تعذر الإرسال: المستخدم محظور.";
"system.dm.blocked_recipient" = "لا يمكن الإرسال إلى %@: المستخدم محظور.";
"system.dm.unreachable" = "لا يمكن الإرسال إلى %@: المستلم غير متاح عبر mesh أو nostr.";
"system.geohash.blocked" = "تم حظر %@ في محادثات geohash";
"system.geohash.unblocked" = "تم إلغاء حظر %@ في محادثات geohash";
"system.location.not_in_channel" = "تعذر الإرسال: لست داخل قناة موقع";
"system.location.send_failed" = "تعذر الإرسال إلى قناة الموقع";
"system.tor.dev_bypass" = "بناء تطوير: تجاوز tor مفعل.";
"system.tor.restarted" = "tor أُعيد تشغيله. تمت استعادة التوجيه.";
"system.tor.restarting" = "tor يعاد تشغيله لاستعادة الاتصال...";
"system.tor.started" = "tor يعمل. كل الدردشة تمر عبر tor للخصوصية.";
"system.tor.starting" = "يتم تشغيل tor...";
"verification.my_qr.accessibility_label" = "رمز qr للتحقق";
"verification.my_qr.title" = "امسح للتحقق مني";
"verification.my_qr.unavailable" = "qr غير متاح";
"verification.scan.paste_prompt" = "الصق محتوى qr للتحقق:";
"verification.scan.prompt_friend" = "امسح qr لصديق";
"verification.scan.status.invalid" = "qr غير صالح أو منتهٍ";
"verification.scan.status.no_peer" = "لم يتم العثور على قرين مطابق";
"verification.scan.status.requested" = "تم طلب التحقق لـ %@";
"verification.scan.validate" = "تحقق";
"verification.sheet.title" = "تحقق";
@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>%d ملاحظات</string>
<key>one</key>
<string>%d ملاحظة</string>
<key>two</key>
<string>%d ملاحظتان</string>
<key>few</key>
<string>%d ملاحظات</string>
<key>many</key>
<string>%d ملاحظة</string>
<key>other</key>
<string>%d ملاحظة</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>%d أشخاص</string>
<key>one</key>
<string>%d شخص</string>
<key>two</key>
<string>%d شخصان</string>
<key>few</key>
<string>%d أشخاص</string>
<key>many</key>
<string>%d شخص</string>
<key>other</key>
<string>%d شخص</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>zero</key>
<string>%d أشخاص</string>
<key>one</key>
<string>%d شخص</string>
<key>two</key>
<string>%d شخصان</string>
<key>few</key>
<string>%d أشخاص</string>
<key>many</key>
<string>%d شخص</string>
<key>other</key>
<string>%d شخص</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (German)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "schließen";
"app_info.done" = "FERTIG";
"app_info.features.encryption.description" = "private nachrichten werden mit dem noise-protokoll verschlüsselt";
"app_info.features.encryption.title" = "end-to-end-verschlüsselung";
"app_info.features.extended_range.description" = "nachrichten werden zwischen peers weitergeleitet und reichen weiter";
"app_info.features.extended_range.title" = "erweiterte reichweite";
"app_info.features.favorites.description" = "erhalte hinweise, wenn deine lieblingsmenschen online kommen";
"app_info.features.favorites.title" = "favoriten";
"app_info.features.geohash.description" = "geohash-kanäle zum chatten mit menschen in der nähe über dezentrale anonyme relays";
"app_info.features.geohash.title" = "lokale kanäle";
"app_info.features.mentions.description" = "nutze @nickname, um bestimmte personen zu benachrichtigen";
"app_info.features.mentions.title" = "erwähnungen";
"app_info.features.offline.description" = "funktioniert ohne internet per bluetooth low energy";
"app_info.features.offline.title" = "offline-kommunikation";
"app_info.features.title" = "FUNKTIONEN";
"app_info.how_to_use.change_channels" = "• tippe auf #mesh, um den kanal zu wechseln";
"app_info.how_to_use.clear_chat" = "• tippe den chat dreimal, um ihn zu leeren";
"app_info.how_to_use.commands" = "• tippe /, um befehle zu sehen";
"app_info.how_to_use.open_sidebar" = "• tippe auf das personen-icon, um die seitenleiste zu öffnen";
"app_info.how_to_use.set_nickname" = "• tippe auf deinen nickname, um ihn zu ändern";
"app_info.how_to_use.start_dm" = "• tippe auf den namen eines peers, um eine pn zu starten";
"app_info.how_to_use.title" = "SO FUNKTIONIERT'S";
"app_info.privacy.ephemeral.description" = "neue peer-id wird regelmäßig erzeugt";
"app_info.privacy.ephemeral.title" = "flüchtige identität";
"app_info.privacy.no_tracking.description" = "keine server, konten oder datensammlung";
"app_info.privacy.no_tracking.title" = "kein tracking";
"app_info.privacy.panic.description" = "tippe dreimal auf das logo, um alle daten sofort zu löschen";
"app_info.privacy.panic.title" = "panikmodus";
"app_info.privacy.title" = "PRIVATSPHÄRE";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "die sicherheit privater nachrichten wurde noch nicht vollständig geprüft. nutze sie nicht für kritische situationen, solange dieser hinweis erscheint.";
"app_info.warning.title" = "WARNUNG";
"common.cancel" = "abbrechen";
"common.close" = "schließen";
"common.copy" = "kopieren";
"common.ok" = "OK";
"common.toggle.off" = "aus";
"common.toggle.on" = "an";
"common.unknown" = "unbekannt";
"content.accessibility.add_favorite" = "zu favoriten hinzufügen";
"content.accessibility.available_nostr" = "verfügbar über nostr";
"content.accessibility.back_to_main_chat" = "zurück zum hauptchat";
"content.accessibility.connected_mesh" = "verbunden über mesh";
"content.accessibility.encryption_status" = "verschlüsselungsstatus: %@";
"content.accessibility.location_channels" = "kanäle für standorte";
"content.accessibility.location_notes" = "standortnotizen für diesen ort";
"content.accessibility.open_unread_private_chat" = "ungelesene privatnachricht öffnen";
"content.accessibility.private_chat_header" = "privatchat mit %@";
"content.accessibility.reachable_mesh" = "erreichbar über mesh";
"content.accessibility.remove_favorite" = "aus favoriten entfernen";
"content.accessibility.send_hint_empty" = "gib eine nachricht zum senden ein";
"content.accessibility.send_hint_ready" = "doppelt tippen zum senden";
"content.accessibility.send_message" = "nachricht senden";
"content.accessibility.toggle_bookmark" = "bookmark für #%@ umschalten";
"content.accessibility.toggle_favorite_hint" = "doppelt tippen, um favoritenstatus zu wechseln";
"content.accessibility.view_fingerprint_hint" = "tippe, um den verschlüsselungs-fingerprint zu sehen";
"content.actions.block" = "blockieren";
"content.actions.direct_message" = "direktnachricht";
"content.actions.hug" = "umarmen";
"content.actions.mention" = "erwähnen";
"content.actions.slap" = "ohrfeige";
"content.actions.title" = "aktionen";
"content.alert.bluetooth_required.off" = "bluetooth ist ausgeschaltet. aktiviere bluetooth in den einstellungen, um bitchat zu verwenden.";
"content.alert.bluetooth_required.permission" = "bitchat benötigt bluetooth-berechtigung, um sich mit geräten in der nähe zu verbinden. erlaube den zugriff in den einstellungen.";
"content.alert.bluetooth_required.settings" = "einstellungen";
"content.alert.bluetooth_required.title" = "bluetooth erforderlich";
"content.alert.bluetooth_required.unsupported" = "dieses gerät unterstützt kein bluetooth. bitchat benötigt bluetooth zum funktionieren.";
"content.alert.screenshot.message" = "screenshots von standortkanälen verraten deinen standort. überleg dir das teilen vorher gut.";
"content.alert.screenshot.title" = "achtung";
"content.commands.block" = "blocked peers anzeigen oder blockieren";
"content.commands.clear" = "chatnachrichten löschen";
"content.commands.favorite" = "zu favoriten hinzufügen";
"content.commands.hug" = "eine warme umarmung senden";
"content.commands.message" = "privatnachricht senden";
"content.commands.slap" = "jemandem eine forelle um die ohren schlagen";
"content.commands.unblock" = "peer entsperren";
"content.commands.unfavorite" = "aus favoriten entfernen";
"content.commands.who" = "sehen, wer online ist";
"content.delivery.delivered_members" = "zugestellt an %1$d von %2$d mitgliedern";
"content.delivery.delivered_to" = "zugestellt an %@";
"content.delivery.failed" = "fehlgeschlagen: %@";
"content.delivery.read_by" = "gelesen von %@";
"content.delivery.reason.blocked" = "nutzer blockiert";
"content.delivery.reason.self" = "kann nicht an dich selbst senden";
"content.delivery.reason.send_error" = "sende-fehler";
"content.delivery.reason.unknown_recipient" = "unbekannter empfänger";
"content.delivery.reason.unreachable" = "peer nicht erreichbar";
"content.header.people" = "PERSONEN";
"content.help.verification" = "verifizierung: meinen qr zeigen oder freund scannen";
"content.input.message_placeholder" = "nachricht eingeben...";
"content.input.nickname_placeholder" = "nickname";
"content.location.enable" = "standort aktivieren";
"content.message.copy" = "nachricht kopieren";
"content.message.show_less" = "weniger anzeigen";
"content.message.show_more" = "mehr anzeigen";
"content.notes.location_unavailable" = "standort nicht verfügbar";
"content.notes.title" = "notizen";
"content.payment.cashu" = "per cashu bezahlen";
"content.payment.lightning" = "per lightning bezahlen";
"encryption.accessibility.establishing" = "verschlüsselung wird aufgebaut";
"encryption.accessibility.failed" = "verschlüsselung fehlgeschlagen";
"encryption.accessibility.not_encrypted" = "nicht verschlüsselt";
"encryption.accessibility.secured" = "verschlüsselt";
"encryption.accessibility.verified" = "verschlüsselt und verifiziert";
"encryption.status.establishing" = "verschlüsselung wird aufgebaut...";
"encryption.status.failed" = "verschlüsselung fehlgeschlagen";
"encryption.status.not_encrypted" = "nicht verschlüsselt";
"encryption.status.secured" = "verschlüsselt";
"encryption.status.verified" = "verschlüsselt und verifiziert";
"fingerprint.action.mark_verified" = "als verifiziert markieren";
"fingerprint.action.remove_verification" = "verifizierung entfernen";
"fingerprint.badge.not_verified" = "⚠️ NICHT VERIFIZIERT";
"fingerprint.badge.verified" = "✓ VERIFIZIERT";
"fingerprint.handshake_pending" = "nicht verfügbar handshake läuft";
"fingerprint.message.verified" = "du hast die identität dieser person verifiziert.";
"fingerprint.message.verify_hint" = "vergleiche diese fingerabdrücke mit %@ über einen sicheren kanal.";
"fingerprint.their_label" = "deren fingerabdruck:";
"fingerprint.title" = "sicherheitsverifizierung";
"fingerprint.your_label" = "dein fingerabdruck:";
"geohash_people.action.block" = "blockieren";
"geohash_people.action.unblock" = "entsperren";
"geohash_people.none_nearby" = "niemand in der nähe...";
"geohash_people.tooltip.blocked" = "in geohash blockiert";
"geohash_people.you_suffix" = " (du)";
"location_channels.action.open_settings" = "einstellungen öffnen";
"location_channels.action.remove_access" = "standortzugriff entfernen";
"location_channels.action.request_permissions" = "standort und geohash abrufen";
"location_channels.action.teleport" = "teleportieren";
"location_channels.bookmarked_section_title" = "gespeichert";
"location_channels.description" = "chatte mit menschen in deiner nähe über geohash-kanäle. geteilt wird nur ein grober geohash, niemals exakte gps-daten. deine ip bleibt verborgen, weil der gesamte verkehr über tor läuft.";
"location_channels.error.invalid_geohash" = "ungültiger geohash";
"location_channels.loading_nearby" = "suche nach kanälen in der nähe…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "standortberechtigung verweigert. aktiviere sie in den einstellungen für standortkanäle.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#standort-kanäle";
"location_channels.tor.subtitle" = "verbirgt deine ip für standortkanäle. empfohlen: an.";
"location_channels.tor.title" = "tor-routing";
"location_levels.block" = "block";
"location_levels.building" = "gebäude";
"location_levels.city" = "stadt";
"location_levels.neighborhood" = "viertel";
"location_levels.province" = "bundesland";
"location_levels.region" = "region";
"location_notes.action.dismiss" = "schließen";
"location_notes.action.retry" = "erneut versuchen";
"location_notes.description" = "füge diesem ort kurze dauerhafte notizen hinzu, damit andere sie finden.";
"location_notes.empty_subtitle" = "sei die erste person, die hier eine notiz hinterlässt.";
"location_notes.empty_title" = "noch keine notizen";
"location_notes.error.failed_to_send" = "notiz konnte nicht gesendet werden. %@";
"location_notes.error.no_relays" = "keine geo-relays in der nähe verfügbar. versuch es später erneut.";
"location_notes.loading_notes" = "notizen werden geladen…";
"location_notes.loading_recent" = "aktuelle notizen werden geladen…";
"location_notes.no_relays_nearby" = "keine geo-relays in der nähe";
"location_notes.placeholder" = "notiz für diesen ort hinzufügen";
"location_notes.relays_paused" = "geo-relays nicht verfügbar; notizen pausiert";
"location_notes.relays_retry_hint" = "notizen hängen von geo-relays ab. prüfe die verbindung und versuch es erneut.";
"mesh_peers.tooltip.new_messages" = "neue nachrichten";
"system.chat.blocked" = "chat mit %@ kann nicht gestartet werden: nutzer blockiert.";
"system.chat.requires_favorite" = "chat mit %@ kann nicht gestartet werden: gegenseitige favoriten für offline nötig.";
"system.common.user" = "nutzer";
"system.dm.blocked_generic" = "senden nicht möglich: nutzer blockiert.";
"system.dm.blocked_recipient" = "senden an %@ nicht möglich: nutzer blockiert.";
"system.dm.unreachable" = "senden an %@ nicht möglich: empfänger über mesh oder nostr nicht erreichbar.";
"system.geohash.blocked" = "%@ wurde in geohash-chats blockiert";
"system.geohash.unblocked" = "%@ wurde in geohash-chats entsperrt";
"system.location.not_in_channel" = "senden fehlgeschlagen: du bist nicht in einem standortkanal";
"system.location.send_failed" = "konnte nicht an den standortkanal senden";
"system.tor.dev_bypass" = "dev-build: tor-bypass aktiv.";
"system.tor.restarted" = "tor wurde neu gestartet. routing wiederhergestellt.";
"system.tor.restarting" = "tor startet neu, um die verbindung herzustellen...";
"system.tor.started" = "tor läuft. der gesamte chat wird über tor geleitet.";
"system.tor.starting" = "tor wird gestartet...";
"verification.my_qr.accessibility_label" = "verifizierungs-qr-code";
"verification.my_qr.title" = "scanne, um mich zu verifizieren";
"verification.my_qr.unavailable" = "qr nicht verfügbar";
"verification.scan.paste_prompt" = "füge den qr-inhalt zum prüfen ein:";
"verification.scan.prompt_friend" = "scanne den qr eines freundes";
"verification.scan.status.invalid" = "qr ungültig oder abgelaufen";
"verification.scan.status.no_peer" = "kein passender peer gefunden";
"verification.scan.status.requested" = "verifizierung für %@ angefordert";
"verification.scan.validate" = "prüfen";
"verification.sheet.title" = "VERIFIZIEREN";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d notiz</string>
<key>other</key>
<string>%d notizen</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d person</string>
<key>other</key>
<string>%d personen</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d person</string>
<key>other</key>
<string>%d personen</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Spanish)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "cerrar";
"app_info.done" = "LISTO";
"app_info.features.encryption.description" = "mensajes privados cifrados con el protocolo Noise";
"app_info.features.encryption.title" = "cifrado de extremo a extremo";
"app_info.features.extended_range.description" = "los mensajes se retransmiten entre pares y llegan lejos";
"app_info.features.extended_range.title" = "alcance ampliado";
"app_info.features.favorites.description" = "recibe avisos cuando tus personas favoritas se conecten";
"app_info.features.favorites.title" = "favoritos";
"app_info.features.geohash.description" = "canales geohash para chatear con personas en regiones cercanas a través de relays descentralizados anónimos";
"app_info.features.geohash.title" = "canales locales";
"app_info.features.mentions.description" = "usa @nickname para avisar a personas concretas";
"app_info.features.mentions.title" = "menciones";
"app_info.features.offline.description" = "funciona sin internet utilizando Bluetooth de bajo consumo";
"app_info.features.offline.title" = "comunicación sin conexión";
"app_info.features.title" = "FUNCIONES";
"app_info.how_to_use.change_channels" = "• toca #mesh para cambiar de canal";
"app_info.how_to_use.clear_chat" = "• toca tres veces el chat para limpiarlo";
"app_info.how_to_use.commands" = "• escribe / para ver los comandos";
"app_info.how_to_use.open_sidebar" = "• toca el ícono de personas para abrir la barra lateral";
"app_info.how_to_use.set_nickname" = "• define tu apodo tocándolo";
"app_info.how_to_use.start_dm" = "• toca el nombre de un participante para iniciar un MD";
"app_info.how_to_use.title" = "CÓMO USARLO";
"app_info.privacy.ephemeral.description" = "nuevo ID de peer generado periódicamente";
"app_info.privacy.ephemeral.title" = "identidad efímera";
"app_info.privacy.no_tracking.description" = "sin servidores, cuentas ni recopilación de datos";
"app_info.privacy.no_tracking.title" = "sin seguimiento";
"app_info.privacy.panic.description" = "toca el logotipo tres veces para borrar todos los datos al instante";
"app_info.privacy.panic.title" = "modo pánico";
"app_info.privacy.title" = "PRIVACIDAD";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "la seguridad de los mensajes privados aún no ha sido auditada por completo. no lo uses en situaciones críticas hasta que este aviso desaparezca.";
"app_info.warning.title" = "ADVERTENCIA";
"common.cancel" = "cancelar";
"common.close" = "cerrar";
"common.copy" = "copiar";
"common.ok" = "aceptar";
"common.toggle.off" = "desactivado";
"common.toggle.on" = "activado";
"common.unknown" = "desconocido";
"content.accessibility.add_favorite" = "agregar a favoritos";
"content.accessibility.available_nostr" = "disponible vía Nostr";
"content.accessibility.back_to_main_chat" = "volver al chat principal";
"content.accessibility.connected_mesh" = "conectado por mesh";
"content.accessibility.encryption_status" = "estado de cifrado: %@";
"content.accessibility.location_channels" = "canales de ubicación";
"content.accessibility.location_notes" = "notas de ubicación de este lugar";
"content.accessibility.open_unread_private_chat" = "abrir chat privado sin leer";
"content.accessibility.private_chat_header" = "chat privado con %@";
"content.accessibility.reachable_mesh" = "disponible por mesh";
"content.accessibility.remove_favorite" = "quitar de favoritos";
"content.accessibility.send_hint_empty" = "introduce un mensaje para enviarlo";
"content.accessibility.send_hint_ready" = "toca dos veces para enviar";
"content.accessibility.send_message" = "enviar mensaje";
"content.accessibility.toggle_bookmark" = "alternar marcador para #%@";
"content.accessibility.toggle_favorite_hint" = "toca dos veces para alternar el estado de favorito";
"content.accessibility.view_fingerprint_hint" = "toca para ver la huella de cifrado";
"content.actions.block" = "bloquear";
"content.actions.direct_message" = "mensaje directo";
"content.actions.hug" = "abrazo";
"content.actions.mention" = "mencionar";
"content.actions.slap" = "bofetada";
"content.actions.title" = "acciones";
"content.alert.bluetooth_required.off" = "bluetooth está desactivado. Actívalo en Ajustes para usar BitChat.";
"content.alert.bluetooth_required.permission" = "bitChat necesita permiso de Bluetooth para conectarse con dispositivos cercanos. Habilita el acceso en Ajustes.";
"content.alert.bluetooth_required.settings" = "ajustes";
"content.alert.bluetooth_required.title" = "se requiere Bluetooth";
"content.alert.bluetooth_required.unsupported" = "este dispositivo no admite Bluetooth. BitChat necesita Bluetooth para funcionar.";
"content.alert.screenshot.message" = "las capturas de pantalla de los canales de ubicación revelarán tu ubicación. Piensa antes de compartirlas públicamente.";
"content.alert.screenshot.title" = "atención";
"content.commands.block" = "bloquear o listar usuarios bloqueados";
"content.commands.clear" = "borrar los mensajes del chat";
"content.commands.favorite" = "agregar a favoritos";
"content.commands.hug" = "enviar un abrazo caluroso";
"content.commands.message" = "enviar mensaje privado";
"content.commands.slap" = "abofetear a alguien con una trucha";
"content.commands.unblock" = "desbloquear a un usuario";
"content.commands.unfavorite" = "quitar de favoritos";
"content.commands.who" = "ver quién está en línea";
"content.delivery.delivered_members" = "entregado a %1$d de %2$d miembros";
"content.delivery.delivered_to" = "entregado a %@";
"content.delivery.failed" = "falló: %@";
"content.delivery.read_by" = "leído por %@";
"content.delivery.reason.blocked" = "el usuario está bloqueado";
"content.delivery.reason.self" = "no puedes enviarte mensajes a ti mismo";
"content.delivery.reason.send_error" = "error al enviar";
"content.delivery.reason.unknown_recipient" = "destinatario desconocido";
"content.delivery.reason.unreachable" = "el destinatario no es alcanzable";
"content.header.people" = "PERSONAS";
"content.help.verification" = "verificación: mostrar mi QR o escanear a un amigo";
"content.input.message_placeholder" = "escribe un mensaje...";
"content.input.nickname_placeholder" = "apodo";
"content.location.enable" = "activar ubicación";
"content.message.copy" = "copiar mensaje";
"content.message.show_less" = "mostrar menos";
"content.message.show_more" = "mostrar más";
"content.notes.location_unavailable" = "ubicación no disponible";
"content.notes.title" = "notas";
"content.payment.cashu" = "pagar con Cashu";
"content.payment.lightning" = "pagar con Lightning";
"encryption.accessibility.establishing" = "estableciendo cifrado";
"encryption.accessibility.failed" = "cifrado fallido";
"encryption.accessibility.not_encrypted" = "sin cifrar";
"encryption.accessibility.secured" = "cifrado";
"encryption.accessibility.verified" = "cifrado y verificado";
"encryption.status.establishing" = "estableciendo cifrado...";
"encryption.status.failed" = "cifrado fallido";
"encryption.status.not_encrypted" = "sin cifrar";
"encryption.status.secured" = "cifrado";
"encryption.status.verified" = "cifrado y verificado";
"fingerprint.action.mark_verified" = "marcar como verificado";
"fingerprint.action.remove_verification" = "eliminar verificación";
"fingerprint.badge.not_verified" = "⚠️ NO VERIFICADO";
"fingerprint.badge.verified" = "✓ VERIFICADO";
"fingerprint.handshake_pending" = "no disponible: el handshake está en curso";
"fingerprint.message.verified" = "has verificado la identidad de esta persona.";
"fingerprint.message.verify_hint" = "compara estas huellas con %@ mediante un canal seguro.";
"fingerprint.their_label" = "huella de la otra persona:";
"fingerprint.title" = "verificación de seguridad";
"fingerprint.your_label" = "tu huella:";
"geohash_people.action.block" = "bloquear";
"geohash_people.action.unblock" = "desbloquear";
"geohash_people.none_nearby" = "nadie cerca...";
"geohash_people.tooltip.blocked" = "bloqueado en geohash";
"geohash_people.you_suffix" = " (tú)";
"location_channels.action.open_settings" = "abrir ajustes";
"location_channels.action.remove_access" = "eliminar acceso a la ubicación";
"location_channels.action.request_permissions" = "obtener mi ubicación y mis geohashes";
"location_channels.action.teleport" = "teletransportar";
"location_channels.bookmarked_section_title" = "marcados";
"location_channels.description" = "chatea con personas cercanas usando canales geohash. Solo se comparte un geohash aproximado, nunca GPS exacto. Tu IP se oculta al enrutar todo el tráfico por Tor.";
"location_channels.error.invalid_geohash" = "geohash no válido";
"location_channels.loading_nearby" = "buscando canales cercanos…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "permiso de ubicación denegado. Actívalo en Ajustes para usar los canales de ubicación.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#canales de ubicación";
"location_channels.tor.subtitle" = "oculta tu IP para los canales de ubicación. Recomendado: activado.";
"location_channels.tor.title" = "enrutamiento Tor";
"location_levels.block" = "bloque";
"location_levels.building" = "edificio";
"location_levels.city" = "ciudad";
"location_levels.neighborhood" = "barrio";
"location_levels.province" = "provincia";
"location_levels.region" = "región";
"location_notes.action.dismiss" = "descartar";
"location_notes.action.retry" = "reintentar";
"location_notes.description" = "añade notas permanentes cortas sobre este lugar para que otras personas las encuentren.";
"location_notes.empty_subtitle" = "sé la primera persona en añadir una en este lugar.";
"location_notes.empty_title" = "aún no hay notas";
"location_notes.error.failed_to_send" = "no se pudo enviar la nota. %@";
"location_notes.error.no_relays" = "no hay relays geográficos disponibles cerca de este lugar. Inténtalo de nuevo pronto.";
"location_notes.loading_notes" = "cargando notas…";
"location_notes.loading_recent" = "cargando notas recientes…";
"location_notes.no_relays_nearby" = "no hay relays geográficos cercanos";
"location_notes.placeholder" = "añade una nota para este lugar";
"location_notes.relays_paused" = "relays geográficos no disponibles; notas en pausa";
"location_notes.relays_retry_hint" = "las notas dependen de los relays geográficos. Comprueba la conexión e inténtalo de nuevo.";
"mesh_peers.tooltip.new_messages" = "nuevos mensajes";
"system.chat.blocked" = "no se puede iniciar un chat con %@: el usuario está bloqueado.";
"system.chat.requires_favorite" = "no se puede iniciar un chat con %@: necesitas ser favoritos mutuos para mensajería sin conexión.";
"system.common.user" = "usuario";
"system.dm.blocked_generic" = "no se puede enviar el mensaje: el usuario está bloqueado.";
"system.dm.blocked_recipient" = "no se puede enviar un mensaje a %@: el usuario está bloqueado.";
"system.dm.unreachable" = "no se puede enviar un mensaje a %@: el destinatario no es alcanzable por mesh ni Nostr.";
"system.geohash.blocked" = "se bloqueó a %@ en los chats geohash";
"system.geohash.unblocked" = "se desbloqueó a %@ en los chats geohash";
"system.location.not_in_channel" = "no se puede enviar: no estás en un canal de ubicación";
"system.location.send_failed" = "no se pudo enviar al canal de ubicación";
"system.tor.dev_bypass" = "compilación de desarrollo: bypass de Tor activado.";
"system.tor.restarted" = "tor se reinició. Se restauró el enrutamiento de la red.";
"system.tor.restarting" = "tor se está reiniciando para recuperar la conectividad...";
"system.tor.started" = "tor se inició. Todo el chat se enruta por Tor para privacidad.";
"system.tor.starting" = "iniciando Tor...";
"verification.my_qr.accessibility_label" = "código QR de verificación";
"verification.my_qr.title" = "escanea para verificarme";
"verification.my_qr.unavailable" = "QR no disponible";
"verification.scan.paste_prompt" = "pega el contenido del QR para validarlo:";
"verification.scan.prompt_friend" = "escanea el QR de un amigo";
"verification.scan.status.invalid" = "QR inválido o caducado";
"verification.scan.status.no_peer" = "no se encontró un peer coincidente";
"verification.scan.status.requested" = "se solicitó la verificación de %@";
"verification.scan.validate" = "validar";
"verification.sheet.title" = "VERIFICAR";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d nota</string>
<key>other</key>
<string>%d notas</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d persona</string>
<key>other</key>
<string>%d personas</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d persona</string>
<key>other</key>
<string>%d personas</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (French)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "fermer";
"app_info.done" = "TERMINÉ";
"app_info.features.encryption.description" = "messages privés chiffrés avec le protocole noise";
"app_info.features.encryption.title" = "chiffrement de bout en bout";
"app_info.features.extended_range.description" = "messages relayés entre pairs pour aller plus loin";
"app_info.features.extended_range.title" = "portée étendue";
"app_info.features.favorites.description" = "reçois une alerte quand tes personnes favorites arrivent";
"app_info.features.favorites.title" = "favoris";
"app_info.features.geohash.description" = "canaux geohash pour discuter avec des personnes proches via des relais décentralisés anonymes";
"app_info.features.geohash.title" = "canaux locaux";
"app_info.features.mentions.description" = "utilise @nickname pour avertir des personnes précises";
"app_info.features.mentions.title" = "mentions";
"app_info.features.offline.description" = "fonctionne sans internet avec le bluetooth basse énergie";
"app_info.features.offline.title" = "communication hors ligne";
"app_info.features.title" = "FONCTIONNALITÉS";
"app_info.how_to_use.change_channels" = "• tape sur #mesh pour changer de canal";
"app_info.how_to_use.clear_chat" = "• tape trois fois sur le chat pour le vider";
"app_info.how_to_use.commands" = "• tape / pour voir les commandes";
"app_info.how_to_use.open_sidebar" = "• tape sur l'icône personnes pour ouvrir la barre latérale";
"app_info.how_to_use.set_nickname" = "• règle ton pseudo en le touchant";
"app_info.how_to_use.start_dm" = "• tape sur le nom d'un pair pour démarrer un mp";
"app_info.how_to_use.title" = "MODE D'EMPLOI";
"app_info.privacy.ephemeral.description" = "nouvel id de pair généré régulièrement";
"app_info.privacy.ephemeral.title" = "identité éphémère";
"app_info.privacy.no_tracking.description" = "sans serveurs, comptes ni collecte de données";
"app_info.privacy.no_tracking.title" = "sans suivi";
"app_info.privacy.panic.description" = "tape trois fois sur le logo pour tout effacer instantanément";
"app_info.privacy.panic.title" = "mode panique";
"app_info.privacy.title" = "CONFIDENTIALITÉ";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "la sécurité des messages privés n'a pas encore été entièrement auditée. n'utilise pas pour des situations critiques tant que cet avertissement reste.";
"app_info.warning.title" = "AVERTISSEMENT";
"common.cancel" = "annuler";
"common.close" = "fermer";
"common.copy" = "copier";
"common.ok" = "OK";
"common.toggle.off" = "désactivé";
"common.toggle.on" = "activé";
"common.unknown" = "inconnu";
"content.accessibility.add_favorite" = "ajouter aux favoris";
"content.accessibility.available_nostr" = "disponible via nostr";
"content.accessibility.back_to_main_chat" = "retour au chat principal";
"content.accessibility.connected_mesh" = "connecté via mesh";
"content.accessibility.encryption_status" = "état du chiffrement : %@";
"content.accessibility.location_channels" = "canaux de localisation";
"content.accessibility.location_notes" = "notes de localisation pour cet endroit";
"content.accessibility.open_unread_private_chat" = "ouvrir le chat privé non lu";
"content.accessibility.private_chat_header" = "chat privé avec %@";
"content.accessibility.reachable_mesh" = "joignable via mesh";
"content.accessibility.remove_favorite" = "retirer des favoris";
"content.accessibility.send_hint_empty" = "saisis un message à envoyer";
"content.accessibility.send_hint_ready" = "tape deux fois pour envoyer";
"content.accessibility.send_message" = "envoyer le message";
"content.accessibility.toggle_bookmark" = "basculer le favori pour #%@";
"content.accessibility.toggle_favorite_hint" = "tape deux fois pour basculer le statut favori";
"content.accessibility.view_fingerprint_hint" = "tape pour voir l'empreinte de chiffrement";
"content.actions.block" = "bloquer";
"content.actions.direct_message" = "message direct";
"content.actions.hug" = "câlin";
"content.actions.mention" = "mentionner";
"content.actions.slap" = "gifle";
"content.actions.title" = "actions";
"content.alert.bluetooth_required.off" = "bluetooth est désactivé. active le bluetooth dans réglages pour utiliser bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat a besoin de l'autorisation bluetooth pour se connecter aux appareils proches. active l'accès dans réglages.";
"content.alert.bluetooth_required.settings" = "réglages";
"content.alert.bluetooth_required.title" = "bluetooth requis";
"content.alert.bluetooth_required.unsupported" = "cet appareil ne prend pas en charge le bluetooth. bitchat en a besoin pour fonctionner.";
"content.alert.screenshot.message" = "les captures des canaux de localisation révéleront ta position. réfléchis avant de partager publiquement.";
"content.alert.screenshot.title" = "attention";
"content.commands.block" = "bloquer ou lister les pairs bloqués";
"content.commands.clear" = "effacer les messages du chat";
"content.commands.favorite" = "ajouter aux favoris";
"content.commands.hug" = "envoyer un câlin chaleureux";
"content.commands.message" = "envoyer un message privé";
"content.commands.slap" = "gifler quelqu'un avec une truite";
"content.commands.unblock" = "débloquer un pair";
"content.commands.unfavorite" = "retirer des favoris";
"content.commands.who" = "voir qui est en ligne";
"content.delivery.delivered_members" = "livré à %1$d sur %2$d membres";
"content.delivery.delivered_to" = "livré à %@";
"content.delivery.failed" = "échec : %@";
"content.delivery.read_by" = "lu par %@";
"content.delivery.reason.blocked" = "utilisateur bloqué";
"content.delivery.reason.self" = "impossible d'envoyer à toi-même";
"content.delivery.reason.send_error" = "erreur d'envoi";
"content.delivery.reason.unknown_recipient" = "destinataire inconnu";
"content.delivery.reason.unreachable" = "pair injoignable";
"content.header.people" = "PERSONNES";
"content.help.verification" = "vérification : afficher mon qr ou scanner un ami";
"content.input.message_placeholder" = "écris un message...";
"content.input.nickname_placeholder" = "pseudo";
"content.location.enable" = "activer la localisation";
"content.message.copy" = "copier le message";
"content.message.show_less" = "afficher moins";
"content.message.show_more" = "afficher plus";
"content.notes.location_unavailable" = "localisation indisponible";
"content.notes.title" = "notes";
"content.payment.cashu" = "payer via cashu";
"content.payment.lightning" = "payer via lightning";
"encryption.accessibility.establishing" = "établissement du chiffrement";
"encryption.accessibility.failed" = "chiffrement échoué";
"encryption.accessibility.not_encrypted" = "non chiffré";
"encryption.accessibility.secured" = "chiffré";
"encryption.accessibility.verified" = "chiffré et vérifié";
"encryption.status.establishing" = "mise en place du chiffrement...";
"encryption.status.failed" = "chiffrement échoué";
"encryption.status.not_encrypted" = "non chiffré";
"encryption.status.secured" = "chiffré";
"encryption.status.verified" = "chiffré et vérifié";
"fingerprint.action.mark_verified" = "marquer comme vérifié";
"fingerprint.action.remove_verification" = "retirer la vérification";
"fingerprint.badge.not_verified" = "⚠️ NON VÉRIFIÉ";
"fingerprint.badge.verified" = "✓ VÉRIFIÉ";
"fingerprint.handshake_pending" = "indisponible - handshake en cours";
"fingerprint.message.verified" = "tu as vérifié l'identité de cette personne.";
"fingerprint.message.verify_hint" = "compare ces empreintes avec %@ via un canal sécurisé.";
"fingerprint.their_label" = "leur empreinte :";
"fingerprint.title" = "vérification de sécurité";
"fingerprint.your_label" = "ton empreinte :";
"geohash_people.action.block" = "bloquer";
"geohash_people.action.unblock" = "débloquer";
"geohash_people.none_nearby" = "personne à proximité...";
"geohash_people.tooltip.blocked" = "bloqué dans geohash";
"geohash_people.you_suffix" = " (toi)";
"location_channels.action.open_settings" = "ouvrir réglages";
"location_channels.action.remove_access" = "retirer l'accès localisation";
"location_channels.action.request_permissions" = "obtenir ma localisation et mes geohash";
"location_channels.action.teleport" = "téléporter";
"location_channels.bookmarked_section_title" = "enregistrés";
"location_channels.description" = "discute avec les personnes proches grâce aux canaux geohash. seul un geohash grossier est partagé, jamais de gps exact. ton ip reste cachée car tout le trafic passe par tor.";
"location_channels.error.invalid_geohash" = "geohash invalide";
"location_channels.loading_nearby" = "recherche de canaux proches…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "autorisation de localisation refusée. active-la dans réglages pour utiliser les canaux.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#canaux localisation";
"location_channels.tor.subtitle" = "cache ton ip pour les canaux localisation. recommandé : activé.";
"location_channels.tor.title" = "routage tor";
"location_levels.block" = "bloc";
"location_levels.building" = "bâtiment";
"location_levels.city" = "ville";
"location_levels.neighborhood" = "quartier";
"location_levels.province" = "province";
"location_levels.region" = "région";
"location_notes.action.dismiss" = "ignorer";
"location_notes.action.retry" = "réessayer";
"location_notes.description" = "ajoute de courtes notes permanentes ici pour aider les autres.";
"location_notes.empty_subtitle" = "sois la première personne à en ajouter ici.";
"location_notes.empty_title" = "pas encore de notes";
"location_notes.error.failed_to_send" = "impossible d'envoyer la note. %@";
"location_notes.error.no_relays" = "aucun relais géo disponible près d'ici. réessaie bientôt.";
"location_notes.loading_notes" = "chargement des notes…";
"location_notes.loading_recent" = "chargement des notes récentes…";
"location_notes.no_relays_nearby" = "aucun relais géo à proximité";
"location_notes.placeholder" = "ajoute une note pour cet endroit";
"location_notes.relays_paused" = "relais géo indisponibles ; notes en pause";
"location_notes.relays_retry_hint" = "les notes dépendent des relais géo. vérifie la connexion et réessaie.";
"mesh_peers.tooltip.new_messages" = "nouveaux messages";
"system.chat.blocked" = "impossible de démarrer un chat avec %@ : utilisateur bloqué.";
"system.chat.requires_favorite" = "impossible de démarrer un chat avec %@ : favoris mutuels requis pour le hors ligne.";
"system.common.user" = "utilisateur";
"system.dm.blocked_generic" = "envoi impossible : utilisateur bloqué.";
"system.dm.blocked_recipient" = "impossible d'envoyer à %@ : utilisateur bloqué.";
"system.dm.unreachable" = "impossible d'envoyer à %@ : destinataire injoignable via mesh ou nostr.";
"system.geohash.blocked" = "%@ a été bloqué dans les chats geohash";
"system.geohash.unblocked" = "%@ a été débloqué dans les chats geohash";
"system.location.not_in_channel" = "envoi impossible : tu n'es pas dans un canal localisation";
"system.location.send_failed" = "envoi au canal localisation impossible";
"system.tor.dev_bypass" = "build de développement : bypass tor actif.";
"system.tor.restarted" = "tor a redémarré. routage restauré.";
"system.tor.restarting" = "tor redémarre pour rétablir la connectivité...";
"system.tor.started" = "tor a démarré. tout le chat passe par tor pour la confidentialité.";
"system.tor.starting" = "lancement de tor...";
"verification.my_qr.accessibility_label" = "code qr de vérification";
"verification.my_qr.title" = "scanne pour me vérifier";
"verification.my_qr.unavailable" = "qr indisponible";
"verification.scan.paste_prompt" = "colle le contenu du qr pour valider :";
"verification.scan.prompt_friend" = "scanne le qr d'un ami";
"verification.scan.status.invalid" = "qr invalide ou expiré";
"verification.scan.status.no_peer" = "aucun pair correspondant trouvé";
"verification.scan.status.requested" = "vérification demandée pour %@";
"verification.scan.validate" = "valider";
"verification.sheet.title" = "VÉRIFIER";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d note</string>
<key>other</key>
<string>%d notes</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d personne</string>
<key>other</key>
<string>%d personnes</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d personne</string>
<key>other</key>
<string>%d personnes</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Hebrew)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "סגור";
"app_info.done" = "בוצע";
"app_info.features.encryption.description" = "הודעות פרטיות מוצפנות בפרוטוקול noise";
"app_info.features.encryption.title" = "הצפנה מקצה לקצה";
"app_info.features.extended_range.description" = "הודעות משודרות בין עמיתים ומגיעות רחוק יותר";
"app_info.features.extended_range.title" = "טווח מורחב";
"app_info.features.favorites.description" = "קבל התראות כשהאנשים המועדפים שלך מצטרפים";
"app_info.features.favorites.title" = "מועדפים";
"app_info.features.geohash.description" = "ערוצי geohash לשיחה עם אנשים קרובים דרך ממסרים אנונימיים מבוזרים";
"app_info.features.geohash.title" = "ערוצים מקומיים";
"app_info.features.mentions.description" = "השתמש ב-@nickname כדי להתריע לאנשים ספציפיים";
"app_info.features.mentions.title" = "אזכורים";
"app_info.features.offline.description" = "עובד בלי אינטרנט באמצעות bluetooth בתצריכת אנרגיה נמוכה";
"app_info.features.offline.title" = "תקשורת לא מקוונת";
"app_info.features.title" = "יכולות";
"app_info.how_to_use.change_channels" = "• הקש על #mesh כדי להחליף ערוץ";
"app_info.how_to_use.clear_chat" = "• הקש שלוש פעמים על הצ'אט כדי לנקות";
"app_info.how_to_use.commands" = "• הקלד / כדי לראות פקודות";
"app_info.how_to_use.open_sidebar" = "• הקש על אייקון האנשים כדי לפתוח סרגל צד";
"app_info.how_to_use.set_nickname" = "• הקש על הכינוי שלך כדי לעדכן";
"app_info.how_to_use.start_dm" = "• הקש על שם עמית כדי להתחיל הודעה פרטית";
"app_info.how_to_use.title" = "איך להשתמש";
"app_info.privacy.ephemeral.description" = "מזהה עמית חדש נוצר באופן קבוע";
"app_info.privacy.ephemeral.title" = "זהות זמנית";
"app_info.privacy.no_tracking.description" = "אין שרתים, חשבונות או איסוף נתונים";
"app_info.privacy.no_tracking.title" = "ללא מעקב";
"app_info.privacy.panic.description" = "הקש על הלוגו שלוש פעמים למחיקת כל הנתונים מייד";
"app_info.privacy.panic.title" = "מצב בהלה";
"app_info.privacy.title" = "פרטיות";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "אבטחת ההודעות הפרטיות עדיין לא נבדקה במלואה. אל תשתמש למצבים קריטיים עד שהאזהרה תיעלם.";
"app_info.warning.title" = "אזהרה";
"common.cancel" = "ביטול";
"common.close" = "סגור";
"common.copy" = "העתק";
"common.ok" = "OK";
"common.toggle.off" = "כבוי";
"common.toggle.on" = "פעיל";
"common.unknown" = "לא ידוע";
"content.accessibility.add_favorite" = "הוסף למועדפים";
"content.accessibility.available_nostr" = "זמין דרך nostr";
"content.accessibility.back_to_main_chat" = "חזרה לצ'אט הראשי";
"content.accessibility.connected_mesh" = "מחובר דרך mesh";
"content.accessibility.encryption_status" = "מצב הצפנה: %@";
"content.accessibility.location_channels" = "ערוצי מיקום";
"content.accessibility.location_notes" = "הערות מיקום למקום הזה";
"content.accessibility.open_unread_private_chat" = "פתח צ'אט פרטי שלא נקרא";
"content.accessibility.private_chat_header" = "צ'אט פרטי עם %@";
"content.accessibility.reachable_mesh" = "זמין דרך mesh";
"content.accessibility.remove_favorite" = "הסר מהמועדפים";
"content.accessibility.send_hint_empty" = "הזן הודעה לשליחה";
"content.accessibility.send_hint_ready" = "הקש פעמיים לשליחה";
"content.accessibility.send_message" = "שלח הודעה";
"content.accessibility.toggle_bookmark" = "החלף סימנייה עבור #%@";
"content.accessibility.toggle_favorite_hint" = "הקש פעמיים כדי להחליף מצב מועדפים";
"content.accessibility.view_fingerprint_hint" = "הקש להצגת טביעת ההצפנה";
"content.actions.block" = "חסום";
"content.actions.direct_message" = "הודעה ישירה";
"content.actions.hug" = "חיבוק";
"content.actions.mention" = "אזכור";
"content.actions.slap" = "סטירה";
"content.actions.title" = "פעולות";
"content.alert.bluetooth_required.off" = "bluetooth כבוי. הפעל bluetooth בהגדרות כדי להשתמש ב-bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat צריכה הרשאת bluetooth כדי להתחבר למכשירים קרובים. אפשר גישה בהגדרות.";
"content.alert.bluetooth_required.settings" = "הגדרות";
"content.alert.bluetooth_required.title" = "נדרש bluetooth";
"content.alert.bluetooth_required.unsupported" = "המכשיר הזה לא תומך ב-bluetooth. bitchat זקוקה ל-bluetooth כדי לעבוד.";
"content.alert.screenshot.message" = "צילומי מסך של ערוצי מיקום יחשפו את מיקומך. חשב לפני שיתוף פומבי.";
"content.alert.screenshot.title" = "שים לב";
"content.commands.block" = "חסום או הצג עמיתים חסומים";
"content.commands.clear" = "נקה הודעות צ'אט";
"content.commands.favorite" = "הוסף למועדפים";
"content.commands.hug" = "שלח חיבוק חם";
"content.commands.message" = "שלח הודעה פרטית";
"content.commands.slap" = "תן למישהו סטירת פורל";
"content.commands.unblock" = "בטל חסימה לעמית";
"content.commands.unfavorite" = "הסר מהמועדפים";
"content.commands.who" = "ראה מי מחובר";
"content.delivery.delivered_members" = "נמסר ל-%1$d מתוך %2$d חברים";
"content.delivery.delivered_to" = "נמסר ל-%@";
"content.delivery.failed" = "נכשל: %@";
"content.delivery.read_by" = "נקרא על ידי %@";
"content.delivery.reason.blocked" = "המשתמש חסום";
"content.delivery.reason.self" = "אי אפשר לשלוח לעצמך";
"content.delivery.reason.send_error" = "שגיאת שליחה";
"content.delivery.reason.unknown_recipient" = "נמען לא ידוע";
"content.delivery.reason.unreachable" = "עמית לא זמין";
"content.header.people" = "אנשים";
"content.help.verification" = "אימות: הצג את ה-qr שלי או סרוק חבר";
"content.input.message_placeholder" = "כתוב הודעה...";
"content.input.nickname_placeholder" = "כינוי";
"content.location.enable" = "הפעל מיקום";
"content.message.copy" = "העתק הודעה";
"content.message.show_less" = "הצג פחות";
"content.message.show_more" = "הצג עוד";
"content.notes.location_unavailable" = "המיקום לא זמין";
"content.notes.title" = "הערות";
"content.payment.cashu" = "תשלום דרך cashu";
"content.payment.lightning" = "תשלום דרך lightning";
"encryption.accessibility.establishing" = "הצפנה בהקמה";
"encryption.accessibility.failed" = "הצפנה נכשלה";
"encryption.accessibility.not_encrypted" = "לא מוצפן";
"encryption.accessibility.secured" = "מוצפן";
"encryption.accessibility.verified" = "מוצפן ומאומת";
"encryption.status.establishing" = "מקימים הצפנה...";
"encryption.status.failed" = "הצפנה נכשלה";
"encryption.status.not_encrypted" = "לא מוצפן";
"encryption.status.secured" = "מוצפן";
"encryption.status.verified" = "מוצפן ומאומת";
"fingerprint.action.mark_verified" = "סמן כמאומת";
"fingerprint.action.remove_verification" = "הסר אימות";
"fingerprint.badge.not_verified" = "⚠️ לא מאומת";
"fingerprint.badge.verified" = "✓ מאומת";
"fingerprint.handshake_pending" = "לא זמין - handshake מתבצע";
"fingerprint.message.verified" = "אישרת את זהותו של האדם הזה.";
"fingerprint.message.verify_hint" = "השווה את הטביעות עם %@ בערוץ מאובטח.";
"fingerprint.their_label" = "הטבעת שלהם:";
"fingerprint.title" = "אימות אבטחה";
"fingerprint.your_label" = "הטבעת שלך:";
"geohash_people.action.block" = "חסום";
"geohash_people.action.unblock" = "בטל חסימה";
"geohash_people.none_nearby" = "אין אף אחד בסביבה...";
"geohash_people.tooltip.blocked" = "חסום ב-geohash";
"geohash_people.you_suffix" = " (אתה)";
"location_channels.action.open_settings" = "פתח הגדרות";
"location_channels.action.remove_access" = "הסר גישת מיקום";
"location_channels.action.request_permissions" = "קבל את המיקום וה-geohash שלי";
"location_channels.action.teleport" = "טלפורט";
"location_channels.bookmarked_section_title" = "שמורים";
"location_channels.description" = "שוחח עם אנשים קרובים בערוצי geohash. משתף רק geohash גס, אף פעם לא gps מדויק. כתובת ה-ip מוסתרת כי כל התעבורה עוברת דרך tor.";
"location_channels.error.invalid_geohash" = "geohash לא תקף";
"location_channels.loading_nearby" = "מחפש ערוצים קרובים…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "הרשאת מיקום נדחתה. אפשר בהגדרות כדי להשתמש בערוצי מיקום.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#ערוצי מיקום";
"location_channels.tor.subtitle" = "מסתיר את ה-ip שלך לערוצי מיקום. מומלץ: פעיל.";
"location_channels.tor.title" = "ניתוב tor";
"location_levels.block" = "בלוק";
"location_levels.building" = "מבנה";
"location_levels.city" = "עיר";
"location_levels.neighborhood" = "שכונה";
"location_levels.province" = "מחוז";
"location_levels.region" = "אזור";
"location_notes.action.dismiss" = "סגור";
"location_notes.action.retry" = "ניסיון שוב";
"location_notes.description" = "הוסף הערות קצרות וקבועות למקום הזה כדי שאחרים ימצאו.";
"location_notes.empty_subtitle" = "היה הראשון להוסיף כאן.";
"location_notes.empty_title" = "אין הערות עדיין";
"location_notes.error.failed_to_send" = "לא ניתן לשלוח את ההערה. %@";
"location_notes.error.no_relays" = "אין ממסרי geo זמינים בקרבת מקום. נסה שוב מאוחר יותר.";
"location_notes.loading_notes" = "טוען הערות…";
"location_notes.loading_recent" = "טוען הערות אחרונות…";
"location_notes.no_relays_nearby" = "אין ממסרי geo קרובים";
"location_notes.placeholder" = "הוסף הערה למקום הזה";
"location_notes.relays_paused" = "ממסרי geo אינם זמינים; הערות הושהו";
"location_notes.relays_retry_hint" = "הערות תלויות בממסרי geo. בדוק את החיבור ונסה שוב.";
"mesh_peers.tooltip.new_messages" = "הודעות חדשות";
"system.chat.blocked" = "לא ניתן להתחיל צ'אט עם %@: המשתמש חסום.";
"system.chat.requires_favorite" = "לא ניתן להתחיל צ'אט עם %@: נדרשים מועדפים הדדיים לאופליין.";
"system.common.user" = "משתמש";
"system.dm.blocked_generic" = "אי אפשר לשלוח: המשתמש חסום.";
"system.dm.blocked_recipient" = "אי אפשר לשלוח ל-%@: המשתמש חסום.";
"system.dm.unreachable" = "אי אפשר לשלוח ל-%@: הנמען אינו נגיש דרך mesh או nostr.";
"system.geohash.blocked" = "%@ נחסם בצ'אטי geohash";
"system.geohash.unblocked" = "%@ הוסר מהחסימה בצ'אטי geohash";
"system.location.not_in_channel" = "אי אפשר לשלוח: אינך בערוץ מיקום";
"system.location.send_failed" = "השליחה לערוץ המיקום נכשלה";
"system.tor.dev_bypass" = "בנייה לפיתוח: עקיפת tor פעילה.";
"system.tor.restarted" = "tor הופעל מחדש. הניתוב שוחזר.";
"system.tor.restarting" = "tor מופעל מחדש להשבת החיבור...";
"system.tor.started" = "tor פעיל. כל הצ'אט עובר דרך tor לפרטיות.";
"system.tor.starting" = "tor מופעל...";
"verification.my_qr.accessibility_label" = "קוד qr לאימות";
"verification.my_qr.title" = "סרוק כדי לאמת";
"verification.my_qr.unavailable" = "qr לא זמין";
"verification.scan.paste_prompt" = "הדבק תוכן qr לאימות:";
"verification.scan.prompt_friend" = "סרוק qr של חבר";
"verification.scan.status.invalid" = "qr לא תקף או שפג תוקפו";
"verification.scan.status.no_peer" = "לא נמצא עמית תואם";
"verification.scan.status.requested" = "התבקש אימות עבור %@";
"verification.scan.validate" = "אשר";
"verification.sheet.title" = "אימות";
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d הערה</string>
<key>two</key>
<string>%d הערות</string>
<key>many</key>
<string>%d הערות</string>
<key>other</key>
<string>%d הערות</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d אדם</string>
<key>two</key>
<string>%d אנשים</string>
<key>many</key>
<string>%d אנשים</string>
<key>other</key>
<string>%d אנשים</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d אדם</string>
<key>two</key>
<string>%d אנשים</string>
<key>many</key>
<string>%d אנשים</string>
<key>other</key>
<string>%d אנשים</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Indonesian)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "tutup";
"app_info.done" = "SELESAI";
"app_info.features.encryption.description" = "pesan pribadi dienkripsi dengan protokol noise";
"app_info.features.encryption.title" = "enkripsi ujung ke ujung";
"app_info.features.extended_range.description" = "pesan diteruskan antar peer sehingga jangkauannya lebih jauh";
"app_info.features.extended_range.title" = "jangkauan diperluas";
"app_info.features.favorites.description" = "dapatkan notifikasi saat orang favoritmu bergabung";
"app_info.features.favorites.title" = "favorit";
"app_info.features.geohash.description" = "kanal geohash untuk ngobrol dengan orang di wilayah sekitar lewat relay anonim terdesentralisasi";
"app_info.features.geohash.title" = "kanal lokal";
"app_info.features.mentions.description" = "pakai @nickname untuk memberi tahu orang tertentu";
"app_info.features.mentions.title" = "mention";
"app_info.features.offline.description" = "bekerja tanpa internet memakai bluetooth low energy";
"app_info.features.offline.title" = "komunikasi offline";
"app_info.features.title" = "FITUR";
"app_info.how_to_use.change_channels" = "• ketuk #mesh untuk ganti kanal";
"app_info.how_to_use.clear_chat" = "• ketuk chat tiga kali untuk menghapus";
"app_info.how_to_use.commands" = "• ketik / untuk melihat perintah";
"app_info.how_to_use.open_sidebar" = "• ketuk ikon orang untuk membuka sidebar";
"app_info.how_to_use.set_nickname" = "• atur nama panggilanmu dengan mengetuknya";
"app_info.how_to_use.start_dm" = "• ketuk nama peer untuk mulai dm";
"app_info.how_to_use.title" = "CARA PAKAI";
"app_info.privacy.ephemeral.description" = "id peer baru dibuat secara berkala";
"app_info.privacy.ephemeral.title" = "identitas sementara";
"app_info.privacy.no_tracking.description" = "tanpa server, akun, atau pengumpulan data";
"app_info.privacy.no_tracking.title" = "tanpa pelacakan";
"app_info.privacy.panic.description" = "ketuk logo tiga kali untuk langsung menghapus semua data";
"app_info.privacy.panic.title" = "mode panik";
"app_info.privacy.title" = "PRIVASI";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "keamanan pesan pribadi belum diaudit sepenuhnya. jangan dipakai untuk situasi kritis sampai peringatan ini hilang.";
"app_info.warning.title" = "PERINGATAN";
"common.cancel" = "batal";
"common.close" = "tutup";
"common.copy" = "salin";
"common.ok" = "OK";
"common.toggle.off" = "mati";
"common.toggle.on" = "nyala";
"common.unknown" = "tidak diketahui";
"content.accessibility.add_favorite" = "tambah ke favorit";
"content.accessibility.available_nostr" = "tersedia melalui nostr";
"content.accessibility.back_to_main_chat" = "kembali ke chat utama";
"content.accessibility.connected_mesh" = "terhubung lewat mesh";
"content.accessibility.encryption_status" = "status enkripsi: %@";
"content.accessibility.location_channels" = "kanal lokasi";
"content.accessibility.location_notes" = "catatan lokasi untuk tempat ini";
"content.accessibility.open_unread_private_chat" = "buka chat pribadi belum dibaca";
"content.accessibility.private_chat_header" = "chat pribadi dengan %@";
"content.accessibility.reachable_mesh" = "dapat dijangkau lewat mesh";
"content.accessibility.remove_favorite" = "hapus dari favorit";
"content.accessibility.send_hint_empty" = "masukkan pesan untuk dikirim";
"content.accessibility.send_hint_ready" = "ketuk dua kali untuk mengirim";
"content.accessibility.send_message" = "kirim pesan";
"content.accessibility.toggle_bookmark" = "ubah penanda untuk #%@";
"content.accessibility.toggle_favorite_hint" = "ketuk dua kali untuk mengubah status favorit";
"content.accessibility.view_fingerprint_hint" = "ketuk untuk melihat sidik enkripsi";
"content.actions.block" = "blokir";
"content.actions.direct_message" = "pesan langsung";
"content.actions.hug" = "peluk";
"content.actions.mention" = "sebut";
"content.actions.slap" = "tampar";
"content.actions.title" = "aksi";
"content.alert.bluetooth_required.off" = "bluetooth dimatikan. aktifkan bluetooth di pengaturan untuk memakai bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat memerlukan izin bluetooth untuk terhubung dengan perangkat dekat. aktifkan akses di pengaturan.";
"content.alert.bluetooth_required.settings" = "pengaturan";
"content.alert.bluetooth_required.title" = "butuh bluetooth";
"content.alert.bluetooth_required.unsupported" = "perangkat ini tidak mendukung bluetooth. bitchat memerlukan bluetooth untuk berjalan.";
"content.alert.screenshot.message" = "tangkapan layar kanal lokasi akan mengungkap lokasimu. pikirkan dulu sebelum membagikannya.";
"content.alert.screenshot.title" = "perhatian";
"content.commands.block" = "blokir atau lihat peer yang diblokir";
"content.commands.clear" = "hapus pesan chat";
"content.commands.favorite" = "tambah ke favorit";
"content.commands.hug" = "kirim pelukan hangat";
"content.commands.message" = "kirim pesan pribadi";
"content.commands.slap" = "tampar seseorang dengan ikan trout";
"content.commands.unblock" = "buka blokir peer";
"content.commands.unfavorite" = "hapus dari favorit";
"content.commands.who" = "lihat siapa yang online";
"content.delivery.delivered_members" = "terkirim ke %1$d dari %2$d anggota";
"content.delivery.delivered_to" = "terkirim ke %@";
"content.delivery.failed" = "gagal: %@";
"content.delivery.read_by" = "dibaca oleh %@";
"content.delivery.reason.blocked" = "pengguna diblokir";
"content.delivery.reason.self" = "tidak bisa kirim ke diri sendiri";
"content.delivery.reason.send_error" = "kesalahan pengiriman";
"content.delivery.reason.unknown_recipient" = "penerima tidak dikenal";
"content.delivery.reason.unreachable" = "peer tidak dapat dijangkau";
"content.header.people" = "ORANG";
"content.help.verification" = "verifikasi: tampilkan qr-ku atau pindai teman";
"content.input.message_placeholder" = "ketik pesan...";
"content.input.nickname_placeholder" = "nama panggilan";
"content.location.enable" = "aktifkan lokasi";
"content.message.copy" = "salin pesan";
"content.message.show_less" = "tampilkan lebih sedikit";
"content.message.show_more" = "tampilkan lebih banyak";
"content.notes.location_unavailable" = "lokasi tidak tersedia";
"content.notes.title" = "catatan";
"content.payment.cashu" = "bayar via cashu";
"content.payment.lightning" = "bayar via lightning";
"encryption.accessibility.establishing" = "menyiapkan enkripsi";
"encryption.accessibility.failed" = "enkripsi gagal";
"encryption.accessibility.not_encrypted" = "tidak terenkripsi";
"encryption.accessibility.secured" = "terenkripsi";
"encryption.accessibility.verified" = "terenkripsi dan terverifikasi";
"encryption.status.establishing" = "menyiapkan enkripsi...";
"encryption.status.failed" = "enkripsi gagal";
"encryption.status.not_encrypted" = "tidak terenkripsi";
"encryption.status.secured" = "terenkripsi";
"encryption.status.verified" = "terenkripsi dan terverifikasi";
"fingerprint.action.mark_verified" = "tandai sebagai terverifikasi";
"fingerprint.action.remove_verification" = "hapus verifikasi";
"fingerprint.badge.not_verified" = "⚠️ BELUM TERVERIFIKASI";
"fingerprint.badge.verified" = "✓ TERVERIFIKASI";
"fingerprint.handshake_pending" = "tidak tersedia - handshake sedang berlangsung";
"fingerprint.message.verified" = "kamu sudah memverifikasi identitas orang ini.";
"fingerprint.message.verify_hint" = "bandingkan sidik ini dengan %@ lewat kanal aman.";
"fingerprint.their_label" = "sidik mereka:";
"fingerprint.title" = "verifikasi keamanan";
"fingerprint.your_label" = "sidikmu:";
"geohash_people.action.block" = "blokir";
"geohash_people.action.unblock" = "buka blokir";
"geohash_people.none_nearby" = "tidak ada siapa pun...";
"geohash_people.tooltip.blocked" = "diblokir di geohash";
"geohash_people.you_suffix" = " (kamu)";
"location_channels.action.open_settings" = "buka pengaturan";
"location_channels.action.remove_access" = "cabut akses lokasi";
"location_channels.action.request_permissions" = "ambil lokasiku dan geohash";
"location_channels.action.teleport" = "teleport";
"location_channels.bookmarked_section_title" = "disimpan";
"location_channels.description" = "ngobrol dengan orang terdekat lewat kanal geohash. hanya geohash kasar yang dibagikan, tidak pernah gps tepat. alamat ip-mu tersembunyi karena seluruh trafik lewat tor.";
"location_channels.error.invalid_geohash" = "geohash tidak valid";
"location_channels.loading_nearby" = "mencari kanal sekitar…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "izin lokasi ditolak. aktifkan di pengaturan untuk memakai kanal lokasi.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#kanal lokasi";
"location_channels.tor.subtitle" = "menyembunyikan ip-mu untuk kanal lokasi. disarankan: aktif.";
"location_channels.tor.title" = "perutean tor";
"location_levels.block" = "blok";
"location_levels.building" = "gedung";
"location_levels.city" = "kota";
"location_levels.neighborhood" = "lingkungan";
"location_levels.province" = "provinsi";
"location_levels.region" = "wilayah";
"location_notes.action.dismiss" = "tutup";
"location_notes.action.retry" = "coba lagi";
"location_notes.description" = "tambahkan catatan permanen singkat di tempat ini agar orang lain menemukannya.";
"location_notes.empty_subtitle" = "jadilah orang pertama yang menambahkannya di sini.";
"location_notes.empty_title" = "belum ada catatan";
"location_notes.error.failed_to_send" = "tidak bisa mengirim catatan. %@";
"location_notes.error.no_relays" = "tidak ada relay geo tersedia dekat sini. coba lagi nanti.";
"location_notes.loading_notes" = "memuat catatan…";
"location_notes.loading_recent" = "memuat catatan terbaru…";
"location_notes.no_relays_nearby" = "tidak ada relay geo di dekatmu";
"location_notes.placeholder" = "tambahkan catatan untuk tempat ini";
"location_notes.relays_paused" = "relay geo tidak tersedia; catatan dijeda";
"location_notes.relays_retry_hint" = "catatan bergantung pada relay geo. cek koneksi lalu coba lagi.";
"mesh_peers.tooltip.new_messages" = "pesan baru";
"system.chat.blocked" = "tidak bisa mulai chat dengan %@: pengguna diblokir.";
"system.chat.requires_favorite" = "tidak bisa mulai chat dengan %@: butuh favorit bersama untuk offline.";
"system.common.user" = "pengguna";
"system.dm.blocked_generic" = "tidak bisa mengirim: pengguna diblokir.";
"system.dm.blocked_recipient" = "tidak bisa mengirim ke %@: pengguna diblokir.";
"system.dm.unreachable" = "tidak bisa mengirim ke %@: penerima tidak dapat dijangkau lewat mesh atau nostr.";
"system.geohash.blocked" = "%@ diblokir di chat geohash";
"system.geohash.unblocked" = "%@ dibuka blokirnya di chat geohash";
"system.location.not_in_channel" = "gagal mengirim: kamu tidak berada di kanal lokasi";
"system.location.send_failed" = "gagal mengirim ke kanal lokasi";
"system.tor.dev_bypass" = "build pengembangan: bypass tor aktif.";
"system.tor.restarted" = "tor dimulai ulang. perutean dipulihkan.";
"system.tor.restarting" = "tor sedang dimulai ulang untuk memulihkan konektivitas...";
"system.tor.started" = "tor berjalan. seluruh chat dirutekan lewat tor demi privasi.";
"system.tor.starting" = "menjalankan tor...";
"verification.my_qr.accessibility_label" = "kode qr verifikasi";
"verification.my_qr.title" = "pindai untuk verifikasi";
"verification.my_qr.unavailable" = "qr tidak tersedia";
"verification.scan.paste_prompt" = "tempel konten qr untuk validasi:";
"verification.scan.prompt_friend" = "pindai qr teman";
"verification.scan.status.invalid" = "qr tidak valid atau kedaluwarsa";
"verification.scan.status.no_peer" = "tidak ada peer yang cocok";
"verification.scan.status.requested" = "verifikasi diminta untuk %@";
"verification.scan.validate" = "validasi";
"verification.sheet.title" = "VERIFIKASI";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d catatan</string>
<key>other</key>
<string>%d catatan</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d orang</string>
<key>other</key>
<string>%d orang</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d orang</string>
<key>other</key>
<string>%d orang</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Italian)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "chiudi";
"app_info.done" = "FATTO";
"app_info.features.encryption.description" = "messaggi privati cifrati con il protocollo noise";
"app_info.features.encryption.title" = "crittografia end-to-end";
"app_info.features.extended_range.description" = "i messaggi vengono inoltrati tra peer per arrivare più lontano";
"app_info.features.extended_range.title" = "portata estesa";
"app_info.features.favorites.description" = "ricevi avvisi quando entrano le tue persone preferite";
"app_info.features.favorites.title" = "preferiti";
"app_info.features.geohash.description" = "canali geohash per chattare con persone vicine tramite relay anonimi decentralizzati";
"app_info.features.geohash.title" = "canali locali";
"app_info.features.mentions.description" = "usa @nickname per avvisare persone specifiche";
"app_info.features.mentions.title" = "menzioni";
"app_info.features.offline.description" = "funziona senza internet usando bluetooth a basso consumo";
"app_info.features.offline.title" = "comunicazione offline";
"app_info.features.title" = "FUNZIONI";
"app_info.how_to_use.change_channels" = "• tocca #mesh per cambiare canale";
"app_info.how_to_use.clear_chat" = "• tocca tre volte la chat per svuotarla";
"app_info.how_to_use.commands" = "• digita / per vedere i comandi";
"app_info.how_to_use.open_sidebar" = "• tocca l'icona persone per aprire la barra laterale";
"app_info.how_to_use.set_nickname" = "• imposta il tuo nickname toccandolo";
"app_info.how_to_use.start_dm" = "• tocca il nome di un peer per avviare un dm";
"app_info.how_to_use.title" = "COME SI USA";
"app_info.privacy.ephemeral.description" = "nuovo id peer generato regolarmente";
"app_info.privacy.ephemeral.title" = "identità effimera";
"app_info.privacy.no_tracking.description" = "niente server, account o raccolta dati";
"app_info.privacy.no_tracking.title" = "senza tracciamento";
"app_info.privacy.panic.description" = "tocca il logo tre volte per cancellare subito tutti i dati";
"app_info.privacy.panic.title" = "modalità panico";
"app_info.privacy.title" = "PRIVACY";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "la sicurezza dei messaggi privati non è stata ancora auditata completamente. non usarli in situazioni critiche finché questo avviso resta.";
"app_info.warning.title" = "AVVISO";
"common.cancel" = "annulla";
"common.close" = "chiudi";
"common.copy" = "copia";
"common.ok" = "OK";
"common.toggle.off" = "spento";
"common.toggle.on" = "acceso";
"common.unknown" = "sconosciuto";
"content.accessibility.add_favorite" = "aggiungi ai preferiti";
"content.accessibility.available_nostr" = "disponibile via nostr";
"content.accessibility.back_to_main_chat" = "torna alla chat principale";
"content.accessibility.connected_mesh" = "connesso tramite mesh";
"content.accessibility.encryption_status" = "stato crittografia: %@";
"content.accessibility.location_channels" = "canali posizione";
"content.accessibility.location_notes" = "note di posizione per questo posto";
"content.accessibility.open_unread_private_chat" = "apri chat privata non letta";
"content.accessibility.private_chat_header" = "chat privata con %@";
"content.accessibility.reachable_mesh" = "raggiungibile via mesh";
"content.accessibility.remove_favorite" = "rimuovi dai preferiti";
"content.accessibility.send_hint_empty" = "inserisci un messaggio da inviare";
"content.accessibility.send_hint_ready" = "tocca due volte per inviare";
"content.accessibility.send_message" = "invia messaggio";
"content.accessibility.toggle_bookmark" = "cambia segnalibro per #%@";
"content.accessibility.toggle_favorite_hint" = "tocca due volte per cambiare stato preferito";
"content.accessibility.view_fingerprint_hint" = "tocca per vedere l'impronta di cifratura";
"content.actions.block" = "blocca";
"content.actions.direct_message" = "messaggio diretto";
"content.actions.hug" = "abbraccia";
"content.actions.mention" = "menziona";
"content.actions.slap" = "schiaffo";
"content.actions.title" = "azioni";
"content.alert.bluetooth_required.off" = "bluetooth è disattivato. attiva bluetooth nelle impostazioni per usare bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat richiede l'autorizzazione bluetooth per collegarsi ai dispositivi vicini. abilita l'accesso nelle impostazioni.";
"content.alert.bluetooth_required.settings" = "impostazioni";
"content.alert.bluetooth_required.title" = "serve bluetooth";
"content.alert.bluetooth_required.unsupported" = "questo dispositivo non supporta bluetooth. bitchat richiede bluetooth per funzionare.";
"content.alert.screenshot.message" = "gli screenshot dei canali posizione rivelano la tua posizione. pensaci prima di condividerli.";
"content.alert.screenshot.title" = "attenzione";
"content.commands.block" = "blocca o mostra i peer bloccati";
"content.commands.clear" = "svuota la chat";
"content.commands.favorite" = "aggiungi ai preferiti";
"content.commands.hug" = "invia un caldo abbraccio";
"content.commands.message" = "invia messaggio privato";
"content.commands.slap" = "schiaffeggia qualcuno con una trota";
"content.commands.unblock" = "sblocca un peer";
"content.commands.unfavorite" = "rimuovi dai preferiti";
"content.commands.who" = "vedi chi è online";
"content.delivery.delivered_members" = "consegnato a %1$d di %2$d membri";
"content.delivery.delivered_to" = "consegnato a %@";
"content.delivery.failed" = "non riuscito: %@";
"content.delivery.read_by" = "letto da %@";
"content.delivery.reason.blocked" = "utente bloccato";
"content.delivery.reason.self" = "impossibile inviarti il messaggio";
"content.delivery.reason.send_error" = "errore di invio";
"content.delivery.reason.unknown_recipient" = "destinatario sconosciuto";
"content.delivery.reason.unreachable" = "peer irraggiungibile";
"content.header.people" = "PERSONE";
"content.help.verification" = "verifica: mostra il mio qr o scansiona un amico";
"content.input.message_placeholder" = "scrivi un messaggio...";
"content.input.nickname_placeholder" = "nickname";
"content.location.enable" = "attiva posizione";
"content.message.copy" = "copia messaggio";
"content.message.show_less" = "mostra meno";
"content.message.show_more" = "mostra di più";
"content.notes.location_unavailable" = "posizione non disponibile";
"content.notes.title" = "note";
"content.payment.cashu" = "paga con cashu";
"content.payment.lightning" = "paga con lightning";
"encryption.accessibility.establishing" = "avvio crittografia";
"encryption.accessibility.failed" = "crittografia fallita";
"encryption.accessibility.not_encrypted" = "non crittografato";
"encryption.accessibility.secured" = "crittografato";
"encryption.accessibility.verified" = "crittografato e verificato";
"encryption.status.establishing" = "avvio della crittografia...";
"encryption.status.failed" = "crittografia fallita";
"encryption.status.not_encrypted" = "non crittografato";
"encryption.status.secured" = "crittografato";
"encryption.status.verified" = "crittografato e verificato";
"fingerprint.action.mark_verified" = "segna come verificato";
"fingerprint.action.remove_verification" = "rimuovi verifica";
"fingerprint.badge.not_verified" = "⚠️ NON VERIFICATO";
"fingerprint.badge.verified" = "✓ VERIFICATO";
"fingerprint.handshake_pending" = "non disponibile - handshake in corso";
"fingerprint.message.verified" = "hai verificato l'identità di questa persona.";
"fingerprint.message.verify_hint" = "confronta queste impronte con %@ tramite un canale sicuro.";
"fingerprint.their_label" = "impronta loro:";
"fingerprint.title" = "verifica di sicurezza";
"fingerprint.your_label" = "tua impronta:";
"geohash_people.action.block" = "blocca";
"geohash_people.action.unblock" = "sblocca";
"geohash_people.none_nearby" = "nessuno nei dintorni...";
"geohash_people.tooltip.blocked" = "bloccato su geohash";
"geohash_people.you_suffix" = " (tu)";
"location_channels.action.open_settings" = "apri impostazioni";
"location_channels.action.remove_access" = "revoca accesso alla posizione";
"location_channels.action.request_permissions" = "ottieni la mia posizione e i geohash";
"location_channels.action.teleport" = "teletrasporto";
"location_channels.bookmarked_section_title" = "salvati";
"location_channels.description" = "chatta con le persone vicine tramite canali geohash. condividiamo solo geohash approssimativi, mai il gps esatto. il tuo ip resta nascosto perché tutto il traffico passa da tor.";
"location_channels.error.invalid_geohash" = "geohash non valido";
"location_channels.loading_nearby" = "ricerca canali vicini…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "autorizzazione posizione negata. abilitala nelle impostazioni per usare i canali.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#canali posizione";
"location_channels.tor.subtitle" = "nasconde il tuo ip per i canali posizione. consigliato: attivo.";
"location_channels.tor.title" = "instradamento tor";
"location_levels.block" = "isolato";
"location_levels.building" = "edificio";
"location_levels.city" = "città";
"location_levels.neighborhood" = "quartiere";
"location_levels.province" = "provincia";
"location_levels.region" = "regione";
"location_notes.action.dismiss" = "chiudi";
"location_notes.action.retry" = "riprova";
"location_notes.description" = "aggiungi brevi note permanenti su questo luogo per chi verrà.";
"location_notes.empty_subtitle" = "fai tu la prima nota qui.";
"location_notes.empty_title" = "ancora nessuna nota";
"location_notes.error.failed_to_send" = "impossibile inviare la nota. %@";
"location_notes.error.no_relays" = "nessun relay geo disponibile qui vicino. riprova presto.";
"location_notes.loading_notes" = "caricamento note…";
"location_notes.loading_recent" = "caricamento note recenti…";
"location_notes.no_relays_nearby" = "nessun relay geo vicino";
"location_notes.placeholder" = "aggiungi una nota per questo posto";
"location_notes.relays_paused" = "relay geo non disponibili; note in pausa";
"location_notes.relays_retry_hint" = "le note dipendono dai relay geo. controlla la connessione e riprova.";
"mesh_peers.tooltip.new_messages" = "nuovi messaggi";
"system.chat.blocked" = "impossibile avviare una chat con %@: utente bloccato.";
"system.chat.requires_favorite" = "impossibile avviare una chat con %@: servono preferiti reciproci per l'offline.";
"system.common.user" = "utente";
"system.dm.blocked_generic" = "invio non riuscito: utente bloccato.";
"system.dm.blocked_recipient" = "impossibile inviare a %@: utente bloccato.";
"system.dm.unreachable" = "impossibile inviare a %@: destinatario irraggiungibile via mesh o nostr.";
"system.geohash.blocked" = "%@ è stato bloccato nei chat geohash";
"system.geohash.unblocked" = "%@ è stato sbloccato nei chat geohash";
"system.location.not_in_channel" = "invio fallito: non sei in un canale posizione";
"system.location.send_failed" = "impossibile inviare al canale posizione";
"system.tor.dev_bypass" = "build di sviluppo: bypass tor attivo.";
"system.tor.restarted" = "tor è stato riavviato. instradamento ripristinato.";
"system.tor.restarting" = "tor si sta riavviando per ripristinare la connettività...";
"system.tor.started" = "tor è avviato. tutta la chat passa da tor per la privacy.";
"system.tor.starting" = "avvio tor...";
"verification.my_qr.accessibility_label" = "codice qr di verifica";
"verification.my_qr.title" = "scansiona per verificarmi";
"verification.my_qr.unavailable" = "qr non disponibile";
"verification.scan.paste_prompt" = "incolla il contenuto del qr per convalidare:";
"verification.scan.prompt_friend" = "scansiona il qr di un amico";
"verification.scan.status.invalid" = "qr non valido o scaduto";
"verification.scan.status.no_peer" = "nessun peer corrispondente trovato";
"verification.scan.status.requested" = "verifica richiesta per %@";
"verification.scan.validate" = "convalida";
"verification.sheet.title" = "VERIFICA";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d nota</string>
<key>other</key>
<string>%d note</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d persona</string>
<key>other</key>
<string>%d persone</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d persona</string>
<key>other</key>
<string>%d persone</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Japanese)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "閉じる";
"app_info.done" = "完了";
"app_info.features.encryption.description" = "プライベートメッセージはnoiseプロトコルで暗号化されます";
"app_info.features.encryption.title" = "エンドツーエンド暗号";
"app_info.features.extended_range.description" = "メッセージはピア間でリレーされより遠くに届きます";
"app_info.features.extended_range.title" = "拡張レンジ";
"app_info.features.favorites.description" = "お気に入りの人が参加したら通知を受け取れます";
"app_info.features.favorites.title" = "お気に入り";
"app_info.features.geohash.description" = "geohashチャンネルで近くの人と匿名分散リレー越しにチャット";
"app_info.features.geohash.title" = "ローカルチャンネル";
"app_info.features.mentions.description" = "@nicknameで特定の人に通知";
"app_info.features.mentions.title" = "メンション";
"app_info.features.offline.description" = "bluetooth low energyでインターネットなしでも動作";
"app_info.features.offline.title" = "オフライン通信";
"app_info.features.title" = "機能";
"app_info.how_to_use.change_channels" = "• #meshをタップしてチャンネルを切り替え";
"app_info.how_to_use.clear_chat" = "• チャットを3回タップするとクリア";
"app_info.how_to_use.commands" = "• /を入力してコマンド表示";
"app_info.how_to_use.open_sidebar" = "• 人アイコンをタップしてサイドバーを開く";
"app_info.how_to_use.set_nickname" = "• ニックネームをタップして設定";
"app_info.how_to_use.start_dm" = "• ピアの名前をタップしてdm開始";
"app_info.how_to_use.title" = "使い方";
"app_info.privacy.ephemeral.description" = "新しいpeer idが定期的に生成されます";
"app_info.privacy.ephemeral.title" = "一時的なアイデンティティ";
"app_info.privacy.no_tracking.description" = "サーバーもアカウントもデータ収集もなし";
"app_info.privacy.no_tracking.title" = "追跡なし";
"app_info.privacy.panic.description" = "ロゴを3回タップすると全データを即削除";
"app_info.privacy.panic.title" = "パニックモード";
"app_info.privacy.title" = "プライバシー";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "プライベートメッセージの安全性はまだ完全に監査されていません。この警告が消えるまで重要な場面では使わないでください。";
"app_info.warning.title" = "警告";
"common.cancel" = "キャンセル";
"common.close" = "閉じる";
"common.copy" = "コピー";
"common.ok" = "OK";
"common.toggle.off" = "オフ";
"common.toggle.on" = "オン";
"common.unknown" = "不明";
"content.accessibility.add_favorite" = "お気に入りに追加";
"content.accessibility.available_nostr" = "nostrで利用可能";
"content.accessibility.back_to_main_chat" = "メインチャットに戻る";
"content.accessibility.connected_mesh" = "mesh経由で接続";
"content.accessibility.encryption_status" = "暗号状態: %@";
"content.accessibility.location_channels" = "ロケーションチャンネル";
"content.accessibility.location_notes" = "この場所のロケーションノート";
"content.accessibility.open_unread_private_chat" = "未読のプライベートチャットを開く";
"content.accessibility.private_chat_header" = "%@とのプライベートチャット";
"content.accessibility.reachable_mesh" = "meshで到達可能";
"content.accessibility.remove_favorite" = "お気に入りから削除";
"content.accessibility.send_hint_empty" = "送信するメッセージを入力";
"content.accessibility.send_hint_ready" = "ダブルタップで送信";
"content.accessibility.send_message" = "メッセージ送信";
"content.accessibility.toggle_bookmark" = "#%@のブックマークを切り替え";
"content.accessibility.toggle_favorite_hint" = "ダブルタップでお気に入り状態を切り替え";
"content.accessibility.view_fingerprint_hint" = "暗号フィンガープリントを見る";
"content.actions.block" = "ブロック";
"content.actions.direct_message" = "ダイレクトメッセージ";
"content.actions.hug" = "ハグ";
"content.actions.mention" = "メンション";
"content.actions.slap" = "ビンタ";
"content.actions.title" = "アクション";
"content.alert.bluetooth_required.off" = "bluetoothがオフです。設定でbluetoothをオンにしてbitchatを使ってください。";
"content.alert.bluetooth_required.permission" = "bitchatは近くのデバイスと接続するためbluetooth権限が必要です。設定でアクセスを有効にしてください。";
"content.alert.bluetooth_required.settings" = "設定";
"content.alert.bluetooth_required.title" = "bluetoothが必要";
"content.alert.bluetooth_required.unsupported" = "このデバイスはbluetoothをサポートしていません。bitchatにはbluetoothが必要です。";
"content.alert.screenshot.message" = "ロケーションチャンネルのスクリーンショットはあなたの場所を明かします。公開前によく考えてください。";
"content.alert.screenshot.title" = "注意";
"content.commands.block" = "ブロックまたはブロック済みを表示";
"content.commands.clear" = "チャットをクリア";
"content.commands.favorite" = "お気に入りに追加";
"content.commands.hug" = "あたたかいハグを送る";
"content.commands.message" = "プライベートメッセージを送る";
"content.commands.slap" = "誰かをトラウトでたたく";
"content.commands.unblock" = "ピアのブロックを解除";
"content.commands.unfavorite" = "お気に入りから外す";
"content.commands.who" = "オンラインの人を見る";
"content.delivery.delivered_members" = "%2$d人中%1$d人に配信";
"content.delivery.delivered_to" = "%@に配信";
"content.delivery.failed" = "失敗: %@";
"content.delivery.read_by" = "%@が既読";
"content.delivery.reason.blocked" = "ユーザーをブロック中";
"content.delivery.reason.self" = "自分には送れません";
"content.delivery.reason.send_error" = "送信エラー";
"content.delivery.reason.unknown_recipient" = "不明な宛先";
"content.delivery.reason.unreachable" = "ピアに到達できません";
"content.header.people" = "ユーザー";
"content.help.verification" = "検証: 自分のqrを表示するか友達をスキャン";
"content.input.message_placeholder" = "メッセージを入力...";
"content.input.nickname_placeholder" = "ニックネーム";
"content.location.enable" = "位置情報を有効化";
"content.message.copy" = "メッセージをコピー";
"content.message.show_less" = "表示を減らす";
"content.message.show_more" = "さらに表示";
"content.notes.location_unavailable" = "位置情報を取得できません";
"content.notes.title" = "ノート";
"content.payment.cashu" = "cashuで支払う";
"content.payment.lightning" = "lightningで支払う";
"encryption.accessibility.establishing" = "暗号を確立しています";
"encryption.accessibility.failed" = "暗号に失敗";
"encryption.accessibility.not_encrypted" = "未暗号";
"encryption.accessibility.secured" = "暗号化済み";
"encryption.accessibility.verified" = "暗号化し検証済み";
"encryption.status.establishing" = "暗号を確立中...";
"encryption.status.failed" = "暗号に失敗";
"encryption.status.not_encrypted" = "未暗号";
"encryption.status.secured" = "暗号化済み";
"encryption.status.verified" = "暗号化し検証済み";
"fingerprint.action.mark_verified" = "検証済みにする";
"fingerprint.action.remove_verification" = "検証を削除";
"fingerprint.badge.not_verified" = "⚠️ 未検証";
"fingerprint.badge.verified" = "✓ 検証済み";
"fingerprint.handshake_pending" = "利用不可 - handshake進行中";
"fingerprint.message.verified" = "この人の身元を確認しました。";
"fingerprint.message.verify_hint" = "これらのフィンガープリントを%@と安全なチャネルで比較";
"fingerprint.their_label" = "相手のフィンガープリント:";
"fingerprint.title" = "セキュリティ検証";
"fingerprint.your_label" = "あなたのフィンガープリント:";
"geohash_people.action.block" = "ブロック";
"geohash_people.action.unblock" = "ブロック解除";
"geohash_people.none_nearby" = "近くに誰もいません...";
"geohash_people.tooltip.blocked" = "geohashでブロック中";
"geohash_people.you_suffix" = " (あなた)";
"location_channels.action.open_settings" = "設定を開く";
"location_channels.action.remove_access" = "位置アクセスを解除";
"location_channels.action.request_permissions" = "位置情報とgeohashを取得";
"location_channels.action.teleport" = "テレポート";
"location_channels.bookmarked_section_title" = "保存済み";
"location_channels.description" = "geohashチャンネルで近くの人と会話。共有されるのはざっくりしたgeohashだけで正確なgpsは含みません。全トラフィックをtor経由にすることであなたのipを隠します。";
"location_channels.error.invalid_geohash" = "無効なgeohash";
"location_channels.loading_nearby" = "近くのチャンネルを検索中…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "位置情報の許可が拒否されました。チャンネルを使うには設定で許可してください。";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#ロケーションチャンネル";
"location_channels.tor.subtitle" = "ロケーションチャンネル用にipを隠します。推奨: オン";
"location_channels.tor.title" = "torルーティング";
"location_levels.block" = "ブロック";
"location_levels.building" = "建物";
"location_levels.city" = "都市";
"location_levels.neighborhood" = "近所";
"location_levels.province" = "州";
"location_levels.region" = "地域";
"location_notes.action.dismiss" = "閉じる";
"location_notes.action.retry" = "再試行";
"location_notes.description" = "他の人が見つけられるようこの場所に短いノートを追加";
"location_notes.empty_subtitle" = "ここで最初のノートを残そう。";
"location_notes.empty_title" = "ノートはまだありません";
"location_notes.error.failed_to_send" = "ノートを送信できませんでした。%@";
"location_notes.error.no_relays" = "近くに利用できるジオリレーがありません。後で再試行してください。";
"location_notes.loading_notes" = "ノートを読み込み中…";
"location_notes.loading_recent" = "最新ノートを読み込み中…";
"location_notes.no_relays_nearby" = "近くにジオリレーなし";
"location_notes.placeholder" = "この場所のノートを追加";
"location_notes.relays_paused" = "ジオリレーが利用不可: ノート一時停止";
"location_notes.relays_retry_hint" = "ノートはジオリレーに依存します。接続を確認して再試行してください。";
"mesh_peers.tooltip.new_messages" = "新しいメッセージ";
"system.chat.blocked" = "%@とはチャットできません: ユーザーをブロック中。";
"system.chat.requires_favorite" = "%@とはチャットできません: オフラインには相互のお気に入りが必要です。";
"system.common.user" = "ユーザー";
"system.dm.blocked_generic" = "送信できません: ユーザーをブロック中。";
"system.dm.blocked_recipient" = "%@に送れません: ユーザーをブロック中。";
"system.dm.unreachable" = "%@に送れません: 受信者はmeshやnostrで到達できません。";
"system.geohash.blocked" = "%@をgeohashチャットでブロックしました";
"system.geohash.unblocked" = "%@のgeohashチャットでのブロックを解除しました";
"system.location.not_in_channel" = "送信失敗: ロケーションチャンネルに参加していません";
"system.location.send_failed" = "ロケーションチャンネルに送信できませんでした";
"system.tor.dev_bypass" = "開発ビルド: torバイパスが有効です。";
"system.tor.restarted" = "torを再起動しました。ルーティングを復旧。";
"system.tor.restarting" = "接続回復のためtorを再起動しています...";
"system.tor.started" = "torを起動しました。全チャットをtor経由で配信します。";
"system.tor.starting" = "torを起動中...";
"verification.my_qr.accessibility_label" = "検証用qrコード";
"verification.my_qr.title" = "スキャンして確認";
"verification.my_qr.unavailable" = "qrは利用不可";
"verification.scan.paste_prompt" = "確認するqr内容を貼り付け:";
"verification.scan.prompt_friend" = "友達のqrをスキャン";
"verification.scan.status.invalid" = "qrが無効または期限切れ";
"verification.scan.status.no_peer" = "該当するピアが見つかりません";
"verification.scan.status.requested" = "%@の検証をリクエストしました";
"verification.scan.validate" = "確認";
"verification.sheet.title" = "確認";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d件のノート</string>
<key>other</key>
<string>%d件のノート</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d人</string>
<key>other</key>
<string>%d人</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d人</string>
<key>other</key>
<string>%d人</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Nepali)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "बन्द";
"app_info.done" = "सम्पन्न";
"app_info.features.encryption.description" = "व्यक्तिगत सन्देशहरू noise प्रोटोकलले सङ्केत गर्छ";
"app_info.features.encryption.title" = "एन्ड-टु-एन्ड सङ्केत";
"app_info.features.extended_range.description" = "सन्देशहरू सहकर्मीमार्फत रिले भएर टाढासम्म पुग्छन्";
"app_info.features.extended_range.title" = "विस्तारित पहुँच";
"app_info.features.favorites.description" = "तिम्रा मनपर्ने मानिस जोडिएपछि सूचनाहरू पाऊ";
"app_info.features.favorites.title" = "मनपर्ने";
"app_info.features.geohash.description" = "geohash च्यानलहरूले नजिकका व्यक्तिसँग विकेन्द्रित गोप्य रिलेबाट कुराकानी गर्न मद्दत गर्छ";
"app_info.features.geohash.title" = "स्थानीय च्यानल";
"app_info.features.mentions.description" = "विशेष व्यक्तिलाई सूचित गर्न @nickname प्रयोग गर";
"app_info.features.mentions.title" = "उल्लेख";
"app_info.features.offline.description" = "bluetooth low energy प्रयोग गरेर इन्टरनेट बिना काम गर्छ";
"app_info.features.offline.title" = "अफलाइन सञ्चार";
"app_info.features.title" = "विशेषता";
"app_info.how_to_use.change_channels" = "• च्यानल बदल्न #mesh ट्याप गर";
"app_info.how_to_use.clear_chat" = "• च्याट खाली गर्न तीन पटक ट्याप गर";
"app_info.how_to_use.commands" = "• आदेशहरू हेर्न / टाइप गर";
"app_info.how_to_use.open_sidebar" = "• साइडबार खोल्न मान्छे आइकन ट्याप गर";
"app_info.how_to_use.set_nickname" = "• आफ्नो उपनाममा ट्याप गरेर मिलाऊ";
"app_info.how_to_use.start_dm" = "• dm सुरु गर्न कुनै सहकर्मीको नाम ट्याप गर";
"app_info.how_to_use.title" = "प्रयोग गर्ने तरिका";
"app_info.privacy.ephemeral.description" = "नयाँ peer id नियमित रूपमा सिर्जना हुन्छ";
"app_info.privacy.ephemeral.title" = "क्षणिक पहिचान";
"app_info.privacy.no_tracking.description" = "सर्भर, खाताहरू वा तथ्याङ्क सङ्कलन छैन";
"app_info.privacy.no_tracking.title" = "ट्र्याकिङ छैन";
"app_info.privacy.panic.description" = "लगो तीन पटक ट्याप गर्दा सबै डाटा तुरुन्त मेटिन्छ";
"app_info.privacy.panic.title" = "घबराहट मोड";
"app_info.privacy.title" = "गोपनीयता";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "व्यक्तिगत सन्देशको सुरक्षा पूर्ण रूपमा अडिट भएको छैन। यो चेतावनी हट्दासम्म गम्भीर अवस्थामा प्रयोग नगर्नु।";
"app_info.warning.title" = "चेतावनी";
"common.cancel" = "रद्द";
"common.close" = "बन्द";
"common.copy" = "प्रतिलिपि";
"common.ok" = "ठिक";
"common.toggle.off" = "अफ";
"common.toggle.on" = "अन";
"common.unknown" = "अज्ञात";
"content.accessibility.add_favorite" = "मनपर्नेमा थप";
"content.accessibility.available_nostr" = "nostr मार्फत उपलब्ध";
"content.accessibility.back_to_main_chat" = "मुख्य च्याटमा फर्क";
"content.accessibility.connected_mesh" = "mesh मार्फत जडान";
"content.accessibility.encryption_status" = "सङ्केतको अवस्था: %@";
"content.accessibility.location_channels" = "स्थान च्यानल";
"content.accessibility.location_notes" = "यस ठाउँका स्थान नोटहरू";
"content.accessibility.open_unread_private_chat" = "नपढिएको निजी च्याट खोल";
"content.accessibility.private_chat_header" = "%@ सँग निजी च्याट";
"content.accessibility.reachable_mesh" = "mesh मार्फत पहुँचयोग्य";
"content.accessibility.remove_favorite" = "मनपर्नेबाट हटाउ";
"content.accessibility.send_hint_empty" = "पठाउन सन्देश लेख";
"content.accessibility.send_hint_ready" = "पठाउन दोहोरो ट्याप गर";
"content.accessibility.send_message" = "सन्देश पठाउ";
"content.accessibility.toggle_bookmark" = "#%@ का लागि बुकमार्क बदल";
"content.accessibility.toggle_favorite_hint" = "मनपर्ने स्थिति बदल्न दोहोरो ट्याप गर";
"content.accessibility.view_fingerprint_hint" = "सङ्केत फिङ्गरप्रिन्ट हेर्न ट्याप गर";
"content.actions.block" = "ब्लक";
"content.actions.direct_message" = "प्रत्यक्ष सन्देश";
"content.actions.hug" = "अँगालो";
"content.actions.mention" = "उल्लेख";
"content.actions.slap" = "थप्पड";
"content.actions.title" = "कार्य";
"content.alert.bluetooth_required.off" = "bluetooth बन्द छ। bitchat प्रयोग गर्न bluetooth सेटिङमा अन गर।";
"content.alert.bluetooth_required.permission" = "bitchat लाई नजिकका उपकरणसँग जडान हुन bluetooth अनुमति चाहिन्छ। सेटिङमा पहुँच सक्षम गर।";
"content.alert.bluetooth_required.settings" = "सेटिङ";
"content.alert.bluetooth_required.title" = "bluetooth आवश्यक";
"content.alert.bluetooth_required.unsupported" = "यो उपकरणले bluetooth समर्थन गर्दैन। bitchat चलाउन bluetooth चाहिन्छ।";
"content.alert.screenshot.message" = "स्थान च्यानलको स्क्रिनसटले तिम्रो स्थान खुलाउँछ। सार्वजनिकरूपमा बाँड्नु अघि सोच।";
"content.alert.screenshot.title" = "ध्यान";
"content.commands.block" = "ब्लक गर वा ब्लक गरिएको सूची देखाउ";
"content.commands.clear" = "च्याट सन्देश खाली गर";
"content.commands.favorite" = "मनपर्नेमा थप";
"content.commands.hug" = "न्यानो अँगालो पठाउ";
"content.commands.message" = "निजी सन्देश पठाउ";
"content.commands.slap" = "कसैलाई ट्राउटले थप्पड दे";
"content.commands.unblock" = "पीयर अनब्लक गर";
"content.commands.unfavorite" = "मनपर्नेबाट हटाउ";
"content.commands.who" = "अनलाइन को-को छन् हेर्नु";
"content.delivery.delivered_members" = "%2$d सदस्यमध्ये %1$d जनालाई पुर्याइयो";
"content.delivery.delivered_to" = "%@ लाई पुर्याइयो";
"content.delivery.failed" = "असफल: %@";
"content.delivery.read_by" = "%@ ले पढ्यो";
"content.delivery.reason.blocked" = "प्रयोगकर्ता ब्लक गरिएको";
"content.delivery.reason.self" = "आफूलाई पठाउन मिल्दैन";
"content.delivery.reason.send_error" = "पठाउने त्रुटि";
"content.delivery.reason.unknown_recipient" = "अज्ञात प्राप्तकर्ता";
"content.delivery.reason.unreachable" = "पीयर पहुँचयोग्य छैन";
"content.header.people" = "मानिस";
"content.help.verification" = "प्रमाणीकरण: मेरो qr देखाउ वा साथी स्क्यान गर";
"content.input.message_placeholder" = "सन्देश टाइप गर...";
"content.input.nickname_placeholder" = "उपनाम";
"content.location.enable" = "स्थान सक्षम गर";
"content.message.copy" = "सन्देश प्रतिलिपि गर";
"content.message.show_less" = "थोरै देखाउ";
"content.message.show_more" = "थप देखाउ";
"content.notes.location_unavailable" = "स्थान उपलब्ध छैन";
"content.notes.title" = "नोट";
"content.payment.cashu" = "cashu मार्फत तिर्नु";
"content.payment.lightning" = "lightning मार्फत तिर्नु";
"encryption.accessibility.establishing" = "सङ्केत सेट हुँदै";
"encryption.accessibility.failed" = "सङ्केत असफल";
"encryption.accessibility.not_encrypted" = "सङ्केत छैन";
"encryption.accessibility.secured" = "सङ्केत गरिएको";
"encryption.accessibility.verified" = "सङ्केत र प्रमाणित";
"encryption.status.establishing" = "सङ्केत सेट गर्दै...";
"encryption.status.failed" = "सङ्केत असफल";
"encryption.status.not_encrypted" = "सङ्केत छैन";
"encryption.status.secured" = "सङ्केत गरिएको";
"encryption.status.verified" = "सङ्केत र प्रमाणित";
"fingerprint.action.mark_verified" = "प्रमाणित चिन्ह लगाउ";
"fingerprint.action.remove_verification" = "प्रमाणीकरण हटाउ";
"fingerprint.badge.not_verified" = "⚠️ प्रमाणित छैन";
"fingerprint.badge.verified" = "✓ प्रमाणित";
"fingerprint.handshake_pending" = "उपलब्ध छैन - handshake हुँदै";
"fingerprint.message.verified" = "तिमीले यस व्यक्तिको पहिचान प्रमाणित गरेको छौ.";
"fingerprint.message.verify_hint" = "यी फिङ्गरप्रिन्टहरू %@ सँग सुरक्षित च्यानलमा तुलना गर।";
"fingerprint.their_label" = "उनको फिङ्गरप्रिन्ट:";
"fingerprint.title" = "सुरक्षा प्रमाणीकरण";
"fingerprint.your_label" = "तिम्रो फिङ्गरप्रिन्ट:";
"geohash_people.action.block" = "ब्लक";
"geohash_people.action.unblock" = "अनब्लक";
"geohash_people.none_nearby" = "वरिपरि कोही छैन...";
"geohash_people.tooltip.blocked" = "geohash मा ब्लक";
"geohash_people.you_suffix" = " (तिमी)";
"location_channels.action.open_settings" = "सेटिङ खोल";
"location_channels.action.remove_access" = "स्थान पहुँच हटाउ";
"location_channels.action.request_permissions" = "मेरो स्थान र geohash प्राप्त गर";
"location_channels.action.teleport" = "टेलिपोर्ट";
"location_channels.bookmarked_section_title" = "बुकमार्क";
"location_channels.description" = "geohash च्यानलबाट नजिकका मानिससँग कुरा गर। केवल मोटामो geohash साझा हुन्छ, कहिल्यै सहि gps होइन। सबै ट्राफिक tor मार्फत गएका कारण तिम्रो ip लुकेको हुन्छ।";
"location_channels.error.invalid_geohash" = "अवैध geohash";
"location_channels.loading_nearby" = "नजिकका च्यानल खोज्दै…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "स्थान अनुमति अस्वीकार। स्थान च्यानल प्रयोग गर्न सेटिङमा सक्षम गर।";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#स्थान च्यानल";
"location_channels.tor.subtitle" = "स्थान च्यानलका लागि तिम्रो ip लुकाउँछ। सिफारिस: अन।";
"location_channels.tor.title" = "tor रूटिङ";
"location_levels.block" = "ब्लक";
"location_levels.building" = "भवन";
"location_levels.city" = "सहर";
"location_levels.neighborhood" = "छिमेक";
"location_levels.province" = "प्रदेश";
"location_levels.region" = "क्षेत्र";
"location_notes.action.dismiss" = "बन्द गर";
"location_notes.action.retry" = "फेरि प्रयास गर";
"location_notes.description" = "अन्यले भेटून् भनी यस स्थानमा छोटो स्थायी नोट थप।";
"location_notes.empty_subtitle" = "यस ठाउँमा नोट थप्ने पहिलो व्यक्ती बन।";
"location_notes.empty_title" = "अहिले नोट छैन";
"location_notes.error.failed_to_send" = "नोट पठाउन सकेन। %@";
"location_notes.error.no_relays" = "यस स्थान नजिक georelay उपलब्ध छैन। केही बेरपछि प्रयास गर।";
"location_notes.loading_notes" = "नोट लोड हुँदै…";
"location_notes.loading_recent" = "हालैका नोट लोड गर्दै…";
"location_notes.no_relays_nearby" = "नजिक georelay छैन";
"location_notes.placeholder" = "यस स्थानका लागि नोट थप";
"location_notes.relays_paused" = "georelay उपलब्ध छैन; नोट रोकिएको";
"location_notes.relays_retry_hint" = "नोट georelay मा निर्भर छन्। जडान जाँच गरेर फेरि प्रयास गर.";
"mesh_peers.tooltip.new_messages" = "नयाँ सन्देश";
"system.chat.blocked" = "%@ सँग च्याट सुरु गर्न मिलेन: प्रयोगकर्ता ब्लक गरिएको";
"system.chat.requires_favorite" = "%@ सँग च्याट सुरु गर्न मिलेन: अफलाइनका लागि दुवै मनपर्ने हुनुपर्छ";
"system.common.user" = "प्रयोगकर्ता";
"system.dm.blocked_generic" = "पठाउन मिलेन: प्रयोगकर्ता ब्लक";
"system.dm.blocked_recipient" = "%@ लाई पठाउन मिलेन: प्रयोगकर्ता ब्लक";
"system.dm.unreachable" = "%@ लाई पठाउन मिलेन: प्राप्तकर्ता mesh वा nostr बाट उपलब्ध छैन";
"system.geohash.blocked" = "%@ लाई geohash च्याटमा ब्लक गरियो";
"system.geohash.unblocked" = "%@ लाई geohash च्याटमा अनब्लक गरियो";
"system.location.not_in_channel" = "पठाउन मिलेन: तिमी स्थान च्यानलमा छैनौ";
"system.location.send_failed" = "स्थान च्यानलमा पठाउन सकेन";
"system.tor.dev_bypass" = "डेभ बिल्ड: tor बाइपास सक्षम।";
"system.tor.restarted" = "tor फेरि सुरु भयो। रूटिङ पुनःस्थापित।";
"system.tor.restarting" = "tor जडान फर्काउन पुनः सुरु हुँदैछ...";
"system.tor.started" = "tor सुरु भयो। गोपनीयताका लागि पूरा च्याट tor मार्फत जान्छ।";
"system.tor.starting" = "tor सुरु हुँदै...";
"verification.my_qr.accessibility_label" = "प्रमाणीकरण qr कोड";
"verification.my_qr.title" = "मलाई प्रमाणित गर्न स्क्यान गर";
"verification.my_qr.unavailable" = "qr उपलब्ध छैन";
"verification.scan.paste_prompt" = "प्रमाणित गर्न qr सामग्री पेस्ट गर:";
"verification.scan.prompt_friend" = "साथीको qr स्क्यान गर";
"verification.scan.status.invalid" = "qr अवैध या म्याद सकिएको";
"verification.scan.status.no_peer" = "मिल्ने peer फेला परेन";
"verification.scan.status.requested" = "%@ को लागि प्रमाणीकरण अनुरोध भयो";
"verification.scan.validate" = "प्रमाणित गर";
"verification.sheet.title" = "प्रमाणित";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d नोट</string>
<key>other</key>
<string>%d नोटहरू</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d व्यक्ति</string>
<key>other</key>
<string>%d व्यक्तिहरू</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d व्यक्ति</string>
<key>other</key>
<string>%d व्यक्तिहरू</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Portuguese - Brazil)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "fechar";
"app_info.done" = "CONCLUÍDO";
"app_info.features.encryption.description" = "mensagens privadas criptografadas com o protocolo noise";
"app_info.features.encryption.title" = "criptografia ponto a ponto";
"app_info.features.extended_range.description" = "mensagens retransmitidas entre pares para alcançar mais longe";
"app_info.features.extended_range.title" = "alcance estendido";
"app_info.features.favorites.description" = "receba avisos quando suas pessoas favoritas entrarem";
"app_info.features.favorites.title" = "favoritos";
"app_info.features.geohash.description" = "canais geohash para conversar com pessoas em regiões próximas por relays descentralizados anônimos";
"app_info.features.geohash.title" = "canais locais";
"app_info.features.mentions.description" = "use @nickname para notificar pessoas específicas";
"app_info.features.mentions.title" = "menções";
"app_info.features.offline.description" = "funciona sem internet usando bluetooth de baixa energia";
"app_info.features.offline.title" = "comunicação offline";
"app_info.features.title" = "RECURSOS";
"app_info.how_to_use.change_channels" = "• toque #mesh para trocar de canal";
"app_info.how_to_use.clear_chat" = "• toque o chat três vezes para limpar";
"app_info.how_to_use.commands" = "• digite / para ver comandos";
"app_info.how_to_use.open_sidebar" = "• toque o ícone de pessoas para abrir a barra lateral";
"app_info.how_to_use.set_nickname" = "• defina seu apelido tocando nele";
"app_info.how_to_use.start_dm" = "• toque o nome de um par para iniciar um dm";
"app_info.how_to_use.title" = "COMO USAR";
"app_info.privacy.ephemeral.description" = "novo id de peer gerado regularmente";
"app_info.privacy.ephemeral.title" = "identidade efêmera";
"app_info.privacy.no_tracking.description" = "sem servidores, contas ou coleta de dados";
"app_info.privacy.no_tracking.title" = "sem rastreamento";
"app_info.privacy.panic.description" = "toque o logo três vezes para limpar todos os dados instantaneamente";
"app_info.privacy.panic.title" = "modo pânico";
"app_info.privacy.title" = "PRIVACIDADE";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "a segurança das mensagens privadas ainda não foi totalmente auditada. não use em situações críticas até que este aviso desapareça.";
"app_info.warning.title" = "AVISO";
"common.cancel" = "cancelar";
"common.close" = "fechar";
"common.copy" = "copiar";
"common.ok" = "OK";
"common.toggle.off" = "desligado";
"common.toggle.on" = "ligado";
"common.unknown" = "desconhecido";
"content.accessibility.add_favorite" = "adicionar aos favoritos";
"content.accessibility.available_nostr" = "disponível via nostr";
"content.accessibility.back_to_main_chat" = "voltar ao chat principal";
"content.accessibility.connected_mesh" = "conectado por mesh";
"content.accessibility.encryption_status" = "status da criptografia: %@";
"content.accessibility.location_channels" = "canais de localização";
"content.accessibility.location_notes" = "notas de localização deste lugar";
"content.accessibility.open_unread_private_chat" = "abrir chat privado não lido";
"content.accessibility.private_chat_header" = "chat privado com %@";
"content.accessibility.reachable_mesh" = "alcançável por mesh";
"content.accessibility.remove_favorite" = "remover dos favoritos";
"content.accessibility.send_hint_empty" = "digite uma mensagem para enviar";
"content.accessibility.send_hint_ready" = "toque duas vezes para enviar";
"content.accessibility.send_message" = "enviar mensagem";
"content.accessibility.toggle_bookmark" = "alternar favorito para #%@";
"content.accessibility.toggle_favorite_hint" = "toque duas vezes para alternar status de favorito";
"content.accessibility.view_fingerprint_hint" = "toque para ver a impressão de criptografia";
"content.actions.block" = "bloquear";
"content.actions.direct_message" = "mensagem direta";
"content.actions.hug" = "abraço";
"content.actions.mention" = "mencionar";
"content.actions.slap" = "tapa";
"content.actions.title" = "ações";
"content.alert.bluetooth_required.off" = "bluetooth está desligado. ative o bluetooth em ajustes para usar bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat precisa de permissão de bluetooth para conectar com dispositivos próximos. habilite o acesso em ajustes.";
"content.alert.bluetooth_required.settings" = "ajustes";
"content.alert.bluetooth_required.title" = "bluetooth necessário";
"content.alert.bluetooth_required.unsupported" = "este dispositivo não suporta bluetooth. bitchat precisa de bluetooth para funcionar.";
"content.alert.screenshot.message" = "capturas de canais de localização revelam sua localização. pense antes de compartilhar publicamente.";
"content.alert.screenshot.title" = "atenção";
"content.commands.block" = "bloquear ou listar pares bloqueados";
"content.commands.clear" = "limpar mensagens do chat";
"content.commands.favorite" = "adicionar aos favoritos";
"content.commands.hug" = "enviar um abraço quente";
"content.commands.message" = "enviar mensagem privada";
"content.commands.slap" = "dar um tapa em alguém com uma truta";
"content.commands.unblock" = "desbloquear um par";
"content.commands.unfavorite" = "remover dos favoritos";
"content.commands.who" = "ver quem está online";
"content.delivery.delivered_members" = "entregue a %1$d de %2$d membros";
"content.delivery.delivered_to" = "entregue para %@";
"content.delivery.failed" = "falhou: %@";
"content.delivery.read_by" = "lido por %@";
"content.delivery.reason.blocked" = "usuário bloqueado";
"content.delivery.reason.self" = "não é possível enviar mensagem para si mesmo";
"content.delivery.reason.send_error" = "erro ao enviar";
"content.delivery.reason.unknown_recipient" = "destinatário desconhecido";
"content.delivery.reason.unreachable" = "par inalcançável";
"content.header.people" = "PESSOAS";
"content.help.verification" = "verificação: mostrar meu qr ou escanear um amigo";
"content.input.message_placeholder" = "digite uma mensagem...";
"content.input.nickname_placeholder" = "apelido";
"content.location.enable" = "habilitar localização";
"content.message.copy" = "copiar mensagem";
"content.message.show_less" = "mostrar menos";
"content.message.show_more" = "mostrar mais";
"content.notes.location_unavailable" = "localização indisponível";
"content.notes.title" = "notas";
"content.payment.cashu" = "pagar via cashu";
"content.payment.lightning" = "pagar via lightning";
"encryption.accessibility.establishing" = "estabelecendo criptografia";
"encryption.accessibility.failed" = "falha na criptografia";
"encryption.accessibility.not_encrypted" = "não criptografado";
"encryption.accessibility.secured" = "criptografado";
"encryption.accessibility.verified" = "criptografado e verificado";
"encryption.status.establishing" = "estabelecendo criptografia...";
"encryption.status.failed" = "falha na criptografia";
"encryption.status.not_encrypted" = "não criptografado";
"encryption.status.secured" = "criptografado";
"encryption.status.verified" = "criptografado e verificado";
"fingerprint.action.mark_verified" = "marcar como verificado";
"fingerprint.action.remove_verification" = "remover verificação";
"fingerprint.badge.not_verified" = "⚠️ NÃO VERIFICADO";
"fingerprint.badge.verified" = "✓ VERIFICADO";
"fingerprint.handshake_pending" = "indisponível - handshake em andamento";
"fingerprint.message.verified" = "você verificou a identidade dessa pessoa.";
"fingerprint.message.verify_hint" = "compare essas impressões com %@ usando um canal seguro.";
"fingerprint.their_label" = "impressão digital deles:";
"fingerprint.title" = "verificação de segurança";
"fingerprint.your_label" = "sua impressão digital:";
"geohash_people.action.block" = "bloquear";
"geohash_people.action.unblock" = "desbloquear";
"geohash_people.none_nearby" = "ninguém por perto...";
"geohash_people.tooltip.blocked" = "bloqueado em geohash";
"geohash_people.you_suffix" = " (você)";
"location_channels.action.open_settings" = "abrir ajustes";
"location_channels.action.remove_access" = "remover acesso à localização";
"location_channels.action.request_permissions" = "obter localização e meus geohashes";
"location_channels.action.teleport" = "teletransportar";
"location_channels.bookmarked_section_title" = "marcados";
"location_channels.description" = "converse com pessoas próximas usando canais geohash. apenas um geohash grosseiro é compartilhado, nunca gps exato. seu ip fica oculto ao rotear todo o tráfego por tor.";
"location_channels.error.invalid_geohash" = "geohash inválido";
"location_channels.loading_nearby" = "procurando canais próximos…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "permissão de localização negada. habilite em ajustes para usar canais de localização.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#canais de localização";
"location_channels.tor.subtitle" = "oculta seu ip para canais de localização. recomendado: ligado.";
"location_channels.tor.title" = "roteamento tor";
"location_levels.block" = "quadra";
"location_levels.building" = "prédio";
"location_levels.city" = "cidade";
"location_levels.neighborhood" = "bairro";
"location_levels.province" = "estado";
"location_levels.region" = "região";
"location_notes.action.dismiss" = "dispensar";
"location_notes.action.retry" = "tentar novamente";
"location_notes.description" = "adicione notas curtas permanentes neste local para outras pessoas encontrarem.";
"location_notes.empty_subtitle" = "seja a primeira pessoa a adicionar uma aqui.";
"location_notes.empty_title" = "nenhuma nota ainda";
"location_notes.error.failed_to_send" = "não foi possível enviar a nota. %@";
"location_notes.error.no_relays" = "nenhum relay geográfico disponível perto deste local. tente novamente em breve.";
"location_notes.loading_notes" = "carregando notas…";
"location_notes.loading_recent" = "carregando notas recentes…";
"location_notes.no_relays_nearby" = "nenhum relay geográfico próximo";
"location_notes.placeholder" = "adicione uma nota para este lugar";
"location_notes.relays_paused" = "relays geográficos indisponíveis; notas pausadas";
"location_notes.relays_retry_hint" = "notas dependem de relays geográficos. verifique a conexão e tente de novo.";
"mesh_peers.tooltip.new_messages" = "novas mensagens";
"system.chat.blocked" = "não é possível iniciar chat com %@: usuário bloqueado.";
"system.chat.requires_favorite" = "não é possível iniciar chat com %@: vocês precisam ser favoritos mútuos para mensagens offline.";
"system.common.user" = "usuário";
"system.dm.blocked_generic" = "não foi possível enviar: usuário bloqueado.";
"system.dm.blocked_recipient" = "não é possível enviar mensagem para %@: usuário bloqueado.";
"system.dm.unreachable" = "não é possível enviar mensagem para %@: destinatário inalcançável por mesh ou nostr.";
"system.geohash.blocked" = "%@ foi bloqueado nos chats geohash";
"system.geohash.unblocked" = "%@ foi desbloqueado nos chats geohash";
"system.location.not_in_channel" = "não foi possível enviar: você não está em um canal de localização";
"system.location.send_failed" = "não foi possível enviar para o canal de localização";
"system.tor.dev_bypass" = "compilação de desenvolvimento: bypass de tor ativo.";
"system.tor.restarted" = "tor reiniciou. roteamento restaurado.";
"system.tor.restarting" = "tor está reiniciando para recuperar conectividade...";
"system.tor.started" = "tor iniciou. todo o chat é roteado por tor para privacidade.";
"system.tor.starting" = "iniciando tor...";
"verification.my_qr.accessibility_label" = "código qr de verificação";
"verification.my_qr.title" = "escaneie para me verificar";
"verification.my_qr.unavailable" = "qr indisponível";
"verification.scan.paste_prompt" = "cole o conteúdo do qr para validar:";
"verification.scan.prompt_friend" = "escaneie o qr de um amigo";
"verification.scan.status.invalid" = "qr inválido ou expirado";
"verification.scan.status.no_peer" = "nenhum peer correspondente encontrado";
"verification.scan.status.requested" = "verificação solicitada para %@";
"verification.scan.validate" = "validar";
"verification.sheet.title" = "VERIFICAR";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d nota</string>
<key>other</key>
<string>%d notas</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d pessoa</string>
<key>other</key>
<string>%d pessoas</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d pessoa</string>
<key>other</key>
<string>%d pessoas</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Russian)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "закрыть";
"app_info.done" = "ГОТОВО";
"app_info.features.encryption.description" = "личные сообщения шифруются протоколом noise";
"app_info.features.encryption.title" = "сквозное шифрование";
"app_info.features.extended_range.description" = "сообщения ретранслируются между пирами и уходят дальше";
"app_info.features.extended_range.title" = "расширенный радиус";
"app_info.features.favorites.description" = "получай уведомления, когда подключаются любимые люди";
"app_info.features.favorites.title" = "избранное";
"app_info.features.geohash.description" = "каналы geohash для чата с людьми поблизости через децентрализованные анонимные реле";
"app_info.features.geohash.title" = "локальные каналы";
"app_info.features.mentions.description" = "используй @nickname, чтобы уведомить конкретных людей";
"app_info.features.mentions.title" = "упоминания";
"app_info.features.offline.description" = "работает без интернета через bluetooth low energy";
"app_info.features.offline.title" = "офлайн-связь";
"app_info.features.title" = "ВОЗМОЖНОСТИ";
"app_info.how_to_use.change_channels" = "• нажми #mesh, чтобы сменить канал";
"app_info.how_to_use.clear_chat" = "• тройной тап по чату очистит его";
"app_info.how_to_use.commands" = "• введи /, чтобы увидеть команды";
"app_info.how_to_use.open_sidebar" = "• нажми на иконку людей, чтобы открыть боковое меню";
"app_info.how_to_use.set_nickname" = "• коснись своего ника, чтобы изменить его";
"app_info.how_to_use.start_dm" = "• нажми имя пользователя, чтобы начать лс";
"app_info.how_to_use.title" = "КАК ИСПОЛЬЗОВАТЬ";
"app_info.privacy.ephemeral.description" = "новый id пира создаётся регулярно";
"app_info.privacy.ephemeral.title" = "эфемерная личность";
"app_info.privacy.no_tracking.description" = "без серверов, аккаунтов и сбора данных";
"app_info.privacy.no_tracking.title" = "без трекинга";
"app_info.privacy.panic.description" = "тройной тап по логотипу мгновенно очищает все данные";
"app_info.privacy.panic.title" = "режим паники";
"app_info.privacy.title" = "КОНФИДЕНЦИАЛЬНОСТЬ";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "безопасность приватных сообщений ещё не прошла полный аудит. не используй для критичных случаев, пока предупреждение не исчезнет.";
"app_info.warning.title" = "ПРЕДУПРЕЖДЕНИЕ";
"common.cancel" = "отмена";
"common.close" = "закрыть";
"common.copy" = "копировать";
"common.ok" = "OK";
"common.toggle.off" = "выкл";
"common.toggle.on" = "вкл";
"common.unknown" = "неизвестно";
"content.accessibility.add_favorite" = "добавить в избранное";
"content.accessibility.available_nostr" = "доступно через nostr";
"content.accessibility.back_to_main_chat" = "назад в основной чат";
"content.accessibility.connected_mesh" = "подключено через mesh";
"content.accessibility.encryption_status" = "статус шифрования: %@";
"content.accessibility.location_channels" = "каналы локации";
"content.accessibility.location_notes" = "заметки для этого места";
"content.accessibility.open_unread_private_chat" = "открыть непрочитанный приватный чат";
"content.accessibility.private_chat_header" = "приватный чат с %@";
"content.accessibility.reachable_mesh" = "достижим через mesh";
"content.accessibility.remove_favorite" = "убрать из избранного";
"content.accessibility.send_hint_empty" = "введи сообщение для отправки";
"content.accessibility.send_hint_ready" = "дважды тапни, чтобы отправить";
"content.accessibility.send_message" = "отправить сообщение";
"content.accessibility.toggle_bookmark" = "переключить закладку для #%@";
"content.accessibility.toggle_favorite_hint" = "дважды тапни, чтобы переключить статус избранного";
"content.accessibility.view_fingerprint_hint" = "нажми, чтобы увидеть криптографический отпечаток";
"content.actions.block" = "заблокировать";
"content.actions.direct_message" = "личное сообщение";
"content.actions.hug" = "обнять";
"content.actions.mention" = "упомянуть";
"content.actions.slap" = "дать леща";
"content.actions.title" = "действия";
"content.alert.bluetooth_required.off" = "bluetooth выключен. включи bluetooth в настройках, чтобы использовать bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat нужен доступ к bluetooth, чтобы соединяться с ближайшими устройствами. включи разрешение в настройках.";
"content.alert.bluetooth_required.settings" = "настройки";
"content.alert.bluetooth_required.title" = "bluetooth обязателен";
"content.alert.bluetooth_required.unsupported" = "это устройство не поддерживает bluetooth. bitchat нужен bluetooth для работы.";
"content.alert.screenshot.message" = "скриншоты каналов местоположения раскроют твою позицию. подумай, прежде чем делиться публично.";
"content.alert.screenshot.title" = "внимание";
"content.commands.block" = "заблокировать или показать заблокированных";
"content.commands.clear" = "очистить чат";
"content.commands.favorite" = "добавить в избранное";
"content.commands.hug" = "отправить тёплое объятие";
"content.commands.message" = "отправить приватное сообщение";
"content.commands.slap" = "дать кому-то пощёчину форелью";
"content.commands.unblock" = "разблокировать пира";
"content.commands.unfavorite" = "убрать из избранного";
"content.commands.who" = "посмотреть, кто онлайн";
"content.delivery.delivered_members" = "доставлено %1$d из %2$d участников";
"content.delivery.delivered_to" = "доставлено %@";
"content.delivery.failed" = "ошибка: %@";
"content.delivery.read_by" = "прочитано %@";
"content.delivery.reason.blocked" = "пользователь заблокирован";
"content.delivery.reason.self" = "нельзя отправить себе";
"content.delivery.reason.send_error" = "ошибка отправки";
"content.delivery.reason.unknown_recipient" = "неизвестный получатель";
"content.delivery.reason.unreachable" = "пир недостижим";
"content.header.people" = "ЛЮДИ";
"content.help.verification" = "верификация: показать мой qr или сканировать друга";
"content.input.message_placeholder" = "напиши сообщение...";
"content.input.nickname_placeholder" = "ник";
"content.location.enable" = "включить локацию";
"content.message.copy" = "копировать сообщение";
"content.message.show_less" = "показать меньше";
"content.message.show_more" = "показать больше";
"content.notes.location_unavailable" = "локация недоступна";
"content.notes.title" = "заметки";
"content.payment.cashu" = "оплатить через cashu";
"content.payment.lightning" = "оплатить через lightning";
"encryption.accessibility.establishing" = "устанавливается шифрование";
"encryption.accessibility.failed" = "шифрование не удалось";
"encryption.accessibility.not_encrypted" = "не зашифровано";
"encryption.accessibility.secured" = "зашифровано";
"encryption.accessibility.verified" = "зашифровано и проверено";
"encryption.status.establishing" = "устанавливаем шифрование...";
"encryption.status.failed" = "шифрование не удалось";
"encryption.status.not_encrypted" = "не зашифровано";
"encryption.status.secured" = "зашифровано";
"encryption.status.verified" = "зашифровано и проверено";
"fingerprint.action.mark_verified" = "пометить как проверено";
"fingerprint.action.remove_verification" = "удалить проверку";
"fingerprint.badge.not_verified" = "⚠️ НЕ ПРОВЕРЕНО";
"fingerprint.badge.verified" = "✓ ПРОВЕРЕНО";
"fingerprint.handshake_pending" = "недоступно — handshake выполняется";
"fingerprint.message.verified" = "ты подтвердил личность этого человека.";
"fingerprint.message.verify_hint" = "сравни эти отпечатки с %@ по безопасному каналу.";
"fingerprint.their_label" = "их отпечаток:";
"fingerprint.title" = "проверка безопасности";
"fingerprint.your_label" = "твой отпечаток:";
"geohash_people.action.block" = "заблокировать";
"geohash_people.action.unblock" = "разблокировать";
"geohash_people.none_nearby" = "никого рядом...";
"geohash_people.tooltip.blocked" = "заблокирован в geohash";
"geohash_people.you_suffix" = " (ты)";
"location_channels.action.open_settings" = "открыть настройки";
"location_channels.action.remove_access" = "отключить доступ к локации";
"location_channels.action.request_permissions" = "получить мою локацию и geohash";
"location_channels.action.teleport" = "телепорт";
"location_channels.bookmarked_section_title" = "закреплённые";
"location_channels.description" = "общайся с людьми рядом через каналы geohash. делится только грубый geohash, без точного gps. твой ip скрывается за счёт маршрутизации трафика через tor.";
"location_channels.error.invalid_geohash" = "некорректный geohash";
"location_channels.loading_nearby" = "поиск каналов рядом…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "доступ к локации запрещён. включи разрешение в настройках, чтобы использовать каналы.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#каналы локации";
"location_channels.tor.subtitle" = "скрывает твой ip для каналов локации. рекомендуем включить.";
"location_channels.tor.title" = "маршрутизация tor";
"location_levels.block" = "квартал";
"location_levels.building" = "здание";
"location_levels.city" = "город";
"location_levels.neighborhood" = "район";
"location_levels.province" = "область";
"location_levels.region" = "регион";
"location_notes.action.dismiss" = "закрыть";
"location_notes.action.retry" = "повторить";
"location_notes.description" = "добавь короткие постоянные заметки об этом месте для других.";
"location_notes.empty_subtitle" = "стань первым, кто добавит здесь заметку.";
"location_notes.empty_title" = "заметок пока нет";
"location_notes.error.failed_to_send" = "не удалось отправить заметку. %@";
"location_notes.error.no_relays" = "рядом нет георелеев. попробуй позже.";
"location_notes.loading_notes" = "загрузка заметок…";
"location_notes.loading_recent" = "загрузка свежих заметок…";
"location_notes.no_relays_nearby" = "рядом нет георелеев";
"location_notes.placeholder" = "добавь заметку для этого места";
"location_notes.relays_paused" = "геореле недоступны; заметки приостановлены";
"location_notes.relays_retry_hint" = "заметки зависят от георелеев. проверь подключение и попробуй снова.";
"mesh_peers.tooltip.new_messages" = "новые сообщения";
"system.chat.blocked" = "нельзя начать чат с %@: пользователь заблокирован.";
"system.chat.requires_favorite" = "нельзя начать чат с %@: нужны взаимные избранные для офлайна.";
"system.common.user" = "пользователь";
"system.dm.blocked_generic" = "отправка невозможна: пользователь заблокирован.";
"system.dm.blocked_recipient" = "нельзя отправить %@: пользователь заблокирован.";
"system.dm.unreachable" = "нельзя отправить %@: адресат недоступен через mesh или nostr.";
"system.geohash.blocked" = "%@ заблокирован в geohash-чатах";
"system.geohash.unblocked" = "%@ разблокирован в geohash-чатах";
"system.location.not_in_channel" = "отправка невозможна: ты не в канале локации";
"system.location.send_failed" = "не удалось отправить в канал локации";
"system.tor.dev_bypass" = "dev-сборка: обход tor включён.";
"system.tor.restarted" = "tor перезапущен. маршрутизация восстановлена.";
"system.tor.restarting" = "tor перезапускается, чтобы вернуть связь...";
"system.tor.started" = "tor запущен. весь чат идёт через tor для приватности.";
"system.tor.starting" = "запуск tor...";
"verification.my_qr.accessibility_label" = "qr-код проверки";
"verification.my_qr.title" = "отсканируй, чтобы подтвердить меня";
"verification.my_qr.unavailable" = "qr недоступен";
"verification.scan.paste_prompt" = "вставь содержимое qr для проверки:";
"verification.scan.prompt_friend" = "отсканируй qr друга";
"verification.scan.status.invalid" = "qr недействителен или просрочен";
"verification.scan.status.no_peer" = "соответствующий пир не найден";
"verification.scan.status.requested" = "проверка запрошена для %@";
"verification.scan.validate" = "проверить";
"verification.sheet.title" = "ПРОВЕРИТЬ";
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d заметка</string>
<key>few</key>
<string>%d заметки</string>
<key>many</key>
<string>%d заметок</string>
<key>other</key>
<string>%d заметки</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d человек</string>
<key>few</key>
<string>%d человека</string>
<key>many</key>
<string>%d человек</string>
<key>other</key>
<string>%d человека</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d человек</string>
<key>few</key>
<string>%d человека</string>
<key>many</key>
<string>%d человек</string>
<key>other</key>
<string>%d человека</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Ukrainian)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "закрити";
"app_info.done" = "ГОТОВО";
"app_info.features.encryption.description" = "приватні повідомлення шифруються протоколом noise";
"app_info.features.encryption.title" = "скрізьове шифрування";
"app_info.features.extended_range.description" = "повідомлення ретранслюються між пірами й долітають далі";
"app_info.features.extended_range.title" = "розширена дальність";
"app_info.features.favorites.description" = "отримуй сповіщення, коли підключаються улюблені люди";
"app_info.features.favorites.title" = "вибране";
"app_info.features.geohash.description" = "канали geohash для спілкування з людьми поблизу через децентралізовані анонімні ретранслятори";
"app_info.features.geohash.title" = "локальні канали";
"app_info.features.mentions.description" = "використовуй @nickname, щоб сповістити конкретних людей";
"app_info.features.mentions.title" = "згадки";
"app_info.features.offline.description" = "працює без інтернету через bluetooth low energy";
"app_info.features.offline.title" = "офлайн-зв'язок";
"app_info.features.title" = "МОЖЛИВОСТІ";
"app_info.how_to_use.change_channels" = "• торкнися #mesh, щоб змінити канал";
"app_info.how_to_use.clear_chat" = "• торкни чат тричі, щоб очистити";
"app_info.how_to_use.commands" = "• введи /, щоб побачити команди";
"app_info.how_to_use.open_sidebar" = "• торкни піктограму людей, щоб відкрити бічну панель";
"app_info.how_to_use.set_nickname" = "• змінюй свій нік, торкаючись його";
"app_info.how_to_use.start_dm" = "• торкни ім'я піра, щоб почати приватний чат";
"app_info.how_to_use.title" = "ЯК КОРИСТУВАТИСЯ";
"app_info.privacy.ephemeral.description" = "новий id піра генерується регулярно";
"app_info.privacy.ephemeral.title" = "ефемерна ідентичність";
"app_info.privacy.no_tracking.description" = "жодних серверів, обліковок чи збору даних";
"app_info.privacy.no_tracking.title" = "без відстеження";
"app_info.privacy.panic.description" = "тричі торкни логотип, щоб миттєво стерти всі дані";
"app_info.privacy.panic.title" = "режим паніки";
"app_info.privacy.title" = "КОНФІДЕНЦІЙНІСТЬ";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "безпека приватних повідомлень ще не пройшла повний аудит. не використовуй для критичних ситуацій, поки це попередження не зникне.";
"app_info.warning.title" = "ПОПЕРЕДЖЕННЯ";
"common.cancel" = "скасувати";
"common.close" = "закрити";
"common.copy" = "скопіювати";
"common.ok" = "OK";
"common.toggle.off" = "вимк";
"common.toggle.on" = "увімк";
"common.unknown" = "невідомо";
"content.accessibility.add_favorite" = "додати до вибраного";
"content.accessibility.available_nostr" = "доступно через nostr";
"content.accessibility.back_to_main_chat" = "назад до основного чату";
"content.accessibility.connected_mesh" = "з'єднано через mesh";
"content.accessibility.encryption_status" = "стан шифрування: %@";
"content.accessibility.location_channels" = "канали локації";
"content.accessibility.location_notes" = "замітки про це місце";
"content.accessibility.open_unread_private_chat" = "відкрити непрочитаний приватний чат";
"content.accessibility.private_chat_header" = "приватний чат з %@";
"content.accessibility.reachable_mesh" = "досяжно через mesh";
"content.accessibility.remove_favorite" = "видалити з вибраного";
"content.accessibility.send_hint_empty" = "введи повідомлення для надсилання";
"content.accessibility.send_hint_ready" = "торкни двічі, щоб надіслати";
"content.accessibility.send_message" = "надіслати повідомлення";
"content.accessibility.toggle_bookmark" = "перемкнути закладку для #%@";
"content.accessibility.toggle_favorite_hint" = "торкни двічі, щоб змінити статус вибраного";
"content.accessibility.view_fingerprint_hint" = "торкни, щоб переглянути криптографічний відбиток";
"content.actions.block" = "заблокувати";
"content.actions.direct_message" = "приватне повідомлення";
"content.actions.hug" = "обійняти";
"content.actions.mention" = "згадати";
"content.actions.slap" = "ляпас";
"content.actions.title" = "дії";
"content.alert.bluetooth_required.off" = "bluetooth вимкнений. увімкни bluetooth у налаштуваннях, щоб користуватися bitchat.";
"content.alert.bluetooth_required.permission" = "bitchat потребує дозволу bluetooth для з'єднання з пристроями поруч. ввімкни доступ у налаштуваннях.";
"content.alert.bluetooth_required.settings" = "налаштування";
"content.alert.bluetooth_required.title" = "потрібен bluetooth";
"content.alert.bluetooth_required.unsupported" = "цей пристрій не підтримує bluetooth. bitchat потрібен bluetooth для роботи.";
"content.alert.screenshot.message" = "скріншоти каналів локації розкриють твоє місце. подумай, перш ніж ділитися публічно.";
"content.alert.screenshot.title" = "увага";
"content.commands.block" = "заблокувати або показати заблокованих";
"content.commands.clear" = "очистити чат";
"content.commands.favorite" = "додати до вибраного";
"content.commands.hug" = "відправити теплі обійми";
"content.commands.message" = "надіслати приватне повідомлення";
"content.commands.slap" = "лупнути когось фореллю";
"content.commands.unblock" = "розблокувати піра";
"content.commands.unfavorite" = "видалити з вибраного";
"content.commands.who" = "подивитися, хто онлайн";
"content.delivery.delivered_members" = "доставлено %1$d з %2$d учасників";
"content.delivery.delivered_to" = "доставлено %@";
"content.delivery.failed" = "не вдалося: %@";
"content.delivery.read_by" = "прочитано %@";
"content.delivery.reason.blocked" = "користувач заблокований";
"content.delivery.reason.self" = "не можна надіслати собі";
"content.delivery.reason.send_error" = "помилка надсилання";
"content.delivery.reason.unknown_recipient" = "невідомий одержувач";
"content.delivery.reason.unreachable" = "пір недосяжний";
"content.header.people" = "ЛЮДИ";
"content.help.verification" = "верифікація: показати мій qr або сканувати друга";
"content.input.message_placeholder" = "напиши повідомлення...";
"content.input.nickname_placeholder" = "нік";
"content.location.enable" = "увімкнути локацію";
"content.message.copy" = "скопіювати повідомлення";
"content.message.show_less" = "показати менше";
"content.message.show_more" = "показати більше";
"content.notes.location_unavailable" = "локація недоступна";
"content.notes.title" = "замітки";
"content.payment.cashu" = "оплатити через cashu";
"content.payment.lightning" = "оплатити через lightning";
"encryption.accessibility.establishing" = "встановлюється шифрування";
"encryption.accessibility.failed" = "шифрування не вдалося";
"encryption.accessibility.not_encrypted" = "не зашифровано";
"encryption.accessibility.secured" = "зашифровано";
"encryption.accessibility.verified" = "зашифровано та перевірено";
"encryption.status.establishing" = "встановлюємо шифрування...";
"encryption.status.failed" = "шифрування не вдалося";
"encryption.status.not_encrypted" = "не зашифровано";
"encryption.status.secured" = "зашифровано";
"encryption.status.verified" = "зашифровано та перевірено";
"fingerprint.action.mark_verified" = "позначити як перевірено";
"fingerprint.action.remove_verification" = "зняти перевірку";
"fingerprint.badge.not_verified" = "⚠️ НЕ ПЕРЕВІРЕНО";
"fingerprint.badge.verified" = "✓ ПЕРЕВІРЕНО";
"fingerprint.handshake_pending" = "недоступно — handshake триває";
"fingerprint.message.verified" = "ти підтвердив особу цієї людини.";
"fingerprint.message.verify_hint" = "порівняй ці відбитки з %@ у безпечному каналі.";
"fingerprint.their_label" = "їхній відбиток:";
"fingerprint.title" = "перевірка безпеки";
"fingerprint.your_label" = "твій відбиток:";
"geohash_people.action.block" = "заблокувати";
"geohash_people.action.unblock" = "розблокувати";
"geohash_people.none_nearby" = "поруч нікого...";
"geohash_people.tooltip.blocked" = "заблоковано в geohash";
"geohash_people.you_suffix" = " (ти)";
"location_channels.action.open_settings" = "відкрити налаштування";
"location_channels.action.remove_access" = "відключити доступ до локації";
"location_channels.action.request_permissions" = "отримати мою локацію та geohash";
"location_channels.action.teleport" = "телепорт";
"location_channels.bookmarked_section_title" = "закладені";
"location_channels.description" = "спілкуйся з людьми поруч у каналах geohash. передається лише грубий geohash, без точного gps. твій ip приховується, бо весь трафік йде через tor.";
"location_channels.error.invalid_geohash" = "некоректний geohash";
"location_channels.loading_nearby" = "пошук каналів поруч…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "доступ до локації заборонено. увімкни дозвіл у налаштуваннях, щоб користуватися каналами.";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#канали локації";
"location_channels.tor.subtitle" = "приховує твій ip для каналів локації. рекомендовано ввімкнути.";
"location_channels.tor.title" = "маршрутизація tor";
"location_levels.block" = "квартал";
"location_levels.building" = "будівля";
"location_levels.city" = "місто";
"location_levels.neighborhood" = "район";
"location_levels.province" = "область";
"location_levels.region" = "регіон";
"location_notes.action.dismiss" = "закрити";
"location_notes.action.retry" = "повторити";
"location_notes.description" = "додай короткі постійні замітки про це місце для інших.";
"location_notes.empty_subtitle" = "стань першим, хто додасть тут замітку.";
"location_notes.empty_title" = "заміток ще немає";
"location_notes.error.failed_to_send" = "не вдалося надіслати замітку. %@";
"location_notes.error.no_relays" = "поруч немає гео-релеїв. спробуй пізніше.";
"location_notes.loading_notes" = "завантаження заміток…";
"location_notes.loading_recent" = "завантаження свіжих заміток…";
"location_notes.no_relays_nearby" = "немає гео-релеїв поблизу";
"location_notes.placeholder" = "додай замітку для цього місця";
"location_notes.relays_paused" = "гео-релеї недоступні; замітки призупинено";
"location_notes.relays_retry_hint" = "замітки залежать від гео-релеїв. перевір з'єднання й спробуй ще раз.";
"mesh_peers.tooltip.new_messages" = "нові повідомлення";
"system.chat.blocked" = "не можна почати чат з %@: користувач заблокований.";
"system.chat.requires_favorite" = "не можна почати чат з %@: потрібне взаємне вибране для офлайна.";
"system.common.user" = "користувач";
"system.dm.blocked_generic" = "не вдалося надіслати: користувач заблокований.";
"system.dm.blocked_recipient" = "неможливо надіслати %@: користувач заблокований.";
"system.dm.unreachable" = "неможливо надіслати %@: одержувач недосяжний через mesh або nostr.";
"system.geohash.blocked" = "%@ заблоковано в geohash-чатах";
"system.geohash.unblocked" = "%@ розблоковано в geohash-чатах";
"system.location.not_in_channel" = "не вдалося надіслати: ти не в каналі локації";
"system.location.send_failed" = "не вдалося надіслати в канал локації";
"system.tor.dev_bypass" = "dev-збірка: обхід tor увімкнено.";
"system.tor.restarted" = "tor перезапущено. маршрутизацію відновлено.";
"system.tor.restarting" = "tor перезапускається, щоб відновити підключення...";
"system.tor.started" = "tor запущено. увесь чат іде через tor для приватності.";
"system.tor.starting" = "запуск tor...";
"verification.my_qr.accessibility_label" = "qr-код підтвердження";
"verification.my_qr.title" = "скануй, щоб підтвердити мене";
"verification.my_qr.unavailable" = "qr недоступний";
"verification.scan.paste_prompt" = "встав вміст qr для перевірки:";
"verification.scan.prompt_friend" = "скануй qr друга";
"verification.scan.status.invalid" = "qr недійсний або прострочений";
"verification.scan.status.no_peer" = "відповідний пір не знайдений";
"verification.scan.status.requested" = "перевірка запитана для %@";
"verification.scan.validate" = "перевірити";
"verification.sheet.title" = "ПЕРЕВІРИТИ";
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d замітка</string>
<key>few</key>
<string>%d замітки</string>
<key>many</key>
<string>%d заміток</string>
<key>other</key>
<string>%d замітки</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d людина</string>
<key>few</key>
<string>%d людини</string>
<key>many</key>
<string>%d людей</string>
<key>other</key>
<string>%d людини</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d людина</string>
<key>few</key>
<string>%d людини</string>
<key>many</key>
<string>%d людей</string>
<key>other</key>
<string>%d людини</string>
</dict>
</dict>
</dict>
</plist>
@@ -1,190 +0,0 @@
/*
Localizable.strings
bitchat (Simplified Chinese)
*/
"app_info.app_name" = "bitchat";
"app_info.close" = "关闭";
"app_info.done" = "完成";
"app_info.features.encryption.description" = "私密消息使用 noise 协议加密";
"app_info.features.encryption.title" = "端到端加密";
"app_info.features.extended_range.description" = "消息通过同伴中继,传得更远";
"app_info.features.extended_range.title" = "扩展范围";
"app_info.features.favorites.description" = "你喜欢的人加入时立刻提醒";
"app_info.features.favorites.title" = "收藏";
"app_info.features.geohash.description" = "geohash 频道让你通过去中心化匿名中继与附近地区的人聊天";
"app_info.features.geohash.title" = "本地频道";
"app_info.features.mentions.description" = "使用 @nickname 提醒特定的人";
"app_info.features.mentions.title" = "提及";
"app_info.features.offline.description" = "利用低功耗 bluetooth 离线工作";
"app_info.features.offline.title" = "离线通信";
"app_info.features.title" = "功能";
"app_info.how_to_use.change_channels" = "• 轻点 #mesh 切换频道";
"app_info.how_to_use.clear_chat" = "• 三击聊天即可清除";
"app_info.how_to_use.commands" = "• 输入 / 查看指令";
"app_info.how_to_use.open_sidebar" = "• 轻点人物图标打开侧栏";
"app_info.how_to_use.set_nickname" = "• 轻点昵称即可设置";
"app_info.how_to_use.start_dm" = "• 轻点同伴名字开始 dm";
"app_info.how_to_use.title" = "使用方法";
"app_info.privacy.ephemeral.description" = "定期生成新的 peer id";
"app_info.privacy.ephemeral.title" = "临时身份";
"app_info.privacy.no_tracking.description" = "无服务器、无账号、无数据收集";
"app_info.privacy.no_tracking.title" = "无跟踪";
"app_info.privacy.panic.description" = "三击标志立即清除全部数据";
"app_info.privacy.panic.title" = "紧急模式";
"app_info.privacy.title" = "隐私";
"app_info.tagline" = "sidegroupchat";
"app_info.warning.message" = "私信安全尚未完全审计。在此警告消失前不要用于关键情境。";
"app_info.warning.title" = "警告";
"common.cancel" = "取消";
"common.close" = "关闭";
"common.copy" = "复制";
"common.ok" = "确定";
"common.toggle.off" = "关闭";
"common.toggle.on" = "开启";
"common.unknown" = "未知";
"content.accessibility.add_favorite" = "加入收藏";
"content.accessibility.available_nostr" = "通过 Nostr 可用";
"content.accessibility.back_to_main_chat" = "返回主聊天";
"content.accessibility.connected_mesh" = "通过 mesh 已连接";
"content.accessibility.encryption_status" = "加密状态:%@";
"content.accessibility.location_channels" = "位置频道";
"content.accessibility.location_notes" = "此位置的笔记";
"content.accessibility.open_unread_private_chat" = "打开未读私聊";
"content.accessibility.private_chat_header" = "与 %@ 的私聊";
"content.accessibility.reachable_mesh" = "可通过 mesh 到达";
"content.accessibility.remove_favorite" = "移出收藏";
"content.accessibility.send_hint_empty" = "输入要发送的消息";
"content.accessibility.send_hint_ready" = "双击发送";
"content.accessibility.send_message" = "发送消息";
"content.accessibility.toggle_bookmark" = "切换 #%@ 的书签";
"content.accessibility.toggle_favorite_hint" = "双击切换收藏状态";
"content.accessibility.view_fingerprint_hint" = "轻点查看加密指纹";
"content.actions.block" = "屏蔽";
"content.actions.direct_message" = "私信";
"content.actions.hug" = "拥抱";
"content.actions.mention" = "提及";
"content.actions.slap" = "拍打";
"content.actions.title" = "操作";
"content.alert.bluetooth_required.off" = "bluetooth 已关闭。请在设置中开启以使用 bitchat。";
"content.alert.bluetooth_required.permission" = "bitchat 需要 bluetooth 权限以连接附近设备。请在设置中启用访问。";
"content.alert.bluetooth_required.settings" = "设置";
"content.alert.bluetooth_required.title" = "需要 bluetooth";
"content.alert.bluetooth_required.unsupported" = "此设备不支持 bluetooth。bitchat 需要 bluetooth 才能运行。";
"content.alert.screenshot.message" = "位置频道的截图会暴露你的位置。公开分享前请三思。";
"content.alert.screenshot.title" = "注意";
"content.commands.block" = "屏蔽或查看已屏蔽的同伴";
"content.commands.clear" = "清除聊天消息";
"content.commands.favorite" = "加入收藏";
"content.commands.hug" = "送出温暖拥抱";
"content.commands.message" = "发送私信";
"content.commands.slap" = "用鳟鱼拍某人";
"content.commands.unblock" = "取消屏蔽同伴";
"content.commands.unfavorite" = "移出收藏";
"content.commands.who" = "查看谁在线";
"content.delivery.delivered_members" = "已送达 %2$d 人中的 %1$d 人";
"content.delivery.delivered_to" = "已送达 %@";
"content.delivery.failed" = "失败:%@";
"content.delivery.read_by" = "已读:%@";
"content.delivery.reason.blocked" = "用户已被屏蔽";
"content.delivery.reason.self" = "不能给自己发消息";
"content.delivery.reason.send_error" = "发送错误";
"content.delivery.reason.unknown_recipient" = "未知收件人";
"content.delivery.reason.unreachable" = "同伴不可达";
"content.header.people" = "成员";
"content.help.verification" = "验证:展示我的 qr 或扫描好友";
"content.input.message_placeholder" = "输入消息...";
"content.input.nickname_placeholder" = "昵称";
"content.location.enable" = "启用位置";
"content.message.copy" = "复制消息";
"content.message.show_less" = "收起";
"content.message.show_more" = "展开";
"content.notes.location_unavailable" = "位置不可用";
"content.notes.title" = "笔记";
"content.payment.cashu" = "通过 cashu 支付";
"content.payment.lightning" = "通过 lightning 支付";
"encryption.accessibility.establishing" = "正在建立加密";
"encryption.accessibility.failed" = "加密失败";
"encryption.accessibility.not_encrypted" = "未加密";
"encryption.accessibility.secured" = "已加密";
"encryption.accessibility.verified" = "已加密并验证";
"encryption.status.establishing" = "正在建立加密...";
"encryption.status.failed" = "加密失败";
"encryption.status.not_encrypted" = "未加密";
"encryption.status.secured" = "已加密";
"encryption.status.verified" = "已加密并验证";
"fingerprint.action.mark_verified" = "标记为已验证";
"fingerprint.action.remove_verification" = "移除验证";
"fingerprint.badge.not_verified" = "⚠️ 未验证";
"fingerprint.badge.verified" = "✓ 已验证";
"fingerprint.handshake_pending" = "暂不可用 - handshake 进行中";
"fingerprint.message.verified" = "你已经核实了此人的身份。";
"fingerprint.message.verify_hint" = "通过安全渠道与 %@ 比对这些指纹。";
"fingerprint.their_label" = "对方指纹:";
"fingerprint.title" = "安全验证";
"fingerprint.your_label" = "你的指纹:";
"geohash_people.action.block" = "屏蔽";
"geohash_people.action.unblock" = "取消屏蔽";
"geohash_people.none_nearby" = "附近没人...";
"geohash_people.tooltip.blocked" = "在 geohash 中已屏蔽";
"geohash_people.you_suffix" = " (你)";
"location_channels.action.open_settings" = "打开设置";
"location_channels.action.remove_access" = "移除位置访问";
"location_channels.action.request_permissions" = "获取位置和我的 geohash";
"location_channels.action.teleport" = "瞬移";
"location_channels.bookmarked_section_title" = "已收藏";
"location_channels.description" = "使用 geohash 频道与附近的人聊天。只会共享粗略 geohash,从不泄露精确 GPS。所有流量通过 tor 路由来隐藏你的 IP。";
"location_channels.error.invalid_geohash" = "无效的 geohash";
"location_channels.loading_nearby" = "正在寻找附近频道…";
"location_channels.mesh_label" = "mesh";
"location_channels.permission_denied" = "位置权限被拒。请在设置中启用以使用位置频道。";
"location_channels.subtitle_prefix" = "#%@ • %@";
"location_channels.subtitle_with_name" = "%1$@ • %2$@";
"location_channels.title" = "#位置频道";
"location_channels.tor.subtitle" = "为位置频道隐藏你的 IP。推荐:开启。";
"location_channels.tor.title" = "tor 路由";
"location_levels.block" = "街区";
"location_levels.building" = "楼栋";
"location_levels.city" = "城市";
"location_levels.neighborhood" = "社区";
"location_levels.province" = "省份";
"location_levels.region" = "区域";
"location_notes.action.dismiss" = "关闭";
"location_notes.action.retry" = "重试";
"location_notes.description" = "为此地点添加简短的常驻笔记,方便其他访客发现。";
"location_notes.empty_subtitle" = "成为这里的第一条笔记。";
"location_notes.empty_title" = "尚无笔记";
"location_notes.error.failed_to_send" = "无法发送笔记。%@";
"location_notes.error.no_relays" = "附近没有可用的地理中继。稍后再试。";
"location_notes.loading_notes" = "正在加载笔记…";
"location_notes.loading_recent" = "正在加载最新笔记…";
"location_notes.no_relays_nearby" = "附近没有地理中继";
"location_notes.placeholder" = "为此地点添加笔记";
"location_notes.relays_paused" = "地理中继不可用;笔记已暂停";
"location_notes.relays_retry_hint" = "笔记依赖地理中继。检查连接后再试。";
"mesh_peers.tooltip.new_messages" = "新消息";
"system.chat.blocked" = "无法与 %@ 开始聊天:用户已被屏蔽。";
"system.chat.requires_favorite" = "无法与 %@ 开始聊天:离线消息需要互相关注。";
"system.common.user" = "用户";
"system.dm.blocked_generic" = "无法发送:用户已被屏蔽。";
"system.dm.blocked_recipient" = "无法向 %@ 发送:用户已被屏蔽。";
"system.dm.unreachable" = "无法向 %@ 发送:对方无法通过 mesh 或 Nostr 到达。";
"system.geohash.blocked" = "已在 geohash 聊天中屏蔽 %@";
"system.geohash.unblocked" = "已在 geohash 聊天中解除屏蔽 %@";
"system.location.not_in_channel" = "发送失败:你不在位置频道中";
"system.location.send_failed" = "无法发送到位置频道";
"system.tor.dev_bypass" = "开发构建:tor 绕过已启用。";
"system.tor.restarted" = "tor 已重启。网络路由已恢复。";
"system.tor.restarting" = "tor 正在重启以恢复连接...";
"system.tor.started" = "tor 已启动。所有聊天通过 tor 路由以保护 IP。";
"system.tor.starting" = "正在启动 tor...";
"verification.my_qr.accessibility_label" = "验证 QR 码";
"verification.my_qr.title" = "扫描验证我";
"verification.my_qr.unavailable" = "QR 不可用";
"verification.scan.paste_prompt" = "粘贴 QR 内容以验证:";
"verification.scan.prompt_friend" = "扫描好友的 QR";
"verification.scan.status.invalid" = "QR 无效或已过期";
"verification.scan.status.no_peer" = "未找到匹配的同伴";
"verification.scan.status.requested" = "已请求 %@ 的验证";
"verification.scan.validate" = "验证";
"verification.sheet.title" = "验证";
@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>location_notes.header</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>#%@ • %#@note_count@</string>
<key>note_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d 条笔记</string>
<key>other</key>
<string>%d 条笔记</string>
</dict>
</dict>
<key>location_channels.row_title</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ [%#@people_count@]</string>
<key>people_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d 人</string>
<key>other</key>
<string>%d 人</string>
</dict>
</dict>
<key>content.accessibility.people_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@people@</string>
<key>people</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d 人</string>
<key>other</key>
<string>%d 人</string>
</dict>
</dict>
</dict>
</plist>
+6 -6
View File
@@ -24,17 +24,17 @@ enum GeohashChannelLevel: CaseIterable, Codable, Equatable {
var displayName: String {
switch self {
case .building:
return L10n.string("location_levels.building", comment: "Name for building-level location channel")
return String(localized: "location_levels.building", comment: "Name for building-level location channel")
case .block:
return L10n.string("location_levels.block", comment: "Name for block-level location channel")
return String(localized: "location_levels.block", comment: "Name for block-level location channel")
case .neighborhood:
return L10n.string("location_levels.neighborhood", comment: "Name for neighborhood-level location channel")
return String(localized: "location_levels.neighborhood", comment: "Name for neighborhood-level location channel")
case .city:
return L10n.string("location_levels.city", comment: "Name for city-level location channel")
return String(localized: "location_levels.city", comment: "Name for city-level location channel")
case .province:
return L10n.string("location_levels.province", comment: "Name for province-level location channel")
return String(localized: "location_levels.province", comment: "Name for province-level location channel")
case .region:
return L10n.string("location_levels.region", comment: "Name for region-level location channel")
return String(localized: "location_levels.region", comment: "Name for region-level location channel")
}
}
}
+4 -7
View File
@@ -77,15 +77,12 @@ final class LocationNotesManager: ObservableObject {
private let dependencies: LocationNotesDependencies
private enum Strings {
static let noRelays = L10n.string(
"location_notes.error.no_relays",
comment: "Shown when no geo relays are available near the selected location"
)
static let noRelays = String(localized: "location_notes.error.no_relays", comment: "Shown when no geo relays are available near the selected location")
static func failedToSend(_ detail: String) -> String {
L10n.string(
"location_notes.error.failed_to_send",
comment: "Shown when a location note fails to send",
String(
format: String(localized: "location_notes.error.failed_to_send", comment: "Shown when a location note fails to send"),
locale: .current,
detail
)
}
+10 -40
View File
@@ -115,60 +115,30 @@ enum EncryptionStatus: Equatable {
var description: String {
switch self {
case .none:
return L10n.string(
"encryption.status.failed",
comment: "Status text when encryption failed"
)
return String(localized: "encryption.status.failed", comment: "Status text when encryption failed")
case .noHandshake:
return L10n.string(
"encryption.status.not_encrypted",
comment: "Status text when no encryption handshake happened"
)
return String(localized: "encryption.status.not_encrypted", comment: "Status text when no encryption handshake happened")
case .noiseHandshaking:
return L10n.string(
"encryption.status.establishing",
comment: "Status text when encryption is being established"
)
return String(localized: "encryption.status.establishing", comment: "Status text when encryption is being established")
case .noiseSecured:
return L10n.string(
"encryption.status.secured",
comment: "Status text when encryption is secured but not verified"
)
return String(localized: "encryption.status.secured", comment: "Status text when encryption is secured but not verified")
case .noiseVerified:
return L10n.string(
"encryption.status.verified",
comment: "Status text when encryption is verified"
)
return String(localized: "encryption.status.verified", comment: "Status text when encryption is verified")
}
}
var accessibilityDescription: String {
switch self {
case .none:
return L10n.string(
"encryption.accessibility.failed",
comment: "Accessibility text when encryption failed"
)
return String(localized: "encryption.accessibility.failed", comment: "Accessibility text when encryption failed")
case .noHandshake:
return L10n.string(
"encryption.accessibility.not_encrypted",
comment: "Accessibility text when encryption is not established"
)
return String(localized: "encryption.accessibility.not_encrypted", comment: "Accessibility text when encryption is not established")
case .noiseHandshaking:
return L10n.string(
"encryption.accessibility.establishing",
comment: "Accessibility text when encryption is being established"
)
return String(localized: "encryption.accessibility.establishing", comment: "Accessibility text when encryption is being established")
case .noiseSecured:
return L10n.string(
"encryption.accessibility.secured",
comment: "Accessibility text when encryption is secured"
)
return String(localized: "encryption.accessibility.secured", comment: "Accessibility text when encryption is secured")
case .noiseVerified:
return L10n.string(
"encryption.accessibility.verified",
comment: "Accessibility text when encryption is verified"
)
return String(localized: "encryption.accessibility.verified", comment: "Accessibility text when encryption is verified")
}
}
}
-21
View File
@@ -1,21 +0,0 @@
import Foundation
enum L10n {
static func string(_ key: String, comment: String, _ args: CVarArg...) -> String {
let basic = NSLocalizedString(key, bundle: .localization, comment: comment)
if args.isEmpty {
return basic
}
return String(format: basic, locale: .current, arguments: args)
}
}
private extension Bundle {
static var localization: Bundle {
#if SWIFT_PACKAGE
return Bundle.module
#else
return Bundle.main
#endif
}
}
+41 -93
View File
@@ -554,20 +554,14 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
if TorManager.shared.torEnforced && !torStatusAnnounced && TorManager.shared.isAutoStartAllowed() {
torStatusAnnounced = true
addGeohashOnlySystemMessage(
L10n.string(
"system.tor.starting",
comment: "System message when Tor is starting"
)
String(localized: "system.tor.starting", comment: "System message when Tor is starting")
)
// Suppress incremental Tor progress messages
torProgressCancellable = nil
} else if !TorManager.shared.torEnforced && !torStatusAnnounced {
torStatusAnnounced = true
addGeohashOnlySystemMessage(
L10n.string(
"system.tor.dev_bypass",
comment: "System message when Tor bypass is enabled in development"
)
String(localized: "system.tor.dev_bypass", comment: "System message when Tor bypass is enabled in development")
)
}
@@ -866,10 +860,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
self.torStatusAnnounced = true
// Post only in geohash channels (queue if not active)
self.addGeohashOnlySystemMessage(
L10n.string(
"system.tor.starting",
comment: "System message when Tor is starting"
)
String(localized: "system.tor.starting", comment: "System message when Tor is starting")
)
}
}
@@ -879,10 +870,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
self.torRestartPending = true
// Post only in geohash channels (queue if not active)
self.addGeohashOnlySystemMessage(
L10n.string(
"system.tor.restarting",
comment: "System message when Tor is restarting"
)
String(localized: "system.tor.restarting", comment: "System message when Tor is restarting")
)
}
}
@@ -893,19 +881,13 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
if self.torRestartPending {
// Post only in geohash channels (queue if not active)
self.addGeohashOnlySystemMessage(
L10n.string(
"system.tor.restarted",
comment: "System message when Tor has restarted"
)
String(localized: "system.tor.restarted", comment: "System message when Tor has restarted")
)
self.torRestartPending = false
} else if TorManager.shared.torEnforced && !self.torInitialReadyAnnounced {
// Initial start completed
self.addGeohashOnlySystemMessage(
L10n.string(
"system.tor.started",
comment: "System message when Tor has started"
)
String(localized: "system.tor.started", comment: "System message when Tor has started")
)
self.torInitialReadyAnnounced = true
}
@@ -1588,10 +1570,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
} catch {
SecureLogger.error("❌ Failed to send geohash message: \(error)", category: .session)
addSystemMessage(
L10n.string(
"system.location.send_failed",
comment: "System message when a location channel send fails"
)
String(localized: "system.location.send_failed", comment: "System message when a location channel send fails")
)
}
}
@@ -2077,9 +2056,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
for (k, v) in nostrKeyMapping where v.lowercased() == hex { nostrKeyMapping.removeValue(forKey: k) }
addSystemMessage(
L10n.string(
"system.geohash.blocked",
comment: "System message shown when a user is blocked in geohash chats",
String(
format: String(localized: "system.geohash.blocked", comment: "System message shown when a user is blocked in geohash chats"),
locale: .current,
displayName
)
)
@@ -2088,9 +2067,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
func unblockGeohashUser(pubkeyHexLowercased: String, displayName: String) {
identityManager.setNostrBlocked(pubkeyHexLowercased, isBlocked: false)
addSystemMessage(
L10n.string(
"system.geohash.unblocked",
comment: "System message shown when a user is unblocked in geohash chats",
String(
format: String(localized: "system.geohash.unblocked", comment: "System message shown when a user is unblocked in geohash chats"),
locale: .current,
displayName
)
)
@@ -2278,9 +2257,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
if unifiedPeerService.isBlocked(peerID) {
let nickname = meshService.peerNickname(peerID: peerID) ?? "user"
addSystemMessage(
L10n.string(
"system.dm.blocked_recipient",
comment: "System message when attempting to message a blocked user",
String(
format: String(localized: "system.dm.blocked_recipient", comment: "System message when attempting to message a blocked user"),
locale: .current,
nickname
)
)
@@ -2346,17 +2325,15 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// Update delivery status to failed
if let index = privateChats[peerID]?.firstIndex(where: { $0.id == messageID }) {
privateChats[peerID]?[index].deliveryStatus = .failed(
reason: L10n.string(
"content.delivery.reason.unreachable",
comment: "Failure reason when a peer is unreachable"
)
reason: String(localized: "content.delivery.reason.unreachable", comment: "Failure reason when a peer is unreachable")
)
}
let name = recipientNickname ?? "user"
addSystemMessage(
L10n.string(
"system.dm.unreachable",
comment: "System message when a recipient is unreachable",
recipientNickname ?? L10n.string("system.common.user", comment: "Fallback recipient name")
String(
format: String(localized: "system.dm.unreachable", comment: "System message when a recipient is unreachable"),
locale: .current,
name
)
)
}
@@ -2365,10 +2342,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
private func sendGeohashDM(_ content: String, to peerID: String) {
guard case .location(let ch) = activeChannel else {
addSystemMessage(
L10n.string(
"system.location.not_in_channel",
comment: "System message when attempting to send without being in a location channel"
)
String(localized: "system.location.not_in_channel", comment: "System message when attempting to send without being in a location channel")
)
return
}
@@ -2399,10 +2373,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
guard let recipientHex = nostrKeyMapping[peerID] else {
if let msgIdx = privateChats[peerID]?.firstIndex(where: { $0.id == messageID }) {
privateChats[peerID]?[msgIdx].deliveryStatus = .failed(
reason: L10n.string(
"content.delivery.reason.unknown_recipient",
comment: "Failure reason when the recipient is unknown"
)
reason: String(localized: "content.delivery.reason.unknown_recipient", comment: "Failure reason when the recipient is unknown")
)
}
return
@@ -2412,17 +2383,11 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
if identityManager.isNostrBlocked(pubkeyHexLowercased: recipientHex) {
if let msgIdx = privateChats[peerID]?.firstIndex(where: { $0.id == messageID }) {
privateChats[peerID]?[msgIdx].deliveryStatus = .failed(
reason: L10n.string(
"content.delivery.reason.blocked",
comment: "Failure reason when the user is blocked"
)
reason: String(localized: "content.delivery.reason.blocked", comment: "Failure reason when the user is blocked")
)
}
addSystemMessage(
L10n.string(
"system.dm.blocked_generic",
comment: "System message when sending fails because user is blocked"
)
String(localized: "system.dm.blocked_generic", comment: "System message when sending fails because user is blocked")
)
return
}
@@ -2434,10 +2399,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
if recipientHex.lowercased() == id.publicKeyHex.lowercased() {
if let idx = privateChats[peerID]?.firstIndex(where: { $0.id == messageID }) {
privateChats[peerID]?[idx].deliveryStatus = .failed(
reason: L10n.string(
"content.delivery.reason.self",
comment: "Failure reason when attempting to message yourself"
)
reason: String(localized: "content.delivery.reason.self", comment: "Failure reason when attempting to message yourself")
)
}
return
@@ -2452,10 +2414,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
} catch {
if let idx = privateChats[peerID]?.firstIndex(where: { $0.id == messageID }) {
privateChats[peerID]?[idx].deliveryStatus = .failed(
reason: L10n.string(
"content.delivery.reason.send_error",
comment: "Failure reason for a generic send error"
)
reason: String(localized: "content.delivery.reason.send_error", comment: "Failure reason for a generic send error")
)
}
}
@@ -2515,22 +2474,13 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
switch state {
case .poweredOff:
bluetoothAlertMessage = L10n.string(
"content.alert.bluetooth_required.off",
comment: "Message shown when Bluetooth is turned off"
)
bluetoothAlertMessage = String(localized: "content.alert.bluetooth_required.off", comment: "Message shown when Bluetooth is turned off")
showBluetoothAlert = true
case .unauthorized:
bluetoothAlertMessage = L10n.string(
"content.alert.bluetooth_required.permission",
comment: "Message shown when Bluetooth permission is missing"
)
bluetoothAlertMessage = String(localized: "content.alert.bluetooth_required.permission", comment: "Message shown when Bluetooth permission is missing")
showBluetoothAlert = true
case .unsupported:
bluetoothAlertMessage = L10n.string(
"content.alert.bluetooth_required.unsupported",
comment: "Message shown when the device lacks Bluetooth support"
)
bluetoothAlertMessage = String(localized: "content.alert.bluetooth_required.unsupported", comment: "Message shown when the device lacks Bluetooth support")
showBluetoothAlert = true
case .poweredOn:
// Hide alert when Bluetooth is powered on
@@ -2561,9 +2511,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// Check if the peer is blocked
if unifiedPeerService.isBlocked(peerID) {
addSystemMessage(
L10n.string(
"system.chat.blocked",
comment: "System message when starting chat fails because peer is blocked",
String(
format: String(localized: "system.chat.blocked", comment: "System message when starting chat fails because peer is blocked"),
locale: .current,
peerNickname
)
)
@@ -2574,9 +2524,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
if let peer = unifiedPeerService.getPeer(by: peerID),
peer.isFavorite && !peer.theyFavoritedUs && !peer.isConnected {
addSystemMessage(
L10n.string(
"system.chat.requires_favorite",
comment: "System message when mutual favorite requirement blocks chat",
String(
format: String(localized: "system.chat.requires_favorite", comment: "System message when mutual favorite requirement blocks chat"),
locale: .current,
peerNickname
)
)
@@ -3034,10 +2984,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
} catch {
SecureLogger.error("❌ Failed to send geohash screenshot message: \(error)", category: .session)
self.addSystemMessage(
L10n.string(
"system.location.send_failed",
comment: "System message when a location channel send fails"
)
String(localized: "system.location.send_failed", comment: "System message when a location channel send fails")
)
}
}
@@ -3609,8 +3556,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
mentionStyle.font = .bitchatSystem(size: 14, weight: isSelf ? .bold : .semibold, design: .monospaced)
let mentionColor: Color = isMentionToMe ? .orange : baseColor
mentionStyle.foregroundColor = mentionColor
// Emit '@'
result.append(AttributedString("@").mergingAttributes(mentionStyle))
// Emit '@' (non-localizable symbol - use interpolation to avoid extraction)
let at = "@"
result.append(AttributedString("\(at)").mergingAttributes(mentionStyle))
// Base name
result.append(AttributedString(mBase).mergingAttributes(mentionStyle))
// Suffix in light grey
+59 -128
View File
@@ -190,10 +190,7 @@ struct ContentView: View {
}
}
.confirmationDialog(
selectedMessageSender.map { "@\($0)" } ?? L10n.string(
"content.actions.title",
comment: "Fallback title for the message action sheet"
),
selectedMessageSender.map { "@\($0)" } ?? String(localized: "content.actions.title", comment: "Fallback title for the message action sheet"),
isPresented: $showMessageActions,
titleVisibility: .visible
) {
@@ -352,10 +349,7 @@ struct ContentView: View {
let link = lightningLinks[i]
PaymentChipView(
emoji: "",
label: L10n.string(
"content.payment.lightning",
comment: "Label for Lightning payment chip"
),
label: String(localized: "content.payment.lightning", comment: "Label for Lightning payment chip"),
colorScheme: colorScheme
) {
#if os(iOS)
@@ -371,10 +365,7 @@ struct ContentView: View {
let urlStr = "cashu:\(enc)"
PaymentChipView(
emoji: "🥜",
label: L10n.string(
"content.payment.cashu",
comment: "Label for Cashu payment chip"
),
label: String(localized: "content.payment.cashu", comment: "Label for Cashu payment chip"),
colorScheme: colorScheme
) {
#if os(iOS)
@@ -845,18 +836,18 @@ struct ContentView: View {
}()
let isGeoDM: Bool = (viewModel.selectedPrivateChatPeer?.hasPrefix("nostr_") == true)
var commandDescriptions = [
("/block", L10n.string("content.commands.block", comment: "Description for /block command")),
("/clear", L10n.string("content.commands.clear", comment: "Description for /clear command")),
("/hug", L10n.string("content.commands.hug", comment: "Description for /hug command")),
("/m", L10n.string("content.commands.message", comment: "Description for /m command")),
("/slap", L10n.string("content.commands.slap", comment: "Description for /slap command")),
("/unblock", L10n.string("content.commands.unblock", comment: "Description for /unblock command")),
("/w", L10n.string("content.commands.who", comment: "Description for /w command"))
("/block", String(localized: "content.commands.block", comment: "Description for /block command")),
("/clear", String(localized: "content.commands.clear", comment: "Description for /clear command")),
("/hug", String(localized: "content.commands.hug", comment: "Description for /hug command")),
("/m", String(localized: "content.commands.message", comment: "Description for /m command")),
("/slap", String(localized: "content.commands.slap", comment: "Description for /slap command")),
("/unblock", String(localized: "content.commands.unblock", comment: "Description for /unblock command")),
("/w", String(localized: "content.commands.who", comment: "Description for /w command"))
]
// Only show favorites commands when not in geohash context
if !(isGeoPublic || isGeoDM) {
commandDescriptions.append(("/fav", L10n.string("content.commands.favorite", comment: "Description for /fav command")))
commandDescriptions.append(("/unfav", L10n.string("content.commands.unfavorite", comment: "Description for /unfav command")))
commandDescriptions.append(("/fav", String(localized: "content.commands.favorite", comment: "Description for /fav command")))
commandDescriptions.append(("/unfav", String(localized: "content.commands.unfavorite", comment: "Description for /unfav command")))
}
let input = newValue.lowercased()
@@ -903,21 +894,12 @@ struct ContentView: View {
.buttonStyle(.plain)
.padding(.trailing, 12)
.accessibilityLabel(
L10n.string(
"content.accessibility.send_message",
comment: "Accessibility label for the send message button"
)
String(localized: "content.accessibility.send_message", comment: "Accessibility label for the send message button")
)
.accessibilityHint(
messageText.isEmpty
? L10n.string(
"content.accessibility.send_hint_empty",
comment: "Hint prompting the user to enter a message"
)
: L10n.string(
"content.accessibility.send_hint_ready",
comment: "Hint prompting the user to send the message"
)
? String(localized: "content.accessibility.send_hint_empty", comment: "Hint prompting the user to enter a message")
: String(localized: "content.accessibility.send_hint_ready", comment: "Hint prompting the user to send the message")
)
}
.padding(.vertical, 8)
@@ -962,10 +944,7 @@ struct ContentView: View {
}
.buttonStyle(.plain)
.help(
L10n.string(
"content.help.verification",
comment: "Help text for verification button"
)
String(localized: "content.help.verification", comment: "Help text for verification button")
)
}
}
@@ -1119,7 +1098,7 @@ struct ContentView: View {
private var mainHeaderView: some View {
HStack(spacing: 0) {
Text("bitchat/")
Text(verbatim: "bitchat/")
.font(.bitchatSystem(size: 18, weight: .medium, design: .monospaced))
.foregroundColor(textColor)
.onTapGesture(count: 3) {
@@ -1132,7 +1111,7 @@ struct ContentView: View {
}
HStack(spacing: 0) {
Text("@")
Text(verbatim: "@")
.font(.bitchatSystem(size: 14, design: .monospaced))
.foregroundColor(secondaryTextColor)
@@ -1182,10 +1161,7 @@ struct ContentView: View {
}
.buttonStyle(.plain)
.accessibilityLabel(
L10n.string(
"content.accessibility.open_unread_private_chat",
comment: "Accessibility label for the unread private chat button"
)
String(localized: "content.accessibility.open_unread_private_chat", comment: "Accessibility label for the unread private chat button")
)
}
// Notes icon (mesh only and when location is authorized), to the left of #mesh
@@ -1210,10 +1186,7 @@ struct ContentView: View {
}
.buttonStyle(.plain)
.accessibilityLabel(
L10n.string(
"content.accessibility.location_notes",
comment: "Accessibility label for location notes button"
)
String(localized: "content.accessibility.location_notes", comment: "Accessibility label for location notes button")
)
}
@@ -1225,9 +1198,9 @@ struct ContentView: View {
}
.buttonStyle(.plain)
.accessibilityLabel(
L10n.string(
"content.accessibility.toggle_bookmark",
comment: "Accessibility label for toggling a geohash bookmark",
String(
format: String(localized: "content.accessibility.toggle_bookmark", comment: "Accessibility label for toggling a geohash bookmark"),
locale: .current,
ch.geohash
)
)
@@ -1256,10 +1229,7 @@ struct ContentView: View {
.fixedSize(horizontal: true, vertical: false)
.layoutPriority(2)
.accessibilityLabel(
L10n.string(
"content.accessibility.location_channels",
comment: "Accessibility label for the location channels button"
)
String(localized: "content.accessibility.location_channels", comment: "Accessibility label for the location channels button")
)
}
.buttonStyle(.plain)
@@ -1271,9 +1241,9 @@ struct ContentView: View {
Image(systemName: "person.2.fill")
.font(.system(size: headerPeerIconSize, weight: .regular))
.accessibilityLabel(
L10n.string(
"content.accessibility.people_count",
comment: "Accessibility label announcing number of people in header",
String(
format: String(localized: "content.accessibility.people_count", comment: "Accessibility label announcing number of people in header"),
locale: .current,
headerOtherPeersCount
)
)
@@ -1325,10 +1295,7 @@ struct ContentView: View {
.frame(width: 32, height: 32)
}
.buttonStyle(.plain)
.accessibilityLabel(L10n.string(
"common.close",
comment: "Accessibility label for close buttons"
))
.accessibilityLabel(String(localized: "common.close", comment: "Accessibility label for close buttons"))
}
.frame(height: headerHeight)
.padding(.horizontal, 12)
@@ -1453,10 +1420,7 @@ struct ContentView: View {
if !social.claimedNickname.isEmpty { return social.claimedNickname }
}
}
return L10n.string(
"common.unknown",
comment: "Fallback label for unknown peer"
)
return String(localized: "common.unknown", comment: "Fallback label for unknown peer")
}()
let isNostrAvailable: Bool = {
guard let connectionState = peer?.connectionState else {
@@ -1491,10 +1455,7 @@ struct ContentView: View {
.font(.bitchatSystem(size: 14))
.foregroundColor(textColor)
.accessibilityLabel(
L10n.string(
"content.accessibility.connected_mesh",
comment: "Accessibility label for mesh-connected peer indicator"
)
String(localized: "content.accessibility.connected_mesh", comment: "Accessibility label for mesh-connected peer indicator")
)
case .meshReachable:
// point.3 filled icon for reachable via mesh (not directly connected)
@@ -1502,10 +1463,7 @@ struct ContentView: View {
.font(.bitchatSystem(size: 14))
.foregroundColor(textColor)
.accessibilityLabel(
L10n.string(
"content.accessibility.reachable_mesh",
comment: "Accessibility label for mesh-reachable peer indicator"
)
String(localized: "content.accessibility.reachable_mesh", comment: "Accessibility label for mesh-reachable peer indicator")
)
case .nostrAvailable:
// Purple globe for Nostr
@@ -1513,10 +1471,7 @@ struct ContentView: View {
.font(.bitchatSystem(size: 14))
.foregroundColor(.purple)
.accessibilityLabel(
L10n.string(
"content.accessibility.available_nostr",
comment: "Accessibility label for Nostr-available peer indicator"
)
String(localized: "content.accessibility.available_nostr", comment: "Accessibility label for Nostr-available peer indicator")
)
case .offline:
// Should not happen for PM header, but handle gracefully
@@ -1528,10 +1483,7 @@ struct ContentView: View {
.font(.bitchatSystem(size: 14))
.foregroundColor(textColor)
.accessibilityLabel(
L10n.string(
"content.accessibility.reachable_mesh",
comment: "Accessibility label for mesh-reachable peer indicator"
)
String(localized: "content.accessibility.reachable_mesh", comment: "Accessibility label for mesh-reachable peer indicator")
)
} else if isNostrAvailable {
// Fallback to Nostr if peer not in list but is mutual favorite
@@ -1539,10 +1491,7 @@ struct ContentView: View {
.font(.bitchatSystem(size: 14))
.foregroundColor(.purple)
.accessibilityLabel(
L10n.string(
"content.accessibility.available_nostr",
comment: "Accessibility label for Nostr-available peer indicator"
)
String(localized: "content.accessibility.available_nostr", comment: "Accessibility label for Nostr-available peer indicator")
)
} else if viewModel.meshService.isPeerConnected(headerPeerID) || viewModel.connectedPeers.contains(headerPeerID) {
// Fallback: if peer lookup is missing but mesh reports connected, show radio
@@ -1550,10 +1499,7 @@ struct ContentView: View {
.font(.bitchatSystem(size: 14))
.foregroundColor(textColor)
.accessibilityLabel(
L10n.string(
"content.accessibility.connected_mesh",
comment: "Accessibility label for mesh-connected peer indicator"
)
String(localized: "content.accessibility.connected_mesh", comment: "Accessibility label for mesh-connected peer indicator")
)
}
@@ -1576,9 +1522,9 @@ struct ContentView: View {
encryptionStatus == .noiseSecured ? textColor :
Color.red)
.accessibilityLabel(
L10n.string(
"content.accessibility.encryption_status",
comment: "Accessibility label announcing encryption status",
String(
format: String(localized: "content.accessibility.encryption_status", comment: "Accessibility label announcing encryption status"),
locale: .current,
encryptionStatus.accessibilityDescription
)
)
@@ -1586,17 +1532,14 @@ struct ContentView: View {
}
}
.accessibilityLabel(
L10n.string(
"content.accessibility.private_chat_header",
comment: "Accessibility label describing the private chat header",
String(
format: String(localized: "content.accessibility.private_chat_header", comment: "Accessibility label describing the private chat header"),
locale: .current,
privatePeerNick
)
)
.accessibilityHint(
L10n.string(
"content.accessibility.view_fingerprint_hint",
comment: "Accessibility hint for viewing encryption fingerprint"
)
String(localized: "content.accessibility.view_fingerprint_hint", comment: "Accessibility hint for viewing encryption fingerprint")
)
}
.buttonStyle(.plain)
@@ -1617,10 +1560,7 @@ struct ContentView: View {
}
.buttonStyle(.plain)
.accessibilityLabel(
L10n.string(
"content.accessibility.back_to_main_chat",
comment: "Accessibility label for returning to main chat"
)
String(localized: "content.accessibility.back_to_main_chat", comment: "Accessibility label for returning to main chat")
)
Spacer()
@@ -1637,20 +1577,11 @@ struct ContentView: View {
.buttonStyle(.plain)
.accessibilityLabel(
viewModel.isFavorite(peerID: privatePeerID)
? L10n.string(
"content.accessibility.remove_favorite",
comment: "Accessibility label to remove a favorite"
)
: L10n.string(
"content.accessibility.add_favorite",
comment: "Accessibility label to add a favorite"
)
? String(localized: "content.accessibility.remove_favorite", comment: "Accessibility label to remove a favorite")
: String(localized: "content.accessibility.add_favorite", comment: "Accessibility label to add a favorite")
)
.accessibilityHint(
L10n.string(
"content.accessibility.toggle_favorite_hint",
comment: "Accessibility hint for toggling favorite status"
)
String(localized: "content.accessibility.toggle_favorite_hint", comment: "Accessibility hint for toggling favorite status")
)
}
}
@@ -1749,33 +1680,33 @@ struct DeliveryStatusView: View {
private enum Strings {
static func delivered(to nickname: String) -> String {
L10n.string(
"content.delivery.delivered_to",
comment: "Tooltip for delivered private messages",
String(
format: String(localized: "content.delivery.delivered_to", comment: "Tooltip for delivered private messages"),
locale: .current,
nickname
)
}
static func read(by nickname: String) -> String {
L10n.string(
"content.delivery.read_by",
comment: "Tooltip for read private messages",
String(
format: String(localized: "content.delivery.read_by", comment: "Tooltip for read private messages"),
locale: .current,
nickname
)
}
static func failed(_ reason: String) -> String {
L10n.string(
"content.delivery.failed",
comment: "Tooltip for failed message delivery",
String(
format: String(localized: "content.delivery.failed", comment: "Tooltip for failed message delivery"),
locale: .current,
reason
)
}
static func deliveredToMembers(_ reached: Int, _ total: Int) -> String {
L10n.string(
"content.delivery.delivered_members",
comment: "Tooltip for partially delivered messages",
String(
format: String(localized: "content.delivery.delivered_members", comment: "Tooltip for partially delivered messages"),
locale: .current,
reached,
total
)
@@ -1826,7 +1757,7 @@ struct DeliveryStatusView: View {
HStack(spacing: 1) {
Image(systemName: "checkmark")
.font(.bitchatSystem(size: 10))
Text("\(reached)/\(total)")
Text(verbatim: "\(reached)/\(total)")
.font(.bitchatSystem(size: 10, design: .monospaced))
}
.foregroundColor(secondaryTextColor.opacity(0.6))
+4 -7
View File
@@ -32,19 +32,16 @@ struct FingerprintView: View {
static let notVerifiedBadge: LocalizedStringKey = "fingerprint.badge.not_verified"
static let verifiedMessage: LocalizedStringKey = "fingerprint.message.verified"
static func verifyHint(_ nickname: String) -> String {
L10n.string(
"fingerprint.message.verify_hint",
comment: "Instruction to compare fingerprints with a named peer",
String(
format: String(localized: "fingerprint.message.verify_hint", comment: "Instruction to compare fingerprints with a named peer"),
locale: .current,
nickname
)
}
static let markVerified: LocalizedStringKey = "fingerprint.action.mark_verified"
static let removeVerification: LocalizedStringKey = "fingerprint.action.remove_verification"
static func unknownPeer() -> String {
L10n.string(
"common.unknown",
comment: "Label for an unknown peer"
)
String(localized: "common.unknown", comment: "Label for an unknown peer")
}
}
+1 -4
View File
@@ -11,10 +11,7 @@ struct GeohashPeopleList: View {
private enum Strings {
static let noneNearby: LocalizedStringKey = "geohash_people.none_nearby"
static let youSuffix: LocalizedStringKey = "geohash_people.you_suffix"
static let blockedTooltip = L10n.string(
"geohash_people.tooltip.blocked",
comment: "Tooltip shown next to users blocked in geohash channels"
)
static let blockedTooltip = String(localized: "geohash_people.tooltip.blocked", comment: "Tooltip shown next to users blocked in geohash channels")
static let unblock: LocalizedStringKey = "geohash_people.action.unblock"
static let block: LocalizedStringKey = "geohash_people.action.block"
}
+15 -23
View File
@@ -32,16 +32,10 @@ struct LocationChannelsSheet: View {
static let toggleOn: LocalizedStringKey = "common.toggle.on"
static let toggleOff: LocalizedStringKey = "common.toggle.off"
static let invalidGeohash = L10n.string(
"location_channels.error.invalid_geohash",
comment: "Error shown when a custom geohash is invalid"
)
static let invalidGeohash = String(localized: "location_channels.error.invalid_geohash", comment: "Error shown when a custom geohash is invalid")
static func meshTitle(_ count: Int) -> String {
let label = L10n.string(
"location_channels.mesh_label",
comment: "Label for the mesh channel row"
)
let label = String(localized: "location_channels.mesh_label", comment: "Label for the mesh channel row")
return rowTitle(label: label, count: count)
}
@@ -54,28 +48,26 @@ struct LocationChannelsSheet: View {
}
static func subtitlePrefix(geohash: String, coverage: String) -> String {
L10n.string(
"location_channels.subtitle_prefix",
comment: "Subtitle prefix showing geohash and coverage",
geohash,
coverage
String(
format: String(localized: "location_channels.subtitle_prefix", comment: "Subtitle prefix showing geohash and coverage"),
locale: .current,
geohash, coverage
)
}
static func subtitle(prefix: String, name: String?) -> String {
guard let name, !name.isEmpty else { return prefix }
return L10n.string(
"location_channels.subtitle_with_name",
comment: "Subtitle combining prefix and resolved location name",
prefix,
name
return String(
format: String(localized: "location_channels.subtitle_with_name", comment: "Subtitle combining prefix and resolved location name"),
locale: .current,
prefix, name
)
}
private static func rowTitle(label: String, count: Int) -> String {
L10n.string(
"location_channels.row_title",
comment: "List row title with participant count",
String(
format: String(localized: "location_channels.row_title", comment: "List row title with participant count"),
locale: .current,
label, count
)
}
@@ -271,7 +263,7 @@ struct LocationChannelsSheet: View {
private var customTeleportSection: some View {
VStack(alignment: .leading, spacing: 6) {
HStack(spacing: 2) {
Text("#")
Text(verbatim: "#")
.font(.bitchatSystem(size: 14, design: .monospaced))
.foregroundColor(.secondary)
TextField("geohash", text: $customGeohash)
@@ -427,7 +419,7 @@ struct LocationChannelsSheet: View {
}
Spacer()
if isSelected {
Text("✔︎")
Text(verbatim: "✔︎")
.font(.bitchatSystem(size: 16, design: .monospaced))
.foregroundColor(standardGreen)
}
+5 -8
View File
@@ -24,10 +24,7 @@ struct LocationNotesView: View {
private var maxDraftLines: Int { dynamicTypeSize.isAccessibilitySize ? 5 : 3 }
private enum Strings {
static let closeAccessibility = L10n.string(
"common.close",
comment: "Accessibility label for close buttons"
)
static let closeAccessibility = String(localized: "common.close", comment: "Accessibility label for close buttons")
static let description: LocalizedStringKey = "location_notes.description"
static let loadingRecent: LocalizedStringKey = "location_notes.loading_recent"
static let relaysPaused: LocalizedStringKey = "location_notes.relays_paused"
@@ -145,9 +142,9 @@ struct LocationNotesView: View {
}
private func headerTitle(for count: Int) -> String {
L10n.string(
"location_notes.header",
comment: "Header displaying the geohash and localized note count",
String(
format: String(localized: "location_notes.header", comment: "Header displaying the geohash and localized note count"),
locale: .current,
geohash, count
)
}
@@ -179,7 +176,7 @@ struct LocationNotesView: View {
let ts = timestampText(for: note.createdAt)
return VStack(alignment: .leading, spacing: 2) {
HStack(spacing: 6) {
Text("@\(baseName)")
Text(verbatim: "@\(baseName)")
.font(.bitchatSystem(size: 12, weight: .semibold, design: .monospaced))
if !ts.isEmpty {
Text(ts)
+2 -8
View File
@@ -13,14 +13,8 @@ struct MeshPeerList: View {
private enum Strings {
static let noneNearby: LocalizedStringKey = "geohash_people.none_nearby"
static let blockedTooltip = L10n.string(
"geohash_people.tooltip.blocked",
comment: "Tooltip shown next to a blocked peer indicator"
)
static let newMessagesTooltip = L10n.string(
"mesh_peers.tooltip.new_messages",
comment: "Tooltip for the unread messages indicator"
)
static let blockedTooltip = String(localized: "geohash_people.tooltip.blocked", comment: "Tooltip shown next to a blocked peer indicator")
static let newMessagesTooltip = String(localized: "mesh_peers.tooltip.new_messages", comment: "Tooltip for the unread messages indicator")
}
var body: some View {
+6 -15
View File
@@ -15,10 +15,7 @@ struct MyQRView: View {
private enum Strings {
static let title: LocalizedStringKey = "verification.my_qr.title"
static let accessibilityLabel = L10n.string(
"verification.my_qr.accessibility_label",
comment: "Accessibility label describing the verification QR code"
)
static let accessibilityLabel = String(localized: "verification.my_qr.accessibility_label", comment: "Accessibility label describing the verification QR code")
}
var body: some View {
@@ -120,20 +117,14 @@ struct QRScanView: View {
static let pastePrompt: LocalizedStringKey = "verification.scan.paste_prompt"
static let validate: LocalizedStringKey = "verification.scan.validate"
static func requested(_ nickname: String) -> String {
L10n.string(
"verification.scan.status.requested",
comment: "Status text when verification is requested for a nickname",
String(
format: String(localized: "verification.scan.status.requested", comment: "Status text when verification is requested for a nickname"),
locale: .current,
nickname
)
}
static let notFound = L10n.string(
"verification.scan.status.no_peer",
comment: "Status when no matching peer is found for a verification request"
)
static let invalid = L10n.string(
"verification.scan.status.invalid",
comment: "Status when a scanned QR payload is invalid"
)
static let notFound = String(localized: "verification.scan.status.no_peer", comment: "Status when no matching peer is found for a verification request")
static let invalid = String(localized: "verification.scan.status.invalid", comment: "Status when a scanned QR payload is invalid")
}
var body: some View {
@@ -1,14 +0,0 @@
/*
Localizable.strings
bitchatShareExtension
Base English strings for the share extension.
*/
"share.status.nothing_to_share" = "nothing to share";
"share.status.no_shareable_content" = "no shareable content";
"share.fallback.shared_link_title" = "shared Link";
"share.status.shared_link" = "✓ shared link to bitchat";
"share.status.shared_text" = "✓ shared text to bitchat";
"share.status.failed_to_encode" = "failed to encode link";
@@ -0,0 +1,666 @@
{
"sourceLanguage": "en",
"strings": {
"share.fallback.shared_link_title": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "shared Link",
"comment": "Fallback title when saving a shared link"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "رابط مشترك",
"comment": "Fallback title when saving a shared link"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "geteilter link",
"comment": "Fallback title when saving a shared link"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "enlace compartido",
"comment": "Fallback title when saving a shared link"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "lien partagé",
"comment": "Fallback title when saving a shared link"
}
},
"he": {
"stringUnit": {
"state": "translated",
"value": "קישור משותף",
"comment": "Fallback title when saving a shared link"
}
},
"id": {
"stringUnit": {
"state": "translated",
"value": "tautan dibagikan",
"comment": "Fallback title when saving a shared link"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "link condiviso",
"comment": "Fallback title when saving a shared link"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "共有リンク",
"comment": "Fallback title when saving a shared link"
}
},
"ne": {
"stringUnit": {
"state": "translated",
"value": "साझा गरिएको लिङ्क",
"comment": "Fallback title when saving a shared link"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "link compartilhado",
"comment": "Fallback title when saving a shared link"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "поделился ссылкой",
"comment": "Fallback title when saving a shared link"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "спільне посилання",
"comment": "Fallback title when saving a shared link"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "分享的链接",
"comment": "Fallback title when saving a shared link"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "공유된 링크",
"comment": "Fallback title when saving a shared link"
}
}
}
},
"share.status.failed_to_encode": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "failed to encode link",
"comment": "Shown when the share payload cannot be encoded"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "تعذر ترميز الرابط",
"comment": "Shown when the share payload cannot be encoded"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "link konnte nicht codiert werden",
"comment": "Shown when the share payload cannot be encoded"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "no se pudo codificar el enlace",
"comment": "Shown when the share payload cannot be encoded"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "échec de l'encodage du lien",
"comment": "Shown when the share payload cannot be encoded"
}
},
"he": {
"stringUnit": {
"state": "translated",
"value": "לא ניתן לקודד את הקישור",
"comment": "Shown when the share payload cannot be encoded"
}
},
"id": {
"stringUnit": {
"state": "translated",
"value": "gagal mengodekan tautan",
"comment": "Shown when the share payload cannot be encoded"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "impossibile codificare il link",
"comment": "Shown when the share payload cannot be encoded"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "リンクのエンコードに失敗しました",
"comment": "Shown when the share payload cannot be encoded"
}
},
"ne": {
"stringUnit": {
"state": "translated",
"value": "लिङ्क सङ्केत गर्न सकेन",
"comment": "Shown when the share payload cannot be encoded"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "falha ao codificar link",
"comment": "Shown when the share payload cannot be encoded"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "не удалось закодировать ссылку",
"comment": "Shown when the share payload cannot be encoded"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "не вдалося закодувати посилання",
"comment": "Shown when the share payload cannot be encoded"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "无法编码链接",
"comment": "Shown when the share payload cannot be encoded"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "링크를 인코딩하는 데 실패했습니다",
"comment": "Shown when the share payload cannot be encoded"
}
}
}
},
"share.status.no_shareable_content": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "no shareable content",
"comment": "Shown when provided content cannot be shared"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "لا محتوى قابلاً للمشاركة",
"comment": "Shown when provided content cannot be shared"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "kein teilbarer inhalt",
"comment": "Shown when provided content cannot be shared"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "sin contenido que se pueda compartir",
"comment": "Shown when provided content cannot be shared"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "aucun contenu partageable",
"comment": "Shown when provided content cannot be shared"
}
},
"he": {
"stringUnit": {
"state": "translated",
"value": "אין תוכן שניתן לשתף",
"comment": "Shown when provided content cannot be shared"
}
},
"id": {
"stringUnit": {
"state": "translated",
"value": "tidak ada konten yang bisa dibagikan",
"comment": "Shown when provided content cannot be shared"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "nessun contenuto condivisibile",
"comment": "Shown when provided content cannot be shared"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "共有可能なコンテンツがありません",
"comment": "Shown when provided content cannot be shared"
}
},
"ne": {
"stringUnit": {
"state": "translated",
"value": "बाँड्न मिल्ने सामग्री छैन",
"comment": "Shown when provided content cannot be shared"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "nenhum conteúdo compartilhável",
"comment": "Shown when provided content cannot be shared"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "нет подходящего контента",
"comment": "Shown when provided content cannot be shared"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "нема відповідного контенту",
"comment": "Shown when provided content cannot be shared"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "没有可分享的素材",
"comment": "Shown when provided content cannot be shared"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "공유할 수 있는 내용이 없습니다",
"comment": "Shown when provided content cannot be shared"
}
}
}
},
"share.status.nothing_to_share": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "nothing to share",
"comment": "Shown when the share extension receives no content"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "لا شيء لمشاركته",
"comment": "Shown when the share extension receives no content"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "nichts zum teilen",
"comment": "Shown when the share extension receives no content"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "nada que compartir",
"comment": "Shown when the share extension receives no content"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "rien à partager",
"comment": "Shown when the share extension receives no content"
}
},
"he": {
"stringUnit": {
"state": "translated",
"value": "אין מה לשתף",
"comment": "Shown when the share extension receives no content"
}
},
"id": {
"stringUnit": {
"state": "translated",
"value": "tidak ada yang bisa dibagikan",
"comment": "Shown when the share extension receives no content"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "niente da condividere",
"comment": "Shown when the share extension receives no content"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "共有できるものがありません",
"comment": "Shown when the share extension receives no content"
}
},
"ne": {
"stringUnit": {
"state": "translated",
"value": "बाँड्ने केही छैन",
"comment": "Shown when the share extension receives no content"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "nada para compartilhar",
"comment": "Shown when the share extension receives no content"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "нечем поделиться",
"comment": "Shown when the share extension receives no content"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "нема чим ділитися",
"comment": "Shown when the share extension receives no content"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "没有可分享的内容",
"comment": "Shown when the share extension receives no content"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "공유할 내용이 없습니다",
"comment": "Shown when the share extension receives no content"
}
}
}
},
"share.status.shared_link": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "✓ shared link to bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "✓ تم إرسال الرابط إلى bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "✓ link zu bitchat geteilt",
"comment": "Confirmation after successfully sharing a link"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "✓ enlace compartido con bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "✓ lien partagé vers bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"he": {
"stringUnit": {
"state": "translated",
"value": "✓ הקישור נשלח אל bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"id": {
"stringUnit": {
"state": "translated",
"value": "✓ tautan dikirim ke bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "✓ link inviato a bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "✓ bitchatにリンクを共有",
"comment": "Confirmation after successfully sharing a link"
}
},
"ne": {
"stringUnit": {
"state": "translated",
"value": "✓ bitchat मा लिङ्क पठाइयो",
"comment": "Confirmation after successfully sharing a link"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "✓ link enviado para bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "✓ ссылка отправлена в bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "✓ посилання надіслано в bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "✓ 已将链接分享至 bitchat",
"comment": "Confirmation after successfully sharing a link"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "✓ bitchat으로 링크를 공유했습니다",
"comment": "Confirmation after successfully sharing a link"
}
}
}
},
"share.status.shared_text": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "✓ shared text to bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"ar": {
"stringUnit": {
"state": "translated",
"value": "✓ تم إرسال النص إلى bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"de": {
"stringUnit": {
"state": "translated",
"value": "✓ text zu bitchat geteilt",
"comment": "Confirmation after successfully sharing text"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "✓ texto compartido con bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "✓ texte partagé vers bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"he": {
"stringUnit": {
"state": "translated",
"value": "✓ הטקסט נשלח אל bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"id": {
"stringUnit": {
"state": "translated",
"value": "✓ teks dikirim ke bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"it": {
"stringUnit": {
"state": "translated",
"value": "✓ testo inviato a bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "✓ bitchatにテキストを共有",
"comment": "Confirmation after successfully sharing text"
}
},
"ne": {
"stringUnit": {
"state": "translated",
"value": "✓ bitchat मा पाठ पठाइयो",
"comment": "Confirmation after successfully sharing text"
}
},
"pt-BR": {
"stringUnit": {
"state": "translated",
"value": "✓ texto enviado para bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"ru": {
"stringUnit": {
"state": "translated",
"value": "✓ текст отправлен в bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"uk": {
"stringUnit": {
"state": "translated",
"value": "✓ текст надіслано в bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "✓ 已将文本分享至 bitchat",
"comment": "Confirmation after successfully sharing text"
}
},
"ko": {
"stringUnit": {
"state": "translated",
"value": "✓ bitchat으로 텍스트를 공유했습니다",
"comment": "Confirmation after successfully sharing text"
}
}
}
}
},
"version": "1.0"
}
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Arabic)
*/
"share.status.nothing_to_share" = "لا شيء لمشاركته";
"share.status.no_shareable_content" = "لا محتوى قابلاً للمشاركة";
"share.fallback.shared_link_title" = "رابط مشترك";
"share.status.shared_link" = "✓ تم إرسال الرابط إلى bitchat";
"share.status.shared_text" = "✓ تم إرسال النص إلى bitchat";
"share.status.failed_to_encode" = "تعذر ترميز الرابط";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (German)
*/
"share.status.nothing_to_share" = "nichts zum teilen";
"share.status.no_shareable_content" = "kein teilbarer inhalt";
"share.fallback.shared_link_title" = "geteilter link";
"share.status.shared_link" = "✓ link zu bitchat geteilt";
"share.status.shared_text" = "✓ text zu bitchat geteilt";
"share.status.failed_to_encode" = "link konnte nicht codiert werden";
@@ -1,12 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Spanish)
*/
"share.status.nothing_to_share" = "nada que compartir";
"share.status.no_shareable_content" = "sin contenido que se pueda compartir";
"share.fallback.shared_link_title" = "enlace compartido";
"share.status.shared_link" = "✓ enlace compartido con bitchat";
"share.status.shared_text" = "✓ texto compartido con bitchat";
"share.status.failed_to_encode" = "no se pudo codificar el enlace";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (French)
*/
"share.status.nothing_to_share" = "rien à partager";
"share.status.no_shareable_content" = "aucun contenu partageable";
"share.fallback.shared_link_title" = "lien partagé";
"share.status.shared_link" = "✓ lien partagé vers bitchat";
"share.status.shared_text" = "✓ texte partagé vers bitchat";
"share.status.failed_to_encode" = "échec de l'encodage du lien";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Hebrew)
*/
"share.status.nothing_to_share" = "אין מה לשתף";
"share.status.no_shareable_content" = "אין תוכן שניתן לשתף";
"share.fallback.shared_link_title" = "קישור משותף";
"share.status.shared_link" = "✓ הקישור נשלח אל bitchat";
"share.status.shared_text" = "✓ הטקסט נשלח אל bitchat";
"share.status.failed_to_encode" = "לא ניתן לקודד את הקישור";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Indonesian)
*/
"share.status.nothing_to_share" = "tidak ada yang bisa dibagikan";
"share.status.no_shareable_content" = "tidak ada konten yang bisa dibagikan";
"share.fallback.shared_link_title" = "tautan dibagikan";
"share.status.shared_link" = "✓ tautan dikirim ke bitchat";
"share.status.shared_text" = "✓ teks dikirim ke bitchat";
"share.status.failed_to_encode" = "gagal mengodekan tautan";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Italian)
*/
"share.status.nothing_to_share" = "niente da condividere";
"share.status.no_shareable_content" = "nessun contenuto condivisibile";
"share.fallback.shared_link_title" = "link condiviso";
"share.status.shared_link" = "✓ link inviato a bitchat";
"share.status.shared_text" = "✓ testo inviato a bitchat";
"share.status.failed_to_encode" = "impossibile codificare il link";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Japanese)
*/
"share.status.nothing_to_share" = "共有できるものがありません";
"share.status.no_shareable_content" = "共有可能なコンテンツがありません";
"share.fallback.shared_link_title" = "共有リンク";
"share.status.shared_link" = "✓ bitchatにリンクを共有";
"share.status.shared_text" = "✓ bitchatにテキストを共有";
"share.status.failed_to_encode" = "リンクのエンコードに失敗しました";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Nepali)
*/
"share.status.nothing_to_share" = "बाँड्ने केही छैन";
"share.status.no_shareable_content" = "बाँड्न मिल्ने सामग्री छैन";
"share.fallback.shared_link_title" = "साझा गरिएको लिङ्क";
"share.status.shared_link" = "✓ bitchat मा लिङ्क पठाइयो";
"share.status.shared_text" = "✓ bitchat मा पाठ पठाइयो";
"share.status.failed_to_encode" = "लिङ्क सङ्केत गर्न सकेन";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Portuguese - Brazil)
*/
"share.status.nothing_to_share" = "nada para compartilhar";
"share.status.no_shareable_content" = "nenhum conteúdo compartilhável";
"share.fallback.shared_link_title" = "link compartilhado";
"share.status.shared_link" = "✓ link enviado para bitchat";
"share.status.shared_text" = "✓ texto enviado para bitchat";
"share.status.failed_to_encode" = "falha ao codificar link";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Russian)
*/
"share.status.nothing_to_share" = "нечем поделиться";
"share.status.no_shareable_content" = "нет подходящего контента";
"share.fallback.shared_link_title" = "поделился ссылкой";
"share.status.shared_link" = "✓ ссылка отправлена в bitchat";
"share.status.shared_text" = "✓ текст отправлен в bitchat";
"share.status.failed_to_encode" = "не удалось закодировать ссылку";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Ukrainian)
*/
"share.status.nothing_to_share" = "нема чим ділитися";
"share.status.no_shareable_content" = "нема відповідного контенту";
"share.fallback.shared_link_title" = "спільне посилання";
"share.status.shared_link" = "✓ посилання надіслано в bitchat";
"share.status.shared_text" = "✓ текст надіслано в bitchat";
"share.status.failed_to_encode" = "не вдалося закодувати посилання";
@@ -1,11 +0,0 @@
/*
Localizable.strings
bitchatShareExtension (Simplified Chinese)
*/
"share.status.nothing_to_share" = "没有可分享的内容";
"share.status.no_shareable_content" = "没有可分享的素材";
"share.fallback.shared_link_title" = "分享的链接";
"share.status.shared_link" = "✓ 已将链接分享至 bitchat";
"share.status.shared_text" = "✓ 已将文本分享至 bitchat";
"share.status.failed_to_encode" = "无法编码链接";
@@ -16,12 +16,12 @@ final class ShareViewController: UIViewController {
private static let groupID = "group.chat.bitchat"
private enum Strings {
static let nothingToShare = L10n.string("share.status.nothing_to_share", comment: "Shown when the share extension receives no content")
static let noShareableContent = L10n.string("share.status.no_shareable_content", comment: "Shown when provided content cannot be shared")
static let sharedLinkTitleFallback = L10n.string("share.fallback.shared_link_title", comment: "Fallback title when saving a shared link")
static let sharedLinkConfirmation = L10n.string("share.status.shared_link", comment: "Confirmation after successfully sharing a link")
static let sharedTextConfirmation = L10n.string("share.status.shared_text", comment: "Confirmation after successfully sharing text")
static let failedToEncode = L10n.string("share.status.failed_to_encode", comment: "Shown when the share payload cannot be encoded")
static let nothingToShare = String(localized: "share.status.nothing_to_share", comment: "Shown when the share extension receives no content")
static let noShareableContent = String(localized: "share.status.no_shareable_content", comment: "Shown when provided content cannot be shared")
static let sharedLinkTitleFallback = String(localized: "share.fallback.shared_link_title", comment: "Fallback title when saving a shared link")
static let sharedLinkConfirmation = String(localized: "share.status.shared_link", comment: "Confirmation after successfully sharing a link")
static let sharedTextConfirmation = String(localized: "share.status.shared_text", comment: "Confirmation after successfully sharing text")
static let failedToEncode = String(localized: "share.status.failed_to_encode", comment: "Shown when the share payload cannot be encoded")
}
private let statusLabel: UILabel = {
@@ -0,0 +1,367 @@
import Foundation
import XCTest
private let localizationTestsDirectoryURL = URL(fileURLWithPath: #filePath).deletingLastPathComponent()
private let testsRootURL = localizationTestsDirectoryURL.deletingLastPathComponent()
private let repoRootURL = testsRootURL.deletingLastPathComponent()
final class LocalizationCatalogTests: XCTestCase {
// Ensures every app locale includes exactly the same keys as Base.
func testAppCatalogLocaleParity() throws {
let context = try loadContext(relativePath: "bitchat/Localizable.xcstrings")
assertLocaleParity(context: context, catalogName: "App")
}
// Verifies format placeholders stay consistent across app locales.
func testAppCatalogPlaceholderConsistency() throws {
let context = try loadContext(relativePath: "bitchat/Localizable.xcstrings")
assertPlaceholderConsistency(context: context, catalogName: "App")
}
// Guards a core set of app strings from going empty per locale.
func testAppPrimaryKeysNonEmpty() throws {
let context = try loadContext(relativePath: "bitchat/Localizable.xcstrings")
let primaryKeys = try loadPrimaryKeys().app
assertPrimaryKeysPresent(context: context, keys: primaryKeys, catalogName: "App")
}
// Ensures every share extension locale matches Base key coverage.
func testShareExtensionCatalogLocaleParity() throws {
let context = try loadContext(relativePath: "bitchatShareExtension/Localization/Localizable.xcstrings")
assertLocaleParity(context: context, catalogName: "ShareExtension")
}
// Verifies share extension placeholders align across locales.
func testShareExtensionCatalogPlaceholderConsistency() throws {
let context = try loadContext(relativePath: "bitchatShareExtension/Localization/Localizable.xcstrings")
assertPlaceholderConsistency(context: context, catalogName: "ShareExtension")
}
// Confirms critical share extension strings remain non-empty per locale.
func testShareExtensionPrimaryKeysNonEmpty() throws {
let context = try loadContext(relativePath: "bitchatShareExtension/Localization/Localizable.xcstrings")
let primaryKeys = try loadPrimaryKeys().shareExtension
assertPrimaryKeysPresent(context: context, keys: primaryKeys, catalogName: "ShareExtension")
}
// Validates that configured locales contain expected string values.
func testLocalizationExpectedValues() throws {
let appContext = try loadContext(relativePath: "bitchat/Localizable.xcstrings")
let shareContext = try loadContext(relativePath: "bitchatShareExtension/Localization/Localizable.xcstrings")
let config = try loadPrimaryKeys()
guard let testLocales = config.testLocales else {
// If no testLocales specified, skip this test
return
}
guard let expectedValues = config.expectedValues else {
XCTFail("No expectedValues configured in PrimaryLocalizationKeys.json")
return
}
// Loop through each locale to test
for locale in testLocales {
guard let localeExpectedValues = expectedValues[locale] else {
XCTFail("No expected values configured for locale '\(locale)' in PrimaryLocalizationKeys.json")
continue
}
// Test each expected key/value pair for this locale
for (key, expectedValue) in localeExpectedValues {
if config.app.contains(key) {
assertLocaleStringValue(context: appContext, locale: locale, key: key, expectedValue: expectedValue, catalogName: "App")
} else if config.shareExtension.contains(key) {
assertLocaleStringValue(context: shareContext, locale: locale, key: key, expectedValue: expectedValue, catalogName: "ShareExtension")
}
}
}
}
// Ensures configured test locales are present and complete.
func testConfiguredLocalesCompleteness() throws {
let appContext = try loadContext(relativePath: "bitchat/Localizable.xcstrings")
let shareContext = try loadContext(relativePath: "bitchatShareExtension/Localization/Localizable.xcstrings")
let config = try loadPrimaryKeys()
guard let testLocales = config.testLocales else {
// If no testLocales specified, skip this test
return
}
let baseLocale = appContext.baseLocale
let baseAppKeys = appContext.keysByLocale[baseLocale] ?? Set()
let baseShareKeys = shareContext.keysByLocale[baseLocale] ?? Set()
for locale in testLocales {
// Skip base locale comparison with itself
if locale == baseLocale { continue }
// Verify locale is present in both catalogs
XCTAssertTrue(appContext.locales.contains(locale), "Locale '\(locale)' missing from app catalog")
XCTAssertTrue(shareContext.locales.contains(locale), "Locale '\(locale)' missing from share extension catalog")
// Verify locale has same number of keys as base locale
let appLocaleKeys = appContext.keysByLocale[locale] ?? Set()
XCTAssertEqual(appLocaleKeys.count, baseAppKeys.count, "Locale '\(locale)' app catalog missing keys compared to \(baseLocale)")
let shareLocaleKeys = shareContext.keysByLocale[locale] ?? Set()
XCTAssertEqual(shareLocaleKeys.count, baseShareKeys.count, "Locale '\(locale)' share extension catalog missing keys compared to \(baseLocale)")
}
}
// MARK: - Assertions
private func assertLocaleParity(context: CatalogContext, catalogName: String, file: StaticString = #filePath, line: UInt = #line) {
let baseLocale = context.baseLocale
guard let baseKeys = context.keysByLocale[baseLocale] else {
return XCTFail("Missing base locale \(baseLocale) in \(catalogName) catalog", file: file, line: line)
}
for (locale, keys) in context.keysByLocale.sorted(by: { $0.key < $1.key }) {
XCTAssertEqual(keys, baseKeys, "Locale \(locale) has key mismatch in \(catalogName) catalog", file: file, line: line)
}
}
private func assertPlaceholderConsistency(context: CatalogContext, catalogName: String, file: StaticString = #filePath, line: UInt = #line) {
let baseLocale = context.baseLocale
guard let baseSignatures = context.placeholderSignature[baseLocale] else {
return XCTFail("Missing base placeholder signature for \(catalogName)", file: file, line: line)
}
for (locale, localeSignatures) in context.placeholderSignature.sorted(by: { $0.key < $1.key }) {
guard locale != baseLocale else { continue }
for key in baseSignatures.keys.sorted() {
guard let baseMap = baseSignatures[key] else {
continue
}
guard let localeMap = localeSignatures[key] else {
return XCTFail("Key \(key) missing for locale \(locale) in \(catalogName) catalog", file: file, line: line)
}
for path in baseMap.keys.sorted() {
let expected = normalizedPlaceholders(baseMap[path, default: []])
let actual = normalizedPlaceholders(localeMap[path, default: []])
XCTAssertEqual(actual, expected, "Placeholder mismatch for key \(key) at \(path) in locale \(locale) (\(catalogName))", file: file, line: line)
}
for (localePath, localeTokens) in localeMap {
guard baseMap[localePath] == nil else { continue }
guard let fallback = fallbackPath(for: localePath, baseMap: baseMap) else {
XCTFail("Unexpected variation \(localePath) for key \(key) in locale \(locale) (\(catalogName))", file: file, line: line)
continue
}
let expected = normalizedPlaceholders(baseMap[fallback, default: []])
let actual = normalizedPlaceholders(localeTokens)
XCTAssertEqual(actual, expected, "Placeholder mismatch for key \(key) at \(localePath) (fallback \(fallback)) in locale \(locale) (\(catalogName))", file: file, line: line)
}
}
}
}
private func assertPrimaryKeysPresent(context: CatalogContext, keys: [String], catalogName: String, file: StaticString = #filePath, line: UInt = #line) {
for key in keys {
guard let entry = context.catalog.strings[key] else {
XCTFail("Missing primary key \(key) in \(catalogName) catalog", file: file, line: line)
continue
}
for locale in context.locales.sorted() {
guard let localization = entry.localizations[locale], let unit = localization.stringUnit else {
XCTFail("Missing localization for key \(key) in locale \(locale) (\(catalogName))", file: file, line: line)
continue
}
let segments = gatherSegments(from: unit)
XCTAssertFalse(segments.isEmpty, "No content for key \(key) in locale \(locale) (\(catalogName))", file: file, line: line)
for segment in segments {
let trimmed = segment.value.trimmingCharacters(in: .whitespacesAndNewlines)
XCTAssertFalse(trimmed.isEmpty, "Empty translation for key \(key) at \(segment.path) in locale \(locale) (\(catalogName))", file: file, line: line)
}
}
}
}
private func assertLocaleStringValue(context: CatalogContext, locale: String, key: String, expectedValue: String, catalogName: String, file: StaticString = #filePath, line: UInt = #line) {
guard let entry = context.catalog.strings[key] else {
XCTFail("Missing key \(key) in \(catalogName) catalog", file: file, line: line)
return
}
guard let localization = entry.localizations[locale], let unit = localization.stringUnit else {
XCTFail("Missing \(locale) localization for key \(key) in \(catalogName) catalog", file: file, line: line)
return
}
// For simple strings (non-pluralized)
if let actualValue = unit.value {
XCTAssertEqual(actualValue, expectedValue, "\(locale) translation mismatch for key \(key) in \(catalogName) catalog. Expected: '\(expectedValue)', Actual: '\(actualValue)'", file: file, line: line)
} else {
XCTFail("Key \(key) has no value in \(locale) localization for \(catalogName) catalog", file: file, line: line)
}
}
// MARK: - Loading
private func loadContext(relativePath: String) throws -> CatalogContext {
let catalog = try loadCatalog(relativePath: relativePath)
let locales = catalog.locales
let baseLocale = catalog.sourceLanguage
var keysByLocale: [String: Set<String>] = [:]
var placeholderSignature: [String: [String: [String: [String]]]] = [:]
for locale in locales {
var localeKeys: Set<String> = []
var localePlaceholders: [String: [String: [String]]] = [:]
for (key, entry) in catalog.strings {
guard let localization = entry.localizations[locale], let unit = localization.stringUnit else {
continue
}
localeKeys.insert(key)
let segments = gatherSegments(from: unit)
var pathMap: [String: [String]] = [:]
for segment in segments {
pathMap[segment.path] = placeholders(in: segment.value)
}
localePlaceholders[key] = pathMap
}
keysByLocale[locale] = localeKeys
placeholderSignature[locale] = localePlaceholders
}
return CatalogContext(catalog: catalog, locales: locales, baseLocale: baseLocale, keysByLocale: keysByLocale, placeholderSignature: placeholderSignature)
}
private func loadCatalog(relativePath: String) throws -> StringCatalog {
let url = repoRootURL.appendingPathComponent(relativePath)
let data = try Data(contentsOf: url)
return try JSONDecoder().decode(StringCatalog.self, from: data)
}
private func loadPrimaryKeys() throws -> PrimaryKeyConfig {
let url = localizationTestsDirectoryURL.appendingPathComponent("PrimaryLocalizationKeys.json")
let data = try Data(contentsOf: url)
return try JSONDecoder().decode(PrimaryKeyConfig.self, from: data)
}
}
// MARK: - Helpers
private struct CatalogContext {
let catalog: StringCatalog
let locales: [String]
let baseLocale: String
let keysByLocale: [String: Set<String>]
let placeholderSignature: [String: [String: [String: [String]]]]
}
private struct StringCatalog: Decodable {
let sourceLanguage: String
let strings: [String: CatalogEntry]
var locales: [String] {
var localeSet: Set<String> = []
for entry in strings.values {
localeSet.formUnion(entry.localizations.keys)
}
return localeSet.sorted()
}
}
private struct CatalogEntry: Decodable {
let localizations: [String: CatalogLocalization]
}
private struct CatalogLocalization: Decodable {
let stringUnit: CatalogStringUnit?
}
private struct CatalogStringUnit: Decodable {
let state: String
let value: String?
let variations: CatalogVariations?
let comment: String?
}
private struct CatalogVariations: Decodable {
let plural: [String: [String: CatalogVariationValue]]?
}
private struct CatalogVariationValue: Decodable {
let stringUnit: CatalogStringUnit?
}
private struct Segment {
let components: [String]
let value: String
var path: String {
components.isEmpty ? "base" : components.joined(separator: ".")
}
}
private func gatherSegments(from unit: CatalogStringUnit, prefix: [String] = []) -> [Segment] {
var segments: [Segment] = []
if let value = unit.value {
segments.append(Segment(components: prefix, value: value))
} else if prefix.isEmpty {
segments.append(Segment(components: [], value: ""))
}
if let plural = unit.variations?.plural {
for (variable, categories) in plural.sorted(by: { $0.key < $1.key }) {
for (category, variation) in categories.sorted(by: { $0.key < $1.key }) {
if let nested = variation.stringUnit {
var nextPrefix = prefix
nextPrefix.append("plural")
nextPrefix.append(variable)
nextPrefix.append(category)
segments.append(contentsOf: gatherSegments(from: nested, prefix: nextPrefix))
}
}
}
}
return segments
}
private func normalizedPlaceholders(_ tokens: [String]) -> [String] {
tokens.sorted()
}
private func fallbackPath(for localePath: String, baseMap: [String: [String]]) -> String? {
let parts = localePath.split(separator: ".")
guard parts.count == 3, parts.first == "plural" else {
return nil
}
let variable = parts[1]
let otherKey = "plural.\(variable).other"
if baseMap[otherKey] != nil {
return otherKey
}
let oneKey = "plural.\(variable).one"
if baseMap[oneKey] != nil {
return oneKey
}
return nil
}
private let placeholderRegex: NSRegularExpression = {
let pattern = "%(?:\\d+\\$)?#@[A-Za-z0-9_]+@|%(?:\\d+\\$)?[#0\\- +'\"]*(?:\\d+|\\*)?(?:\\.\\d+)?(?:hh|h|ll|l|z|t|L)?[a-zA-Z@]"
return try! NSRegularExpression(pattern: pattern, options: [])
}()
private func placeholders(in string: String) -> [String] {
let range = NSRange(location: 0, length: (string as NSString).length)
let matches = placeholderRegex.matches(in: string, options: [], range: range)
var tokens: [String] = []
for match in matches {
if let range = Range(match.range, in: string) {
let token = String(string[range])
if token == "%%" { continue }
tokens.append(token)
}
}
return tokens
}
private struct PrimaryKeyConfig: Decodable {
let app: [String]
let shareExtension: [String]
let expectedValues: [String: [String: String]]?
let testLocales: [String]?
}
@@ -0,0 +1,450 @@
{
"app": [
"app_info.app_name",
"app_info.close",
"app_info.done",
"app_info.features.encryption.title",
"app_info.features.offline.title",
"app_info.warning.message",
"common.cancel",
"common.close",
"common.copy",
"common.ok",
"content.accessibility.people_count",
"content.accessibility.send_message",
"content.actions.title",
"content.alert.bluetooth_required.permission",
"content.alert.bluetooth_required.settings",
"content.alert.bluetooth_required.title",
"content.delivery.delivered_to",
"content.input.message_placeholder",
"fingerprint.action.mark_verified",
"fingerprint.badge.not_verified",
"fingerprint.badge.verified",
"fingerprint.title",
"location_channels.action.open_settings",
"location_channels.action.request_permissions",
"location_channels.title",
"location_notes.header",
"system.tor.started"
],
"shareExtension": [
"share.fallback.shared_link_title",
"share.status.failed_to_encode",
"share.status.no_shareable_content",
"share.status.nothing_to_share",
"share.status.shared_link",
"share.status.shared_text"
],
"expectedValues": {
"ar": {
"common.ok": "موافق",
"content.input.message_placeholder": "اكتب رسالة...",
"location_channels.title": "#قنوات الموقع",
"system.tor.started": "tor يعمل. كل الدردشة تمر عبر tor للخصوصية.",
"share.status.shared_text": "✓ تم إرسال النص إلى bitchat",
"share.status.shared_link": "✓ تم إرسال الرابط إلى bitchat",
"share.status.failed_to_encode": "تعذر ترميز الرابط",
"common.cancel": "إلغاء",
"common.close": "إغلاق",
"common.copy": "نسخ",
"app_info.close": "إغلاق",
"app_info.done": "تم",
"content.alert.bluetooth_required.permission": "تحتاج bitchat إلى إذن bluetooth للاتصال بالأجهزة القريبة. فعّل الوصول في الإعدادات.",
"content.alert.bluetooth_required.settings": "الإعدادات",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "تشفير طرف لطرف",
"app_info.features.offline.title": "تواصل بدون اتصال",
"fingerprint.badge.verified": "✓ مُتحقق",
"fingerprint.badge.not_verified": "⚠️ غير مُتحقق",
"fingerprint.action.mark_verified": "وضع علامة تم التحقق",
"location_channels.action.open_settings": "فتح الإعدادات",
"content.actions.title": "إجراءات",
"content.accessibility.send_message": "إرسال رسالة",
"share.status.nothing_to_share": "لا شيء لمشاركته",
"share.status.no_shareable_content": "لا محتوى قابلاً للمشاركة",
"share.fallback.shared_link_title": "رابط مشترك"
},
"de": {
"common.ok": "OK",
"content.input.message_placeholder": "nachricht eingeben...",
"location_channels.title": "#standort-kanäle",
"system.tor.started": "tor läuft. der gesamte chat wird über tor geleitet.",
"share.status.shared_text": "✓ text zu bitchat geteilt",
"share.status.shared_link": "✓ link zu bitchat geteilt",
"share.status.failed_to_encode": "link konnte nicht codiert werden",
"common.cancel": "abbrechen",
"common.close": "schließen",
"common.copy": "kopieren",
"app_info.close": "schließen",
"app_info.done": "FERTIG",
"content.alert.bluetooth_required.permission": "bitchat benötigt bluetooth-berechtigung, um sich mit geräten in der nähe zu verbinden. erlaube den zugriff in den einstellungen.",
"content.alert.bluetooth_required.settings": "einstellungen",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "end-to-end-verschlüsselung",
"app_info.features.offline.title": "offline-kommunikation",
"fingerprint.badge.verified": "✓ VERIFIZIERT",
"fingerprint.badge.not_verified": "⚠️ NICHT VERIFIZIERT",
"fingerprint.action.mark_verified": "als verifiziert markieren",
"location_channels.action.open_settings": "einstellungen öffnen",
"content.actions.title": "aktionen",
"content.accessibility.send_message": "nachricht senden",
"share.status.nothing_to_share": "nichts zum teilen",
"share.status.no_shareable_content": "kein teilbarer inhalt",
"share.fallback.shared_link_title": "geteilter link"
},
"es": {
"common.ok": "aceptar",
"content.input.message_placeholder": "escribe un mensaje...",
"location_channels.title": "#canales de ubicación",
"system.tor.started": "tor se inició. Todo el chat se enruta por Tor para privacidad.",
"share.status.shared_text": "✓ texto compartido con bitchat",
"share.status.shared_link": "✓ enlace compartido con bitchat",
"share.status.failed_to_encode": "no se pudo codificar el enlace",
"common.cancel": "cancelar",
"common.close": "cerrar",
"common.copy": "copiar",
"app_info.close": "cerrar",
"app_info.done": "LISTO",
"content.alert.bluetooth_required.permission": "bitChat necesita permiso de Bluetooth para conectarse con dispositivos cercanos. Habilita el acceso en Ajustes.",
"content.alert.bluetooth_required.settings": "ajustes",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "cifrado de extremo a extremo",
"app_info.features.offline.title": "comunicación sin conexión",
"fingerprint.badge.verified": "✓ VERIFICADO",
"fingerprint.badge.not_verified": "⚠️ NO VERIFICADO",
"fingerprint.action.mark_verified": "marcar como verificado",
"location_channels.action.open_settings": "abrir ajustes",
"content.actions.title": "acciones",
"content.accessibility.send_message": "enviar mensaje",
"share.status.nothing_to_share": "nada que compartir",
"share.status.no_shareable_content": "sin contenido que se pueda compartir",
"share.fallback.shared_link_title": "enlace compartido"
},
"fr": {
"common.ok": "OK",
"content.input.message_placeholder": "écris un message...",
"location_channels.title": "#canaux localisation",
"system.tor.started": "tor a démarré. tout le chat passe par tor pour la confidentialité.",
"share.status.shared_text": "✓ texte partagé vers bitchat",
"share.status.shared_link": "✓ lien partagé vers bitchat",
"share.status.failed_to_encode": "échec de l'encodage du lien",
"common.cancel": "annuler",
"common.close": "fermer",
"common.copy": "copier",
"app_info.close": "fermer",
"app_info.done": "TERMINÉ",
"content.alert.bluetooth_required.permission": "bitchat a besoin de l'autorisation bluetooth pour se connecter aux appareils proches. active l'accès dans réglages.",
"content.alert.bluetooth_required.settings": "réglages",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "chiffrement de bout en bout",
"app_info.features.offline.title": "communication hors ligne",
"fingerprint.badge.verified": "✓ VÉRIFIÉ",
"fingerprint.badge.not_verified": "⚠️ NON VÉRIFIÉ",
"fingerprint.action.mark_verified": "marquer comme vérifié",
"location_channels.action.open_settings": "ouvrir réglages",
"content.actions.title": "actions",
"content.accessibility.send_message": "envoyer le message",
"share.status.nothing_to_share": "rien à partager",
"share.status.no_shareable_content": "aucun contenu partageable",
"share.fallback.shared_link_title": "lien partagé"
},
"he": {
"common.ok": "OK",
"content.input.message_placeholder": "כתוב הודעה...",
"location_channels.title": "#ערוצי מיקום",
"system.tor.started": "tor פעיל. כל הצ'אט עובר דרך tor לפרטיות.",
"share.status.shared_text": "✓ הטקסט נשלח אל bitchat",
"share.status.shared_link": "✓ הקישור נשלח אל bitchat",
"share.status.failed_to_encode": "לא ניתן לקודד את הקישור",
"common.cancel": "ביטול",
"common.close": "סגור",
"common.copy": "העתק",
"app_info.close": "סגור",
"app_info.done": "בוצע",
"content.alert.bluetooth_required.permission": "bitchat צריכה הרשאת bluetooth כדי להתחבר למכשירים קרובים. אפשר גישה בהגדרות.",
"content.alert.bluetooth_required.settings": "הגדרות",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "הצפנה מקצה לקצה",
"app_info.features.offline.title": "תקשורת לא מקוונת",
"fingerprint.badge.verified": "✓ מאומת",
"fingerprint.badge.not_verified": "⚠️ לא מאומת",
"fingerprint.action.mark_verified": "סמן כמאומת",
"location_channels.action.open_settings": "פתח הגדרות",
"content.actions.title": "פעולות",
"content.accessibility.send_message": "שלח הודעה",
"share.status.nothing_to_share": "אין מה לשתף",
"share.status.no_shareable_content": "אין תוכן שניתן לשתף",
"share.fallback.shared_link_title": "קישור משותף"
},
"id": {
"common.ok": "OK",
"content.input.message_placeholder": "ketik pesan...",
"location_channels.title": "#kanal lokasi",
"system.tor.started": "tor berjalan. seluruh chat dirutekan lewat tor demi privasi.",
"share.status.shared_text": "✓ teks dikirim ke bitchat",
"share.status.shared_link": "✓ tautan dikirim ke bitchat",
"share.status.failed_to_encode": "gagal mengodekan tautan",
"common.cancel": "batal",
"common.close": "tutup",
"common.copy": "salin",
"app_info.close": "tutup",
"app_info.done": "SELESAI",
"content.alert.bluetooth_required.permission": "bitchat memerlukan izin bluetooth untuk terhubung dengan perangkat dekat. aktifkan akses di pengaturan.",
"content.alert.bluetooth_required.settings": "pengaturan",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "enkripsi ujung ke ujung",
"app_info.features.offline.title": "komunikasi offline",
"fingerprint.badge.verified": "✓ TERVERIFIKASI",
"fingerprint.badge.not_verified": "⚠️ BELUM TERVERIFIKASI",
"fingerprint.action.mark_verified": "tandai sebagai terverifikasi",
"location_channels.action.open_settings": "buka pengaturan",
"content.actions.title": "aksi",
"content.accessibility.send_message": "kirim pesan",
"share.status.nothing_to_share": "tidak ada yang bisa dibagikan",
"share.status.no_shareable_content": "tidak ada konten yang bisa dibagikan",
"share.fallback.shared_link_title": "tautan dibagikan"
},
"it": {
"common.ok": "OK",
"content.input.message_placeholder": "scrivi un messaggio...",
"location_channels.title": "#canali posizione",
"system.tor.started": "tor è avviato. tutta la chat passa da tor per la privacy.",
"share.status.shared_text": "✓ testo inviato a bitchat",
"share.status.shared_link": "✓ link inviato a bitchat",
"share.status.failed_to_encode": "impossibile codificare il link",
"common.cancel": "annulla",
"common.close": "chiudi",
"common.copy": "copia",
"app_info.close": "chiudi",
"app_info.done": "FATTO",
"content.alert.bluetooth_required.permission": "bitchat richiede l'autorizzazione bluetooth per collegarsi ai dispositivi vicini. abilita l'accesso nelle impostazioni.",
"content.alert.bluetooth_required.settings": "impostazioni",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "crittografia end-to-end",
"app_info.features.offline.title": "comunicazione offline",
"fingerprint.badge.verified": "✓ VERIFICATO",
"fingerprint.badge.not_verified": "⚠️ NON VERIFICATO",
"fingerprint.action.mark_verified": "segna come verificato",
"location_channels.action.open_settings": "apri impostazioni",
"content.actions.title": "azioni",
"content.accessibility.send_message": "invia messaggio",
"share.status.nothing_to_share": "niente da condividere",
"share.status.no_shareable_content": "nessun contenuto condivisibile",
"share.fallback.shared_link_title": "link condiviso"
},
"ja": {
"common.ok": "OK",
"content.input.message_placeholder": "メッセージを入力...",
"location_channels.title": "#ロケーションチャンネル",
"system.tor.started": "torを起動しました。全チャットをtor経由で配信します。",
"share.status.shared_text": "✓ bitchatにテキストを共有",
"share.status.shared_link": "✓ bitchatにリンクを共有",
"share.status.failed_to_encode": "リンクのエンコードに失敗しました",
"common.cancel": "キャンセル",
"common.close": "閉じる",
"common.copy": "コピー",
"app_info.close": "閉じる",
"app_info.done": "完了",
"content.alert.bluetooth_required.permission": "bitchatは近くのデバイスと接続するためbluetooth権限が必要です。設定でアクセスを有効にしてください。",
"content.alert.bluetooth_required.settings": "設定",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "エンドツーエンド暗号",
"app_info.features.offline.title": "オフライン通信",
"fingerprint.badge.verified": "✓ 検証済み",
"fingerprint.badge.not_verified": "⚠️ 未検証",
"fingerprint.action.mark_verified": "検証済みにする",
"location_channels.action.open_settings": "設定を開く",
"content.actions.title": "アクション",
"content.accessibility.send_message": "メッセージ送信",
"share.status.nothing_to_share": "共有できるものがありません",
"share.status.no_shareable_content": "共有可能なコンテンツがありません",
"share.fallback.shared_link_title": "共有リンク"
},
"ko": {
"common.ok": "확인",
"content.input.message_placeholder": "메시지를 입력하세요...",
"location_channels.title": "#위치 채널",
"system.tor.started": "tor가 시작되었습니다. IP 보호를 위해 모든 대화를 tor를 통해 라우팅합니다.",
"share.status.shared_text": "✓ bitchat으로 텍스트를 공유했습니다",
"share.status.shared_link": "✓ bitchat으로 링크를 공유했습니다",
"share.status.failed_to_encode": "링크를 인코딩하는 데 실패했습니다",
"common.cancel": "취소",
"common.close": "닫기",
"common.copy": "복사",
"app_info.close": "닫기",
"app_info.done": "확인",
"content.alert.bluetooth_required.permission": "bitchat은 주변 기기와 연결하기 위해 bluetooth 권한이 필요합니다. 설정에서 bluetooth 접근을 활성화해주세요.",
"content.alert.bluetooth_required.settings": "설정",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "종단간 암호화",
"app_info.features.offline.title": "오프라인 통신",
"fingerprint.badge.verified": "✓ 인증됨",
"fingerprint.badge.not_verified": "⚠️ 인증되지 않음",
"fingerprint.action.mark_verified": "인증됨으로 표시",
"location_channels.action.open_settings": "설정 열기",
"content.actions.title": "작업",
"content.accessibility.send_message": "메시지 보내기",
"share.status.nothing_to_share": "공유할 내용이 없습니다",
"share.status.no_shareable_content": "공유할 수 있는 내용이 없습니다",
"share.fallback.shared_link_title": "공유된 링크"
},
"ne": {
"common.ok": "ठिक",
"content.input.message_placeholder": "सन्देश टाइप गर...",
"location_channels.title": "#स्थान च्यानल",
"system.tor.started": "tor सुरु भयो। गोपनीयताका लागि पूरा च्याट tor मार्फत जान्छ।",
"share.status.shared_text": "✓ bitchat मा पाठ पठाइयो",
"share.status.shared_link": "✓ bitchat मा लिङ्क पठाइयो",
"share.status.failed_to_encode": "लिङ्क सङ्केत गर्न सकेन",
"common.cancel": "रद्द",
"common.close": "बन्द",
"common.copy": "प्रतिलिपि",
"app_info.close": "बन्द",
"app_info.done": "सम्पन्न",
"content.alert.bluetooth_required.permission": "bitchat लाई नजिकका उपकरणसँग जडान हुन bluetooth अनुमति चाहिन्छ। सेटिङमा पहुँच सक्षम गर।",
"content.alert.bluetooth_required.settings": "सेटिङ",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "एन्ड-टु-एन्ड सङ्केत",
"app_info.features.offline.title": "अफलाइन सञ्चार",
"fingerprint.badge.verified": "✓ प्रमाणित",
"fingerprint.badge.not_verified": "⚠️ प्रमाणित छैन",
"fingerprint.action.mark_verified": "प्रमाणित चिन्ह लगाउ",
"location_channels.action.open_settings": "सेटिङ खोल",
"content.actions.title": "कार्य",
"content.accessibility.send_message": "सन्देश पठाउ",
"share.status.nothing_to_share": "बाँड्ने केही छैन",
"share.status.no_shareable_content": "बाँड्न मिल्ने सामग्री छैन",
"share.fallback.shared_link_title": "साझा गरिएको लिङ्क"
},
"pt-BR": {
"common.ok": "OK",
"content.input.message_placeholder": "digite uma mensagem...",
"location_channels.title": "#canais de localização",
"system.tor.started": "tor iniciou. todo o chat é roteado por tor para privacidade.",
"share.status.shared_text": "✓ texto enviado para bitchat",
"share.status.shared_link": "✓ link enviado para bitchat",
"share.status.failed_to_encode": "falha ao codificar link",
"common.cancel": "cancelar",
"common.close": "fechar",
"common.copy": "copiar",
"app_info.close": "fechar",
"app_info.done": "CONCLUÍDO",
"content.alert.bluetooth_required.permission": "bitchat precisa de permissão de bluetooth para conectar com dispositivos próximos. habilite o acesso em ajustes.",
"content.alert.bluetooth_required.settings": "ajustes",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "criptografia ponto a ponto",
"app_info.features.offline.title": "comunicação offline",
"fingerprint.badge.verified": "✓ VERIFICADO",
"fingerprint.badge.not_verified": "⚠️ NÃO VERIFICADO",
"fingerprint.action.mark_verified": "marcar como verificado",
"location_channels.action.open_settings": "abrir ajustes",
"content.actions.title": "ações",
"content.accessibility.send_message": "enviar mensagem",
"share.status.nothing_to_share": "nada para compartilhar",
"share.status.no_shareable_content": "nenhum conteúdo compartilhável",
"share.fallback.shared_link_title": "link compartilhado"
},
"ru": {
"common.ok": "OK",
"content.input.message_placeholder": "напиши сообщение...",
"location_channels.title": "#каналы локации",
"system.tor.started": "tor запущен. весь чат идёт через tor для приватности.",
"share.status.shared_text": "✓ текст отправлен в bitchat",
"share.status.shared_link": "✓ ссылка отправлена в bitchat",
"share.status.failed_to_encode": "не удалось закодировать ссылку",
"common.cancel": "отмена",
"common.close": "закрыть",
"common.copy": "копировать",
"app_info.close": "закрыть",
"app_info.done": "ГОТОВО",
"content.alert.bluetooth_required.permission": "bitchat нужен доступ к bluetooth, чтобы соединяться с ближайшими устройствами. включи разрешение в настройках.",
"content.alert.bluetooth_required.settings": "настройки",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "сквозное шифрование",
"app_info.features.offline.title": "офлайн-связь",
"fingerprint.badge.verified": "✓ ПРОВЕРЕНО",
"fingerprint.badge.not_verified": "⚠️ НЕ ПРОВЕРЕНО",
"fingerprint.action.mark_verified": "пометить как проверено",
"location_channels.action.open_settings": "открыть настройки",
"content.actions.title": "действия",
"content.accessibility.send_message": "отправить сообщение",
"share.status.nothing_to_share": "нечем поделиться",
"share.status.no_shareable_content": "нет подходящего контента",
"share.fallback.shared_link_title": "поделился ссылкой"
},
"uk": {
"common.ok": "OK",
"content.input.message_placeholder": "напиши повідомлення...",
"location_channels.title": "#канали локації",
"system.tor.started": "tor запущено. увесь чат іде через tor для приватності.",
"share.status.shared_text": "✓ текст надіслано в bitchat",
"share.status.shared_link": "✓ посилання надіслано в bitchat",
"share.status.failed_to_encode": "не вдалося закодувати посилання",
"common.cancel": "скасувати",
"common.close": "закрити",
"common.copy": "скопіювати",
"app_info.close": "закрити",
"app_info.done": "ГОТОВО",
"content.alert.bluetooth_required.permission": "bitchat потребує дозволу bluetooth для з'єднання з пристроями поруч. ввімкни доступ у налаштуваннях.",
"content.alert.bluetooth_required.settings": "налаштування",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "скрізьове шифрування",
"app_info.features.offline.title": "офлайн-зв'язок",
"fingerprint.badge.verified": "✓ ПЕРЕВІРЕНО",
"fingerprint.badge.not_verified": "⚠️ НЕ ПЕРЕВІРЕНО",
"fingerprint.action.mark_verified": "позначити як перевірено",
"location_channels.action.open_settings": "відкрити налаштування",
"content.actions.title": "дії",
"content.accessibility.send_message": "надіслати повідомлення",
"share.status.nothing_to_share": "нема чим ділитися",
"share.status.no_shareable_content": "нема відповідного контенту",
"share.fallback.shared_link_title": "спільне посилання"
},
"zh-Hans": {
"common.ok": "确定",
"content.input.message_placeholder": "输入消息...",
"location_channels.title": "#位置频道",
"system.tor.started": "tor 已启动。所有聊天通过 tor 路由以保护 IP。",
"share.status.shared_text": "✓ 已将文本分享至 bitchat",
"share.status.shared_link": "✓ 已将链接分享至 bitchat",
"share.status.failed_to_encode": "无法编码链接",
"common.cancel": "取消",
"common.close": "关闭",
"common.copy": "复制",
"app_info.close": "关闭",
"app_info.done": "完成",
"content.alert.bluetooth_required.permission": "bitchat 需要 bluetooth 权限以连接附近设备。请在设置中启用访问。",
"content.alert.bluetooth_required.settings": "设置",
"app_info.app_name": "bitchat",
"app_info.features.encryption.title": "端到端加密",
"app_info.features.offline.title": "离线通信",
"fingerprint.badge.verified": "✓ 已验证",
"fingerprint.badge.not_verified": "⚠️ 未验证",
"fingerprint.action.mark_verified": "标记为已验证",
"location_channels.action.open_settings": "打开设置",
"content.actions.title": "操作",
"content.accessibility.send_message": "发送消息",
"share.status.nothing_to_share": "没有可分享的内容",
"share.status.no_shareable_content": "没有可分享的素材",
"share.fallback.shared_link_title": "分享的链接"
}
},
"testLocales": [
"en",
"ar",
"de",
"es",
"fr",
"he",
"id",
"it",
"ja",
"ko",
"ne",
"pt-BR",
"ru",
"uk",
"zh-Hans"
]
}