Flutter文本翻译插件fl_mlkit_translate_text的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter文本翻译插件 fl_mlkit_translate_text 的使用

fl_mlkit_translate_text 是一个基于 Google ML Kit 的 Flutter 插件,支持在 Android 和 iOS 平台上进行文本翻译。本文将介绍如何使用该插件,并提供一个完整的示例 Demo。

功能概述

  • 翻译文本:将一种语言的文本翻译为另一种语言。
  • 切换翻译语言:动态更改源语言和目标语言。
  • 管理下载的模型:查看、下载或删除已下载的语言模型。
  • 检查模型状态:判断某个语言模型是否已下载。

安装插件

首先,在 pubspec.yaml 文件中添加依赖:

dependencies:
  fl_mlkit_translate_text: ^latest_version

然后运行 flutter pub get 来安装插件。

示例代码

以下是一个完整的示例应用,展示了如何使用 fl_mlkit_translate_text 插件进行文本翻译。

main.dart

import 'package:fl_extended/fl_extended.dart';
import 'package:fl_mlkit_translate_text/fl_mlkit_translate_text.dart';
import 'package:flutter/material.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MaterialApp(
      navigatorKey: FlExtended().navigatorKey,
      scaffoldMessengerKey: FlExtended().scaffoldMessengerKey,
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(useMaterial3: true),
      darkTheme: ThemeData.dark(useMaterial3: true),
      title: 'FlMlKitTranslate',
      home: Scaffold(
          appBar: AppBarText('Fl MlKit Translate Text'),
          body: SingleChildScrollView(
              child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: _App(),
          )))));
}

class _App extends StatefulWidget {
  [@override](/user/override)
  State<_App> createState() => _AppState();
}

class _AppState extends State<_App> {
  TextEditingController controller = TextEditingController();
  List<TranslateRemoteModel> remoteModels = [];
  FlMlKitTranslateText translateText = FlMlKitTranslateText();
  ValueNotifier<String> text = ValueNotifier<String>('No Translate');

  [@override](/user/override)
  void initState() {
    super.initState();
    addPostFrameCallback((duration) {
      getDownloadedModels();
    });
  }

  Future<void> getDownloadedModels() async {
    remoteModels = await translateText.getDownloadedModels();
    bool hasZH = false;
    for (var element in remoteModels) {
      if (element.language == TranslateLanguage.chinese) {
        hasZH = true;
        break;
      }
    }
    if (!hasZH) {
      final state =
          await translateText.downloadedModel(TranslateLanguage.chinese);
      'DownloadedModel TranslateLanguage.chinese = $state'.log();
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(children: [
      ElevatedText(
          text: 'TranslateRemoteModel Manager',
          onPressed: () {
            context.requestFocus();
            push(const TranslateRemoteModelManagerPage());
          }),
      const SizedBox(height: 20),
      TextField(
          controller: controller,
          maxLength: 500,
          maxLines: 4,
          onSubmitted: (value) {
            context.requestFocus();
          },
          decoration: const InputDecoration(
              border: OutlineInputBorder(), hintText: 'Please enter text')),
      StatefulBuilder(builder: (_, state) {
        return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
          ElevatedText(
              onPressed: () async {
                context.requestFocus();
                final language = await selectLanguage();
                if (language != null &&
                    language != translateText.sourceLanguage &&
                    language != translateText.targetLanguage) {
                  translateText
                      .switchLanguage(language, translateText.targetLanguage)
                      .then((value) {
                    state(() {});
                  });
                }
              },
              text: translateText.sourceLanguage.name),
          IconButton(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              onPressed: () {
                translateText
                    .switchLanguage(translateText.targetLanguage,
                        translateText.sourceLanguage)
                    .then((value) {
                  state(() {});
                });
              },
              icon: const Icon(Icons.swap_horizontal_circle)),
          ElevatedText(
              onPressed: () async {
                context.requestFocus();
                final language = await selectLanguage();
                if (language != null &&
                    language != translateText.sourceLanguage &&
                    language != translateText.targetLanguage) {
                  translateText
                      .switchLanguage(translateText.sourceLanguage, language)
                      .then((value) {
                    state(() {});
                  });
                }
              },
              text: translateText.targetLanguage.name),
        ]);
      }),
      ElevatedText(text: 'Translation', onPressed: translation),
      const SizedBox(height: 20),
      ValueListenableBuilder(
          valueListenable: text,
          builder: (_, String value, __) {
            return Universal(
                onLongPress: () {
                  value.toClipboard;
                  showToast('Has been copied');
                },
                alignment: Alignment.center,
                width: double.infinity,
                padding: const EdgeInsets.all(20),
                decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(10)),
                child: BText(value,
                    color: Colors.black, textAlign: TextAlign.center));
          })
    ]);
  }

  Future<void> translation() async {
    if (controller.text.isEmpty) {
      showToast('Please enter the text');
      return;
    }
    context.requestFocus();
    final hasSourceModel =
        await translateText.isModelDownloaded(translateText.sourceLanguage);
    final hasTargetModel =
        await translateText.isModelDownloaded(translateText.targetLanguage);
    if (hasSourceModel && hasTargetModel) {
      final value = await translateText.translate(controller.text);
      if (value != null) text.value = value;
    } else {
      showToast('No download TranslateRemoteModel');
    }
  }

  Future<TranslateLanguage?> selectLanguage() => Container(
      padding: const EdgeInsets.all(20),
      decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.horizontal(
              left: Radius.circular(10), right: Radius.circular(10))),
      child: CustomFutureBuilder<List<TranslateRemoteModel>>(
          future: translateText.getDownloadedModels,
          onWaiting: (_) => const CircularProgressIndicator(),
          onDone: (_, value, __) {
            return ListView.separated(
                itemBuilder: (_, index) {
                  return Universal(
                      onTap: () {
                        pop(value[index].language);
                      },
                      padding: const EdgeInsets.symmetric(vertical: 5),
                      child: BText(value[index].language.toString(),
                          color: Colors.black));
                },
                itemCount: value.length,
                separatorBuilder: (BuildContext context, int index) =>
                    const Divider(thickness: 0.3));
          })).popupBottomSheet(
      options: const BottomSheetOptions(isScrollControlled: false));

  [@override](/user/override)
  void dispose() {
    super.dispose();
    text.dispose();
    translateText.dispose();
  }
}

class TranslateRemoteModelManagerPage extends StatefulWidget {
  const TranslateRemoteModelManagerPage({super.key});

  [@override](/user/override)
  State<TranslateRemoteModelManagerPage> createState() =>
      _TranslateRemoteModelManagerPageState();
}

class _TranslateRemoteModelManagerPageState
    extends State<TranslateRemoteModelManagerPage> {
  List<String> listLanguage = [];

  [@override](/user/override)
  void initState() {
    super.initState();
    addPostFrameCallback((duration) => getDownloadedModels());
  }

  Future<void> getDownloadedModels() async {
    var list = await FlMlKitTranslateText().getDownloadedModels();
    listLanguage = list.builder(
        (item) => FlMlKitTranslateText().toAbbreviations(item.language));
    setState(() {});
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBarText('TranslateRemoteModel Manager'),
        body: ListView.separated(
          padding: const EdgeInsets.symmetric(vertical: 10),
          itemBuilder: (_, int index) {
            var item = TranslateLanguage.values[index];
            var abb = FlMlKitTranslateText().toAbbreviations(item);
            var isDownload = listLanguage.contains(abb);
            return Universal(
                direction: Axis.horizontal,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                padding:
                    const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
                children: [
                  RText(texts: [
                    '${abb.toUpperCase()}  ',
                    item.toString().split('.')[1]
                  ], styles: [
                    TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                        color: context.theme.primaryColor),
                    TextStyle(color: context.theme.primaryColor),
                  ]),
                  ValueBuilder<bool>(builder: (_, bool? isLoading, updater) {
                    isLoading ??= false;
                    if (isLoading) return const CircularProgressIndicator();
                    return isDownload
                        ? ElevatedText(
                            text: 'Delete',
                            onPressed: () async {
                              updater(true);
                              final state = await FlMlKitTranslateText()
                                  .deleteDownloadedModel(item);
                              updater(false);
                              if (state) getDownloadedModels();
                            })
                        : ElevatedText(
                            text: 'Download',
                            onPressed: () async {
                              updater(true);
                              final state = await FlMlKitTranslateText()
                                  .downloadedModel(item);
                              updater(false);
                              if (state) getDownloadedModels();
                            });
                  })
                ]);
          },
          itemCount: TranslateLanguage.values.length,
          separatorBuilder: (BuildContext context, int index) =>
              const Divider(),
        ));
  }
}

class AppBarText extends AppBar {
  AppBarText(String text, {super.key})
      : super(
            elevation: 0,
            title: BText(text, fontSize: 18, fontWeight: FontWeight.bold),
            centerTitle: true);
}

class ElevatedText extends ElevatedButton {
  ElevatedText({super.key, required String text, required super.onPressed})
      : super(child: Text(text));
}

主要功能解释

  1. 初始化翻译插件

    FlMlKitTranslateText translateText = FlMlKitTranslateText();
    
  2. 获取已下载的模型

    remoteModels = await translateText.getDownloadedModels();
    
  3. 下载新的模型

    final state = await translateText.downloadedModel(TranslateLanguage.chinese);
    
  4. 切换翻译语言

    translateText.switchLanguage(sourceLanguage, targetLanguage);
    
  5. 执行翻译

    final translatedText = await translateText.translate(inputText);
    
  6. 释放资源

    [@override](/user/override)
    void dispose() {
      super.dispose();
      translateText.dispose();
    }
    

更多关于Flutter文本翻译插件fl_mlkit_translate_text的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文本翻译插件fl_mlkit_translate_text的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用fl_mlkit_translate_text插件来实现文本翻译的示例代码。这个插件利用Google的ML Kit进行文本翻译,非常适合需要实时翻译功能的应用。

首先,确保你已经在pubspec.yaml文件中添加了fl_mlkit_translate_text依赖:

dependencies:
  flutter:
    sdk: flutter
  fl_mlkit_translate_text: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,是一个完整的示例代码,展示了如何使用fl_mlkit_translate_text插件进行文本翻译:

import 'package:flutter/material.dart';
import 'package:fl_mlkit_translate_text/fl_mlkit_translate_text.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Text Translation Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: TranslateScreen(),
    );
  }
}

class TranslateScreen extends StatefulWidget {
  @override
  _TranslateScreenState createState() => _TranslateScreenState();
}

class _TranslateScreenState extends State<TranslateScreen> {
  final TextEditingController _sourceTextController = TextEditingController();
  final TextEditingController _translatedTextController = TextEditingController();
  String _sourceLanguageCode = 'en';
  String _targetLanguageCode = 'es';
  String _errorMessage = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Text Translation Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            TextField(
              controller: _sourceTextController,
              decoration: InputDecoration(
                labelText: 'Source Text',
              ),
              maxLines: 4,
            ),
            SizedBox(height: 16),
            DropdownButtonFormField<String>(
              value: _sourceLanguageCode,
              hint: Text('Source Language'),
              onChanged: (newValue) {
                setState(() {
                  _sourceLanguageCode = newValue;
                });
              },
              items: [
                'en', 'es', 'fr', 'de', // 添加更多语言代码根据需要
              ].map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value.toUpperCase()),
                );
              }).toList(),
            ),
            SizedBox(height: 16),
            DropdownButtonFormField<String>(
              value: _targetLanguageCode,
              hint: Text('Target Language'),
              onChanged: (newValue) {
                setState(() {
                  _targetLanguageCode = newValue;
                });
              },
              items: [
                'en', 'es', 'fr', 'de', // 添加更多语言代码根据需要
              ].map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value.toUpperCase()),
                );
              }).toList(),
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () async {
                setState(() {
                  _errorMessage = '';
                  _translatedTextController.clear();
                });

                try {
                  final translationResult = await FlutterMlKitTranslateText.translateText(
                    _sourceTextController.text,
                    sourceLanguage: _sourceLanguageCode,
                    targetLanguage: _targetLanguageCode,
                  );
                  _translatedTextController.value = _translatedTextController.value.copyWith(
                    text: translationResult.translatedText,
                  );
                } catch (e) {
                  setState(() {
                    _errorMessage = e.toString();
                  });
                }
              },
              child: Text('Translate'),
            ),
            SizedBox(height: 16),
            if (_errorMessage.isNotEmpty)
              Text(
                _errorMessage,
                style: TextStyle(color: Colors.red),
              ),
            TextField(
              controller: _translatedTextController,
              decoration: InputDecoration(
                labelText: 'Translated Text',
                readOnly: true,
              ),
              maxLines: 4,
            ),
          ],
        ),
      ),
    );
  }
}

这个示例代码包括以下几个部分:

  1. 用户界面:使用TextField来输入源文本,使用DropdownButtonFormField来选择源语言和目标语言。
  2. 翻译功能:点击“Translate”按钮后,调用FlutterMlKitTranslateText.translateText方法进行文本翻译,并将翻译结果显示在另一个TextField中。
  3. 错误处理:如果在翻译过程中发生错误,将错误信息显示在界面上。

请注意,为了使用Google的ML Kit服务,你可能需要在Firebase项目中启用相关服务,并在应用中进行相应的配置。具体配置步骤可以参考fl_mlkit_translate_text插件的官方文档。

回到顶部