Developing a Flutter app?
Follow these steps to integrate doloc into your workflow and ensure your app is always translated with only one command.
Expect great translations integrated into your workflow, with no extra effort.
Setup Flutter Internationalization
If you already have internationalization configured, you can skip this step and proceed with Add doloc to your workflow.
Flutter uses ARB (Application Resource Bundle) files for internationalization. Follow the official Flutter guide to set up internationalization in your Flutter project.
In short, you’ll need to:
Add the flutter_localizations
Run below command to add the flutter_localizations package to your pubspec.yaml:
In your Dart code, you can access the translations using the AppLocalizations class.
For example:
AppLocalizations.of(context)!.helloWorld
If there is a compile error, make sure to run flutter pub get to (re-)generate the localization files.
Add doloc to your workflow
You can add the following dart script to your project to automate the translation process. This script will call the doloc API and update your ARB files with the translations.
(Alternatively you can also run a curl command to call the doloc API directly.)
import'dart:convert';
import'dart:io';
void main() async {
final sourceFile ='lib/l10n/app_en.arb';
final resultFileEs ='lib/l10n/app_es.arb';
final resultFileFr ='lib/l10n/app_fr.arb';
final apiToken = Platform.environment['API_TOKEN'];
if (apiToken ==null) {
stderr.writeln('Error: provide API_TOKEN as 3rd argument or environment variable!');
exit(1);
}
void updateFile(String targetFile) {
final boundary ='----dartFormBoundary${DateTime.now().millisecondsSinceEpoch}';
final body = StringBuffer();
void addFilePart(String name, String filePath) {
body
..write('--$boundary\r\n')
..write('Content-Disposition: form-data; name="$name"; filename="${filePath.split('/').last}"\r\n')
..write('Content-Type: application/octet-stream\r\n\r\n')
..write(utf8.decode(File(filePath).readAsBytesSync()))
..write('\r\n');
}
addFilePart('source', sourceFile);
addFilePart('target', targetFile);
body.write('--$boundary--\r\n');
final request =await HttpClient().postUrl(Uri.parse('https://api.doloc.io'))
..headers.set(HttpHeaders.contentTypeHeader, 'multipart/form-data; boundary=$boundary')
..headers.set(HttpHeaders.authorizationHeader, 'Bearer $apiToken')
..add(utf8.encode(body.toString()));
final response =await request.close();
if (response.statusCode ==200) {
File(targetFile).writeAsBytesSync(await response.fold<List<int>>([], (p, e) => p..addAll(e)));
print('result written to $targetFile');
} else {
stderr.writeln('Request failed with status: ${response.statusCode}');
await response.transform(utf8.decoder).forEach(stderr.writeln);
exit(2);
}
}
updateFile(resultFileEs);
updateFile(resultFileFr);
}
Make sure to update the translation file paths and to replace Platform.environment['API_TOKEN'] with your API token or set the corresponding environment variable.
The API token can be found or created in your doloc account.
With this setup, you can run
dart run doloc.dart
to translate all new texts into all target languages! 🎉
Running the script
Generally, you should run this script as a developer after adding or updating translations (in your source language file - e.g. lib/l10n/app_en.arb). This ensures that your code always stays in sync with translations and allows you to review them before committing.
Flutter’s hot reload functionality works well with this approach - you can see the translations update in real-time.
Of course, you can also run the script in the CI/CD pipeline - for a detailed discussion, see When to Run doloc?.
Testing your translations
For testing your app in different languages, you can:
When changing texts in the source file (lib/l10n/app_en.arb), one should remove the corresponding texts in the target file(s) (lib/l10n/app_es.arb and lib/l10n/app_fr.arb) to ensure that the translations are updated.
Alternatively, one can manually update the translations in the target file(s), of course.
Storing the API token
Your API tokens generally should not be shared publicly.
Having said that, if your repository is private, it is acceptable to store the API token in your repository.
The worst-case scenario is that others might use your quota, but never access or change any of your data.
Of course, you can always revoke the token and create a new one if needed.
Configuration
The default configurations of doloc work well for Flutter ARB files and cover most use cases.
For advanced configurations, doloc can be configured by passing options in the URL. See Options for general information and ARB Format for ARB-specific options.
Example
Check out our Flutter demo repository to see doloc integrated into a Flutter project with both local and CI workflows ready to use.