Last updated:
0 purchases
language helper
Language Helper #
Multi-language app tool with an efficient generator and a custom GPT-4 translator for easy localization.
Features #
Easy to control the language translations in your application. Automatically uses the current device locale upon first open, if possible.
You can completely control the translated text with LanguageConditions.
Supports analyzing which text is missing in a specific language or is in your app but not in your language data, and vice versa.
Supports extracting the needed text for translation from all .dart files in your project with a single command (Not using build_runner nor custom parser so it very fast and reliable).
A Language Helper Translator on Chat GPT-4 that make it easier to translate the language data to a destination language.
Contents #
Set Up: Only this step is required while developing
Add The language_helper To The Project
Add An Empty LanguageHelper While Developing
Add .tr Or .trP To All Needed Strings
Generator Flow Usage
Dart Map
JSON
Manual Flow Usage
Create The Translations
Add To The Project
Using LanguageBuilder To Update The Strings
Control The Translation
Change The Language
Add A New Language Data
Get The List Of Supported Language Code
Listen To The Language Changing State
Advanced Language Helper Generator
Modify The Input Path
Modify The Output Path
Convert From LanguageData to JSON
Language Data Serialization
Language Helper Translator (A Custom Chat GPT-4)
Additional Information
Contributions
Set Up #
While developing, we just need to finish the Set Up steps. All other steps can be done when the app is ready to implement the localizations.
Add The language_helper To The Project #
flutter pub add language_helper
copied to clipboard
Add An Empty LanguageHelper While Developing #
final languageHelper = LanguageHelper.instance;
main() async {
WidgetsFlutterBinding.ensureInitialized();
await languageHelper.initial(data: []);
runApp(const MyApp());
}
copied to clipboard
Add .tr Or .trP To All Needed Strings #
Normal translation
Text('Translate this text'.tr)
copied to clipboard
Translate with parameters
Text('Hello @{name}'.trP({'name': name}))
copied to clipboard
Plural (Read Manual Flow Usage to know how to use it)
Text('We have @{number} dollar'.trP({'number': number}))
copied to clipboard
iOS configuration #
Add the supported localizations to the Infi.plist. For instance with en and vi supported:
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>vi</string>
</array>
copied to clipboard
Generator Flow Usage #
Dart Map #
Generate:
dart run language_helper:generate
copied to clipboard
The data will be generated in this path by default:
|-- .lib
| |--- resources
| | |--- language_helper
| | | |--- language_data.dart
| | | |--- languages
| | | | |--- _generated.dart ; This file will be overwritten when re-generating
copied to clipboard
Implement to your project:
final languageHelper = LanguageHelper.instance;
final languageDataProvider = LanguageDataProvider.data(languageData);
main() async {
await languageHelper.initial(
data: [languageDataProvider],
);
runApp(const MyApp());
}
copied to clipboard
JSON #
When using JSON, you can store your translation data in assets or on network
dart run language_helper:generate --json
copied to clipboard
The data will be generated in this path by default:
|-- assets
| |--- resources
| | |--- language_helper
| | | |--- codes.json
| | | |--- languages
| | | | |--- _generated.json ; This file will be overwritten when re-generating
copied to clipboard
Implement to your project #
Define the language data:
final languageHelper = LanguageHelper.instance;
// Network
final languageDataProvider = LanguageDataProvider.network('https://example.com/resources');
// Assets
final languageDataProvider = LanguageDataProvider.asset('assets/resources');
copied to clipboard
Add to the LanguageHelper instance:
final languageHelper = LanguageHelper.instance;
main() async {
await languageHelper.initial(
data: [languageDataProvider],
);
runApp(const MyApp());
}
copied to clipboard
Combine all of them to improve the translation:
main() async {
await languageHelper.initial(
data: [
LanguageDataProvider.network('https://example.com/resources'),
LanguageDataProvider.asset('assets/resources'),
LanguageDataProvider.data(languageData),
],
);
runApp(const MyApp());
}
copied to clipboard
The package will get the translation data in order from top to bottom.
Manual Flow Usage #
Create The Translations #
Dart Map:
final en = {
'Translate this text': 'Translate this text',
'Hello @{name}': 'Hello @{name}',
'We have @{number} dollar': LanguageCondition(
param: 'number',
conditions: {
'0': 'We have zero dollar',
'1': 'We have one dollar',
// Default value.
'_': 'We have @{number} dollars',
}
),
};
const vi = {
'Translate this text': 'Dịch chữ này',
'Hello @{name}': 'Xin chào @{name}',
'We have @{number} dollar': 'Chúng ta có @{number} đô-la',
};
LanguageData languageData = {
LanguageCodes.en: en,
LanguageCodes.vi: vi,
};
final languageDataProvider = LanguageDataProvider.data(languageData);
copied to clipboard
With LanguageConditions, you can completely control which text is returned according to the parameters' conditions. You can use 'default' or '_' to set the default value for the condition.
JSON:
assets/resources/language_helper/codes.json: Contains all language codes
["en", "vi"]
copied to clipboard
assets/resources/language_helper/languages/en.json:
{
"Translate this text": "Translate this text",
"Hello @{name}": "Hello @{name}",
"We have @{number} dollar": {
"param": "number",
"conditions": {
"0": "We have zero dollar",
"1": "We have one dollar",
// Default value.
"_": "We have @{number} dollars",
}
}
}
copied to clipboard
assets/resources/language_helper/languages/vi.json:
{
"Translate this text": "Dịch chữ này",
"Hello @{name}": "Xin chào @{name}",
"We have @{number} dollar": "Chúng ta có @{number} đô-la",
}
copied to clipboard
Remember to add those files to the pubspec.yaml:
flutter:
assets:
- assets/resources/language_helper/codes.json
- assets/resources/language_helper/languages/
copied to clipboard
final languageDataProvider = LanguageDataProvider.asset('assets/resources');
copied to clipboard
Add To The Project #
final languageHelper = LanguageHelper.instance;
main() async {
await languageHelper.initial(
data: [languageDataProvider],
);
runApp(const MyApp());
}
copied to clipboard
Using LanguageBuilder To Update The Strings #
In the MaterialApp #
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return LanguageBuilder(
builder: (context) {
return MaterialApp(
localizationsDelegates: languageHelper.delegates,
supportedLocales: languageHelper.locales,
locale: languageHelper.locale,
home: const HomePage(),
);
}
);
}
}
copied to clipboard
In your Widgets #
Using LanguageBuilder:
LanguageBuilder(
builder: (context) {
return Scaffold(
body: Column(
children: [
Text('Hello @{name}'.tr),
Text('We have @{number} dollar'.tr),
],
),
);
},
),
copied to clipboard
Using Tr (A short version of LanguageBuilder):
Tr((_) => Text('Hello @{name}'.tr)),
copied to clipboard
Control The Translation #
Change The Language #
languageHelper.change(LanguageCodes.vi);
copied to clipboard
Add A New Language Data #
languageHelper.addData(LanguageDataProvider.data(newLanguageData));
languageHelper.addDataOverrides(LanguageDataProvider.data(newLanguageDataOverrides));
copied to clipboard
The addData and addDataOverrides have activate parameter which automaticaly rebuild all needed LanguageBuilder, so notice that you may get the setState issue because of the rebuilding of the LanguageBuilder when it's still building. If the error occurs, you may need to set it to false and activate the new data yourself by using reload method.
Get The List Of Supported Language Code #
// List of [LanguageCodes] from both of the [data] and [dataOverrides] without duplicated
final codes = languageHelper.codes;
// List of [LanguageCodes] from the [dataOverrides]
final codesOverrides = languageHelper.codesOverrides;
copied to clipboard
Listen To The Language Changing State #
Beside the onChanged callback, you can listen to the language changed events by using stream:
final sub = languageHelper.stream.listen((code) => print(code));
copied to clipboard
Note: Remember to sub.cancel() when it's not in use to avoid memory leaks.
Analyze The Translation #
Currently works properly with LanguageDataProvider.data method
languageHelper.analyze();
copied to clipboard
This function will automatically be called in initial when isDebug is true.
Advanced Language Helper Generator #
Modify The Input Path #
Add --path option to your command:
dart run language_helper:generate --path=./lib
copied to clipboard
Modify The Output Path #
Add --output option to your command:
dart run language_helper:generate --output=./lib/resources
copied to clipboard
Convert From LanguageData to JSON #
Create a bin folder in the same level with your lib.
Create a export_json.dart file in your bin.
Add this code to your export_json.dart:
void main() {
test('', () {
languageData.exportJson('./assets/resources');
});
}
copied to clipboard
Add the missing imports.
Run flutter test ./bin/export_json.dart.
The JSON will be generated in this path:
assets
| |- language_helper
| | |- codes.json
| | | |- languages
| | | | |- en.json
| | | | |- vi.json
| | | | |- ...
copied to clipboard
Language Data Serialization #
Convert LanguageData to JSON:
final json = data.toJson();
copied to clipboard
Convert JSON to LanguageData:
final data = LanguageDataSerializer.fromJson(json);
copied to clipboard
Language Helper Translator (A Custom Chat GPT-4) #
Assume that here is our language data:
final en = {
'Hello @{name}': 'Hello @{name}',
'We have @{number} dollar': LanguageCondition(
param: 'number',
conditions: {
'0': 'We have zero dollar',
'1': 'We have one dollar',
// Default value.
'_': 'We have @{number} dollars',
}
),
};
copied to clipboard
Go to Language Helper Translator. You should open a New Chat a few times to let the AI read the instructions carefully to improve the translation (just my personal experience).
Use this template to translate the data. Be sure to replace [] with the appropriate infomation:
This is the translation of the [app/game] that [purpose of the app/game to help the AI understand the context]. Translate it into [destination language]:
final en = {
'Hello @{name}': 'Hello @{name}',
'We have @{number} dollar': LanguageCondition(
param: 'number',
conditions: {
'0': 'We have zero dollar',
'1': 'We have one dollar',
// Default value.
'_': 'We have @{number} dollars',
}
),
};
copied to clipboard
The GPT will keeps all keys and comments in their original text, positions them exactly as they appear in the source, keeps the @{param} and @param in their appropriate places during the translation.
Additional Information #
The app will try to use the Devicelocale to set the initialCode if it is not set. If the Devicelocale is unavailable, it will use the first language in data instead.
No matter how many LanguageBuilder that you use, the plugin only rebuilds the outest (the root) widget of LanguageBuilder, so it significantly improves performance. If you want to force rebuild some Widget, you can set the forceRebuild parameter in the LanguageBuilder to true.
The LanguageCodes contains all the common languages with additional information like name in English (englishName) and name in native language (nativeName).
The @{param} works in all cases (We should use this way to avoid issues when translating with Language Helper Translator). The @param only work if the text ends with a white space, end of line, or end with a new line.
The addData and addDataOverrides have activate parameter which automaticaly rebuild all needed LanguageBuilder, so notice that you may get the setState issue because of the rebuilding of the LanguageBuilder when it's still building. If the error occurs, you may need to set it to false and activate the new data yourself by using reload method.
The assets data is preferred between assets and network because we still haven't a way to cache it.
Use the isInitialized (bool) and ensureInitialized (Future
Contributions #
As the project is currently in its early stages, it may contain bugs or other issues. Should you experience any problems, we kindly ask that you file an issue to let us know. Additionally, we welcome contributions in the form of pull requests (PRs) to help enhance the project.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.