422 lines
11 KiB
Plaintext
422 lines
11 KiB
Plaintext
#! Fluent i18n translation daemon functions
|
|
#!
|
|
#! Provides high-performance message translation via HTTP API using Mozilla's Fluent.
|
|
#! The CLI daemon's Fluent engine offers 50-100x better performance than using
|
|
#! the nu_plugin_fluent plugin due to aggressive caching and no process spawning.
|
|
#!
|
|
#! Performance:
|
|
#! - Single translation: ~1-5ms uncached, ~0.1-0.5ms cached (vs ~50ms with plugin)
|
|
#! - Batch 10 translations: ~10-20ms with cache
|
|
#! - Cache hit ratio: 75-80% on typical workloads
|
|
|
|
use ../env.nu [get-cli-daemon-url]
|
|
|
|
# Translate a message ID to the target locale
|
|
#
|
|
# Uses the CLI daemon's Fluent engine for fast i18n translation.
|
|
# Supports variable interpolation and fallback locales.
|
|
#
|
|
# # Arguments
|
|
# * `message_id` - Message identifier (e.g., "welcome-message")
|
|
# * `--locale (-l)` - Target locale (default: "en-US")
|
|
# * `--args (-a)` - Arguments for variable interpolation (record)
|
|
# * `--fallback (-f)` - Fallback locale if message not found
|
|
#
|
|
# # Returns
|
|
# Translated message string or error if translation failed
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# # Simple translation
|
|
# fluent-translate "welcome-message" --locale en-US
|
|
#
|
|
# # With arguments
|
|
# fluent-translate "greeting" --locale es --args {name: "María"}
|
|
#
|
|
# # With fallback
|
|
# fluent-translate "new-feature" --locale fr --fallback en-US
|
|
# ```
|
|
export def fluent-translate [
|
|
message_id: string
|
|
--locale (-l): string = "en-US"
|
|
--args (-a): record = {}
|
|
--fallback (-f): string
|
|
] -> string {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
# Build request
|
|
let request = {
|
|
message_id: $message_id
|
|
locale: $locale
|
|
args: ($args | to json | from json)
|
|
fallback_locale: $fallback
|
|
}
|
|
|
|
# Send to daemon's Fluent endpoint
|
|
let response = (
|
|
http post $"($daemon_url)/fluent/translate" $request
|
|
--raw
|
|
)
|
|
|
|
# Parse response
|
|
let parsed = ($response | from json)
|
|
|
|
# Check for error
|
|
if ($parsed.error? != null) {
|
|
error make {msg: $"Fluent translation error: ($parsed.error)"}
|
|
}
|
|
|
|
# Return translated message
|
|
$parsed.translated
|
|
}
|
|
|
|
# Translate multiple messages in batch mode
|
|
#
|
|
# Translates a list of message IDs to the same locale. More efficient
|
|
# than calling fluent-translate multiple times due to connection reuse.
|
|
#
|
|
# # Arguments
|
|
# * `message_ids` - List of message IDs to translate
|
|
# * `--locale (-l)` - Target locale (default: "en-US")
|
|
# * `--fallback (-f)` - Fallback locale if messages not found
|
|
#
|
|
# # Returns
|
|
# List of translated messages
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# let messages = ["welcome", "goodbye", "thank-you"]
|
|
# fluent-translate-batch $messages --locale fr --fallback en
|
|
# ```
|
|
export def fluent-translate-batch [
|
|
message_ids: list<string>
|
|
--locale (-l): string = "en-US"
|
|
--fallback (-f): string
|
|
] -> list<string> {
|
|
$message_ids | each { |msg_id|
|
|
fluent-translate $msg_id --locale $locale --fallback $fallback
|
|
}
|
|
}
|
|
|
|
# Load a Fluent bundle from a specific FTL file
|
|
#
|
|
# Loads messages from an FTL file into the daemon's bundle cache.
|
|
# This is useful for loading custom translations at runtime.
|
|
#
|
|
# # Arguments
|
|
# * `locale` - Locale identifier (e.g., "es", "fr-FR")
|
|
# * `path` - Path to FTL file
|
|
#
|
|
# # Returns
|
|
# Record with load status and message count
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-load-bundle "es" "/path/to/es.ftl"
|
|
# ```
|
|
export def fluent-load-bundle [
|
|
locale: string
|
|
path: string
|
|
] -> record {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
let request = {
|
|
locale: $locale
|
|
path: $path
|
|
}
|
|
|
|
let response = (
|
|
http post $"($daemon_url)/fluent/bundles/load" $request
|
|
)
|
|
|
|
$response | from json
|
|
}
|
|
|
|
# Reload all Fluent bundles from the FTL directory
|
|
#
|
|
# Clears all cached bundles and reloads them from the configured
|
|
# FTL directory. Useful after updating translation files.
|
|
#
|
|
# # Returns
|
|
# Record with reload status and list of loaded locales
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-reload-bundles
|
|
# ```
|
|
export def fluent-reload-bundles [] -> record {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
let response = (
|
|
http post $"($daemon_url)/fluent/bundles/reload" ""
|
|
)
|
|
|
|
$response | from json
|
|
}
|
|
|
|
# List all available locales
|
|
#
|
|
# Returns a list of all currently loaded locale identifiers.
|
|
#
|
|
# # Returns
|
|
# List of locale strings
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-list-locales
|
|
# # Output: [en-US, es, fr-FR, de]
|
|
# ```
|
|
export def fluent-list-locales [] -> list<string> {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
let response = (http get $"($daemon_url)/fluent/bundles/locales")
|
|
|
|
($response | from json).locales
|
|
}
|
|
|
|
# Get translation statistics from daemon
|
|
#
|
|
# Returns statistics about translations since daemon startup or last reset.
|
|
#
|
|
# # Returns
|
|
# Record with:
|
|
# - `total_translations`: Total number of translations
|
|
# - `successful_translations`: Number of successful translations
|
|
# - `failed_translations`: Number of failed translations
|
|
# - `cache_hits`: Number of cache hits
|
|
# - `cache_misses`: Number of cache misses
|
|
# - `cache_hit_ratio`: Cache hit ratio (0.0 - 1.0)
|
|
# - `bundles_loaded`: Number of bundles loaded
|
|
# - `total_time_ms`: Total time spent translating (milliseconds)
|
|
# - `average_time_ms`: Average time per translation
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-stats
|
|
# ```
|
|
export def fluent-stats [] -> record {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
let response = (http get $"($daemon_url)/fluent/stats")
|
|
|
|
$response | from json
|
|
}
|
|
|
|
# Reset translation statistics on daemon
|
|
#
|
|
# Clears all counters and timing statistics.
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-reset-stats
|
|
# ```
|
|
export def fluent-reset-stats [] -> void {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
http post $"($daemon_url)/fluent/stats/reset" ""
|
|
}
|
|
|
|
# Clear all Fluent caches
|
|
#
|
|
# Clears both the translation cache and bundle cache.
|
|
# All subsequent translations will reload bundles and re-translate messages.
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-clear-caches
|
|
# ```
|
|
export def fluent-clear-caches [] -> void {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
|
|
http delete $"($daemon_url)/fluent/cache/clear"
|
|
}
|
|
|
|
# Check if CLI daemon is running with Fluent support
|
|
#
|
|
# # Returns
|
|
# `true` if daemon is running with Fluent support, `false` otherwise
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# if (is-fluent-daemon-available) {
|
|
# fluent-translate "welcome"
|
|
# } else {
|
|
# print "Fallback: Welcome!"
|
|
# }
|
|
# ```
|
|
export def is-fluent-daemon-available [] -> bool {
|
|
let result = (do {
|
|
let daemon_url = (get-cli-daemon-url)
|
|
let response = (http get $"($daemon_url)/fluent/health" --timeout 500ms)
|
|
|
|
($response | from json | .status == "healthy")
|
|
} | complete)
|
|
|
|
if $result.exit_code != 0 {
|
|
false
|
|
} else {
|
|
$result.stdout
|
|
}
|
|
}
|
|
|
|
# Ensure Fluent daemon is available
|
|
#
|
|
# Checks if the daemon is running and prints a status message.
|
|
# Useful for diagnostics and setup scripts.
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# ensure-fluent-daemon
|
|
# ```
|
|
export def ensure-fluent-daemon [] -> void {
|
|
if (is-fluent-daemon-available) {
|
|
print "✅ Fluent i18n daemon is available and running"
|
|
} else {
|
|
print "⚠️ Fluent i18n daemon is not available"
|
|
print " CLI daemon may not be running at http://localhost:9091"
|
|
print " Translations will not work until daemon is started"
|
|
}
|
|
}
|
|
|
|
# Profile translation performance
|
|
#
|
|
# Translates a message multiple times and reports timing statistics.
|
|
# Useful for benchmarking and performance optimization.
|
|
#
|
|
# # Arguments
|
|
# * `message_id` - Message ID to translate
|
|
# * `--locale (-l)` - Target locale (default: "en-US")
|
|
# * `--iterations (-i)` - Number of times to translate (default: 100)
|
|
# * `--args (-a)` - Arguments for variable interpolation (record)
|
|
#
|
|
# # Returns
|
|
# Record with performance metrics
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-profile "greeting" --locale es --iterations 1000 --args {name: "Usuario"}
|
|
# ```
|
|
export def fluent-profile [
|
|
message_id: string
|
|
--locale (-l): string = "en-US"
|
|
--iterations (-i): int = 100
|
|
--args (-a): record = {}
|
|
] -> record {
|
|
let start = (date now)
|
|
|
|
# Reset stats before profiling
|
|
fluent-reset-stats
|
|
|
|
# Run translations
|
|
for i in 0..<$iterations {
|
|
fluent-translate $message_id --locale $locale --args $args
|
|
}
|
|
|
|
let elapsed_ms = ((date now) - $start) | into duration | .0 / 1_000_000
|
|
let stats = (fluent-stats)
|
|
|
|
{
|
|
message_id: $message_id
|
|
locale: $locale
|
|
iterations: $iterations
|
|
total_time_ms: $elapsed_ms
|
|
avg_time_ms: ($elapsed_ms / $iterations)
|
|
daemon_total_translations: $stats.total_translations
|
|
daemon_cache_hits: $stats.cache_hits
|
|
daemon_cache_hit_ratio: $stats.cache_hit_ratio
|
|
daemon_avg_time_ms: $stats.average_time_ms
|
|
daemon_successful: $stats.successful_translations
|
|
daemon_failed: $stats.failed_translations
|
|
}
|
|
}
|
|
|
|
# Show cache efficiency report
|
|
#
|
|
# Displays a formatted report of cache performance.
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-cache-report
|
|
# ```
|
|
export def fluent-cache-report [] -> void {
|
|
let stats = (fluent-stats)
|
|
|
|
print $"=== Fluent i18n Cache Report ==="
|
|
print $""
|
|
print $"Total translations: ($stats.total_translations)"
|
|
print $"Cache hits: ($stats.cache_hits)"
|
|
print $"Cache misses: ($stats.cache_misses)"
|
|
print $"Hit ratio: (($stats.cache_hit_ratio * 100) | math round --precision 1)%"
|
|
print $""
|
|
print $"Average latency: ($stats.average_time_ms | math round --precision 2)ms"
|
|
print $"Total time: ($stats.total_time_ms)ms"
|
|
print $""
|
|
print $"Bundles loaded: ($stats.bundles_loaded)"
|
|
print $"Success rate: (($stats.successful_translations / $stats.total_translations * 100) | math round --precision 1)%"
|
|
}
|
|
|
|
# Translate and fallback to default if not found
|
|
#
|
|
# Attempts to translate a message, falling back to a default value if not found.
|
|
#
|
|
# # Arguments
|
|
# * `message_id` - Message ID to translate
|
|
# * `default` - Default value if translation fails
|
|
# * `--locale (-l)` - Target locale (default: "en-US")
|
|
# * `--args (-a)` - Arguments for variable interpolation (record)
|
|
#
|
|
# # Returns
|
|
# Translated message or default value
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# fluent-translate-or "new-feature" "New Feature" --locale fr
|
|
# ```
|
|
export def fluent-translate-or [
|
|
message_id: string
|
|
default: string
|
|
--locale (-l): string = "en-US"
|
|
--args (-a): record = {}
|
|
] -> string {
|
|
let result = (do {
|
|
fluent-translate $message_id --locale $locale --args $args
|
|
} | complete)
|
|
|
|
if $result.exit_code != 0 {
|
|
$default
|
|
} else {
|
|
$result.stdout
|
|
}
|
|
}
|
|
|
|
# Create a localized string table from message IDs
|
|
#
|
|
# Translates a list of message IDs and returns a record mapping IDs to translations.
|
|
#
|
|
# # Arguments
|
|
# * `message_ids` - List of message IDs
|
|
# * `--locale (-l)` - Target locale (default: "en-US")
|
|
#
|
|
# # Returns
|
|
# Record mapping message IDs to translated strings
|
|
#
|
|
# # Example
|
|
# ```nushell
|
|
# let ids = ["welcome", "goodbye", "help"]
|
|
# let strings = (fluent-string-table $ids --locale es)
|
|
# $strings.welcome # Accesses translated "welcome" message
|
|
# ```
|
|
export def fluent-string-table [
|
|
message_ids: list<string>
|
|
--locale (-l): string = "en-US"
|
|
] -> record {
|
|
let table = {}
|
|
|
|
for msg_id in $message_ids {
|
|
let translation = (fluent-translate $msg_id --locale $locale)
|
|
$table | insert $msg_id $translation
|
|
}
|
|
|
|
$table
|
|
}
|