From d36c8e987d2d7f957b5074e34ce6a40a8d80cdfb Mon Sep 17 00:00:00 2001 From: NaiJi Date: Tue, 4 Oct 2022 02:32:35 +0300 Subject: [PATCH 1/3] Completely refactor language asset files --- assets/translations/en.json | 518 +++++++---------- assets/translations/ru.json | 532 ++++++++---------- lib/logic/common_enum/common_enum.dart | 40 +- lib/logic/cubit/backups/backups_cubit.dart | 5 +- .../cubit/client_jobs/client_jobs_cubit.dart | 16 +- .../cubit/dns_records/dns_records_cubit.dart | 27 +- .../provider_volume_cubit.dart | 2 +- .../server_installation_repository.dart | 16 +- lib/logic/models/disk_size.dart | 6 +- lib/logic/models/job.dart | 8 +- .../components/jobs_content/jobs_content.dart | 10 +- .../not_ready_card/not_ready_card.dart | 6 +- .../server_storage_list_item.dart | 4 +- .../pages/backup_details/backup_details.dart | 32 +- lib/ui/pages/dns_details/dns_details.dart | 22 +- .../info.dart => about_application.dart} | 13 +- .../more/{about/about.dart => about_us.dart} | 6 +- .../pages/more/app_settings/app_setting.dart | 28 +- lib/ui/pages/more/{console => }/console.dart | 16 +- lib/ui/pages/more/more.dart | 28 +- lib/ui/pages/providers/providers.dart | 16 +- lib/ui/pages/server_details/charts/chart.dart | 14 +- .../server_details/charts/network_charts.dart | 2 +- .../server_details/server_details_screen.dart | 8 +- .../pages/server_details/server_settings.dart | 16 +- lib/ui/pages/server_details/text_details.dart | 17 +- .../server_details/time_zone/time_zone.dart | 2 +- .../migration_process_page.dart | 4 +- .../binds_migration/services_migration.dart | 6 +- .../server_storage/extending_volume.dart | 17 +- .../pages/server_storage/server_storage.dart | 6 +- lib/ui/pages/server_storage/storage_card.dart | 6 +- lib/ui/pages/services/service_page.dart | 12 +- lib/ui/pages/services/services.dart | 4 +- lib/ui/pages/setup/initializing.dart | 44 +- .../recovering/recover_by_new_device_key.dart | 2 +- .../recovering/recover_by_old_token.dart | 2 +- .../recovering/recover_by_recovery_key.dart | 2 +- .../recovery_confirm_cloudflare.dart | 2 +- .../recovery_hentzner_connected.dart | 2 +- .../setup/recovering/recovery_routing.dart | 2 +- lib/ui/pages/users/user_details.dart | 6 +- 42 files changed, 682 insertions(+), 845 deletions(-) rename lib/ui/pages/more/{info/info.dart => about_application.dart} (83%) rename lib/ui/pages/more/{about/about.dart => about_us.dart} (85%) rename lib/ui/pages/more/{console => }/console.dart (89%) diff --git a/assets/translations/en.json b/assets/translations/en.json index 3c849eff..bee29120 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -2,9 +2,10 @@ "test": "en-test", "locale": "en", "basis": { - "_comment": "Basic interface elements", "providers": "Providers", + "providers_title": "Your Data Center", "services": "Services", + "services_title": "Your personal, private and independent services.", "users": "Users", "more": "More", "next": "Next", @@ -29,41 +30,38 @@ "wait": "Wait", "remove": "Remove", "apply": "Apply", - "done": "Done" + "done": "Done", + "continue": "Continue" }, - "more": { - "_comment": "'More' tab", + "more_page": { "configuration_wizard": "Setup wizard", "about_project": "About us", - "about_app": "About application", + "about_application": "About", "onboarding": "Onboarding", "create_ssh_key": "Create SSH key", - "generate_key": "Generate key", - "generate_key_text": "You can generate ssh key", "console": "Console", - "remove": "Remove", - "enable": "Enable", - "ok": "ok", - "continue": "Continue", - "ssh_key_exist_text": "You have generated ssh key", - "yes_delete": "Yes, delete my SSH key", - "share": "Share", - "copy_buffer": "Copy to buffer", - "copied_ssh": "SSH copied to clipboard", - "delete_ssh_text": "Delete SSH key?", - "about_app_page": { - "application_version_text": "Application version v.{}", - "api_version_text": "Server API version v.{}" - }, - "settings": { - "title": "Application settings", - "1": "Dark Theme", - "2": "Change your the app theme", - "3": "Reset app config", - "4": "Reset api keys and root user", - "5": "Delete Server", - "6": "This removes the Server. It will be no longer accessible" - } + "application_settings": "Application settings" + }, + "console_page": { + "title": "Console", + "waiting": "Waiting for initialization..." + }, + "about_us_page": { + "title": "About us" + }, + "about_application_page": { + "title": "About", + "application_version_text": "Application version v.{}", + "api_version_text": "Server API version v.{}" + }, + "application_settings": { + "title": "Application settings", + "dark_theme_title": "Dark theme", + "dark_theme_description": "Switch your application theme", + "reset_config_title": "Reset application config", + "reset_config_description": "Reset api keys and root user", + "delete_server_title": "Delete server", + "delete_server_description": "This removes your server. It will be no longer accessible" }, "ssh": { "title": "SSH keys", @@ -73,248 +71,170 @@ "subtitle_with_keys": "{} keys", "subtitle_without_keys": "No keys", "no_key_name": "Unnamed key", - "root": { - "title": "These are superuser keys", - "subtitle": "Owners of these keys get full access to the server and can do anything on it. Only add your own keys to the server." - }, + "root_title": "These are superuser keys", + "root_subtitle": "Owners of these keys get full access to the server and can do anything on it. Only add your own keys to the server.", "input_label": "Public ED25519 or RSA key" }, "onboarding": { - "_comment": "Onboarding pages", "page1_title": "Digital independence, available to all of us", "page1_text": "Mail, VPN, Messenger, social network and much more on your private server, under your control.", "page2_title": "SelfPrivacy — it's not a cloud, but your personal datacenter", "page2_text": "SelfPrivacy works only with your provider accounts: Hetzner, Cloudflare, Backblaze. If you do not own those, we'll help you to create them" }, - "providers": { - "_comment": "'Providers' tab", - "page_title": "Your Data Center", - "server": { - "card_title": "Server", - "status": "Status — Good", - "bottom_sheet": { - "1": "It's a virtual computer, where all your services live.", - "2": "General information", - "3": "Location" - }, - "chart": { - "month": "Month", - "day": "Day", - "hour": "Hour", - "cpu_title": "CPU Usage", - "network_title": "Network Usage", - "in": "In", - "out": "Out" - }, - "resource_usage": "Resource usage", - "settings": { - "allow_autoupgrade": "Allow auto-upgrade", - "allow_autoupgrade_hint": "Allow automatic packages upgrades on server", - "reboot_after_upgrade": "Reboot after upgrade", - "reboot_after_upgrade_hint": "Reboot without prompt after applying changes on server", - "server_timezone": "Server timezone", - "select_timezone": "Select timezone" - }, - "info": { - "server_id": "Server ID", - "status": "Status", - "cpu": "CPU", - "ram": "Memory", - "disk": "Disk local", - "monthly_cost": "Monthly cost", - "location": "Location", - "core_count": { - "one": "{} core", - "other": "{} cores" - } - } - }, - "domain": { - "card_title": "Domain", - "status": "Status — Good", - "bottom_sheet": { - "1": "It's your personal internet address that will point to the server and other services of yours." - }, - "screen_title": "Domain and DNS", - "states": { - "ok": "Records are OK", - "error": "Problems found", - "error_subtitle": "Tap here to fix them", - "refreshing": "Refreshing status...", - "uninitialized": "Data is not retrieved yet" - }, - "record_description": { - "root": "Root domain", - "api": "SelfPrivacy API", - "cloud": "File cloud", - "git": "Git server", - "meet": "Video conference", - "social": "Social network", - "password": "Password manager", - "vpn": "VPN", - "mx": "MX record", - "dmarc": "DMARC record", - "spf": "SPF record", - "dkim": "DKIM key" - }, - "cards": { - "services": { - "title": "Services", - "subtitle": "Type “A” records required for each service." - }, - "email": { - "title": "Email", - "subtitle": "Records necessary for secure email exchange." - } - } - }, - "backup": { - "card_title": "Backup", - "status": "Status — Good", - "bottom_sheet": { - "1": "Will save your day in case of incident: hackers attack, server deletion, etc.", - "2": "3Gb/10Gb, last backup was yesterday {}" - }, - "reuploadKey": "Force reupload key", - "reuploadedKey": "Key reuploaded", - "initialize": "Initialize", - "waitingForRebuild": "You will be able to create your first backup in a few minutes.", - "restore": "Restore from backup", - "no_backups": "There are no backups yet", - "create_new": "Create a new backup", - "creating": "Creating a new backup: {}%", - "restoring": "Restoring from backup", - "error_pending": "Server returned error, check it below", - "restore_alert": "You are about to restore from backup created on {}. All current data will be lost. Are you sure?", - "refresh": "Refresh status", - "refetchBackups": "Refetch backup list", - "refetchingList": "In a few minutes list will be updated" - }, - "storage": { - "card_title": "Server Storage", - "status_ok": "Disk usage is OK", - "status_error": "Low disk space", - "disk_usage": "{} used", - "disk_total": "{} total · {}", - "gb": "{} GB", - "mb": "{} MB", - "kb": "{} KB", - "extend_volume_button": "Extend volume", - "extending_volume_title": "Extending volume", - "extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.", - "extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by Hetzner. Server will be rebooted after resizing.", - "extending_volume_error": "Couldn't initialize volume extending.", - "size": "Size", - "euro": "Euro", - "data_migration_title": "Data migration", - "data_migration_notice": "During migration all services will be turned off.", - "start_migration_button": "Start migration", - "migration_process": "Migrating...", - "migration_done": "Finish" + "resource_chart": { + "month": "Month", + "day": "Day", + "hour": "Hour", + "cpu_title": "CPU Usage", + "network_title": "Network Usage", + "in": "In", + "out": "Out" + }, + "server": { + "card_title": "Server", + "description": "All your services live here", + "general_information": "General information", + "resource_usage": "Resource usage", + "allow_autoupgrade": "Allow auto-upgrade", + "allow_autoupgrade_hint": "Allow automatic packages upgrades on server", + "reboot_after_upgrade": "Reboot after upgrade", + "reboot_after_upgrade_hint": "Reboot without prompt after applying changes on server", + "server_timezone": "Server timezone", + "select_timezone": "Select timezone", + "server_id": "Server ID", + "status": "Status", + "cpu": "CPU", + "ram": "Memory", + "disk": "Disk local", + "monthly_cost": "Monthly cost", + "location": "Location", + "core_count": { + "one": "{} core", + "other": "{} cores" } }, + "record": { + "root": "Root domain", + "api": "SelfPrivacy API", + "cloud": "File cloud", + "git": "Git server", + "meet": "Video conference", + "social": "Social network", + "password": "Password manager", + "vpn": "VPN", + "mx": "MX record", + "dmarc": "DMARC record", + "spf": "SPF record", + "dkim": "DKIM key" + }, + "domain": { + "card_title": "Domain", + "screen_title": "Domain and DNS", + "ok": "Records are OK", + "error": "Problems found", + "error_subtitle": "Tap here to fix them", + "refreshing": "Refreshing status...", + "uninitialized": "Data is not retrieved yet", + "services_title": "Services", + "services_subtitle": "Type “A” records required for each service.", + "email_title": "Email", + "email_subtitle": "Records necessary for secure email exchange." + }, + "backup": { + "card_title": "Backup", + "description": "Will save your day in case of incident: hackers attack, server deletion, etc.", + "reupload_key": "Force reupload key", + "reuploaded_key": "Key reuploaded", + "initialize": "Initialize", + "waiting_for_rebuild": "You will be able to create your first backup in a few minutes.", + "restore": "Restore from backup", + "no_backups": "There are no backups yet", + "create_new": "Create a new backup", + "creating": "Creating a new backup: {}%", + "restoring": "Restoring from backup", + "error_pending": "Server returned error, check it below", + "restore_alert": "You are about to restore from backup created on {}. All current data will be lost. Are you sure?", + "refresh": "Refresh status", + "refetch_backups": "Refetch backup list", + "refetching_list": "In a few minutes list will be updated" + }, + "storage": { + "card_title": "Server Storage", + "status_ok": "Disk usage is OK", + "status_error": "Low disk space", + "disk_usage": "{} used", + "disk_total": "{} total · {}", + "gb": "{} GB", + "mb": "{} MB", + "kb": "{} KB", + "extend_volume_button": "Extend volume", + "extending_volume_title": "Extending volume", + "extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.", + "extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by Hetzner. Server will be rebooted after resizing.", + "extending_volume_error": "Couldn't initialize volume extending.", + "size": "Size", + "euro": "Euro", + "data_migration_title": "Data migration", + "data_migration_notice": "During migration all services will be turned off.", + "start_migration_button": "Start migration", + "migration_process": "Migrating...", + "migration_done": "Finish" + }, "not_ready_card": { - "_comment": "Card shown when user skips initial setup", - "1": "Please finish application setup using ", - "2": "@:more.configuration_wizard", - "3": " for further work", + "begin": "Please finish application setup using ", + "insertion": "@:more.configuration_wizard", + "end": " for further work", "in_menu": "Server is not set up yet. Please finish setup using setup wizard for further work." }, - "services": { - "_comment": "Services", - "title": "Your personal, private and independent services.", - "service_page": { - "open_in_browser": "Open in browser", - "restart": "Restart service", - "disable": "Disable service", - "enable": "Enable service", - "move": "Move to another volume", - "uses": "Uses {usage} on {volume}" - }, - "mail": { - "title": "E-Mail", - "subtitle": "E-Mail for company and family.", - "login_info": "Use username and password from users tab. IMAP port is 143 with STARTTLS, SMTP port is 587 with STARTTLS.", - "bottom_sheet": { - "1": "To connect to the mailserver, please use {} domain alongside with username and password, that you created. Also feel free to invite", - "2": "new users" - } - }, - "messenger": { - "title": "Messenger", - "subtitle": "Telegram or Signal not so private as Delta.Chat that uses your private server.", - "login_info": "Use the same username and password as for e-mail.", - "bottom_sheet": { - "1": "For connection, please use {} domain and credentials that you created." - } - }, - "password_manager": { - "title": "Password Manager", - "subtitle": "Base of your security. Bitwarden will help you to create, store and move passwords between devices, as well as input them, when requested using autocompletion.", - "login_info": "You will have to create an account on the website.", - "bottom_sheet": { - "1": "You can connect to the service and create a user via this link:" - } - }, - "video": { - "title": "Videomeet", - "subtitle": "Zoom and Google Meet are good, but Jitsi Meet is a worth alternative that also gives you confidence that you're not being listened.", - "login_info": "No account needed.", - "bottom_sheet": { - "1": "Using Jitsi as simple as just visiting this link:" - } - }, - "cloud": { - "title": "Cloud Storage", - "subtitle": "Do not allow cloud services to read your data by using NextCloud.", - "login_info": "Login is admin, password is the same as with your main user. Create new accounts in Nextcloud interface.", - "bottom_sheet": { - "1": "You can connect and create a new user here:" - } - }, - "social_network": { - "title": "Social Network", - "subtitle": "It's hard to believe, but it became possible to create your own social network, with your own rules and target audience.", - "login_info": "You will have to create an account on the website.", - "bottom_sheet": { - "1": "You can connect and create new social user here:" - } - }, - "git": { - "title": "Git Server", - "subtitle": "Private alternative to the Github, that belongs to you, but not a Microsoft.", - "login_info": "You will have to create an account on the website. First user will become an admin.", - "bottom_sheet": { - "1": "You can connect and create a new user here:" - } - }, - "vpn": { - "title": "VPN Server", - "subtitle": "Private VPN server", - "bottom_sheet": { - "1": "Openconnect VPN Server. Engine for secure and scalable VPN infrastructure" - } - }, - "page": { - "up_and_running": "Up and running", - "resource_usage": "Resource usage", - "disk_used": "{} of disk space used", - "users": "Users", - "controlled_by": "Controlled by {}", - "apps": "Apps", - "settings": "Settings and maintenance" - } + "service_page": { + "open_in_browser": "Open in browser", + "restart": "Restart service", + "disable": "Disable service", + "enable": "Enable service", + "move": "Move to another volume", + "uses": "Uses {usage} on {volume}" + }, + "mail": { + "title": "E-Mail", + "subtitle": "E-Mail for company and family.", + "login_info": "Use username and password from users tab. IMAP port is 143 with STARTTLS, SMTP port is 587 with STARTTLS." + }, + "password_manager": { + "title": "Password Manager", + "subtitle": "Base of your security. Bitwarden will help you to create, store and move passwords between devices, as well as input them, when requested using autocompletion.", + "login_info": "You will have to create an account on the website." + }, + "video": { + "title": "Videomeet", + "subtitle": "Zoom and Google Meet are good, but Jitsi Meet is a worth alternative that also gives you confidence that you're not being listened.", + "login_info": "No account needed." + }, + "cloud": { + "title": "Cloud Storage", + "subtitle": "Do not allow cloud services to read your data by using NextCloud.", + "login_info": "Login is admin, password is the same as with your main user. Create new accounts in Nextcloud interface." + }, + "social_network": { + "title": "Social Network", + "subtitle": "It's hard to believe, but it became possible to create your own social network, with your own rules and target audience.", + "login_info": "You will have to create an account on the website." + }, + "git": { + "title": "Git Server", + "subtitle": "Private alternative to the Github, that belongs to you, but not a Microsoft.", + "login_info": "You will have to create an account on the website. First user will become an admin." + }, + "vpn": { + "title": "VPN Server", + "subtitle": "Private VPN server" }, "users": { - "_comment": "'Users' tab", "add_new_user": "Add a first user", "new_user": "New user", "delete_user": "Delete user", "not_ready": "Please connect server, domain and DNS in the Providers tab, to be able to add a first user", "nobody_here": "Nobody here", "login": "Login", - "onboarding": "Onboarding", - "console": "Console", "new_user_info_note": "New user will automatically be granted an access to all of the services", "delete_confirm_question": "Are you sure?", "reset_password": "Reset password", @@ -327,38 +247,34 @@ "could_not_delete_user": "Couldn't delete user", "could_not_add_ssh_key": "Couldn't add SSH key", "email_login": "Email login", - "no_sso_notice": "Only email and SSH accounts are created for this user. Single Sign On for all services is coming soon." + "no_ssh_notice": "Only email and SSH accounts are created for this user. Single Sign On for all services is coming soon." }, "initializing": { - "_comment": "initializing page", - "1": "Connect a server", - "2": "A place where your data and SelfPrivacy services will reside:", + "connect_to_server": "Connect a server", + "place_where_data": "A place where your data and SelfPrivacy services will reside:", "how": "How to obtain API token", "hetzner_bad_key_error": "Hetzner API key is invalid", "cloudflare_bad_key_error": "Cloudflare API key is invalid", "backblaze_bad_key_error": "Backblaze storage information is invalid", - "3": "Connect CloudFlare", - "4": "To manage your domain's DNS", - "5": "CloudFlare API Token", - "6": "Connect Backblaze storage", - "7": "No connected domains at the moment", - "8": "Loading domains list", - "9": "Found more than one domain. For your own security, please be asked to delete unnecessary domains", - "10": "Save domain", + "connect_cloudflare": "Connect CloudFlare", + "manage_domain_dns": "To manage your domain's DNS", + "cloudflare_api_token": "CloudFlare API Token", + "connect_backblaze_storage": "Connect Backblaze storage", + "no_connected_domains": "No connected domains at the moment", + "loading_domain_list": "Loading domain list", + "found_more_domains": "Found more than one domain. For your own security, please be asked to delete unnecessary domains", + "save_domain": "Save domain", "final": "Final step", - "11": "Create server", + "create_server": "Create server", "what": "What does it mean?", - "13": "Server rebooted. Waiting for the last verification...", - "14": "Server started. It will be validated and rebooted now...", - "15": "Server created. DNS checks and server boot in progress...", - "16": "Until the next check: ", - "17": "Check", - "18": "How to obtain Hetzner API Token:'", - "19": "1 Go via this link ", - "20": "\n", - "21": "One more restart to apply your security certificates.", - "22": "Create master account", - "23": "Enter a nickname and strong password", + "server_rebooted": "Server rebooted. Waiting for the last verification...", + "server_started": "Server started. It will be validated and rebooted now...", + "server_created": "Server created. DNS checks and server boot in progress...", + "until_the_next_check": "Until the next check: ", + "check": "Check", + "one_more_restart": "One more restart to apply your security certificates.", + "create_master_account": "Create master account", + "enter_nickname_and_password": "Enter a nickname and strong password", "finish": "Everything is initialized", "checks": "Checks have been completed \n{} out of {}" }, @@ -451,19 +367,16 @@ "generation_error": "Couldn't generate a recovery key. {}" }, "modals": { - "_comment": "messages in modals", - "1": "Server with such name, already exist.", - "1_1": "Unexpected error during placement from the provider side.", - "2": "Destroy server and create a new one?", - "2_2": "Try again?", - "3": "Are you sure?", - "4": "Purge all authentication keys?", - "5": "Yes, purge all my tokens", - "6": "Delete the server and volume?", - "7": "Yes", - "8": "Remove task", - "9": "Reboot", - "10": "You cannot use this API for domains with such TLD.", + "already_exists": "Such server already exists.", + "unexpected_error": "Unexpected error during placement from the provider side.", + "destroy_server": "Destroy the server and create a new one?", + "try_again": "Try again?", + "are_you_sure": "Are you sure?", + "purge_all_keys": "Purge all authentication keys?", + "purge_all_keys_confirm": "Yes, purge all my tokens", + "delete_server_volume": "Delete the server and volume?", + "reboot": "Reboot", + "you_cant_use_this_api": "You cannot use this API for domains with such TLD.", "yes": "Yes", "no": "No" }, @@ -471,27 +384,26 @@ "sec": "{} sec" }, "jobs": { - "_comment": "Jobs list", "title": "Jobs list", "start": "Start", "empty": "No jobs", - "createUser": "Create user", - "deleteUser": "Delete user", - "serviceTurnOff": "Turn off", - "serviceTurnOn": "Turn on", - "jobAdded": "Job added", - "runJobs": "Run jobs", - "rebootSuccess": "Server is rebooting", - "rebootFailed": "Couldn't reboot the server. Check the app logs.", - "configPullFailed": "Failed to pull configuration upgrade. Started software upgrade anyways.", - "upgradeSuccess": "Server upgrade started", - "upgradeFailed": "Failed to upgrade server", - "upgradeServer": "Upgrade server", - "rebootServer": "Reboot server", + "create_user": "Create user", + "delete_user": "Delete user", + "service_turn_off": "Turn off", + "service_turn_on": "Turn on", + "job_added": "Job added", + "run_jobs": "Run jobs", + "reboot_success": "Server is rebooting", + "reboot_failed": "Couldn't reboot the server. Check the app logs.", + "config_pull_failed": "Failed to pull configuration upgrade. Started software upgrade anyways.", + "upgrade_success": "Server upgrade started", + "upgrade_failed": "Failed to upgrade server", + "upgrade_server": "Upgrade server", + "reboot_server": "Reboot server", "create_ssh_key": "Create SSH key for {}", "delete_ssh_key": "Delete SSH key for {}", "server_jobs": "Jobs on the server", - "resetUserPassword": "Reset password of user" + "reset_user_password": "Reset password of user" }, "validations": { "required": "Required.", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index ce2d6231..8b33890b 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -2,9 +2,10 @@ "test": "ru-test", "locale": "ru", "basis": { - "_comment": "базовые элементы интерфейса", "providers": "Провайдеры", + "providers_title": "Ваш Дата Центр", "services": "Сервисы", + "services_title": "Ваши личные, приватные и независимые сервисы.", "users": "Пользователи", "more": "Ещё", "next": "Далее", @@ -29,41 +30,38 @@ "wait": "Загрузка", "remove": "Удалить", "apply": "Подать", - "done": "Готово" + "done": "Готово", + "continue": "Продолжить" }, - "more": { - "_comment": "вкладка ещё", + "more_page": { "configuration_wizard": "Мастер Подключения", "about_project": "О проекте SelfPrivacy", - "about_app": "О приложении", + "about_application": "О приложении", "onboarding": "Приветствие", "console": "Консоль", "create_ssh_key": "Создать ssh ключ", - "generate_key": "Сгенерировать ключ", - "generate_key_text": "Вы сможете сгенерировать ключ", - "remove": "Отключить", - "enable": "Включить", - "ok": "ok", - "continue": "Продолжить", - "ssh_key_exist_text": "У Вас уже есть сгенерированный ssh ключ", - "yes_delete": "Да, удалить", - "share": "Поделиться", - "copy_buffer": "Копировать в буфер", - "copied_ssh": "SSH ключ cкопирован в буфер", - "delete_ssh_text": "Удалить SSH ключ?", - "about_app_page": { - "application_version_text": "Версия приложения v.{}", - "api_version_text": "Версия API сервера v.{}" - }, - "settings": { - "title": "Настройки приложения", - "1": "Тёмная тема", - "2": "Сменить цветовую тему.", - "3": "Сброс настроек", - "4": "Сбросить API ключи а также root пользвателя.", - "5": "Удалить сервер", - "6": "Действие приведет к удалению сервера. После этого он будет недоступен." - } + "application_settings": "Настройки приложения" + }, + "console_page": { + "title": "Консоль", + "waiting": "Ждём инициализации..." + }, + "about_us_page": { + "title": "О проекте SelfPrivacy" + }, + "about_application_page": { + "title": "О приложении", + "application_version_text": "Версия приложения v.{}", + "api_version_text": "Версия API сервера v.{}" + }, + "application_settings": { + "title": "Настройки приложения", + "dark_theme_title": "Тёмная тема", + "dark_theme_description": "Сменить цветовую тему.", + "reset_config_title": "Сброс настроек", + "reset_config_description": "Сбросить API ключи а также root пользвателя.", + "delete_server_title": "Удалить сервер", + "delete_server_description": "Действие приведет к удалению сервера. После этого он будет недоступен." }, "ssh": { "title": "SSH ключи", @@ -73,285 +71,213 @@ "subtitle_with_keys": "Ключей: {}", "subtitle_without_keys": "Ключей нет", "no_key_name": "Безымянный ключ", - "root": { - "title": "Это ключи суперпользователя", - "subtitle": "Владельцы указанных здесь ключей получают полный доступ к данным и настройкам сервера. Добавляйте исключительно свои ключи." - }, + "root_title": "Это ключи суперпользователя", + "root_subtitle": "Владельцы указанных здесь ключей получают полный доступ к данным и настройкам сервера. Добавляйте исключительно свои ключи.", "input_label": "Публичный ED25519 или RSA ключ" }, "onboarding": { - "_comment": "страницы онбординга", "page1_title": "Цифровая независимость доступна каждому", "page1_text": "Почта, VPN, Мессенджер, социальная сеть и многое другое на Вашем личном сервере, под Вашим полным контролем.", "page2_title": "SelfPrivacy — это не облако, а Ваш личный дата-центр", "page2_text": "SelfPrivacy работает только с вашими сервис-провайдерами: Hetzner, Cloudflare, Backblaze. Если у Вас нет учётных записей, мы поможем их создать." }, - "providers": { - "_comment": "вкладка провайдеры", - "page_title": "Ваш Дата-центр", - "server": { - "card_title": "Сервер", - "status": "Статус — в норме", - "bottom_sheet": { - "1": "Это виртуальный компьютер на котором работают все Ваши сервисы.", - "2": "Общая информация", - "3": "Размещение" - }, - "chart": { - "month": "Месяц", - "day": "День", - "hour": "Час", - "cpu_title": "Использование процессора", - "network_title": "Использование сети", - "in": "Получено", - "out": "Отправлено" - }, - "settings": { - "allow_autoupgrade": "Разрешить авто-обноления", - "allow_autoupgrade_hint": "Разрешить автоматичесую установку обновлений на сервер", - "reboot_after_upgrade": "Перезагружать после обновлений", - "reboot_after_upgrade_hint": "Автоматически перезагружать сервер после применения обновлений", - "server_timezone": "Часовой пояс сервера", - "select_timezone": "Выберите часовой пояс" - }, - "info": { - "server_id": "ID сервера", - "status": "Статус", - "cpu": "Процессор", - "ram": "Операивная память", - "disk": "Диск", - "monthly_cost": "Ежемесячная стоимость", - "location": "Размещение", - "core_count": { - "one": "{} ядро", - "two": "{} ядра", - "few": "{} ядра", - "many": "{} ядер", - "other": "{} ядер" - } - } - }, - "domain": { - "card_title": "Домен", - "status": "Статус — в норме", - "bottom_sheet": { - "1": "Это ваш личный адрес в интернете, который будет указывать на сервер и другие ваши сервисы." - }, - "screen_title": "Домен и DNS", - "states": { - "ok": "Записи в норме", - "error": "Обнаружены проблемы", - "error_subtitle": "Нажмите здесь, чтобы исправить", - "refreshing": "Обновление данных...", - "uninitialized": "Данные ещё не получены" - }, - "record_description": { - "root": "Корневой домен", - "api": "SelfPrivacy API", - "cloud": "Файловое облако", - "git": "Git сервер", - "meet": "Видеоконференции", - "social": "Социальная сеть", - "password": "Менеджер паролей", - "vpn": "VPN", - "mx": "MX запись", - "dmarc": "DMARC запись", - "spf": "SPF запись", - "dkim": "DKIM ключ" - }, - "cards": { - "services": { - "title": "Сервисы", - "subtitle": "Записи типа “A” необходимые для работы сервисов." - }, - "email": { - "title": "Электронная почта", - "subtitle": "Записи необходимые для безопасного обмена электронной почтой." - } - } - }, - "backup": { - "card_title": "Резервное копирование", - "status": "Статус — в норме", - "bottom_sheet": { - "1": "Выручит Вас в любой ситуации: хакерская атака, удаление сервера и т.д.", - "2": "Использовано 3Gb из бесплатых 10Gb. Последнее копирование была сделано вчера в {}." - }, - "reuploadKey": "Принудительно обновить ключ", - "reuploadedKey": "Ключ на сервере обновлён", - "initialize": "Настроить", - "waitingForRebuild": "Через несколько минут можно будет создать первую копию.", - "restore": "Восстановить из копии", - "no_backups": "Резервных копий пока нет", - "create_new": "Создать новую копию", - "creating": "Создание копии: {}%", - "restoring": "Восстановление из копии", - "error_pending": "Сервер вернул ошибку: проверьте её ниже.", - "restore_alert": "Вы собираетесь восстановить из копии созданной {}. Все текущие данные будут потеряны. Вы уверены?", - "refresh": "Обновить статус", - "refetchBackups": "Обновить список копий", - "refetchingList": "Через несколько минут список будет обновлён" - }, - "storage": { - "card_title": "Хранилище", - "status_ok": "Проблем на диске не обнаружено", - "status_error": "Заканчивается место на диске", - "disk_usage": "{} использовано", - "disk_total": "{} всего · {}", - "gb": "{} GB", - "mb": "{} MB", - "kb": "{} KB", - "extend_volume_button": "Расширить хранилище", - "extending_volume_title": "Расширение хранилища", - "extending_volume_description": "Изменение размера хранилища позволит вам держать больше данных на вашем сервере без расширения самого сервера. Объем можно только увеличить: уменьшить нельзя.", - "extending_volume_price_info": "Цена включает НДС и рассчитана на основе данных о ценах, предоставленных Hetzner. Сервер будет перезагружен во время процесса.", - "extending_volume_error": "Не удалось начать расширение хранилища.", - "size": "Размер", - "euro": "Евро", - "data_migration_title": "Миграция данных", - "data_migration_notice": "На время миграции данных все сервисы будут выключены.", - "start_migration_button": "Начать миграцию", - "migration_process": "Мигрируем...", - "migration_done": "Завершить" + "resource_chart": { + "month": "Месяц", + "day": "День", + "hour": "Час", + "cpu_title": "Использование процессора", + "network_title": "Использование сети", + "in": "Получено", + "out": "Отправлено" + }, + "server": { + "card_title": "Сервер", + "description": "Это виртуальный компьютер на котором работают все Ваши сервисы.", + "general_information": "Общая информация", + "resource_usage": "Потребление ресурсов", + "allow_autoupgrade": "Разрешить авто-обноления", + "allow_autoupgrade_hint": "Разрешить автоматичесую установку обновлений на сервер", + "reboot_after_upgrade": "Перезагружать после обновлений", + "reboot_after_upgrade_hint": "Автоматически перезагружать сервер после применения обновлений", + "server_timezone": "Часовой пояс сервера", + "select_timezone": "Выберите часовой пояс", + "server_id": "ID сервера", + "status": "Статус", + "cpu": "Процессор", + "ram": "Оперативная память", + "disk": "Диск", + "monthly_cost": "Ежемесячная стоимость", + "location": "Размещение", + "core_count": { + "one": "{} ядро", + "two": "{} ядра", + "few": "{} ядра", + "many": "{} ядер", + "other": "{} ядер" } }, + "record": { + "root": "Корневой домен", + "api": "SelfPrivacy API", + "cloud": "Файловое облако", + "git": "Git сервер", + "meet": "Видеоконференции", + "social": "Социальная сеть", + "password": "Менеджер паролей", + "vpn": "VPN", + "mx": "MX запись", + "dmarc": "DMARC запись", + "spf": "SPF запись", + "dkim": "DKIM ключ" + }, + "domain": { + "card_title": "Домен", + "screen_title": "Домен и DNS", + "ok": "Записи в норме", + "error": "Обнаружены проблемы", + "error_subtitle": "Нажмите здесь, чтобы исправить", + "refreshing": "Обновление данных...", + "uninitialized": "Данные ещё не получены", + "services_title": "Сервисы", + "services_subtitle": "Записи типа “A” необходимые для работы сервисов.", + "email_title": "Электронная почта", + "email_subtitle": "Записи необходимые для безопасного обмена электронной почтой." + }, + "backup": { + "card_title": "Резервное копирование", + "description": "Выручит Вас в любой ситуации: хакерская атака, удаление сервера и т.д.", + "reupload_key": "Принудительно обновить ключ", + "reuploaded_key": "Ключ на сервере обновлён", + "initialize": "Настроить", + "waiting_for_rebuild": "Через несколько минут можно будет создать первую копию.", + "restore": "Восстановить из копии", + "no_backups": "Резервных копий пока нет", + "create_new": "Создать новую копию", + "creating": "Создание копии: {}%", + "restoring": "Восстановление из копии", + "error_pending": "Сервер вернул ошибку: проверьте её ниже.", + "restore_alert": "Вы собираетесь восстановить из копии созданной {}. Все текущие данные будут потеряны. Вы уверены?", + "refresh": "Обновить статус", + "refetch_backups": "Обновить список копий", + "refetching_list": "Через несколько минут список будет обновлён" + }, + "storage": { + "card_title": "Хранилище", + "status_ok": "Проблем на диске не обнаружено", + "status_error": "Заканчивается место на диске", + "disk_usage": "{} использовано", + "disk_total": "{} всего · {}", + "gb": "{} GB", + "mb": "{} MB", + "kb": "{} KB", + "extend_volume_button": "Расширить хранилище", + "extending_volume_title": "Расширение хранилища", + "extending_volume_description": "Изменение размера хранилища позволит вам держать больше данных на вашем сервере без расширения самого сервера. Объем можно только увеличить: уменьшить нельзя.", + "extending_volume_price_info": "Цена включает НДС и рассчитана на основе данных о ценах, предоставленных Hetzner. Сервер будет перезагружен во время процесса.", + "extending_volume_error": "Не удалось начать расширение хранилища.", + "size": "Размер", + "euro": "Евро", + "data_migration_title": "Миграция данных", + "data_migration_notice": "На время миграции данных все сервисы будут выключены.", + "start_migration_button": "Начать миграцию", + "migration_process": "Мигрируем...", + "migration_done": "Завершить" + }, "not_ready_card": { - "_comment": "Карточка показывающая когда человек скипнул настройку, на карте текст из 3 блоков, средний содержит ссыку на мастер подключения", - "1": "Завершите настройку приложения используя ", - "2": "@:more.configuration_wizard", - "3": " для продолжения работы", + "begin": "Завершите настройку приложения используя ", + "insertion": "@:more.configuration_wizard", + "end": " для продолжения работы", "in_menu": "Сервер ещё не настроен, воспользуйтесь мастером подключения." }, - "services": { - "_comment": "Вкладка сервисы", - "title": "Ваши личные, приватные и независимые сервисы:", - "service_page": { - "open_in_browser": "Открыть в браузере", - "restart": "Перезапустить сервис", - "disable": "Выключить сервис", - "enable": "Включить сервис", - "move": "Переместить на другой диск", - "uses": "Использует {usage} на {volume}" - }, - "mail": { - "title": "Почта", - "subtitle": "Электронная почта для семьи или компании.", - "login_info": "Используйте логин и пароль из вкладки пользователей. IMAP порт: 143, STARTTLS. SMTP порт: 587, STARTTLS.", - "bottom_sheet": { - "1": "Для подключения почтового ящика используйте {} и профиль, который Вы создали. Так же приглашайте", - "2": "новых пользователей." - } - }, - "messenger": { - "title": "Мессенджер", - "subtitle": "Telegram и Signal не так приватны, как Delta.Chat — он использует Ваш личный сервер.", - "login_info": "Используйте те же логин и пароль, что и для почты.", - "bottom_sheet": { - "1": "Для подключения используйте {} и логин пароль, который Вы создали." - } - }, - "password_manager": { - "title": "Менеджер паролей", - "subtitle": "Это фундамент Вашей безопасности. Создавать, хранить, копировать пароли между устройствами и вбивать их в формы поможет Bitwarden.", - "login_info": "Аккаунт нужно создать на сайте.", - "bottom_sheet": { - "1": "Подключиться к серверу и создать пользователя можно по адресу:." - } - }, - "video": { - "title": "Видеоконференция", - "subtitle": "Jitsi meet — отличный аналог Zoom и Google meet который помимо удобства ещё и гарантирует Вам защищённые высококачественные видеоконференции.", - "login_info": "Аккаунт не требуется.", - "bottom_sheet": { - "1": "Для использования просто перейдите по ссылке:." - } - }, - "cloud": { - "title": "Файловое облако", - "subtitle": "Не позволяйте облачным сервисам просматривать ваши данные. Используйте NextCloud — надёжный дом для всех Ваших данных.", - "login_info": "Логин администратора: admin, пароль такой же как у основного пользователя. Создавайте новых пользователей в интерфейсе администратора NextCloud.", - "bottom_sheet": { - "1": "Подключиться к серверу и создать пользователя можно по адресу:." - } - }, - "social_network": { - "title": "Социальная сеть", - "subtitle": "Сложно поверить, но стало возможным создать свою собственную социальную сеть, со своими правилами и аудиторией.", - "login_info": "Аккаунт нужно создать на сайте.", - "bottom_sheet": { - "1": "Подключиться к серверу и создать пользователя можно по адресу:." - } - }, - "git": { - "title": "Git-сервер", - "subtitle": "Приватная альтернатива Github, которая принадлежит вам, а не Microsoft.", - "login_info": "Аккаунт нужно создать на сайте. Первый зарегистрированный пользователь становится администратором.", - "bottom_sheet": { - "1": "Подключиться к серверу и создать пользователя можно по адресу:." - } - }, - "vpn": { - "title": "VPN сервер", - "subtitle": "Закрытый VPN сервер", - "bottom_sheet": { - "1": "Создать подключиться к VPN-серверу. Движок для безопасной и масштабируемой инфраструктуры VPN" - } - }, - "page": { - "up_and_running": "Запущен и работает", - "resource_usage": "Потребление ресурсов", - "disk_used": "{} использовано места на диске", - "users": "Пользователи", - "controlled_by": "Контролируется {}", - "apps": "Приложения", - "settings": "Настройки" - } + "service_page": { + "open_in_browser": "Открыть в браузере", + "restart": "Перезапустить сервис", + "disable": "Выключить сервис", + "enable": "Включить сервис", + "move": "Переместить на другой диск", + "uses": "Использует {usage} на {volume}" + }, + "mail": { + "title": "Почта", + "subtitle": "Электронная почта для семьи или компании.", + "login_info": "Используйте логин и пароль из вкладки пользователей. IMAP порт: 143, STARTTLS. SMTP порт: 587, STARTTLS." + }, + "password_manager": { + "title": "Менеджер паролей", + "subtitle": "Это фундамент Вашей безопасности. Создавать, хранить, копировать пароли между устройствами и вбивать их в формы поможет Bitwarden.", + "login_info": "Аккаунт нужно создать на сайте." + }, + "video": { + "title": "Видеоконференция", + "subtitle": "Jitsi meet — отличный аналог Zoom и Google meet который помимо удобства ещё и гарантирует Вам защищённые высококачественные видеоконференции.", + "login_info": "Аккаунт не требуется." + }, + "cloud": { + "title": "Файловое облако", + "subtitle": "Не позволяйте облачным сервисам просматривать ваши данные. Используйте NextCloud — надёжный дом для всех Ваших данных.", + "login_info": "Логин администратора: admin, пароль такой же как у основного пользователя. Создавайте новых пользователей в интерфейсе администратора NextCloud." + }, + "social_network": { + "title": "Социальная сеть", + "subtitle": "Сложно поверить, но стало возможным создать свою собственную социальную сеть, со своими правилами и аудиторией.", + "login_info": "Аккаунт нужно создать на сайте." + }, + "git": { + "title": "Git-сервер", + "subtitle": "Приватная альтернатива Github, которая принадлежит вам, а не Microsoft.", + "login_info": "Аккаунт нужно создать на сайте. Первый зарегистрированный пользователь становится администратором." + }, + "vpn": { + "title": "VPN сервер", + "subtitle": "Закрытый VPN сервер" }, "users": { - "_comment": "'Users' tab", "add_new_user": "Добавьте первого пользователя.", "new_user": "Новый пользователь", + "delete_user": "Удалить пользователя", "not_ready": "Подключите сервер, домен и DNS в разделе Провайдеры чтобы добавить первого пользователя", "nobody_here": "Здесь будут отображаться пользователи.", "login": "Логин", - "onboarding": "Приветствие", - "console": "Консоль разработчика", "new_user_info_note": "Новый пользователь автоматически получит доступ ко всем сервисам.", "delete_confirm_question": "Вы действительно хотите удалить учетную запись?", "reset_password": "Сбросить пароль", "account": "Учетная запись", - "send_registration_data": "Поделиться реквизитами" + "send_registration_data": "Поделиться реквизитами", + "could_not_fetch_users": "Не удалось получить пользователей", + "could_not_fetch_description": "Проверьте интернет соединение и попробуйте снова", + "refresh_users": "Обновить список пользователей", + "could_not_create_user": "Не удалось создать пользователя", + "could_not_delete_user": "Не удалось стереть пользователя", + "could_not_add_ssh_key": "Не удалось создать SSH ключить", + "email_login": "Авторизация по Email", + "no_ssh_notice": "Для этого пользователя созданы только SSH и Email аккаунты. Единая авторизация для всех сервисов ещё не реализована." }, "initializing": { - "_comment": "initializing page", - "1": "Подключите сервер", - "2": "Здесь будут жить наши данные и SelfPrivacy-сервисы", + "connect_to_server": "Подключите сервер", + "place_where_data": "Здесь будут жить наши данные и SelfPrivacy-сервисы", "how": "Как получить API Token", "hetzner_bad_key_error": "Hetzner API ключ неверен", "cloudflare_bad_key_error": "Cloudflare API ключ неверен", "backblaze_bad_key_error": "Информация о Backblaze хранилище неверна", - "3": "Подключите CloudFlare", - "4": "Для управления DNS вашего домена", - "5": "CloudFlare API Token", - "6": "Подключите облачное хранилище Backblaze", - "7": "На данный момент подлюченных доменов нет", - "8": "Загружаем список доменов", - "9": "Найдено больше одного домена, для вашей безопастности, просим Вам удалить не нужные домены", - "10": "Сохранить домен", + "connect_cloudflare": "Подключите CloudFlare", + "manage_domain_dns": "Для управления DNS вашего домена", + "cloudflare_api_token": "CloudFlare API Token", + "connect_backblaze_storage": "Подключите облачное хранилище Backblaze", + "no_connected_domains": "На данный момент подлюченных доменов нет", + "loading_domain_list": "Загружаем список доменов", + "found_more_domains": "Найдено больше одного домена, для вашей безопастности, просим Вам удалить не нужные домены", + "save_domain": "Сохранить домен", "final": "Последний шаг", - "11": "Создать сервер", + "create_server": "Создать сервер", "what": "Что это значит?", - "13": "Сервер презагружен, ждем последнюю проверку.", - "14": "Cервер запущен, сейчас он будет проверен и перезагружен.", - "15": "Cервер создан, идет проверка ДНС адресов и запуск сервера.", - "16": "До следующей проверки: ", - "17": "Проверка", - "18": "Как получить Hetzner API Token:'", - "19": "1 Переходим по ссылке ", - "20": "\n2 Заходим в созданный нами проект. Если такового нет - значит создаём.\n3 Наводим мышкой на боковую панель. Она должна раскрыться, показав нам пункты меню. Нас интересует последний — Security (с иконкой ключика).\n4 Далее, в верхней части интерфейса видим примерно такой список: SSH Keys, API Tokens, Certificates, Members. Нам нужен API Tokens. Переходим по нему.\n5 В правой части интерфейса, нас будет ожидать кнопка Generate API token. Если же Вы используете мобильную версию сайта - в нижнем правом углу Вы увидите красный плюсик. Нажимаем на эту кнопку.\n6 В поле Description даём нашему токену название (это может быть любое название, которое Вам нравиться, сути оно не меняет.", - "21": "Сейчас будет дополнительная перезагрузка для активации сертификатов безопастности", - "22": "Создайте главную учетную запись", - "23": "Введите никнейм и сложный пароль", + "server_rebooted": "Сервер презагружен, ждем последнюю проверку.", + "server_started": "Cервер запущен, сейчас он будет проверен и перезагружен.", + "server_created": "Cервер создан, идет проверка ДНС адресов и запуск сервера.", + "until_the_next_check": "До следующей проверки: ", + "check": "Проверка", + "one_more_restart": "Сейчас будет дополнительная перезагрузка для активации сертификатов безопастности", + "create_master_account": "Создайте главную учетную запись", + "enter_nickname_and_password": "Введите никнейм и сложный пароль", "finish": "Всё инициализировано.", "checks": "Проверок выполнено: \n{} / {}" }, @@ -444,19 +370,16 @@ "generation_error": "Не удалось сгенерировать ключ. {}" }, "modals": { - "_comment": "messages in modals", - "1": "Сервер с таким именем уже существует.", - "1.1": "Непредвиденная ошибка при создании со стороны провайдера.", - "2": "Уничтожить сервер и создать новый?", - "2.2": "Попробовать ещё раз?", - "3": "Подтвердите", - "4": "Сбросить все ключи?", - "5": "Да, сбросить", - "6": "Удалить сервер и диск?", - "7": "Да, удалить", - "8": "Удалить задачу", - "9": "Перезагрузить", - "10": "API не поддерживает домены с таким TLD.", + "already_exists": "Такой сервер уже существует.", + "unexpected_error": "Непредвиденная ошибка со стороны провайдера.", + "destroy_server": "Уничтожить сервер и создать новый?", + "try_again": "Попробовать ещё раз?", + "are_you_sure": "Вы уверены?", + "purge_all_keys": "Стереть все ключи авторизации?", + "purge_all_keys_confirm": "Да, стереть все ключи!", + "delete_server_volume": "Удалить сервер и хранилище?", + "reboot": "Перезагрузить", + "you_cant_use_this_api": "Нельзя использовать этот API для доменом с подобным TLD.", "yes": "Да", "no": "Нет" }, @@ -464,27 +387,26 @@ "sec": "{} сек" }, "jobs": { - "_comment": "Jobs list", "title": "Задачи", "start": "Начать выполенение", "empty": "Пусто.", - "createUser": "Создать пользователя", - "deleteUser": "Удалить пользователя", - "serviceTurnOff": "Остановить", - "serviceTurnOn": "Запустить", - "jobAdded": "Задача добавленна", - "runJobs": "Запустите задачи", - "rebootSuccess": "Сервер перезагружается", - "rebootFailed": "Не удалось перезагрузить сервер, проверьте логи", - "configPullFailed": "Не удалось обновить конфигурацию сервера. Обновление ПО запущено.", - "upgradeSuccess": "Запущено обновление сервера", - "upgradeFailed": "Обновить сервер не вышло", - "upgradeServer": "Обновить сервер", - "rebootServer": "Перезагрузить сервер", + "create_user": "Создать пользователя", + "delete_user": "Удалить пользователя", + "service_turn_off": "Остановить", + "service_turn_on": "Запустить", + "job_added": "Задача добавленна", + "run_jobs": "Запустите задачи", + "reboot_success": "Сервер перезагружается", + "reboot_failed": "Не удалось перезагрузить сервер, проверьте логи", + "config_pull_failed": "Не удалось обновить конфигурацию сервера. Обновление ПО запущено.", + "upgrade_success": "Запущено обновление сервера", + "upgrade_failed": "Обновить сервер не вышло", + "upgrade_server": "Обновить сервер", + "reboot_server": "Перезагрузить сервер", "create_ssh_key": "Создать SSH ключ для {}", "delete_ssh_key": "Удалить SSH ключ для {}", "server_jobs": "Задачи на сервере", - "resetUserPassword": "Сбросить пароль пользователя" + "reset_user_password": "Сбросить пароль пользователя" }, "validations": { "required": "Обязательное поле.", diff --git a/lib/logic/common_enum/common_enum.dart b/lib/logic/common_enum/common_enum.dart index 77c2fa82..b1d0b730 100644 --- a/lib/logic/common_enum/common_enum.dart +++ b/lib/logic/common_enum/common_enum.dart @@ -51,55 +51,55 @@ extension ServiceTypesExt on ServiceTypes { String get title { switch (this) { case ServiceTypes.mailserver: - return 'services.mail.title'.tr(); + return 'mail.title'.tr(); case ServiceTypes.bitwarden: - return 'services.password_manager.title'.tr(); + return 'password_manager.title'.tr(); case ServiceTypes.jitsi: - return 'services.video.title'.tr(); + return 'video.title'.tr(); case ServiceTypes.nextcloud: - return 'services.cloud.title'.tr(); + return 'cloud.title'.tr(); case ServiceTypes.pleroma: - return 'services.social_network.title'.tr(); + return 'social_network.title'.tr(); case ServiceTypes.gitea: - return 'services.git.title'.tr(); + return 'git.title'.tr(); case ServiceTypes.ocserv: - return 'services.vpn.title'.tr(); + return 'vpn.title'.tr(); } } String get subtitle { switch (this) { case ServiceTypes.mailserver: - return 'services.mail.subtitle'.tr(); + return 'mail.subtitle'.tr(); case ServiceTypes.bitwarden: - return 'services.password_manager.subtitle'.tr(); + return 'password_manager.subtitle'.tr(); case ServiceTypes.jitsi: - return 'services.video.subtitle'.tr(); + return 'video.subtitle'.tr(); case ServiceTypes.nextcloud: - return 'services.cloud.subtitle'.tr(); + return 'cloud.subtitle'.tr(); case ServiceTypes.pleroma: - return 'services.social_network.subtitle'.tr(); + return 'social_network.subtitle'.tr(); case ServiceTypes.gitea: - return 'services.git.subtitle'.tr(); + return 'git.subtitle'.tr(); case ServiceTypes.ocserv: - return 'services.vpn.subtitle'.tr(); + return 'vpn.subtitle'.tr(); } } String get loginInfo { switch (this) { case ServiceTypes.mailserver: - return 'services.mail.login_info'.tr(); + return 'mail.login_info'.tr(); case ServiceTypes.bitwarden: - return 'services.password_manager.login_info'.tr(); + return 'password_manager.login_info'.tr(); case ServiceTypes.jitsi: - return 'services.video.login_info'.tr(); + return 'video.login_info'.tr(); case ServiceTypes.nextcloud: - return 'services.cloud.login_info'.tr(); + return 'cloud.login_info'.tr(); case ServiceTypes.pleroma: - return 'services.social_network.login_info'.tr(); + return 'social_network.login_info'.tr(); case ServiceTypes.gitea: - return 'services.git.login_info'.tr(); + return 'git.login_info'.tr(); case ServiceTypes.ocserv: return ''; } diff --git a/lib/logic/cubit/backups/backups_cubit.dart b/lib/logic/cubit/backups/backups_cubit.dart index bb89bb49..084a2b47 100644 --- a/lib/logic/cubit/backups/backups_cubit.dart +++ b/lib/logic/cubit/backups/backups_cubit.dart @@ -135,7 +135,7 @@ class BackupsCubit extends ServerInstallationDependendCubit { } else { await api.uploadBackblazeConfig(bucket); emit(state.copyWith(isInitialized: true, preventActions: false)); - getIt().showSnackBar('providers.backup.reuploadedKey'); + getIt().showSnackBar('backup.reuploaded_key'); } } @@ -173,8 +173,7 @@ class BackupsCubit extends ServerInstallationDependendCubit { Future forceUpdateBackups() async { emit(state.copyWith(preventActions: true)); await api.forceBackupListReload(); - getIt() - .showSnackBar('providers.backup.refetchingList'.tr()); + getIt().showSnackBar('backup.refetching_list'.tr()); emit(state.copyWith(preventActions: false)); } diff --git a/lib/logic/cubit/client_jobs/client_jobs_cubit.dart b/lib/logic/cubit/client_jobs/client_jobs_cubit.dart index 4fa610cd..a6d23a23 100644 --- a/lib/logic/cubit/client_jobs/client_jobs_cubit.dart +++ b/lib/logic/cubit/client_jobs/client_jobs_cubit.dart @@ -30,7 +30,7 @@ class JobsCubit extends Cubit { newJobsList.addAll(jobsState.clientJobList); } newJobsList.add(job); - getIt().showSnackBar('jobs.jobAdded'.tr()); + getIt().showSnackBar('jobs.job_added'.tr()); emit(JobsStateWithJobs(newJobsList)); } @@ -53,7 +53,7 @@ class JobsCubit extends Cubit { removeJob(removingJob.id); } else { newJobsList.add(job); - getIt().showSnackBar('jobs.jobAdded'.tr()); + getIt().showSnackBar('jobs.job_added'.tr()); emit(JobsStateWithJobs(newJobsList)); } } @@ -67,7 +67,7 @@ class JobsCubit extends Cubit { newJobsList.any((final el) => el is CreateSSHKeyJob); if (!isExistInJobList) { newJobsList.add(job); - getIt().showSnackBar('jobs.jobAdded'.tr()); + getIt().showSnackBar('jobs.job_added'.tr()); emit(JobsStateWithJobs(newJobsList)); } } @@ -76,9 +76,9 @@ class JobsCubit extends Cubit { emit(JobsStateLoading()); final bool isSuccessful = await api.reboot(); if (isSuccessful) { - getIt().showSnackBar('jobs.rebootSuccess'.tr()); + getIt().showSnackBar('jobs.reboot_success'.tr()); } else { - getIt().showSnackBar('jobs.rebootFailed'.tr()); + getIt().showSnackBar('jobs.reboot_failed'.tr()); } emit(JobsStateEmpty()); } @@ -89,12 +89,12 @@ class JobsCubit extends Cubit { final bool isSuccessful = await api.upgrade(); if (isSuccessful) { if (!isPullSuccessful) { - getIt().showSnackBar('jobs.configPullFailed'.tr()); + getIt().showSnackBar('jobs.config_pull_failed'.tr()); } else { - getIt().showSnackBar('jobs.upgradeSuccess'.tr()); + getIt().showSnackBar('jobs.upgrade_success'.tr()); } } else { - getIt().showSnackBar('jobs.upgradeFailed'.tr()); + getIt().showSnackBar('jobs.upgrade_failed'.tr()); } emit(JobsStateEmpty()); } diff --git a/lib/logic/cubit/dns_records/dns_records_cubit.dart b/lib/logic/cubit/dns_records/dns_records_cubit.dart index 93ff3db8..b6d503aa 100644 --- a/lib/logic/cubit/dns_records/dns_records_cubit.dart +++ b/lib/logic/cubit/dns_records/dns_records_cubit.dart @@ -51,8 +51,7 @@ class DnsRecordsCubit _getDesiredDnsRecords(domain.domainName, ipAddress, dkimPublicKey); final List foundRecords = []; for (final DesiredDnsRecord record in desiredRecords) { - if (record.description == - 'providers.domain.record_description.dkim') { + if (record.description == 'record.dkim') { final DnsRecord foundRecord = records.firstWhere( (final r) => r.name == record.name && r.type == record.type, orElse: () => DnsRecord( @@ -146,61 +145,61 @@ class DnsRecordsCubit DesiredDnsRecord( name: domainName, content: ipAddress, - description: 'providers.domain.record_description.root', + description: 'record.root', ), DesiredDnsRecord( name: 'api.$domainName', content: ipAddress, - description: 'providers.domain.record_description.api', + description: 'record.api', ), DesiredDnsRecord( name: 'cloud.$domainName', content: ipAddress, - description: 'providers.domain.record_description.cloud', + description: 'record.cloud', ), DesiredDnsRecord( name: 'git.$domainName', content: ipAddress, - description: 'providers.domain.record_description.git', + description: 'record.git', ), DesiredDnsRecord( name: 'meet.$domainName', content: ipAddress, - description: 'providers.domain.record_description.meet', + description: 'record.meet', ), DesiredDnsRecord( name: 'social.$domainName', content: ipAddress, - description: 'providers.domain.record_description.social', + description: 'record.social', ), DesiredDnsRecord( name: 'password.$domainName', content: ipAddress, - description: 'providers.domain.record_description.password', + description: 'record.password', ), DesiredDnsRecord( name: 'vpn.$domainName', content: ipAddress, - description: 'providers.domain.record_description.vpn', + description: 'record.vpn', ), DesiredDnsRecord( name: domainName, content: domainName, - description: 'providers.domain.record_description.mx', + description: 'record.mx', type: 'MX', category: DnsRecordsCategory.email, ), DesiredDnsRecord( name: '_dmarc.$domainName', content: 'v=DMARC1; p=none', - description: 'providers.domain.record_description.dmarc', + description: 'record.dmarc', type: 'TXT', category: DnsRecordsCategory.email, ), DesiredDnsRecord( name: domainName, content: 'v=spf1 a mx ip4:$ipAddress -all', - description: 'providers.domain.record_description.spf', + description: 'record.spf', type: 'TXT', category: DnsRecordsCategory.email, ), @@ -208,7 +207,7 @@ class DnsRecordsCubit DesiredDnsRecord( name: 'selector._domainkey.$domainName', content: dkimPublicKey, - description: 'providers.domain.record_description.dkim', + description: 'record.dkim', type: 'TXT', category: DnsRecordsCategory.email, ), diff --git a/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart b/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart index 6a1c7d16..b0500452 100644 --- a/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart +++ b/lib/logic/cubit/provider_volumes/provider_volume_cubit.dart @@ -86,7 +86,7 @@ class ApiProviderVolumeCubit if (!resized) { getIt().showSnackBar( - 'providers.storage.extending_volume_error'.tr(), + 'storage.extending_volume_error'.tr(), ); emit(state.copyWith(isResizing: false)); return false; diff --git a/lib/logic/cubit/server_installation/server_installation_repository.dart b/lib/logic/cubit/server_installation/server_installation_repository.dart index 76089229..c941b9d1 100644 --- a/lib/logic/cubit/server_installation/server_installation_repository.dart +++ b/lib/logic/cubit/server_installation/server_installation_repository.dart @@ -250,8 +250,8 @@ class ServerInstallationRepository { final NavigationService nav = getIt.get(); nav.showPopUpDialog( BrandAlert( - title: 'modals.1'.tr(), - contentText: 'modals.2'.tr(), + title: 'modals.already_exists'.tr(), + contentText: 'modals.destroy_server'.tr(), actions: [ ActionButton( text: 'basis.delete'.tr(), @@ -291,11 +291,11 @@ class ServerInstallationRepository { final NavigationService nav = getIt.get(); nav.showPopUpDialog( BrandAlert( - title: 'modals.1_1'.tr(), - contentText: 'modals.2_2'.tr(), + title: 'modals.unexpected_error'.tr(), + contentText: 'modals.try_again'.tr(), actions: [ ActionButton( - text: 'modals.7'.tr(), + text: 'modals.yes'.tr(), isRed: true, onPressed: () async { ServerHostingDetails? serverDetails; @@ -353,9 +353,9 @@ class ServerInstallationRepository { nav.showPopUpDialog( BrandAlert( title: e.response!.data['errors'][0]['code'] == 1038 - ? 'modals.10'.tr() - : 'providers.domain.states.error'.tr(), - contentText: 'modals.6'.tr(), + ? 'modals.you_cant_use_this_api'.tr() + : 'domain.states.error'.tr(), + contentText: 'modals.delete_server_volume'.tr(), actions: [ ActionButton( text: 'basis.delete'.tr(), diff --git a/lib/logic/models/disk_size.dart b/lib/logic/models/disk_size.dart index 9fe18b7d..44c6bc35 100644 --- a/lib/logic/models/disk_size.dart +++ b/lib/logic/models/disk_size.dart @@ -28,11 +28,11 @@ class DiskSize { if (byte < 1024) { return '${byte.toStringAsFixed(0)} ${tr('bytes')}'; } else if (byte < 1024 * 1024) { - return 'providers.storage.kb'.tr(args: [kibibyte.toStringAsFixed(1)]); + return 'storage.kb'.tr(args: [kibibyte.toStringAsFixed(1)]); } else if (byte < 1024 * 1024 * 1024) { - return 'providers.storage.mb'.tr(args: [mebibyte.toStringAsFixed(1)]); + return 'storage.mb'.tr(args: [mebibyte.toStringAsFixed(1)]); } else { - return 'providers.storage.gb'.tr(args: [gibibyte.toStringAsFixed(1)]); + return 'storage.gb'.tr(args: [gibibyte.toStringAsFixed(1)]); } } } diff --git a/lib/logic/models/job.dart b/lib/logic/models/job.dart index 1dc1bd91..c3748daa 100644 --- a/lib/logic/models/job.dart +++ b/lib/logic/models/job.dart @@ -30,7 +30,7 @@ class RebuildServerJob extends ClientJob { class CreateUserJob extends ClientJob { CreateUserJob({ required this.user, - }) : super(title: '${"jobs.createUser".tr()} ${user.login}'); + }) : super(title: '${"jobs.create_user".tr()} ${user.login}'); final User user; @@ -41,7 +41,7 @@ class CreateUserJob extends ClientJob { class ResetUserPasswordJob extends ClientJob { ResetUserPasswordJob({ required this.user, - }) : super(title: '${"jobs.resetUserPassword".tr()} ${user.login}'); + }) : super(title: '${"jobs.reset_user_password".tr()} ${user.login}'); final User user; @@ -52,7 +52,7 @@ class ResetUserPasswordJob extends ClientJob { class DeleteUserJob extends ClientJob { DeleteUserJob({ required this.user, - }) : super(title: '${"jobs.deleteUser".tr()} ${user.login}'); + }) : super(title: '${"jobs.delete_user".tr()} ${user.login}'); final User user; @@ -78,7 +78,7 @@ class ServiceToggleJob extends ToggleJob { required this.needToTurnOn, }) : super( title: - '${needToTurnOn ? "jobs.serviceTurnOn".tr() : "jobs.serviceTurnOff".tr()} ${type.title}', + '${needToTurnOn ? "jobs.service_turn_on".tr() : "jobs.service_turn_off".tr()} ${type.title}', ); final bool needToTurnOn; diff --git a/lib/ui/components/jobs_content/jobs_content.dart b/lib/ui/components/jobs_content/jobs_content.dart index 877770dc..c49ceccf 100644 --- a/lib/ui/components/jobs_content/jobs_content.dart +++ b/lib/ui/components/jobs_content/jobs_content.dart @@ -43,7 +43,7 @@ class JobsContent extends StatelessWidget { const SizedBox(height: 80), BrandButton.rised( onPressed: () => context.read().upgradeServer(), - text: 'jobs.upgradeServer'.tr(), + text: 'jobs.upgrade_server'.tr(), ), const SizedBox(height: 10), BrandButton.text( @@ -51,8 +51,8 @@ class JobsContent extends StatelessWidget { final NavigationService nav = getIt(); nav.showPopUpDialog( BrandAlert( - title: 'jobs.rebootServer'.tr(), - contentText: 'modals.3'.tr(), + title: 'jobs.reboot_server'.tr(), + contentText: 'modals.are_you_sure'.tr(), actions: [ ActionButton( text: 'basis.cancel'.tr(), @@ -60,13 +60,13 @@ class JobsContent extends StatelessWidget { ActionButton( onPressed: () => {context.read().rebootServer()}, - text: 'modals.9'.tr(), + text: 'modals.reboot'.tr(), ) ], ), ); }, - title: 'jobs.rebootServer'.tr(), + title: 'jobs.reboot_server'.tr(), ), ]; } diff --git a/lib/ui/components/not_ready_card/not_ready_card.dart b/lib/ui/components/not_ready_card/not_ready_card.dart index 49947c1b..faa23381 100644 --- a/lib/ui/components/not_ready_card/not_ready_card.dart +++ b/lib/ui/components/not_ready_card/not_ready_card.dart @@ -19,7 +19,7 @@ class NotReadyCard extends StatelessWidget { text: TextSpan( children: [ TextSpan( - text: 'not_ready_card.1'.tr(), + text: 'not_ready_card.begin'.tr(), style: const TextStyle(color: BrandColors.white), ), WidgetSpan( @@ -32,7 +32,7 @@ class NotReadyCard extends StatelessWidget { ), ), child: Text( - 'not_ready_card.2'.tr(), + 'not_ready_card.insertion'.tr(), style: body1Style.copyWith( color: Colors.white, fontWeight: FontWeight.bold, @@ -44,7 +44,7 @@ class NotReadyCard extends StatelessWidget { ), ), TextSpan( - text: 'not_ready_card.3'.tr(), + text: 'not_ready_card.end'.tr(), style: const TextStyle(color: BrandColors.white), ), ], diff --git a/lib/ui/components/storage_list_items/server_storage_list_item.dart b/lib/ui/components/storage_list_items/server_storage_list_item.dart index 1cc07572..8c675685 100644 --- a/lib/ui/components/storage_list_items/server_storage_list_item.dart +++ b/lib/ui/components/storage_list_items/server_storage_list_item.dart @@ -17,12 +17,12 @@ class ServerStorageListItem extends StatelessWidget { @override Widget build(final BuildContext context) => ConsumptionListItem( - title: 'providers.storage.disk_usage'.tr( + title: 'storage.disk_usage'.tr( args: [ volume.sizeUsed.toString(), ], ), - subtitle: 'providers.storage.disk_total'.tr( + subtitle: 'storage.disk_total'.tr( args: [ volume.sizeTotal.toString(), volume.displayName, diff --git a/lib/ui/pages/backup_details/backup_details.dart b/lib/ui/pages/backup_details/backup_details.dart index b3635d3f..8936f59e 100644 --- a/lib/ui/pages/backup_details/backup_details.dart +++ b/lib/ui/pages/backup_details/backup_details.dart @@ -46,8 +46,8 @@ class _BackupDetailsState extends State return BrandHeroScreen( heroIcon: BrandIcons.save, - heroTitle: 'providers.backup.card_title'.tr(), - heroSubtitle: 'providers.backup.bottom_sheet.1'.tr(), + heroTitle: 'backup.card_title'.tr(), + heroSubtitle: 'backup.description'.tr(), children: [ if (isReady && !isBackupInitialized) BrandButton.rised( @@ -56,10 +56,10 @@ class _BackupDetailsState extends State : () async { await context.read().createBucket(); }, - text: 'providers.backup.initialize'.tr(), + text: 'backup.initialize'.tr(), ), if (backupStatus == BackupStatusEnum.initializing) - BrandText.body1('providers.backup.waitingForRebuild'.tr()), + BrandText.body1('backup.waiting_for_rebuild'.tr()), if (backupStatus != BackupStatusEnum.initializing && backupStatus != BackupStatusEnum.noKey) OutlinedCard( @@ -77,14 +77,14 @@ class _BackupDetailsState extends State Icons.add_circle_outline_rounded, ), title: Text( - 'providers.backup.create_new'.tr(), + 'backup.create_new'.tr(), style: Theme.of(context).textTheme.headline6, ), ), if (backupStatus == BackupStatusEnum.backingUp) ListTile( title: Text( - 'providers.backup.creating'.tr( + 'backup.creating'.tr( args: [(backupProgress * 100).round().toString()], ), style: Theme.of(context).textTheme.headline6, @@ -97,7 +97,7 @@ class _BackupDetailsState extends State if (backupStatus == BackupStatusEnum.restoring) ListTile( title: Text( - 'providers.backup.restoring'.tr( + 'backup.restoring'.tr( args: [(backupProgress * 100).round().toString()], ), style: Theme.of(context).textTheme.headline6, @@ -113,7 +113,7 @@ class _BackupDetailsState extends State color: Theme.of(context).colorScheme.error, ), title: Text( - 'providers.backup.error_pending'.tr(), + 'backup.error_pending'.tr(), style: Theme.of(context).textTheme.headline6, ), ), @@ -135,7 +135,7 @@ class _BackupDetailsState extends State Icons.refresh, ), title: Text( - 'providers.backup.restore'.tr(), + 'backup.restore'.tr(), style: Theme.of(context).textTheme.headline6, ), ), @@ -147,7 +147,7 @@ class _BackupDetailsState extends State leading: const Icon( Icons.error_outline, ), - title: Text('providers.backup.no_backups'.tr()), + title: Text('backup.no_backups'.tr()), ), if (backups.isNotEmpty) Column( @@ -161,10 +161,8 @@ class _BackupDetailsState extends State getIt(); nav.showPopUpDialog( BrandAlert( - title: - 'providers.backup.restoring'.tr(), - contentText: - 'providers.backup.restore_alert'.tr( + title: 'backup.restoring'.tr(), + contentText: 'backup.restore_alert'.tr( args: [backup.time.toString()], ), actions: [ @@ -200,7 +198,7 @@ class _BackupDetailsState extends State children: [ ListTile( title: Text( - 'providers.backup.refresh'.tr(), + 'backup.refresh'.tr(), ), onTap: refreshing ? null @@ -215,7 +213,7 @@ class _BackupDetailsState extends State ), ListTile( title: Text( - 'providers.backup.refetchBackups'.tr(), + 'backup.refetch_backups'.tr(), ), onTap: preventActions ? null @@ -230,7 +228,7 @@ class _BackupDetailsState extends State ), ListTile( title: Text( - 'providers.backup.reuploadKey'.tr(), + 'backup.reupload_key'.tr(), ), onTap: preventActions ? null diff --git a/lib/ui/pages/dns_details/dns_details.dart b/lib/ui/pages/dns_details/dns_details.dart index 5a3d0dfd..5a93a53e 100644 --- a/lib/ui/pages/dns_details/dns_details.dart +++ b/lib/ui/pages/dns_details/dns_details.dart @@ -28,7 +28,7 @@ class _DnsDetailsPageState extends State { bool isError = false; switch (dnsState) { case DnsRecordsStatus.uninitialized: - description = 'providers.domain.states.uninitialized'.tr(); + description = 'domain.states.uninitialized'.tr(); icon = const Icon( Icons.refresh, size: 24.0, @@ -36,7 +36,7 @@ class _DnsDetailsPageState extends State { isError = false; break; case DnsRecordsStatus.refreshing: - description = 'providers.domain.states.refreshing'.tr(); + description = 'domain.states.refreshing'.tr(); icon = const Icon( Icons.refresh, size: 24.0, @@ -44,7 +44,7 @@ class _DnsDetailsPageState extends State { isError = false; break; case DnsRecordsStatus.good: - description = 'providers.domain.states.ok'.tr(); + description = 'domain.states.ok'.tr(); icon = const Icon( Icons.check_circle_outline, size: 24.0, @@ -52,8 +52,8 @@ class _DnsDetailsPageState extends State { isError = false; break; case DnsRecordsStatus.error: - description = 'providers.domain.states.error'.tr(); - subtitle = 'providers.domain.states.error_subtitle'.tr(); + description = 'domain.states.error'.tr(); + subtitle = 'domain.states.error_subtitle'.tr(); icon = const Icon( Icons.error_outline, size: 24.0, @@ -93,7 +93,7 @@ class _DnsDetailsPageState extends State { hasBackButton: true, headerTitle: '', heroIcon: BrandIcons.globe, - heroTitle: 'providers.domain.screen_title'.tr(), + heroTitle: 'domain.screen_title'.tr(), heroSubtitle: 'not_ready_card.in_menu'.tr(), children: const [], ); @@ -107,7 +107,7 @@ class _DnsDetailsPageState extends State { hasBackButton: true, heroSubtitle: domain, heroIcon: BrandIcons.globe, - heroTitle: 'providers.domain.screen_title'.tr(), + heroTitle: 'domain.screen_title'.tr(), children: [ _getStateCard(dnsCubit.dnsState, () { context.read().fix(); @@ -115,13 +115,13 @@ class _DnsDetailsPageState extends State { const SizedBox(height: 16.0), ListTile( title: Text( - 'providers.domain.cards.services.title'.tr(), + 'domain.services_title'.tr(), style: Theme.of(context).textTheme.headlineSmall!.copyWith( color: Theme.of(context).colorScheme.secondary, ), ), subtitle: Text( - 'providers.domain.cards.services.subtitle'.tr(), + 'domain.services_subtitle'.tr(), style: Theme.of(context).textTheme.labelMedium, ), ), @@ -160,13 +160,13 @@ class _DnsDetailsPageState extends State { const SizedBox(height: 16.0), ListTile( title: Text( - 'providers.domain.cards.email.title'.tr(), + 'domain.email_title'.tr(), style: Theme.of(context).textTheme.headlineSmall!.copyWith( color: Theme.of(context).colorScheme.secondary, ), ), subtitle: Text( - 'providers.domain.cards.email.subtitle'.tr(), + 'domain.email_subtitle'.tr(), style: Theme.of(context).textTheme.labelMedium, ), ), diff --git a/lib/ui/pages/more/info/info.dart b/lib/ui/pages/more/about_application.dart similarity index 83% rename from lib/ui/pages/more/info/info.dart rename to lib/ui/pages/more/about_application.dart index 8d2526d6..664dce3e 100644 --- a/lib/ui/pages/more/info/info.dart +++ b/lib/ui/pages/more/about_application.dart @@ -6,16 +6,17 @@ import 'package:selfprivacy/ui/components/brand_text/brand_text.dart'; import 'package:package_info/package_info.dart'; import 'package:easy_localization/easy_localization.dart'; -class InfoPage extends StatelessWidget { - const InfoPage({final super.key}); +class AboutApplicationPage extends StatelessWidget { + const AboutApplicationPage({final super.key}); @override Widget build(final BuildContext context) => SafeArea( child: Scaffold( appBar: PreferredSize( preferredSize: const Size.fromHeight(52), - child: - BrandHeader(title: 'more.about_app'.tr(), hasBackButton: true), + child: BrandHeader( + title: 'about_application_page.title'.tr(), + hasBackButton: true), ), body: ListView( padding: paddingH15V0, @@ -24,14 +25,14 @@ class InfoPage extends StatelessWidget { FutureBuilder( future: _packageVersion(), builder: (final context, final snapshot) => BrandText.body1( - 'more.about_app_page.application_version_text' + 'about_application_page.application_version_text' .tr(args: [snapshot.data.toString()]), ), ), FutureBuilder( future: _apiVersion(), builder: (final context, final snapshot) => BrandText.body1( - 'more.about_app_page.api_version_text' + 'about_application_page.api_version_text' .tr(args: [snapshot.data.toString()]), ), ), diff --git a/lib/ui/pages/more/about/about.dart b/lib/ui/pages/more/about_us.dart similarity index 85% rename from lib/ui/pages/more/about/about.dart rename to lib/ui/pages/more/about_us.dart index 15a7db13..4061c2bb 100644 --- a/lib/ui/pages/more/about/about.dart +++ b/lib/ui/pages/more/about_us.dart @@ -4,8 +4,8 @@ import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:selfprivacy/ui/components/brand_md/brand_md.dart'; -class AboutPage extends StatelessWidget { - const AboutPage({final super.key}); +class AboutUsPage extends StatelessWidget { + const AboutUsPage({final super.key}); @override Widget build(final BuildContext context) => SafeArea( @@ -13,7 +13,7 @@ class AboutPage extends StatelessWidget { appBar: PreferredSize( preferredSize: const Size.fromHeight(52), child: BrandHeader( - title: 'more.about_project'.tr(), + title: 'about_us_page.title'.tr(), hasBackButton: true, ), ), diff --git a/lib/ui/pages/more/app_settings/app_setting.dart b/lib/ui/pages/more/app_settings/app_setting.dart index 47e2e1a8..abbfd0ee 100644 --- a/lib/ui/pages/more/app_settings/app_setting.dart +++ b/lib/ui/pages/more/app_settings/app_setting.dart @@ -30,7 +30,7 @@ class _AppSettingsPageState extends State { appBar: PreferredSize( preferredSize: const Size.fromHeight(52), child: BrandHeader( - title: 'more.settings.title'.tr(), + title: 'application_settings.title'.tr(), hasBackButton: true, ), ), @@ -46,8 +46,9 @@ class _AppSettingsPageState extends State { children: [ Flexible( child: _TextColumn( - title: 'more.settings.1'.tr(), - value: 'more.settings.2'.tr(), + title: 'application_settings.dark_theme_title'.tr(), + value: + 'application_settings.dark_theme_description'.tr(), hasWarning: false, ), ), @@ -70,8 +71,9 @@ class _AppSettingsPageState extends State { children: [ Flexible( child: _TextColumn( - title: 'more.settings.3'.tr(), - value: 'more.settings.4'.tr(), + title: 'application_settings.reset_config_title'.tr(), + value: 'application_settings.reset_config_description' + .tr(), hasWarning: false, ), ), @@ -91,11 +93,11 @@ class _AppSettingsPageState extends State { showDialog( context: context, builder: (final _) => BrandAlert( - title: 'modals.3'.tr(), - contentText: 'modals.4'.tr(), + title: 'modals.are_you_sure'.tr(), + contentText: 'modals.purge_all_keys'.tr(), actions: [ ActionButton( - text: 'modals.5'.tr(), + text: 'modals.purge_all_keys_confirm'.tr(), isRed: true, onPressed: () { context @@ -135,8 +137,8 @@ class _AppSettingsPageState extends State { children: [ Flexible( child: _TextColumn( - title: 'more.settings.5'.tr(), - value: 'more.settings.6'.tr(), + title: 'application_settings.delete_server_title'.tr(), + value: 'application_settings.delete_server_description'.tr(), hasWarning: false, ), ), @@ -151,11 +153,11 @@ class _AppSettingsPageState extends State { showDialog( context: context, builder: (final _) => BrandAlert( - title: 'modals.3'.tr(), - contentText: 'modals.6'.tr(), + title: 'modals.are_you_sure'.tr(), + contentText: 'modals.delete_server_volume'.tr(), actions: [ ActionButton( - text: 'modals.7'.tr(), + text: 'modals.yes'.tr(), isRed: true, onPressed: () async { showDialog( diff --git a/lib/ui/pages/more/console/console.dart b/lib/ui/pages/more/console.dart similarity index 89% rename from lib/ui/pages/more/console/console.dart rename to lib/ui/pages/more/console.dart index e3951013..81c387f1 100644 --- a/lib/ui/pages/more/console/console.dart +++ b/lib/ui/pages/more/console.dart @@ -1,5 +1,6 @@ import 'dart:collection'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/get_it_config.dart'; @@ -35,8 +36,11 @@ class _ConsoleState extends State { appBar: PreferredSize( preferredSize: const Size.fromHeight(53), child: Column( - children: const [ - BrandHeader(title: 'Console', hasBackButton: true) + children: [ + BrandHeader( + title: 'console_page.title'.tr(), + hasBackButton: true, + ), ], ), ), @@ -90,12 +94,12 @@ class _ConsoleState extends State { return Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, - children: const [ - Text('Waiting for initialisation'), - SizedBox( + children: [ + Text('console_page.waiting'.tr()), + const SizedBox( height: 16, ), - CircularProgressIndicator(), + const CircularProgressIndicator(), ], ); } diff --git a/lib/ui/pages/more/more.dart b/lib/ui/pages/more/more.dart index bc0468b0..5d487717 100644 --- a/lib/ui/pages/more/more.dart +++ b/lib/ui/pages/more/more.dart @@ -17,10 +17,10 @@ import 'package:selfprivacy/ui/pages/root_route.dart'; import 'package:selfprivacy/ui/pages/users/users.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart'; -import 'package:selfprivacy/ui/pages/more/about/about.dart'; +import 'package:selfprivacy/ui/pages/more/about_us.dart'; import 'package:selfprivacy/ui/pages/more/app_settings/app_setting.dart'; -import 'package:selfprivacy/ui/pages/more/console/console.dart'; -import 'package:selfprivacy/ui/pages/more/info/info.dart'; +import 'package:selfprivacy/ui/pages/more/console.dart'; +import 'package:selfprivacy/ui/pages/more/about_application.dart'; class MorePage extends StatelessWidget { const MorePage({final super.key}); @@ -48,7 +48,7 @@ class MorePage extends StatelessWidget { children: [ if (isReady && usesBinds != null && !usesBinds) _MoreMenuItem( - title: 'providers.storage.start_migration_button'.tr(), + title: 'storage.start_migration_button'.tr(), iconData: Icons.drive_file_move_outline, goTo: ServicesMigrationPage( diskStatus: context @@ -70,12 +70,12 @@ class MorePage extends StatelessWidget { .toList(), isMigration: true, ), - subtitle: 'providers.storage.data_migration_notice'.tr(), + subtitle: 'storage.data_migration_notice'.tr(), accent: true, ), if (!isReady) _MoreMenuItem( - title: 'more.configuration_wizard'.tr(), + title: 'more_page.configuration_wizard'.tr(), iconData: Icons.change_history_outlined, goTo: const InitializingPage(), subtitle: 'not_ready_card.in_menu'.tr(), @@ -83,7 +83,7 @@ class MorePage extends StatelessWidget { ), if (isReady) _MoreMenuItem( - title: 'more.create_ssh_key'.tr(), + title: 'more_page.create_ssh_key'.tr(), iconData: Ionicons.key_outline, goTo: const UserDetails( login: 'root', @@ -102,28 +102,28 @@ class MorePage extends StatelessWidget { title: 'devices.main_screen.header'.tr(), ), _MoreMenuItem( - title: 'more.settings.title'.tr(), + title: 'more_page.application_settings'.tr(), iconData: Icons.settings_outlined, goTo: const AppSettingsPage(), ), _MoreMenuItem( - title: 'more.about_project'.tr(), + title: 'more_page.about_project'.tr(), iconData: BrandIcons.engineer, - goTo: const AboutPage(), + goTo: const AboutUsPage(), ), _MoreMenuItem( - title: 'more.about_app'.tr(), + title: 'more_page.about_application'.tr(), iconData: BrandIcons.fire, - goTo: const InfoPage(), + goTo: const AboutApplicationPage(), ), if (!isReady) _MoreMenuItem( - title: 'more.onboarding'.tr(), + title: 'more_page.onboarding'.tr(), iconData: BrandIcons.start, goTo: const OnboardingPage(nextPage: RootPage()), ), _MoreMenuItem( - title: 'more.console'.tr(), + title: 'more_page.console'.tr(), iconData: BrandIcons.terminal, goTo: const Console(), ), diff --git a/lib/ui/pages/providers/providers.dart b/lib/ui/pages/providers/providers.dart index 8b06751b..988b609a 100644 --- a/lib/ui/pages/providers/providers.dart +++ b/lib/ui/pages/providers/providers.dart @@ -64,7 +64,7 @@ class _ProvidersPageState extends State { appBar: PreferredSize( preferredSize: const Size.fromHeight(52), child: BrandHeader( - title: 'providers.page_title'.tr(), + title: 'basis.providers_title'.tr(), ), ), body: ListView( @@ -77,10 +77,10 @@ class _ProvidersPageState extends State { _Card( state: getServerStatus(), icon: BrandIcons.server, - title: 'providers.server.card_title'.tr(), + title: 'server.card_title'.tr(), subtitle: diskStatus.isDiskOkay - ? 'providers.storage.status_ok'.tr() - : 'providers.storage.status_error'.tr(), + ? 'storage.status_ok'.tr() + : 'storage.status_error'.tr(), onTap: () => Navigator.of(context) .push(materialRoute(const ServerDetailsScreen())), ), @@ -88,7 +88,7 @@ class _ProvidersPageState extends State { _Card( state: getDnsStatus(), icon: BrandIcons.globe, - title: 'providers.domain.screen_title'.tr(), + title: 'domain.screen_title'.tr(), subtitle: appConfig.isDomainSelected ? appConfig.serverDomain!.domainName : '', @@ -106,10 +106,8 @@ class _ProvidersPageState extends State { ? StateType.stable : StateType.uninitialized, icon: BrandIcons.save, - title: 'providers.backup.card_title'.tr(), - subtitle: isBackupInitialized - ? 'providers.backup.card_subtitle'.tr() - : '', + title: 'backup.card_title'.tr(), + subtitle: isBackupInitialized ? 'backup.card_subtitle'.tr() : '', onTap: () => Navigator.of(context) .push(materialRoute(const BackupDetails())), ), diff --git a/lib/ui/pages/server_details/charts/chart.dart b/lib/ui/pages/server_details/charts/chart.dart index 60dfc092..3a3eb5a7 100644 --- a/lib/ui/pages/server_details/charts/chart.dart +++ b/lib/ui/pages/server_details/charts/chart.dart @@ -17,7 +17,7 @@ class _Chart extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'providers.server.chart.cpu_title'.tr(), + 'resource_chart.cpu_title'.tr(), style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), @@ -50,7 +50,7 @@ class _Chart extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - 'providers.server.chart.network_title'.tr(), + 'resource_chart.network_title'.tr(), style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, @@ -59,12 +59,12 @@ class _Chart extends StatelessWidget { const Spacer(), Legend( color: Theme.of(context).colorScheme.primary, - text: 'providers.server.chart.in'.tr(), + text: 'resource_chart.in'.tr(), ), const SizedBox(width: 5), Legend( color: Theme.of(context).colorScheme.tertiary, - text: 'providers.server.chart.out'.tr(), + text: 'resource_chart.out'.tr(), ), ], ), @@ -111,9 +111,9 @@ class _Chart extends StatelessWidget { } }, titles: [ - 'providers.server.chart.month'.tr(), - 'providers.server.chart.day'.tr(), - 'providers.server.chart.hour'.tr() + 'resource_chart.month'.tr(), + 'resource_chart.day'.tr(), + 'resource_chart.hour'.tr() ], ), const SizedBox(height: 8), diff --git a/lib/ui/pages/server_details/charts/network_charts.dart b/lib/ui/pages/server_details/charts/network_charts.dart index 7487fd32..43a092f2 100644 --- a/lib/ui/pages/server_details/charts/network_charts.dart +++ b/lib/ui/pages/server_details/charts/network_charts.dart @@ -51,7 +51,7 @@ class NetworkChart extends StatelessWidget { res.add( LineTooltipItem( - '${timeShown ? '' : DateFormat('HH:mm dd.MM.yyyy').format(date)} ${spot.barIndex == 0 ? 'providers.server.chart.in'.tr() : 'providers.server.chart.out'.tr()} ${DiskSize(byte: value.toInt()).toString()}', + '${timeShown ? '' : DateFormat('HH:mm dd.MM.yyyy').format(date)} ${spot.barIndex == 0 ? 'resource_chart.in'.tr() : 'resource_chart.out'.tr()} ${DiskSize(byte: value.toInt()).toString()}', TextStyle( color: Theme.of(context).colorScheme.onSurface, fontWeight: FontWeight.bold, diff --git a/lib/ui/pages/server_details/server_details_screen.dart b/lib/ui/pages/server_details/server_details_screen.dart index 24675dad..d1eada36 100644 --- a/lib/ui/pages/server_details/server_details_screen.dart +++ b/lib/ui/pages/server_details/server_details_screen.dart @@ -70,7 +70,7 @@ class _ServerDetailsScreenState extends State if (!isReady) { return BrandHeroScreen( heroIcon: BrandIcons.server, - heroTitle: 'providers.server.card_title'.tr(), + heroTitle: 'server.card_title'.tr(), heroSubtitle: 'not_ready_card.in_menu'.tr(), children: const [], ); @@ -80,8 +80,8 @@ class _ServerDetailsScreenState extends State create: (final context) => context.read()..check(), child: BrandHeroScreen( heroIcon: BrandIcons.server, - heroTitle: 'providers.server.card_title'.tr(), - heroSubtitle: 'providers.server.bottom_sheet.1'.tr(), + heroTitle: 'server.card_title'.tr(), + heroSubtitle: 'server.description'.tr(), children: [ StorageCard( diskStatus: context.watch().state.diskStatus, @@ -90,7 +90,7 @@ class _ServerDetailsScreenState extends State const _ServerSettings(), const Divider(height: 32), Text( - 'providers.server.resource_usage'.tr(), + 'server.resource_usage'.tr(), style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 8), diff --git a/lib/ui/pages/server_details/server_settings.dart b/lib/ui/pages/server_details/server_settings.dart index 38c7133b..f669dce0 100644 --- a/lib/ui/pages/server_details/server_settings.dart +++ b/lib/ui/pages/server_details/server_settings.dart @@ -34,7 +34,7 @@ class _ServerSettingsState extends State<_ServerSettings> { onChanged: (final switched) { if (didSomethingChange == false) { context.read().addJob( - RebuildServerJob(title: 'jobs.upgradeServer'.tr()), + RebuildServerJob(title: 'jobs.upgrade_server'.tr()), ); } context @@ -51,9 +51,9 @@ class _ServerSettingsState extends State<_ServerSettings> { didSomethingChange = true; }); }, - title: Text('providers.server.settings.allow_autoupgrade'.tr()), + title: Text('server.allow_autoupgrade'.tr()), subtitle: Text( - 'providers.server.settings.allow_autoupgrade_hint'.tr(), + 'server.allow_autoupgrade_hint'.tr(), ), activeColor: Theme.of(context).colorScheme.primary, ), @@ -62,7 +62,7 @@ class _ServerSettingsState extends State<_ServerSettings> { onChanged: (final switched) { if (didSomethingChange == false) { context.read().addJob( - RebuildServerJob(title: 'jobs.upgradeServer'.tr()), + RebuildServerJob(title: 'jobs.upgrade_server'.tr()), ); } context @@ -79,21 +79,21 @@ class _ServerSettingsState extends State<_ServerSettings> { didSomethingChange = true; }); }, - title: Text('providers.server.settings.reboot_after_upgrade'.tr()), + title: Text('server.reboot_after_upgrade'.tr()), subtitle: Text( - 'providers.server.settings.reboot_after_upgrade_hint'.tr(), + 'server.reboot_after_upgrade_hint'.tr(), ), activeColor: Theme.of(context).colorScheme.primary, ), ListTile( - title: Text('providers.server.settings.server_timezone'.tr()), + title: Text('server.server_timezone'.tr()), subtitle: Text( serverDetailsState.serverTimezone.toString(), ), onTap: () { if (didSomethingChange == false) { context.read().addJob( - RebuildServerJob(title: 'jobs.upgradeServer'.tr()), + RebuildServerJob(title: 'jobs.upgrade_server'.tr()), ); } setState(() { diff --git a/lib/ui/pages/server_details/text_details.dart b/lib/ui/pages/server_details/text_details.dart index f512e917..e9b3c0f7 100644 --- a/lib/ui/pages/server_details/text_details.dart +++ b/lib/ui/pages/server_details/text_details.dart @@ -18,7 +18,7 @@ class _TextDetails extends StatelessWidget { Padding( padding: const EdgeInsets.all(16.0), child: Text( - 'providers.server.bottom_sheet.2'.tr(), + 'server.general_information'.tr(), style: Theme.of(context).textTheme.titleMedium?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), @@ -27,34 +27,33 @@ class _TextDetails extends StatelessWidget { ListTileOnSurfaceVariant( leadingIcon: Icons.numbers_outlined, title: data.id.toString(), - subtitle: 'providers.server.info.server_id'.tr(), + subtitle: 'server.server_id'.tr(), ), ListTileOnSurfaceVariant( leadingIcon: Icons.mode_standby_outlined, title: data.status.toString().split('.')[1].capitalize(), - subtitle: 'providers.server.info.status'.tr(), + subtitle: 'server.status'.tr(), ), ListTileOnSurfaceVariant( leadingIcon: Icons.memory_outlined, - title: 'providers.server.info.core_count' - .plural(data.serverType.cores), - subtitle: 'providers.server.info.cpu'.tr(), + title: 'server.core_count'.plural(data.serverType.cores), + subtitle: 'server.cpu'.tr(), ), ListTileOnSurfaceVariant( leadingIcon: Icons.memory_outlined, title: '${data.serverType.memory.toString()} GB', - subtitle: 'providers.server.info.ram'.tr(), + subtitle: 'server.ram'.tr(), ), ListTileOnSurfaceVariant( leadingIcon: Icons.euro_outlined, title: data.serverType.prices[1].monthly.toStringAsFixed(2), - subtitle: 'providers.server.info.monthly_cost'.tr(), + subtitle: 'server.monthly_cost'.tr(), ), // Server location ListTileOnSurfaceVariant( leadingIcon: Icons.location_on_outlined, title: '${data.location.city}, ${data.location.country}', - subtitle: 'providers.server.info.location'.tr(), + subtitle: 'server.location'.tr(), ), ], ), diff --git a/lib/ui/pages/server_details/time_zone/time_zone.dart b/lib/ui/pages/server_details/time_zone/time_zone.dart index fa652a58..1711a59b 100644 --- a/lib/ui/pages/server_details/time_zone/time_zone.dart +++ b/lib/ui/pages/server_details/time_zone/time_zone.dart @@ -50,7 +50,7 @@ class _SelectTimezoneState extends State { appBar: PreferredSize( preferredSize: const Size.fromHeight(52), child: BrandHeader( - title: 'providers.server.settings.select_timezone'.tr(), + title: 'server.select_timezone'.tr(), hasBackButton: true, ), ), diff --git a/lib/ui/pages/server_storage/binds_migration/migration_process_page.dart b/lib/ui/pages/server_storage/binds_migration/migration_process_page.dart index a63748c6..cfe3fcb5 100644 --- a/lib/ui/pages/server_storage/binds_migration/migration_process_page.dart +++ b/lib/ui/pages/server_storage/binds_migration/migration_process_page.dart @@ -53,7 +53,7 @@ class _MigrationProcessPageState extends State { if (job.finishedAt != null) const SizedBox(height: 16), if (job.finishedAt != null) FilledButton( - title: 'providers.storage.migration_done'.tr(), + title: 'storage.migration_done'.tr(), onPressed: () { Navigator.of(context).pushAndRemoveUntil( materialRoute(const RootPage()), @@ -65,7 +65,7 @@ class _MigrationProcessPageState extends State { } return BrandHeroScreen( hasBackButton: false, - heroTitle: 'providers.storage.migration_process'.tr(), + heroTitle: 'storage.migration_process'.tr(), heroSubtitle: subtitle, children: [ BrandLinearIndicator( diff --git a/lib/ui/pages/server_storage/binds_migration/services_migration.dart b/lib/ui/pages/server_storage/binds_migration/services_migration.dart index 9783a479..750bbf80 100644 --- a/lib/ui/pages/server_storage/binds_migration/services_migration.dart +++ b/lib/ui/pages/server_storage/binds_migration/services_migration.dart @@ -100,7 +100,7 @@ class _ServicesMigrationPageState extends State { child: Column( children: [ BrandHeader( - title: 'providers.storage.data_migration_title'.tr(), + title: 'storage.data_migration_title'.tr(), hasBackButton: true, ), Padding( @@ -158,13 +158,13 @@ class _ServicesMigrationPageState extends State { Padding( padding: const EdgeInsets.all(8.0), child: InfoBox( - text: 'providers.storage.data_migration_notice'.tr(), + text: 'storage.data_migration_notice'.tr(), isWarning: true, ), ), const SizedBox(height: 16), FilledButton( - title: 'providers.storage.start_migration_button'.tr(), + title: 'storage.start_migration_button'.tr(), onPressed: () { if (widget.isMigration) { context.read().migrateToBinds( diff --git a/lib/ui/pages/server_storage/extending_volume.dart b/lib/ui/pages/server_storage/extending_volume.dart index 1c8980e2..e465c2b2 100644 --- a/lib/ui/pages/server_storage/extending_volume.dart +++ b/lib/ui/pages/server_storage/extending_volume.dart @@ -57,9 +57,8 @@ class _ExtendingVolumePageState extends State { if (!snapshot.hasData) { return BrandHeroScreen( hasBackButton: true, - heroTitle: 'providers.storage.extending_volume_title'.tr(), - heroSubtitle: - 'providers.storage.extending_volume_description'.tr(), + heroTitle: 'storage.extending_volume_title'.tr(), + heroSubtitle: 'storage.extending_volume_description'.tr(), children: const [ SizedBox(height: 16), Center( @@ -84,8 +83,8 @@ class _ExtendingVolumePageState extends State { return BrandHeroScreen( hasBackButton: true, - heroTitle: 'providers.storage.extending_volume_title'.tr(), - heroSubtitle: 'providers.storage.extending_volume_description'.tr(), + heroTitle: 'storage.extending_volume_title'.tr(), + heroSubtitle: 'storage.extending_volume_description'.tr(), children: [ const SizedBox(height: 16), Row( @@ -104,7 +103,7 @@ class _ExtendingVolumePageState extends State { decoration: InputDecoration( border: const OutlineInputBorder(), errorText: _isError ? ' ' : null, - labelText: 'providers.storage.size'.tr(), + labelText: 'storage.size'.tr(), ), ), ), @@ -120,7 +119,7 @@ class _ExtendingVolumePageState extends State { decoration: InputDecoration( border: const OutlineInputBorder(), errorText: _isError ? ' ' : null, - labelText: 'providers.storage.euro'.tr(), + labelText: 'storage.euro'.tr(), ), ), ), @@ -140,7 +139,7 @@ class _ExtendingVolumePageState extends State { ), const SizedBox(height: 16), FilledButton( - title: 'providers.storage.extend_volume_button.title'.tr(), + title: 'storage.extend_volume_button.title'.tr(), onPressed: _isError ? null : () { @@ -169,7 +168,7 @@ class _ExtendingVolumePageState extends State { ), ), const SizedBox(height: 16), - Text('providers.storage.extending_volume_price_info'.tr()), + Text('storage.extending_volume_price_info'.tr()), const SizedBox(height: 16), ], ); diff --git a/lib/ui/pages/server_storage/server_storage.dart b/lib/ui/pages/server_storage/server_storage.dart index 9a83789a..16b027ac 100644 --- a/lib/ui/pages/server_storage/server_storage.dart +++ b/lib/ui/pages/server_storage/server_storage.dart @@ -32,14 +32,14 @@ class _ServerStoragePageState extends State { if (!isReady) { return BrandHeroScreen( hasBackButton: true, - heroTitle: 'providers.storage.card_title'.tr(), + heroTitle: 'storage.card_title'.tr(), children: const [], ); } return BrandHeroScreen( hasBackButton: true, - heroTitle: 'providers.storage.card_title'.tr(), + heroTitle: 'storage.card_title'.tr(), children: [ // ...sections, ...widget.diskStatus.diskVolumes @@ -101,7 +101,7 @@ class ServerStorageSection extends StatelessWidget { if (volume.isResizable) ...[ const SizedBox(height: 16), BrandOutlinedButton( - title: 'providers.storage.extend_volume_button.title'.tr(), + title: 'storage.extend_volume_button.title'.tr(), onPressed: () => Navigator.of(context).push( materialRoute( ExtendingVolumePage( diff --git a/lib/ui/pages/server_storage/storage_card.dart b/lib/ui/pages/server_storage/storage_card.dart index 33b742a2..a18e4f86 100644 --- a/lib/ui/pages/server_storage/storage_card.dart +++ b/lib/ui/pages/server_storage/storage_card.dart @@ -65,14 +65,14 @@ class StorageCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'providers.storage.card_title'.tr(), + 'storage.card_title'.tr(), style: Theme.of(context).textTheme.titleLarge, ), if (state != StateType.uninitialized) Text( diskStatus.isDiskOkay - ? 'providers.storage.status_ok'.tr() - : 'providers.storage.status_error'.tr(), + ? 'storage.status_ok'.tr() + : 'storage.status_error'.tr(), style: Theme.of(context).textTheme.bodyLarge, ), ], diff --git a/lib/ui/pages/services/service_page.dart b/lib/ui/pages/services/service_page.dart index 417f1bf2..f592aceb 100644 --- a/lib/ui/pages/services/service_page.dart +++ b/lib/ui/pages/services/service_page.dart @@ -74,7 +74,7 @@ class _ServicePageState extends State { onTap: () => _launchURL(service.url), leading: const Icon(Icons.open_in_browser), title: Text( - 'services.service_page.open_in_browser'.tr(), + 'service_page.open_in_browser'.tr(), style: Theme.of(context).textTheme.titleMedium, ), subtitle: Text( @@ -92,7 +92,7 @@ class _ServicePageState extends State { }, leading: const Icon(Icons.restart_alt_outlined), title: Text( - 'services.service_page.restart'.tr(), + 'service_page.restart'.tr(), style: Theme.of(context).textTheme.titleMedium, ), enabled: !serviceDisabled && !serviceLocked, @@ -110,8 +110,8 @@ class _ServicePageState extends State { leading: const Icon(Icons.power_settings_new), title: Text( serviceDisabled - ? 'services.service_page.enable'.tr() - : 'services.service_page.disable'.tr(), + ? 'service_page.enable'.tr() + : 'service_page.disable'.tr(), style: Theme.of(context).textTheme.titleMedium, ), enabled: !serviceLocked, @@ -132,11 +132,11 @@ class _ServicePageState extends State { ), leading: const Icon(Icons.drive_file_move_outlined), title: Text( - 'services.service_page.move'.tr(), + 'service_page.move'.tr(), style: Theme.of(context).textTheme.titleMedium, ), subtitle: Text( - 'services.service_page.uses'.tr( + 'service_page.uses'.tr( namedArgs: { 'usage': service.storageUsage.used.toString(), 'volume': context diff --git a/lib/ui/pages/services/services.dart b/lib/ui/pages/services/services.dart index d638866a..4909af13 100644 --- a/lib/ui/pages/services/services.dart +++ b/lib/ui/pages/services/services.dart @@ -67,7 +67,7 @@ class _ServicesPageState extends State { child: ListView( padding: paddingH15V0, children: [ - BrandText.body1('services.title'.tr()), + BrandText.body1('basis.services_title'.tr()), const SizedBox(height: 24), if (!isReady) ...[const NotReadyCard(), const SizedBox(height: 24)], ...ServiceTypes.values @@ -218,7 +218,7 @@ class _Card extends StatelessWidget { sigmaY: 2, ), child: BrandText.h2( - 'jobs.runJobs'.tr(), + 'jobs.run_jobs'.tr(), textAlign: TextAlign.center, ), ), diff --git a/lib/ui/pages/setup/initializing.dart b/lib/ui/pages/setup/initializing.dart index 1764b576..ff4c0748 100644 --- a/lib/ui/pages/setup/initializing.dart +++ b/lib/ui/pages/setup/initializing.dart @@ -154,9 +154,9 @@ class InitializingPage extends StatelessWidget { width: 150, ), const SizedBox(height: 10), - BrandText.h2('initializing.1'.tr()), + BrandText.h2('initializing.connect_to_server'.tr()), const SizedBox(height: 10), - BrandText.body2('initializing.2'.tr()), + BrandText.body2('initializing.place_where_data'.tr()), const Spacer(), CubitFormTextField( formFieldCubit: context.read().apiKey, @@ -211,16 +211,16 @@ class InitializingPage extends StatelessWidget { width: 150, ), const SizedBox(height: 10), - BrandText.h2('initializing.3'.tr()), + BrandText.h2('initializing.connect_cloudflare'.tr()), const SizedBox(height: 10), - BrandText.body2('initializing.4'.tr()), + BrandText.body2('initializing.manage_domain_dns'.tr()), const Spacer(), CubitFormTextField( formFieldCubit: context.read().apiKey, textAlign: TextAlign.center, scrollPadding: const EdgeInsets.only(bottom: 70), decoration: InputDecoration( - hintText: 'initializing.5'.tr(), + hintText: 'initializing.cloudflare_api_token'.tr(), ), ), const Spacer(), @@ -260,7 +260,7 @@ class InitializingPage extends StatelessWidget { height: 50, ), const SizedBox(height: 10), - BrandText.h2('initializing.6'.tr()), + BrandText.h2('initializing.connect_backblaze_storage'.tr()), const SizedBox(height: 10), const Spacer(), CubitFormTextField( @@ -321,16 +321,17 @@ class InitializingPage extends StatelessWidget { const SizedBox(height: 30), BrandText.h2('basis.domain'.tr()), const SizedBox(height: 10), - if (state is Empty) BrandText.body2('initializing.7'.tr()), + if (state is Empty) + BrandText.body2('initializing.no_connected_domains'.tr()), if (state is Loading) BrandText.body2( state.type == LoadingTypes.loadingDomain - ? 'initializing.8'.tr() + ? 'initializing.loading_domain_list'.tr() : 'basis.saving'.tr(), ), if (state is MoreThenOne) BrandText.body2( - 'initializing.9'.tr(), + 'initializing.found_more_domains'.tr(), ), if (state is Loaded) ...[ const SizedBox(height: 10), @@ -387,7 +388,7 @@ class InitializingPage extends StatelessWidget { BrandButton.rised( onPressed: () => context.read().saveDomain(), - text: 'initializing.10'.tr(), + text: 'initializing.save_domain'.tr(), ), ], const SizedBox( @@ -411,9 +412,10 @@ class InitializingPage extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - BrandText.h2('initializing.22'.tr()), + BrandText.h2('initializing.create_master_account'.tr()), const SizedBox(height: 10), - BrandText.body2('initializing.23'.tr()), + BrandText.body2( + 'initializing.enter_nickname_and_password'.tr()), const Spacer(), CubitFormTextField( formFieldCubit: context.read().userName, @@ -477,12 +479,14 @@ class InitializingPage extends StatelessWidget { const Spacer(flex: 2), BrandText.h2('initializing.final'.tr()), const SizedBox(height: 10), - BrandText.body2('initializing.11'.tr()), + BrandText.body2('initializing.create_server'.tr()), const Spacer(), BrandButton.rised( onPressed: isLoading ? null : appConfigCubit.createServerAndSetDnsRecords, - text: isLoading ? 'basis.loading'.tr() : 'initializing.11'.tr(), + text: isLoading + ? 'basis.loading'.tr() + : 'initializing.create_server'.tr(), ), ], ), @@ -498,16 +502,16 @@ class InitializingPage extends StatelessWidget { late int doneCount; late String? text; if (state.isServerResetedSecondTime) { - text = 'initializing.13'.tr(); + text = 'initializing.server_rebooted'.tr(); doneCount = 3; } else if (state.isServerResetedFirstTime) { - text = 'initializing.21'.tr(); + text = 'initializing.one_more_restart'.tr(); doneCount = 2; } else if (state.isServerStarted) { - text = 'initializing.14'.tr(); + text = 'initializing.server_started'.tr(); doneCount = 1; } else if (state.isServerCreated) { - text = 'initializing.15'.tr(); + text = 'initializing.server_created'.tr(); doneCount = 0; } return Builder( @@ -542,14 +546,14 @@ class InitializingPage extends StatelessWidget { if (!state.isLoading) Row( children: [ - BrandText.body2('initializing.16'.tr()), + BrandText.body2('initializing.until_the_next_check'.tr()), BrandTimer( startDateTime: state.timerStart!, duration: state.duration!, ) ], ), - if (state.isLoading) BrandText.body2('initializing.17'.tr()), + if (state.isLoading) BrandText.body2('initializing.check'.tr()), ], ), ); diff --git a/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart b/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart index a9f37b19..e32cac5d 100644 --- a/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart +++ b/lib/ui/pages/setup/recovering/recover_by_new_device_key.dart @@ -73,7 +73,7 @@ class RecoverByNewDeviceKeyInput extends StatelessWidget { ), const SizedBox(height: 16), FilledButton( - title: 'more.continue'.tr(), + title: 'basis.continue'.tr(), onPressed: formCubitState.isSubmitting ? null : () => diff --git a/lib/ui/pages/setup/recovering/recover_by_old_token.dart b/lib/ui/pages/setup/recovering/recover_by_old_token.dart index e3507a0e..10a6c279 100644 --- a/lib/ui/pages/setup/recovering/recover_by_old_token.dart +++ b/lib/ui/pages/setup/recovering/recover_by_old_token.dart @@ -83,7 +83,7 @@ class RecoverByOldToken extends StatelessWidget { ), const SizedBox(height: 16), FilledButton( - title: 'more.continue'.tr(), + title: 'basis.continue'.tr(), onPressed: formCubitState.isSubmitting ? null : () => context.read().trySubmit(), diff --git a/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart b/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart index f729524e..e17a9436 100644 --- a/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart +++ b/lib/ui/pages/setup/recovering/recover_by_recovery_key.dart @@ -44,7 +44,7 @@ class RecoverByRecoveryKey extends StatelessWidget { ), const SizedBox(height: 16), FilledButton( - title: 'more.continue'.tr(), + title: 'basis.continue'.tr(), onPressed: formCubitState.isSubmitting ? null : () => context.read().trySubmit(), diff --git a/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart b/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart index b7891bc1..46db75b7 100644 --- a/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart +++ b/lib/ui/pages/setup/recovering/recovery_confirm_cloudflare.dart @@ -38,7 +38,7 @@ class RecoveryConfirmCloudflare extends StatelessWidget { formFieldCubit: context.read().apiKey, decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: 'initializing.5'.tr(), + labelText: 'initializing.cloudflare_api_token'.tr(), ), ), const SizedBox(height: 16), diff --git a/lib/ui/pages/setup/recovering/recovery_hentzner_connected.dart b/lib/ui/pages/setup/recovering/recovery_hentzner_connected.dart index 5ee461a7..84be9808 100644 --- a/lib/ui/pages/setup/recovering/recovery_hentzner_connected.dart +++ b/lib/ui/pages/setup/recovering/recovery_hentzner_connected.dart @@ -45,7 +45,7 @@ class RecoveryHetznerConnected extends StatelessWidget { ), const SizedBox(height: 16), FilledButton( - title: 'more.continue'.tr(), + title: 'basis.continue'.tr(), onPressed: formCubitState.isSubmitting ? null : () => context.read().trySubmit(), diff --git a/lib/ui/pages/setup/recovering/recovery_routing.dart b/lib/ui/pages/setup/recovering/recovery_routing.dart index 3c375ef0..028b8618 100644 --- a/lib/ui/pages/setup/recovering/recovery_routing.dart +++ b/lib/ui/pages/setup/recovering/recovery_routing.dart @@ -127,7 +127,7 @@ class SelectDomainToRecover extends StatelessWidget { ), const SizedBox(height: 16), FilledButton( - title: 'more.continue'.tr(), + title: 'basis.continue'.tr(), onPressed: formCubitState.isSubmitting ? null : () => diff --git a/lib/ui/pages/users/user_details.dart b/lib/ui/pages/users/user_details.dart index 86a9e3d7..e3cfc21f 100644 --- a/lib/ui/pages/users/user_details.dart +++ b/lib/ui/pages/users/user_details.dart @@ -25,8 +25,8 @@ class UserDetails extends StatelessWidget { if (user.type == UserType.root) { return BrandHeroScreen( hasBackButton: true, - heroTitle: 'ssh.root.title'.tr(), - heroSubtitle: 'ssh.root.subtitle'.tr(), + heroTitle: 'ssh.root_title'.tr(), + heroSubtitle: 'ssh.root_subtitle'.tr(), children: [ _SshKeysCard(user: user), ], @@ -64,7 +64,7 @@ class UserDetails extends StatelessWidget { Padding( padding: const EdgeInsets.all(16.0), child: InfoBox( - text: 'users.no_sso_notice'.tr(), + text: 'users.no_ssh_notice'.tr(), isWarning: true, ), ), From c1cba41b7bae94acb3bb3a8c52aa9de8410b1f1d Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 4 Oct 2022 11:05:26 +0300 Subject: [PATCH 2/3] fix(i18l): Un-hardcode service status descriptions --- assets/translations/en.json | 11 ++++++- lib/ui/pages/services/service_page.dart | 42 ++++++++++++------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/assets/translations/en.json b/assets/translations/en.json index bee29120..1af2fa0a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -192,7 +192,16 @@ "disable": "Disable service", "enable": "Enable service", "move": "Move to another volume", - "uses": "Uses {usage} on {volume}" + "uses": "Uses {usage} on {volume}", + "status": { + "active": "Up and running", + "inactive": "Stopped", + "failed": "Failed to start", + "off": "Disabled", + "activating": "Activating", + "deactivating": "Deactivating", + "reloading": "Restarting" + } }, "mail": { "title": "E-Mail", diff --git a/lib/ui/pages/services/service_page.dart b/lib/ui/pages/services/service_page.dart index f592aceb..ad398072 100644 --- a/lib/ui/pages/services/service_page.dart +++ b/lib/ui/pages/services/service_page.dart @@ -188,79 +188,79 @@ class ServiceStatusCard extends StatelessWidget { Widget build(final BuildContext context) { switch (status) { case ServiceStatus.active: - return const FilledCard( + return FilledCard( child: ListTile( - leading: Icon( + leading: const Icon( Icons.check_circle_outline, size: 24, ), - title: Text('Up and running'), + title: Text('service_page.status.active'.tr()), ), ); case ServiceStatus.inactive: - return const FilledCard( + return FilledCard( tertiary: true, child: ListTile( - leading: Icon( + leading: const Icon( Icons.stop_circle_outlined, size: 24, ), - title: Text('Stopped'), + title: Text('service_page.status.inactive'.tr()), ), ); case ServiceStatus.failed: - return const FilledCard( + return FilledCard( error: true, child: ListTile( - leading: Icon( + leading: const Icon( Icons.error_outline, size: 24, ), - title: Text('Failed to start'), + title: Text('service_page.status.failed'.tr()), ), ); case ServiceStatus.off: - return const FilledCard( + return FilledCard( tertiary: true, child: ListTile( - leading: Icon( + leading: const Icon( Icons.power_settings_new, size: 24, ), - title: Text('Disabled'), + title: Text('service_page.status.off'.tr()), ), ); case ServiceStatus.activating: - return const FilledCard( + return FilledCard( tertiary: true, child: ListTile( - leading: Icon( + leading: const Icon( Icons.restart_alt_outlined, size: 24, ), - title: Text('Activating'), + title: Text('service_page.status.activating'.tr()), ), ); case ServiceStatus.deactivating: - return const FilledCard( + return FilledCard( tertiary: true, child: ListTile( - leading: Icon( + leading: const Icon( Icons.restart_alt_outlined, size: 24, ), - title: Text('Deactivating'), + title: Text('service_page.status.deactivating'.tr()), ), ); case ServiceStatus.reloading: - return const FilledCard( + return FilledCard( tertiary: true, child: ListTile( - leading: Icon( + leading: const Icon( Icons.restart_alt_outlined, size: 24, ), - title: Text('Restarting'), + title: Text('service_page.status.reloading'.tr()), ), ); } From 9644ade367c632133a2713cecfe965de915969d7 Mon Sep 17 00:00:00 2001 From: Inex Code Date: Tue, 4 Oct 2022 11:26:18 +0300 Subject: [PATCH 3/3] fix(i18l): Use fallback English translations when localized one not available --- lib/config/localization.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/config/localization.dart b/lib/config/localization.dart index b8356950..5e5ffc38 100644 --- a/lib/config/localization.dart +++ b/lib/config/localization.dart @@ -13,6 +13,7 @@ class Localization extends StatelessWidget { supportedLocales: const [Locale('ru'), Locale('en')], path: 'assets/translations', fallbackLocale: const Locale('en'), + useFallbackTranslations: true, saveLocale: false, useOnlyLangCode: true, child: child!,