sheety_localization 0.2.2
sheety_localization: ^0.2.2 copied to clipboard
A package to generate localization files from Google Sheets. It uses the Google Sheets API to fetch translations and generates Dart localization files for use in Flutter applications.
Sheety Localization #
Sheety Localization is a Dart console script that generates ARB files (Application Resource Bundle) and corresponding Dart localization classes from a Google Sheets spreadsheet. It uses the Google Sheets API to fetch localization tables and produces everything you need to integrate internationalization into your Flutter project.
Features #
- Fetch data from Google Sheets via Service Account credentials.
- Generate ARB files for each language column (e.g.,
en,ru,fr). - Produce a "library barrel" file (e.g.,
localization.dart) that exports generated localization classes. - Generate Dart localization classes under a configurable folder (e.g.,
src/generated). - Flexible directory structure via command-line options:
- Specify credentials JSON path (
--credentials) - Provide the Google Spreadsheet ID (
--sheet) - Configure output directories for ARB files (
--arb) and generated Dart classes (--gen) - Customize ARB filename prefix (
--prefix) - Insert author, comments, last-modified timestamp, and context metadata into generated files
- Specify credentials JSON path (
- Automatic
dart formatof generated Dart files (enabled by default) - Default folder structure if you don't override:
credentials.jsonin the working directory- Library barrel file under
lib/localization.dart - ARB files under
lib/src/l10n/ - Generated Dart classes under
lib/src/generated/
TL;DR #
-
Create a properly formatted Google Sheet with headers:
label | description | meta | en | ru | ... (other locales). -
Generate a Service Account in Google Cloud, enable Sheets API, and share the sheet.
-
Activate Sheety Localization via
dart pub global activate sheety_localization. -
Run the generator:
dart pub global run sheety_localization:generate \ --credentials=credentials.json \ --sheet=<YOUR_SPREADSHEET_ID> \ --lib=lib \ --arb=src/l10n \ --gen=src/generated \ --prefix=app \ --format -
Import/Export the generated barrel file (
lib/localization.dart) in your Flutter project. -
Optionally automate translation formulas, conditional formatting, VS Code tasks, and CI pipelines.
Prerequisites #
-
Dart SDK >= 3.7.0 < 4.0.0
-
Service Account with Google Sheets API enabled:
- Create a new project in Google Cloud Console.
- Enable Google Sheets API for that project.
- Create a Service Account and download its credentials JSON (e.g.,
credentials.json). - Share your spreadsheet with the Service Account's email (visible in the credentials JSON).
-
Google Sheet laid out in the following format (each sheet/tab = one ARB file):
- First row (header) must contain:
label | description | meta | en | ru | es | de | ... (other locales) - Column definitions:
label- key (getter name) for your Dart codedescription- human-readable note (e.g., Button text on login screen)meta- JSON with metadata (e.g., plural rules, date formats, placeholders)en,ru,es,de- one column per locale
- First row (header) must contain:
Installation #
Activate the script globally so you can invoke the generate command from anywhere:
dart pub global activate sheety_localization
Note: If you already have
sheety_localizationactivated, rundart pub global activate sheety_localizationagain to upgrade to the latest version.
Usage #
After activation, run:
dart pub global run sheety_localization:generate --help
This will display the help message with all available options and their descriptions.
Basic Command #
dart pub global run sheety_localization:generate \
--credentials=credentials.json \
--sheet=<YOUR_SPREADSHEET_ID> \
--lib=lib \
--arb=src/l10n \
--gen=src/generated \
--prefix=app \
--format
Option Definitions
--credentials(or-c): Path to your Service Account JSON file. Defaults tocredentials.jsonin the current directory.--sheet(or-s) (required): The Google Spreadsheet ID (found in the sheet's URL, between/d/and/edit).--lib(or-o): Output root folder for the "library barrel" file (localization.dart). Defaults tolib.--arb(or-a): Relative path (under--lib) where ARB files will be written. Defaults tosrc/l10n.--gen(or-g): Relative path (under--lib) where generated Dart classes will be written. Defaults tosrc/generated.--author: String to insert as author in generated ARB files (e.g.,--author="Jane Doe <jane@example.com>").--comment: Description text to include in generated ARB files.--modified: Last modified timestamp for generated ARB files in ISO 8601 (e.g.,2025-06-04T12:30:00Z). Defaults to the current time.--context: Arbitrary string (e.g., version number) to embed in ARB files.--prefix: Prefix for ARB filenames (e.g.,appwill produceapp_en.arb,app_ru.arb, etc.). Defaults toapp.--header: Custom header comment for each generated Dart file. Defaults to// This file is generated, do not edit it manually!.--format/--no-format: Whether to rundart formaton generated Dart code. Enabled by default.
Integration Steps #
-
Prepare your Google Sheet
-
Create a new or reuse an existing Google Sheet.
-
For each sheet/tab within that spreadsheet, set up the header in the first row as follows:
label | description | meta | en | ru | es | de | ... (other locales). -
Each subsequent row represents one localized string:
label: Unique key (used as a Dart getter name).description: Short human-readable note (e.g.,"Login button text").meta: JSON string with any metadata (e.g.,{"plural":"one","other":"{count} items"}).en,ru,es,de, ...: One column per locale.
-
-
Create a Google Cloud project & Service Account
- Go to Google Cloud Console.
- Create a new project or select an existing one.
- Enable the Google Sheets API for that project.
- Create a Service Account under IAM -> Service Accounts.
- Grant it "Viewer" (or higher) access to the target spreadsheet.
- Download the JSON key file (e.g.,
credentials.json).
-
Share your spreadsheet with the Service Account
- In Google Sheets, click Share (top right).
- Add your Service Account's email (from the JSON file) with Viewer or Editor rights.
-
(Optional) Create a dedicated localization Dart package If you want to keep generated localization code in its own package, set up a new Flutter package, for example:
# packages/localization/pubspec.yaml name: localization description: "Localization" version: 0.0.1 environment: sdk: ">=3.7.0 <4.0.0" flutter: ">=3.29.3" dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter- Run
flutter pub get(ordart pub get). - Later, import this package as a dependency in your app, and export the generated
localization.dartbarrel file.
- Run
-
(Optional) Configure a VS Code task If you use VS Code, add a task to automatically generate localization on demand. Create (or edit)
.vscode/tasks.jsonin your package root:{ "version": "2.0.0", "tasks": [ { "label": "Generate Localization", "type": "shell", "command": [ "dart pub global activate sheety_localization", "&& dart pub global run sheety_localization:generate --credentials=credentials.json", "--sheet=1QgD5i0U-va3VrljXw8I3o8FxtMJAqrhk3ybbJ9O5mA4", "--lib=lib", "--arb=src/l10n", "--gen=src/generated", "--prefix=app", "--format" ], "options": { "cwd": "${workspaceFolder}/packages/localization" }, "problemMatcher": [] } ] }- Adjust
--sheet=<YOUR_SPREADSHEET_ID>to match your actual ID. - Change
cwdto point to your localization package location.
- Adjust
-
(Optional) Add automatic translations via Google Sheets formulas If you want to auto-fill missing translations, add a formula in your sheet cells. For example, in column
E2(assumingD2is the source text in English):=IF(ISBLANK(D2), "", GOOGLETRANSLATE(D2, "en", "ru"))This formula translates the English text to Russian whenever
E2is empty. Replace"ru"with any target locale code. -
(Optional) Conditional formatting to highlight missing or machine-translated cells
-
Set up Conditional Formatting in Google Sheets:
- Select all cells in a language column (e.g., column
Efor Russian). - Use a rule like
=ISFORMULA(E2)to gray out any cell where a formula (i.e., machine translation) is used. - Use
=E2=""to highlight cells that are still empty (missing translation).
- Select all cells in a language column (e.g., column
-
-
Run the generator In your terminal (inside the package folder containing
credentials.json), execute:dart pub global activate sheety_localization dart pub global run sheety_localization:generate \ --credentials=credentials.json \ --sheet=<YOUR_SPREADSHEET_ID> \ --lib=lib \ --arb=src/l10n \ --gen=src/generated \ --prefix=app \ --format-
This will produce:
lib/localization.dart(exports all generated classes)- One ARB file per sheet (e.g.,
app_en.arb,app_ru.arb, etc.) underlib/src/l10n/ - One Dart file per locale under
lib/src/generated/(e.g.,app_localizations_en.dart,app_localizations_ru.dart, etc.)
-
-
Add the generated localization package to your app
In your main Dart file (e.g.,
main.dart), import the generated localization and set up the localization delegates at MaterialApp:import 'package:localization/localization.dart'; MaterialApp( // Add generated localization delegate here: localizationsDelegates: const <LocalizationsDelegate<Object?>>[ AppLocalization.delegate, ErrorsLocalization.delegate, SignUpLocalization.delegate, ChatLocalization.delegate, SettingsLocalization.delegate, GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], supportedLocales: const <Locale>[ Locale('en'), Locale('ru'), // Add other supported locales here ], -
Use the generated localization classes in your app
You can now access localized strings from context under the MaterialApp, using the generated localization classes. For example:
String title = AppLocalization.of(context).title;
Directory Structure Example #
After you run the generator with default paths, your package might look like:
.vscode/
tasks.json
packages/
localization/
credentials.json
lib/
localization.dart <- Barrel file (exports generated classes)
src/
l10n/
app_en.arb
app_ru.arb
(other languages)
generated/
app_localizations_en.dart
app_localizations_ru.dart
(other languages)
pubspec.yaml
-
localization.dart:// GENERATED file: localization.dart // This file exports all generated localization classes. export 'src/generated/app_localizations_en.dart'; export 'src/generated/app_localizations_ru.dart'; // ... other exports -
app_en.arb(example):{ "@@locale": "en", "title": "Doctorina", "@title": { "description": "App title" }, "checkVersionUpdateNowButton": "Update Now", "@checkVersionUpdateNowButton": { "description": "Button text to update now" } // ... more key-value pairs for English } -
app_localizations_en.dart(example):// GENERATED CODE - DO NOT MODIFY BY HAND // Author: Jane Doe <jane@example.com> // Generated by sheety_localization on 2025-06-04T15:23:21.739113Z import 'package:flutter/widgets.dart'; import 'package:intl/intl.dart'; import 'package:intl/message_lookup_by_library.dart'; class AppLocalizationsEn { static Future<AppLocalizationsEn> load(Locale locale) { // load logic using ARB data } String get title => "Doctorina"; String get checkVersionUpdateNowButton => "Update Now"; // ... other getters }
(Actual generated Dart code may vary depending on your template and ARB contents.)
Tips & Best Practices #
- Keep your ARB files under version control (for reference and manual tweaks).
- Do not commit service account JSON to public repos. Store
credentials.jsonsecurely, or inject it as CI secret. - Use
--author,--comment, and--modifiedflags to annotate generated files for auditing. - If you add or remove columns in the sheet (e.g., adding
frfor French), delete old ARB files or run the generator with--prefixset to a new value to force regeneration. - To regenerate only a subset of sheets, you can temporarily hide unwanted sheets in Google Sheets, or maintain separate spreadsheets per feature set.
Sample VS Code Task #
Copy the following into .vscode/tasks.json to run generation from the command palette:
{
"version": "2.0.0",
"tasks": [
{
"label": "Generate Localization",
"type": "shell",
"command": [
"dart pub global activate sheety_localization",
"&& dart pub global run sheety_localization:generate --credentials=credentials.json",
"--sheet=1QgD5i0U-va3VrljXw8I3o8FxtMJAqrhk3ybbJ9O5mA4",
"--lib=lib",
"--arb=src/l10n",
"--gen=src/generated",
"--prefix=app",
"--format"
],
"options": {
"cwd": "${workspaceFolder}/packages/localization"
},
"problemMatcher": []
}
]
}
- Open Command Palette -> Tasks: Run Task -> Generate Localization.
Example: Automatic Google Translate Formula #
If you want to auto-fill missing translations from English to Russian:
=IF(ISBLANK(D2), "", GOOGLETRANSLATE(D2, "en", "ru"))
- Place this formula in cell
E2(under therucolumn). - Drag/fill down to apply to all rows.
- Cells with empty
enwill remain blank; otherwise, English text will be machine-translated to Russian.
Example: Conditional Formatting Rules #
-
Gray out machine translations
- Select entire column (e.g., column
Eforru). - Add a custom formula rule:
=ISFORMULA(E2). - Set fill color to light gray.
- Select entire column (e.g., column
-
Highlight empty cells (missing translations)
- Select entire column (e.g.,
E). - Add a custom formula rule:
=E2="". - Set fill color to red (or any noticeable color).
- Select entire column (e.g.,