Skip to content

Issue apache#2814 [Bug]: changing GUI language changes also decimal separator - #8159

Draft
sramazzina wants to merge 2 commits into
apache:mainfrom
sramazzina:bugfix/2814-regional-settings
Draft

Issue apache#2814 [Bug]: changing GUI language changes also decimal separator#8159
sramazzina wants to merge 2 commits into
apache:mainfrom
sramazzina:bugfix/2814-regional-settings

Conversation

@sramazzina

@sramazzina sramazzina commented Aug 28, 2026

Copy link
Copy Markdown
Contributor
  • The interface language was installed as the JVM-wide default locale, so it also decided decimal separator, grouping separator, currency and date formats. The language now writes only Locale.Category.DISPLAY and the regional settings write Locale.Category.FORMAT.
  • Regional settings had no representation of their own. Added RegionalSettings in core, resolving a single source - OPERATING_SYSTEM (the default), CUSTOM or LANGUAGE - from RegionalSettingsSource and RegionalSettingsLocale in hop-config.json; an unreadable or unknown configuration degrades to OPERATING_SYSTEM.
  • Locale.setDefault lived in HopGui.main, so hop-run and hop-server never applied it and the same pipeline formatted differently in the editor and in production. The regional settings are now applied from HopEnvironment.init(), the bootstrap common to every entry point.
  • Const.DEFAULT_DECIMAL_SEPARATOR and its siblings are static final, computed at class load before any locale was installed, and ValueMetaBase copied them into every value, overwriting correctly localised symbols. Added getDefaultDecimalSeparator(), getDefaultGroupingSeparator(), getDefaultCurrencySymbol() and getDefaultNumberFormat(), which read the live FORMAT category and cache the symbols against the locale they were built from; the constants are kept and deprecated because they are public API.
  • The setting was not reachable from the GUI. Added a Regional settings tab carrying the interface language combo moved out of GUI options, two mutually exclusive checkboxes, a type-to-filter combo over the available locales and a live preview of the resulting formats.
  • ValueMetaBase and ValueMetaTimestamp compared an explicitly chosen date format locale against Locale.getDefault(), so a field locale that happened to match the interface language was discarded and the date rendered with the regional locale instead. The comparison now reads the FORMAT category.

Fixes #2814


Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:

  • Run mvn clean install apache-rat:check to make sure basic checks pass. A more thorough check will be performed on your pull request automatically.
  • If you have a group of commits related to the same change, please squash your commits into one and force push your branch using git rebase -i.
  • Mention the appropriate issue in your description (for example: addresses #123), if applicable.

To make clear that you license your contribution under the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.

@sramazzina sramazzina added this to the 2.20 milestone Aug 28, 2026
@sramazzina
sramazzina marked this pull request as draft August 28, 2026 17:25
@mattcasters

Copy link
Copy Markdown
Contributor

I started the work to bring this PR in line with main and fix a few of the oversights in it. Then I'll create another PR to implement the requested features from both @hansva and myself, including integration tests.

sramazzina and others added 2 commits August 29, 2026 11:46
…eparator

* The interface language was installed as the JVM-wide default locale, so it
  also decided decimal separator, grouping separator, currency and date
  formats. The language now writes only Locale.Category.DISPLAY and the
  regional settings write Locale.Category.FORMAT.
* Regional settings had no representation of their own. Added RegionalSettings
  in core, resolving a single source - OPERATING_SYSTEM (the default), CUSTOM
  or LANGUAGE - from RegionalSettingsSource and RegionalSettingsLocale in
  hop-config.json; an unreadable or unknown configuration degrades to
  OPERATING_SYSTEM.
* Locale.setDefault lived in HopGui.main, so hop-run and hop-server never
  applied it and the same pipeline formatted differently in the editor and in
  production. The regional settings are now applied from HopEnvironment.init(),
  the bootstrap common to every entry point.
* Const.DEFAULT_DECIMAL_SEPARATOR and its siblings are static final, computed
  at class load before any locale was installed, and ValueMetaBase copied them
  into every value, overwriting correctly localised symbols. Added
  getDefaultDecimalSeparator(), getDefaultGroupingSeparator(),
  getDefaultCurrencySymbol() and getDefaultNumberFormat(), which read the live
  FORMAT category and cache the symbols against the locale they were built
  from; the constants are kept and deprecated because they are public API.
* The setting was not reachable from the GUI. Added a Regional settings tab
  carrying the interface language combo moved out of GUI options, two mutually
  exclusive checkboxes, a type-to-filter combo over the available locales and a
  live preview of the resulting formats.
* ValueMetaBase and ValueMetaTimestamp compared an explicitly chosen date
  format locale against Locale.getDefault(), so a field locale that happened to
  match the interface language was discarded and the date rendered with the
  regional locale instead. The comparison now reads the FORMAT category.

Fixes apache#2814
ValueMetaBase copied Locale.getDefault() into every field, which is the
interface language once DISPLAY and FORMAT are split. New fields now take
the FORMAT category so month names follow regional settings, not the GUI
language.

hop-gui, hop-run and hop-server log the effective language, FORMAT locale
and timezone at start so a machine-local mismatch is visible.

Docs: field-level symbols still win; default OS source still differs
across machines unless Override is set; Beam/Spark workers do not load
hop-config.json.
@mattcasters
mattcasters force-pushed the bugfix/2814-regional-settings branch from a1cba08 to b932755 Compare August 29, 2026 10:25
@mattcasters

Copy link
Copy Markdown
Contributor

Rebased onto current main (the HopGui conflict with session isolation) and pushed two small follow-ups on top of Sergio's original commit:

  • ValueMetaBase now takes dateFormatLocale from Locale.Category.FORMAT, not the interface language, so a field with no explicit date locale follows regional settings rather than the GUI language.
  • hop-gui / hop-run / hop-server log the effective language, FORMAT locale and timezone at start (Regional settings: language=… format=… timezone=… source=installation:…).
  • Docs: field-level decimal/grouping/date locale still win; the default OS source still differs across machines unless Override is set; Beam/Spark workers never load hop-config.json.

Still draft. Lifecycle-environment locale/timezone (and the hop-run integration tests for “works on my machine”) are intentionally not in this PR.

@mattcasters

Copy link
Copy Markdown
Contributor

Follow-up for the environment-level FORMAT locale and timezone (Hans' locality concern: laptop nl_BE vs hop-server en_US) is in #8172. It is stacked on this PR: Regional tab on the environment dialog, HOP_FORMAT_LOCALE / HOP_TIMEZONE, and locale-us / locale-eu integration tests.

Please merge this one first. Incremental diff of #8172: sramazzina:hop:bugfix/2814-regional-settings...mattcasters:hop:issue-2814-environment-regional

@sramazzina

Copy link
Copy Markdown
Contributor Author

Thanks for picking this up, and for the ValueMetaBase constructor fix in particular — that is the same defect we had chased on the comparison path, and we missed the assignment side of it entirely.

One thought that came up while reading the commit, purely as an observation.

The new logEffective() line reads as a start-up line, and for hop-run and hop-server that is exactly what it is: one line per process. In the GUI it also fires during normal use, because our ConfigRegionalSettingsTab.save() calls applyGui() on every widget event — so a user trying out the tab, ticking a checkbox, picking a locale, changing their mind, ends up writing a long run of near-identical Regional settings: … lines into the log. That is our side meeting your call site, nothing you could have seen from yours.

What made us stop on it is Hop Web, where that tab is reachable and the process is a long-lived server. There the noise is not transient: it accumulates in a server log that outlives the session, mixed in with everything else that log is meant to carry.

No strong opinion on the fix, and it may well not be worth the churn. Happy to push something small here if you want it handled, otherwise feel free to leave it as is.

@sramazzina

Copy link
Copy Markdown
Contributor Author

A follow-up on the log line, now that we have run it in the GUI. It prints twice at start-up:

2026/08/31 13:00:47 - General - Regional settings: language=en_US format=bo_CN timezone=Europe/Rome source=installation:CUSTOM
2026/08/31 13:00:50 - General - Regional settings: language=it_IT format=bo_CN timezone=Europe/Rome source=installation:CUSTOM

Hop GUI goes through both apply paths: HopEnvironment.init() calls applyHeadless(), and HopGui.main calls applyGui() a moment later. The first one runs before the interface language is installed, so it reports the JVM language rather than the configured one — en_US above, on a GUI that is actually running it_IT.

Together with the lines the configuration tab emits per widget event, that is what we were describing earlier.

We have a small patch sitting locally that moves the call to the entry points (HopGui.main, HopRun, HopServer) and leaves the static logEffective(ILogChannel, String) alone so the environment work keeps using it. Happy to push it here if you want it off your plate, or to leave it entirely to you — no rush either way.

@mattcasters

Copy link
Copy Markdown
Contributor

I don't know what it is lately but Claude Opus/Fable have been very verbose concerning even the smallest things. Humans are reading this Claude, have a care.

Please note that it's NOT the same line so it's not "printed twice". I only fixed this issue to make sure #8172 could be done. It's all yours if there are improvements you want to make. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: changing GUI language changes also decimal separator

2 participants