mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-14 22:55:12 +10:00
Merge pull request #400 from HDDen/dev
Feature Request: alternative compression by replace some 2-byte symbols by 1-byte latin analogs (named Cyr2Lat)
This commit is contained in:
@@ -16,6 +16,7 @@ import '../models/message.dart';
|
||||
import '../models/path_selection.dart';
|
||||
import '../models/translation_support.dart';
|
||||
import '../helpers/reaction_helper.dart';
|
||||
import '../helpers/cyr2lat.dart';
|
||||
import '../helpers/smaz.dart';
|
||||
import '../services/app_debug_log_service.dart';
|
||||
import '../services/ble_debug_log_service.dart';
|
||||
@@ -290,9 +291,13 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
final UnreadStore _unreadStore = UnreadStore();
|
||||
List<Channel> _cachedChannels = [];
|
||||
final Map<int, bool> _channelSmazEnabled = {};
|
||||
final Map<int, bool> _channelCyr2LatEnabled = {};
|
||||
final Map<int, String?> _channelCyr2LatProfileId = {};
|
||||
bool _lastSentWasCliCommand =
|
||||
false; // Track if last sent message was a CLI command
|
||||
final Map<String, bool> _contactSmazEnabled = {};
|
||||
final Map<String, bool> _contactCyr2LatEnabled = {};
|
||||
final Map<String, String?> _contactCyr2LatProfileId = {};
|
||||
final Set<String> _knownContactKeys = {};
|
||||
final Map<String, int> _contactUnreadCount = {};
|
||||
final Map<String, RepeaterBatterySnapshot> _repeaterBatterySnapshots = {};
|
||||
@@ -625,6 +630,20 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
_ensureContactSmazSettingLoaded(contactKeyHex);
|
||||
}
|
||||
|
||||
bool isChannelCyr2LatEnabled(int channelIndex) {
|
||||
_ensureChannelCyr2LatSettingLoaded(channelIndex);
|
||||
return _channelCyr2LatEnabled[channelIndex] ?? false;
|
||||
}
|
||||
|
||||
bool isContactCyr2LatEnabled(String contactKeyHex) {
|
||||
_ensureContactCyr2LatSettingLoaded(contactKeyHex);
|
||||
return _contactCyr2LatEnabled[contactKeyHex] ?? false;
|
||||
}
|
||||
|
||||
void ensureContactCyr2LatSettingLoaded(String contactKeyHex) {
|
||||
_ensureContactCyr2LatSettingLoaded(contactKeyHex);
|
||||
}
|
||||
|
||||
Future<void> loadUnreadState() async {
|
||||
_contactUnreadCount
|
||||
..clear()
|
||||
@@ -721,6 +740,10 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
|
||||
Future<void> setChannelSmazEnabled(int channelIndex, bool enabled) async {
|
||||
_channelSmazEnabled[channelIndex] = enabled;
|
||||
if (enabled) {
|
||||
_channelCyr2LatEnabled[channelIndex] = false;
|
||||
await _channelSettingsStore.saveCyr2LatEnabled(channelIndex, false);
|
||||
}
|
||||
await _channelSettingsStore.saveSmazEnabled(channelIndex, enabled);
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -731,6 +754,25 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> setChannelCyr2LatEnabled(int channelIndex, bool enabled) async {
|
||||
_channelCyr2LatEnabled[channelIndex] = enabled;
|
||||
if (enabled) {
|
||||
_channelSmazEnabled[channelIndex] = false;
|
||||
await _channelSettingsStore.saveSmazEnabled(channelIndex, false);
|
||||
}
|
||||
await _channelSettingsStore.saveCyr2LatEnabled(channelIndex, enabled);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> setContactCyr2LatEnabled(
|
||||
String contactKeyHex,
|
||||
bool enabled,
|
||||
) async {
|
||||
_contactCyr2LatEnabled[contactKeyHex] = enabled;
|
||||
await _contactSettingsStore.saveCyr2LatEnabled(contactKeyHex, enabled);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _loadChannelOrder() async {
|
||||
_channelOrder = await _channelOrderStore.loadChannelOrder();
|
||||
_applyChannelOrder();
|
||||
@@ -867,6 +909,7 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
..addAll(cached);
|
||||
for (final contact in cached) {
|
||||
_ensureContactSmazSettingLoaded(contact.publicKeyHex);
|
||||
_ensureContactCyr2LatSettingLoaded(contact.publicKeyHex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,9 +922,12 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
|
||||
Future<void> loadChannelSettings({int? maxChannels}) async {
|
||||
_channelSmazEnabled.clear();
|
||||
_channelCyr2LatEnabled.clear();
|
||||
final channelCount = maxChannels ?? _maxChannels;
|
||||
for (int i = 0; i < channelCount; i++) {
|
||||
_channelSmazEnabled[i] = await _channelSettingsStore.loadSmazEnabled(i);
|
||||
_channelCyr2LatEnabled[i] = await _channelSettingsStore
|
||||
.loadCyr2LatEnabled(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4507,6 +4553,72 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
});
|
||||
}
|
||||
|
||||
void _ensureContactCyr2LatSettingLoaded(String contactKeyHex) {
|
||||
if (_contactCyr2LatEnabled.containsKey(contactKeyHex)) return;
|
||||
_contactSettingsStore.loadCyr2LatEnabled(contactKeyHex).then((enabled) {
|
||||
if (_contactCyr2LatEnabled[contactKeyHex] == enabled) return;
|
||||
_contactCyr2LatEnabled[contactKeyHex] = enabled;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
void _ensureContactCyr2LatProfileLoaded(String contactKeyHex) {
|
||||
if (_contactCyr2LatProfileId.containsKey(contactKeyHex)) return;
|
||||
_contactSettingsStore.loadCyr2LatProfileId(contactKeyHex).then((profileId) {
|
||||
if (_contactCyr2LatProfileId[contactKeyHex] == profileId) return;
|
||||
_contactCyr2LatProfileId[contactKeyHex] = profileId;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
void _ensureChannelCyr2LatSettingLoaded(int channelIndex) {
|
||||
if (_channelCyr2LatEnabled.containsKey(channelIndex)) return;
|
||||
_channelSettingsStore.loadCyr2LatEnabled(channelIndex).then((enabled) {
|
||||
if (_channelCyr2LatEnabled[channelIndex] == enabled) return;
|
||||
_channelCyr2LatEnabled[channelIndex] = enabled;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
void _ensureChannelCyr2LatProfileLoaded(int channelIndex) {
|
||||
if (_channelCyr2LatProfileId.containsKey(channelIndex)) return;
|
||||
_channelSettingsStore.loadCyr2LatProfileId(channelIndex).then((profileId) {
|
||||
if (_channelCyr2LatProfileId[channelIndex] == profileId) return;
|
||||
_channelCyr2LatProfileId[channelIndex] = profileId;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
String? getChannelCyr2LatProfileId(int channelIndex) {
|
||||
_ensureChannelCyr2LatProfileLoaded(channelIndex);
|
||||
return _channelCyr2LatProfileId[channelIndex];
|
||||
}
|
||||
|
||||
Future<void> setChannelCyr2LatProfileId(
|
||||
int channelIndex,
|
||||
String? profileId,
|
||||
) async {
|
||||
if (_channelCyr2LatProfileId[channelIndex] == profileId) return;
|
||||
_channelCyr2LatProfileId[channelIndex] = profileId;
|
||||
await _channelSettingsStore.saveCyr2LatProfileId(channelIndex, profileId);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
String? getContactCyr2LatProfileId(String contactKeyHex) {
|
||||
_ensureContactCyr2LatProfileLoaded(contactKeyHex);
|
||||
return _contactCyr2LatProfileId[contactKeyHex];
|
||||
}
|
||||
|
||||
Future<void> setContactCyr2LatProfileId(
|
||||
String contactKeyHex,
|
||||
String? profileId,
|
||||
) async {
|
||||
if (_contactCyr2LatProfileId[contactKeyHex] == profileId) return;
|
||||
_contactCyr2LatProfileId[contactKeyHex] = profileId;
|
||||
await _contactSettingsStore.saveCyr2LatProfileId(contactKeyHex, profileId);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Prepares contact outbound text by applying SMAZ encoding if enabled.
|
||||
/// This should be used to transform text before computing ACK hashes.
|
||||
String prepareContactOutboundText(Contact contact, String text) {
|
||||
@@ -4515,8 +4627,26 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
trimmed.startsWith('g:') ||
|
||||
trimmed.startsWith('m:') ||
|
||||
trimmed.startsWith('V1|');
|
||||
if (!isStructuredPayload && isContactSmazEnabled(contact.publicKeyHex)) {
|
||||
return Smaz.encodeIfSmaller(text);
|
||||
if (!isStructuredPayload) {
|
||||
if (isContactSmazEnabled(contact.publicKeyHex)) {
|
||||
return Smaz.encodeIfSmaller(text);
|
||||
} else if (isContactCyr2LatEnabled(contact.publicKeyHex)) {
|
||||
final profileId = getContactCyr2LatProfileId(contact.publicKeyHex);
|
||||
final profile = profileId != null && _appSettingsService != null
|
||||
? _appSettingsService!.getCyr2LatProfileById(profileId)
|
||||
: null;
|
||||
if (profile != null) {
|
||||
Cyr2Lat.setCharMap(profile.charMap);
|
||||
} else {
|
||||
// Use global profile
|
||||
final globalProfile = _appSettingsService
|
||||
?.getSelectedCyr2LatProfile();
|
||||
if (globalProfile != null) {
|
||||
Cyr2Lat.setCharMap(globalProfile.charMap);
|
||||
}
|
||||
}
|
||||
return Cyr2Lat.encode(text);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -4525,8 +4655,26 @@ class MeshCoreConnector extends ChangeNotifier {
|
||||
final trimmed = text.trim();
|
||||
final isStructuredPayload =
|
||||
trimmed.startsWith('g:') || trimmed.startsWith('m:');
|
||||
if (!isStructuredPayload && isChannelSmazEnabled(channelIndex)) {
|
||||
return Smaz.encodeIfSmaller(text);
|
||||
if (!isStructuredPayload) {
|
||||
if (isChannelSmazEnabled(channelIndex)) {
|
||||
return Smaz.encodeIfSmaller(text);
|
||||
} else if (isChannelCyr2LatEnabled(channelIndex)) {
|
||||
final profileId = getChannelCyr2LatProfileId(channelIndex);
|
||||
final profile = profileId != null && _appSettingsService != null
|
||||
? _appSettingsService!.getCyr2LatProfileById(profileId)
|
||||
: null;
|
||||
if (profile != null) {
|
||||
Cyr2Lat.setCharMap(profile.charMap);
|
||||
} else {
|
||||
// Use global profile
|
||||
final globalProfile = _appSettingsService
|
||||
?.getSelectedCyr2LatProfile();
|
||||
if (globalProfile != null) {
|
||||
Cyr2Lat.setCharMap(globalProfile.charMap);
|
||||
}
|
||||
}
|
||||
return Cyr2Lat.encode(text);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
class Cyr2Lat {
|
||||
static Map<String, String> _charMap = {
|
||||
'А': 'A',
|
||||
'В': 'B',
|
||||
'Е': 'E',
|
||||
'Ё': 'E',
|
||||
'З': '3',
|
||||
'К': 'K',
|
||||
'М': 'M',
|
||||
'Н': 'H',
|
||||
'О': 'O',
|
||||
'Р': 'P',
|
||||
'С': 'C',
|
||||
'Т': 'T',
|
||||
'Х': 'X',
|
||||
'Ь': 'b',
|
||||
'а': 'a',
|
||||
'е': 'e',
|
||||
'ё': 'e',
|
||||
'о': 'o',
|
||||
'р': 'p',
|
||||
'с': 'c',
|
||||
'у': 'y',
|
||||
'х': 'x',
|
||||
};
|
||||
|
||||
static final RegExp _prefixRegExp = RegExp(r'\@\[[\S\s]+\] ');
|
||||
|
||||
static void setCharMap(Map<String, String> charMap) {
|
||||
_charMap = Map.from(charMap);
|
||||
}
|
||||
|
||||
static String encode(String text) {
|
||||
if (text.isEmpty) return text;
|
||||
final buffer = StringBuffer();
|
||||
|
||||
final senderName = extractSenderName(text);
|
||||
final msgText = removeSenderName(text);
|
||||
|
||||
for (final rune in msgText.runes) {
|
||||
final char = String.fromCharCode(rune);
|
||||
buffer.write(_charMap[char] ?? char);
|
||||
}
|
||||
|
||||
return senderName + buffer.toString();
|
||||
}
|
||||
|
||||
static String removeSenderName(String text) {
|
||||
final match = _prefixRegExp.matchAsPrefix(text);
|
||||
if (match != null) {
|
||||
return text.substring(match.end);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
static String extractSenderName(String text) {
|
||||
final match = _prefixRegExp.matchAsPrefix(text);
|
||||
if (match != null) {
|
||||
return match.group(0) ?? '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Компресия SMAZ",
|
||||
"channels_cyr2latCompression": "Компресия Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Заменя някои кирилични символи с латиница при изпращане.",
|
||||
"channels_cyr2latSettingsHeading": "Настройки на Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Списък със замествания",
|
||||
"channels_cyr2latSettingsDscr": "Редактиране на JSON конфигурацията за заместване на символи",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON карта за замествания",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Неправилен JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Добавяне на профил Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Име на профила",
|
||||
"settings_cyr2latProfileNameEmpty": "Името на профила не може да бъде празно",
|
||||
"settings_cyr2latProfileAdded": "Профилът е добавен успешно",
|
||||
"settings_cyr2latProfileUpdated": "Профилът е актуализиран успешно",
|
||||
"settings_cyr2latProfileEdit": "Редактиране на Cyr2Lat профил",
|
||||
"settings_cyr2latProfileDelete": "Изтриване на профил Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Профилът беше изтрит успешно",
|
||||
"settings_cyr2latProfileDeleteDscr": "Сигурен ли сте, че искате да изтриете профила \"{name}\"?",
|
||||
"channels_channelUpdated": "Каналът \"{name}\" е актуализиран",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ-Komprimierung",
|
||||
"channels_cyr2latCompression": "Cyr2Lat-Komprimierung",
|
||||
"channels_cyr2latCompressionDscr": "Ersetzt einige kyrillische Zeichen durch lateinische Zeichen, wenn sie gesendet werden.",
|
||||
"channels_cyr2latSettingsHeading": "Cyr2Lat-Einstellungen",
|
||||
"channels_cyr2latSettingsSubheading": "Ersetzungsliste",
|
||||
"channels_cyr2latSettingsDscr": "JSON-Konfiguration für die Zeichenersetzung bearbeiten",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-Ersetzungstabelle",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Ungültiges JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Cyr2Lat-Profil hinzufügen",
|
||||
"settings_cyr2latProfileName": "Profilname",
|
||||
"settings_cyr2latProfileNameEmpty": "Der Profilname darf nicht leer sein",
|
||||
"settings_cyr2latProfileAdded": "Profil erfolgreich hinzugefügt",
|
||||
"settings_cyr2latProfileUpdated": "Profil erfolgreich aktualisiert",
|
||||
"settings_cyr2latProfileEdit": "Cyr2Lat-Profil bearbeiten",
|
||||
"settings_cyr2latProfileDelete": "Cyr2Lat-Profil löschen",
|
||||
"settings_cyr2latProfileDeleted": "Profil erfolgreich gelöscht",
|
||||
"settings_cyr2latProfileDeleteDscr": "Möchten Sie das Profil \"{name}\" wirklich löschen?",
|
||||
"channels_channelUpdated": "Kanal \"{name}\" aktualisiert",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -580,6 +580,18 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ compression",
|
||||
"channels_cyr2latCompression": "Cyr2Lat compression",
|
||||
"channels_cyr2latCompressionDscr": "Replaces some Cyrillic characters with Latin characters when sending.",
|
||||
"channels_cyr2latSettingsHeading": "Cyr2Lat Setup",
|
||||
"channels_cyr2latSettingsSubheading": "List of replacements",
|
||||
"channels_cyr2latSettingsDscr": "Edit the JSON configuration of character replacement",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON replacement map",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Invalid JSON: {error}",
|
||||
"@channels_cyr2latSettingsDialogWrongJSON": {
|
||||
"placeholders": {
|
||||
"error": {}
|
||||
}
|
||||
},
|
||||
"channels_channelUpdated": "Channel \"{name}\" updated",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
@@ -588,6 +600,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings_cyr2latProfileAdd": "Add Cyr2Lat Profile",
|
||||
"settings_cyr2latProfileName": "Profile Name",
|
||||
"settings_cyr2latProfileNameEmpty": "Profile name cannot be empty",
|
||||
"settings_cyr2latProfileAdded": "Profile added successfully",
|
||||
"settings_cyr2latProfileUpdated": "Profile updated successfully",
|
||||
"settings_cyr2latProfileEdit": "Edit Cyr2Lat Profile",
|
||||
"settings_cyr2latProfileDelete": "Delete Cyr2Lat Profile",
|
||||
"settings_cyr2latProfileDeleted": "Profile deleted successfully",
|
||||
"settings_cyr2latProfileDeleteDscr": "Are you sure you want to delete the profile \"{name}\"?",
|
||||
"@settings_cyr2latProfileDeleteDscr": {
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"channels_publicChannelAdded": "Public channel added",
|
||||
"channels_sortBy": "Sort by",
|
||||
"channels_sortManual": "Manual",
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Compresión SMAZ",
|
||||
"channels_cyr2latCompression": "Compresión Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Reemplaza algunos caracteres cirílicos con caracteres latinos al enviar.",
|
||||
"channels_cyr2latSettingsHeading": "Configuración de Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Lista de sustituciones",
|
||||
"channels_cyr2latSettingsDscr": "Editar la configuración JSON de sustitución de caracteres",
|
||||
"channels_cyr2latSettingsDialogHint": "Mapa JSON de sustituciones",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "JSON incorrecto: {error}",
|
||||
"settings_cyr2latProfileAdd": "Añadir perfil Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Nombre del perfil",
|
||||
"settings_cyr2latProfileNameEmpty": "El nombre del perfil no puede estar vacío",
|
||||
"settings_cyr2latProfileAdded": "Perfil añadido correctamente",
|
||||
"settings_cyr2latProfileUpdated": "Perfil actualizado correctamente",
|
||||
"settings_cyr2latProfileEdit": "Editar perfil Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Eliminar perfil Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Perfil eliminado correctamente",
|
||||
"settings_cyr2latProfileDeleteDscr": "¿Está seguro de que desea eliminar el perfil \"{name}\"?",
|
||||
"channels_channelUpdated": "Canal \"{name}\" actualizado",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Compression SMAZ",
|
||||
"channels_cyr2latCompression": "Compression Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Remplace certains caractères cyrilliques par des caractères latins lors de l'envoi.",
|
||||
"channels_cyr2latSettingsHeading" : "Paramètres Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading" : "Liste des remplacements",
|
||||
"channels_cyr2latSettingsDscr" : "Modifier la configuration JSON des remplacements de caractères",
|
||||
"channels_cyr2latSettingsDialogHint": "Tableau de remplacement JSON",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "JSON incorrect : {error}",
|
||||
"settings_cyr2latProfileAdd" : "Ajouter un profil Cyr2Lat",
|
||||
"settings_cyr2latProfileName" : "Nom du profil",
|
||||
"settings_cyr2latProfileNameEmpty" : "Le nom du profil ne peut pas être vide",
|
||||
"settings_cyr2latProfileAdded": "Profil ajouté avec succès",
|
||||
"settings_cyr2latProfileUpdated": "Profil mis à jour avec succès",
|
||||
"settings_cyr2latProfileEdit": "Modifier le profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete" : "Supprimer le profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted" : "Profil supprimé avec succès",
|
||||
"settings_cyr2latProfileDeleteDscr" : "Êtes-vous sûr de vouloir supprimer le profil \"{name}\"?",
|
||||
"channels_channelUpdated": "Le canal \"{name}\" a été mis à jour",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -547,6 +547,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ kompresszió",
|
||||
"channels_cyr2latCompression": "Cyr2Lat kompresszió",
|
||||
"channels_cyr2latCompressionDscr": "Néhány Cirill betűt Latin betűkkel helyettesít küldéskor.",
|
||||
"channels_cyr2latSettingsHeading": "Cyr2Lat beállítások",
|
||||
"channels_cyr2latSettingsSubheading": "Helyettesítési lista",
|
||||
"channels_cyr2latSettingsDscr": "A karakterhelyettesítési JSON-konfiguráció szerkesztése",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-csere táblázat",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Hibás JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Cyr2Lat-profil hozzáadása",
|
||||
"settings_cyr2latProfileName": "Profil neve",
|
||||
"settings_cyr2latProfileNameEmpty": "A profil neve nem lehet üres",
|
||||
"settings_cyr2latProfileAdded": "A profil hozzáadása sikeres",
|
||||
"settings_cyr2latProfileUpdated": "A profil frissítése sikeres",
|
||||
"settings_cyr2latProfileEdit": "Cyr2Lat profil szerkesztése",
|
||||
"settings_cyr2latProfileDelete": "Cyr2Lat profil törlése",
|
||||
"settings_cyr2latProfileDeleted": "A profil törlése sikeresen megtörtént",
|
||||
"settings_cyr2latProfileDeleteDscr": "Biztosan törölni szeretné a \"{name}\" profilt?",
|
||||
"channels_channelUpdated": "A {name} csatorna frissítve",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Compressione SMAZ",
|
||||
"channels_cyr2latCompression": "Compressione Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Sostituisce alcuni caratteri cirillici con caratteri latini durante l'invio.",
|
||||
"channels_cyr2latSettingsHeading": "Impostazioni Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Elenco delle sostituzioni",
|
||||
"channels_cyr2latSettingsDscr": "Modifica la configurazione JSON delle sostituzioni dei caratteri",
|
||||
"channels_cyr2latSettingsDialogHint": "Mappa JSON delle sostituzioni",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "JSON non corretto: {error}",
|
||||
"settings_cyr2latProfileAdd": "Aggiungi profilo Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Nome profilo",
|
||||
"settings_cyr2latProfileNameEmpty": "Il nome del profilo non può essere vuoto",
|
||||
"settings_cyr2latProfileAdded": "Profilo aggiunto con successo",
|
||||
"settings_cyr2latProfileUpdated": "Profilo aggiornato con successo",
|
||||
"settings_cyr2latProfileEdit": "Modifica profilo Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Elimina profilo Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Profilo eliminato con successo",
|
||||
"settings_cyr2latProfileDeleteDscr": "Sei sicuro di voler eliminare il profilo \"{name}\"?",
|
||||
"channels_channelUpdated": "Canale \"{name}\" aggiornato",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -547,6 +547,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ 圧縮",
|
||||
"channels_cyr2latCompression": "Cyr2Lat 圧縮",
|
||||
"channels_cyr2latCompressionDscr": "送信時に一部のキリル文字をラテン文字に置き換えます。",
|
||||
"channels_cyr2latSettingsHeading": "cyr2latの設定",
|
||||
"channels_cyr2latSettingsSubheading": "置換リスト",
|
||||
"channels_cyr2latSettingsDscr": "文字置換のJSON設定を編集する",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON置換マップ",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "不正なJSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Cyr2Latプロファイルの追加",
|
||||
"settings_cyr2latProfileName": "プロファイル名",
|
||||
"settings_cyr2latProfileNameEmpty": "プロファイル名は空にできません",
|
||||
"settings_cyr2latProfileAdded": "プロファイルが正常に追加されました",
|
||||
"settings_cyr2latProfileUpdated": "プロファイルの更新に成功しました",
|
||||
"settings_cyr2latProfileEdit": "Cyr2Latプロファイルを編集",
|
||||
"settings_cyr2latProfileDelete": "Cyr2Latプロファイルを削除",
|
||||
"settings_cyr2latProfileDeleted": "プロファイルの削除に成功しました",
|
||||
"settings_cyr2latProfileDeleteDscr": "プロファイル \"{name}\" を削除してもよろしいですか?",
|
||||
"channels_channelUpdated": "チャンネル「{name}」が更新されました",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -547,6 +547,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ 압축",
|
||||
"channels_cyr2latCompression": "Cyr2Lat 압축",
|
||||
"channels_cyr2latCompressionDscr": "보낼 때 일부 키릴 문자를 라틴 문자로 바꿉니다.",
|
||||
"channels_cyr2latSettingsHeading": "Cyr2Lat 설정",
|
||||
"channels_cyr2latSettingsSubheading": "변환 목록",
|
||||
"channels_cyr2latSettingsDscr": "문자 변환 JSON 구성 편집",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON 변환 맵",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "잘못된 JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Cyr2Lat 프로필 추가",
|
||||
"settings_cyr2latProfileName": "프로필 이름",
|
||||
"settings_cyr2latProfileNameEmpty": "프로필 이름은 비워둘 수 없습니다",
|
||||
"settings_cyr2latProfileAdded": "프로필이 성공적으로 추가되었습니다",
|
||||
"settings_cyr2latProfileUpdated": "프로필이 성공적으로 업데이트되었습니다",
|
||||
"settings_cyr2latProfileEdit": "Cyr2Lat 프로필 편집",
|
||||
"settings_cyr2latProfileDelete": "Cyr2Lat 프로필 삭제",
|
||||
"settings_cyr2latProfileDeleted": "프로필이 성공적으로 삭제되었습니다",
|
||||
"settings_cyr2latProfileDeleteDscr": "\"{name}\" 프로필을 삭제하시겠습니까?",
|
||||
"channels_channelUpdated": "채널 \"{name}\"이 업데이트되었습니다.",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -2182,12 +2182,108 @@ abstract class AppLocalizations {
|
||||
/// **'SMAZ compression'**
|
||||
String get channels_smazCompression;
|
||||
|
||||
/// No description provided for @channels_cyr2latCompression.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cyr2Lat compression'**
|
||||
String get channels_cyr2latCompression;
|
||||
|
||||
/// No description provided for @channels_cyr2latCompressionDscr.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Replaces some Cyrillic characters with Latin characters when sending.'**
|
||||
String get channels_cyr2latCompressionDscr;
|
||||
|
||||
/// No description provided for @channels_cyr2latSettingsHeading.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cyr2Lat Setup'**
|
||||
String get channels_cyr2latSettingsHeading;
|
||||
|
||||
/// No description provided for @channels_cyr2latSettingsSubheading.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'List of replacements'**
|
||||
String get channels_cyr2latSettingsSubheading;
|
||||
|
||||
/// No description provided for @channels_cyr2latSettingsDscr.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Edit the JSON configuration of character replacement'**
|
||||
String get channels_cyr2latSettingsDscr;
|
||||
|
||||
/// No description provided for @channels_cyr2latSettingsDialogHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'JSON replacement map'**
|
||||
String get channels_cyr2latSettingsDialogHint;
|
||||
|
||||
/// No description provided for @channels_cyr2latSettingsDialogWrongJSON.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Invalid JSON: {error}'**
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error);
|
||||
|
||||
/// No description provided for @channels_channelUpdated.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Channel \"{name}\" updated'**
|
||||
String channels_channelUpdated(String name);
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileAdd.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Add Cyr2Lat Profile'**
|
||||
String get settings_cyr2latProfileAdd;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileName.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Profile Name'**
|
||||
String get settings_cyr2latProfileName;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileNameEmpty.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Profile name cannot be empty'**
|
||||
String get settings_cyr2latProfileNameEmpty;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileAdded.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Profile added successfully'**
|
||||
String get settings_cyr2latProfileAdded;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileUpdated.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Profile updated successfully'**
|
||||
String get settings_cyr2latProfileUpdated;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileEdit.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Edit Cyr2Lat Profile'**
|
||||
String get settings_cyr2latProfileEdit;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileDelete.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Delete Cyr2Lat Profile'**
|
||||
String get settings_cyr2latProfileDelete;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileDeleted.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Profile deleted successfully'**
|
||||
String get settings_cyr2latProfileDeleted;
|
||||
|
||||
/// No description provided for @settings_cyr2latProfileDeleteDscr.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Are you sure you want to delete the profile \"{name}\"?'**
|
||||
String settings_cyr2latProfileDeleteDscr(String name);
|
||||
|
||||
/// No description provided for @channels_publicChannelAdded.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -1178,11 +1178,67 @@ class AppLocalizationsBg extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Компресия SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Компресия Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Заменя някои кирилични символи с латиница при изпращане.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Настройки на Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Списък със замествания';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Редактиране на JSON конфигурацията за заместване на символи';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON карта за замествания';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Неправилен JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Каналът \"$name\" е актуализиран';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Добавяне на профил Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Име на профила';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Името на профила не може да бъде празно';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Профилът е добавен успешно';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Профилът е актуализиран успешно';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Редактиране на Cyr2Lat профил';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Изтриване на профил Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Профилът беше изтрит успешно';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Сигурен ли сте, че искате да изтриете профила \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Публичен канал добавен';
|
||||
|
||||
|
||||
@@ -1174,11 +1174,67 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ-Komprimierung';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat-Komprimierung';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Ersetzt einige kyrillische Zeichen durch lateinische Zeichen, wenn sie gesendet werden.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Cyr2Lat-Einstellungen';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Ersetzungsliste';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'JSON-Konfiguration für die Zeichenersetzung bearbeiten';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-Ersetzungstabelle';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Ungültiges JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Kanal \"$name\" aktualisiert';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Cyr2Lat-Profil hinzufügen';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Profilname';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Der Profilname darf nicht leer sein';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profil erfolgreich hinzugefügt';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Profil erfolgreich aktualisiert';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Cyr2Lat-Profil bearbeiten';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Cyr2Lat-Profil löschen';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profil erfolgreich gelöscht';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Möchten Sie das Profil \"$name\" wirklich löschen?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Öffentlicher Kanal hinzugefügt';
|
||||
|
||||
|
||||
@@ -1154,11 +1154,65 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ compression';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat compression';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Replaces some Cyrillic characters with Latin characters when sending.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Cyr2Lat Setup';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'List of replacements';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Edit the JSON configuration of character replacement';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON replacement map';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Invalid JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Channel \"$name\" updated';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Add Cyr2Lat Profile';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Profile Name';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty => 'Profile name cannot be empty';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profile added successfully';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Profile updated successfully';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Edit Cyr2Lat Profile';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Delete Cyr2Lat Profile';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profile deleted successfully';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Are you sure you want to delete the profile \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Public channel added';
|
||||
|
||||
|
||||
@@ -1176,11 +1176,67 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Compresión SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Compresión Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Reemplaza algunos caracteres cirílicos con caracteres latinos al enviar.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Configuración de Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Lista de sustituciones';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Editar la configuración JSON de sustitución de caracteres';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'Mapa JSON de sustituciones';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'JSON incorrecto: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Canal \"$name\" actualizado';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Añadir perfil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Nombre del perfil';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'El nombre del perfil no puede estar vacío';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Perfil añadido correctamente';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Perfil actualizado correctamente';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Editar perfil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Eliminar perfil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Perfil eliminado correctamente';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return '¿Está seguro de que desea eliminar el perfil \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Canal público añadido';
|
||||
|
||||
|
||||
@@ -1181,11 +1181,67 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Compression SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Compression Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Remplace certains caractères cyrilliques par des caractères latins lors de l\'envoi.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Paramètres Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Liste des remplacements';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Modifier la configuration JSON des remplacements de caractères';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint =>
|
||||
'Tableau de remplacement JSON';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'JSON incorrect : $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Le canal \"$name\" a été mis à jour';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Ajouter un profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Nom du profil';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Le nom du profil ne peut pas être vide';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profil ajouté avec succès';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Profil mis à jour avec succès';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Modifier le profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Supprimer le profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profil supprimé avec succès';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Êtes-vous sûr de vouloir supprimer le profil \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Le canal public a été ajouté';
|
||||
|
||||
|
||||
@@ -1181,11 +1181,66 @@ class AppLocalizationsHu extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ kompresszió';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat kompresszió';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Néhány Cirill betűt Latin betűkkel helyettesít küldéskor.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Cyr2Lat beállítások';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Helyettesítési lista';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'A karakterhelyettesítési JSON-konfiguráció szerkesztése';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-csere táblázat';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Hibás JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'A $name csatorna frissítve';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Cyr2Lat-profil hozzáadása';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Profil neve';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty => 'A profil neve nem lehet üres';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'A profil hozzáadása sikeres';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'A profil frissítése sikeres';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Cyr2Lat profil szerkesztése';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Cyr2Lat profil törlése';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted =>
|
||||
'A profil törlése sikeresen megtörtént';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Biztosan törölni szeretné a \"$name\" profilt?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'A nyilvános csatorna hozzáadva';
|
||||
|
||||
|
||||
@@ -1177,11 +1177,68 @@ class AppLocalizationsIt extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Compressione SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Compressione Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Sostituisce alcuni caratteri cirillici con caratteri latini durante l\'invio.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Impostazioni Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Elenco delle sostituzioni';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Modifica la configurazione JSON delle sostituzioni dei caratteri';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint =>
|
||||
'Mappa JSON delle sostituzioni';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'JSON non corretto: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Canale \"$name\" aggiornato';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Aggiungi profilo Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Nome profilo';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Il nome del profilo non può essere vuoto';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profilo aggiunto con successo';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Profilo aggiornato con successo';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Modifica profilo Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Elimina profilo Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profilo eliminato con successo';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Sei sicuro di voler eliminare il profilo \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Canale pubblico aggiunto';
|
||||
|
||||
|
||||
@@ -1122,11 +1122,63 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ 圧縮';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat 圧縮';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr => '送信時に一部のキリル文字をラテン文字に置き換えます。';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'cyr2latの設定';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => '置換リスト';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr => '文字置換のJSON設定を編集する';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON置換マップ';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return '不正なJSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'チャンネル「$name」が更新されました';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Cyr2Latプロファイルの追加';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'プロファイル名';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty => 'プロファイル名は空にできません';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'プロファイルが正常に追加されました';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'プロファイルの更新に成功しました';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Cyr2Latプロファイルを編集';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Cyr2Latプロファイルを削除';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'プロファイルの削除に成功しました';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'プロファイル \"$name\" を削除してもよろしいですか?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'パブリックチャンネルが追加されました';
|
||||
|
||||
|
||||
@@ -1117,11 +1117,63 @@ class AppLocalizationsKo extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ 압축';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat 압축';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr => '보낼 때 일부 키릴 문자를 라틴 문자로 바꿉니다.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Cyr2Lat 설정';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => '변환 목록';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr => '문자 변환 JSON 구성 편집';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON 변환 맵';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return '잘못된 JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return '채널 \"$name\"이 업데이트되었습니다.';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Cyr2Lat 프로필 추가';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => '프로필 이름';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty => '프로필 이름은 비워둘 수 없습니다';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => '프로필이 성공적으로 추가되었습니다';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => '프로필이 성공적으로 업데이트되었습니다';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Cyr2Lat 프로필 편집';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Cyr2Lat 프로필 삭제';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => '프로필이 성공적으로 삭제되었습니다';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return '\"$name\" 프로필을 삭제하시겠습니까?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => '공개 채널 추가';
|
||||
|
||||
|
||||
@@ -1165,11 +1165,66 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ compressie';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat compressie';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Vervangt sommige Cyrillische tekens door Latijnse tekens bij het verzenden.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Instellingen Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Lijst met vervangingen';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Bewerk de JSON-configuratie voor tekenvervanging';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-vervangingskaart';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Onjuiste JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Kanaal \"$name\" is bijgewerkt';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Cyr2Lat-profiel toevoegen';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Profielnaam';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Profielnaam mag niet leeg zijn';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profiel succesvol toegevoegd';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Profiel succesvol bijgewerkt';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Cyr2Lat-profiel bewerken';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Cyr2Lat-profiel verwijderen';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profiel succesvol verwijderd';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Weet u zeker dat u het profiel \"$name\" wilt verwijderen?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Open kanaal toegevoegd';
|
||||
|
||||
|
||||
@@ -1185,11 +1185,68 @@ class AppLocalizationsPl extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Kompresja SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Kompresja Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Zastępuje niektóre znaki cyrylicy alfabetem łacińskim podczas wysyłania.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Ustawienia Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Lista zamian';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Edytuj konfigurację JSON zamiany znaków';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'Mapa zamian JSON';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Nieprawidłowy JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Kanał \"$name\" został zaktualizowany';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Dodaj profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Nazwa profilu';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Nazwa profilu nie może być pusta';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profil dodano pomyślnie';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Profil został pomyślnie zaktualizowany';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Edytuj profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Usuń profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted =>
|
||||
'Profil został pomyślnie usunięty';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Czy na pewno chcesz usunąć profil \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Kanał publiczny dodany';
|
||||
|
||||
|
||||
@@ -1176,11 +1176,66 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Compressão SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Compressão Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Substitui alguns caracteres cirílicos por caracteres latinos ao enviar.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Configuração do Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Lista de substituições';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Editar a configuração JSON de substituição de caracteres';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'Mapa de substituições JSON';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'JSON incorreto: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Canal \"$name\" atualizado';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Adicionar perfil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Nome do perfil';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'O nome do perfil não pode estar vazio';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Perfil adicionado com sucesso';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Perfil atualizado com sucesso';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Editar perfil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Eliminar perfil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Perfil eliminado com sucesso';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Tem a certeza de que deseja eliminar o perfil \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Canal público adicionado';
|
||||
|
||||
|
||||
@@ -1176,11 +1176,66 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Сжатие SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Сжатие Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Заменяет некоторые кириллические символы на латиницу при отправке.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Настройка Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Список замен';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Редактировать JSON-конфигурацию замены символов';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-карта замен';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Некорректный JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Канал \"$name\" обновлён';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Добавить профиль Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Название профиля';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Название профиля не может быть пустым';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Профиль добавлен';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Профиль успешно обновлен';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Редактировать профиль Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Удалить профиль Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Профиль успешно удален';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Вы действительно хотите удалить профиль \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Публичный канал добавлен';
|
||||
|
||||
@@ -1568,10 +1623,10 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
}
|
||||
|
||||
@override
|
||||
String get chat_markAsUnread => 'Mark as Unread';
|
||||
String get chat_markAsUnread => 'Пометить как непрочитанные';
|
||||
|
||||
@override
|
||||
String get chat_newMessages => 'New messages';
|
||||
String get chat_newMessages => 'Новые сообщения';
|
||||
|
||||
@override
|
||||
String get chat_openLink => 'Открыть ссылку?';
|
||||
|
||||
@@ -1165,11 +1165,67 @@ class AppLocalizationsSk extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Odstránenie kompresie SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Odstránenie kompresie Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Pri odosielaní nahradí niektoré znaky cyriliky latinskými znakmi.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Nastavenia Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Zoznam nahradení';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Upravte konfiguráciu JSON pre nahradenie znakov';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON mapa nahradení';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Nesprávny JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Kanál \"$name\" bol aktualizovaný';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Pridať profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Názov profilu';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Názov profilu nesmie byť prázdny';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profil bol úspešne pridaný';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Profil bol úspešne aktualizovaný';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Upraviť profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Odstrániť profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profil bol úspešne odstránený';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Naozaj chcete odstrániť profil \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Veľký kanál pridaný';
|
||||
|
||||
|
||||
@@ -1163,11 +1163,67 @@ class AppLocalizationsSl extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Kompresija SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Kompresija Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Pri pošiljanju nekatere cirilice nadomesti z latiničnimi.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Nastavitve Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Seznam zamenjav';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Uredi JSON-konfiguracijo zamenjav znakov';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-tabela zamenjav';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Nepravilen JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Kanal $name je bil posodobljen';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Dodaj profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Ime profila';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Ime profila ne sme biti prazno';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profil je bil uspešno dodan';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated =>
|
||||
'Profil je bil uspešno posodobljen';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Uredi profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Izbriši profil Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profil je bil uspešno izbrisan';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Ali res želite izbrisati profil \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'javna skupnost dodana';
|
||||
|
||||
|
||||
@@ -1156,11 +1156,66 @@ class AppLocalizationsSv extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ-komprimering';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat-komprimering';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Ersätter vissa kyrilliska tecken med latinska tecken när du skickar.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Inställningar för Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Ersättningslista';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Redigera JSON-konfigurationen för teckenersättning';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-ersättningskarta';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Felaktig JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Kanalen \"$name\" har uppdaterats';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Lägg till Cyr2Lat-profil';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Profilnamn';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Profilnamnet får inte vara tomt';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Profilen har lagts till';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Profilen har uppdaterats';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Redigera Cyr2Lat-profil';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Ta bort Cyr2Lat-profil';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Profilen har tagits bort';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Är du säker på att du vill ta bort profilen \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Allmänt kanal tillagd';
|
||||
|
||||
|
||||
@@ -1171,11 +1171,66 @@ class AppLocalizationsUk extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'Стиснення SMAZ';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Стиснення Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr =>
|
||||
'Замінює деякі кириличні символи на латиницю при відправці.';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Налаштування Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => 'Список замін';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr =>
|
||||
'Редагувати JSON-конфігурацію заміни символів';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON-карта замін';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'Некоректний JSON: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return 'Канал «$name» оновлено';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => 'Додати профіль Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => 'Назва профілю';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty =>
|
||||
'Назва профілю не може бути порожньою';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => 'Профіль успішно додано';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => 'Профіль успішно оновлено';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => 'Редагувати профіль Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => 'Видалити профіль Cyr2Lat';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => 'Профіль успішно видалено';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return 'Ви впевнені, що хочете видалити профіль \"$name\"?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => 'Публічний канал додано';
|
||||
|
||||
|
||||
@@ -1104,11 +1104,63 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get channels_smazCompression => 'SMAZ 压缩';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompression => 'Cyr2Lat 压缩';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latCompressionDscr => '发送时将一些西里尔字符替换为拉丁字符。';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsHeading => 'Cyr2Lat 設定';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsSubheading => '替換清單';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDscr => '編輯 JSON 字元替換設定檔';
|
||||
|
||||
@override
|
||||
String get channels_cyr2latSettingsDialogHint => 'JSON 替換映射表';
|
||||
|
||||
@override
|
||||
String channels_cyr2latSettingsDialogWrongJSON(Object error) {
|
||||
return 'JSON 格式錯誤:$error';
|
||||
}
|
||||
|
||||
@override
|
||||
String channels_channelUpdated(String name) {
|
||||
return '频道 \"$name\" 已更新';
|
||||
}
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdd => '新增 Cyr2Lat 設定檔';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileName => '設定檔名稱';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileNameEmpty => '設定檔名稱不能為空';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileAdded => '設定檔已成功新增';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileUpdated => '設定檔已成功更新';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileEdit => '編輯 Cyr2Lat 設定檔';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDelete => '刪除 Cyr2Lat 設定檔';
|
||||
|
||||
@override
|
||||
String get settings_cyr2latProfileDeleted => '設定檔已成功刪除';
|
||||
|
||||
@override
|
||||
String settings_cyr2latProfileDeleteDscr(String name) {
|
||||
return '您確定要刪除設定檔 \"$name\" 嗎?';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channels_publicChannelAdded => '已添加公共频道';
|
||||
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ compressie",
|
||||
"channels_cyr2latCompression": "Cyr2Lat compressie",
|
||||
"channels_cyr2latCompressionDscr": "Vervangt sommige Cyrillische tekens door Latijnse tekens bij het verzenden.",
|
||||
"channels_cyr2latSettingsHeading": "Instellingen Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Lijst met vervangingen",
|
||||
"channels_cyr2latSettingsDscr": "Bewerk de JSON-configuratie voor tekenvervanging",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-vervangingskaart",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Onjuiste JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Cyr2Lat-profiel toevoegen",
|
||||
"settings_cyr2latProfileName": "Profielnaam",
|
||||
"settings_cyr2latProfileNameEmpty": "Profielnaam mag niet leeg zijn",
|
||||
"settings_cyr2latProfileAdded": "Profiel succesvol toegevoegd",
|
||||
"settings_cyr2latProfileUpdated": "Profiel succesvol bijgewerkt",
|
||||
"settings_cyr2latProfileEdit": "Cyr2Lat-profiel bewerken",
|
||||
"settings_cyr2latProfileDelete": "Cyr2Lat-profiel verwijderen",
|
||||
"settings_cyr2latProfileDeleted": "Profiel succesvol verwijderd",
|
||||
"settings_cyr2latProfileDeleteDscr": "Weet u zeker dat u het profiel \"{name}\" wilt verwijderen?",
|
||||
"channels_channelUpdated": "Kanaal \"{name}\" is bijgewerkt",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -397,6 +397,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Kompresja SMAZ",
|
||||
"channels_cyr2latCompression": "Kompresja Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Zastępuje niektóre znaki cyrylicy alfabetem łacińskim podczas wysyłania.",
|
||||
"channels_cyr2latSettingsHeading": "Ustawienia Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Lista zamian",
|
||||
"channels_cyr2latSettingsDscr": "Edytuj konfigurację JSON zamiany znaków",
|
||||
"channels_cyr2latSettingsDialogHint": "Mapa zamian JSON",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Nieprawidłowy JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Dodaj profil Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Nazwa profilu",
|
||||
"settings_cyr2latProfileNameEmpty": "Nazwa profilu nie może być pusta",
|
||||
"settings_cyr2latProfileAdded": "Profil dodano pomyślnie",
|
||||
"settings_cyr2latProfileUpdated": "Profil został pomyślnie zaktualizowany",
|
||||
"settings_cyr2latProfileEdit": "Edytuj profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Usuń profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Profil został pomyślnie usunięty",
|
||||
"settings_cyr2latProfileDeleteDscr": "Czy na pewno chcesz usunąć profil \"{name}\"?",
|
||||
"channels_channelUpdated": "Kanał \"{name}\" został zaktualizowany",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Compressão SMAZ",
|
||||
"channels_cyr2latCompression": "Compressão Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Substitui alguns caracteres cirílicos por caracteres latinos ao enviar.",
|
||||
"channels_cyr2latSettingsHeading": "Configuração do Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Lista de substituições",
|
||||
"channels_cyr2latSettingsDscr": "Editar a configuração JSON de substituição de caracteres",
|
||||
"channels_cyr2latSettingsDialogHint": "Mapa de substituições JSON",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "JSON incorreto: {error}",
|
||||
"settings_cyr2latProfileAdd": "Adicionar perfil Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Nome do perfil",
|
||||
"settings_cyr2latProfileNameEmpty": "O nome do perfil não pode estar vazio",
|
||||
"settings_cyr2latProfileAdded": "Perfil adicionado com sucesso",
|
||||
"settings_cyr2latProfileUpdated": "Perfil atualizado com sucesso",
|
||||
"settings_cyr2latProfileEdit": "Editar perfil Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Eliminar perfil Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Perfil eliminado com sucesso",
|
||||
"settings_cyr2latProfileDeleteDscr": "Tem a certeza de que deseja eliminar o perfil \"{name}\"?",
|
||||
"channels_channelUpdated": "Canal \"{name}\" atualizado",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -251,6 +251,22 @@
|
||||
"channels_channelAdded": "Канал \"{name}\" добавлен",
|
||||
"channels_editChannelTitle": "Изменить канал {index}",
|
||||
"channels_smazCompression": "Сжатие SMAZ",
|
||||
"channels_cyr2latCompression": "Сжатие Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Заменяет некоторые кириллические символы на латиницу при отправке.",
|
||||
"channels_cyr2latSettingsHeading": "Настройка Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Список замен",
|
||||
"channels_cyr2latSettingsDscr": "Редактировать JSON-конфигурацию замены символов",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-карта замен",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Некорректный JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Добавить профиль Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Название профиля",
|
||||
"settings_cyr2latProfileNameEmpty": "Название профиля не может быть пустым",
|
||||
"settings_cyr2latProfileAdded": "Профиль добавлен",
|
||||
"settings_cyr2latProfileUpdated": "Профиль успешно обновлен",
|
||||
"settings_cyr2latProfileEdit": "Редактировать профиль Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Удалить профиль Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Профиль успешно удален",
|
||||
"settings_cyr2latProfileDeleteDscr": "Вы действительно хотите удалить профиль \"{name}\"?",
|
||||
"channels_channelUpdated": "Канал \"{name}\" обновлён",
|
||||
"channels_publicChannelAdded": "Публичный канал добавлен",
|
||||
"channels_sortBy": "Сортировка",
|
||||
@@ -357,6 +373,8 @@
|
||||
"chat_direct": "Прямой",
|
||||
"chat_poiShared": "Точка интереса отправлена",
|
||||
"chat_unread": "Непрочитанных: {count}",
|
||||
"chat_markAsUnread": "Пометить как непрочитанные",
|
||||
"chat_newMessages": "Новые сообщения",
|
||||
"map_title": "Карта нод",
|
||||
"map_noNodesWithLocation": "Нет нод с данными о местоположении",
|
||||
"map_nodesNeedGps": "Ноды должны передавать свои GPS-координаты, чтобы отображаться на карте",
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Odstránenie kompresie SMAZ",
|
||||
"channels_cyr2latCompression": "Odstránenie kompresie Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Pri odosielaní nahradí niektoré znaky cyriliky latinskými znakmi.",
|
||||
"channels_cyr2latSettingsHeading": "Nastavenia Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Zoznam nahradení",
|
||||
"channels_cyr2latSettingsDscr": "Upravte konfiguráciu JSON pre nahradenie znakov",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON mapa nahradení",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Nesprávny JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Pridať profil Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Názov profilu",
|
||||
"settings_cyr2latProfileNameEmpty": "Názov profilu nesmie byť prázdny",
|
||||
"settings_cyr2latProfileAdded": "Profil bol úspešne pridaný",
|
||||
"settings_cyr2latProfileUpdated": "Profil bol úspešne aktualizovaný",
|
||||
"settings_cyr2latProfileEdit": "Upraviť profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Odstrániť profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Profil bol úspešne odstránený",
|
||||
"settings_cyr2latProfileDeleteDscr": "Naozaj chcete odstrániť profil \"{name}\"?",
|
||||
"channels_channelUpdated": "Kanál \"{name}\" bol aktualizovaný",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Kompresija SMAZ",
|
||||
"channels_cyr2latCompression": "Kompresija Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Pri pošiljanju nekatere cirilice nadomesti z latiničnimi.",
|
||||
"channels_cyr2latSettingsHeading": "Nastavitve Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Seznam zamenjav",
|
||||
"channels_cyr2latSettingsDscr": "Uredi JSON-konfiguracijo zamenjav znakov",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-tabela zamenjav",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Nepravilen JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Dodaj profil Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Ime profila",
|
||||
"settings_cyr2latProfileNameEmpty": "Ime profila ne sme biti prazno",
|
||||
"settings_cyr2latProfileAdded": "Profil je bil uspešno dodan",
|
||||
"settings_cyr2latProfileUpdated": "Profil je bil uspešno posodobljen",
|
||||
"settings_cyr2latProfileEdit": "Uredi profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Izbriši profil Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Profil je bil uspešno izbrisan",
|
||||
"settings_cyr2latProfileDeleteDscr": "Ali res želite izbrisati profil \"{name}\"?",
|
||||
"channels_channelUpdated": "Kanal {name} je bil posodobljen",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -387,6 +387,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ-komprimering",
|
||||
"channels_cyr2latCompression": "Cyr2Lat-komprimering",
|
||||
"channels_cyr2latCompressionDscr": "Ersätter vissa kyrilliska tecken med latinska tecken när du skickar.",
|
||||
"channels_cyr2latSettingsHeading": "Inställningar för Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Ersättningslista",
|
||||
"channels_cyr2latSettingsDscr": "Redigera JSON-konfigurationen för teckenersättning",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-ersättningskarta",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Felaktig JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Lägg till Cyr2Lat-profil",
|
||||
"settings_cyr2latProfileName": "Profilnamn",
|
||||
"settings_cyr2latProfileNameEmpty": "Profilnamnet får inte vara tomt",
|
||||
"settings_cyr2latProfileAdded": "Profilen har lagts till",
|
||||
"settings_cyr2latProfileUpdated": "Profilen har uppdaterats",
|
||||
"settings_cyr2latProfileEdit": "Redigera Cyr2Lat-profil",
|
||||
"settings_cyr2latProfileDelete": "Ta bort Cyr2Lat-profil",
|
||||
"settings_cyr2latProfileDeleted": "Profilen har tagits bort",
|
||||
"settings_cyr2latProfileDeleteDscr": "Är du säker på att du vill ta bort profilen \"{name}\"?",
|
||||
"channels_channelUpdated": "Kanalen \"{name}\" har uppdaterats",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -390,6 +390,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "Стиснення SMAZ",
|
||||
"channels_cyr2latCompression": "Стиснення Cyr2Lat",
|
||||
"channels_cyr2latCompressionDscr": "Замінює деякі кириличні символи на латиницю при відправці.",
|
||||
"channels_cyr2latSettingsHeading": "Налаштування Cyr2Lat",
|
||||
"channels_cyr2latSettingsSubheading": "Список замін",
|
||||
"channels_cyr2latSettingsDscr": "Редагувати JSON-конфігурацію заміни символів",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON-карта замін",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "Некоректний JSON: {error}",
|
||||
"settings_cyr2latProfileAdd": "Додати профіль Cyr2Lat",
|
||||
"settings_cyr2latProfileName": "Назва профілю",
|
||||
"settings_cyr2latProfileNameEmpty": "Назва профілю не може бути порожньою",
|
||||
"settings_cyr2latProfileAdded": "Профіль успішно додано",
|
||||
"settings_cyr2latProfileUpdated": "Профіль успішно оновлено",
|
||||
"settings_cyr2latProfileEdit": "Редагувати профіль Cyr2Lat",
|
||||
"settings_cyr2latProfileDelete": "Видалити профіль Cyr2Lat",
|
||||
"settings_cyr2latProfileDeleted": "Профіль успішно видалено",
|
||||
"settings_cyr2latProfileDeleteDscr": "Ви впевнені, що хочете видалити профіль \"{name}\"?",
|
||||
"channels_channelUpdated": "Канал «{name}» оновлено",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -402,6 +402,22 @@
|
||||
}
|
||||
},
|
||||
"channels_smazCompression": "SMAZ 压缩",
|
||||
"channels_cyr2latCompression": "Cyr2Lat 压缩",
|
||||
"channels_cyr2latCompressionDscr": "发送时将一些西里尔字符替换为拉丁字符。",
|
||||
"channels_cyr2latSettingsHeading": "Cyr2Lat 設定",
|
||||
"channels_cyr2latSettingsSubheading": "替換清單",
|
||||
"channels_cyr2latSettingsDscr": "編輯 JSON 字元替換設定檔",
|
||||
"channels_cyr2latSettingsDialogHint": "JSON 替換映射表",
|
||||
"channels_cyr2latSettingsDialogWrongJSON": "JSON 格式錯誤:{error}",
|
||||
"settings_cyr2latProfileAdd": "新增 Cyr2Lat 設定檔",
|
||||
"settings_cyr2latProfileName": "設定檔名稱",
|
||||
"settings_cyr2latProfileNameEmpty": "設定檔名稱不能為空",
|
||||
"settings_cyr2latProfileAdded": "設定檔已成功新增",
|
||||
"settings_cyr2latProfileUpdated": "設定檔已成功更新",
|
||||
"settings_cyr2latProfileEdit": "編輯 Cyr2Lat 設定檔",
|
||||
"settings_cyr2latProfileDelete": "刪除 Cyr2Lat 設定檔",
|
||||
"settings_cyr2latProfileDeleted": "設定檔已成功刪除",
|
||||
"settings_cyr2latProfileDeleteDscr": "您確定要刪除設定檔 \"{name}\" 嗎?",
|
||||
"channels_channelUpdated": "频道 \"{name}\" 已更新",
|
||||
"@channels_channelUpdated": {
|
||||
"placeholders": {
|
||||
|
||||
@@ -13,6 +13,67 @@ extension UnitSystemValue on UnitSystem {
|
||||
}
|
||||
}
|
||||
|
||||
const Map<String, String> defaultCyr2LatCharMap = {
|
||||
'А': 'A',
|
||||
'В': 'B',
|
||||
'Е': 'E',
|
||||
'Ё': 'E',
|
||||
'З': '3',
|
||||
'К': 'K',
|
||||
'М': 'M',
|
||||
'Н': 'H',
|
||||
'О': 'O',
|
||||
'Р': 'P',
|
||||
'С': 'C',
|
||||
'Т': 'T',
|
||||
'Х': 'X',
|
||||
'Ь': 'b',
|
||||
'а': 'a',
|
||||
'е': 'e',
|
||||
'ё': 'e',
|
||||
'о': 'o',
|
||||
'р': 'p',
|
||||
'с': 'c',
|
||||
'у': 'y',
|
||||
'х': 'x',
|
||||
};
|
||||
|
||||
class Cyr2LatProfile {
|
||||
final String id;
|
||||
final String name;
|
||||
final Map<String, String> charMap;
|
||||
|
||||
Cyr2LatProfile({required this.id, required this.name, required this.charMap});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'id': id, 'name': name, 'char_map': charMap};
|
||||
}
|
||||
|
||||
factory Cyr2LatProfile.fromJson(Map<String, dynamic> json) {
|
||||
return Cyr2LatProfile(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
charMap:
|
||||
(json['char_map'] as Map?)?.map(
|
||||
(key, value) => MapEntry(key.toString(), value.toString()),
|
||||
) ??
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
Cyr2LatProfile copyWith({
|
||||
String? id,
|
||||
String? name,
|
||||
Map<String, String>? charMap,
|
||||
}) {
|
||||
return Cyr2LatProfile(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
charMap: charMap ?? this.charMap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppSettings {
|
||||
static const Object _unset = Object();
|
||||
|
||||
@@ -57,6 +118,16 @@ class AppSettings {
|
||||
final String? translationModelSourceUrl;
|
||||
final String? translationSelectedModelId;
|
||||
final List<TranslationModelRecord> translationDownloadedModels;
|
||||
final List<Cyr2LatProfile> cyr2latProfiles;
|
||||
final String selectedCyr2latProfileId;
|
||||
|
||||
Map<String, String> get cyr2latCharMap {
|
||||
final profile = cyr2latProfiles.firstWhere(
|
||||
(p) => p.id == selectedCyr2latProfileId,
|
||||
orElse: () => cyr2latProfiles.first,
|
||||
);
|
||||
return profile.charMap;
|
||||
}
|
||||
|
||||
AppSettings({
|
||||
this.clearPathOnMaxRetry = false,
|
||||
@@ -100,10 +171,22 @@ class AppSettings {
|
||||
this.translationModelSourceUrl,
|
||||
this.translationSelectedModelId,
|
||||
List<TranslationModelRecord>? translationDownloadedModels,
|
||||
List<Cyr2LatProfile>? cyr2latProfiles,
|
||||
String? selectedCyr2latProfileId,
|
||||
}) : batteryChemistryByDeviceId = batteryChemistryByDeviceId ?? {},
|
||||
batteryChemistryByRepeaterId = batteryChemistryByRepeaterId ?? {},
|
||||
mutedChannels = mutedChannels ?? {},
|
||||
translationDownloadedModels = translationDownloadedModels ?? const [];
|
||||
translationDownloadedModels = translationDownloadedModels ?? const [],
|
||||
cyr2latProfiles =
|
||||
cyr2latProfiles ??
|
||||
[
|
||||
Cyr2LatProfile(
|
||||
id: 'default',
|
||||
name: 'Default',
|
||||
charMap: defaultCyr2LatCharMap,
|
||||
),
|
||||
],
|
||||
selectedCyr2latProfileId = selectedCyr2latProfileId ?? 'default';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
@@ -150,6 +233,10 @@ class AppSettings {
|
||||
'translation_downloaded_models': translationDownloadedModels
|
||||
.map((model) => model.toJson())
|
||||
.toList(),
|
||||
'cyr2lat_profiles': cyr2latProfiles
|
||||
.map((profile) => profile.toJson())
|
||||
.toList(),
|
||||
'selected_cyr2lat_profile_id': selectedCyr2latProfileId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -237,6 +324,38 @@ class AppSettings {
|
||||
)
|
||||
.toList() ??
|
||||
const [],
|
||||
cyr2latProfiles:
|
||||
(json['cyr2lat_profiles'] as List<dynamic>?)
|
||||
?.map(
|
||||
(entry) => Cyr2LatProfile.fromJson(
|
||||
Map<String, dynamic>.from(entry as Map),
|
||||
),
|
||||
)
|
||||
.toList() ??
|
||||
// Backward compatibility: if old cyr2lat_char_map exists, create a profile from it
|
||||
(json['cyr2lat_char_map'] != null
|
||||
? [
|
||||
Cyr2LatProfile(
|
||||
id: 'migrated',
|
||||
name: 'Migrated Profile',
|
||||
charMap:
|
||||
(json['cyr2lat_char_map'] as Map?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry(key.toString(), value.toString()),
|
||||
) ??
|
||||
defaultCyr2LatCharMap,
|
||||
),
|
||||
]
|
||||
: [
|
||||
Cyr2LatProfile(
|
||||
id: 'default',
|
||||
name: 'Default',
|
||||
charMap: defaultCyr2LatCharMap,
|
||||
),
|
||||
]),
|
||||
selectedCyr2latProfileId:
|
||||
json['selected_cyr2lat_profile_id'] as String? ??
|
||||
(json['cyr2lat_char_map'] != null ? 'migrated' : 'default'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -282,6 +401,8 @@ class AppSettings {
|
||||
Object? translationModelSourceUrl = _unset,
|
||||
Object? translationSelectedModelId = _unset,
|
||||
List<TranslationModelRecord>? translationDownloadedModels,
|
||||
List<Cyr2LatProfile>? cyr2latProfiles,
|
||||
String? selectedCyr2latProfileId,
|
||||
}) {
|
||||
return AppSettings(
|
||||
clearPathOnMaxRetry: clearPathOnMaxRetry ?? this.clearPathOnMaxRetry,
|
||||
@@ -345,6 +466,9 @@ class AppSettings {
|
||||
: translationSelectedModelId as String?,
|
||||
translationDownloadedModels:
|
||||
translationDownloadedModels ?? this.translationDownloadedModels,
|
||||
cyr2latProfiles: cyr2latProfiles ?? this.cyr2latProfiles,
|
||||
selectedCyr2latProfileId:
|
||||
selectedCyr2latProfileId ?? this.selectedCyr2latProfileId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -60,6 +61,8 @@ class AppSettingsScreen extends StatelessWidget {
|
||||
const SizedBox(height: 16),
|
||||
_buildMapSettingsCard(context, settingsService),
|
||||
const SizedBox(height: 16),
|
||||
_buildCyr2LatCard(context, settingsService),
|
||||
const SizedBox(height: 16),
|
||||
_buildDebugCard(context, settingsService),
|
||||
],
|
||||
);
|
||||
@@ -1260,6 +1263,298 @@ class AppSettingsScreen extends StatelessWidget {
|
||||
return '${sizeMb.toStringAsFixed(1)} MB • $source';
|
||||
}
|
||||
|
||||
Widget _buildCyr2LatCard(
|
||||
BuildContext context,
|
||||
AppSettingsService settingsService,
|
||||
) {
|
||||
final selectedProfile = settingsService.getSelectedCyr2LatProfile();
|
||||
return Card(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||
child: Text(
|
||||
context.l10n.channels_cyr2latSettingsHeading,
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
|
||||
child: DropdownButtonFormField<String>(
|
||||
initialValue: settingsService.settings.selectedCyr2latProfileId,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.channels_cyr2latSettingsSubheading,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
items: settingsService.settings.cyr2latProfiles.map((profile) {
|
||||
return DropdownMenuItem(
|
||||
value: profile.id,
|
||||
child: Text(profile.name),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
settingsService.setSelectedCyr2LatProfile(value);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () =>
|
||||
_showAddCyr2LatProfileDialog(context, settingsService),
|
||||
icon: const Icon(Icons.add),
|
||||
label: Text(context.l10n.common_add),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => _showEditCyr2LatProfileDialog(
|
||||
context,
|
||||
settingsService,
|
||||
selectedProfile,
|
||||
),
|
||||
icon: const Icon(Icons.edit),
|
||||
label: Text(context.l10n.common_edit),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed:
|
||||
settingsService.settings.cyr2latProfiles.length > 1
|
||||
? () => _showDeleteCyr2LatProfileDialog(
|
||||
context,
|
||||
settingsService,
|
||||
selectedProfile,
|
||||
)
|
||||
: null,
|
||||
icon: const Icon(Icons.delete),
|
||||
label: Text(context.l10n.common_delete),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showAddCyr2LatProfileDialog(
|
||||
BuildContext context,
|
||||
AppSettingsService settingsService,
|
||||
) {
|
||||
final nameController = TextEditingController();
|
||||
final jsonController = TextEditingController(
|
||||
text: const JsonEncoder.withIndent(' ').convert(defaultCyr2LatCharMap),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.l10n.settings_cyr2latProfileAdd),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
controller: nameController,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.settings_cyr2latProfileName,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: jsonController,
|
||||
maxLines: 15,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.channels_cyr2latSettingsDialogHint,
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: context.l10n.channels_cyr2latSettingsDscr,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(context.l10n.common_cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (nameController.text.isEmpty) {
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(context.l10n.settings_cyr2latProfileNameEmpty),
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final json =
|
||||
jsonDecode(jsonController.text) as Map<String, dynamic>;
|
||||
final map = json.map(
|
||||
(key, value) => MapEntry(key, value.toString()),
|
||||
);
|
||||
final profile = Cyr2LatProfile(
|
||||
id: DateTime.now().millisecondsSinceEpoch.toString(),
|
||||
name: nameController.text,
|
||||
charMap: map,
|
||||
);
|
||||
await settingsService.addCyr2LatProfile(profile);
|
||||
if (!context.mounted) return;
|
||||
Navigator.pop(context);
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(context.l10n.settings_cyr2latProfileAdded),
|
||||
);
|
||||
} catch (e) {
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(
|
||||
context.l10n.channels_cyr2latSettingsDialogWrongJSON(
|
||||
e.toString(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.common_save),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showEditCyr2LatProfileDialog(
|
||||
BuildContext context,
|
||||
AppSettingsService settingsService,
|
||||
Cyr2LatProfile profile,
|
||||
) {
|
||||
final nameController = TextEditingController(text: profile.name);
|
||||
final jsonController = TextEditingController(
|
||||
text: const JsonEncoder.withIndent(' ').convert(profile.charMap),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.l10n.settings_cyr2latProfileEdit),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
controller: nameController,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.settings_cyr2latProfileName,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: jsonController,
|
||||
maxLines: 15,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.l10n.channels_cyr2latSettingsDialogHint,
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: context.l10n.channels_cyr2latSettingsDscr,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(context.l10n.common_cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (nameController.text.isEmpty) {
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(context.l10n.settings_cyr2latProfileNameEmpty),
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final json =
|
||||
jsonDecode(jsonController.text) as Map<String, dynamic>;
|
||||
final map = json.map(
|
||||
(key, value) => MapEntry(key, value.toString()),
|
||||
);
|
||||
final updatedProfile = profile.copyWith(
|
||||
name: nameController.text,
|
||||
charMap: map,
|
||||
);
|
||||
await settingsService.updateCyr2LatProfile(updatedProfile);
|
||||
if (!context.mounted) return;
|
||||
Navigator.pop(context);
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(context.l10n.settings_cyr2latProfileUpdated),
|
||||
);
|
||||
} catch (e) {
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(
|
||||
context.l10n.channels_cyr2latSettingsDialogWrongJSON(
|
||||
e.toString(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.common_save),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showDeleteCyr2LatProfileDialog(
|
||||
BuildContext context,
|
||||
AppSettingsService settingsService,
|
||||
Cyr2LatProfile profile,
|
||||
) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.l10n.settings_cyr2latProfileDelete),
|
||||
content: Text(
|
||||
context.l10n.settings_cyr2latProfileDeleteDscr(profile.name),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(context.l10n.common_cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await settingsService.removeCyr2LatProfile(profile.id);
|
||||
if (!context.mounted) return;
|
||||
Navigator.pop(context);
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
content: Text(context.l10n.settings_cyr2latProfileDeleted),
|
||||
);
|
||||
},
|
||||
child: Text(context.l10n.common_delete),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDebugCard(
|
||||
BuildContext context,
|
||||
AppSettingsService settingsService,
|
||||
|
||||
@@ -11,6 +11,7 @@ import '../connector/meshcore_connector.dart';
|
||||
import '../utils/platform_info.dart';
|
||||
import '../helpers/chat_scroll_controller.dart';
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
import '../helpers/cyr2lat.dart';
|
||||
import '../helpers/gif_helper.dart';
|
||||
import '../helpers/reaction_helper.dart';
|
||||
import '../helpers/snack_bar_builder.dart';
|
||||
@@ -1151,7 +1152,12 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
||||
hintText: context.l10n.chat_typeMessage,
|
||||
onSubmitted: (_) => _sendMessage(),
|
||||
encoder:
|
||||
connector.isChannelSmazEnabled(widget.channel.index)
|
||||
(connector.isChannelSmazEnabled(
|
||||
widget.channel.index,
|
||||
) ||
|
||||
connector.isChannelCyr2LatEnabled(
|
||||
widget.channel.index,
|
||||
))
|
||||
? (text) => connector.prepareChannelOutboundText(
|
||||
widget.channel.index,
|
||||
text,
|
||||
@@ -1264,6 +1270,15 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
|
||||
return;
|
||||
}
|
||||
|
||||
// When messageText is transformed with cyr2lat, it (generally) hasn't visual differences,
|
||||
// but we getting messages doubles in chat screen (source text and transformed).
|
||||
// To prevent, we'll perform transform of source before pass to main sender logic.
|
||||
// We can pass whole text, senderName will be kept intact
|
||||
if (connector.isChannelCyr2LatEnabled(widget.channel.index)) {
|
||||
messageText = Cyr2Lat.encode(messageText);
|
||||
}
|
||||
// end transform
|
||||
|
||||
_textController.clear();
|
||||
_cancelReply();
|
||||
_textFieldFocusNode.requestFocus();
|
||||
|
||||
@@ -1397,9 +1397,17 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
||||
MeshCoreConnector connector,
|
||||
Channel channel,
|
||||
) {
|
||||
final appSettingsService = Provider.of<AppSettingsService>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
final nameController = TextEditingController(text: channel.name);
|
||||
final pskController = TextEditingController(text: channel.pskHex);
|
||||
bool smazEnabled = connector.isChannelSmazEnabled(channel.index);
|
||||
bool cyr2latEnabled = connector.isChannelCyr2LatEnabled(channel.index);
|
||||
String? selectedCyr2LatProfileId = connector.getChannelCyr2LatProfileId(
|
||||
channel.index,
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -1445,8 +1453,52 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(dialogContext.l10n.channels_smazCompression),
|
||||
value: smazEnabled,
|
||||
onChanged: (value) => setState(() => smazEnabled = value),
|
||||
onChanged: (value) => setState(() {
|
||||
smazEnabled = value;
|
||||
if (smazEnabled) {
|
||||
cyr2latEnabled = false;
|
||||
}
|
||||
}),
|
||||
),
|
||||
SwitchListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(dialogContext.l10n.channels_cyr2latCompression),
|
||||
subtitle: Text(
|
||||
dialogContext.l10n.channels_cyr2latCompressionDscr,
|
||||
),
|
||||
value: cyr2latEnabled,
|
||||
onChanged: (value) => setState(() {
|
||||
cyr2latEnabled = value;
|
||||
if (cyr2latEnabled) {
|
||||
smazEnabled = false;
|
||||
}
|
||||
}),
|
||||
),
|
||||
if (cyr2latEnabled) ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 8),
|
||||
child: DropdownButtonFormField<String>(
|
||||
initialValue: selectedCyr2LatProfileId,
|
||||
decoration: InputDecoration(
|
||||
labelText: dialogContext
|
||||
.l10n
|
||||
.channels_cyr2latSettingsSubheading,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
items: appSettingsService.settings.cyr2latProfiles.map((
|
||||
profile,
|
||||
) {
|
||||
return DropdownMenuItem(
|
||||
value: profile.id,
|
||||
child: Text(profile.name),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) => setState(() {
|
||||
selectedCyr2LatProfileId = value;
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1478,6 +1530,14 @@ class _ChannelsScreenState extends State<ChannelsScreen>
|
||||
channel.index,
|
||||
smazEnabled,
|
||||
);
|
||||
await connector.setChannelCyr2LatEnabled(
|
||||
channel.index,
|
||||
cyr2latEnabled,
|
||||
);
|
||||
await connector.setChannelCyr2LatProfileId(
|
||||
channel.index,
|
||||
selectedCyr2LatProfileId,
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
showDismissibleSnackBar(
|
||||
context,
|
||||
|
||||
@@ -12,6 +12,7 @@ import '../utils/platform_info.dart';
|
||||
|
||||
import '../connector/meshcore_connector.dart';
|
||||
import '../connector/meshcore_protocol.dart';
|
||||
import '../helpers/cyr2lat.dart';
|
||||
import '../helpers/reaction_helper.dart';
|
||||
import '../widgets/message_status_icon.dart';
|
||||
import '../helpers/chat_scroll_controller.dart';
|
||||
@@ -624,9 +625,12 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
hintText: context.l10n.chat_typeMessage,
|
||||
onSubmitted: (_) => _sendMessage(connector),
|
||||
encoder:
|
||||
connector.isContactSmazEnabled(
|
||||
widget.contact.publicKeyHex,
|
||||
)
|
||||
(connector.isContactSmazEnabled(
|
||||
widget.contact.publicKeyHex,
|
||||
) ||
|
||||
connector.isContactCyr2LatEnabled(
|
||||
widget.contact.publicKeyHex,
|
||||
))
|
||||
? (text) => connector.prepareContactOutboundText(
|
||||
widget.contact,
|
||||
text,
|
||||
@@ -745,6 +749,18 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is only for cyr2lat compression - to see the message being sent in the same format as the other person will receive
|
||||
try {
|
||||
if (connector.isContactCyr2LatEnabled(
|
||||
_resolveContact(connector).publicKeyHex,
|
||||
)) {
|
||||
outgoingText = Cyr2Lat.encode(outgoingText);
|
||||
}
|
||||
} catch (_) {
|
||||
// TODO maybe log
|
||||
}
|
||||
// end transform
|
||||
|
||||
_textController.clear();
|
||||
_textFieldFocusNode.requestFocus();
|
||||
connector.sendMessage(
|
||||
@@ -1251,9 +1267,20 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
|
||||
void _showContactSettings(BuildContext context) {
|
||||
final connector = Provider.of<MeshCoreConnector>(context, listen: false);
|
||||
final appSettingsService = Provider.of<AppSettingsService>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
connector.ensureContactSmazSettingLoaded(widget.contact.publicKeyHex);
|
||||
connector.ensureContactCyr2LatSettingLoaded(widget.contact.publicKeyHex);
|
||||
final contact = widget.contact;
|
||||
bool smazEnabled = connector.isContactSmazEnabled(contact.publicKeyHex);
|
||||
bool cyr2latEnabled = connector.isContactCyr2LatEnabled(
|
||||
contact.publicKeyHex,
|
||||
);
|
||||
String? selectedCyr2LatProfileId = connector.getContactCyr2LatProfileId(
|
||||
contact.publicKeyHex,
|
||||
);
|
||||
bool teleBaseEnabled = contact.teleBaseEnabled;
|
||||
bool teleLocEnabled = contact.teleLocEnabled;
|
||||
bool teleEnvEnabled = contact.teleEnvEnabled;
|
||||
@@ -1284,10 +1311,72 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
contact.publicKeyHex,
|
||||
value,
|
||||
);
|
||||
setDialogState(() => smazEnabled = value);
|
||||
connector.setContactCyr2LatEnabled(
|
||||
contact.publicKeyHex,
|
||||
false,
|
||||
);
|
||||
setDialogState(() {
|
||||
smazEnabled = value;
|
||||
if (smazEnabled) {
|
||||
cyr2latEnabled = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
const Divider(height: 8),
|
||||
SwitchListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(context.l10n.channels_cyr2latCompression),
|
||||
subtitle: Text(context.l10n.channels_cyr2latCompressionDscr),
|
||||
value: cyr2latEnabled,
|
||||
onChanged: (value) {
|
||||
connector.setContactCyr2LatEnabled(
|
||||
contact.publicKeyHex,
|
||||
value,
|
||||
);
|
||||
connector.setContactSmazEnabled(
|
||||
contact.publicKeyHex,
|
||||
false,
|
||||
);
|
||||
setDialogState(() {
|
||||
cyr2latEnabled = value;
|
||||
if (cyr2latEnabled) {
|
||||
smazEnabled = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
if (cyr2latEnabled) ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 8),
|
||||
child: DropdownButtonFormField<String>(
|
||||
initialValue: selectedCyr2LatProfileId,
|
||||
decoration: InputDecoration(
|
||||
labelText:
|
||||
context.l10n.channels_cyr2latSettingsSubheading,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
items: appSettingsService.settings.cyr2latProfiles.map((
|
||||
profile,
|
||||
) {
|
||||
return DropdownMenuItem(
|
||||
value: profile.id,
|
||||
child: Text(profile.name),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
connector.setContactCyr2LatProfileId(
|
||||
contact.publicKeyHex,
|
||||
value,
|
||||
);
|
||||
setDialogState(() {
|
||||
selectedCyr2LatProfileId = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
const Divider(height: 8),
|
||||
SwitchListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(context.l10n.contact_teleBase),
|
||||
|
||||
@@ -4,6 +4,7 @@ import '../models/app_settings.dart';
|
||||
import '../models/translation_support.dart';
|
||||
import '../storage/prefs_manager.dart';
|
||||
import '../utils/app_logger.dart';
|
||||
import '../helpers/cyr2lat.dart';
|
||||
|
||||
class AppSettingsService extends ChangeNotifier {
|
||||
static const String _settingsKey = 'app_settings';
|
||||
@@ -32,16 +33,22 @@ class AppSettingsService extends ChangeNotifier {
|
||||
try {
|
||||
final json = jsonDecode(jsonStr) as Map<String, dynamic>;
|
||||
_settings = AppSettings.fromJson(json);
|
||||
Cyr2Lat.setCharMap(_settings.cyr2latCharMap);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
// If parsing fails, use defaults
|
||||
_settings = AppSettings();
|
||||
Cyr2Lat.setCharMap(_settings.cyr2latCharMap);
|
||||
}
|
||||
} else {
|
||||
_settings = AppSettings();
|
||||
Cyr2Lat.setCharMap(_settings.cyr2latCharMap);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateSettings(AppSettings newSettings) async {
|
||||
_settings = newSettings;
|
||||
Cyr2Lat.setCharMap(_settings.cyr2latCharMap);
|
||||
notifyListeners();
|
||||
|
||||
final prefs = PrefsManager.instance;
|
||||
@@ -253,4 +260,56 @@ class AppSettingsService extends ChangeNotifier {
|
||||
_settings.copyWith(translationDownloadedModels: value),
|
||||
);
|
||||
}
|
||||
|
||||
Cyr2LatProfile getSelectedCyr2LatProfile() {
|
||||
return _settings.cyr2latProfiles.firstWhere(
|
||||
(p) => p.id == _settings.selectedCyr2latProfileId,
|
||||
orElse: () => _settings.cyr2latProfiles.first,
|
||||
);
|
||||
}
|
||||
|
||||
Cyr2LatProfile? getCyr2LatProfileById(String profileId) {
|
||||
return _settings.cyr2latProfiles.cast<Cyr2LatProfile?>().firstWhere(
|
||||
(p) => p?.id == profileId,
|
||||
orElse: () => null,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setSelectedCyr2LatProfile(String profileId) async {
|
||||
await updateSettings(
|
||||
_settings.copyWith(selectedCyr2latProfileId: profileId),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addCyr2LatProfile(Cyr2LatProfile profile) async {
|
||||
final updated = List<Cyr2LatProfile>.from(_settings.cyr2latProfiles)
|
||||
..add(profile);
|
||||
await updateSettings(_settings.copyWith(cyr2latProfiles: updated));
|
||||
}
|
||||
|
||||
Future<void> updateCyr2LatProfile(Cyr2LatProfile updatedProfile) async {
|
||||
final updated = _settings.cyr2latProfiles
|
||||
.map((p) => p.id == updatedProfile.id ? updatedProfile : p)
|
||||
.toList();
|
||||
await updateSettings(_settings.copyWith(cyr2latProfiles: updated));
|
||||
}
|
||||
|
||||
Future<void> removeCyr2LatProfile(String profileId) async {
|
||||
if (_settings.cyr2latProfiles.length <= 1) {
|
||||
return; // Don't remove the last profile
|
||||
}
|
||||
final updated = _settings.cyr2latProfiles
|
||||
.where((p) => p.id != profileId)
|
||||
.toList();
|
||||
var newSelectedId = _settings.selectedCyr2latProfileId;
|
||||
if (newSelectedId == profileId) {
|
||||
newSelectedId = updated.first.id;
|
||||
}
|
||||
await updateSettings(
|
||||
_settings.copyWith(
|
||||
cyr2latProfiles: updated,
|
||||
selectedCyr2latProfileId: newSelectedId,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ import 'prefs_manager.dart';
|
||||
|
||||
class ChannelSettingsStore {
|
||||
static const String _keyPrefix = 'channel_smaz_';
|
||||
static const String _cyr2latKeyPrefix = 'channel_cyr2lat_';
|
||||
|
||||
String publicKeyHex = '';
|
||||
set setPublicKeyHex(String value) =>
|
||||
publicKeyHex = value.length > 10 ? value.substring(0, 10) : '';
|
||||
|
||||
String get keyFor => '$_keyPrefix$publicKeyHex';
|
||||
String get keyForCyr2Lat => '$_cyr2latKeyPrefix$publicKeyHex';
|
||||
|
||||
Future<bool> loadSmazEnabled(int channelIndex) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
@@ -20,7 +22,7 @@ class ChannelSettingsStore {
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '$keyFor$channelIndex';
|
||||
final oldKey = '$_keyPrefix$channelIndex';
|
||||
bool? enabled = prefs.getBool(oldKey);
|
||||
bool? enabled = prefs.getBool(key);
|
||||
if (enabled == null) {
|
||||
// Attempt migration from legacy unscoped key on first load
|
||||
enabled = prefs.getBool(oldKey);
|
||||
@@ -46,4 +48,56 @@ class ChannelSettingsStore {
|
||||
final key = '$keyFor$channelIndex';
|
||||
await prefs.setBool(key, enabled);
|
||||
}
|
||||
|
||||
Future<bool> loadCyr2LatEnabled(int channelIndex) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot load channel Cyr2Lat settings.',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '$keyForCyr2Lat$channelIndex';
|
||||
return prefs.getBool(key) ?? false;
|
||||
}
|
||||
|
||||
Future<void> saveCyr2LatEnabled(int channelIndex, bool enabled) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot save channel Cyr2Lat settings.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '$keyForCyr2Lat$channelIndex';
|
||||
await prefs.setBool(key, enabled);
|
||||
}
|
||||
|
||||
Future<String?> loadCyr2LatProfileId(int channelIndex) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot load channel settings.',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '${keyForCyr2Lat}profile_$channelIndex';
|
||||
return prefs.getString(key);
|
||||
}
|
||||
|
||||
Future<void> saveCyr2LatProfileId(int channelIndex, String? profileId) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot save channel settings.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '${keyForCyr2Lat}profile_$channelIndex';
|
||||
if (profileId == null) {
|
||||
await prefs.remove(key);
|
||||
} else {
|
||||
await prefs.setString(key, profileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ import 'prefs_manager.dart';
|
||||
|
||||
class ContactSettingsStore {
|
||||
static const String _keyPrefix = 'contact_smaz_';
|
||||
static const String _cyr2latKeyPrefix = 'contact_cyr2lat_';
|
||||
|
||||
String publicKeyHex = '';
|
||||
set setPublicKeyHex(String value) =>
|
||||
publicKeyHex = value.length > 10 ? value.substring(0, 10) : '';
|
||||
|
||||
String get keyFor => '$_keyPrefix$publicKeyHex';
|
||||
String get keyForCyr2Lat => '$_cyr2latKeyPrefix$publicKeyHex';
|
||||
|
||||
Future<bool> loadSmazEnabled(String contactKeyHex) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
@@ -46,4 +48,59 @@ class ContactSettingsStore {
|
||||
final key = '$keyFor$contactKeyHex';
|
||||
await prefs.setBool(key, enabled);
|
||||
}
|
||||
|
||||
Future<bool> loadCyr2LatEnabled(String contactKeyHex) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot load contact Cyr2Lat settings.',
|
||||
);
|
||||
return false;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '$keyForCyr2Lat$contactKeyHex';
|
||||
return prefs.getBool(key) ?? false;
|
||||
}
|
||||
|
||||
Future<void> saveCyr2LatEnabled(String contactKeyHex, bool enabled) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot save contact Cyr2Lat settings.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '$keyForCyr2Lat$contactKeyHex';
|
||||
await prefs.setBool(key, enabled);
|
||||
}
|
||||
|
||||
Future<String?> loadCyr2LatProfileId(String contactKeyHex) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot load contact settings.',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '${keyForCyr2Lat}profile_$contactKeyHex';
|
||||
return prefs.getString(key);
|
||||
}
|
||||
|
||||
Future<void> saveCyr2LatProfileId(
|
||||
String contactKeyHex,
|
||||
String? profileId,
|
||||
) async {
|
||||
if (publicKeyHex.isEmpty) {
|
||||
appLogger.warn(
|
||||
'Public key hex is not set. Cannot save contact settings.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
final prefs = PrefsManager.instance;
|
||||
final key = '${keyForCyr2Lat}profile_$contactKeyHex';
|
||||
if (profileId == null) {
|
||||
await prefs.remove(key);
|
||||
} else {
|
||||
await prefs.setString(key, profileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user