Skip to content

Commit fd3d6d7

Browse files
authored
Allow localized strings (#178)
* chore: allow localized strings (#97) * chore: dart format and analyze * chore: split work done to only add localised strings (removed added dependencies and version update * fix: Fixed CI issues
1 parent 0d1be88 commit fd3d6d7

18 files changed

+680
-65
lines changed

example/ios/Runner/Info.plist

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@
4949
<string>UIInterfaceOrientationLandscapeLeft</string>
5050
<string>UIInterfaceOrientationLandscapeRight</string>
5151
</array>
52-
<key>CADisableMinimumFrameDurationOnPhone</key>
53-
<true/>
54-
<key>UIApplicationSupportsIndirectInputEvents</key>
55-
<true/>
52+
<key>CADisableMinimumFrameDurationOnPhone</key>
53+
<true/>
54+
<key>UIApplicationSupportsIndirectInputEvents</key>
55+
<true/>
5656
</dict>
5757
</plist>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2025 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:firebase_ai/firebase_ai.dart';
6+
import 'package:firebase_core/firebase_core.dart';
7+
import 'package:flutter/material.dart';
8+
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';
9+
10+
import '../firebase_options.dart';
11+
12+
void main() async {
13+
WidgetsFlutterBinding.ensureInitialized();
14+
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
15+
runApp(const App());
16+
}
17+
18+
class App extends StatelessWidget {
19+
static const title = 'Example: Google Gemini AI';
20+
21+
const App({super.key});
22+
23+
@override
24+
Widget build(BuildContext context) =>
25+
const MaterialApp(title: title, home: CustomStringsExample());
26+
}
27+
28+
class CustomStringsExample extends StatelessWidget {
29+
static const title = 'Custom Chat Strings';
30+
31+
const CustomStringsExample({super.key});
32+
33+
@override
34+
Widget build(BuildContext context) {
35+
final customStrings = const LlmChatViewStrings(
36+
addAttachment: 'Add',
37+
attachFile: 'Attach File',
38+
takePhoto: 'Take Photo',
39+
stop: '⏹️ Stop',
40+
close: '❌ Close',
41+
cancel: '❌ Cancel',
42+
copyToClipboard: '📋 Copy',
43+
editMessage: '✏️ Edit',
44+
attachImage: '🖼️ Add Image',
45+
recordAudio: '🎤 Record',
46+
submitMessage: '📤 Send',
47+
closeMenu: '❌ Close Menu',
48+
49+
// Message related
50+
typeAMessage: 'Type your message here...',
51+
recording: '🔴 Recording...',
52+
tapToStop: 'Tap to stop',
53+
tapToRecord: 'Tap to record',
54+
releaseToCancel: 'Release to cancel',
55+
slideToCancel: 'Slide to cancel',
56+
57+
submit: 'Submit',
58+
send: 'Send',
59+
delete: '🗑️ Delete',
60+
edit: '✏️ Edit',
61+
copy: '📋 Copy',
62+
share: '↗️ Share',
63+
retry: '🔄 Retry',
64+
yes: '✅ Yes',
65+
no: '❌ No',
66+
clear: '🗑️ Clear',
67+
search: '🔍 Search',
68+
69+
// Messages and errors
70+
messageCopiedToClipboard: '📋 Copied to clipboard!',
71+
editing: '✏️ Editing',
72+
error: '❌ Error',
73+
cancelMessage: 'Cancel',
74+
confirmDelete: 'Confirm Delete',
75+
areYouSureYouWantToDeleteThisMessage:
76+
'Are you sure you want to delete this message?',
77+
errorSendingMessage: '❌ Failed to send message',
78+
errorLoadingMessages: '❌ Failed to load messages',
79+
noMessagesYet: 'No messages yet. Start the conversation!',
80+
tapToRetry: 'Tap to retry',
81+
noResultsFound: 'No results found',
82+
unableToRecordAudio: 'Unable to record audio',
83+
unsupportedImageSource: 'Unsupported image source',
84+
unableToPickImage: 'Unable to pick image',
85+
unableToPickFile: 'Unable to pick file',
86+
unableToPickUrl: 'Unable to process URL',
87+
);
88+
89+
return Scaffold(
90+
appBar: AppBar(title: const Text(App.title)),
91+
body: LlmChatView(
92+
provider: FirebaseProvider(
93+
model: FirebaseAI.googleAI().generativeModel(
94+
model: 'gemini-2.0-flash',
95+
),
96+
),
97+
strings: customStrings,
98+
style: LlmChatViewStyle(strings: customStrings),
99+
),
100+
);
101+
}
102+
}

lib/flutter_ai_toolkit.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ export 'src/providers/interface/chat_message.dart';
1919
export 'src/providers/providers.dart';
2020
export 'src/styles/styles.dart';
2121
export 'src/views/llm_chat_view/llm_chat_view.dart';
22+
export 'src/strings/strings.dart';

lib/src/chat_view_model/chat_view_model.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'package:flutter/foundation.dart';
66

77
import '../providers/interface/llm_provider.dart';
8+
import '../strings/llm_chat_view_strings.dart';
89
import '../styles/llm_chat_view_style.dart';
910
import '../views/response_builder.dart';
1011

@@ -35,6 +36,7 @@ class ChatViewModel {
3536
required this.speechToText,
3637
required this.enableAttachments,
3738
required this.enableVoiceNotes,
39+
this.strings = const LlmChatViewStrings(),
3840
});
3941

4042
/// The LLM provider for the chat interface.
@@ -92,6 +94,12 @@ class ChatViewModel {
9294
/// will be disabled.
9395
final bool enableVoiceNotes;
9496

97+
/// The strings used throughout the chat interface.
98+
///
99+
/// This provides access to all the text strings used in the chat interface,
100+
/// allowing for easy customization and internationalization.
101+
final LlmChatViewStrings strings;
102+
95103
// The following is needed to support the
96104
// ChatViewModelProvider.updateShouldNotify implementation
97105
@override
@@ -104,8 +112,10 @@ class ChatViewModel {
104112
other.welcomeMessage == welcomeMessage &&
105113
other.responseBuilder == responseBuilder &&
106114
other.messageSender == messageSender &&
115+
other.speechToText == speechToText &&
107116
other.enableAttachments == enableAttachments &&
108-
other.enableVoiceNotes == enableVoiceNotes);
117+
other.enableVoiceNotes == enableVoiceNotes &&
118+
other.strings == strings);
109119

110120
// the following is best practices when overriding operator ==
111121
@override
@@ -116,7 +126,9 @@ class ChatViewModel {
116126
welcomeMessage,
117127
responseBuilder,
118128
messageSender,
129+
speechToText,
119130
enableAttachments,
120131
enableVoiceNotes,
132+
strings,
121133
);
122134
}

0 commit comments

Comments
 (0)