Why isn't my translator system working in flutter?

1,173

To some up the debugging process:

  1. hard code a different language to check whether the translations are correctly registered

    MaterialApp(
      locale: Locale('vi'),
      ...
    )
    
  2. If this works, make sure the language is correctly configured for the system. for Chrome:

    • Open the Chrome preferences
    • Search for "Languages"
    • Find "Order languages based on your preference"
    • Sort the preferred language to the top.
Share:
1,173
Trang Nguyen
Author by

Trang Nguyen

Updated on December 31, 2022

Comments

  • Trang Nguyen
    Trang Nguyen over 1 year

    I'm attempt to do a localization translator in flutter for my project. I got help from this tutorial:

    https://resocoder.com/2019/06/01/flutter-localization-the-easy-way-internationalization-with-json/

    But when I run the program, it only show one language even when I change the language in the laptop setting (I use Chrome for debugging so i had to change language from the laptop setting).

    Here's my code:

    MAIN.dart:

    import 'package:final_translating_test/taylake.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    
    import 'app_localizations.dart';
    import 'dakmilprison.dart';
    import 'damw.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          routes: {
            '/1': (context) => TayLake(),
            '/2': (context) => DamW(),
            '/3': (context) => DakMilPrison(),
          },
          supportedLocales: [Locale('en', 'US'), Locale('vi', 'VN')],
          localizationsDelegates: [
            // THIS CLASS WILL BE ADDED LATER
            // A class which loads the translations from JSON files
            AppLocalizations.delegate,
            // Built-in localization of basic text for Material widgets
            GlobalMaterialLocalizations.delegate,
            // Built-in localization for text direction LTR/RTL
            GlobalWidgetsLocalizations.delegate,
          ],
          localeResolutionCallback: (locale, supportedLocales) {
            for (var supportedLocale in supportedLocales) {
              if (supportedLocale.languageCode == locale!.languageCode &&
                  supportedLocale.countryCode == locale.countryCode) {
                return supportedLocale;
              }
            }
    
            return supportedLocales.first;
          },
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({
        Key? key,
      }) : super(key: key);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: [
              Stack(
                children: [
                  Image.network(
                    'https://t4.ftcdn.net/jpg/03/36/07/85/240_F_336078503_3rIlo0PPrbrxyPbR99qXVo6VATqWsHvl.jpg',
                    filterQuality: FilterQuality.high,
                    fit: BoxFit.fitWidth,
                    width: 500,
                  ),
                  ListTile(
                    leading:
                        Icon(Icons.menu_outlined, color: Colors.white, size: 30),
                    trailing: Icon(Icons.verified_user_outlined,
                        size: 30, color: Colors.white),
                  ),
                ],
              ),
              Expanded(
                child: PageView(
                  children: <Widget>[
                    placeButton(
                        context,
                        "titleHoTay",
                        "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLRsM_lVQtJSMBRgTzeyPIrqdeMFV7M3gCzA&usqp=CAU",
                        "/1"),
                    placeButton(
                        context,
                        "titleDapW",
                        "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTabeU7lO71WhEE3EY99nU087Xwlj5PAPd76g&usqp=CAU",
                        "/2"),
                    placeButton(
                        context,
                        "titleNhaNgucDm",
                        "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSzl8XkPISxI0Uqcy0FR6g3cRvtng1Ghu6T9w&usqp=CAUs",
                        "/3")
                  ],
                ),
              ),
            ],
          ),
        );
      }
    }
    
    Widget placeButton(BuildContext context, String name, String image, String id) {
      return Column(children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(130.0, 0.0, 130.00, 0.0),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(20),
            child: SizedBox(
              height: 300,
              width: 400,
              child: GestureDetector(
                onTap: () {
                  Navigator.pushNamed(context, id);
                },
                child: Card(
                  child: ListTile(
                    title: Padding(
                      padding: const EdgeInsets.fromLTRB(20, 5, 20, 0),
                      child: Text(AppLocalizations.of(context)!.translate(name),
                          style: TextStyle(fontFamily: 'Manrope', fontSize: 18)),
                    ),
                    subtitle: Image.network(
                      image,
                      height: 250,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
        Container(
          height: 40,
          width: 200,
          padding: EdgeInsets.only(top: 0),
          color: Colors.white,
          child: ListTile(
            leading: Text(
              "Rating:",
              style: TextStyle(fontFamily: 'Klasik'),
            ),
            trailing: IconButton(
              splashRadius: 20,
              icon: Icon(Icons.star_border_outlined),
              onPressed: () {},
            ),
          ),
        ),
      ]);
    }
    

    APP_LOCALIZATIONS.dart:

    import 'dart:async';
    import 'dart:convert';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    class AppLocalizations {
      final Locale  locale;
    
       AppLocalizations (this.locale);
    
      static AppLocalizations? of(BuildContext context) {
        return Localizations.of<AppLocalizations>(context, AppLocalizations);
      }
    
      static const LocalizationsDelegate<AppLocalizations> delegate =
          _AppLocalizationsDelegate();
    
      late Map<String, String> _localizedStrings;
    
      Future<bool> load() async {
        String jsonString =
            await rootBundle.loadString('lang/${locale.languageCode}.json');
        Map<String, dynamic> jsonMap = json.decode(jsonString);
    
        _localizedStrings = jsonMap.map((key, value) {
          return MapEntry(key, value.toString());
        });
        return true;
      }
    
      String translate(String key) {
        return _localizedStrings[key]!;
      }
    }
    
    class _AppLocalizationsDelegate
        extends LocalizationsDelegate<AppLocalizations> {
      const _AppLocalizationsDelegate();
    
      @override
      bool isSupported(Locale locale) {
        return ['en', 'vi'].contains(locale.languageCode);
      }
    
      @override
      Future<AppLocalizations> load(Locale locale) async {
        AppLocalizations localizations = new AppLocalizations(locale);
        await localizations.load();
        return localizations;
      }
    
      @override
      bool shouldReload(_AppLocalizationsDelegate old) => false;
    }
    

    en.JSON:

    {
        "first_string": "Hello! This is the first message.",
        "second_string": "If this tutorial helps you, give it a like and subscribe to Reso Coder 😉",
        "titleHoTay": "Tay Lake",
        "titleDapW": "W Dam",
        "titleNhaNgucDm": "DakMil Prison",
        "GioiThieu": "Introduction",
        "GioiThieuHoTay": "West Lake Dak Mil is an extremely familiar destination for people in the small town of Dak Mil, which not only plays the role of regulating and creating a balance in the landscape for this beautiful town, but also a tourist destination which attracts young people and tourists by the poetic and peaceful scenery. If you have the opportunity to come to the small town of Dak Mil of Dak Nong province, do not forget to check-in at this extremely hot destination.",
        "LichSu": "History",
        "LichSuHoTay": "West Lake in Dak Mil is a semi-artificial lake, formed in the 1940s. Initially, the lake was planned by the French colonialists to store water for the coffee growing project in Dak Nong. Until 1982, the town continued to invest in expanding the lake surface to better serve the irrigation needs of the people and at the same time become a place to store water from underground aquifers. It is also for this reason that the water here is always blue all year round.",
        "ViTriDiaLy": "Geological Location",
        "ViTriDiaLyDakMil": "The lake is located 67km from the center of Gia Nghia city to the northeast with an area of ​​more than 10km with an open surface area of ​​108ha and the deepest place reaching 17m. Explaining the special name, locals said, this name comes from the location of the lake. Because it is located in the west of the town, many people have called it West Lake, which has become familiar, over time people add the town's name to form the name Tay Dak Mil lake as it is today.",
        "CanhDep":"Beauty scene",
        "CanhDepDakMil":"As the most beautiful lake in Dak Mil town, it is not difficult to understand that West Lake is a familiar destination for tourists as well as locals, especially young people. The scenery at West Dak Mil lake is both beautiful and romantic, even though it is located in the middle of the city. From a distance, this lake is divided into two branches, hugging around the green coffee plantation, reminiscent of the image of a beautiful oasis. The winding roads or the rows of green trees around the lake also contribute to the poetic beauty of the lake.",
        "GioiThieuDapW":"The unique flow and design of the W dam in Dak Nong make tourists excited and curious. This beautiful dam is one of the familiar check-in places for young people every season when the water rises.",
        "LichSuDapW":"W Dak Nong Dam was built in 1999, with an area of ​​about 22 hectares to serve the needs of irrigation and water supply for the lives of local people. Although the original purpose of construction was just to prevent water and serve local life and production, with its unique design, this dam has become a favorite check-in point of local young people as well as tourists when coming to Dak Mil.",
        "ViTriDiaLyDapW":"W Dam is located in Dak Sak village, Dak Mil district. to reach this place you just need to move to Duc Manh junction of Dak Sak village, then go through Nguyen Du school and enjoy the unique yet beautiful scence of Dam W.",
        "CanhDepDapW":"This monumental dam possesses impressive beauty with large streams of water splashing on the spillways, creating an extremely impressive scene. The scenery here is as beautiful as any famous waterfall in Dak Nong, so it attracts more and more tourists to visit. You can check-in at W Dak Nong dam in many different locations from on the shore to the bottom of the spillway, the white foaming strips of water are the perfect background for you to freely pose and take pictures. ravishingly beautiful. With the unique beauty of W Dam as well as the love of tourists from all over the world, the site is being planned to become one of Dak Mil's tourist attractions."
    }
    

    VI.json:

    {
          "first_string": "Xin chào! Đây là tin nhắn đầu tiên. ",
          "second_string": "Nếu hướng dẫn này hữu ích với bạn, hãy like và đăng ký Reso Coder 😉",
          "titleHoTay": "Hồ Tây",
          "titleDapW": "Đập W",
          "titleNhaNgucDm": "Nhà ngục Đắk Mil",
          "GioiThieu": "Giới Thiệu",
          "GioiThieuHoTay": "Hồ Tây Đăk Mil là một điểm đến cực kỳ quen thuộc với người dân tại thị trấn nhỏ Đắk Mil, không chỉ có vai trò điều hòa và tạo sự cân bằng về cảnh quan cho thị trấn xinh đẹp này mà đây còn là điểm đến thu hút các bạn trẻ và du khách bởi khung cảnh thơ mộng và yên bình. Có dịp đến với thị trấn nhỏ Đăk Mil của tỉnh Đắk Nông, bạn đừng quên đến check-in tại điểm đến cực hot này nhé. ",
          "LichSu":"Lịch Sử",
          "LichSuHoTay":"Hồ Tây ở Đăk Mil là hồ nước bán nhân tạo, được hình thành từ những năm 1940. Ban đầu hồ được thực dân Pháp quy hoạch để trữ nước phục vụ cho dự án trồng cafe tại Đắk Nông. Đến năm 1982, thị trấn tiếp tục đầu tư mở rộng mặt hồ để phục vụ tốt hơn nhu cầu tưới tiêu của người dân và đồng thời trở thành nơi dung chứa nước từ các mạch nước ngầm. Cũng chính vì nguyên nhân này mà nước tại đây luôn trong xanh quanh năm. ",
          "ViTriDiaLy":"Vị Trí Địa Lý",
          "ViTriDiaLyDakMil":"Hồ nằm cách trung tâm của thành phố Gia Nghĩa 67km về hướng Đông Bắc với diện tích hơn 10km với diện tích mặt thoáng là 108ha và nơi sâu nhất đạt 17m. Lý giải về cái tên đặc biệt người dân địa phương cho biết, tên gọi này xuất phát từ vị trí của hồ. Do nằm ở phía Tây của thị trấn nên nhiều người đã gọi thành hồ Tây, lâu thành quen, theo thời gian người ta gắn thêm tên thị trấn hình thành nên tên gọi hồ Tây Đăk Mil như hiện tại. ",
          "CanhDep":"Cảnh Đẹp",
          "CanhDepDakMil":"Là hồ nước đẹp bậc nhất thị trấn Đăk Mil, nên không khó hiểu khi hồ Tây chính là điểm đến quen thuộc của du khách cũng như người dân địa phương, nhất là với các bạn trẻ. Khung cảnh ở hồ Tây Đăk Mil vừa đẹp lãng mạn lại có chút gì đó hoang sơ dù nằm giữa phố thị. Nhìn từ xa hồ nước này được chia thành hai nhánh, ôm quanh đồi trồng cafe xanh mướt khiến ta liên tưởng đến hình ảnh của một ốc đảo xinh tươi. Những con đường uốn lượn hay những hàng cây xanh mướt xung quanh hồ cũng góp phần tạo nên vẻ đẹp thơ mộng của hồ.",
          "GioiThieuDapW":"Dòng chảy và thiết kế độc lạ của đập W ở Đăk Nông  khiến các tín đồ du lịch phấn khích lẫn tò mò. Đập nước tuyệt đẹp này là một trong những địa điểm check-in quen thuộc của các bạn trẻ mỗi mùa nước lên. ",
          "LichSuDapW":"Đập W Đăk Nông được xây dựng từ năm 1999, với diện tích khoảng 22 ha để phục vụ cho nhu cầu tưới tiêu, cung cấp nước phục vụ đời sống của đồng bào địa phương. Mặc dù mục đích xây dựng ban đầu chỉ là để ngăn nước và phục vụ đời sống và sản xuất tại địa phương, tuy nhiên với thiết kế độc đáo, đập nước này đã trở thành điểm check-in yêu thích của các bạn trẻ địa phương cũng như du khách khi đến với Đăk Mil.",
          "ViTriDiaLyDapW":"Đập W Đăk Nông tọa lạc tại xã Đăk Săk, huyện Đăk Mil, để đến được địa điểm này bạn chỉ cần di chuyển đến ngã 3 Đức Mạnh của xã Đăk Săk sau đó đi qua ngôi trường Nguyên Du rồi rẽ vào đập W.",
          "CanhDepDapW":"Đập nước hoành tráng này sở hữu vẻ đẹp ấn tượng với những luồng nước lớn bắn tung tóe trên các trụ tràn, tạo nên khung cảnh vô cùng ấn tượng. Khung cảnh ở đây đẹp không kém bất cứ thác nước nổi tiếng nào tại Đăk Nông, nên ngày càng thu hút du khách tìm đến thăm quan. Bạn có thể check-in tại đập W Đăk Nông ở nhiều vị trí khác nhau từ trên bờ đến phía dưới đập tràn, những dải nước tung bọt trắng xóa chính là background hoàn hảo để bạn thỏa sức tạo dáng và thu về những bức ảnh đẹp mê hồn. Trước vẻ đẹp độc đáo của đập W cũng như sự yêu thích của du khách thập phương, địa điểm đang được quy hoạch để trở thành một trong những điểm du lịch của Đắk Mil. "
      }
    

    TayLake,DamW,DakMilPrison.dart:

    import 'package:flutter/material.dart';
    
    import 'app_localizations.dart';
    
    class DamW extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text(AppLocalizations.of(context)!.translate("titleDapW")),
            ),
            body: Scrollbar(
                isAlwaysShown: true,
                showTrackOnHover: true,
                child: SingleChildScrollView(
                    child: Column(
                  children: [
                    printImage("",
                        170.0),
                    printTitle(
                        AppLocalizations.of(context)!.translate("GioiThieu")),
                    printText(
                        AppLocalizations.of(context)!.translate("GioiThieuDapW")),
                    printImage("",
                        180.0),
                    printTitle(
                      AppLocalizations.of(context)!.translate("LichSu")),
                    printText(
                        AppLocalizations.of(context)!.translate("LichSuDapW")),
                    printImage("",
                        
                        180.0),
                    printTitle(
                        AppLocalizations.of(context)!.translate("ViTriDiaLy")),
                    printText(
                        AppLocalizations.of(context)!.translate("ViTriDiaLyDapW")),
                    printImage(
                        "",
                        180.0),
                    printTitle(AppLocalizations.of(context)!.translate("CanhDep")),
                    printText(
                        AppLocalizations.of(context)!.translate("CanhDepDapW")),
                  ],
                ))));
      }
    
      Widget printTitle(String text) {
        return Container(
            child: Text(text,
                style: TextStyle(fontSize: 20, color: Colors.grey.shade800)),
            padding: EdgeInsets.fromLTRB(0, 50, 50, 0));
      }
    
      Widget printText(String text) {
        return Container(
            child: Text(text,
                style: TextStyle(
                    fontSize: 15,
                    color: Colors.grey.shade600,
                    fontFamily: 'Manrope')),
            padding: EdgeInsets.fromLTRB(50, 25, 50, 25));
      }
    
      Widget printImage(String url, double height) {
        return Container(
          constraints: BoxConstraints.tightFor(height: height),
          child: Image.network(url, fit: BoxFit.fitWidth),
        );
      }
    }
    

    Note:

    • I have already imported all the package needed,
    • In fact, TayLake.dart;DamW.dart and DakMilPrison.dart are three different file, but they are basiclly the same format so I just put one of them there. (If you want the code, tell me down below :>)
    • The localization system is not the exact same as the tutorial, I don't know why but the tutorial is not including null safety so I add a lot of "!" and "?" to fix it (may be that's the reason).
    • Herbert Poul
      Herbert Poul over 2 years
      Chrome usually uses it's own language preferences settings, not necessarily that from the operating system. have you tried simply passing in another locale in the MaterialApp whether the problem is that the languages aren't configured properly or whether the system locale does not take effect? something like MaterialApp( locale: Locale('vi'), ... )
    • Trang Nguyen
      Trang Nguyen over 2 years
      Can you tell me a bit more clearly about the "MaterialApp( locale: Locale('vi'), ... )" code that you talk about?
    • Trang Nguyen
      Trang Nguyen over 2 years
      Also It Worked when I follow your advice but now I can't switch language. I can only switch it in the code that you suggest, any help?
    • Herbert Poul
      Herbert Poul over 2 years
      If you can switch language this way, then there is something wrong with how the language is detected. so remove the locale parameter again.. and try to go to the chrome settings and search for "language" - you should see something like "Order languages based on your preference" -- make sure the correct language is moved all the way to the top.
    • Trang Nguyen
      Trang Nguyen over 2 years
      ok ill try to do it
    • Trang Nguyen
      Trang Nguyen over 2 years
      It worked! Thank you for helping. Anyway, can you help me about this problem: stackoverflow.com/questions/68708967/…
    • Herbert Poul
      Herbert Poul over 2 years
      glad it worked. i've summed up the problem below. maybe you can accept my answer. thanks
    • Trang Nguyen
      Trang Nguyen over 2 years
      I'll close it for now.