SheetGlot
Lightweight Google Sheets localization for Unity. No Google Cloud, API keys, or manual JSON. Paste your Sheets link, import translations, and use plurals, placeholders, validation, and type-safe keys.
$17.00
SheetGlot
Keep your game's translations in a Google Sheets spreadsheet and sync them to your project with a single click. No complex setup, no proprietary formats: just a spreadsheet your team already knows and fast JSON files your game loads locally.
Battle-tested in production: SheetGlot powers the localization of EraClicker, a live commercial game. Every bug, edge case, and optimization was found and fixed in a real-world environment with actual players.
Key Features
- One-click import directly from a Google Sheets sharing link
- Automatic language detection from spreadsheet headers
- CLDR-based plural support, including Russian, Arabic, Polish, Portuguese and more
- Searchable key picker with live validation on every [TranslationKey] field
- Editor preview: see translations in the Scene view without entering Play Mode
- Ready-to-use components for uGUI Text and TextMeshPro
- Fallback language system and system language auto-detection
- Optional PlayerPrefs persistence for the player language choice
- Validation window with per-language coverage, missing-key and duplicate-key checks
- TranslationKeys.cs generator for type-safe key access in code
- Android and WebGL compatible; no internet needed at runtime
Welcome to SheetGlot
Thank you for choosing SheetGlot! This asset is designed to solve a single problem with excellence: keeping your game's translations synchronized with a Google Sheets spreadsheet, without the complexity of a heavy localization framework.
Your translators work in a spreadsheet they already know, and with a single click, SheetGlot turns it into fast, flat JSON files that your game can load instantly, featuring CLDR-based plural support for supported languages, including those with complex plural rules like Portuguese, Russian, Arabic, and Polish. Whether you are localizing a small indie project or a game launched in 15 languages, SheetGlot is built to stay out of your way and just work.
System requirements: SheetGlot requires Unity 2022.3 LTS or higher. It is compatible with the Built-in, Universal (URP), and High Definition (HDRP) render pipelines, and works on Windows, macOS, Linux, Android, and WebGL.
Quick start (3 steps)
Step 1: Open the settings window
Go to Tools > SheetGlot > Settings in the Unity menu bar. This automatically creates your TranslationSettings asset the first time you open it.
Step 2: Connect your spreadsheet
Paste your Google Sheets sharing or editing link into the Google Sheets CSV URL field. SheetGlot automatically converts the link to the correct export format, so there is no need to look for the "Publish to Web" CSV link.
Sample spreadsheet: don't have one ready? Use ours as a starting point: open the sample spreadsheet. Go to File > Make a copy to get your own editable version.
Prefer a local file? Place your CSV file in the folder configured in Settings, then click the Import Local CSV button, located below the Download & Import button. SheetGlot imports from that file instead of downloading from Google Sheets.
Step 3: Import and go
Click Download & Import. SheetGlot downloads the spreadsheet, converts it into JSON files, automatically detects and populates the available languages based on the spreadsheet headers, and validates that all keys are present in each language. Now you can translate in code:
string text = Localization.Translate("ui.play_button");
Configuring Google Sheets
SheetGlot expects a simple and predictable layout:
| key | en | pt-br | ru |
|---|---|---|---|
ui.play_button | Play | Jogar | Играть |
shop.open | Open store | Abrir loja | Открыть магазин |
items.count.one | {count} item | {count} item | {count} товар |
items.count.other | {count} items | {count} itens | {count} товаров |
Rules for the key column
- The first column is always the key and must be named strictly
key. - All subsequent columns represent a language code (
en,pt-br,ja, etc.). These are mapped automatically during import. - Use
.to create nested structures.cart.titleturns into{ "cart": { "title": "..." } }. - A purely numeric segment becomes a list index:
cart.items.0andcart.items.1become{ "cart": { "items": ["...", "..."] } }. In the generated Keys class, list indexes become method parameters (see Runtime API). - For plurals (integer numbers only), append the required CLDR plural form suffix to your base key (
.one,.other,.few,.many, etc.). The plural system is designed exclusively for whole number counts (int).
Getting the correct link
Copy the regular sharing link or address bar URL from Google Sheets. You do not need to manually assemble an /export?format=csv URL: SheetGlot's built-in URL normalizer handles this for you, regardless of the pasted link format.
The only important requirement is that the spreadsheet is shared as "Anyone with the link can view" (or published to the web). If it isn't, Google returns an HTML login page instead of your CSV, and SheetGlot flags it as an import error (see the FAQ).
Language management and persistence
SheetGlot gives you full flexibility over how your game's language behaves through the options in the settings asset (TranslationSettings).
Initial language configuration
You decide in the settings whether the game starts with a fixed default language or tries to automatically detect the player's operating system language (using Unity's settings). If automatic detection is enabled but the system language is not supported by your spreadsheet, SheetGlot automatically falls back to the configured fallback language.
Persistence: PlayerPrefs vs. custom system
- PlayerPrefs (default): if Persist Language Choice is active in Settings, SheetGlot automatically saves the player's choice to PlayerPrefs whenever
Localization.ChangeLanguage()is called. On the next launch, the game loads this choice automatically. - Custom save system: if your game has its own save system and you prefer saving the language alongside the player's data, disable Persist Language Choice in the Inspector. SheetGlot then won't touch PlayerPrefs, and you can load the language from your save file and pass it manually using the API.
Querying the current language at runtime
To know which language is currently active (for example, when building an options menu), access the static property CurrentLanguage:
string currentLang = Localization.CurrentLanguage;
Debug.Log("The active language is: " + currentLang);
Runtime API
Getting a translated string, with or without pluralization, takes just one line:
// Basic lookup
string text = Localization.Translate("ui.play_button");
// With a single placeholder (e.g., "Welcome, {name}!")
// This overload skips the Dictionary allocation for the common one-placeholder case.
string welcome = Localization.Translate("ui.welcome", "name", playerName);
// With two or more placeholders, passed as alternating name/value pairs
string trade = Localization.Translate("ui.trade", "item", itemName, "price", price.ToString());
// With placeholders already available as a Dictionary
string welcome2 = Localization.Translate("ui.welcome", new Dictionary<string, string> { { "name", playerName } });
// Plural lookup: automatically resolves the correct CLDR form for the active language
string pluralText = Localization.TranslatePlural("items.count", itemCount);
API reference: Translate overloads
Translate(string key): plain lookup, no placeholders.Translate(string key, string paramName, string paramValue): single placeholder, without allocating a Dictionary.Translate(string key, params string[] placeholders): two or more placeholders as alternating name/value pairs.Translate(string key, Dictionary<string, string> placeholders): placeholders already available as a Dictionary.TranslatePlural(string baseKey, int count): CLDR-aware plural lookup for whole numbers.
Before calling them at the start of the game, you can await asynchronous loading:
await Localization.Ready;
Switching languages at runtime:
Localization.ChangeLanguage("pt-br");
Using generated key constants (optional)
Every import also generates a Keys class, so you can use autocomplete instead of typing key strings. If a key is renamed or removed in the spreadsheet, your code stops compiling instead of silently showing [MISSING: key] at runtime.
// Same call, with a generated constant
string text = Localization.Translate(Keys.Ui.Play_button);
// Works with every overload
string welcome = Localization.Translate(Keys.Ui.Welcome, "name", playerName);
string pluralText = Localization.TranslatePlural(Keys.Items.Count, itemCount);
// List indexes become methods (achievements.energy.0.name, .1.name, ...)
string name = Localization.Translate(Keys.Achievements.Energy.Name(index));
The Keys class is regenerated on every import. Do not edit it by hand.
UI components
SheetGlot also ships ready-to-use components so designers can configure translated texts without touching code: LocalizedUGUIText for legacy uGUI Text and LocalizedTMP for TextMeshPro. Add the component, set the translation key in the Inspector, and it updates automatically whenever the language changes (including dynamic plural updates via SetPlural(count)).
LocalizedTMPrequires the TextMeshPro package to be installed in your project. If your project only uses legacy uGUI Text, you do not need to import TextMeshPro; useLocalizedUGUITextinstead.
The [TranslationKey] attribute
If you have your own MonoBehaviour and want a translation key field with the same Inspector dropdown and validation, decorate any string field with [TranslationKey]:
using SheetGlot.Components;
public class MyComponent : MonoBehaviour
{
[SerializeField, TranslationKey] private string titleKey;
void Start()
{
GetComponent<Text>().text = Localization.Translate(titleKey);
}
}
Editor tools
The settings window (Tools > SheetGlot > Settings) includes a set of editor tools to keep your translations clean and complete:
- Scene View Preview: once your translation keys are assigned to components in a scene, SheetGlot can display the resolved text directly in the Scene view without entering Play Mode, so you can check layout and text length while designing your UI.
- Validate Localization: compares every available language against the full set of keys found across all languages and reports which keys are missing per language, so incomplete translations don't slip into a build unnoticed.
- Check Duplicate Keys: scans all imported keys and flags keys that are repeated in the spreadsheet, showing the rows where they appear, so you can fix them before they create conflicting entries.
Setting up your own project
The package ships with a working demo configuration already set up: a sample Google Sheet, its generated JSON files, and a demo scene that translates text as soon as you press Play. This lets you see SheetGlot working immediately, with zero setup.
That demo configuration lives in a single asset: TranslationSettings (found under Tools > SheetGlot > Settings). This is the same asset your own game will use; there is no separate "production" settings object to create. To switch from the demo to your own project, simply edit the fields of this same asset.
Fields to replace
- Google Sheets CSV URL: the demo uses SheetGlot's public sample spreadsheet. Replace it with the sharing link of your own Google Sheet.
- Available Languages: the demo uses
en,pt-br,ru. Replace with the language codes your game actually supports. - Output Folder: the demo uses
Language. Use any folder name you prefer (optional, can be left as is). - Fallback / Fixed Language: the demo uses
en. Replace with whichever language should be the safety net for missing keys.
What happens to the demo files
Once you click Download & Import with your own spreadsheet URL, SheetGlot regenerates the JSON files in the Output Folder, overwriting the demo translations with your own. This is expected and safe: the demo data is only a starting example, not something you need to keep.
If you want to keep the demo scene available for reference afterward, make a copy of the generated demo JSON files before importing your own spreadsheet.
Because your own spreadsheet almost certainly uses a different set of languages than the demo (
en,pt-br,ru), SheetGlot detects that the demo languages are being removed and shows a confirmation dialog before deleting their JSON files and updating Available Languages. This is expected the first time you switch away from the demo spreadsheet. Simply confirm to proceed.
Thank you again for supporting SheetGlot, and happy localizing!
Import failed stating the spreadsheet "returned HTML". What does that mean?
This usually means Google did not allow SheetGlot to access the spreadsheet's CSV, returning an HTML login or preview page instead of the CSV data. Make sure the spreadsheet is shared as "Anyone with the link can view".
Where are the generated JSON files saved?
Inside Assets/StreamingAssets/<your output folder>/, with one file per language (e.g., en.json, pt-br.json). This is configurable via the Output Folder field in the settings window.
A language appears incomplete in Validation. What should I do?
Click the language row to expand the list of all missing keys. Fill out those rows in your Google Sheets spreadsheet and import again. SheetGlot only modifies files whose contents have actually changed, keeping your version control history (Git) clean.
I see [MISSING: key.name] in the game.
This means the key exists in neither the active language nor the fallback language. Check that the key spelling matches the spreadsheet exactly (keys are case-sensitive).
Do I need an internet connection at runtime?
No. Downloading occurs only inside the Unity Editor when you click Import. The exported JSON files are bundled with your build and loaded locally on any platform, including mobile devices.
How do plurals work in practice?
SheetGlot uses CLDR-based plural categories (zero, one, two, few, many, other) for supported languages, going far beyond a simple "singular vs plural" distinction and keeping grammar correct in languages with complex rules (Arabic, Polish, Russian, etc.). Add one row per plural form using the .form suffix on your key and call TranslatePlural("base.key", count). The system supports exclusively whole numbers (int); for decimal values, plural behavior varies across languages and is outside the scope of this tool.
I imported a new spreadsheet and a language I had before is gone. Is that expected?
Yes, and it's intentional. If a spreadsheet you import no longer includes a language column that was previously available, SheetGlot shows a confirmation dialog before removing that language from Available Languages and deleting its generated JSON file. This prevents outdated or orphaned translation files from silently lingering in your project after you switch spreadsheets. If you see this dialog and did not mean to remove a language, choose Cancel and check that the column is still present (and correctly named) in your spreadsheet header.
What does the "Check Duplicate Keys" tool do?
It finds keys that are repeated in your spreadsheet and shows the rows where they appear, so you can remove or rename the extras before importing again.
What happens to the generated Keys class if I rename or restructure keys?
Changing the key structure changes the generated API. Renaming ui.play_button in the spreadsheet makes Keys.Ui.Play_button disappear and breaks the compilation of any code that used it. This is intended behavior (a compile-time error instead of a missing translation at runtime), but worth knowing before you rename keys. Numeric key segments that are not a list (for example items.1001.name) also become a method that takes an index.
1.0.0
Initial release
- Compatibility
- 2022.3 LTS+
- Languages
- C#
- Store
- Asset Store