flutterflutter-getx

update font family based on selected language


Using Flutter and Getx .. i want to update the font family based on selected language .. so if i select english language the font family updated to "Poppins" .. if it arabic the font updated to "Cairo" .. i tried this in controller and the font family changed but the theme did not updated

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initialServices();
  LanguageController controller = Get.put(LanguageController());
  runApp(
    GetMaterialApp(
      themeMode: ThemeMode.light,
      theme: AppTheme.lightTheme,
      darkTheme: AppTheme.darkTheme,
      getPages: AppPages.routes,
      initialRoute: AppPages.INITIAL,
      translations: AppTranslation(),
      locale: controller.initLang,

    ),
  );
}

and the app theme class

class AppTheme {
  AppTheme._();

  static ThemeData lightTheme = _buildLightTheme();
  static ThemeData darkTheme = _buildDarkTheme();

// ---------------- LIGHT THEME ---------------- //
  static ThemeData _buildLightTheme() {
    return ThemeData(
      fontFamily: 'Cairo',
      brightness: Brightness.light,
    );
  }

// ---------------- DARK THEME ---------------- //
  static ThemeData _buildDarkTheme() {
    return ThemeData(
      fontFamily: 'Cairo',
      brightness: Brightness.dark,
    );
  }
}

LanguageController.dart

class LanguageController extends GetxController {
  Locale? initLang;

  AppServices appServices = Get.find();

  changeLang(String languageCode) {
    Locale locale = Locale(languageCode);
    appServices.box.write(AppStorageKeys.lang, languageCode);
    Get.updateLocale(locale);
  }

  @override
  void onInit() {
    String? storedLang = appServices.box.read(AppStorageKeys.lang);
    initLang = _getLocaleFromStoredLang(storedLang) ?? _getDefaultLocale();
    super.onInit();
  }

  /// Get the stored language if it exist
  Locale? _getLocaleFromStoredLang(String? storedLang) {
    return storedLang != null ? Locale(storedLang) : null;
  }

  /// Get the default device language
  Locale _getDefaultLocale() {
    return Locale(Get.deviceLocale!.languageCode);
  }
}

Solution

  • You need to make sure that the ThemeData is updated whenever the language is changed. Currently, the theme is static, so even though you change the language, but the theme isn't being rebuilt.

    Try this...

    //Added fonts into assets folder

    pubspec.yaml

    ...
      assets:
        - assets/fonts/Cairo/
        - assets/fonts/Poppins/
    
      fonts:
        - family: Poppins
          fonts:
            - asset: assets/fonts/Poppins/Poppins-Regular.ttf
            - asset: assets/fonts/Poppins/Poppins-Bold.ttf
              weight: 700
        - family: Cairo
          fonts:
            - asset: assets/fonts/Cairo/Cairo-Regular.ttf
            - asset: assets/fonts/Cairo/Cairo-Bold.ttf
              weight: 700
    

    language_controller.dart

    class LanguageController extends GetxController {
      Locale? initLang;
      RxString fontFamily = 'Cairo'.obs; // Default font family
    
      AppServices appServices = Get.find();
    
      changeLang(String languageCode) {
        Locale locale = Locale(languageCode);
        appServices.box.write(AppStorageKeys.lang, languageCode);
    
        // Update the font family based on the selected language
        if (languageCode == 'ar') {
          fontFamily.value = 'Cairo'; // Arabic font
        } else {
          fontFamily.value = 'Poppins'; // English or other font
        }
    
        Get.updateLocale(locale);
      }
    
      @override
      void onInit() {
        String? storedLang = appServices.box.read(AppStorageKeys.lang);
        initLang = _getLocaleFromStoredLang(storedLang) ?? _getDefaultLocale();
    
        // Set the initial font family based on the stored language
        if (storedLang == 'ar') {
          fontFamily.value = 'Cairo';
        } else {
          fontFamily.value = 'Poppins';
        }
    
        super.onInit();
      }
    
      /// Get the stored language if it exists
      Locale? _getLocaleFromStoredLang(String? storedLang) {
        return storedLang != null ? Locale(storedLang) : null;
      }
    
      /// Get the default device language
      Locale _getDefaultLocale() {
        return Locale(Get.deviceLocale!.languageCode);
      }
    }
    
    

    main.dart

    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await init();
    
      runApp(const MyApp());
    }
    
    Future<void> init() async {
      await GetStorage.init();
      Get.put(AppServices());
      Get.put(LanguageController());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        final controller = Get.find<LanguageController>();
        return Obx(() => GetMaterialApp(
              themeMode: ThemeMode.system,
              theme: AppTheme.lightTheme(controller.fontFamily.value),
              darkTheme: AppTheme.darkTheme(controller.fontFamily.value),
              translations: AppTranslation(),
              locale: controller.initLang,
              home: const HomePage(),
            ));
      }
    }
    
    class HomePage extends StatefulWidget {
      const HomePage({super.key});
    
      @override
      State<HomePage> createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Center(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('welcome'.tr), // For Welcome
                  Text('login'.tr), // For Login
                  Text('logout'.tr), // For Logout
                  Text('profile'.tr), // For View Profile
                  Text('settings'.tr), // For Settings
                  TextButton(
                      onPressed: () {
                        Get.find<LanguageController>().changeLang('en');
                      },
                      child: const Text("Change to EN")),
                  TextButton(
                      onPressed: () {
                        Get.find<LanguageController>().changeLang('ar');
                      },
                      child: const Text("Change to AR")),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    

    app_theme.dart

    class AppTheme {
      AppTheme._();
    
      static ThemeData lightTheme(String fontFamily) {
        return ThemeData(
            fontFamily: fontFamily,
            brightness: Brightness.light,
            scaffoldBackgroundColor: Colors.white);
      }
    
      static ThemeData darkTheme(String fontFamily) {
        return ThemeData(
            fontFamily: fontFamily,
            brightness: Brightness.dark,
            scaffoldBackgroundColor: Colors.black);
      }
    }
    

    app_translations.dart

    
    class AppTranslation extends Translations {
      @override
      Map<String, Map<String, String>> get keys => {
            'en': {
              'welcome': 'Welcome to our app!',
              'login': 'Login',
              'logout': 'Logout',
              'profile': 'View Profile',
              'settings': 'Settings',
              'language_select': 'Select Language',
            },
            'ar': {
              'welcome': 'مرحبًا بك في تطبيقنا!',
              'login': 'تسجيل الدخول',
              'logout': 'تسجيل الخروج',
              'profile': 'عرض الملف الشخصي',
              'settings': 'الإعدادات',
              'language_select': 'اختر اللغة',
            }
          };
    }
    
    

    Here's the result: updating language