Google Translator - Flutter

In this post we are going to learn how use Google Translator in Flutter.

For this we are using translator plugin

Let's start

Step 1: Create flutter application

Step 2: Add dependencies

Add translator plugin in pubspec.yaml file and run flutter pub get

dependencies:
  flutter_sticky_header: "^0.4.2"
  translator: ^0.1.0+7

 

Step 3: Create Language widget

This widget contains all languages list.

LanguagePage.dart
import 'package:flutter/material.dart';
import 'package:flutter_sticky_header/flutter_sticky_header.dart';

import '../models/language.dart';
import '../components/language-list-element.dart';

class LanguagePage extends StatefulWidget {
  LanguagePage({Key key, this.title, this.isAutomaticEnabled})
      : super(key: key);

  final String title;
  final bool isAutomaticEnabled;

  @override
  _LanguagePageState createState() => _LanguagePageState();
}

class _LanguagePageState extends State {
  final TextEditingController _searchTextController = TextEditingController();
  final List _languageList = [
    Language('auto', 'Automatic', false, false, false),
    Language('af', 'Afrikaans', false, false, true),
    Language('sq', 'Albanian', false, false, true),
    Language('am', 'Amharic', false, false, false),
    Language('ar', 'Arabic', false, false, true),
    Language('hy', 'Armenian', false, false, false),
    Language('az', 'Azerbaijani', false, false, false),
    Language('eu', 'Basque', false, false, false),
    Language('be', 'Belarusian', false, false, true),
    Language('bn', 'Bengali', false, false, true),
    Language('bs', 'Bosnian', false, false, false),
    Language('bg', 'Bulgarian', false, false, true),
    Language('ca', 'Catalan', false, false, true),
    Language('ceb', 'Cebuano', false, false, false),
    Language('ny', 'Chichewa', false, false, false),
    Language('zh-cn', 'Chinese Simplified', true, false, true),
    Language('zh-tw', 'Chinese Traditional', false, false, true),
    Language('co', 'Corsican', false, false, false),
    Language('hr', 'Croatian', false, false, true),
    Language('cs', 'Czech', false, false, true),
    Language('da', 'Danish', false, false, true),
    Language('nl', 'Dutch', false, false, true),
    Language('en', 'English', true, true, true),
    Language('eo', 'Esperanto', false, false, true),
    Language('et', 'Estonian', false, false, true),
    Language('tl', 'Filipino', false, false, true),
    Language('fi', 'Finnish', false, false, true),
    Language('fr', 'French', true, true, true),
    Language('fy', 'Frisian', false, false, false),
    Language('gl', 'Galician', false, false, true),
    Language('ka', 'Georgian', false, false, true),
    Language('de', 'German', false, false, true),
    Language('el', 'Greek', false, false, true),
    Language('gu', 'Gujarati', false, false, true),
    Language('ht', 'Haitian Creole', false, false, true),
    Language('ha', 'Hausa', false, false, false),
    Language('haw', 'Hawaiian', false, false, false),
    Language('iw', 'Hebrew', false, false, true),
    Language('hi', 'Hindi', false, false, true),
    Language('hmn', 'Hmong', false, false, false),
    Language('hu', 'Hungarian', false, false, true),
    Language('is', 'Icelandic', false, false, true),
    Language('ig', 'Igbo', false, false, false),
    Language('id', 'Indonesian', false, false, true),
    Language('ga', 'Irish', false, false, true),
    Language('it', 'Italian', false, false, true),
    Language('ja', 'Japanese', false, false, false),
    Language('jw', 'Javanese', false, false, true),
    Language('kn', 'Kannada', false, false, true),
    Language('kk', 'Kazakh', false, false, false),
    Language('km', 'Khmer', false, false, false),
    Language('ko', 'Korean', false, false, true),
    Language('ku', 'Kurdish (Kurmanji)', false, false, false),
    Language('ky', 'Kyrgyz', false, false, false),
    Language('lo', 'Lao', false, false, false),
    Language('la', 'Latin', false, false, false),
    Language('lv', 'Latvian', false, false, true),
    Language('lt', 'Lithuanian', false, false, true),
    Language('lb', 'Luxembourgish', false, false, false),
    Language('mk', 'Macedonian', false, false, true),
    Language('mg', 'Malagasy', false, false, false),
    Language('ms', 'Malay', false, false, true),
    Language('ml', 'Malayalam', false, false, false),
    Language('mt', 'Maltese', false, false, true),
    Language('mi', 'Maori', false, false, false),
    Language('mr', 'Marathi', false, false, true),
    Language('mn', 'Mongolian', false, false, false),
    Language('my', 'Myanmar (Burmese)', false, false, false),
    Language('ne', 'Nepali', false, false, false),
    Language('no', 'Norwegian', false, false, true),
    Language('ps', 'Pashto', false, false, false),
    Language('fa', 'Persian', false, false, true),
    Language('pl', 'Polish', false, false, true),
    Language('pt', 'Portuguese', false, false, true),
    Language('ma', 'Punjabi', false, false, false),
    Language('ro', 'Romanian', false, false, true),
    Language('ru', 'Russian', false, false, true),
    Language('sm', 'Samoan', false, false, false),
    Language('gd', 'Scots Gaelic', false, false, false),
    Language('sr', 'Serbian', false, false, false),
    Language('st', 'Sesotho', false, false, false),
    Language('sn', 'Shona', false, false, false),
    Language('sd', 'Sindhi', false, false, false),
    Language('si', 'Sinhala', false, false, false),
    Language('sk', 'Slovak', false, false, true),
    Language('sl', 'Slovenian', false, false, true),
    Language('so', 'Somali', false, false, false),
    Language('es', 'Spanish', false, false, true),
    Language('su', 'Sundanese', false, false, false),
    Language('sw', 'Swahili', false, false, true),
    Language('sv', 'Swedish', false, false, true),
    Language('tg', 'Tajik', false, false, false),
    Language('ta', 'Tamil', false, false, true),
    Language('te', 'Telugu', false, false, true),
    Language('th', 'Thai', false, false, true),
    Language('tr', 'Turkish', false, false, true),
    Language('uk', 'Ukrainian', false, false, true),
    Language('ur', 'Urdu', false, false, true),
    Language('uz', 'Uzbek', false, false, false),
    Language('vi', 'Vietnamese', false, false, true),
    Language('cy', 'Welsh', false, false, true),
    Language('xh', 'Xhosa', false, false, false),
    Language('yi', 'Yiddish', false, false, false),
    Language('yo', 'Yoruba', false, false, false),
    Language('zu', 'Zulu', false, false, false),
  ];

  @override
  void initState() {
    super.initState();

    // Remove the automatic element if disabled
    if (!this.widget.isAutomaticEnabled) {
      var automaticElement = this
          ._languageList
          .where((language) => language.code == 'auto')
          .toList()[0];
      this._languageList.remove(automaticElement);
    }
  }

  // Send back the selected language
  _sendBackLanguage(Language language) {
    Navigator.pop(context, language);
  }

  // Display the delete text icon if we typed text in the search input
  Widget _displayDeleteTextIcon() {
    if (this._searchTextController.text.length > 0) {
      return IconButton(
        icon: Icon(Icons.close),
        color: Colors.grey,
        onPressed: () {
          setState(() {
            _searchTextController.text = "";
          });
        },
      );
    } else {
      return null;
    }
  }

  // Display the list with header if we are not searching
  // Display the list with only languages if we are searching
  Widget _displayTheRightList() {
    if (this._searchTextController.text == "") {
      return this._displayListWithHeaders();
    } else {
      return this._displaySearchedList();
    }
  }

  // Display the language list filtered
  Widget _displaySearchedList() {
    List searchedList = this
        ._languageList
        .where((e) => e.name
            .toLowerCase()
            .contains(this._searchTextController.text.toLowerCase()))
        .toList();

    // Display
    return Expanded(
      child: ListView.builder(
        itemCount: searchedList.length,
        itemBuilder: (BuildContext ctxt, int index) {
          return LanguageListElement(
            language: searchedList[index],
            onSelect: this._sendBackLanguage,
          );
        },
      ),
    );
  }

  // Display the list with headers, means we are not searching
  Widget _displayListWithHeaders() {
    List recentLanguages =
        this._languageList.where((e) => e.isRecent).toList();

    // Render
    return Expanded(
      child: CustomScrollView(
        slivers: [
          SliverStickyHeader(
            header: Container(
              height: 60.0,
              color: Colors.pink,
              padding: EdgeInsets.symmetric(horizontal: 16.0),
              alignment: Alignment.centerLeft,
              child: Text(
                'Recent Languages',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
            sliver: SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, i) => LanguageListElement(
                      language: recentLanguages[i],
                      onSelect: this._sendBackLanguage,
                    ),
                childCount: recentLanguages.length,
              ),
            ),
          ),
          SliverStickyHeader(
            header: Container(
              height: 60.0,
              color: Colors.pink,
              padding: EdgeInsets.symmetric(horizontal: 16.0),
              alignment: Alignment.centerLeft,
              child: Text(
                'All languages',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
            sliver: SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, i) => LanguageListElement(
                      language: this._languageList[i],
                      onSelect: this._sendBackLanguage,
                    ),
                childCount: this._languageList.length,
              ),
            ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.widget.title),
        elevation: 0.0,
      ),
      body: Column(
        children: [
          Container(
            margin: EdgeInsets.only(
              top: 12.0,
              bottom: 12.0,
              left: 8.0,
              right: 8.0,
            ),
            child: TextField(
              controller: this._searchTextController,
              onChanged: (text) {
                setState(() {});
              },
              decoration: InputDecoration(
                hintText: "Search",
                border: InputBorder.none,
                focusedBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.pink)),
                prefixIcon: Icon(
                  Icons.search,
                  size: 24.0,
                  color: Colors.grey,
                ),
                suffixIcon: this._displayDeleteTextIcon(),
              ),
            ),
          ),
          this._displayTheRightList(),
        ],
      ),
    );
  }
}

 

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

import '../models/language.dart';

class LanguageListElement extends StatefulWidget {
  LanguageListElement({Key key, this.language, this.onSelect})
      : super(key: key);

  final Language language;
  final Function(Language) onSelect;

  @override
  _LanguageListElementState createState() => _LanguageListElementState();
}

class _LanguageListElementState extends State {

  Widget _displayTrailingIcon() {
    if(this.widget.language.isDownloadable) {
      if(this.widget.language.isDownloaded) {
        return Icon(Icons.check_circle);
      } else {
        return Icon(Icons.file_download);
      }
    } else {
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(this.widget.language.name),
      trailing: this._displayTrailingIcon(),
      onTap: () {
        this.widget.onSelect(this.widget.language);
      },
    );
  }
}

 

Language Model class

class Language {
  String name;
  String code;
  bool isRecent;
  bool isDownloaded;
  bool isDownloadable;

  Language(String code, String name, bool isRecent, bool isDownloaded,
      bool isDownloadable) {
    this.name = name;
    this.code = code;
    this.isRecent = isRecent;
    this.isDownloaded = isDownloaded;
    this.isDownloadable = isDownloadable;
  }
}

 

Step 4: Create Language Choose widget

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

import '../models/language.dart';
import '../screens/language-page.dart';

class ChooseLanguage extends StatefulWidget {
  ChooseLanguage({Key key, this.onLanguageChanged}) : super(key: key);

  final Function(Language firstCode, Language secondCode) onLanguageChanged;

  @override
  _ChooseLanguageState createState() => _ChooseLanguageState();
}

class _ChooseLanguageState extends State {
  Language _firstLanguage = Language('en', 'English', true, true, true);
  Language _secondLanguage = Language('te', 'Telugu', true, true, true);

  // Switch the first and the second language
  void _switchLanguage() {
    Language _tmpLanguage = this._firstLanguage;

    setState(() {
      this._firstLanguage = this._secondLanguage;
      this._secondLanguage = _tmpLanguage;
    });

    this.widget.onLanguageChanged(this._firstLanguage, this._secondLanguage);
  }

  // Choose a new first language
  void _chooseFirstLanguage(String title, bool isAutomaticEnabled) async {
    final language = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => LanguagePage(
              title: title,
              isAutomaticEnabled: isAutomaticEnabled,
            ),
      ),
    );

    if (language != null) {
      this.setState(() {
        this._firstLanguage = language;
      });

      this.widget.onLanguageChanged(this._firstLanguage, this._secondLanguage);
    }
  }

  // Choose a new second language
  void _chooseSecondLanguage(String title, bool isAutomaticEnabled) async {
    final language = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => LanguagePage(
              title: title,
              isAutomaticEnabled: isAutomaticEnabled,
            ),
      ),
    );

    if (language != null) {
      this.setState(() {
        this._secondLanguage = language;
      });

      this.widget.onLanguageChanged(this._firstLanguage, this._secondLanguage);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 55.0,
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border(
          bottom: BorderSide(
            width: 0.5,
            color: Colors.grey[500],
          ),
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Expanded(
            child: Material(
              color: Colors.white,
              child: InkWell(
                onTap: () {
                  this._chooseFirstLanguage("Translate from", true);
                },
                child: Center(
                  child: Text(
                    this._firstLanguage.name,
                    style: TextStyle(
                      color: Colors.pink,
                      fontSize: 15.0,
                    ),
                  ),
                ),
              ),
            ),
          ),
          Material(
            color: Colors.white,
            child: IconButton(
              icon: Icon(
                Icons.compare_arrows,
                color: Colors.grey[700],
              ),
              onPressed: this._switchLanguage,
            ),
          ),
          Expanded(
            child: Material(
              color: Colors.white,
              child: InkWell(
                onTap: () {
                  this._chooseSecondLanguage("Translate to", false);
                },
                child: Center(
                  child: Text(
                    this._secondLanguage.name,
                    style: TextStyle(
                      color: Colors.pink,
                      fontSize: 15.0,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

 

Step 5: Create Input Widgets to take text

TranslateInput.dart

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

import '../models/language.dart';

class TranslateInput extends StatefulWidget {
  TranslateInput(
      {Key key,
      this.onCloseClicked,
      this.focusNode,
      this.firstLanguage,
      this.secondLanguage})
      : super(key: key);

  final Function(bool) onCloseClicked;
  final FocusNode focusNode;
  final Language firstLanguage;
  final Language secondLanguage;

  @override
  _TranslateInputState createState() => _TranslateInputState();
}

class _TranslateInputState extends State {
  TextEditingController _textEditingController = TextEditingController();
  String _textTranslated = "";
  GoogleTranslator _translator = new GoogleTranslator();

  _onTextChanged(String text) {
    if (text != "") {
      _translator
          .translate(text,
              from: this.widget.firstLanguage.code,
              to: this.widget.secondLanguage.code)
          .then((translatedText) {
        this.setState(() {
          this._textTranslated = translatedText;
        });
      });
    } else {
      this.setState(() {
        this._textTranslated = "";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150.0,
      color: Colors.white,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Expanded(
            child: Container(
              margin: EdgeInsets.only(left: 16.0),
              child: TextField(
                focusNode: this.widget.focusNode,
                controller: this._textEditingController,
                onChanged: this._onTextChanged,
                decoration: InputDecoration(
                  border: InputBorder.none,
                  suffixIcon: RawMaterialButton(
                    onPressed: () {
                      if (this._textEditingController.text != "") {
                        this.setState(() {
                          this._textEditingController.clear();
                          this._textTranslated = "";
                        });
                      } else {
                        this.widget.onCloseClicked(false);
                      }
                    },
                    child: new Icon(
                      Icons.close,
                      color: Colors.grey,
                    ),
                    shape: new CircleBorder(),
                  ),
                ),
              ),
            ),
          ),
          Divider(),
          Expanded(
            child: Container(
              margin: EdgeInsets.only(left: 16.0),
              child: Align(
                alignment: Alignment.centerLeft,
                child: Text(
                  this._textTranslated,
                  style: TextStyle(color: Colors.pink),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

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

import 'action-button.dart';

class TranslateText extends StatefulWidget {
  TranslateText({Key key, this.onTextTouched}) : super(key: key);

  final Function(bool) onTextTouched;

  @override
  _TranslateTextState createState() => _TranslateTextState();
}

class _TranslateTextState extends State {


  @override
  Widget build(BuildContext context) {
    return Card(
      color: Colors.white,
      margin: EdgeInsets.all(0.0),
      elevation: 2.0,
      child: Container(
        height: 150.0,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: InkWell(
                onTap: () {
                  this.widget.onTextTouched(true);
                },
                child: Container(
                  width: double.infinity,
                  padding:
                  EdgeInsets.only(left: 16.0, right: 16.0, top: 16.0),
                  child: Text(
                    "Enter text",
                    style: TextStyle(
                      color: Colors.grey[700],
                    ),
                  ),
                ),
              ),
            ),

          ],
        ),
      ),
    );
  }
}

 

Step 6: Create Home Page

import 'package:flutter/material.dart';

import '../components/choose-language.dart';
import '../components/translate-text.dart';
import '../components/list-translate.dart';
import '../components/translate-input.dart';
import '../models/language.dart';

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State
    with SingleTickerProviderStateMixin {
  bool _isTextTouched = false;
  Language _firstLanguage = Language('en', 'English', true, true, true);
  Language _secondLanguage = Language('te', 'Telugu', true, true, true);
  FocusNode _textFocusNode = FocusNode();
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(milliseconds: 150),
      vsync: this,
    )..addListener(() {
        this.setState(() {});
      });
  }

  @override
  void dispose() {
    this._controller.dispose();
    this._textFocusNode.dispose();
    super.dispose();
  }

  _onLanguageChanged(Language firstCode, Language secondCode) {
    this.setState(() {
      this._firstLanguage = firstCode;
      this._secondLanguage = secondCode;
    });
  }

  // Generate animations to enter the text to translate
  _onTextTouched(bool isTouched) {
    Tween _tween = SizeTween(
      begin: Size(0.0, kToolbarHeight),
      end: Size(0.0, 0.0),
    );

    this._animation = _tween.animate(this._controller);

    if (isTouched) {
      FocusScope.of(context).requestFocus(this._textFocusNode);
      this._controller.forward();
    } else {
      FocusScope.of(context).requestFocus(new FocusNode());
      this._controller.reverse();
    }

    this.setState(() {
      this._isTextTouched = isTouched;
    });
  }

  Widget _displaySuggestions() {
    if (this._isTextTouched) {
      return Container(
        color: Colors.black.withOpacity(0.4),
      );
    } else {
      return Container();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(this._isTextTouched
            ? this._animation.value.height
            : kToolbarHeight),
        child: AppBar(
          title: Text(widget.title),
          elevation: 0.0,
        ),
      ),
      body: Column(
        children: [
          ChooseLanguage(
            onLanguageChanged: this._onLanguageChanged,
          ),
          Stack(
            children: [
              Offstage(
                offstage: this._isTextTouched,
                child: TranslateText(
                  onTextTouched: this._onTextTouched,
                ),
              ),
              Offstage(
                offstage: !this._isTextTouched,
                child: TranslateInput(
                  onCloseClicked: this._onTextTouched,
                  focusNode: this._textFocusNode,
                  firstLanguage: this._firstLanguage,
                  secondLanguage: this._secondLanguage,
                ),
              ),
            ],
          ),

        ],
      ),
    );
  }
}

 

Step 7: Update main dart file

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Google Translate',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        primaryColor: Colors.blue[600],
      ),
      home: HomePage(title: 'Google Translate'),
    );
  }
}

 

Step 8: Run application

Google Tanslator

 

Language Translator

 

Google Translator