sheety_localization 0.1.3
sheety_localization: ^0.1.3 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 format
of generated Dart files (enabled by default) - Default folder structure if you don't override:
credentials.json
in 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_localization
activated, rundart pub global activate sheety_localization
again 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.json
in 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.,app
will 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 format
on 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.dart
barrel 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.json
in 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
cwd
to 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
(assumingD2
is the source text in English):=IF(ISBLANK(D2), "", GOOGLETRANSLATE(D2, "en", "ru"))
This formula translates the English text to Russian whenever
E2
is 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
E
for 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.json
securely, or inject it as CI secret. - Use
--author
,--comment
, and--modified
flags to annotate generated files for auditing. - If you add or remove columns in the sheet (e.g., adding
fr
for French), delete old ARB files or run the generator with--prefix
set 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 theru
column). - Drag/fill down to apply to all rows.
- Cells with empty
en
will 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
E
forru
). - 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.,