Skip to content

Add i18n support for toolbar and table translations#940

Open
AliOsm wants to merge 4 commits intobasecamp:mainfrom
AliOsm:main
Open

Add i18n support for toolbar and table translations#940
AliOsm wants to merge 4 commits intobasecamp:mainfrom
AliOsm:main

Conversation

@AliOsm
Copy link
Copy Markdown

@AliOsm AliOsm commented Apr 4, 2026

This adds i18n support to Lexxy so toolbar and table labels can be translated.

I'm using Lexxy in a bilingual Arabic/English Rails app, and the hardcoded English labels in the toolbar, table controls, and link dialog were the one thing I couldn't customize through the existing config system. I was patching them with MutationObservers that watched for <lexxy-editor> and <lexxy-table-tools> elements, then rewrote title attributes and text content after render. Table row/column counts needed a second observer since Lexxy resets them on every update. It worked, but it was fragile and fighting the framework.

With this change, translations go through configure() like everything else:

configure({
  i18n: {
    locale: "ar",
    ar: {
      toolbar: { bold: "عريض", italic: "مائل", ... },
      table: { row: "صف", column: "عمود", ... }
    }
  }
})

You only need to provide the keys you want to translate. Missing keys fall back to English. See src/config/locales/en.js for the list of available keys.

Table count labels use Intl.PluralRules for locale-aware pluralization, which matters for languages like Arabic that have 6 plural forms:

rowCount: { one: "صف واحد", two: "صفان", few: "%{count} صفوف", many: "%{count} صفًا", other: "%{count} صف" }

When no i18n config is provided, nothing changes. The existing English strings are the defaults.

Unit tests added for the i18n module. All existing tests (Vitest + Playwright) pass.

Screenshot 2026-04-04 at 6 56 46 AM

Copilot AI review requested due to automatic review settings April 4, 2026 03:57
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds internationalization (i18n) support to Lexxy, enabling toolbar and table labels to be translated through the configuration system. Users can register additional locales with partial translation overrides, with automatic fallback to English for missing keys.

Changes:

  • Add i18n module (I18n class) with locale registry, translation lookup with fallback, pluralization support via Intl.PluralRules, and variable interpolation
  • Create English locale file with all translatable toolbar and table strings
  • Integrate i18n into configuration system via Lexxy.configure()
  • Replace hardcoded English strings in toolbar, table controls, and editor with translated labels
  • Add comprehensive unit tests for i18n functionality
  • Document i18n feature with examples for partial translations, pluralization, and interpolation

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/config/i18n.js New I18n class implementing translation lookup, fallback, pluralization, and interpolation
src/config/locales/en.js New English locale with all toolbar and table translation keys
src/config/lexxy.js Integration of i18n instance and configuration handling
src/elements/toolbar.js Replaced hardcoded English strings with translation calls in toolbar template
src/elements/table/table_tools.js Replaced hardcoded English strings with translation calls in table controls
src/elements/editor.js Replaced hardcoded heading format labels with translations
test/javascript/unit/config/i18n.test.js Comprehensive unit tests for i18n module
docs/configuration.md Added i18n documentation with examples

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

dropdown.tabIndex = -1

const count = createElement("summary", {}, `_ ${childType}s`)
const count = createElement("summary", {}, t(`table.${childType}Count`, { count: "_" }))
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The count parameter is passed as the string "_" instead of a number. While the placeholder is replaced with actual numeric counts later by #updateRowColumnCount(), using a non-numeric value for Intl.PluralRules.select() is technically incorrect. The initial placeholder should use a number (e.g., 0) to ensure correct plural form selection from the start.

Suggested change
const count = createElement("summary", {}, t(`table.${childType}Count`, { count: "_" }))
const count = createElement("summary", {}, t(`table.${childType}Count`, { count: 0 }))

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used _ to preserve the old behavior. _ will fallback to the other plural option and produce correct output.

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.

2 participants