Sitelet https://github.com/Syncplay/syncplay/pull/810
Skip to content

Fix Arabic, Hebrew and Persian text in mpv chat and the chat log - #810

Open
yuroyami wants to merge 3 commits into
Syncplay:masterfrom
yuroyami:fix-rtl-text
Open

yuroyami wants to merge 3 commits into
Syncplay:masterfrom
yuroyami:fix-rtl-text

Conversation

@yuroyami

Copy link
Copy Markdown

Problem

When a text (written in RTL language) In the mpv chat and in mpv notifications is displayed, the letters of each word show in the opposite order. The word بنجاح shows as حاجنب. Numbers next to this text also change order. The time 10:30 shows as 03:01.

In the chat log, the ! and ? characters go to the wrong end of the line. An Arabic user name can push the time stamp into the middle of the line.

Cause

On mpv: wordwrapify_string puts {\fscx0} {\fscx100} between all characters. This marker contains two spaces. You cannot see the spaces, but the Unicode direction rules still use them. libass then shows each Arabic letter as a separate word.

On Syncplay client: the chat log has a different cause. All messages are in one Qt paragraph, and Qt gives one direction to a full paragraph.

Changes

syncplayintf.lua does not add the wrap markers to a line that contains RTL letters. libass breaks such a line at the spaces. It also breaks a word that is too long for the screen.

gui.py and mpv.py put Unicode isolate marks (U+2068 and U+2069) around each chat line and each user name. You cannot see the marks. Each part of the line keeps its own direction.

The chat log removes these marks again when a user copies or drags text. The copied data stays the same as before this change, in plain text, HTML, Markdown and OpenDocument.

What stays the same

Text without RTL letters shows exactly as before. The mpv screenshots have 0 different pixels. The layout stays left to right.

Limits

A notification is checked as one text. If one line of it has RTL letters, all lines of that notification lose the wrap markers.

A copy from the chat log also removes U+2068 and U+2069 characters that a user typed.

Tests

I tested on macOS with Python 3.14, PySide6 6.11.2, mpv 0.40.0 and libass 0.17.4.

For mpv, I sent chat messages and notifications through the real syncplayintf.lua. I compared the screenshots from before and after the change.

For the chat log, I sent messages through MainWindow.showMessage into a QTextBrowser, before and after the change.

For the copy, I compared the copied data against the same log without the marks. I used 16 selections, in light and dark mode, with Arabic text and emoji. All four formats are the same. A copy of a full log with 2,000 messages takes about 50 ms.

I did not test drag and drop, the Windows (PySide2) build or the Linux build. VLC, MPC-HC and mplayer have no code change.

Screenshots

mpv chat, before and after:

mpv-before-after

Chat log, before and after:

chatlog-before-after

This change follows the wrap changes from #804.

mpv: wordwrapify_string put {\fscx0}  {\fscx100} between every
character. The two hidden spaces split RTL words into single letters,
so libass showed them in reverse order. Text with RTL letters now
skips these markers. libass still wraps it.

Chat log and mpv chat: each line and each username gets Unicode
isolate marks (U+2068/U+2069), so RTL text keeps its own direction
next to LTR text.

Text without RTL letters renders the same as before.
The chat log wraps each line and user name in U+2068/U+2069. Copy
and drag took these invisible marks along, so a copied link could
end with U+2069 and fail to open.

ChatLogBrowser removes the marks from the selection. It gives the
same copy formats as Qt (plain text, HTML, Markdown, ODF) with the
same content as before. The selection is not laid out, because the
log is one long paragraph and its layout takes seconds.
@yuroyami

Copy link
Copy Markdown
Author

This clears the way for an Arabic translation I'm working on next. Right now RTL text isn't readable so the translation has nothing to land on until this merges.

A first-strong isolate on every chat log line gave a notification the
direction of its first letter. An English notification that starts
with an Arabic user name showed its words in reverse order. English
chat that starts with an Arabic word had the same problem.

- Notification and error lines are UI text, so they get a
  left-to-right isolate.
- Chat and MOTD lines get the direction of most of their words. If
  both directions have the same number of words, the first letter
  decides.
- Only lines and user names with RTL characters get isolate marks.
  Other text is the same as before, byte for byte.
- mpv notifications get the same isolates as the chat log.
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