feat(localization): Implement Swedish localization and error messages
- Added localization support for Swedish and English languages. - Integrated localized strings for user messages in the API error mapper. - Updated UI components to use localized strings for labels and messages. - Ensured all error messages are context-aware and utilize the localization framework. - Created regression test to prevent common ASCII fallbacks in Swedish UI text.
This commit is contained in:
@@ -19,7 +19,7 @@ class AuthRepository {
|
||||
if (data is! Map<String, dynamic>) {
|
||||
throw const ApiException(
|
||||
type: ApiErrorType.unknown,
|
||||
message: 'Ogiltigt svar fran servern.',
|
||||
message: 'Ogiltigt svar från servern.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class AuthRepository {
|
||||
} catch (_) {
|
||||
throw const ApiException(
|
||||
type: ApiErrorType.network,
|
||||
message: 'Kunde inte na servern.',
|
||||
message: 'Kunde inte nå servern.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../core/api/api_error_mapper.dart';
|
||||
import '../../../core/l10n/l10n.dart';
|
||||
import '../data/auth_providers.dart';
|
||||
|
||||
class LoginScreen extends ConsumerStatefulWidget {
|
||||
@@ -41,9 +42,10 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
final authState = ref.watch(authStateProvider);
|
||||
final isLoading = authState is AsyncLoading;
|
||||
final l10n = context.l10n;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Logga in')),
|
||||
appBar: AppBar(title: Text(l10n.loginTitle)),
|
||||
body: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
@@ -57,8 +59,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _usernameCtrl,
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Användarnamn'),
|
||||
decoration: InputDecoration(labelText: l10n.usernameLabel),
|
||||
textInputAction: TextInputAction.next,
|
||||
autofocus: true,
|
||||
enabled: !isLoading,
|
||||
@@ -66,7 +67,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
FocusScope.of(context).requestFocus(_passwordFocus),
|
||||
validator: (value) {
|
||||
if (value == null || value.trim().isEmpty) {
|
||||
return 'Ange ditt användarnamn.';
|
||||
return l10n.usernameRequired;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -75,14 +76,14 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
TextFormField(
|
||||
controller: _passwordCtrl,
|
||||
focusNode: _passwordFocus,
|
||||
decoration: const InputDecoration(labelText: 'Lösenord'),
|
||||
decoration: InputDecoration(labelText: l10n.passwordLabel),
|
||||
obscureText: true,
|
||||
textInputAction: TextInputAction.done,
|
||||
enabled: !isLoading,
|
||||
onFieldSubmitted: (_) => _submit(),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Ange ditt lösenord.';
|
||||
return l10n.passwordRequired;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -93,13 +94,13 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
|
||||
else
|
||||
FilledButton(
|
||||
onPressed: _submit,
|
||||
child: const Text('Logga in'),
|
||||
child: Text(l10n.loginAction),
|
||||
),
|
||||
if (authState is AsyncError)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16),
|
||||
child: Text(
|
||||
mapErrorToUserMessage(authState.error!),
|
||||
mapErrorToUserMessage(authState.error!, context),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error),
|
||||
|
||||
Reference in New Issue
Block a user