Skip to content

Add L10N storage for localized database object content - #6703

Open
BurntimeX wants to merge 15 commits into
6.3from
63-l10n
Open

Add L10N storage for localized database object content#6703
BurntimeX wants to merge 15 commits into
6.3from
63-l10n

Conversation

@BurntimeX

Copy link
Copy Markdown
Member

Summary

Introduces a dedicated L10N storage system for localized content of database objects, replacing the previous approach of storing such content as i18n phrases in wcf1_language_item. Localized values now live in a per-object <table>_l10n table (objectID, nullable languageID, payload columns), read/written through a single L10nStorage service. Captcha questions and user options are migrated to the new system as the first adopters.

The L10N system

  • L10nStorage – the only writer/reader for *_l10n tables. Exchanges values as columnName => [languageID => value], supports monolingual content (languageID IS NULL, exposed as L10nStorage::MONOLINGUAL), per-column language sets, a deterministic fallback resolver (resolveValue()), and a correlated getSubSelect() for sortable/filterable list queries.
  • L10nDefinition – describes a localized table (primary table, *_l10n table, object column, payload columns). Optionally declares support for synchronization with language variables via an identifierColumnName + per-column language-variable suffixes.
  • Form fieldIL10nFormField / TL10nFormField add ->l10n() support to form builder fields, mutually exclusive with the phrase-based ->i18n() mode.
  • CollectionsTCollectionL10n trait batch-loads the localized values of all objects in a DatabaseObjectCollection in a single query; OptionCollection / UserOptionCollection / CaptchaQuestionCollection and the L10n*List classes wire this into lists and grid views. L10nTextFilter filters grid columns on localized values.

Synchronization with language variables

Delivered objects (e.g. shipped user options) keep their wcf.* phrases as the source
of truth and mirror them into the L10N storage:

  • The primary table gains an l10nIdentifier column (the language-variable base name, NULL for admin-created objects), and the *_l10n table an isPristine flag.
  • Definitions that support the sync register via the L10nDefinitionCollecting event; SyncL10nLanguageItems runs at the end of every install/update and refreshes pristine rows from the phrases, preserving values an administrator changed locally.
  • isPristine is maintained automatically inside L10nStorage::setValues(): a delivered object keeps the flag per language while the value is unchanged; a changed value or a user-created object is written as modified. L10nLanguageItemSync provides reusable one-time migrate() / ongoing sync() helpers (usable by other packages).

Migrations

  • Captcha questions and user options are refactored to DatabaseObjectBuilder with dedicated create/update commands and events.
  • User options move their title/description from wcf.user.option.* phrases into wcf1_user_option_l10n; system options stay linked (pristine, kept in sync), admin-created options own their values and their obsolete phrases are removed.
  • UserOptionPackageInstallationPlugin and UserOptionImporter write through the new builder / L10N storage; the ACP forms, grid views, cache builder and templates read localized titles/descriptions from the collection.
  • Removed template scripting from the shipped user-option descriptions, which is no longer supported for L10N content.

Notes

  • New *_l10n tables are created via explicit database scripts (install + update); no automatic table provisioning.
  • PackageInstallationDispatcher invokes the sync after the bootstrap loader is rebuilt, so listeners added by the same update are already active.

See #6109
See #6290

@BurntimeX
BurntimeX requested a review from dtdesign July 31, 2026 16:37
@BurntimeX BurntimeX moved this to Foundation in WoltLab Suite 6.3 Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Foundation

Development

Successfully merging this pull request may close these issues.

1 participant