{"id":19056361,"url":"https://github.com/lamnhan066/language_helper","last_synced_at":"2025-04-24T04:34:38.926Z","repository":{"id":62727729,"uuid":"562049819","full_name":"lamnhan066/language_helper","owner":"lamnhan066","description":"Localization for Flutter app with an efficient generator and a custom GPT-4 translator for easy localization.","archived":false,"fork":false,"pushed_at":"2024-11-01T02:03:49.000Z","size":339,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-30T06:51:16.208Z","etag":null,"topics":["dart","flutter","i18n","localization","package"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/language_helper","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lamnhan066.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-05T06:23:08.000Z","updated_at":"2025-03-04T01:22:39.000Z","dependencies_parsed_at":"2023-12-30T17:27:23.306Z","dependency_job_id":"35106faf-3425-458d-bf4d-f29f09308b42","html_url":"https://github.com/lamnhan066/language_helper","commit_stats":null,"previous_names":["lamnhan066/language_helper"],"tags_count":69,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamnhan066%2Flanguage_helper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamnhan066%2Flanguage_helper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamnhan066%2Flanguage_helper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lamnhan066%2Flanguage_helper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lamnhan066","download_url":"https://codeload.github.com/lamnhan066/language_helper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250566144,"owners_count":21451225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","flutter","i18n","localization","package"],"created_at":"2024-11-08T23:49:10.262Z","updated_at":"2025-04-24T04:34:38.902Z","avatar_url":"https://github.com/lamnhan066.png","language":"Dart","funding_links":[],"categories":["Dart"],"sub_categories":[],"readme":"# Language Helper\n\n[![codecov](https://codecov.io/gh/lamnhan066/language_helper/graph/badge.svg?token=AIGGNCGOVR)](https://codecov.io/gh/lamnhan066/language_helper)\n\nMulti-language app tool with an efficient generator and a custom GPT-4 translator for easy localization.\n\n## Features\n\n- Easy to control the language translations in your application. Automatically uses the current device locale upon first open, if possible.\n\n- You can completely control the translated text with `LanguageConditions`.\n\n- Supports analyzing which text is missing in a specific language or is in your app but not in your language data, and vice versa.\n\n- 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).\n\n- A `Language Helper Translator` on Chat GPT-4 that make it easier to translate the language data to a destination language.\n\n## Contents\n\n- [Set Up](#set-up): Only this step is required while developing\n  - [Add The language_helper To The Project](#add-the-language_helper-to-the-project)\n  - [Add An Empty LanguageHelper While Developing](#add-an-empty-languagehelper-while-developing)\n  - [Add `.tr` Or `.trP` To All Needed `String`s](#add-tr-or-trp-to-all-needed-strings)\n- [Generator Flow Usage](#generator-flow-usage)\n  - [Dart Map](#dart-map)\n  - [JSON](#json)\n- [Manual Flow Usage](#manual-flow-usage)\n  - [Create The Translations](#create-the-translations)\n  - [Add To The Project](#add-to-the-project)\n- [Using `LanguageBuilder` To Update The `String`s](#using-languagebuilder-to-update-the-strings)\n- [Control The Translation](#control-the-translation)\n  - [Change The Language](#change-the-language)\n  - [Add A New Language Data](#add-a-new-language-data)\n  - [Get The List Of Supported Language Code](#get-the-list-of-supported-language-code)\n  - [Listen To The Language Changing State](#listen-to-the-language-changing-state)\n- [Advanced Language Helper Generator](#advanced-language-helper-generator)\n  - [Modify The Input Path](#modify-the-input-path)\n  - [Modify The Output Path](#modify-the-output-path)\n  - [Convert From `LanguageData` to `JSON`](#convert-from-languagedata-to-json)\n- [Language Data Serialization](#language-data-serialization)\n- [Language Helper Translator (A Custom Chat GPT-4)](#language-helper-translator-a-custom-chat-gpt-4)\n- [Additional Information](#additional-information)\n- [Contributions](#contributions)\n\n## Set Up\n\nWhile developing, we just need to finish the [Set Up](#set-up) steps. All other steps can be done when the app is ready to implement the localizations.\n\n### Add The language_helper To The Project\n\n```shell\nflutter pub add language_helper\n```\n\n### Add An Empty LanguageHelper While Developing\n\n```dart\nfinal languageHelper = LanguageHelper.instance;\n\nmain() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await languageHelper.initial(data: []);\n  runApp(const MyApp());\n}\n```\n\n### Add `.tr` Or `.trP` To All Needed `String`s\n\nNormal translation\n\n```dart\nText('Translate this text'.tr)\n```\n\nTranslate with parameters\n\n```dart\nText('Hello @{name}'.trP({'name': name}))\n```\n\nPlural (Read [Manual Flow Usage](#manual-flow-usage) to know how to use it)\n\n```dart\nText('We have @{number} dollar'.trP({'number': number}))\n```\n\n### iOS configuration\n\nAdd the supported localizations to the `Infi.plist`. For instance with `en` and `vi` supported:\n\n```plist\n\u003ckey\u003eCFBundleLocalizations\u003c/key\u003e\n\u003carray\u003e\n   \u003cstring\u003een\u003c/string\u003e\n   \u003cstring\u003evi\u003c/string\u003e\n\u003c/array\u003e\n```\n\n## Generator Flow Usage\n\n### Dart Map\n\n**Generate:**\n\n```shell\ndart run language_helper:generate\n```\n\nThe data will be generated in this path by default:\n\n```txt\n|-- .lib\n|   |--- resources\n|   |    |--- language_helper\n|   |    |    |--- language_data.dart\n|   |    |    |--- languages\n|   |    |    |    |--- _generated.dart   ; This file will be overwritten when re-generating\n```\n\n**Implement to your project:**\n\n```dart\nfinal languageHelper = LanguageHelper.instance;\n\nfinal languageDataProvider = LanguageDataProvider.data(languageData);\n\nmain() async {\n  await languageHelper.initial(\n      data: [languageDataProvider],\n  );\n\n  runApp(const MyApp());\n}\n```\n\n### JSON\n\nWhen using JSON, you can store your translation data in `assets` or on network\n\n```shell\ndart run language_helper:generate --json\n```\n\nThe data will be generated in this path by default:\n\n```txt\n|-- assets\n|   |--- resources\n|   |    |--- language_helper\n|   |    |    |--- codes.json\n|   |    |    |--- languages\n|   |    |    |    |--- _generated.json ; This file will be overwritten when re-generating\n```\n\n### Implement to your project\n\n**Define the language data:**\n\n```dart\nfinal languageHelper = LanguageHelper.instance;\n\n// Network\nfinal languageDataProvider = LanguageDataProvider.network('https://example.com/resources');\n\n// Assets\nfinal languageDataProvider = LanguageDataProvider.asset('assets/resources');\n```\n\n**Add to the `LanguageHelper` instance:**\n\n```dart\nfinal languageHelper = LanguageHelper.instance;\n\nmain() async {\n  await languageHelper.initial(\n      data: [languageDataProvider],\n  );\n\n  runApp(const MyApp());\n}\n```\n\n**Combine all of them to improve the translation:**\n\n```dart\nmain() async {\n  await languageHelper.initial(\n      data: [\n        LanguageDataProvider.network('https://example.com/resources'),\n        LanguageDataProvider.asset('assets/resources'),\n        LanguageDataProvider.data(languageData),\n      ],\n  );\n\n  runApp(const MyApp());\n}\n```\n\nThe package will get the translation data in order from top to bottom.\n\n## Manual Flow Usage\n\n### Create The Translations\n\n**Dart Map:**\n\n```dart\nfinal en = {\n  'Translate this text': 'Translate this text',\n  'Hello @{name}': 'Hello @{name}',\n  'We have @{number} dollar': LanguageConditions(\n    param: 'number',\n    conditions: {\n      '0': 'We have zero dollar',\n      '1': 'We have one dollar',\n\n      // Default value.\n      '_': 'We have @{number} dollars',\n    }\n  ),\n};\n\nconst vi = {\n  'Translate this text': 'Dịch chữ này',\n  'Hello @{name}': 'Xin chào @{name}',\n  'We have @{number} dollar': 'Chúng ta có @{number} đô-la', \n};\n\nLanguageData languageData = {\n  LanguageCodes.en: en,\n  LanguageCodes.vi: vi,\n};\n\nfinal languageDataProvider = LanguageDataProvider.data(languageData);\n```\n\nWith `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.\n\n**JSON:**\n\n`assets/resources/language_helper/codes.json`: Contains all language codes\n\n```JSON\n[\"en\", \"vi\"]\n```\n\n`assets/resources/language_helper/languages/en.json`:\n\n```JSON\n{\n  \"Translate this text\": \"Translate this text\",\n  \"Hello @{name}\": \"Hello @{name}\",\n  \"We have @{number} dollar\": {\n    \"param\": \"number\",\n    \"conditions\": {\n      \"0\": \"We have zero dollar\",\n      \"1\": \"We have one dollar\",\n\n      // Default value.\n      \"_\": \"We have @{number} dollars\",\n    }\n  }\n}\n```\n\n`assets/resources/language_helper/languages/vi.json`:\n\n```JSON\n{\n  \"Translate this text\": \"Dịch chữ này\",\n  \"Hello @{name}\": \"Xin chào @{name}\",\n  \"We have @{number} dollar\": \"Chúng ta có @{number} đô-la\", \n}\n```\n\nRemember to add those files to the `pubspec.yaml`:\n\n```yaml\nflutter:\n  assets:\n    - assets/resources/language_helper/codes.json\n    - assets/resources/language_helper/languages/\n```\n\n```dart\nfinal languageDataProvider = LanguageDataProvider.asset('assets/resources');\n```\n\n### Add To The Project\n\n```dart\nfinal languageHelper = LanguageHelper.instance;\n\nmain() async {\n  await languageHelper.initial(\n      data: [languageDataProvider],\n  );\n\n  runApp(const MyApp());\n}\n```\n\n## Using `LanguageBuilder` To Update The `String`s\n\n### In the `MaterialApp`\n\n``` dart\nclass App extends StatelessWidget {\n  const App({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return LanguageBuilder(\n      builder: (context) {\n        return MaterialApp(\n          localizationsDelegates: languageHelper.delegates,\n          supportedLocales: languageHelper.locales,\n          locale: languageHelper.locale,\n          home: const HomePage(),\n        );\n      }\n    );\n  }\n}\n```\n\n### In your `Widget`s\n\n**Using `LanguageBuilder`:**\n\n``` dart\nLanguageBuilder(\n    builder: (context) {\n        return Scaffold(\n          body: Column(\n            children: [\n              Text('Hello @{name}'.tr),\n              Text('We have @{number} dollar'.tr),\n            ],\n          ),\n        );\n    },\n),\n```\n\n**Using `Tr` (A short version of `LanguageBuilder`):**\n\n``` dart\nTr((_) =\u003e Text('Hello @{name}'.tr)),\n```\n\n## Control The Translation\n\n### Change The Language\n\n``` dart\nlanguageHelper.change(LanguageCodes.vi);\n```\n\n### Add A New Language Data\n\n``` dart\nlanguageHelper.addData(LanguageDataProvider.data(newLanguageData));\nlanguageHelper.addDataOverrides(LanguageDataProvider.data(newLanguageDataOverrides));\n```\n\nThe `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.\n\n### Get The List Of Supported Language Code\n\n``` dart\n// List of [LanguageCodes] from both of the [data] and [dataOverrides] without duplicated\nfinal codes = languageHelper.codes;\n\n// List of [LanguageCodes] from the [dataOverrides]\nfinal codesOverrides = languageHelper.codesOverrides;\n```\n\n### Listen To The Language Changing State\n\nBeside the `onChanged` callback, you can listen to the language changed events by using `stream`:\n\n``` dart\nfinal sub = languageHelper.stream.listen((code) =\u003e print(code));\n```\n\n**Note:** Remember to `sub.cancel()` when it's not in use to avoid memory leaks.\n\n### Analyze The Translation\n\n**Currently works properly with `LanguageDataProvider.data` method**\n\n``` dart\nlanguageHelper.analyze();\n```\n\nThis function will automatically be called in `initial` when `isDebug` is `true`.\n\n## Advanced Language Helper Generator\n\n### Modify The Input Path\n\nAdd `--path` option to your command:\n\n```shell\ndart run language_helper:generate --path=./lib\n```\n\n### Modify The Output Path\n\nAdd `--output` option to your command:\n\n```shell\ndart run language_helper:generate --output=./lib/resources\n```\n\n### Convert From `LanguageData` to `JSON`\n\n- Create a `bin` folder in the same level with your `lib`.\n- Create a `export_json.dart` file in your `bin`.\n- Add this code to your `export_json.dart`:\n\n```dart\nvoid main() {\n  test('', () {\n    languageData.exportJson('./assets/resources');\n  });\n}\n```\n\n- Add the missing `import`s.\n- Run `flutter test ./bin/export_json.dart`.\n- The JSON will be generated in this path:\n\n```txt\nassets\n|  |- language_helper\n|  |  |- codes.json\n|  |  |  |- languages\n|  |  |  |  |- en.json\n|  |  |  |  |- vi.json\n|  |  |  |  |- ...\n```\n\n## Language Data Serialization\n\nConvert `LanguageData` to JSON:\n\n``` dart\nfinal json = data.toJson();\n```\n\nConvert JSON to `LanguageData`:\n\n``` dart\nfinal data = LanguageDataSerializer.fromJson(json);\n```\n\n## Language Helper Translator (A Custom Chat GPT-4)\n\n- Assume that here is our language data:\n\n```dart\nfinal en = {\n  'Hello @{name}': 'Hello @{name}',\n  'We have @{number} dollar': LanguageConditions(\n    param: 'number',\n    conditions: {\n      '0': 'We have zero dollar',\n      '1': 'We have one dollar',\n\n      // Default value.\n      '_': 'We have @{number} dollars',\n    }\n  ),\n};\n```\n\n- Go to [Language Helper Translator](https://chat.openai.com/g/g-qoPMopEAb-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).\n- Use this template to translate the data. Be sure to replace `[]` with the appropriate infomation:\n\n```dart\nThis 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]:\n\nfinal en = {\n  'Hello @{name}': 'Hello @{name}',\n  'We have @{number} dollar': LanguageConditions(\n    param: 'number',\n    conditions: {\n      '0': 'We have zero dollar',\n      '1': 'We have one dollar',\n\n      // Default value.\n      '_': 'We have @{number} dollars',\n    }\n  ),\n};\n```\n\n- 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.\n\n## Additional Information\n\n- 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.\n\n- 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`.\n\n- The `LanguageCodes` contains all the common languages with additional information like name in English (englishName) and name in native language (nativeName).\n\n- 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.\n\n- 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.\n\n- The `assets` data is preferred between `assets` and `network` because we still haven't a way to cache it.\n\n- Use the `isInitialized` (bool) and `ensureInitialized` (Future\u003cvoid\u003e) to check whether the `initial` is run.\n\n## Contributions\n\nAs 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flamnhan066%2Flanguage_helper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flamnhan066%2Flanguage_helper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flamnhan066%2Flanguage_helper/lists"}