src/Core/Localization.ps1
|
<#
.SYNOPSIS PSConsoleUI Localization System .DESCRIPTION Provides internationalization (i18n) support for the UI framework. Loads locale-specific resource files and provides string lookup. #> # Module-level variables $script:LocaleResources = @{} $script:ActiveLocale = $null $script:FallbackLocale = 'en-US' function Initialize-Localization { <# .SYNOPSIS Initializes the localization system. .DESCRIPTION Loads locale resource files and sets the active locale based on system culture. .PARAMETER LocalePath Optional path to the locales directory. Defaults to config/locales relative to module root. .PARAMETER DefaultLocale Optional default locale to use. If not specified, uses system culture. .EXAMPLE Initialize-Localization Initializes localization with system default locale. #> [CmdletBinding()] param( [string]$LocalePath = $null, [string]$DefaultLocale = $null ) # Determine locale path if (-not $LocalePath) { $moduleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) $LocalePath = Join-Path $moduleRoot 'config\locales' } # Determine active locale if ($DefaultLocale) { $script:ActiveLocale = $DefaultLocale } else { try { $script:ActiveLocale = (Get-Culture).Name } catch { $script:ActiveLocale = $script:FallbackLocale } } # Load all available locale files if (Test-Path $LocalePath) { $localeFiles = Get-ChildItem -Path $LocalePath -Filter '*.json' foreach ($file in $localeFiles) { $localeName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name) try { $content = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json $script:LocaleResources[$localeName] = $content Write-Verbose "Loaded locale: $localeName" } catch { Write-Warning "Failed to load locale file: $($file.Name) - $_" } } } else { Write-Warning "Locale path not found: $LocalePath" } # Verify active locale is available, fallback if not if (-not $script:LocaleResources.ContainsKey($script:ActiveLocale)) { Write-Verbose "Active locale '$script:ActiveLocale' not found, using fallback '$script:FallbackLocale'" $script:ActiveLocale = $script:FallbackLocale } Write-Verbose "Localization initialized. Active locale: $script:ActiveLocale" } function Get-LocalizedString { <# .SYNOPSIS Retrieves a localized string by key path. .DESCRIPTION Looks up a localized string using dot-notation key path (e.g., "Menu.SelectPrompt"). Falls back to default locale if key not found in active locale. .PARAMETER Key The key path to the localized string (e.g., "Menu.ExitPrompt"). .PARAMETER Locale Optional locale to use instead of active locale. .PARAMETER DefaultValue Optional default value to return if key not found. .EXAMPLE Get-LocalizedString -Key "Menu.SelectPrompt" Returns "Select an option" (in active locale). .EXAMPLE Get-LocalizedString -Key "Menu.SelectPrompt" -Locale "es-ES" Returns "Selecciona una opción". #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Key, [string]$Locale = $null, [string]$DefaultValue = '' ) # Use specified locale or active locale $targetLocale = if ($Locale) { $Locale } else { $script:ActiveLocale } # Get resource for target locale $resource = $script:LocaleResources[$targetLocale] # If not found, try fallback locale if (-not $resource -and $targetLocale -ne $script:FallbackLocale) { Write-Verbose "Locale '$targetLocale' not found, using fallback" $resource = $script:LocaleResources[$script:FallbackLocale] $targetLocale = $script:FallbackLocale } # If still not found, return default value if (-not $resource) { Write-Warning "No locale resources available" return $DefaultValue } # Navigate nested keys (e.g., "Menu.SelectPrompt" -> Menu -> SelectPrompt) $keys = $Key -split '\.' $value = $resource foreach ($k in $keys) { if ($value -is [PSCustomObject] -and (Get-Member -InputObject $value -Name $k -MemberType NoteProperty)) { $value = $value.$k } else { Write-Verbose "Key '$Key' not found in locale '$targetLocale'" # Try fallback locale if we haven't already if ($targetLocale -ne $script:FallbackLocale) { return Get-LocalizedString -Key $Key -Locale $script:FallbackLocale -DefaultValue $DefaultValue } return $DefaultValue } } return $value } function Set-UILocale { <# .SYNOPSIS Changes the active UI locale. .DESCRIPTION Sets the active locale for the UI framework. The locale must be available (have a corresponding JSON file loaded). .PARAMETER Locale The locale code to activate (e.g., "en-US", "es-ES", "fr-FR"). .EXAMPLE Set-UILocale -Locale "es-ES" Changes UI language to Spanish. #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Locale ) if ($script:LocaleResources.ContainsKey($Locale)) { $script:ActiveLocale = $Locale Write-Verbose "Active locale changed to: $Locale" } else { $available = $script:LocaleResources.Keys -join ', ' throw "Locale '$Locale' not available. Available locales: $available" } } function Get-UILocale { <# .SYNOPSIS Gets the current active UI locale. .DESCRIPTION Returns the currently active locale code. .EXAMPLE Get-UILocale Returns "en-US" (or current active locale). #> [CmdletBinding()] param() return $script:ActiveLocale } function Get-AvailableLocales { <# .SYNOPSIS Gets list of available locales. .DESCRIPTION Returns an array of all loaded locale codes. .EXAMPLE Get-AvailableLocales Returns @("en-US", "es-ES", "fr-FR") #> [CmdletBinding()] param() return @($script:LocaleResources.Keys) } # Export functions Export-ModuleMember -Function Initialize-Localization, Get-LocalizedString, Set-UILocale, Get-UILocale, Get-AvailableLocales |