Skip to content

Dashboard guide

Translation Management

Translation keys are the core of your project. Each key represents a piece of translatable content with values in multiple languages.

Understanding Translation Keys

Key Structure

Each translation key in langctl has:

  • Key Name: Unique identifier within the project (e.g., home.welcome, auth.login.title)
  • Translations: Values for each language
  • Module: Optional grouping (e.g., “auth”, “dashboard”)
  • Description: Optional context for translators - also written into exported files as comments or metadata
  • Status: Draft or Published - only published keys are exported
Translation Key Structure
{
"key": "home.welcome",
"translations": {
  "en": "Welcome to our app!",
  "es": "¡Bienvenido a nuestra aplicación!",
  "fr": "Bienvenue dans notre application!"
},
"module": "home",
"description": "Main welcome message",
"published": true
}

The Translations Page

Open Translations in the sidebar. It shows the keys of the project selected in the sidebar’s project switcher: one row per key with the source text, the other languages, and the key’s status. Languages without a translation are marked Missing.

Creating Translation Keys

  1. Click Add Key (or use Add Key in the Cmd/Ctrl + K palette)
  2. Fill in the form:
    • Key Name: Unique identifier (e.g., home.welcome) - letters, numbers, dots, hyphens and underscores
    • Module: Optional grouping (e.g., “home”)
    • Description: Context for translators
    • Translations: Values for the languages you know; empty languages can be filled in later
  3. Turn on Publish immediately if the key is ready, otherwise it’s saved as a draft
  4. Save the key - tick Add another after this to keep the form open for the next key

If a key with that name already exists, the form offers to open the existing key instead.

Key Naming Conventions

Use dot notation for hierarchical organization:

✅ Good:

auth.login.title
auth.login.subtitle
auth.login.button
dashboard.welcome.title
dashboard.stats.users

❌ Bad:

AuthLoginTitle
login_title
titleLogin

Best Practice

Use lowercase, dot-separated names that reflect your app’s structure. This makes keys easier to find and organize. The key name can’t be changed after the key is created.

Editing Translations

Click a key to open its detail panel:

  1. Every project language is listed, with the default language first; right-to-left languages are marked
  2. Edit any translation in place
  3. Use Suggest next to a language to fill it with an AI translation (see AI Translation)
  4. Save:
    • For a draft key: Save draft or Publish
    • For a published key: Save or Unpublish

Use Edit key details in the panel to change the key’s description and module, and Delete key to remove it. Press Esc to close the panel.

Key History

The History tab of the detail panel lists every change to the key’s translations, newest first - whether it was made in the dashboard, with the CLI or by an import:

  • Who made the change and when (hover the time for the exact date)
  • Which languages changed, with the text before and after
  • AI on text that is exactly what AI translation produced, and when someone approved an AI translation
  • The text the key was created with

Members, admins and owners can use Restore this version to bring back the text of an earlier version. Restoring is a normal save: it shows up as a new change in the history (so it can be undone the same way), and AI translations that were never approved need review again. Languages that had no text in that version keep their current text.

Parameter Syntax

Use {{parameter}} syntax for variables:

output
en: "Welcome, {{username}}!"
es: "¡Bienvenido, {{username}}!"
fr: "Bienvenue, {{username}}!"

en: "You have {{count}} new messages"
es: "Tienes {{count}} mensajes nuevos"
fr: "Vous avez {{count}} nouveaux messages"

Note

Placeholders are converted to platform-specific syntax when you export or pull: %1$s for Android, %1$@ for iOS, {param} for Flutter. See File Formats.

Finding Keys

The search box matches key names, translations and descriptions.

Filters

  • All
  • Missing - Keys with at least one missing translation
  • Needs review - Keys with AI translations nobody has approved yet (shown only when there are some)
  • Draft - Unpublished keys
  • Published - Published keys
  • Module - Shown when the project has modules

Click the source column header to sort by key name. Large projects show the first rows; use Show more to load the rest.

To search keys across all projects, use the Cmd/Ctrl + K palette.

Draft vs Published

Draft Keys:

  • Not included in exports or langctl pull by default
  • Shown with a “Draft” badge
  • Useful for work-in-progress translations

Published Keys:

  • Included in exports and langctl pull
  • Should be complete and reviewed

When you publish a key that is missing translations, langctl asks you to confirm - users of those languages will see your app’s fallback text.

Tip

Use the draft/publish workflow like staging/production. Keep keys as drafts while translating, then publish when ready. Learn more ->

Bulk Actions

Select keys with the checkboxes (the header checkbox selects every key in the current view). A bar appears at the bottom with:

  • Publish / Unpublish
  • Approve AI - Approve AI translations in the selected keys
  • Translate missing - Fill empty translations of the selected keys with AI
  • Delete

Warning

Bulk operations apply to all selected keys. Double-check your selection before deleting.

Deleting Keys

Delete a key from its row, from its detail panel, or select several and use Delete in the bulk bar. Deleted keys disappear from the dashboard, exports and langctl pull. You can create a key with the same name again later, and importing or pushing a file that contains it brings it back.

Import and Export

The Import and Export buttons at the top of the page open Import & Export for the current project. Learn more about import ->

Best Practices

Use descriptive key names:

output
✅ user.profile.edit.save_button
❌ btn1

Keep key names consistent:

output
✅ *.button_text  (consistent suffix)
❌ *_btn, *.button, *.btn_text (inconsistent)

Respect parameter names:

output
✅ "Hello, {{username}}!"
❌ "Hello, {{name}}!"  (inconsistent parameter)

Provide context in descriptions:

output
Description: "Shown after successful login on home page"

Use consistent module names:

✅ auth, dashboard, settings
❌ Auth, DASHBOARD, settings_page

Troubleshooting

Key Already Exists

  • Key names must be unique within a project
  • Open the existing key from the prompt, or use a different name

Can’t Edit Translations

  • Viewers have read-only access; you need the Member role or higher
  • Check that you’re in the right organization and project

Missing Language Not Showing

  • Make sure the language is added to the project (Languages in the sidebar)
  • Clear the search and filters
  • Reload the page

Next Steps