Anyone that knows me knows that I love Languages. My first job was at Bachtrack, the world's largest online classical musical listing website, where I was hired to help facilitate the migration into other languages. It was here where I became acutely aware of the issues that come with internationalisation, and why it needs to be dealt with upfront, as had been done at Bachtrack!
Internationalisation, however, goes far beyond just the words on the screen. Think about how the CTAs on a Hebrew or Arabic website change sides, or how the feel of a Japanese website is markedly different to what we are accustomed to here in the West. A lot of frontend styling libraries, like Tailwind and Bootstrap, no longer have a concept of "left" and "right", but rather "start" and "end" to help developers think about Right To Left writing systems. Flutter widgets do the same.
For the text of your website, one can use the builtin translation system, but I wasn't too much of a fan of it. I looked around and found Slang, which felt like I could have my translation strings stored in a fashion similar to what I'm used to in React.


Slang is a "type-safe i18n solution using JSON, YAML or CSV files."


dependencies: ... slang: ^3.23.0 slang_flutter: ^3.23.0 dev_dependencies: ... build_runner: ^2.4.6 slang_build_runner: ^3.23.0
flutter pub get
I used the following configuration so that I could use multiple files (e.g. login.json and dashboard.json all nested under ./libs/i18n/en/).


targets: $default: builders: slang_build_runner: options: base_locale: en fallback_strategy: base_locale input_directory: lib/i18n input_file_pattern: .i18n.json output_directory: lib/i18n output_file_name: translations.g.dart output_format: multiple_files namespaces: true string_interpolation: double_braces


{ "login": "Login", "email": "Email address", "password": "Password" }
Slang compiles your JSON files down to a the builtin translation system, either by running the command dart run slang or by using the build runner flutter pub run build_runner watch --delete-conflicting-outputs. This generates the relevant files which will then allow you to use your new translation strings like so
import 'package:app/i18n/translations.g.dart'; final fieldName =;
Note, .g.dart is a common filename pattern you'll see. It simply means that the file was generated - for which there are a lot of Dart and Flutter packages that want to generate code for you.