Skip to main content

Organize Your Translation Keys Automatically with Tags!

· 4 min read
Štěpán Granát
Localization key lifecycleLocalization key lifecycle

Do you ever struggle with deprecated localization keys? Wondering which keys are active in production and which are part of unreleased features? 😵‍💫

Keeping localization keys organized in a large project can be a headache, especially with many contributors. But it’s crucial for a smooth localization process.

The localization key challenge 🐭

One of my responsibilities is keeping order in localization keys. I need to identify keys linked to new features since they’re in "draft" mode. Until the feature is released, everything is fluid, strings change, keys get added or removed, and sometimes entire features get scrapped. It’s easy to end up with unused keys that are forgotten and never removed.

Keeping up with Git ✨

As we add new features, we inevitably have multiple versions (branches) of our application: the production version and feature branches. It’s essential to know which localization keys belong to which branch since production keys require careful handling, but keys in active development can be modified or removed as needed.

The key lifecycle ♻️

Each key goes through a lifecycle:

  1. Added to the code (draft)
  2. Released to the public (production)
  3. No longer needed (deprecated)

Different companies have different needs, but here’s the system we use at Tolgee:

1. draft 🌱

With the Tolgee SDK, you can set a default tag for new keys:

tagNewKeys: ['draft'],

When adding a new key through the Tolgee In-context tool, it appears like this:

In-context with draft

This approach is nice and simple, but we can't distinguish which feature does the key belong to.

To identify different features, we store the branch name in a file, which is imported into our web application and used in the tag:

import { branchName } from './branch.json';

tagNewKeys: [`draft: ${branchName}`],


"branchName": "current-feature-branch"

We set up Git hooks to update this file automatically with git hooks like this:

  1. Install Husky: npm i -D husky and run npx husky init
  2. Add post-commit and post-checkout files to the .husky folder with this script:
echo "{\"branchName\": \"$(git rev-parse --abbrev-ref HEAD)\"}" > ../branch.json
  1. Add branch.json to .gitignore

So now every time anyone adds a new key, it will automatically receive a tag including the name of the branch. 🎉

2. production 🌿 and deprecated 🍂


If you don't have @tolgee/cli integrated yet, read more here.

To track production keys, use the new CLI tag command, which extracts current keys from the code. We set this command in our GitHub Actions for every new commit in the main branch.

First, tag all production keys:

npx tolgee tag --filter-extracted --tag production --untag 'draft: *'

This moves the key from draft to production.

Next, identify deprecated keys:

npx tolgee tag \
--filter-not-extracted --filter-tag production \
--tag deprecated --untag production

This command filters keys not extracted but tagged as production, marking them as deprecated.

Read more about tag command

Streamline your localization process 🚀

So our system can now distinguish feature branches with draft: ... tag, we know which localization keys are in production and after some time we'll see some deprecated keys. We recommend deleting deprecated with a human check, to avoid any potential issues.

Alright, happy translating!

Bonus: Why not don't we support branches directly in Tolgee platform? 🎯

We’ve considered adding branching to Tolgee, so the platform would be able to mirror your state in git. However, we see the branching behavior as too complicated for this kind of use case and difficult to make user-friendly.

We hope that categorizing by tags is the right compromise, helping you to keep everything in sync, without adding unnecessary complexity.

React banner