Hello! Today, we'll explore how to implement a translation feature in Flutter using Google Translate API. Let's create a multilingual support system that's both efficient and user-friendly.
1. Required Package Installation
First, add these packages to your pubspec.yaml:
dependencies:
translator: ^1.0.3 # For Google Translate API
language_detector: ^1.0.1 # For language detection
freezed_annotation: 2.4.4 # For state management with freezed
dev_dependencies:
build_runner: ^2.4.12
freezed: 2.4.42. Implementing TranslatorService
Create a service class for translation functionality:
import 'package:language_detector/language_detector.dart';
import 'package:translator/translator.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
@Riverpod(keepAlive: true)
class TranslatorService extends _$TranslatorService {
@override
String? build() => null;
Future<String> translate(String text) async {
final translator = GoogleTranslator();
final isSameLanguage = await detectSameLanguage(text);
// Skip translation if same language
if (isSameLanguage) {
return text;
}
// Translate to user's selected language
final translation = await translator.translate(text, to: 'en');
return translation.text;
}
Future<bool> detectSameLanguage(String text) async {
final languageCode = await LanguageDetector.getLanguageCode(content: text);
return languageCode == 'en'; // For English
}
}3. Freezed Model for State Management
Define a model to manage post states:
@freezed
class Post with _$Post {
const factory Post({
required String title,
required String titleTranslated,
required String content,
required String contentTranslated,
required bool isSameLanguage,
required bool isTranslated,
}) = _Post;
}4. Translation Feature Implementation
class PostController extends _$PostController {
Future<void> changePostLanguage(String postId) async {
final post = state.value!.posts.firstWhere((post) => post.id == postId);
// Skip if same language
if (post.isSameLanguage) return;
// Use cached translation if available
if (post.isTranslated) {
final translatedPost = post.copyWith(
titleTranslated: post.titleTranslated,
contentTranslated: post.contentTranslated,
isTranslated: true,
);
_updatePost(postId, translatedPost);
return;
}
// Perform new translation
final translatedTitle = await _translatorService.translate(post.title);
final translatedContent = await _translatorService.translate(post.content);
final translatedPost = post.copyWith(
titleTranslated: translatedTitle,
contentTranslated: translatedContent,
isTranslated: true,
);
_updatePost(postId, translatedPost);
}
// Restore to original language
Future<void> restorePostLanguage(String postId) async {
final post = state.value!.posts.firstWhere((post) => post.id == postId);
final restoredPost = post.copyWith(
titleTranslated: post.title,
contentTranslated: post.content,
isTranslated: false,
);
_updatePost(postId, restoredPost);
}
}5. UI Implementation
class TranslatePostCard extends ConsumerWidget {
final Post post;
const TranslatePostCard({
Key? key,
required this.post,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Card(
margin: const EdgeInsets.all(16.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Title
Text(
post.isTranslated ? post.titleTranslated : post.title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
// Content
Text(
post.isTranslated ? post.contentTranslated : post.content,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 16),
// Translation button
if (!post.isSameLanguage)
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TranslateButton(
isTranslated: post.isTranslated,
onPressed: () {
if (post.isTranslated) {
ref.read(postControllerProvider.notifier)
.restorePostLanguage(post.id);
} else {
ref.read(postControllerProvider.notifier)
.changePostLanguage(post.id);
}
},
),
],
),
],
),
),
);
}
}6. Benefits of Maintaining Original Content
- Performance Optimization:
- Reduces repeated API calls by caching translated content
- Enables instant switching between original and translated versions
- User Experience:
- Quick toggle between original and translated content
- Allows users to verify translation accuracy
- Data Integrity:
- Preserves original content for recovery from translation errors
- Prevents loss of critical information during translation
- Cost Efficiency:
- Minimizes translation API calls
- Reduces server load through cached translation results

Conclusion
This translation implementation provides users with:
- Intuitive UI for easy translation access
- Seamless switching between original and translated content
- Fast response times for better user experience
- Efficient resource management for stable service
Using Freezed for state management and original content preservation strategy enables a robust and efficient translation feature.