i10n_translator 1.2.1

  • Readme
  • Changelog
  • Example
  • Installing
  • 81

i10n_translator #

Supply Translations to your Flutter app.

The idea behind this library package is to allow your app to easily display its text in any number of supported translations. Those translations are stored in a human-readable and easy-to-update format to be accessed by developers and non-developers alike.

Sample App

There is a sample app available to you on Github to see how this library package can be implemented and used in your Flutter app: Shrine MVC

Installing

I don't always like the version number suggested in the 'Installing' page. Instead, always go up to the 'Major' value in the semantic version number when installing my library packages. This means always entering a version number with then two trailing zeros, '.0.0'. This allows you to take in any 'minor' versions introducing new features, or in this case, any 'patch' versions that involves bugfixes. Semantic version numbers are always in this format: major.minor.patch.

  1. patch - I've made bugfixes
  2. minor - I've introduced new features
  3. major - I've essentially made a new app. It's broken backwards-compatibility and has a completely new user experience. You won't get this version until you increment the major number in the pubspec.yaml file.

And so, in this case, add this to your package's pubspec.yaml file instead:

dependencies:
  i10n_translator:^1.0.0

A CSV File

A text file is used to contain the translations separated by commas. It is commonly called a CSV file and is readily recognized by many editors including MS Excel. This allows 'non-developers' for example to easily enter the text translations for your Flutter app. Below is a screenshot of the CSV file named, i10n.csv, displayed in the simple Windows text editor called, Notepad. i10ncsv As you see below, this text file is easily read in by Microsoft Excel presenting the text and its translations in a nice easy-to-read tabular form. You can see there's an English column, a French column and a Spanish column. You're free to insert blank lines, but every column must be filled or it won't be included in your Flutter app. Further note, the text is case-sensitive. i10nExcel Below is a screenshot of the resulting code generated from the CSV file. Note, you do have the option to not generate the code at all and instead have your Flutter app 'read in' this CSV file directly at start up. Thus providing those translations! I'll explain that option later on. For now, let's see how you'd use this generated code below. i10nTrans In the screenshot above, you see there's now a Map object called, i10nWords, that contains all the translations currently available to your Flutter app. The sample app below, for example, takes in that object with an import statement and then supplies that object to the library package's init() function. i10nWords

Example Sample App

As it happens, when you run the sample app, Shrine MVC, you've the means to manually 'switch' between the default text and two translations (French and Spanish). There's a menu option allowing you to do just that. The screenshots below depict the change, for example, from English to French. Notice the labelled names of the photos then change accordingly. i10nShrineMVC Below is the screenshot of the code in the Sample app that displays those items and they're corresponding labels. You can see the default strings, in this case, are in English. However, note when looking at the list of Product objects below, the named parameter, name, is not being supplied a string value directly but are instead being supplied the static function, s(), from the library package, i10n_translator. Which, in turn, takes in the strings. It's there where the translation is performed and returned to the named parameter, name. i10nSFuncs ShrinApp

Keep It Simple

Again, the idea is to provide the translations in a simple text file with its columns delimited by commas. It's assumed the 'default' language is the first column. You would provide those text strings in the app itself to the static function s() or t(). However, they then serve as a 'key' field when reading this CSV file. Again, as a key field, the first column is case-sensitive. i10nTabular Once the translations are ready, you've the option now to generate the code to then supply those translations to your Flutter app. Note, before you can do this, you do have to reference the library package in your pubspec.yaml file. i10npubspecyaml

Type The Command

And so now using your IDE editor terminal window, you're free to reference the specific class in the library package to generate the resulting dart file:

flutter pub run i10n_translator test.csv path/destination/dart file

Simply referencing the class without any arguments, and you will have that class then assume the following input file and resulting dart file:

flutter pub run i10n_translator [i10n.csv] [i10nwords.dart]

Or Not

If you're innately lazy and don't like typing like me, you can, for example, use Android Studio and create a 'Dart command line app' that instead points directly to the library package file, i10n_translator.dart. i10nTranslatorCommand You can see below how that configuration is set up: i10nConfiguration Below is a screenshot of the i10n_translator.dart file being called in the configuration above. You can see there's a main() function there that calls the library package class, I10nTranslator, supplying the two arguments if any to the function, generate(). i10nMain

Just The CSV File

Again, I'm lazy. I don't want to do that 'extra step' of generating the code to display the translations. I've got this CSV file now, and so why don't I just use that file?? You can too! Look at the screenshot of the Sample app below. See what I've done? There's nothing passed into the init() function. i10nShrineApp I simply include that CSV text file as an asset to the Flutter app instead and have the library package read it in at start up to supply the translations. By default, this library package will look for the CSV file in the assets directory under the folder, i10n: assets/i10n/i10n.csv. And so, you then specify that location and file in the pubspec.yaml file. i10nCSVYaml

1.2.1 #

October 24, 2019

  • if (_csvFile != null && _csvFile.isNotEmpty) {

1.2.0 #

October 24, 2019

  • load the app's locale, if (I10n._locale == null)
  • path: ^1.0.0
  • test cvs: parameter in init()
  • removed \nList
  • a second example, main02.dart, in Github repository
  • use the function, getExternalStorageDirectory();

1.1.3 #

October 20, 2019

  • Supply an example
  • Updated README.md

1.1.2 #

October 20, 2019

  • Updated README.md

1.1.1 #

October 18, 2019

  • Add main() to i10n_translator.dart
  • Remove the bin folder

1.1.0 #

October 17, 2019

  • Renamed from i18n to i10n
  • Removed Locale properties for getter, locale

1.0.0 #

October 16, 2019

  • Initial Production Release
  • Remove the functions, _jsonFiles(), jsonEncode() and jsonDecode()
  • targetPath = "i18n_words.dart";

0.1.0 #

October 15, 2019

  • Initial commit

example/lib/main.dart

import 'package:flutter/material.dart';

import 'package:flutter_localizations/flutter_localizations.dart'
    show
        GlobalCupertinoLocalizations,
        GlobalMaterialLocalizations,
        GlobalWidgetsLocalizations;

import 'package:prefs/prefs.dart' show Prefs;

import 'package:i10n_translator/i10n.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<bool>(
      future: init(),
      initialData: false,
      builder: (_, snapshot) {
        return snapshot.hasData && snapshot.data
            ? MaterialApp(
                title: 'Flutter Demo',
                debugShowCheckedModeBanner: false,
                theme: ThemeData(
                  primarySwatch: Colors.blue,
                ),
                localizationsDelegates: [
                  GlobalMaterialLocalizations.delegate,
                  GlobalWidgetsLocalizations.delegate,
                  GlobalCupertinoLocalizations.delegate,
                  I10nDelegate(),
                ],
                supportedLocales: I10n.supportedLocales,
                localeListResolutionCallback:
                    (List<Locale> locales, Iterable<Locale> supportedLocales) {
                  String locale = Prefs.getString('locale');
                  return locale.isEmpty ? locales.first : Locale(locale);
                },
                home: MyHomePage(title: 'Flutter Demo Home Page'))
            : Center(child: const CircularProgressIndicator());
      },
    );
  }

  Future<bool> init() async {
    // Initialize the library packages
    await Prefs.init();
    return I10n.init();
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter;

  void initState() {
    super.initState();
    _counter = Prefs.getInt('counter');
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
    Prefs.setInt('counter', _counter);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: I10n.t(widget.title),
        actions: [
          menuButton(),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            I10n.t(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: I10n.s('Increment'),
        child: const Icon(Icons.add),
      ),
    );
  }

  PopupMenuButton<String> menuButton() {
    return PopupMenuButton<String>(
      onSelected: (String value) {
        I10n.load(Locale(value));
        Prefs.setString('locale', value);
        setState(() {});
      },
      itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
        const PopupMenuItem<String>(value: 'en', child: Text('en')),
        const PopupMenuItem<String>(value: 'fr', child: Text('fr')),
        const PopupMenuItem<String>(value: 'es', child: Text('es')),
        const PopupMenuItem<String>(value: 'de', child: Text('de')),
        const PopupMenuItem<String>(value: 'zh', child: Text('zh')),
        const PopupMenuItem<String>(value: 'ru', child: Text('ru')),
        const PopupMenuItem<String>(value: 'he', child: Text('he')),
        const PopupMenuItem<String>(value: 'fa', child: Text('fa')),
      ],
    );
  }

  void dispose() {
    Prefs.dispose();
    super.dispose();
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  i10n_translator: ^1.2.1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:i10n_translator/i10n_translator.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
62
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
81
Learn more about scoring.

We analyzed this package on Jul 8, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

because of import path [i10n_translator] that is in a package requiring null.

Package not compatible with runtime flutter-web on web

Because of the import of dart:io via the import chain package:i10n_translator/i10n_translator.dartpackage:i10n_translator/src/i10n_translator.dartdart:io

Health suggestions

Fix lib/src/i10n.dart. (-0.50 points)

Analysis of lib/src/i10n.dart reported 1 hint:

line 405 col 23: The declaration 'getTextFileFromAssets' isn't referenced.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0
csv ^4.0.0 4.0.3
flutter 0.0.0
path ^1.0.0 1.7.0
path_provider ^1.0.0 1.6.11
Transitive dependencies
collection 1.14.12 1.14.13
file 5.2.1
intl 0.16.1
meta 1.1.8 1.2.1
path_provider_linux 0.0.1+2
path_provider_macos 0.0.4+3
path_provider_platform_interface 1.0.2
platform 2.2.1
plugin_platform_interface 1.0.2
process 3.0.13
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8
xdg_directories 0.1.0
Dev dependencies
flutter_test