0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

NCMBのFlutter SDKを使って翻訳アプリを作る(その2:翻訳画面の構築とDeepLを使った翻訳処理)

Last updated at Posted at 2022-06-20

NCMBでは公式SDKとしてSwift/Objective-C/Kotlin/Java/Unity/JavaScript SDKを用意しています。また、それ以外にもコミュニティSDKとして、非公式ながらFlutter/React Native/Google Apps Script/C#/Ruby/Python/PHPなど幅広い言語向けにSDKが開発されています。

今回はコミュニティSDKの一つ、Flutter SDKとDeepL APIを使って翻訳アプリを作ってみます。前回は画面の仕様とSDKの初期化について解説しましたので、今回は翻訳画面と翻訳処理について解説します。

ncmb | Dart Package

完成版のコード

作成したデモアプリのコードはNCMBMania/flutter_translation_app: Flutter SDKとDeepL APIを組み合わせた翻訳アプリですにアップロードしてあります。

メイン画面について

メイン画面(MyApp)ではFlutterアプリの初期化を行っているだけです。

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Translation App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: MainPage(),
    );
  }
}

MainPageウィジェットについて

MainPageはタブを用意して、翻訳画面と履歴画面をそれぞれ読み込んでいます。

// タブ表示用
class MainPage extends StatelessWidget {
  MainPage({Key? key}) : super(key: key);
  final _tabs = [
    const Tab(icon: Icon(Icons.translate)), // 翻訳画面
    const Tab(icon: Icon(Icons.list)), // 履歴画面
  ];
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: _tabs.length,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('翻訳アプリ'),
            bottom: TabBar(
              tabs: _tabs.toList(),
            ),
          ),
          body: const TabBarView(
            children: [
              TranslationPage(),
              HistoryPage(),
            ],
          ),
        ),
      ),
    );
  }
}

Simulator Screen Shot - iPhone SE (3rd generation) - 2022-06-20 at 16.59.01のコピー.png

TranslationPageについて

TranslationPageは_TranslationPageStateを読み込んでいるだけです。

class TranslationPage extends StatefulWidget {
  const TranslationPage({Key? key}) : super(key: key);
  @override
  State<TranslationPage> createState() => _TranslationPageState();
}

_TranslationPageStateについて

_TranslationPageStateの役割は以下の3つです。

  • 翻訳画面の構築
  • 入力テキストの翻訳とNCMBへの保存
  • 入力テキストの削除
  • 翻訳結果のクリップボードへのコピー
// 翻訳画面
class _TranslationPageState extends State<TranslationPage> {
}

インスタンス変数

用意しているインスタンス変数は次の通りです。

// テキスト編集用コントローラー
final _controller = TextEditingController();
// 翻訳結果が入る変数
var _translateText = "";
// DeepL用ライブラリ
final _translator = Translator(authKey: dotenv.env['DEEPL_AUTH_KEY']!);

画面構築

ColumnとRowを組み合わせているだけなので難しいものではありません。翻訳するボタンをタップした際のイベント _translate と 翻訳結果をクリップボードにコピーする _copyText 、入力テキストを削除する _clearText を呼び出しています。

@override
Widget build(BuildContext context) {
	return Center(
		child: Column(
			mainAxisAlignment: MainAxisAlignment.center,
			children: [
				const Text(
					'翻訳する言葉を入力してください',
				),
				Row(
					mainAxisAlignment: MainAxisAlignment.center,
					children: [
						SizedBox(
							width: 260,
							child: TextFormField(
								onFieldSubmitted: (str) {
									_translate();
								},
								controller: _controller,
								decoration: const InputDecoration(
									hintText: "日本語…",
								),
								keyboardType: TextInputType.multiline,
								maxLines: null,
							),
						),
						TextButton(onPressed: _translate, child: const Text("翻訳する"))
					],
				),
				Padding(
					padding: const EdgeInsets.all(10),
					child: Container(color: Colors.white),
				),
				_translateText != ""
						? Column(
								children: [
									Row(mainAxisAlignment: MainAxisAlignment.center, children: [
										const Text("翻訳結果"),
										TextButton(
												onPressed: _copyText, child: const Icon(Icons.copy)),
										TextButton(
												onPressed: _clearText, child: const Icon(Icons.clear))
									]),
									Text(_translateText),
								],
							)
						: const Text("翻訳結果がこの下に表示されます")
			],
		),
	);
}

Simulator Screen Shot - iPhone SE (3rd generation) - 2022-06-20 at 16.59.01.png

翻訳処理を行う _translate 関数について

翻訳処理は translator.translateTextSingular だけで完結します。2つ目の引数は翻訳後の言語です。翻訳が完了したら、元の日本語とともにニフクラ mobile backendのデータストア(クラウドデータベース)に保存します。その際にはNCMBObjectを利用します。saveメソッドはasync/awaitですが、処理を特に待つ必要はないのでawaitを使っていません。

// 翻訳処理
void _translate() async {
	// 入力されたテキスト(日本語)
	var originalText = _controller.text;
	// DeepLの翻訳処理
	final result =
			await _translator.translateTextSingular(originalText, 'en-US');
	// 結果を入れるデータストアのオブジェクト
	final translate = NCMBObject("Translate");
	// オブジェクトに必要なデータをセット
	translate
		..set("original", originalText)
		..set("translate", result.text);
	// 保存
	translate.save();
	// 画面に翻訳結果を反映
	setState(() {
		_translateText = result.text;
	});
}

Simulator Screen Shot - iPhone SE (3rd generation) - 2022-06-20 at 17.00.13.png

クリップボードへコピーする _copyText 関数について

クリップボードを操作する際には flutter/services が必要です。

import 'package:flutter/services.dart';

そして、以下のようにClipboardクラスにデータを送信します。

// 翻訳結果をクリップボードにコピー
void _copyText() {
	Clipboard.setData(ClipboardData(text: _translateText));
}

入力値をクリアする_clearText関数について

こちらはテキストを削除するだけです。

// 入力、翻訳結果を消す処理
void _clearText() {
	_controller.text = "";
	setState(() {
		_translateText = "";
	});
}

まとめ

今回は翻訳画面の作成と翻訳処理、そしてクリップボードへのコピー処理までを解説しました。次回は翻訳結果の履歴取得と表示までを解説します

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?