Skip to content

Commit f0a5612

Browse files
committed
"feat-german-translations"
1 parent a467c08 commit f0a5612

16 files changed

Lines changed: 26569 additions & 10877 deletions

‎lib/business_logic/blocs/settings_bloc/settings_bloc.dart‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
311311
final localeCode = switch (appLanguage) {
312312
'English (US)' => 'en',
313313
'Türkçe (TR)' => 'tr',
314+
'Español (ES)' => 'es',
315+
'Français (FR)' => 'fr',
316+
'Deutsch (DE)' => 'de',
314317
_ => 'en', // Default to English for unsupported languages
315318
};
316319

Lines changed: 182 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
import 'dart:io';
22

3+
import 'package:flutter/material.dart';
4+
import 'package:localizer_app_main/i18n/strings.g.dart';
5+
6+
/// Error types for categorization and localization.
7+
enum FriendlyErrorType {
8+
fileNotFound,
9+
accessDenied,
10+
isDirectory,
11+
fileAccess,
12+
unsupportedFormat,
13+
networkError,
14+
notGitRepo,
15+
mergeConflict,
16+
gitAuthFailed,
17+
gitOperationFailed,
18+
invalidJson,
19+
rateLimitReached,
20+
invalidApiKey,
21+
translationServiceError,
22+
outOfMemory,
23+
genericError,
24+
}
25+
326
/// A helper class to map technical exceptions to user-friendly messages.
427
class FriendlyErrorService {
528
FriendlyErrorService._();
@@ -13,28 +36,23 @@ class FriendlyErrorService {
1336
errorString.contains('filesystemexception')) {
1437
if (errorString.contains('no such file') ||
1538
errorString.contains('cannot find')) {
16-
return FriendlyError(
17-
message: 'The file or folder could not be found.',
18-
suggestion: 'Check if the file was moved or deleted.',
39+
return const FriendlyError(
40+
type: FriendlyErrorType.fileNotFound,
1941
);
2042
}
2143
if (errorString.contains('access denied') ||
2244
errorString.contains('permission denied')) {
23-
return FriendlyError(
24-
message: 'Access to the file was denied.',
25-
suggestion:
26-
'Try running the app as administrator or check file permissions.',
45+
return const FriendlyError(
46+
type: FriendlyErrorType.accessDenied,
2747
);
2848
}
2949
if (errorString.contains('is a directory')) {
30-
return FriendlyError(
31-
message: 'A folder was selected instead of a file.',
32-
suggestion: 'Please select a valid file.',
50+
return const FriendlyError(
51+
type: FriendlyErrorType.isDirectory,
3352
);
3453
}
35-
return FriendlyError(
36-
message: 'There was a problem accessing the file.',
37-
suggestion: 'Try closing other programs that might be using it.',
54+
return const FriendlyError(
55+
type: FriendlyErrorType.fileAccess,
3856
);
3957
}
4058

@@ -43,107 +61,216 @@ class FriendlyErrorService {
4361
errorString.contains('unsupportederror') ||
4462
errorString.contains('not supported') ||
4563
errorString.contains('unsupported file type')) {
46-
return FriendlyError(
47-
message: 'This file format or operation is not supported.',
48-
suggestion: 'Check the file extension or try a different format.',
64+
return const FriendlyError(
65+
type: FriendlyErrorType.unsupportedFormat,
4966
);
5067
}
5168

5269
// Network errors
5370
if (errorString.contains('socket') ||
5471
errorString.contains('network') ||
5572
errorString.contains('connection')) {
56-
return FriendlyError(
57-
message: 'Could not connect to the server.',
58-
suggestion: 'Check your internet connection and try again.',
73+
return const FriendlyError(
74+
type: FriendlyErrorType.networkError,
5975
);
6076
}
6177

6278
// Git errors
6379
if (errorString.contains('git')) {
6480
if (errorString.contains('not a git repository')) {
65-
return FriendlyError(
66-
message: 'This folder is not a Git project.',
67-
suggestion: 'Navigate to a folder that contains a .git directory.',
81+
return const FriendlyError(
82+
type: FriendlyErrorType.notGitRepo,
6883
);
6984
}
7085
if (errorString.contains('merge conflict') ||
7186
errorString.contains('conflict')) {
72-
return FriendlyError(
73-
message: 'There are merge conflicts in the repository.',
74-
suggestion: 'Resolve the conflicts before continuing.',
87+
return const FriendlyError(
88+
type: FriendlyErrorType.mergeConflict,
7589
);
7690
}
7791
if (errorString.contains('authentication') ||
7892
errorString.contains('credentials')) {
79-
return FriendlyError(
80-
message: 'Git authentication failed.',
81-
suggestion: 'Check your credentials in Settings > Version Control.',
93+
return const FriendlyError(
94+
type: FriendlyErrorType.gitAuthFailed,
8295
);
8396
}
84-
return FriendlyError(
85-
message: 'A Git operation failed.',
86-
suggestion: 'Check the Git view for more details.',
97+
return const FriendlyError(
98+
type: FriendlyErrorType.gitOperationFailed,
8799
);
88100
}
89101

90102
// JSON parsing errors
91103
if (errorString.contains('json') ||
92104
errorString.contains('formatexception')) {
93-
return FriendlyError(
94-
message: 'The file format is invalid or corrupted.',
95-
suggestion: 'Ensure the file contains valid JSON content.',
105+
return const FriendlyError(
106+
type: FriendlyErrorType.invalidJson,
96107
);
97108
}
98109

99110
// Translation/API errors
100111
if (errorString.contains('api') || errorString.contains('translation')) {
101112
if (errorString.contains('rate limit') || errorString.contains('quota')) {
102-
return FriendlyError(
103-
message: 'Translation limit reached.',
104-
suggestion: 'Wait a few minutes or check your API plan limits.',
113+
return const FriendlyError(
114+
type: FriendlyErrorType.rateLimitReached,
105115
);
106116
}
107117
if (errorString.contains('invalid key') ||
108118
errorString.contains('unauthorized')) {
109-
return FriendlyError(
110-
message: 'Invalid API key.',
111-
suggestion: 'Go to Settings > AI Translation to update your API key.',
119+
return const FriendlyError(
120+
type: FriendlyErrorType.invalidApiKey,
112121
);
113122
}
114-
return FriendlyError(
115-
message: 'Translation service error.',
116-
suggestion: 'Check your API key and internet connection.',
123+
return const FriendlyError(
124+
type: FriendlyErrorType.translationServiceError,
117125
);
118126
}
119127

120128
// Out of memory
121129
if (errorString.contains('out of memory') ||
122130
errorString.contains('memory')) {
123-
return FriendlyError(
124-
message: 'Not enough memory to complete this operation.',
125-
suggestion: 'Try closing other applications or using smaller files.',
131+
return const FriendlyError(
132+
type: FriendlyErrorType.outOfMemory,
126133
);
127134
}
128135

129136
// Generic fallback
130-
return FriendlyError(
131-
message: 'Something went wrong.',
132-
suggestion: 'Please try again. If the problem persists, restart the app.',
137+
return const FriendlyError(
138+
type: FriendlyErrorType.genericError,
133139
);
134140
}
135141
}
136142

137-
/// Data class holding a friendly error message and optional recovery suggestion.
143+
/// Data class holding a friendly error type for localization.
138144
class FriendlyError {
139-
final String message;
140-
final String? suggestion;
145+
final FriendlyErrorType type;
141146

142147
const FriendlyError({
143-
required this.message,
144-
this.suggestion,
148+
required this.type,
145149
});
146150

151+
/// Get localized message using BuildContext.
152+
String getLocalizedMessage(BuildContext context) {
153+
final t = context.t.friendlyErrors;
154+
switch (type) {
155+
case FriendlyErrorType.fileNotFound:
156+
return t.fileNotFound.message;
157+
case FriendlyErrorType.accessDenied:
158+
return t.accessDenied.message;
159+
case FriendlyErrorType.isDirectory:
160+
return t.isDirectory.message;
161+
case FriendlyErrorType.fileAccess:
162+
return t.fileAccess.message;
163+
case FriendlyErrorType.unsupportedFormat:
164+
return t.unsupportedFormat.message;
165+
case FriendlyErrorType.networkError:
166+
return t.networkError.message;
167+
case FriendlyErrorType.notGitRepo:
168+
return t.notGitRepo.message;
169+
case FriendlyErrorType.mergeConflict:
170+
return t.mergeConflict.message;
171+
case FriendlyErrorType.gitAuthFailed:
172+
return t.gitAuthFailed.message;
173+
case FriendlyErrorType.gitOperationFailed:
174+
return t.gitOperationFailed.message;
175+
case FriendlyErrorType.invalidJson:
176+
return t.invalidJson.message;
177+
case FriendlyErrorType.rateLimitReached:
178+
return t.rateLimitReached.message;
179+
case FriendlyErrorType.invalidApiKey:
180+
return t.invalidApiKey.message;
181+
case FriendlyErrorType.translationServiceError:
182+
return t.translationServiceError.message;
183+
case FriendlyErrorType.outOfMemory:
184+
return t.outOfMemory.message;
185+
case FriendlyErrorType.genericError:
186+
return t.genericError.message;
187+
}
188+
}
189+
190+
/// Get localized suggestion using BuildContext.
191+
String? getLocalizedSuggestion(BuildContext context) {
192+
final t = context.t.friendlyErrors;
193+
switch (type) {
194+
case FriendlyErrorType.fileNotFound:
195+
return t.fileNotFound.suggestion;
196+
case FriendlyErrorType.accessDenied:
197+
return t.accessDenied.suggestion;
198+
case FriendlyErrorType.isDirectory:
199+
return t.isDirectory.suggestion;
200+
case FriendlyErrorType.fileAccess:
201+
return t.fileAccess.suggestion;
202+
case FriendlyErrorType.unsupportedFormat:
203+
return t.unsupportedFormat.suggestion;
204+
case FriendlyErrorType.networkError:
205+
return t.networkError.suggestion;
206+
case FriendlyErrorType.notGitRepo:
207+
return t.notGitRepo.suggestion;
208+
case FriendlyErrorType.mergeConflict:
209+
return t.mergeConflict.suggestion;
210+
case FriendlyErrorType.gitAuthFailed:
211+
return t.gitAuthFailed.suggestion;
212+
case FriendlyErrorType.gitOperationFailed:
213+
return t.gitOperationFailed.suggestion;
214+
case FriendlyErrorType.invalidJson:
215+
return t.invalidJson.suggestion;
216+
case FriendlyErrorType.rateLimitReached:
217+
return t.rateLimitReached.suggestion;
218+
case FriendlyErrorType.invalidApiKey:
219+
return t.invalidApiKey.suggestion;
220+
case FriendlyErrorType.translationServiceError:
221+
return t.translationServiceError.suggestion;
222+
case FriendlyErrorType.outOfMemory:
223+
return t.outOfMemory.suggestion;
224+
case FriendlyErrorType.genericError:
225+
return t.genericError.suggestion;
226+
}
227+
}
228+
229+
/// Get full localized error (message + suggestion) using BuildContext.
230+
String toLocalizedString(BuildContext context) {
231+
final message = getLocalizedMessage(context);
232+
final suggestion = getLocalizedSuggestion(context);
233+
return suggestion != null ? '$message $suggestion' : message;
234+
}
235+
236+
/// Fallback English message for logging/debugging (no context needed).
237+
String get fallbackMessage {
238+
switch (type) {
239+
case FriendlyErrorType.fileNotFound:
240+
return 'The file or folder could not be found.';
241+
case FriendlyErrorType.accessDenied:
242+
return 'Access to the file was denied.';
243+
case FriendlyErrorType.isDirectory:
244+
return 'A folder was selected instead of a file.';
245+
case FriendlyErrorType.fileAccess:
246+
return 'There was a problem accessing the file.';
247+
case FriendlyErrorType.unsupportedFormat:
248+
return 'This file format or operation is not supported.';
249+
case FriendlyErrorType.networkError:
250+
return 'Could not connect to the server.';
251+
case FriendlyErrorType.notGitRepo:
252+
return 'This folder is not a Git project.';
253+
case FriendlyErrorType.mergeConflict:
254+
return 'There are merge conflicts in the repository.';
255+
case FriendlyErrorType.gitAuthFailed:
256+
return 'Git authentication failed.';
257+
case FriendlyErrorType.gitOperationFailed:
258+
return 'A Git operation failed.';
259+
case FriendlyErrorType.invalidJson:
260+
return 'The file format is invalid or corrupted.';
261+
case FriendlyErrorType.rateLimitReached:
262+
return 'Translation limit reached.';
263+
case FriendlyErrorType.invalidApiKey:
264+
return 'Invalid API key.';
265+
case FriendlyErrorType.translationServiceError:
266+
return 'Translation service error.';
267+
case FriendlyErrorType.outOfMemory:
268+
return 'Not enough memory to complete this operation.';
269+
case FriendlyErrorType.genericError:
270+
return 'Something went wrong.';
271+
}
272+
}
273+
147274
@override
148-
String toString() => suggestion != null ? '$message $suggestion' : message;
275+
String toString() => fallbackMessage;
149276
}

0 commit comments

Comments
 (0)