fix: use Intl.NumberFormat instead of vue-i18n n() for number formatting (#8600)

## Summary

vue-i18n's n() function does not support passing
Intl.NumberFormatOptions directly as the second argument. When widgets
without precision defined (e.g., KJNodes' CreateShapeImageOnPath) were
rendered, the n() function threw a SyntaxError in parseNumberArgs.

Replace n() with native Intl.NumberFormat which properly supports
NumberFormatOptions while still using the i18n locale for localization.

## Screenshots (if applicable)
before

https://github.com/user-attachments/assets/eb48379b-fe45-4f1c-a674-b92130f0fcac

after

https://github.com/user-attachments/assets/1abcd2da-ad8b-4432-831a-2a7e91f375a5



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Enhanced number input widgets with improved locale-aware number
formatting, ensuring proper decimal and group separator display based on
user locale settings.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8600-fix-use-Intl-NumberFormat-instead-of-vue-i18n-n-for-number-formatting-2fd6d73d365081b78509e87d516c6067)
by [Unito](https://www.unito.io)
This commit is contained in:
Terry Jia
2026-02-03 20:57:49 -05:00
committed by GitHub
parent 6499eda004
commit 507500a9d7

View File

@@ -15,7 +15,7 @@ import {
import { WidgetInputBaseClass } from './layout'
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
const { n } = useI18n()
const { locale } = useI18n()
const props = defineProps<{
widget: SimplifiedWidget<number>
@@ -30,8 +30,16 @@ onClickOutside(widgetContainer, () => {
}
})
const decimalSeparator = computed(() => n(1.1).replace(/\p{Number}/gu, ''))
const groupSeparator = computed(() => n(11111).replace(/\p{Number}/gu, ''))
function formatNumber(value: number, options?: Intl.NumberFormatOptions) {
return new Intl.NumberFormat(locale.value, options).format(value)
}
const decimalSeparator = computed(() =>
formatNumber(1.1).replace(/\p{Number}/gu, '')
)
const groupSeparator = computed(() =>
formatNumber(11111).replace(/\p{Number}/gu, '')
)
function unformatValue(value: string) {
return value
.replaceAll(groupSeparator.value, '')
@@ -45,11 +53,14 @@ const formattedValue = computed(() => {
if ((unformattedValue as unknown) === '' || !isFinite(unformattedValue))
return `${unformattedValue}`
return n(unformattedValue, {
useGrouping: useGrouping.value,
minimumFractionDigits: precision.value,
maximumFractionDigits: precision.value
})
const options: Intl.NumberFormatOptions = {
useGrouping: useGrouping.value
}
if (precision.value !== undefined) {
options.minimumFractionDigits = precision.value
options.maximumFractionDigits = precision.value
}
return formatNumber(unformattedValue, options)
})
function updateValue(e: UIEvent) {