feat(i18n): add N() helper for numeric formatting
N(format, value) wraps T("i18n.numeric.{format}", value).
Supported formats:
- N("number", 1234567) → "1,234,567"
- N("decimal", 1234.5) → "1,234.5"
- N("percent", 0.85) → "85%"
- N("bytes", 1536000) → "1.5 MB"
- N("ordinal", 1) → "1st"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7b9f23dd9e
commit
8f977ed635
2 changed files with 51 additions and 28 deletions
|
|
@ -56,6 +56,17 @@ func _(messageID string, args ...any) string {
|
|||
return messageID
|
||||
}
|
||||
|
||||
// N formats a number using the i18n.numeric.* namespace.
|
||||
// Wrapper for T("i18n.numeric.{format}", value).
|
||||
//
|
||||
// N("number", 1234567) // T("i18n.numeric.number", 1234567)
|
||||
// N("percent", 0.85) // T("i18n.numeric.percent", 0.85)
|
||||
// N("bytes", 1536000) // T("i18n.numeric.bytes", 1536000)
|
||||
// N("ordinal", 1) // T("i18n.numeric.ordinal", 1)
|
||||
func N(format string, value any) string {
|
||||
return T("i18n.numeric."+format, value)
|
||||
}
|
||||
|
||||
// --- Template helpers ---
|
||||
|
||||
// executeIntentTemplate executes an intent template with the given data.
|
||||
|
|
|
|||
|
|
@ -314,36 +314,48 @@ func (s *Service) handleI18nNamespace(key string, args []any) string {
|
|||
return ActionFailed(verb, "")
|
||||
}
|
||||
|
||||
// i18n.number → FormatNumber(n)
|
||||
if key == "i18n.number" && len(args) > 0 {
|
||||
return FormatNumber(toInt64(args[0]))
|
||||
// i18n.numeric.* namespace (for N() helper)
|
||||
if strings.HasPrefix(key, "i18n.numeric.") && len(args) > 0 {
|
||||
format := strings.TrimPrefix(key, "i18n.numeric.")
|
||||
switch format {
|
||||
case "number", "int":
|
||||
return FormatNumber(toInt64(args[0]))
|
||||
case "decimal", "float":
|
||||
return FormatDecimal(toFloat64(args[0]))
|
||||
case "percent", "pct":
|
||||
return FormatPercent(toFloat64(args[0]))
|
||||
case "bytes", "size":
|
||||
return FormatBytes(toInt64(args[0]))
|
||||
case "ordinal", "ord":
|
||||
return FormatOrdinal(toInt(args[0]))
|
||||
case "ago":
|
||||
if len(args) >= 2 {
|
||||
if unit, ok := args[1].(string); ok {
|
||||
return FormatAgo(toInt(args[0]), unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// i18n.decimal → FormatDecimal(f)
|
||||
if key == "i18n.decimal" && len(args) > 0 {
|
||||
return FormatDecimal(toFloat64(args[0]))
|
||||
}
|
||||
|
||||
// i18n.percent → FormatPercent(f)
|
||||
if key == "i18n.percent" && len(args) > 0 {
|
||||
return FormatPercent(toFloat64(args[0]))
|
||||
}
|
||||
|
||||
// i18n.bytes → FormatBytes(n)
|
||||
if key == "i18n.bytes" && len(args) > 0 {
|
||||
return FormatBytes(toInt64(args[0]))
|
||||
}
|
||||
|
||||
// i18n.ordinal → FormatOrdinal(n)
|
||||
if key == "i18n.ordinal" && len(args) > 0 {
|
||||
return FormatOrdinal(toInt(args[0]))
|
||||
}
|
||||
|
||||
// i18n.ago → FormatAgo(count, unit)
|
||||
if key == "i18n.ago" && len(args) >= 2 {
|
||||
count := toInt(args[0])
|
||||
if unit, ok := args[1].(string); ok {
|
||||
return FormatAgo(count, unit)
|
||||
// Legacy i18n.{format} shortcuts (kept for compatibility)
|
||||
if len(args) > 0 {
|
||||
switch key {
|
||||
case "i18n.number":
|
||||
return FormatNumber(toInt64(args[0]))
|
||||
case "i18n.decimal":
|
||||
return FormatDecimal(toFloat64(args[0]))
|
||||
case "i18n.percent":
|
||||
return FormatPercent(toFloat64(args[0]))
|
||||
case "i18n.bytes":
|
||||
return FormatBytes(toInt64(args[0]))
|
||||
case "i18n.ordinal":
|
||||
return FormatOrdinal(toInt(args[0]))
|
||||
case "i18n.ago":
|
||||
if len(args) >= 2 {
|
||||
if unit, ok := args[1].(string); ok {
|
||||
return FormatAgo(toInt(args[0]), unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue