{"id":16583758,"url":"https://github.com/aloisdeniel/flutter_sheet_localization","last_synced_at":"2026-01-11T04:48:21.460Z","repository":{"id":34641559,"uuid":"180376482","full_name":"aloisdeniel/flutter_sheet_localization","owner":"aloisdeniel","description":"Generate Flutter localization from a simple online Google Sheets.","archived":false,"fork":false,"pushed_at":"2022-11-23T10:26:49.000Z","size":532,"stargazers_count":286,"open_issues_count":29,"forks_count":82,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-03-29T03:11:15.430Z","etag":null,"topics":["csv","excel","flutter","internationalization","localization","localize"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aloisdeniel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-09T13:44:59.000Z","updated_at":"2025-03-23T11:43:00.000Z","dependencies_parsed_at":"2023-01-15T08:15:50.167Z","dependency_job_id":null,"html_url":"https://github.com/aloisdeniel/flutter_sheet_localization","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aloisdeniel%2Fflutter_sheet_localization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aloisdeniel%2Fflutter_sheet_localization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aloisdeniel%2Fflutter_sheet_localization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aloisdeniel%2Fflutter_sheet_localization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aloisdeniel","download_url":"https://codeload.github.com/aloisdeniel/flutter_sheet_localization/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247284953,"owners_count":20913704,"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":["csv","excel","flutter","internationalization","localization","localize"],"created_at":"2024-10-11T22:43:06.784Z","updated_at":"2026-01-11T04:48:21.401Z","avatar_url":"https://github.com/aloisdeniel.png","language":"Dart","readme":"# Flutter Google Sheet localizations generator\n\nGenerates a localizations delegate from an online Google Sheet file.\n\n## Install\n\nAdd the following to your `pubspec.yaml`:\n\n```sh\ndependencies:\n  flutter_sheet_localization: \u003clatest\u003e\n  flutter_localizations:\n    sdk: flutter\n\ndev_dependencies:\n  flutter_sheet_localization_generator: \u003clatest\u003e\n  build_runner: \u003clatest\u003e\n```\n\n### Usage\n\n#### 1. Create a Google Sheet\n\nCreate a sheet with your translations (following the bellow format, [an example sheet is available here](https://docs.google.com/spreadsheets/d/1AcjI1BjmQpjlnPUZ7aVLbrnVR98xtATnSjU4CExM9fs/edit#gid=0)) :\n\n![example](https://github.com/aloisdeniel/flutter_sheet_localization/raw/master/flutter_sheet_localization_generator/example.png)\n\nMake sure that your sheet is shared :\n\n![share](https://github.com/aloisdeniel/flutter_sheet_localization/raw/master/flutter_sheet_localization_generator/share.png)\n\nExtract from the link the `DOCID` and `SHEETID` values : `https://docs.google.com/spreadsheets/d/\u003cDOCID\u003e/edit#gid=\u003cSHEETID\u003e`) :\n\n#### 2. Declare a localization delegate\n\nDeclare the following `AppLocalizationsDelegate` class with the `SheetLocalization` annotation pointing to your sheet in a `lib/localization.dart` file :\n\n```dart\nimport 'package:flutter/widgets.dart';\nimport 'package:flutter/foundation.dart';\nimport 'package:flutter_sheet_localization/flutter_sheet_localization.dart';\n\npart 'localization.g.dart';\n\n@SheetLocalization(\"DOCID\", \"SHEETID\", 1) // \u003c- See 1. to get DOCID and SHEETID\n// the `1` is the generated version. You must increment it each time you want to regenerate\n// a new version of the labels.\nclass AppLocalizationsDelegate\n    extends LocalizationsDelegate\u003cAppLocalizationsData\u003e {\n  const AppLocalizationsDelegate();\n\n  @override\n  bool isSupported(Locale locale) =\u003e localizedLabels.containsKey(locale);\n\n  @override\n  Future\u003cAppLocalizationsData\u003e load(Locale locale) =\u003e\n      SynchronousFuture\u003cAppLocalizationsData\u003e(localizedLabels[locale]!);\n  @override\n  bool shouldReload(AppLocalizationsDelegate old) =\u003e false;\n}\n\n```\n\n#### 3. Generate your localizations\n\nRun the following command to generate a `lib/localization.g.dart` file :\n\n```\nflutter packages pub run build_runner build\n```\n\n#### 4. Configure your app\n\nUpdate your Flutter app with your newly created delegate :\n\n```dart\nMaterialApp(\n    locale: AppLocalizations.languages.keys.first, // \u003c- Current locale\n    localizationsDelegates: [\n    const AppLocalizationsDelegate(), // \u003c- Your custom delegate\n    GlobalMaterialLocalizations.delegate,\n    GlobalWidgetsLocalizations.delegate,\n    ],\n    supportedLocales:\n        AppLocalizations.languages.keys.toList(), // \u003c- Supported locales\n    // ...\n);\n```\n\n#### 5. Display your labels\n\n```dart\nfinal labels = AppLocalizations.of(context);\nprint(labels.dates.month.february);\nprint(labels.templated.hello(firstName: \"World\"));\nprint(labels.templated.contact(Gender.male, lastName: \"John\"));\n```\n\n## Regeneration\n\nBecause of the caching system of the build_runner, it can't detect if there is a change on the distant sheet and it can't know if a new generation is needed.\n\nThe `version` parameter of the `@SheetLocalization` annotation solves this issue.\n\nEach time you want to trigger a new generation, simply increment that version number and call the build runner again.\n\n## Google Sheet format\n\nYou can see [an example sheet here](https://docs.google.com/spreadsheets/d/1AcjI1BjmQpjlnPUZ7aVLbrnVR98xtATnSjU4CExM9fs/edit#gid=0).\n\n### Global format\n\nThe file should have :\n\n* A first header row\n  * Column 0 : \"Key\"\n  * then each supported language code (\"en\", \"fr\", ...)\n* Following rows for labels\n  * Column 0 : the label key (can be a hierarchy, separated by dots)\n  * then each translation based on language code of the column\n\n### Ignoring a column\n\nSometimes you may need to add comments for translators. For this, simply add a column with a name between parenthesis and the column will be completely ignored by the generator.\n\nExample :\n\n\u003e | Key | (Comments) | fr | en |\n\u003e | --- | --- | --- | --- |\n\u003e | example.man(Gender.male) | This is a man title on home page | homme | man |\n\u003e | example.man(Gender.female) | This is a woman title on home page | femme | woman |\n\n### Conditionals\n\nIt is pretty common to have variants of a label based on a condition (for example: Genders, Plurals, ...).\n\nSimply duplicate your entries and end them with `(\u003cConditionName\u003e.\u003cConditionCase)`.\n\n\nExample :\n\n\u003e | Key | fr | en |\n\u003e | --- | --- | --- |\n\u003e | example.man(Gender.male) | homme | man |\n\u003e | example.man(Gender.female) | femme | woman |\n\nSee [example](example) for more details.\n\n#### Plurals\n\nThe conditionals can be used the same way for plurals :\n\nExample :\n\n\u003e | Key | fr | en |\n\u003e | --- | --- | --- |\n\u003e | example.man(Plural.zero) | hommes |\tman |\n\u003e | example.man(Plural.one) | homme | man |\n\u003e | example.man(Plural.multiple) | hommes | men |\n\nFrom your Dart code, you can then define an extension :\n\n```dart\nextension PluralExtension on int {\n  Plural plural() {\n    if (this == 0) return Plural.zero;\n    if (this == 1) return Plural.one;\n    return Plural.multiple;\n  }\n}\n```\n\nSee [example](example) for more details.\n\n### Dynamic labels\n\nYou can insert a `{{KEY}}` template into a translation value to have dynamic labels.\n\nA Dart function will be generated to be used from your code.\n\n```\n/// Sheet\nvalues.hello, \"Hello {{first_name}}!\"\n\n/// Code\nprint(labels.values.hello(firstName: \"World\"));\n```\n\n#### Typed parameters\n\nYou can also add one of the compatible types (`int`, `double`, `num`, `DateTime`) to the parameter by suffixing its key with `:\u003ctype\u003e`.\n\n```\n/// Sheet\nvalues.price, \"The price is {{price:double}}\\$\"\n\n/// Code\nprint(labels.values.price(price: 10.5));\n```\n\n#### Formatted parameters\n\nYou can indicate how the templated value must be formatted by ending the value with a formatting rule in brackets `[\u003crule-key\u003e]`. This can be particulary useful for typed parameters.\n\nThe available formatting rules depend on the type and generally rely on the `intl` package.\n\n\u003e | Type | rule-key| Generated code |\n\u003e | --- | --- | --- |\n\u003e | `double`, `int`, `num` | `decimalPercentPattern`, `currency`, `simpleCurrency`, `compact`, `compactLong`, `compactSimpleCurrency`, `compactCurrency`, `decimalPattern`, `percentPattern`, `scientificPattern` |\t`NumberFormat.\u003crule-key\u003e(...)` |\n\u003e | `DateTime` | Any date format valid pattern  |\t`DateFormat('\u003crule-key\u003e', ...).format(...)` |\n\nExamples:\n\n```\n/// Sheet\nvalues.price, \"Price : {{price:double[compactCurrency]}}\"\n\n/// Code\nprint(labels.values.price(price: 2.00));\n```\n\n```\n/// Sheet\nvalues.today, \"Today : {{date:DateTime[EEE, M/d/y]}}\"\n\n/// Code\nprint(labels.values.today(date: DateTime.now()));\n```\n\n\n## Why ?\n\nI find the Flutter internationalization tools not really easy to use, and I wanted a simple tool for sharing translations. Most solutions also use string based keys, and I wanted to generate pure dart code to improve permormance.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faloisdeniel%2Fflutter_sheet_localization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faloisdeniel%2Fflutter_sheet_localization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faloisdeniel%2Fflutter_sheet_localization/lists"}