mirror of
https://github.com/jackjackbits/bitchat.git
synced 2026-05-05 20:22:31 +00:00
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:
@@ -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")
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
Generated
-1
@@ -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>
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user