translate to english

This commit is contained in:
cheykrym 2025-10-07 02:42:44 +03:00
parent a588a33338
commit 19251ed52f
4 changed files with 736 additions and 83 deletions

View File

@ -151,7 +151,7 @@ final class AuthService {
return
}
completion(true, apiResponse.data.message)
completion(true, NSLocalizedString(apiResponse.data.message, comment: ""))
} catch {
completion(false, NSLocalizedString("Не удалось обработать ответ сервера.", comment: ""))
}
@ -280,20 +280,28 @@ final class AuthService {
case .network(let err):
return String(format: NSLocalizedString("Ошибка сети: %@", comment: ""), err.localizedDescription)
case .server(let statusCode, let data):
if let message = extractMessage(from: data) {
return message
}
let message = extractMessage(from: data)
switch statusCode {
case 401:
return NSLocalizedString("Необходимо авторизоваться заново.", comment: "")
case 403:
if let message,
Self.changePasswordForbiddenMessages.contains(message) {
return NSLocalizedString(message, comment: "")
}
return NSLocalizedString("Старый пароль указан неверно или совпадает с новым.", comment: "")
case 422:
if let message {
return message
}
return NSLocalizedString("Проверьте данные и повторите попытку.", comment: "")
case 429:
return NSLocalizedString("Слишком много попыток. Попробуйте позже.", comment: "")
default:
if let message {
return message
}
return String(format: NSLocalizedString("Ошибка сервера: %@", comment: ""), "\(statusCode)")
}
case .unauthorized:
@ -305,7 +313,8 @@ final class AuthService {
private func extractMessage(from data: Data?) -> String? {
guard let data else { return nil }
if let response = try? JSONDecoder().decode(ErrorResponse.self, from: data) {
let decoder = JSONDecoder()
if let response = try? decoder.decode(ErrorResponse.self, from: data) {
if let message = response.data?.message, !message.isEmpty {
return message
}
@ -313,7 +322,58 @@ final class AuthService {
return detail
}
}
if let jsonObject = try? JSONSerialization.jsonObject(with: data) {
if let dictionary = jsonObject as? [String: Any] {
if let detail = Self.normalizedMessage(dictionary["detail"] as? String) {
return detail
}
if let dataDict = dictionary["data"] as? [String: Any],
let message = Self.normalizedMessage(dataDict["message"] as? String) {
return message
}
if let errors = dictionary["errors"] as? [[String: Any]],
let firstMessage = errors.compactMap({ Self.normalizedMessage($0["message"] as? String) }).first {
return firstMessage
}
} else if let array = jsonObject as? [[String: Any]] {
if let firstMessage = array.compactMap({ item -> String? in
if let detail = Self.normalizedMessage(item["detail"] as? String) {
return detail
}
if let message = Self.normalizedMessage(item["message"] as? String) {
return message
}
if let msg = Self.normalizedMessage(item["msg"] as? String) {
return msg
}
return nil
}).first {
return firstMessage
}
}
}
if let string = Self.normalizedMessage(String(data: data, encoding: .utf8)) {
return string
}
return nil
}
}
private extension AuthService {
static let changePasswordForbiddenMessages: Set<String> = [
"Неверный текущий пароль",
"Пароль должен отличаться от старого",
"Пароль не удовлетворяет требованиям"
]
static func normalizedMessage(_ raw: String?) -> String? {
guard let raw = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !raw.isEmpty else {
return nil
}
return raw
}
}

View File

@ -80,6 +80,24 @@
}
}
},
"Password updated" : {
"comment" : "ответ сервера (change password)",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Password updated"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Пароль обновлен"
}
}
}
},
"profile_down_text_1" : {
},
@ -90,7 +108,14 @@
},
"Push-уведомления" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Push-notifications"
}
}
}
},
"Yobble" : {
"localizations" : {
@ -99,11 +124,24 @@
"state" : "translated",
"value" : "Yobble"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Йоббле"
}
}
}
},
"Активные сессии" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Active sessions"
}
}
}
},
"Без звука (скоро)" : {
@ -128,13 +166,27 @@
}
},
"Вы" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "You"
}
}
}
},
"Вы предложили: %@" : {
},
"Выйти из аккаунта" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Log out of your account"
}
}
}
},
"Где найти сохранённые черновики?" : {
"comment" : "FAQ question: drafts"
@ -143,7 +195,14 @@
},
"Двухфакторная аутентификация" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Two-factor authentication"
}
}
}
},
"Добавить друзей" : {
"comment" : "Add friends",
@ -157,7 +216,14 @@
}
},
"Другое" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Other"
}
}
}
},
"Заглушка: Push-уведомления" : {
@ -178,7 +244,14 @@
},
"Загружаем чаты…" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Loading chats…"
}
}
}
},
"Загрузка..." : {
"localizations" : {
@ -227,16 +300,37 @@
}
},
"Здесь не будут чаты" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "There will be no chats here."
}
}
}
},
"Идеи" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Ideas"
}
}
}
},
"Избранные сообщения" : {
},
"Изменение пароля" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Change password"
}
}
}
},
"Инвайт-код (необязательно)" : {
"comment" : "Инвайт-код",
@ -320,7 +414,14 @@
}
},
"Логин уже занят." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The login is already taken."
}
}
}
},
"Мини-приложения" : {
"comment" : "Applets",
@ -376,46 +477,157 @@
}
},
"Не удалось загрузить список чатов." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to load chat list."
}
}
}
},
"Не удалось загрузить чаты." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to load chats."
}
}
}
},
"Не удалось обновить пароль." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to update password."
}
}
}
},
"Не удалось обработать данные чатов." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to process chat data."
}
}
}
},
"Не удалось обработать ответ сервера." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to process server response."
}
}
}
},
"Не удалось сериализовать данные запроса." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Failed to serialize request data."
}
}
}
},
"Неверный запрос (400)." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Invalid request (400)."
}
}
}
},
"Неверный код приглашения." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Invalid invitation code."
}
}
}
},
"Неверный логин" : {
"comment" : "Неверный логин"
"comment" : "Неверный логин",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Invalid login"
}
}
}
},
"Неверный логин или пароль." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Incorrect login or password."
}
}
}
},
"Неверный пароль" : {
"comment" : "Неверный пароль"
"comment" : "Неверный пароль",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Incorrect password"
}
}
}
},
"Неверный текущий пароль" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The current password is incorrect"
}
}
}
},
"Неизвестная ошибка" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unknown error"
}
}
}
},
"Неизвестная ошибка." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unknown error."
}
}
}
},
"Неизвестная ошибка. Попробуйте позже." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unknown error. Please try again later."
}
}
}
},
"Неизвестный" : {
@ -430,19 +642,56 @@
},
"Нет аккаунта? Регистрация" : {
"comment" : "Регистрация"
"comment" : "Регистрация",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Don't have an account? Register"
}
}
}
},
"Нет сообщений" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "No messages"
}
}
}
},
"Новый пароль" : {
"comment" : "Новый пароль"
"comment" : "Новый пароль",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "New Password"
}
}
}
},
"О приложении" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "About the app"
}
}
}
},
"Обновить" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Refresh"
}
}
}
},
"Обратная связь" : {
@ -457,61 +706,197 @@
},
"Ошибка" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Error"
}
}
}
},
"Ошибка авторизации" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Authorization error"
}
}
}
},
"Ошибка при деавторизации." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Error while deauthorizing."
}
}
}
},
"Ошибка регистрация" : {
"comment" : "Ошибка"
"comment" : "Ошибка",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Registration error"
}
}
}
},
"Ошибка сервера (%@)." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Server error (%@)."
}
}
}
},
"Ошибка сервера: %@" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Server error: %@"
}
}
}
},
"Ошибка сети: %@" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Network error: %@"
}
}
}
},
"Ошибка соединения с сервером." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Server connection error."
}
}
}
},
"Пароли не совпадают" : {
"comment" : "Пароли не совпадают"
"comment" : "Пароли не совпадают",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The passwords do not match"
}
}
}
},
"Пароли не совпадают." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The passwords do not match."
}
}
}
},
"Пароль" : {
"comment" : "Пароль"
"comment" : "Пароль",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Password"
}
}
}
},
"Пароль должен быть от 8 до 128 символов" : {
"comment" : "Пароль должен быть от 6 до 32 символов"
"comment" : "Пароль должен быть от 6 до 32 символов",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The password must be between 8 and 128 characters"
}
}
}
},
"Пароль обновлен" : {
"Пароль должен отличаться от старого" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The password must be different from the old one"
}
}
}
},
"Пароль не удовлетворяет требованиям" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The password does not meet the requirements"
}
}
}
},
"Пароль успешно обновлен." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Password updated successfully."
}
}
}
},
"Перейдите в раздел \"Настройки > Сменить пароль\" и следуйте инструкциям." : {
"comment" : "FAQ answer: reset password"
},
"Повторить" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Repeat"
}
}
}
},
"Поддержка" : {
},
"Подтверждение пароля" : {
"comment" : "Подтверждение пароля"
"comment" : "Подтверждение пароля",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Confirm password"
}
}
}
},
"Пока что у вас нет чатов" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "You don't have any chats yet."
}
}
}
},
"Помощь" : {
"comment" : "Help Center",
@ -525,52 +910,151 @@
}
},
"Приглашение достигло лимита использования." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The invitation has reached its usage limit."
}
}
}
},
"Приглашение истекло." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The invitation has expired."
}
}
}
},
"Приглашение не активно." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The invitation is not active."
}
}
}
},
"Приложение" : {
},
"Применить" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Apply"
}
}
}
},
"Проверьте данные и повторите попытку." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Please check your data and try again."
}
}
}
},
"Произошла ошибка." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "An error occurred."
}
}
}
},
"Публичная информация" : {
},
"Регистрация" : {
"comment" : "Регистрация"
"comment" : "Регистрация",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Registration"
}
}
}
},
"Регистрация временно недоступна." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Registration is temporarily unavailable."
}
}
}
},
"Регистрация выполнена, но вход не удался." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Registration completed, but login failed."
}
}
}
},
"Регистрация запрещена." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Registration is prohibited."
}
}
}
},
"Регистрация и вход выполнены успешно." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Registration and login completed successfully."
}
}
}
},
"Редактировать профиль" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Edit profile"
}
}
}
},
"Сервер не отвечает. Попробуйте позже." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The server is not responding. Try again later."
}
}
}
},
"Сессия истекла. Войдите снова." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Session expired. Please log in again."
}
}
}
},
"Скан" : {
"comment" : "Scan",
@ -584,13 +1068,40 @@
}
},
"Слишком много запросов." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Too many requests."
}
}
}
},
"Слишком много попыток. Попробуйте позже." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "You want too much. Take a rest."
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Слишком много хочешь. Отдохни."
}
}
}
},
"Сменить пароль" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Change password"
}
}
}
},
"Сообщение" : {
@ -599,22 +1110,75 @@
},
"Старый пароль" : {
"comment" : "Старый пароль"
"comment" : "Старый пароль",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Old Password"
}
}
}
},
"Старый пароль указан неверно или совпадает с новым." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "The old password is incorrect or the same as the new one."
}
}
}
},
"Темы" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Themes"
}
}
}
},
"Ты шо ебанутый? А ниче тот факт что новый пароль должен отличаться от старого." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Are you fucking nuts? It's okay that the new password has to be different from the old one."
}
}
}
},
"Уведомления" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Notifications"
}
}
}
},
"Удалить чат (скоро)" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Delete chat (cuming soon)"
}
}
}
},
"Ура!" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Fine!"
}
}
}
},
"Центр авторов" : {
"comment" : "Creator Center",
@ -628,13 +1192,35 @@
}
},
"Частые вопросы" : {
"comment" : "FAQ navigation title"
"comment" : "FAQ navigation title",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "FAQ"
}
}
}
},
"Чат" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Chat"
}
}
}
},
"Чаты" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Chats"
}
}
}
},
"Черновики" : {
"comment" : "Drafts",
@ -654,7 +1240,14 @@
},
"Язык" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Language"
}
}
}
}
},
"version" : "1.0"

View File

@ -176,7 +176,7 @@ struct ChangePasswordView: View {
.alert(item: $alertData) { data in
Alert(
title: Text(data.kind == .success
? NSLocalizedString("Пароль обновлен", comment: "")
? NSLocalizedString("Ура!", comment: "")
: NSLocalizedString("Ошибка", comment: "")),
message: Text(data.message),
dismissButton: .default(Text(NSLocalizedString("OK", comment: ""))) {

View File

@ -21,9 +21,9 @@ struct SettingsView: View {
// }
// MARK: - Безопасность
Section(header: Text("Безопасность")) {
Section(header: Text(NSLocalizedString("Безопасность", comment: ""))) {
NavigationLink(destination: ChangePasswordView()) {
Label("Сменить пароль", systemImage: "key")
Label(NSLocalizedString("Сменить пароль", comment: ""), systemImage: "key")
}
NavigationLink(destination: Text("Заглушка: Двухфакторная аутентификация")) {
Label("Двухфакторная аутентификация", systemImage: "lock.shield")