Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Translation Guide

This document provides guidelines for contributing translations to scuv.

Current Status

For the latest translation status, see:


Contribution Process

Step 1: Fork and Clone

git clone https://github.com/YOUR_USERNAME/scoop-uv.git
cd scoop-uv

Step 2: Add Translations

Edit locales/app.yml and add your language to every key:

create.success:
  en: "Created '%{name}' environment"
  ko: "'%{name}' 환경 생성됨"
  pt-BR: "Ambiente '%{name}' criado"
  ja: "'%{name}' 環境を作成しました"
  es: "Entorno '%{name}' creado"
  { lang }: "Your translation here"  # Add your language code and translation

Important:

  • Add translations to all 221 keys
  • Keep placeholder syntax exactly: %{name}, %{version}, etc.
  • Preserve special characters: →, quotes, backticks

The key count grows between releases. For the current number:

grep -c '^[a-z_][a-zA-Z0-9_.]*:$' locales/app.yml

Step 3: Register Language

Edit src/i18n.rs and add your language to SUPPORTED_LANGS:

#![allow(unused)]
fn main() {
pub const SUPPORTED_LANGS: &[(&str, &str)] = &[
    ("en", "English"),
    ("ko", "한국어"),
    ("pt-BR", "Português (Brasil)"),
    ("ja", "日本語"),
    ("es", "Español"),
    ("{lang}", "Your Language Name"),  // Add your language
];
}

Language Code Format:

  • Use BCP 47 format
  • Simple languages: ja, fr, es, de, it
  • Regional variants: pt-BR, zh-CN, zh-TW, es-MX

Three more places list the supported locales. The first one matters most.

1. tests/i18n_completeness.rs — add your code to the LOCALES const:

#![allow(unused)]
fn main() {
const LOCALES: &[&str] = &["en", "ko", "ja", "pt-BR", "es", "{lang}"];
}

This is the CI gate that checks every key exists in every locale. If your language is missing from this list, CI passes while your translation goes completely unverified — nothing tells you it was skipped.

2. Shell completions — the scuv lang candidate lists are hand-written in all four shells:

  • src/shell/fish.rs — the complete -c scuv ... from lang lines
  • src/shell/zsh.rs — the langs=(...) array
  • src/shell/bash.rs — the compgen -W "en ko ja pt-BR es" list under lang)
  • src/shell/powershell.rs — the @('en', 'ko', 'ja', 'pt-BR', 'es') array

Each shell module has a test (lang_completion_list_matches_supported_langs) that compares its list with SUPPORTED_LANGS, so a shell you miss fails cargo test instead of surfacing when a user presses Tab.

3. Locale loops in tests (optional) — src/error/tests.rs and src/error/suggestion.rs iterate the supported locales. Adding yours gives your translation unit-level coverage. Skip it if you would rather not touch Rust, and a maintainer can add it during review.

Step 4: Test Locally

rust-i18n’s proc macro is not tracked by cargo, so editing locales/app.yml on its own does not trigger a rebuild. cargo test reuses the stale binary and reports a false pass. Always touch src/lib.rs first.

# Build and test (the touch is required — see the note above)
touch src/lib.rs
cargo build
cargo test

# Test your language (replace {lang} with your language code)
SCUV_LANG={lang} ./target/debug/scuv --help
SCUV_LANG={lang} ./target/debug/scuv lang

Step 5: Create Pull Request

Required files in PR:

  • locales/app.yml - All 221 keys translated
  • src/i18n.rs - Language registered in SUPPORTED_LANGS
  • tests/i18n_completeness.rs - Language added to LOCALES
  • src/shell/bash.rs, src/shell/zsh.rs, src/shell/fish.rs, src/shell/powershell.rs - Completion lists updated

PR Title Format:

feat(i18n): add {Language Name} translation

feat, not docs: a new language is a user-visible feature, and the changelog generator files it under “Added” only for feat commits.


Style Guidelines

Philosophy: Your Language, Your Style

We trust translators. You know your language and community best.

  • Word choice is yours — Pick terms that feel natural to native speakers
  • Creativity welcome — Witty expressions are fine if they’re clear and widely understood
  • Casual over formal — scuv is a friendly CLI tool, not enterprise software

General Principles

  1. Concise: CLI messages should be short and clear
  2. Natural: Use natural phrasing, not word-for-word translation
  3. Casual: Friendly, approachable tone — like talking to a colleague
  4. Clear: Wit is great, but clarity comes first

Tone Examples

# Too formal (avoid)
"The environment has been successfully created."

# Too robotic (avoid)
"Environment creation: complete."

# Good - casual and clear
"Created 'myenv' — ready to go!"
"'myenv' is ready"

Message Types

TypeEnglish ExampleGuidance
Progress“Installing…”Use progressive/ongoing form
Success“Created ‘myenv’”Completion — feel free to add flair
Error“Can’t find ‘myenv’”Clear and actionable
Hint“→ Create: scuv create…”Helpful, not lecturing

Translator’s Discretion

These decisions are up to you:

  • Vocabulary: Choose words that resonate with your community
  • Idioms: Use local expressions if they fit naturally
  • Humor: Light wit is welcome (e.g., ice cream puns if appropriate)
  • Formality level: Lean casual, but match your culture’s CLI norms

Only requirement: The meaning must be clear to users.

Technical Terms

For technical vocabulary:

  1. Check your community — What do Python developers in your language use?
  2. Consistency — Pick one term and stick with it throughout
  3. Loanwords OK — If your community uses English terms (e.g., “install”), that’s fine

Tip: Study existing translations in locales/app.yml for reference, but don’t feel bound by them.


Glossary

Do NOT Translate

These terms should remain in English in all languages:

TermReason
scuvBrand name
uvTool name
pyenvTool name
condaTool name
virtualenvTechnical term
virtualenvwrapperTool name
PythonLanguage name
shellTechnical term (bash, zsh, fish)
JSONFormat name
PATHEnvironment variable
pipTool name

Commands - Never Translate

All commands and code examples must stay in English:

# WRONG - Command translated
hint: "→ Create: {translated_command} myenv 3.12"

# CORRECT - Only description translated
hint: "→ {translated_word}: scuv create myenv 3.12"

Common Terms to Translate

These are core concepts you’ll need to translate. Reference existing translations for consistency:

EnglishWhat to look for
environmentYour language’s term for “environment”
createCommon verb for “make/create”
remove/deleteCommon verb for “delete/remove”
installStandard software installation term
uninstallStandard software removal term
activateTerm for “enable/turn on”
deactivateTerm for “disable/turn off”
migrateIT term for migration (often kept as loanword)
versionYour language’s term for “version”
pathYour language’s term for file path
errorYour language’s term for “error”
successYour language’s term for “success”

Tip: Check how these terms are translated in existing translations for reference.

Ice Cream Metaphor (README only)

scuv uses ice cream metaphors in documentation:

TermMeaningGuidance
scuvThe toolAlways keep as “scuv”
flavorvirtualenvTranslate if the metaphor works in your language
freezer~/.scuv/ directoryTranslate if the metaphor works

Note: The metaphor is mainly in README.md, not in CLI messages (locales/app.yml).


File Structure

locales/app.yml

# Categories in order:
# 1. lang.*        - Language command messages
# 2. create.*      - Create command messages
# 3. remove.*      - Remove command messages
# 4. list.*        - List command messages
# 5. use.*         - Use command messages
# 6. install.*     - Install command messages
# 7. uninstall.*   - Uninstall command messages
# 8. migrate.*     - Migrate command messages
# 9. error.*       - Error messages
# 10. suggestion.* - Suggestion/hint messages

src/i18n.rs

#![allow(unused)]
fn main() {
// Language detection priority:
// 1. SCUV_LANG environment variable
// 2. Config file (~/.scuv/config.json)
// 3. System locale
// 4. Default: "en"

pub const SUPPORTED_LANGS: &[(&str, &str)] = &[
    ("en", "English"),
    // ... existing languages
    // Add new languages here
];
}

Common Mistakes

1. Missing SUPPORTED_LANGS Registration

Symptom: Translation exists but scuv lang {code} doesn’t work

Fix: Add language to src/i18n.rs SUPPORTED_LANGS

2. Broken Placeholders

# WRONG - Missing placeholder
error: "Cannot find environment"

# CORRECT - Placeholder preserved
error: "Cannot find '%{name}' environment"

3. Translating Commands

# WRONG - Command translated
hint: "→ List: {translated} list"

# CORRECT - Only label translated
hint: "→ {Translated Label}: scuv list"

4. Inconsistent Key Coverage

All languages must have ALL keys. Missing keys fall back to English.

5. Missing LOCALES Registration

Symptom: CI is green, but nothing ever checked your locale

Fix: Add your code to the LOCALES const in tests/i18n_completeness.rs

6. Stale i18n Cache

Symptom: cargo test passes, but your new strings never show up

Fix: Run touch src/lib.rs before cargo test


Testing Checklist

Before submitting PR:

  • All 221 keys translated
  • All placeholders preserved (%{name}, %{version}, etc.)
  • Language registered in SUPPORTED_LANGS
  • Language added to LOCALES in tests/i18n_completeness.rs
  • Shell completion lists updated (bash, zsh, fish, PowerShell)
  • cargo build succeeds
  • touch src/lib.rs run, then cargo test passes
  • SCUV_LANG={code} scuv lang shows your language
  • Messages display correctly in terminal

Questions?

  • Open an issue: GitHub Issues
  • See existing translations for reference: locales/app.yml