Skip to content

fix(fireedge): preload locale catalog server-side to eliminate translation flash - #7978

Open
huiquanyun wants to merge 1 commit into
OpenNebula:masterfrom
huiquanyun:fix/translation-flash-preload
Open

fix(fireedge): preload locale catalog server-side to eliminate translation flash#7978
huiquanyun wants to merge 1 commit into
OpenNebula:masterfrom
huiquanyun:fix/translation-flash-preload

Conversation

@huiquanyun

Copy link
Copy Markdown

Summary

FireEdge Sunstone currently flashes untranslated (English) text on every page load before the locale catalog is asynchronously loaded. This PR eliminates the flash by preloading the default locale catalog server-side and initialising TranslationProvider with those messages.

Problem

When a user opens FireEdge Sunstone, the TranslationProvider component initialises its translation state with an empty messages object:/n/n```javascript
const [state, setState] = useState({
error: null,
isLoading: true,
locale,
messages: {}, // ← empty on first render
})


The actual locale catalog is loaded asynchronously via a dynamically injected `<script>` tag (`loadMessages`). Until the script loads and resolves, the UI renders with no translations — showing English source text (or translation constant names) for a brief but noticeable flash.

This is particularly impactful for non-English locales (e.g. `zh_CN`, `fr_FR`) where the untranslated text is completely foreign to the user.

## Solution

Two minimal changes:/n/n### 1. Server-side locale preload (`App.js`)

Read the default locale JSON catalog at request time and inject it into the HTML as `window.locale`:

```javascript
const defaultLang = appConfig?.default_lang ?? 'en'
const preloadedLocale = loadLocaleCatalog(defaultLang)

// In HTML template:/nconst localePreload = `
  <script id="preload-locale">
    window.locale = ${ensuredScriptValue(preloadedLocale)}
  </script>`

loadLocaleCatalog reads from client/assets/languages/<locale>.json and gracefully returns {} if the file is missing or unparseable.

2. Client-side TranslationProvider init (translationProvider.js)

Initialise the translation state with the preloaded messages instead of an empty object:/n/n```javascript
const preloadedMessages = root.locale ?? {}
const hasPreloaded = Object.keys(preloadedMessages).length > 0

const [state, setState] = useState({
error: null,
isLoading: !hasPreloaded,
locale,
messages: preloadedMessages,
})


The async `loadMessages` call still runs in `useEffect` to ensure the full catalog is loaded. If the preloaded catalog is already complete, the state simply updates to the same value with no visual change.

## Compatibility

- **No breaking changes**: Falls back to original behavior if `window.locale` is not set.
- **No workflow changes**: The Transifex → PO → JSON pipeline is untouched.
- **Performance**: Reading a ~6KB JSON file synchronously at request time has negligible impact.

## Testing

1. Set `default_lang: zh_CN` in `fireedge-server.conf`
2. Ensure `client/assets/languages/zh_CN.json` exists with translations
3. Open FireEdge Sunstone in a browser
4. **Before this PR**: Page flashes English text for ~200-500ms before switching to Chinese
5. **After this PR**: Page renders Chinese immediately on first paint

## Files Changed

- `src/fireedge/src/server/routes/entrypoints/App.js` — Add `loadLocaleCatalog()` and `preload-locale` script injection
- `src/fireedge/src/modules/providers/translationProvider.js` — Initialise state with `root.locale ?? {}`

…ation flash

TranslationProvider initialises with an empty messages object, causing a
flash of untranslated (English) text on every page load before the async
locale script resolves. This is particularly impactful for non-English
locales (zh_CN, fr_FR, etc.) where untranslated text is completely foreign.

Changes:/n- App.js: Read the default locale JSON at request time and inject as
  window.locale in the HTML template (alongside existing preloads)
- translationProvider.js: Initialise useState with root.locale ?? {}
  instead of {}, so the first render uses preloaded translations

The async loadMessages path is unchanged and still runs to ensure the
full catalog is loaded. Falls back gracefully if the JSON file is missing.

Tested on OpenNebula 7.2.0 with zh_CN locale.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant