src/Config/I18nCatalog.ps1

# I18nCatalog — Strings UI en español e inglés.
#
# Devuelve un hashtable plano `key → string` para el locale pedido. La función
# vive afuera de I18nService para que el archivo de la clase quede chico y los
# diccionarios sean fáciles de scanear en review.
#
# Convención de keys: dot.notation jerárquica
# hint.* → labels de teclas en el statusbar (Move, Quit, Back, etc.)
# tab.* → tabs del menu del MainScreen
# prefs.* → labels de items en PreferencesScreen
# setup.* → labels de SetupScreen + acciones
# alias.* → prompts/confirms del flow de alias
# filter.* → modo búsqueda inline
# status.* → mensajes de status (ok/error/info)
# counts.* → labels de contadores en footer
# pill.* → texto de pills de estado git
# browse.* → BrowseScreen específicos
# nav.* → BranchManager (chips, branches, etc.)
# common.* → reutilizables (yes/no/loading…)

# OJO: scope GLOBAL explícito. Bootstrap.ps1 importa este archivo via la
# función Import-RNConfig que envuelve el dot-source en otra función. Las
# funciones declaradas con `function Foo {}` quedarían en el scope local
# de Import-RNConfig (no visibles desde I18nService.T). Con `function global:`
# forzamos el scope global, igual que `$global:RNThemes`. En tests directos
# (Pester dot-sourcea sin envoltorio), también funciona — global es global.
function Get-RepoNavI18nCatalog {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateSet('es', 'en')]
        [string] $Locale
    )

    if ($Locale -eq 'en') { return Get-RepoNavI18nCatalogEn }
    return Get-RepoNavI18nCatalogEs
}

function Get-RepoNavI18nCatalogEs {
    return @{
        # ─── Hints comunes (statusbar) ──────────────────────────────────────
        'hint.move'           = 'Mover'
        'hint.quit'           = 'Salir'
        'hint.back'           = 'Volver'
        'hint.open'           = 'Abrir'
        'hint.openFolder'     = 'Abrir carpeta'
        'hint.openMenu'       = 'Abrir menu'
        'hint.path'           = 'Path'
        'hint.search'         = 'Buscar'
        'hint.fav'            = 'Fav'
        'hint.reload'         = 'Recargar'
        'hint.prefs'          = 'Prefs'
        'hint.tab'            = 'Tab'
        'hint.run'            = 'Ejecutar'
        'hint.close'          = 'Cerrar'
        'hint.accept'         = 'Aceptar'
        'hint.cancel'         = 'Cancelar'
        'hint.save'           = 'Guardar'
        'hint.toggle'         = 'Toggle'
        'hint.cycle'          = 'Cyclear'
        'hint.toggleCycle'    = 'Toggle/Cycle'
        'hint.segment'        = 'Segmento'
        'hint.drill'          = 'Drill'
        'hint.type'           = 'tipear'
        'hint.aliasSet'       = 'Set alias'
        'hint.aliasEdit'      = 'Edit alias'
        'hint.aliasDel'       = 'Borrar alias'

        # ─── Tabs del MainScreen ───────────────────────────────────────────
        'tab.browse'          = 'Browse'
        'tab.search'          = 'Search'
        'tab.git'             = 'Git'

        # ─── PreferencesScreen ──────────────────────────────────────────────
        'prefs.title'         = 'Preferencias'
        'prefs.theme'         = 'Theme'
        'prefs.language'      = 'Idioma'
        'prefs.autoLoadMode'  = 'Auto-cargar repos'
        'prefs.autoFetch'     = 'Auto fetch'
        'prefs.favoritesFirst' = 'Favoritos arriba'
        'prefs.showAliases'   = 'Mostrar aliases'
        'prefs.showTags'      = 'Mostrar tags'
        'prefs.showLastCommit' = 'Mostrar último commit'
        'prefs.useAlt'        = 'Usar alt buffer'
        'prefs.setupAndStatus' = 'Setup y Status'
        'prefs.singleValue'   = 'solo hay un valor disponible para {0}'
        'prefs.savedKv'       = '{0} → {1}'
        'prefs.saveError'     = 'no pude guardar'

        # ─── SetupScreen ────────────────────────────────────────────────────
        'setup.title'           = 'Setup y Status'
        'setup.envSection'      = 'Entorno'
        'setup.profileSection'  = 'Profile'
        'setup.settingsSection' = 'Settings'
        'setup.actionsSection'  = 'Acciones'
        'setup.psLabel'         = 'PowerShell'
        'setup.gitLabel'        = 'git'
        'setup.repoPath'        = 'repo path'
        'setup.path'            = 'path'
        'setup.alias'           = 'alias'
        'setup.otherFunctions'  = 'otras functions'
        'setup.statusLabel'     = 'estado'
        'setup.notInstalled'    = 'NO instalado'
        'setup.aliasManaged'    = '{0} (managed)'
        'setup.gitNotInstalled' = '(no instalado)'
        'setup.jsonValid'       = 'JSON válido'
        'setup.jsonInvalid'     = 'JSON inválido'
        'setup.reinstallAlias'  = 'Reinstall alias {0}'
        'setup.uninstallAlias'  = 'Uninstall alias {0}'
        'setup.cancel'          = 'Volver'
        'setup.installNotFound' = 'no se encontró Install.ps1 en {0}'
        'setup.aliasReinstalled' = 'alias reinstalado · abrí pwsh nueva para ver el cambio'
        'setup.aliasUninstalled' = 'alias desinstalado · abrí pwsh nueva para ver el cambio'
        'setup.installFailed'   = 'falló (exit {0}): {1}'
        'setup.error'           = 'error: {0}'

        # ─── Filter inline (modo búsqueda) ──────────────────────────────────
        'filter.search'         = 'Buscar'
        'filter.acceptHint'     = '· ↵ aceptar · Esc cancelar'

        # ─── Alias prompt ───────────────────────────────────────────────────
        'alias.label'           = 'Alias'
        'alias.hintNoAlias'     = '· sin espacios · ↵ guardar · Esc cancelar'
        'alias.hintWithAlias'   = '· sin espacios · ↵ guardar · vaciá + ↵ para eliminar · Esc cancelar'
        'alias.confirmRemove'   = '¿Eliminar alias {0}? (Y/N)'
        'alias.confirmRemoveNoName' = '¿Eliminar alias? (Y/N)'

        # ─── Status pills (estado git) ──────────────────────────────────────
        'pill.clean'            = 'clean'
        'pill.dirty'            = 'dirty'
        'pill.unpushed'         = 'unpushed'
        'pill.behind'           = 'behind'
        'pill.conflict'         = 'conflict'
        'pill.nogit'            = 'no git'
        'pill.container'        = 'container'
        'pill.notLoaded'        = 'no cargado'

        # ─── Counts / progress ──────────────────────────────────────────────
        'counts.repos'          = 'Repositorios'
        'counts.viewing'        = 'viendo'
        'counts.loadedOf'       = '{0}/{1} cargados'
        'counts.cache'          = 'cache'
        'counts.noRepos'        = '(no hay repositorios)'
        'counts.noMatches'      = '(sin matches para /{0}/)'

        # ─── BrowseScreen ───────────────────────────────────────────────────
        'browse.title'          = 'Browse'
        'browse.parent'         = '..'
        'browse.parentLabel'    = '(carpeta padre)'
        'browse.cantRead'       = 'no se pudo leer: {0}'
        'browse.pathNotExist'   = 'path no existe: {0}'

        # ─── BranchManager (chips) ──────────────────────────────────────────
        'nav.chip.integrate'    = 'Integrate'
        'nav.chip.quick'        = 'Quick'
        'nav.chip.release'      = 'Release'
        'nav.chip.compare'      = 'Compare'
        'nav.chip.cherryPick'   = 'Cherry-Pick'
        'nav.chip.graph'        = 'Graph'

        # ─── Common ─────────────────────────────────────────────────────────
        'common.yes'            = 'Sí'
        'common.no'             = 'No'
        'common.on'             = 'on'
        'common.off'            = 'off'
        'common.dash'           = '—'
    }
}

function Get-RepoNavI18nCatalogEn {
    return @{
        # ─── Hints ──────────────────────────────────────────────────────────
        'hint.move'           = 'Move'
        'hint.quit'           = 'Quit'
        'hint.back'           = 'Back'
        'hint.open'           = 'Open'
        'hint.openFolder'     = 'Open folder'
        'hint.openMenu'       = 'Open menu'
        'hint.path'           = 'Path'
        'hint.search'         = 'Search'
        'hint.fav'            = 'Fav'
        'hint.reload'         = 'Reload'
        'hint.prefs'          = 'Prefs'
        'hint.tab'            = 'Tab'
        'hint.run'            = 'Run'
        'hint.close'          = 'Close'
        'hint.accept'         = 'Accept'
        'hint.cancel'         = 'Cancel'
        'hint.save'           = 'Save'
        'hint.toggle'         = 'Toggle'
        'hint.cycle'          = 'Cycle'
        'hint.toggleCycle'    = 'Toggle/Cycle'
        'hint.segment'        = 'Segment'
        'hint.drill'          = 'Drill'
        'hint.type'           = 'type'
        'hint.aliasSet'       = 'Set alias'
        'hint.aliasEdit'      = 'Edit alias'
        'hint.aliasDel'       = 'Del alias'

        # ─── Tabs ───────────────────────────────────────────────────────────
        'tab.browse'          = 'Browse'
        'tab.search'          = 'Search'
        'tab.git'             = 'Git'

        # ─── Preferences ────────────────────────────────────────────────────
        'prefs.title'         = 'Preferences'
        'prefs.theme'         = 'Theme'
        'prefs.language'      = 'Language'
        'prefs.autoLoadMode'  = 'Auto-load repos'
        'prefs.autoFetch'     = 'Auto fetch'
        'prefs.favoritesFirst' = 'Favorites first'
        'prefs.showAliases'   = 'Show aliases'
        'prefs.showTags'      = 'Show tags'
        'prefs.showLastCommit' = 'Show last commit'
        'prefs.useAlt'        = 'Use alt buffer'
        'prefs.setupAndStatus' = 'Setup & Status'
        'prefs.singleValue'   = 'only one value available for {0}'
        'prefs.savedKv'       = '{0} → {1}'
        'prefs.saveError'     = 'could not save'

        # ─── Setup ──────────────────────────────────────────────────────────
        'setup.title'           = 'Setup & Status'
        'setup.envSection'      = 'Environment'
        'setup.profileSection'  = 'Profile'
        'setup.settingsSection' = 'Settings'
        'setup.actionsSection'  = 'Actions'
        'setup.psLabel'         = 'PowerShell'
        'setup.gitLabel'        = 'git'
        'setup.repoPath'        = 'repo path'
        'setup.path'            = 'path'
        'setup.alias'           = 'alias'
        'setup.otherFunctions'  = 'other functions'
        'setup.statusLabel'     = 'status'
        'setup.notInstalled'    = 'NOT installed'
        'setup.aliasManaged'    = '{0} (managed)'
        'setup.gitNotInstalled' = '(not installed)'
        'setup.jsonValid'       = 'JSON valid'
        'setup.jsonInvalid'     = 'JSON invalid'
        'setup.reinstallAlias'  = 'Reinstall alias {0}'
        'setup.uninstallAlias'  = 'Uninstall alias {0}'
        'setup.cancel'          = 'Back'
        'setup.installNotFound' = 'Install.ps1 not found in {0}'
        'setup.aliasReinstalled' = 'alias reinstalled · open a new pwsh to see the change'
        'setup.aliasUninstalled' = 'alias uninstalled · open a new pwsh to see the change'
        'setup.installFailed'   = 'failed (exit {0}): {1}'
        'setup.error'           = 'error: {0}'

        # ─── Filter inline ──────────────────────────────────────────────────
        'filter.search'         = 'Search'
        'filter.acceptHint'     = '· ↵ accept · Esc cancel'

        # ─── Alias prompt ───────────────────────────────────────────────────
        'alias.label'           = 'Alias'
        'alias.hintNoAlias'     = '· no spaces · ↵ save · Esc cancel'
        'alias.hintWithAlias'   = '· no spaces · ↵ save · empty + ↵ to delete · Esc cancel'
        'alias.confirmRemove'   = 'Delete alias {0}? (Y/N)'
        'alias.confirmRemoveNoName' = 'Delete alias? (Y/N)'

        # ─── Status pills ───────────────────────────────────────────────────
        'pill.clean'            = 'clean'
        'pill.dirty'            = 'dirty'
        'pill.unpushed'         = 'unpushed'
        'pill.behind'           = 'behind'
        'pill.conflict'         = 'conflict'
        'pill.nogit'            = 'no git'
        'pill.container'        = 'container'
        'pill.notLoaded'        = 'not loaded'

        # ─── Counts / progress ──────────────────────────────────────────────
        'counts.repos'          = 'Repositories'
        'counts.viewing'        = 'viewing'
        'counts.loadedOf'       = '{0}/{1} loaded'
        'counts.cache'          = 'cache'
        'counts.noRepos'        = '(no repositories)'
        'counts.noMatches'      = '(no matches for /{0}/)'

        # ─── BrowseScreen ───────────────────────────────────────────────────
        'browse.title'          = 'Browse'
        'browse.parent'         = '..'
        'browse.parentLabel'    = '(parent folder)'
        'browse.cantRead'       = 'could not read: {0}'
        'browse.pathNotExist'   = 'path does not exist: {0}'

        # ─── BranchManager chips ────────────────────────────────────────────
        'nav.chip.integrate'    = 'Integrate'
        'nav.chip.quick'        = 'Quick'
        'nav.chip.release'      = 'Release'
        'nav.chip.compare'      = 'Compare'
        'nav.chip.cherryPick'   = 'Cherry-Pick'
        'nav.chip.graph'        = 'Graph'

        # ─── Common ─────────────────────────────────────────────────────────
        'common.yes'            = 'Yes'
        'common.no'             = 'No'
        'common.on'             = 'on'
        'common.off'            = 'off'
        'common.dash'           = '—'
    }
}