25 files changed
+529
-6
assets/images/flag_bd.png
Binary files /dev/null and b/assets/images/flag_bd.png differ
assets/images/flag_cn.png
Binary files /dev/null and b/assets/images/flag_cn.png differ
assets/images/flag_es.png
Binary files /dev/null and b/assets/images/flag_es.png differ
assets/images/flag_in.png
Binary files /dev/null and b/assets/images/flag_in.png differ
assets/images/flag_sa.png
Binary files /dev/null and b/assets/images/flag_sa.png differ
assets/images/flag_us.png
Binary files /dev/null and b/assets/images/flag_us.png differ
lib/app.dart
+6
@@ -12,6 +12,7 @@ import 'core/theme/app_theme.dart';
12
import 'features/chat/views/chat_screen.dart';
13
import 'features/conversations/views/chat_history_screen.dart';
14
import 'features/on_device/views/model_manager_screen.dart';
15
+import 'features/onboarding/screens/onboarding_language_screen.dart';
16
import 'features/onboarding/screens/onboarding_model_download_screen.dart';
17
import 'features/onboarding/screens/onboarding_notification_permission_screen.dart';
18
import 'features/onboarding/screens/onboarding_server_setup_screen.dart';
@@ -55,6 +56,11 @@ final routerProvider = Provider<GoRouter>((ref) {
56
routes: [
57
GoRoute(
58
path: AppRoutes.onboarding,
59
+ pageBuilder: (context, state) =>
60
+ const NoTransitionPage(child: OnboardingLanguageScreen()),
61
+ ),
62
+ GoRoute(
63
+ path: AppRoutes.onboardingServerType,
64
pageBuilder: (context, state) =>
65
const NoTransitionPage(child: OnboardingServerTypeScreen()),
66
),
lib/core/routes/app_routes.dart
+1
@@ -1,6 +1,7 @@
1
class AppRoutes {
2
static const String home = '/';
3
static const String onboarding = '/onboarding';
4
+ static const String onboardingServerType = '/onboarding/server-type';
5
static const String onboardingSetup = '/onboarding/setup';
6
static const String onboardingModelDownload = '/onboarding/model-download';
7
static const String onboardingTheme = '/onboarding/theme';
lib/features/onboarding/screens/onboarding_language_screen.dart
new
+397
@@ -0,0 +1,397 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:flutter_riverpod/flutter_riverpod.dart';
3
+import 'package:go_router/go_router.dart';
4
+import 'package:hugeicons/hugeicons.dart';
5
+import 'package:shadcn_ui/shadcn_ui.dart';
6
+
7
+import '../../../core/providers/app_providers.dart';
8
+import '../../../core/routes/app_routes.dart';
9
+import '../../../l10n/app_localizations.dart';
10
+
11
+class _LanguageOption {
12
+ final String code;
13
+ final String nativeName;
14
+ final String englishName;
15
+ final String flag;
16
+ final String flagAsset;
17
+ final String countryCode;
18
+ final String shortText;
19
+ final List<Color> gradient;
20
+
21
+ const _LanguageOption({
22
+ required this.code,
23
+ required this.nativeName,
24
+ required this.englishName,
25
+ required this.flag,
26
+ required this.flagAsset,
27
+ required this.countryCode,
28
+ required this.shortText,
29
+ required this.gradient,
30
+ });
31
+}
32
+
33
+const _languages = [
34
+ _LanguageOption(
35
+ code: 'en',
36
+ nativeName: 'English',
37
+ englishName: 'English',
38
+ flag: '🇺🇸',
39
+ flagAsset: 'assets/images/flag_us.png',
40
+ countryCode: 'US',
41
+ shortText: 'En',
42
+ gradient: [Color(0xFF6366F1), Color(0xFF4F46E5)],
43
+ ),
44
+ _LanguageOption(
45
+ code: 'es',
46
+ nativeName: 'Español',
47
+ englishName: 'Spanish',
48
+ flag: '🇪🇸',
49
+ flagAsset: 'assets/images/flag_es.png',
50
+ countryCode: 'ES',
51
+ shortText: 'Es',
52
+ gradient: [Color(0xFFF59E0B), Color(0xFFD97706)],
53
+ ),
54
+ _LanguageOption(
55
+ code: 'zh',
56
+ nativeName: '中文',
57
+ englishName: 'Chinese',
58
+ flag: '🇨🇳',
59
+ flagAsset: 'assets/images/flag_cn.png',
60
+ countryCode: 'CN',
61
+ shortText: 'Zh',
62
+ gradient: [Color(0xFFEF4444), Color(0xFFDC2626)],
63
+ ),
64
+ _LanguageOption(
65
+ code: 'ar',
66
+ nativeName: 'العربية',
67
+ englishName: 'Arabic',
68
+ flag: '🇸🇦',
69
+ flagAsset: 'assets/images/flag_sa.png',
70
+ countryCode: 'SA',
71
+ shortText: 'Ar',
72
+ gradient: [Color(0xFF10B981), Color(0xFF059669)],
73
+ ),
74
+ _LanguageOption(
75
+ code: 'hi',
76
+ nativeName: 'हिन्दी',
77
+ englishName: 'Hindi',
78
+ flag: '🇮🇳',
79
+ flagAsset: 'assets/images/flag_in.png',
80
+ countryCode: 'IN',
81
+ shortText: 'Hi',
82
+ gradient: [Color(0xFFEC4899), Color(0xFFDB2777)],
83
+ ),
84
+ _LanguageOption(
85
+ code: 'bn',
86
+ nativeName: 'বাংলা',
87
+ englishName: 'Bengali',
88
+ flag: '🇧🇩',
89
+ flagAsset: 'assets/images/flag_bd.png',
90
+ countryCode: 'BD',
91
+ shortText: 'Bn',
92
+ gradient: [Color(0xFF06B6D4), Color(0xFF0891B2)],
93
+ ),
94
+];
95
+
96
+class OnboardingLanguageScreen extends ConsumerStatefulWidget {
97
+ const OnboardingLanguageScreen({super.key});
98
+
99
+ @override
100
+ ConsumerState<OnboardingLanguageScreen> createState() =>
101
+ _OnboardingLanguageScreenState();
102
+}
103
+
104
+class _OnboardingLanguageScreenState
105
+ extends ConsumerState<OnboardingLanguageScreen> {
106
+ String? _selectedCode;
107
+
108
+ @override
109
+ void initState() {
110
+ super.initState();
111
+ // Read the current settings locale code
112
+ WidgetsBinding.instance.addPostFrameCallback((_) {
113
+ final settings = ref.read(settingsProvider);
114
+ setState(() {
115
+ _selectedCode = settings.localeCode ?? 'en';
116
+ });
117
+ });
118
+ }
119
+
120
+ @override
121
+ Widget build(BuildContext context) {
122
+ final l10n = AppLocalizations.of(context)!;
123
+ final theme = Theme.of(context);
124
+ final screenWidth = MediaQuery.of(context).size.width;
125
+ final crossAxisCount = screenWidth > 600 ? 3 : 2;
126
+
127
+ return Scaffold(
128
+ appBar: AppBar(
129
+ title: Row(
130
+ children: [
131
+ Padding(
132
+ padding: const EdgeInsets.all(8),
133
+ child: Image.asset(
134
+ 'assets/images/logo.webp',
135
+ width: 24,
136
+ height: 24,
137
+ ),
138
+ ),
139
+ Text(
140
+ l10n.onboarding_localmind,
141
+ style: const TextStyle(letterSpacing: 2, fontSize: 14),
142
+ ),
143
+ ],
144
+ ),
145
+ centerTitle: false,
146
+ actions: [
147
+ TextButton.icon(
148
+ onPressed: () => _skipOnboarding(),
149
+ label: Text(l10n.skip),
150
+ icon: HugeIcon(
151
+ icon: HugeIcons.strokeRoundedNext,
152
+ color: theme.colorScheme.primary,
153
+ size: 20,
154
+ ),
155
+ ),
156
+ ],
157
+ ),
158
+ body: Column(
159
+ crossAxisAlignment: CrossAxisAlignment.stretch,
160
+ children: [
161
+ Expanded(
162
+ child: SingleChildScrollView(
163
+ padding: const EdgeInsets.symmetric(horizontal: 24.0),
164
+ child: Column(
165
+ crossAxisAlignment: CrossAxisAlignment.stretch,
166
+ children: [
167
+ const SizedBox(height: 24),
168
+ Text(
169
+ l10n.onboarding_welcome,
170
+ textAlign: TextAlign.center,
171
+ style: theme.textTheme.headlineLarge?.copyWith(
172
+ fontWeight: FontWeight.w800,
173
+ height: 1.1,
174
+ ),
175
+ ),
176
+ const SizedBox(height: 12),
177
+ Text(
178
+ l10n.onboarding_choose_language,
179
+ textAlign: TextAlign.center,
180
+ style: theme.textTheme.titleMedium?.copyWith(
181
+ fontWeight: FontWeight.w600,
182
+ color: theme.colorScheme.primary,
183
+ ),
184
+ ),
185
+ const SizedBox(height: 8),
186
+ Text(
187
+ l10n.onboarding_choose_language_desc,
188
+ textAlign: TextAlign.center,
189
+ style: theme.textTheme.bodySmall?.copyWith(
190
+ color: theme.colorScheme.onSurface.withValues(alpha: 0.7),
191
+ height: 1.5,
192
+ ),
193
+ ),
194
+ const SizedBox(height: 32),
195
+ GridView.builder(
196
+ shrinkWrap: true,
197
+ physics: const NeverScrollableScrollPhysics(),
198
+ gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
199
+ crossAxisCount: crossAxisCount,
200
+ crossAxisSpacing: 16,
201
+ mainAxisSpacing: 16,
202
+ childAspectRatio: 1.05,
203
+ ),
204
+ itemCount: _languages.length,
205
+ itemBuilder: (context, index) {
206
+ final lang = _languages[index];
207
+ final isSelected = _selectedCode == lang.code;
208
+
209
+ return GestureDetector(
210
+ onTap: () {
211
+ setState(() {
212
+ _selectedCode = lang.code;
213
+ });
214
+ // Dynamically apply settings localization update
215
+ ref
216
+ .read(settingsProvider.notifier)
217
+ .setLocaleCode(lang.code);
218
+ },
219
+ child: AnimatedContainer(
220
+ duration: const Duration(milliseconds: 200),
221
+ padding: const EdgeInsets.all(16),
222
+ decoration: BoxDecoration(
223
+ color: theme.colorScheme.surface,
224
+ borderRadius: BorderRadius.circular(16),
225
+ border: Border.all(
226
+ color: isSelected
227
+ ? theme.colorScheme.primary
228
+ : theme.colorScheme.outline
229
+ .withValues(alpha: 0.3),
230
+ width: isSelected ? 2 : 1,
231
+ ),
232
+ boxShadow: isSelected
233
+ ? [
234
+ BoxShadow(
235
+ color: theme.colorScheme.primary
236
+ .withValues(alpha: 0.15),
237
+ blurRadius: 10,
238
+ offset: const Offset(0, 4),
239
+ )
240
+ ]
241
+ : null,
242
+ ),
243
+ child: Column(
244
+ crossAxisAlignment: CrossAxisAlignment.start,
245
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
246
+ children: [
247
+ Row(
248
+ mainAxisAlignment:
249
+ MainAxisAlignment.spaceBetween,
250
+ children: [
251
+ Container(
252
+ width: 52,
253
+ height: 36,
254
+ decoration: BoxDecoration(
255
+ color: Colors.white,
256
+ borderRadius: BorderRadius.circular(6),
257
+ border: Border.all(
258
+ color: theme.colorScheme.outline
259
+ .withValues(alpha: 0.15),
260
+ width: 1,
261
+ ),
262
+ boxShadow: [
263
+ BoxShadow(
264
+ color: Colors.black.withValues(alpha: 0.05),
265
+ blurRadius: 4,
266
+ offset: const Offset(0, 2),
267
+ ),
268
+ ],
269
+ ),
270
+ alignment: Alignment.center,
271
+ child: ClipRRect(
272
+ borderRadius: BorderRadius.circular(5),
273
+ child: Image.asset(
274
+ lang.flagAsset,
275
+ width: 52,
276
+ height: 36,
277
+ fit: BoxFit.cover,
278
+ errorBuilder: (context, error, stackTrace) {
279
+ return Text(
280
+ lang.flag,
281
+ style: const TextStyle(fontSize: 18),
282
+ );
283
+ },
284
+ ),
285
+ ),
286
+ ),
287
+ if (isSelected)
288
+ Icon(
289
+ Icons.check_circle_rounded,
290
+ color: theme.colorScheme.primary,
291
+ size: 20,
292
+ ),
293
+ ],
294
+ ),
295
+ const SizedBox(height: 12),
296
+ Column(
297
+ crossAxisAlignment: CrossAxisAlignment.start,
298
+ children: [
299
+ Text(
300
+ lang.nativeName,
301
+ style:
302
+ theme.textTheme.titleMedium?.copyWith(
303
+ fontWeight: FontWeight.bold,
304
+ ),
305
+ maxLines: 1,
306
+ overflow: TextOverflow.ellipsis,
307
+ ),
308
+ const SizedBox(height: 2),
309
+ Text(
310
+ '${lang.englishName} • ${lang.shortText.toUpperCase()}',
311
+ style: theme.textTheme.labelSmall?.copyWith(
312
+ color: theme.colorScheme.onSurface
313
+ .withValues(alpha: 0.5),
314
+ ),
315
+ maxLines: 1,
316
+ overflow: TextOverflow.ellipsis,
317
+ ),
318
+ ],
319
+ ),
320
+ ],
321
+ ),
322
+ ),
323
+ );
324
+ },
325
+ ),
326
+ const SizedBox(height: 32),
327
+ ],
328
+ ),
329
+ ),
330
+ ),
331
+ Padding(
332
+ padding: const EdgeInsets.symmetric(horizontal: 24.0),
333
+ child: Column(
334
+ children: [
335
+ Row(
336
+ mainAxisAlignment: MainAxisAlignment.center,
337
+ children: [
338
+ Container(
339
+ width: 8,
340
+ height: 8,
341
+ decoration: BoxDecoration(
342
+ color: theme.colorScheme.primary,
343
+ shape: BoxShape.circle,
344
+ ),
345
+ ),
346
+ const SizedBox(width: 8),
347
+ Text(
348
+ l10n.ready_continue,
349
+ style: theme.textTheme.labelSmall?.copyWith(
350
+ color: theme.colorScheme.onSurface.withValues(
351
+ alpha: 0.5,
352
+ ),
353
+ letterSpacing: 2,
354
+ fontWeight: FontWeight.w600,
355
+ ),
356
+ ),
357
+ ],
358
+ ),
359
+ const SizedBox(height: 16),
360
+ ShadButton(
361
+ width: double.infinity,
362
+ onPressed: () {
363
+ context.push(AppRoutes.onboardingServerType);
364
+ },
365
+ child: Text(
366
+ l10n.continue_action,
367
+ style: const TextStyle(
368
+ fontSize: 16,
369
+ fontWeight: FontWeight.w600,
370
+ ),
371
+ ),
372
+ ),
373
+ SizedBox(
374
+ height: MediaQuery.of(context).padding.bottom,
375
+ ),
376
+ ],
377
+ ),
378
+ ),
379
+ ],
380
+ ),
381
+ );
382
+ }
383
+
384
+ Future<void> _completeOnboarding() async {
385
+ final settings = ref.read(settingsProvider);
386
+ await ref
387
+ .read(settingsProvider.notifier)
388
+ .updateSettings(settings.copyWith(hasCompletedOnboarding: true));
389
+ if (mounted) {
390
+ context.go(AppRoutes.home);
391
+ }
392
+ }
393
+
394
+ void _skipOnboarding() {
395
+ _completeOnboarding();
396
+ }
397
+}
lib/features/onboarding/screens/onboarding_server_setup_screen.dart
+9
-4
@@ -156,7 +156,9 @@ class _OnboardingServerSetupScreenState
156
if (mounted) {
157
ScaffoldMessenger.of(context).showSnackBar(
158
SnackBar(
159
- content: Text(AppLocalizations.of(context)!.error_with_message(e.toString())),
159
+ content: Text(
160
+ AppLocalizations.of(context)!.error_with_message(e.toString()),
161
+ ),
162
backgroundColor: Colors.red,
163
),
164
);
@@ -202,8 +204,9 @@ class _OnboardingServerSetupScreenState
204
filled: true,
205
fillColor: theme.colorScheme.surface,
206
),
205
- validator: (val) =>
206
- val == null || val.trim().isEmpty ? l10n.name_required : null,
207
+ validator: (val) => val == null || val.trim().isEmpty
208
+ ? l10n.name_required
209
+ : null,
210
),
211
const SizedBox(height: 16),
212
@@ -246,7 +249,9 @@ class _OnboardingServerSetupScreenState
249
TextFormField(
250
controller: _apiKeyController,
251
decoration: InputDecoration(
249
- labelText: isCloud ? l10n.api_key_required : l10n.api_key_optional,
252
+ labelText: isCloud
253
+ ? l10n.api_key_required
254
+ : l10n.api_key_optional,
255
filled: true,
256
fillColor: theme.colorScheme.surface,
257
),
lib/features/onboarding/screens/onboarding_server_type_screen.dart
+5
-1
@@ -34,6 +34,7 @@ class _OnboardingServerTypeScreenState
34
35
return Scaffold(
36
appBar: AppBar(
37
+ automaticallyImplyLeading: false,
38
title: Row(
39
children: [
40
Padding(
@@ -196,7 +197,10 @@ class _OnboardingServerTypeScreenState
197
},
198
child: Text(
199
l10n.continue_action,
199
- style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
200
+ style: const TextStyle(
201
+ fontSize: 16,
202
+ fontWeight: FontWeight.w600,
203
+ ),
204
),
205
),
206
SizedBox(
lib/l10n/app_ar.arb
+6
@@ -473,12 +473,18 @@
473
474
"older_section": "الأقدم",
475
476
+ "onboarding_choose_language": "اختر اللغة",
477
+
478
+ "onboarding_choose_language_desc": "اختر لغتك المفضلة. يمكنك تغيير هذا في أي وقت من الإعدادات.",
479
+
480
"onboarding_localmind": "LOCALMIND",
481
482
"onboarding_connect_server": "اتصل\nبخادمك",
483
484
"onboarding_connect_desc": "اتصل بـ LM Studio أو Ollama أو\nOpenRouter لبدء تجربة الذكاء\nالاصطناعي الخاصة بك.",
485
486
+ "onboarding_welcome": "مرحباً بك في LocalMind",
487
+
488
"server_type_on_device": "محلي",
489
490
"server_type_on_device_sub": "لا يحتاج خادماً",
lib/l10n/app_bn.arb
+3
@@ -243,9 +243,12 @@
243
"older_section": "পূর্বের",
244
"on_device_android_only": "অন-ডিভাইস ইনফারেন্স বর্তমানে শুধুমাত্র অ্যান্ড্রয়েডেই উপলব্ধ।",
245
"on_device_models_title": "অন-ডিভাইস মডেলসমূহ",
246
+ "onboarding_choose_language": "ভাষা নির্বাচন করুন",
247
+ "onboarding_choose_language_desc": "আপনার পছন্দের ভাষা নির্বাচন করুন। আপনি সেটিংস থেকে যেকোনো সময় এটি পরিবর্তন করতে পারবেন।",
248
"onboarding_connect_desc": "আপনার নিজস্ব ব্যক্তিগত এআই অভিজ্ঞতা শুরু করতে\nLM Studio, Ollama, অথবা OpenRouter-এর সাথে\nসংযোগ করুন।",
249
"onboarding_connect_server": "আপনার সার্ভার\nসংযোগ করুন",
250
"onboarding_localmind": "LOCALMIND",
251
+ "onboarding_welcome": "LocalMind-এ স্বাগতম",
252
"online": "অনলাইন",
253
"open_source": "ওপেন সোর্স",
254
"open_source_desc": "LocalMind একটি ওপেন সোর্স প্রকল্প। গিটহাবে (GitHub) আমাদের অগ্রগতি অনুসরণ করুন বা অবদান রাখুন।",
lib/l10n/app_en.arb
+15
@@ -1309,6 +1309,16 @@
1309
"description": "Older conversations section header"
1310
},
1311
1312
+ "onboarding_choose_language": "Choose Language",
1313
+ "@onboarding_choose_language": {
1314
+ "description": "Onboarding title to select application language"
1315
+ },
1316
+
1317
+ "onboarding_choose_language_desc": "Select your preferred language. You can change this anytime in settings.",
1318
+ "@onboarding_choose_language_desc": {
1319
+ "description": "Onboarding description for language selection"
1320
+ },
1321
+
1322
"onboarding_localmind": "LOCALMIND",
1323
"@onboarding_localmind": {
1324
"description": "Onboarding screen branding text"
@@ -1324,6 +1334,11 @@
1334
"description": "Onboarding server connection description"
1335
},
1336
1337
+ "onboarding_welcome": "Welcome to LocalMind",
1338
+ "@onboarding_welcome": {
1339
+ "description": "Onboarding welcome message"
1340
+ },
1341
+
1342
"server_type_on_device": "On-Device",
1343
"@server_type_on_device": {
1344
"description": "On-device server type card title"
lib/l10n/app_es.arb
+3
@@ -243,9 +243,12 @@
243
"older_section": "MÁS ANTIGUOS",
244
"on_device_android_only": "La inferencia local está disponible actualmente solo en Android.",
245
"on_device_models_title": "Modelos locales",
246
+ "onboarding_choose_language": "Elija el idioma",
247
+ "onboarding_choose_language_desc": "Seleccione su idioma preferido. Puede cambiar esto en cualquier momento en la configuración.",
248
"onboarding_connect_desc": "Conéctese a LM Studio, Ollama o\nOpenRouter para comenzar su experiencia\nprivada de IA.",
249
"onboarding_connect_server": "Conecte su\nservidor",
250
"onboarding_localmind": "LOCALMIND",
251
+ "onboarding_welcome": "Bienvenido a LocalMind",
252
"online": "En línea",
253
"open_source": "Código abierto",
254
"open_source_desc": "LocalMind es de código abierto. Siga nuestro progreso o contribuya en GitHub.",
lib/l10n/app_hi.arb
+3
@@ -243,9 +243,12 @@
243
"older_section": "पुराने",
244
"on_device_android_only": "ऑन-डिवाइस अनुमान वर्तमान में केवल Android पर उपलब्ध है।",
245
"on_device_models_title": "ऑन-डिवाइस मॉडल",
246
+ "onboarding_choose_language": "भाषा चुनें",
247
+ "onboarding_choose_language_desc": "अपनी पसंदीदा भाषा चुनें। आप इसे सेटिंग्स में कभी भी बदल सकते हैं।",
248
"onboarding_connect_desc": "अपना निजी AI अनुभव शुरू करने के लिए\nLM Studio, Ollama, या OpenRouter से\nकनेक्ट करें।",
249
"onboarding_connect_server": "अपना सर्वर\nकनेक्ट करें",
250
"onboarding_localmind": "LOCALMIND",
251
+ "onboarding_welcome": "LocalMind में आपका स्वागत है",
252
"online": "ऑनलाइन",
253
"open_source": "ओपन सोर्स",
254
"open_source_desc": "LocalMind ओपन सोर्स है। गिटहब (GitHub) पर हमारी प्रगति का अनुसरण करें या योगदान दें।",
lib/l10n/app_localizations.dart
+18
@@ -1522,6 +1522,18 @@ abstract class AppLocalizations {
1522
/// **'OLDER'**
1523
String get older_section;
1524
1525
+ /// Onboarding title to select application language
1526
+ ///
1527
+ /// In en, this message translates to:
1528
+ /// **'Choose Language'**
1529
+ String get onboarding_choose_language;
1530
+
1531
+ /// Onboarding description for language selection
1532
+ ///
1533
+ /// In en, this message translates to:
1534
+ /// **'Select your preferred language. You can change this anytime in settings.'**
1535
+ String get onboarding_choose_language_desc;
1536
+
1537
/// Onboarding screen branding text
1538
///
1539
/// In en, this message translates to:
@@ -1540,6 +1552,12 @@ abstract class AppLocalizations {
1552
/// **'Connect to LM Studio, Ollama, or\nOpenRouter to start your private AI\nexperience.'**
1553
String get onboarding_connect_desc;
1554
1555
+ /// Onboarding welcome message
1556
+ ///
1557
+ /// In en, this message translates to:
1558
+ /// **'Welcome to LocalMind'**
1559
+ String get onboarding_welcome;
1560
+
1561
/// On-device server type card title
1562
///
1563
/// In en, this message translates to:
lib/l10n/app_localizations_ar.dart
+10
@@ -761,6 +761,13 @@ class AppLocalizationsAr extends AppLocalizations {
761
@override
762
String get older_section => 'الأقدم';
763
764
+ @override
765
+ String get onboarding_choose_language => 'اختر اللغة';
766
+
767
+ @override
768
+ String get onboarding_choose_language_desc =>
769
+ 'اختر لغتك المفضلة. يمكنك تغيير هذا في أي وقت من الإعدادات.';
770
+
771
@override
772
String get onboarding_localmind => 'LOCALMIND';
773
@@ -771,6 +778,9 @@ class AppLocalizationsAr extends AppLocalizations {
778
String get onboarding_connect_desc =>
779
'اتصل بـ LM Studio أو Ollama أو\nOpenRouter لبدء تجربة الذكاء\nالاصطناعي الخاصة بك.';
780
781
+ @override
782
+ String get onboarding_welcome => 'مرحباً بك في LocalMind';
783
+
784
@override
785
String get server_type_on_device => 'محلي';
786
lib/l10n/app_localizations_bn.dart
+10
@@ -765,6 +765,13 @@ class AppLocalizationsBn extends AppLocalizations {
765
@override
766
String get older_section => 'পূর্বের';
767
768
+ @override
769
+ String get onboarding_choose_language => 'ভাষা নির্বাচন করুন';
770
+
771
+ @override
772
+ String get onboarding_choose_language_desc =>
773
+ 'আপনার পছন্দের ভাষা নির্বাচন করুন। আপনি সেটিংস থেকে যেকোনো সময় এটি পরিবর্তন করতে পারবেন।';
774
+
775
@override
776
String get onboarding_localmind => 'LOCALMIND';
777
@@ -775,6 +782,9 @@ class AppLocalizationsBn extends AppLocalizations {
782
String get onboarding_connect_desc =>
783
'আপনার নিজস্ব ব্যক্তিগত এআই অভিজ্ঞতা শুরু করতে\nLM Studio, Ollama, অথবা OpenRouter-এর সাথে\nসংযোগ করুন।';
784
785
+ @override
786
+ String get onboarding_welcome => 'LocalMind-এ স্বাগতম';
787
+
788
@override
789
String get server_type_on_device => 'অন-ডিভাইস (On-Device)';
790
lib/l10n/app_localizations_en.dart
+10
@@ -762,6 +762,13 @@ class AppLocalizationsEn extends AppLocalizations {
762
@override
763
String get older_section => 'OLDER';
764
765
+ @override
766
+ String get onboarding_choose_language => 'Choose Language';
767
+
768
+ @override
769
+ String get onboarding_choose_language_desc =>
770
+ 'Select your preferred language. You can change this anytime in settings.';
771
+
772
@override
773
String get onboarding_localmind => 'LOCALMIND';
774
@@ -772,6 +779,9 @@ class AppLocalizationsEn extends AppLocalizations {
779
String get onboarding_connect_desc =>
780
'Connect to LM Studio, Ollama, or\nOpenRouter to start your private AI\nexperience.';
781
782
+ @override
783
+ String get onboarding_welcome => 'Welcome to LocalMind';
784
+
785
@override
786
String get server_type_on_device => 'On-Device';
787
lib/l10n/app_localizations_es.dart
+10
@@ -765,6 +765,13 @@ class AppLocalizationsEs extends AppLocalizations {
765
@override
766
String get older_section => 'MÁS ANTIGUOS';
767
768
+ @override
769
+ String get onboarding_choose_language => 'Elija el idioma';
770
+
771
+ @override
772
+ String get onboarding_choose_language_desc =>
773
+ 'Seleccione su idioma preferido. Puede cambiar esto en cualquier momento en la configuración.';
774
+
775
@override
776
String get onboarding_localmind => 'LOCALMIND';
777
@@ -775,6 +782,9 @@ class AppLocalizationsEs extends AppLocalizations {
782
String get onboarding_connect_desc =>
783
'Conéctese a LM Studio, Ollama o\nOpenRouter para comenzar su experiencia\nprivada de IA.';
784
785
+ @override
786
+ String get onboarding_welcome => 'Bienvenido a LocalMind';
787
+
788
@override
789
String get server_type_on_device => 'Local';
790
lib/l10n/app_localizations_hi.dart
+10
@@ -764,6 +764,13 @@ class AppLocalizationsHi extends AppLocalizations {
764
@override
765
String get older_section => 'पुराने';
766
767
+ @override
768
+ String get onboarding_choose_language => 'भाषा चुनें';
769
+
770
+ @override
771
+ String get onboarding_choose_language_desc =>
772
+ 'अपनी पसंदीदा भाषा चुनें। आप इसे सेटिंग्स में कभी भी बदल सकते हैं।';
773
+
774
@override
775
String get onboarding_localmind => 'LOCALMIND';
776
@@ -774,6 +781,9 @@ class AppLocalizationsHi extends AppLocalizations {
781
String get onboarding_connect_desc =>
782
'अपना निजी AI अनुभव शुरू करने के लिए\nLM Studio, Ollama, या OpenRouter से\nकनेक्ट करें।';
783
784
+ @override
785
+ String get onboarding_welcome => 'LocalMind में आपका स्वागत है';
786
+
787
@override
788
String get server_type_on_device => 'ऑन-डिवाइस';
789
lib/l10n/app_localizations_zh.dart
+9
@@ -752,6 +752,12 @@ class AppLocalizationsZh extends AppLocalizations {
752
@override
753
String get older_section => '更早';
754
755
+ @override
756
+ String get onboarding_choose_language => '选择语言';
757
+
758
+ @override
759
+ String get onboarding_choose_language_desc => '选择您首选的语言。您随时可以在设置中更改此项。';
760
+
761
@override
762
String get onboarding_localmind => 'LOCALMIND';
763
@@ -762,6 +768,9 @@ class AppLocalizationsZh extends AppLocalizations {
768
String get onboarding_connect_desc =>
769
'连接到 LM Studio、Ollama 或\nOpenRouter,开启您的私有 AI\n体验。';
770
771
+ @override
772
+ String get onboarding_welcome => '欢迎使用 LocalMind';
773
+
774
@override
775
String get server_type_on_device => '设备端';
776
lib/l10n/app_zh.arb
+3
@@ -243,9 +243,12 @@
243
"older_section": "更早",
244
"on_device_android_only": "设备端推理当前仅可在 Android 上使用。",
245
"on_device_models_title": "设备端模型",
246
+ "onboarding_choose_language": "选择语言",
247
+ "onboarding_choose_language_desc": "选择您首选的语言。您随时可以在设置中更改此项。",
248
"onboarding_connect_desc": "连接到 LM Studio、Ollama 或\nOpenRouter,开启您的私有 AI\n体验。",
249
"onboarding_connect_server": "连接您的\n服务器",
250
"onboarding_localmind": "LOCALMIND",
251
+ "onboarding_welcome": "欢迎使用 LocalMind",
252
"online": "在线",
253
"open_source": "开源",
254
"open_source_desc": "LocalMind 是开源项目。可在 GitHub 上关注我们的进展或参与贡献。",
pubspec.yaml
+1
-1
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
16
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17
# In Windows, build-name is used as the major, minor, and patch parts
18
# of the product and file versions while build-number is used as the build suffix.
19
-version: 1.2.6+25
19
+version: 1.2.7+26
20
21
environment:
22
sdk: ^3.11.0