/Fluent

A Flutter package that helps you build multi-language apps via code generation techniques

Primary LanguageDartMIT LicenseMIT

MIT License

Introduction

What is Fluent?

It’s a Flutter package that helps you handling your project translations via code generation techniques.

Why Fluent?

Fluent came to get rid of the boilerplate code that the developers used to write to build translations into their apps. It wasn't coding at all more than time wasting and totally error prone process. So why not let the machine does it?!

Installation

dependencies:
  fluent_translator: [latest-version]

dev_dependencies:
  fluent_translator_generator: [latest-version]
  build_runner:

Setup and Usage


Create a placeholder class and annotate it with @Fluent which takes:

  • A list of Translatable objects (in case you'll provide your translations manually)
  • A CSV file path (in case your translations will be provided fromCSV)
  • A list of locales for the supported languages as a required argument.
  • A fallback language as a required argument.

Note: In case of loading translations from a CSV file. Please consider to declare it first in the assets section of your project pubspec.yaml file.

/// In case loading translations from a CSV file

@Fluent(
  fromCSV: 'assets/csv_test.csv',
  fallbackLanguage: 'ar',
  supportedLanguages: ['ar', 'en', 'fr']
)
class Translations {}

/// In case manually provide the traslations into [Translatable] objects
@Fluent(
  fallbackLanguage: 'ar',
  supportedLanguages: [
    'ar',
    'en',
    'fr',
  ],
  translations: [
    Translatable(
      arabic: 'مرحبا',
      english: 'Hello',
      french: 'Salut',
      fieldName: 'helloText',
    )
  ],
)
class Translations {}

Note: In case of providing both CSV file & a list of Translatable objects. Fluent is designed to overwrite the content of the Translatables with the CSV file content. It will not add content from both resources.

Note: Make sure that you're using a valid ISO-639-1 locale codes in the supportedLanguages list. You can find a full list here

Lastly, You need to launch build_runner to start translations code generation using command flutter pub run build_runner build for a single time or using command flutter pub run build_runner watch to keep tracking the changes in the file system and automatically update the translations.

CSV file content structure

For your CSV file be parsed correctly. You need to struct its content in a unified way according to the following rules

  • Starting from cell A1, add all your locales in the first cell of each column (e.g.: ar, en, fr,...etc)
  • After the last locale cell directly, add additional cell with text "fieldName"
  • List all your translations of a certain language in the column related to its locale. (e.g.: Arabic translations in ar column)
  • list the unique correspondant field name to each translation in fieldName column. If any field name duplicated in this column that will lead to errors in code generation process.
  • If you need to add extra information in your CSV file, Skip one column empty next to the right of fieldName column. Any type of data will be added next to the empty column will be ignored and won't be parsed in any form into code.
  • Make sure that no empty columns added between locales columns or before fieldName column
  • Make sure that fieldName spelling and format (Camelcase) is correct.

For full CSV file example, kindly download this CSV file example

Working with Language Manager

Fluent is designed not to only generate your translations for different locales. It also generates a Language Manager that orchestrate the locale changes against the available translations during your app lifetime.

Fetch initial language

LanguageManager class includes init() function that will by default fetch your device current language and set as your locale. If you need the language manager to look into your local cache system (e.g.: Shared Preferences) you can pass named argument LanguageSource.LOCAL_CACHE as you can change it anytime to LanguageSource.DEVICE to reset default settings.

Detect locale changes at runtime

LanguageManager will help you listen to any locale runtime changes by providing onLanguageChanged() that passes a string value for the updated locale code. It's recommended to implement it at the earliest point of your app (e.g.: MyApp class). If you're using any previous language stream listeners, onLanguageChanged() can replace it peacefully without a noticeable breaking change. It's worth mentioning that you can use LanguageManager.currentCode getter to get the most recent locale anywhere in your app.

Update remote server locale

LanguageManager is equipped with setServerLocale() function that is able to update your logged in entity (e.g.: customer, user, ..etc) on the server database so that all future results fetched from server should be translated into your updated language locale. You'll need to provide setServerLocale() with some arguments to help it do its job. languageNodeName, locale and id are required arguments to execute the server request. Meanwhile, you can tell LanguageManager to cache this lacale by setting locallyCached argument to true as it will NOT cache your locales by default to save resources and perform faster.

Release resources

All LanguageManager's streams and listeners could be unsubscribed hence released from memory easily by dart garbage collector (DGC) by simply calling dispose() function. Unlike Init(), it's recommended to call dispose() at the latest point of your app which is usually the dispose() function of MyApp class widget