1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-03 22:35:45 +02:00

i18n: support RTL languages

This patch introduces some mechanisms to fully support RTL languages:
1. RTL detection via UtilsAdapter::isRTL() checking the locale name
2. Using QML mirroring when needed based on UtilsAdapter.isRTL
3. Inverting panels in DualPaneView and JamiListView when needed
with SinglePane support

Moreover, lot of anchors are added to automatically manage layout
updates.

GitLab: #235
Change-Id: I40c245f2d7fae96d796c53505af5403f5e813e7f
This commit is contained in:
Sébastien Blin 2023-05-10 11:05:43 -04:00 committed by Aline Gondim Santos
parent 44d807e6ab
commit e073c6f8a8
33 changed files with 130 additions and 38 deletions

View file

@ -37,6 +37,11 @@ import "commoncomponents"
ApplicationWindow {
id: root
property bool isRTL: UtilsAdapter.isRTL
LayoutMirroring.enabled: isRTL
LayoutMirroring.childrenInherit: isRTL
enum LoadedSource {
WizardView,
MainView,

View file

@ -31,6 +31,8 @@ PushButton {
preferredHeight: JamiTheme.wizardViewPageBackButtonHeight
hoveredColor: JamiTheme.hoveredButtonColorWizard
mirror: Qt.application.layoutDirection === Qt.RightToLeft
source: JamiResources.ic_arrow_back_24dp_svg
toolTipText: JamiStrings.back

View file

@ -30,8 +30,11 @@ BaseView {
property alias splitViewStateKey: splitView.splitViewStateKey
property real leftPaneMinWidth: JamiTheme.mainViewLeftPaneMinWidth
property real rightPaneMinWidth: JamiTheme.mainViewPaneMinWidth
property real minorPaneMinWidth: JamiTheme.mainViewLeftPaneMinWidth
property real majorPaneMinWidth: JamiTheme.mainViewPaneMinWidth
property real previousMinorPaneWidth: leftPane.width
property real previousMajorPaneWidth: rightPane.width
property bool isSinglePane
@ -50,10 +53,9 @@ BaseView {
onIsSinglePaneChanged.connect(isSinglePaneChangedHandler);
}
property real previousLeftPaneWidth: leftPane.width
onWidthChanged: resolvePanes()
function resolvePanes() {
isSinglePane = width < rightPaneMinWidth + previousLeftPaneWidth;
isSinglePane = width < majorPaneMinWidth + previousMinorPaneWidth;
}
// Override this if needed.
@ -65,19 +67,27 @@ BaseView {
id: splitView
anchors.fill: parent
splitViewStateKey: viewNode.objectName
isSinglePane: viewNode.isSinglePane
Item {
SplitPane {
id: leftPane
onWidthChanged: if (!isSinglePane)
previousLeftPaneWidth = width
SplitView.minimumWidth: isSinglePane ? viewNode.width : viewNode.leftPaneMinWidth
SplitView.maximumWidth: isSinglePane ? viewNode.width : viewNode.width - rightPaneMinWidth
SplitView.preferredWidth: viewNode.leftPaneMinWidth
clip: true
isMinorPane: true
}
Item {
SplitPane {
id: rightPane
clip: true
isMinorPane: false
}
}
component SplitPane: Item {
clip: true
required property bool isMinorPane
onWidthChanged: {
if (!isSinglePane && isMinorPane)
previousMinorPaneWidth = width;
}
SplitView.minimumWidth: isSinglePane ? viewNode.width : (isMinorPane ? minorPaneMinWidth : majorPaneMinWidth)
SplitView.maximumWidth: isSinglePane ? viewNode.width : viewNode.width - (isMinorPane ? majorPaneMinWidth : minorPaneMinWidth)
SplitView.preferredWidth: isMinorPane ? minorPaneMinWidth : majorPaneMinWidth
}
}

View file

@ -22,6 +22,13 @@ import net.jami.Constants 1.1
SplitView {
id: root
property bool isRTL: UtilsAdapter.isRTL
property bool isSinglePane: false
property bool isSwapped: UtilsAdapter.isRTL
onIsRTLChanged: swapItems()
onIsSinglePaneChanged: swapItems()
property string splitViewStateKey: objectName
property bool autoManageState: !(parent instanceof BaseView)
@ -41,11 +48,26 @@ SplitView {
visible ? restoreSplitViewState() : saveSplitViewState();
}
function swapItems() {
if ((isSinglePane && !isSwapped) // Do not swap in isSinglePane mode
|| (!isRTL && !isSwapped)) // Do not swap if not RTL
return;
var qqci = children[0];
if (qqci.children.length > 1) {
// swap the children
var tempPane = qqci.children[0];
qqci.children[0] = qqci.children[1];
qqci.children.push(tempPane);
isSwapped = true
}
}
handle: Rectangle {
implicitWidth: JamiTheme.splitViewHandlePreferredWidth
implicitHeight: root.height
color: JamiTheme.primaryBackgroundColor
Rectangle {
anchors.left: parent.left
implicitWidth: 1
implicitHeight: root.height
color: JamiTheme.tabbarBorderColor

View file

@ -72,8 +72,10 @@ RadioButton {
contentItem: Text {
text: root.text
color: root.color
leftPadding: root.indicator.width + root.spacing
anchors.left: rect.right
anchors.leftMargin: root.spacing
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
font.pixelSize: JamiTheme.settingsDescriptionPixelSize
}

View file

@ -74,6 +74,8 @@ AbstractButton {
property alias imagePadding: image.padding
property alias imageOffset: image.offset
property alias mirror: image.mirror
width: preferredWidth ? preferredWidth : preferredSize
height: preferredHeight ? preferredHeight : preferredSize

View file

@ -32,6 +32,7 @@ Item {
property alias source: image.source
property alias status: image.status
property alias cache: image.cache
property alias mirror: image.mirror
property string color: "transparent"
property bool hovered: false
property bool mirrorHorizontally: false
@ -67,8 +68,6 @@ Item {
antialiasing: true
asynchronous: true
visible: false
mirror: root.mirrorHorizontally
mirrorVertically: root.mirrorVertically
function setSourceSize() {
sourceSize = undefined;

View file

@ -85,7 +85,12 @@ ComboBox {
}
contentItem: Text {
leftPadding: root.indicator.width
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: root.indicator.width
width: parent.width - root.indicator.width * 2
anchors.rightMargin: root.indicator.width * 2
font.pixelSize: JamiTheme.settingsDescriptionPixelSize
text: root.displayText
color: JamiTheme.comboboxTextColor

View file

@ -455,9 +455,8 @@ Item {
property real typingDotsSize: 8
// MessageWebView File Transfer Container
property real filesToSendContainerSpacing: 120
property real filesToSendContainerSpacing: 25
property real filesToSendContainerPadding: 10
property real filesToSendDelegateWidth: 100
property real filesToSendDelegateHeight: 100
property real filesToSendDelegateRadius: 7
property real filesToSendDelegateButtonSize: 16

View file

@ -139,6 +139,7 @@ Label {
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.textColor
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
Text {
@ -155,6 +156,7 @@ Label {
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.faddedLastInteractionFontColor
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
}

View file

@ -72,6 +72,7 @@ ItemDelegate {
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.textColor
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
Text {
@ -86,6 +87,7 @@ ItemDelegate {
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.faddedLastInteractionFontColor
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
}

View file

@ -72,6 +72,7 @@ Item {
Layout.leftMargin: root.margin
Layout.preferredWidth: root.prefWidth - 2 * root.margin - root.iconSize
font.pixelSize: JamiTheme.tipBoxTitleFontSize
horizontalAlignment: Text.AlignLeft
elide: Qt.ElideRight
}
}
@ -87,6 +88,7 @@ Item {
font.weight: Font.Normal
text: JamiStrings.whyBackupAccount
color: JamiTheme.textColor
horizontalAlignment: Text.AlignLeft
}
Text {
@ -98,6 +100,7 @@ Item {
wrapMode: Text.WordWrap
text: JamiStrings.backupAccountInfos
color: JamiTheme.textColor
horizontalAlignment: Text.AlignLeft
}
MaterialButton {

View file

@ -250,6 +250,9 @@ Rectangle {
StackLayout {
id: chatViewStack
LayoutMirroring.enabled: false
LayoutMirroring.childrenInherit: true
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.fillHeight: true

View file

@ -221,8 +221,8 @@ Rectangle {
objectName: "dataTransferSendContainer"
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: footerColumnLayout.width
Layout.maximumWidth: JamiTheme.chatViewMaximumWidth
Layout.fillWidth: true
Layout.rightMargin: 10
Layout.preferredHeight: filesToSendCount ? JamiTheme.filesToSendDelegateHeight : 0
}
}

View file

@ -83,6 +83,8 @@ Rectangle {
preferredSize: 24
mirror: UtilsAdapter.isRTL
source: JamiResources.back_24dp_svg
toolTipText: CurrentConversation.inCall ? JamiStrings.backCall : JamiStrings.hideChat

View file

@ -61,6 +61,7 @@ ColumnLayout {
visible: !opened
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: column.margin
horizontalAlignment: Text.AlignLeft
font.pixelSize: JamiTheme.tipBoxTitleFontSize
elide: Qt.ElideRight
}
@ -71,6 +72,7 @@ ColumnLayout {
Layout.leftMargin: 20
Layout.topMargin: 8
Layout.bottomMargin: 15
horizontalAlignment: Text.AlignLeft
font.pixelSize: JamiTheme.tipBoxContentFontSize
visible: !opened
wrapMode: Text.WordWrap

View file

@ -107,13 +107,11 @@ Item {
anchors.fill: parent
anchors.margins: 8
source: {
if(mediaInfo.isVideo)
return JamiResources.video_file_svg
if(mediaInfo.isAudio)
return JamiResources.audio_file_svg
return JamiResources.attached_file_svg
if (mediaInfo.isVideo)
return JamiResources.video_file_svg;
if (mediaInfo.isAudio)
return JamiResources.audio_file_svg;
return JamiResources.attached_file_svg;
}
cache: false
color: JamiTheme.textColor
@ -163,6 +161,7 @@ Item {
color: JamiTheme.chatviewTextColor
text: TransferName
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
RowLayout {

View file

@ -19,6 +19,7 @@ import QtQuick
import QtQuick.Controls
import net.jami.Models 1.1
import net.jami.Constants 1.1
import net.jami.Adapters 1.1
import "../../commoncomponents"
Rectangle {
@ -28,6 +29,9 @@ Rectangle {
property alias filesToSendCount: repeater.count
color: JamiTheme.primaryBackgroundColor
LayoutMirroring.enabled: UtilsAdapter.isRTL
LayoutMirroring.childrenInherit: true
JamiFlickable {
id: filesToSendContainerScrollView
@ -44,6 +48,8 @@ Rectangle {
anchors.centerIn: parent
layoutDirection: UtilsAdapter.isRTL ? Qt.RightToLeft : Qt.LeftToRight
spacing: JamiTheme.filesToSendContainerSpacing
padding: JamiTheme.filesToSendContainerPadding
@ -53,7 +59,6 @@ Rectangle {
delegate: FilesToSendDelegate {
anchors.verticalCenter: filesToSendContainerRow.verticalCenter
width: JamiTheme.filesToSendDelegateWidth
height: JamiTheme.filesToSendDelegateHeight
onRemoveFileButtonClicked: function (index) {

View file

@ -29,6 +29,8 @@ Item {
property real margin: 5
signal removeFileButtonClicked(int index)
width: JamiTheme.layoutWidthFileTransfer * 2
RowLayout {
anchors.fill: root
@ -158,6 +160,7 @@ Item {
font.bold: true
text: FileName
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
RowLayout {

View file

@ -62,6 +62,7 @@ ColumnLayout {
Layout.leftMargin: 8
Layout.preferredWidth: column.prefWidth - 2 * column.margin - column.iconSize
font.pixelSize: JamiTheme.tipBoxTitleFontSize
horizontalAlignment: Text.AlignLeft
elide: Qt.ElideRight
}
}
@ -75,6 +76,7 @@ ColumnLayout {
wrapMode: Text.WordWrap
font.weight: opened ? Font.Medium : Font.Normal
text: root.title
horizontalAlignment: Text.AlignLeft
color: JamiTheme.textColor
}
@ -85,6 +87,7 @@ ColumnLayout {
visible: opened
wrapMode: Text.WordWrap
text: root.description
horizontalAlignment: Text.AlignLeft
color: JamiTheme.textColor
}
}

View file

@ -144,6 +144,7 @@ Item {
Layout.preferredHeight: 50
leftPadding: 16
rightPadding: 16
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter

View file

@ -189,6 +189,7 @@ ColumnLayout {
id: messageBarRowLayout
spacing: JamiTheme.chatViewFooterRowSpacing
anchors.left: parent.left
Row {
@ -843,6 +844,8 @@ ColumnLayout {
toolTipText: JamiStrings.send
mirror: UtilsAdapter.isRTL
source: JamiResources.send_black_24dp_svg
normalColor: JamiTheme.chatViewFooterSendButtonColor

View file

@ -87,6 +87,7 @@ JamiFlickable {
selectByMouse: true
textFormat: TextEdit.PlainText
placeholderTextColor: JamiTheme.placeholderTextColor
horizontalAlignment: Text.AlignLeft
background: Rectangle {
border.width: 0

View file

@ -119,7 +119,7 @@ Rectangle {
}
}
SplitView {
JamiSplitView {
id: mainColumnLayout
anchors.fill: parent
@ -127,12 +127,6 @@ Rectangle {
property bool isHorizontal: false // Calculated when showing the stack view
orientation: isHorizontal ? Qt.Horizontal : Qt.Vertical
handle: Rectangle {
implicitWidth: isHorizontal ? JamiTheme.splitViewHandlePreferredWidth : root.width
implicitHeight: isHorizontal ? root.height : JamiTheme.splitViewHandlePreferredWidth
color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor)
}
Rectangle {
id: callPageMainRect

View file

@ -135,6 +135,7 @@ ItemDelegate {
Layout.fillWidth: true
Layout.minimumHeight: 20
Layout.alignment: Qt.AlignVCenter
horizontalAlignment: Text.AlignLeft
elide: Text.ElideMiddle
text: Title === undefined ? "" : Title
textFormat: TextEdit.PlainText
@ -166,6 +167,7 @@ ItemDelegate {
elide: Text.ElideRight
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
horizontalAlignment: Text.AlignLeft
text: Draft ?
Draft :
(LastInteraction === undefined ? "" : LastInteraction)

View file

@ -178,6 +178,7 @@ ListSelectionView {
Flow {
id: flow
spacing: 13
layoutDirection: UtilsAdapter.isRTL ? Qt.RightToLeft : Qt.LeftToRight
Repeater {
id: tipsRepeater

View file

@ -50,6 +50,7 @@ ItemDelegate {
Layout.rightMargin: JamiTheme.preferredMarginSize
Layout.preferredWidth: JamiTheme.preferredFieldHeight
Layout.preferredHeight: JamiTheme.preferredFieldHeight
horizontalAlignment: Text.AlignLeft
background: Avatar {
id: avatar

View file

@ -116,9 +116,10 @@ ItemDelegate {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
Layout.leftMargin: editDeviceName.leftPadding
Layout.rightMargin: editDeviceName.leftPadding
Layout.bottomMargin: 10
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
elide: Text.ElideMiddle
font.pointSize: JamiTheme.textFontSize
color: JamiTheme.textColor
text: deviceId === "" ? JamiStrings.deviceId : deviceId

View file

@ -26,6 +26,8 @@ ProgressBar {
property real rmsLevel: 0
LayoutMirroring.enabled: false
value: {
return clamp(rmsLevel * 300.0, 0.0, 100.0);
}

View file

@ -63,6 +63,8 @@ RowLayout {
Layout.alignment: Qt.AlignCenter
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
LayoutMirroring.enabled: false
LayoutMirroring.childrenInherit: true
onValueChanged: newValue()

View file

@ -139,6 +139,7 @@ SettingsPageBase {
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
LayoutMirroring.enabled: false
labelText: JamiStrings.language
tipText: JamiStrings.language

View file

@ -48,6 +48,7 @@ UtilsAdapter::UtilsAdapter(AppSettingsManager* settingsManager,
if (lrcInstance_->avModel().getRecordPath().isEmpty()) {
lrcInstance_->avModel().setRecordPath(getDefaultRecordPath());
}
set_isRTL(isRTL());
}
QVariant
@ -80,6 +81,7 @@ UtilsAdapter::setAppValue(const Settings::Key key, const QVariant& value)
if (key == Settings::Key::LANG) {
settingsManager_->loadTranslations();
Q_EMIT changeLanguage();
set_isRTL(isRTL());
} else if (key == Settings::Key::BaseZoom)
Q_EMIT changeFontSize();
else if (key == Settings::Key::EnableExperimentalSwarm)
@ -808,3 +810,11 @@ UtilsAdapter::getVideoPlayer(const QString& resource, const QString& bgColor)
{"html", htmlVideo.arg(resource, bgColor)},
};
}
bool
UtilsAdapter::isRTL()
{
auto pref = getAppValue(Settings::Key::LANG).toString();
pref == "SYSTEM" ? QLocale::system().name() : pref;
return pref == "ar" || pref == "he" || pref == "fa" || pref == "ur";
}

View file

@ -66,6 +66,7 @@ class UtilsAdapter final : public QmlAdapterBase
{
Q_OBJECT
QML_PROPERTY(QStringList, logList)
QML_RO_PROPERTY(bool, isRTL)
public:
explicit UtilsAdapter(AppSettingsManager* settingsManager,
SystemTray* systemTray,
@ -149,6 +150,8 @@ public:
Q_INVOKABLE QVariantMap getVideoPlayer(const QString& resource, const QString& bgColor);
Q_INVOKABLE bool isRTL();
Q_SIGNALS:
void debugMessageReceived(const QString& message);
void changeFontSize();