Solved: Flutter translate List of strings

Question

Asked by ahmed on September 21, 2022 (source).

I need help, i tried to translate a list of strings in flutter with translator package, but it keep displaying _instance of 'Future<translation>' this is my code:

            ListView.builder(
              itemCount: docs.length,
              itemBuilder: (context, index) {
                translated((docs[index]['tweet']));
                return ListTile(
                  title: Text(
                    docs[index]['name'],
                    style:
                        TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold),
                  ),
                  subtitle: Text(
                      translator.translate(docs[index]['tweet']).toString()),
                );
              },
            );

i tried to use async and await with setState() in a sperated method like this:


String output = "";
  Future<void> translated(String post) async {
    final Translation translation = await translator.translate(post, to: 'en');
    final String out =  translation.toString();
    print(out);
    setState(() {
      output = out;
    });
  }
ListView.builder(
              itemCount: docs.length,
              itemBuilder: (context, index) {
                translated((docs[index]['tweet']));
                return ListTile(
                  title: Text(
                    docs[index]['name'],
                    style:
                        TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold),
                  ),
                  subtitle: Text(output),
                );
              },
            );

It does translate but the value keep on changing infinitly while displaying . this is the full body:

body: Container(
          child: StreamBuilder(
        stream: FirebaseFirestore.instance
            .collection('favorite')
            .doc(userID)
            .collection('Publication')
            .snapshots(),
        builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
          if (snapshot.hasData)  {
            List<dynamic> docs = snapshot.data.docs;
            return FutureBuilder<List<String>>(
                      future: translated(),
                      builder: (context, snapshot) {
                        switch (snapshot.connectionState) {
                          case ConnectionState.waiting:
                            return Text('Loading....');
                          default:
                            if (snapshot.hasError) {
                              return Text('Error: ${snapshot.error}');
                            } else {
                              List<String> data = snapshot.data ?? [];

                              return ListView.builder(
                                itemCount: docs.length,
                                itemBuilder: (context, index) {
                                 
                                  return ListTile(
                                    title: Text(
                                      docs[index]['name'],
                                      style: TextStyle(
                                          fontSize: 15.0,
                                          fontWeight: FontWeight.bold),
                                    ),
                                    subtitle: Text(data[index]),
                                  );
                                },
                              );
                            }
                        }
                      },
                    );
          } else {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      )),
  1. List item

Answer

Question answered by eamirho3ein (source).

When you call translated inside build method, and call setState inside translated, means that you are calling setState inside build method, so you are rebuilding you widget again and again. Change you translated to this:

Future<String> translated(String post) async {
    final Translation translation = await translator.translate(post, to: 'en');
    final String out =  translation.toString();
    print(out);
    return out;
  }

and use it like this:

ListView.builder(
              itemCount: docs.length,
              itemBuilder: (context, index) {
                String output = await translated((docs[index]['tweet']));
                return ListTile(
                  title: Text(
                    docs[index]['name'],
                    style:
                        TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold),
                  ),
                  subtitle: Text(output),
                );
              },
            );

I recommended that you fallow this approach:

FutureBuilder<List<String>>(
                      future: translated(),
                      builder: (context, snapshot) {
                        switch (snapshot.connectionState) {
                          case ConnectionState.waiting:
                            return Text('Loading....');
                          default:
                            if (snapshot.hasError) {
                              return Text('Error: ${snapshot.error}');
                            } else {
                              List<String> data = snapshot.data ?? [];

                              return ListView.builder(
                                itemCount: docs.length,
                                itemBuilder: (context, index) {
                                 
                                  return ListTile(
                                    title: Text(
                                      docs[index]['name'],
                                      style: TextStyle(
                                          fontSize: 15.0,
                                          fontWeight: FontWeight.bold),
                                    ),
                                    subtitle: Text(data[index]),
                                  );
                                },
                              );
                            }
                        }
                      },
                    )

and change your translated to this:

Future<List<String>> translated() async{
    List<String> result = [];
    for (var element in docs) {
      String output = await translated((element['tweet']));
      result.add(output);
    }
    return result;
  }
DART FLUTTER TRANSLATION
SHARE: