adjustments to add right-to-left language

This commit is contained in:
schlagmichdoch 2023-10-05 17:11:16 +02:00
parent 8d0e560b1d
commit 117a4d3eb9
8 changed files with 240 additions and 62 deletions

View file

@ -142,14 +142,44 @@
</div>
<div class="language-buttons">
<button class="button fw" data-i18n-key="dialogs.system-language" data-i18n-attrs="text"></button>
<button class="button fw" value="en">English</button>
<button class="button fw" value="de">Deutsch (German)</button>
<button class="button fw" value="fr">Français (French)</button>
<button class="button fw" value="id">Bahasa Indonesia (Indonesian)</button>
<button class="button fw" value="nb">Norsk (Norwegian)</button>
<button class="button fw" value="ro">Română (Romanian)</button>
<button class="button fw" value="ru">Русский язык (Russian)</button>
<button class="button fw" value="zh-CN">中文 (Chinese)</button>
<button class="button fw" value="en">
<span>English</span>
</button>
<button class="button fw" value="de">
<span>Deutsch</span>
<span>-</span>
<span>(German)</span>
</button>
<button class="button fw" value="fr">
<span>Français</span>
<span>-</span>
<span>(French)</span>
</button>
<button class="button fw" value="id">
<span>Bahasa Indonesia</span>
<span>-</span>
<span>(Indonesian)</span>
</button>
<button class="button fw" value="nb">
<span>Norsk</span>
<span>-</span>
<span>(Norwegian)</span>
</button>
<button class="button fw" value="ro">
<span>Română</span>
<span>-</span>
<span>(Romanian)</span>
</button>
<button class="button fw" value="ru">
<span>Русский язык</span>
<span>-</span>
<span>(Russian)</span>
</button>
<button class="button fw" value="zh-CN">
<span>中文</span>
<span>-</span>
<span>(Chinese)</span>
</button>
</div>
<div class="center row-reverse button-row">
<button class="button" type="button" data-i18n-key="dialogs.close" data-i18n-attrs="text" close=""></button>
@ -168,7 +198,7 @@
<div class="row center">
<div class="column">
<div class="center key-qr-code"></div>
<h1 class="center key">000 000</h1>
<h1 class="center key" dir="ltr">000 000</h1>
<p class="center text-center key-instructions">
<span class="font-subheading" data-i18n-key="dialogs.input-key-on-this-device" data-i18n-attrs="text"></span>
<span class="font-subheading" data-i18n-key="dialogs.scan-qr-code" data-i18n-attrs="text"></span>
@ -183,7 +213,7 @@
</div>
<div class="row center">
<div class="column">
<div class="input-key-container six-chars">
<div class="input-key-container six-chars" dir="ltr">
<input type="tel" class="textarea center" aria-label="pair-key-char-1" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" autofocus="" contenteditable="" placeholder="" disabled="">
<input type="tel" class="textarea center" aria-label="pair-key-char-2" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
<input type="tel" class="textarea center" aria-label="pair-key-char-3" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
@ -238,7 +268,7 @@
<div class="row center">
<div class="column">
<div class="center key-qr-code"></div>
<h1 class="center key"></h1>
<h1 class="center key" dir="ltr"></h1>
<p class="center text-center key-instructions">
<span class="font-subheading" data-i18n-key="dialogs.input-room-id-on-another-device" data-i18n-attrs="text"></span>
<span class="font-subheading" data-i18n-key="dialogs.scan-qr-code" data-i18n-attrs="text"></span>
@ -253,7 +283,7 @@
</div>
<div class="row center">
<div class="column">
<div class="input-key-container">
<div class="input-key-container" dir="ltr">
<input type="text" class="textarea center" aria-label="room-id-char-1" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" autofocus="" contenteditable="" placeholder="" disabled="">
<input type="text" class="textarea center" aria-label="room-id-char-2" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
<input type="text" class="textarea center" aria-label="room-id-char-3" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
@ -422,7 +452,7 @@
<svg class="icon logo">
<use xlink:href="#wifi-tethering"></use>
</svg>
<div class="title-wrapper">
<div class="title-wrapper" dir="ltr">
<h1>PairDrop</h1>
<div class="font-subheading">v1.8.3</div>
</div>

View file

@ -2,10 +2,12 @@ class Localization {
constructor() {
Localization.defaultLocale = "en";
Localization.supportedLocales = ["en", "nb", "ru", "zh-CN", "de", "ro", "id", "fr"];
Localization.supportedLocalesRTL = [];
Localization.translations = {};
Localization.defaultTranslations = {};
Localization.systemLocale = Localization.supportedOrDefault(navigator.languages);
Localization.systemLocale = Localization.getSupportedOrDefault(navigator.languages);
let storedLanguageCode = localStorage.getItem("language-code");
@ -24,7 +26,11 @@ class Localization {
return Localization.supportedLocales.indexOf(locale) > -1;
}
static supportedOrDefault(locales) {
static isRTLLanguage(locale) {
return Localization.supportedLocalesRTL.indexOf(locale) > -1;
}
static getSupportedOrDefault(locales) {
return locales.find(Localization.isSupported) || Localization.defaultLocale;
}
@ -34,6 +40,17 @@ class Localization {
await Localization.setLocale(locale)
await Localization.translatePage();
const htmlRootNode = document.querySelector('html');
if (Localization.isRTLLanguage(locale)) {
htmlRootNode.setAttribute('dir', 'rtl');
} else {
htmlRootNode.removeAttribute('dir');
}
htmlRootNode.setAttribute('lang', locale);
console.log("Page successfully translated",
`System language: ${Localization.systemLocale}`,
`Selected language: ${locale}`

View file

@ -398,7 +398,7 @@ class PeerUI {
<div class="name font-subheading"></div>
<div class="device-name font-body2"></div>
<div class="status font-body2"></div>
<span class="connection-hash font-body2" title="${ Localization.getTranslation("peer-ui.connection-hash") }"></span>
<span class="connection-hash font-body2" dir="ltr" title="${ Localization.getTranslation("peer-ui.connection-hash") }"></span>
</div>
</label>`;

View file

@ -99,8 +99,7 @@ header {
right: 0;
}
header > a,
header > div {
header > *:not(:first-child) {
margin-left: 8px;
}
@ -673,7 +672,6 @@ footer .logo {
max-width: 15em;
text-overflow: ellipsis;
cursor: text;
margin-left: -1rem;
margin-bottom: -6px;
padding-bottom: 0.1rem;
border-radius: 1.3rem/30%;
@ -687,11 +685,27 @@ footer .logo {
#edit-pen {
width: 1rem;
height: 1rem;
margin-left: -1rem;
margin-bottom: -2px;
position: relative;
}
html:not([dir="rtl"]) {
#display-name,
#edit-pen {
margin-left: -1rem;
}
}
html[dir="rtl"] {
#display-name,
#edit-pen {
margin-right: -1rem;
}
#edit-pen {
transform: rotateY(180deg);
}
}
/* Dialog */
x-dialog x-background {
@ -799,8 +813,8 @@ x-dialog a {
justify-content: center;
}
.input-key-container > input + * {
margin-left: 6px;
.input-key-container > input {
margin: 0 3px;
}
.input-key-container.six-chars > input:nth-of-type(4) {
@ -811,11 +825,11 @@ x-dialog a {
-webkit-user-select: text;
-moz-user-select: text;
user-select: text;
font-size: 50px;
letter-spacing: min(calc((100vw - 80px - 99px) / 100 * 7), 23px);
display: inline-block;
text-indent: calc(0.5 * (11px + min(calc((100vw - 80px - 99px) / 100 * 6), 23px)));
margin: 15px -15px;
font-size: 50px;
letter-spacing: min(calc((100vw - 80px - 99px) / 100 * 7), 20px);
text-indent: calc(0.5 * (11px + min(calc((100vw - 80px - 99px) / 100 * 6), 28px)));
margin: 25px 0;
}
.key-qr-code {
@ -971,12 +985,28 @@ x-paper > .button-row > .button {
width: 100%;
}
x-paper > .button-row > .button:not(:first-child) {
border-right: solid 1.5px var(--border-color);
html:not([dir="rtl"]) {
& x-paper > .button-row > .button:not(:first-child) {
border-right: solid 1.5px var(--border-color);
}
& x-paper > .button-row > .button:not(:last-child) {
border-left: solid 1.5px var(--border-color);
}
}
x-paper > .button-row > .button:not(:last-child) {
border-left: solid 1.5px var(--border-color);
html[dir="rtl"] {
& x-paper > .button-row > .button:not(:first-child) {
border-left: solid 1.5px var(--border-color);
}
& x-paper > .button-row > .button:not(:last-child) {
border-right: solid 1.5px var(--border-color);
}
}
.language-buttons > button > span {
margin: 0 0.3em;
}
.file-description {
@ -1241,7 +1271,6 @@ button::-moz-focus-inner {
--size: max(max(230vw, 230vh), calc(150vh + 150vw));
--size-half: calc(var(--size)/2);
top: calc(28px - var(--size-half));
right: calc(36px - var(--size-half));
width: var(--size);
height: var(--size);
border-radius: 50%;
@ -1250,6 +1279,19 @@ button::-moz-focus-inner {
z-index: -1;
}
html:not([dir="rtl"]) {
#about x-background {
right: calc(36px - var(--size-half));
}
}
html[dir="rtl"] {
#about x-background {
left: calc(36px - var(--size-half));
}
}
/* Hack such that initial scale(0) isn't animated */
#about x-background {
will-change: transform;

View file

@ -147,14 +147,44 @@
</div>
<div class="language-buttons">
<button class="button fw" data-i18n-key="dialogs.system-language" data-i18n-attrs="text"></button>
<button class="button fw" value="en">English</button>
<button class="button fw" value="de">Deutsch (German)</button>
<button class="button fw" value="fr">Français (French)</button>
<button class="button fw" value="id">Bahasa Indonesia (Indonesian)</button>
<button class="button fw" value="nb">Norsk (Norwegian)</button>
<button class="button fw" value="ro">Română (Romanian)</button>
<button class="button fw" value="ru">Русский язык (Russian)</button>
<button class="button fw" value="zh-CN">中文 (Chinese)</button>
<button class="button fw" value="en">
<span>English</span>
</button>
<button class="button fw" value="de">
<span>Deutsch</span>
<span>-</span>
<span>(German)</span>
</button>
<button class="button fw" value="fr">
<span>Français</span>
<span>-</span>
<span>(French)</span>
</button>
<button class="button fw" value="id">
<span>Bahasa Indonesia</span>
<span>-</span>
<span>(Indonesian)</span>
</button>
<button class="button fw" value="nb">
<span>Norsk</span>
<span>-</span>
<span>(Norwegian)</span>
</button>
<button class="button fw" value="ro">
<span>Română</span>
<span>-</span>
<span>(Romanian)</span>
</button>
<button class="button fw" value="ru">
<span>Русский язык</span>
<span>-</span>
<span>(Russian)</span>
</button>
<button class="button fw" value="zh-CN">
<span>中文</span>
<span>-</span>
<span>(Chinese)</span>
</button>
</div>
<div class="center row-reverse button-row">
<button class="button" type="button" data-i18n-key="dialogs.close" data-i18n-attrs="text" close=""></button>
@ -173,7 +203,7 @@
<div class="row center">
<div class="column">
<div class="center key-qr-code"></div>
<h1 class="center key">000 000</h1>
<h1 class="center key" dir="ltr">000 000</h1>
<p class="center text-center key-instructions">
<span class="font-subheading" data-i18n-key="dialogs.input-key-on-this-device" data-i18n-attrs="text"></span>
<span class="font-subheading" data-i18n-key="dialogs.scan-qr-code" data-i18n-attrs="text"></span>
@ -188,7 +218,7 @@
</div>
<div class="row center">
<div class="column">
<div class="input-key-container six-chars">
<div class="input-key-container six-chars" dir="ltr">
<input type="tel" class="textarea center" aria-label="pair-key-char-1" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" autofocus="" contenteditable="" placeholder="" disabled="">
<input type="tel" class="textarea center" aria-label="pair-key-char-2" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
<input type="tel" class="textarea center" aria-label="pair-key-char-3" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
@ -243,7 +273,7 @@
<div class="row center">
<div class="column">
<div class="center key-qr-code"></div>
<h1 class="center key"></h1>
<h1 class="center key" dir="ltr"></h1>
<p class="center text-center key-instructions">
<span class="font-subheading" data-i18n-key="dialogs.input-room-id-on-another-device" data-i18n-attrs="text"></span>
<span class="font-subheading" data-i18n-key="dialogs.scan-qr-code" data-i18n-attrs="text"></span>
@ -258,7 +288,7 @@
</div>
<div class="row center">
<div class="column">
<div class="input-key-container">
<div class="input-key-container" dir="ltr">
<input type="text" class="textarea center" aria-label="room-id-char-1" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" autofocus="" contenteditable="" placeholder="" disabled="">
<input type="text" class="textarea center" aria-label="room-id-char-2" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
<input type="text" class="textarea center" aria-label="room-id-char-3" maxlength="1" autocorrect="off" autocomplete="off" autocapitalize="none" spellcheck="false" contenteditable="" placeholder="" disabled="">
@ -427,7 +457,7 @@
<svg class="icon logo">
<use xlink:href="#wifi-tethering"></use>
</svg>
<div class="title-wrapper">
<div class="title-wrapper" dir="ltr">
<h1>PairDrop</h1>
<div class="font-subheading">v1.8.3</div>
</div>

View file

@ -2,10 +2,12 @@ class Localization {
constructor() {
Localization.defaultLocale = "en";
Localization.supportedLocales = ["en", "nb", "ru", "zh-CN", "de", "ro", "id", "fr"];
Localization.supportedLocalesRTL = [];
Localization.translations = {};
Localization.defaultTranslations = {};
Localization.systemLocale = Localization.supportedOrDefault(navigator.languages);
Localization.systemLocale = Localization.getSupportedOrDefault(navigator.languages);
let storedLanguageCode = localStorage.getItem("language-code");
@ -24,7 +26,11 @@ class Localization {
return Localization.supportedLocales.indexOf(locale) > -1;
}
static supportedOrDefault(locales) {
static isRTLLanguage(locale) {
return Localization.supportedLocalesRTL.indexOf(locale) > -1;
}
static getSupportedOrDefault(locales) {
return locales.find(Localization.isSupported) || Localization.defaultLocale;
}
@ -34,6 +40,17 @@ class Localization {
await Localization.setLocale(locale)
await Localization.translatePage();
const htmlRootNode = document.querySelector('html');
if (Localization.isRTLLanguage(locale)) {
htmlRootNode.setAttribute('dir', 'rtl');
} else {
htmlRootNode.removeAttribute('dir');
}
htmlRootNode.setAttribute('lang', locale);
console.log("Page successfully translated",
`System language: ${Localization.systemLocale}`,
`Selected language: ${locale}`

View file

@ -398,7 +398,7 @@ class PeerUI {
<div class="name font-subheading"></div>
<div class="device-name font-body2"></div>
<div class="status font-body2"></div>
<span class="connection-hash font-body2" title="${ Localization.getTranslation("peer-ui.connection-hash") }"></span>
<span class="connection-hash font-body2" dir="ltr" title="${ Localization.getTranslation("peer-ui.connection-hash") }"></span>
</div>
</label>`;

View file

@ -100,8 +100,7 @@ header {
right: 0;
}
header > a,
header > div {
header > *:not(:first-child) {
margin-left: 8px;
}
@ -703,7 +702,6 @@ footer .logo {
max-width: 15em;
text-overflow: ellipsis;
cursor: text;
margin-left: -1rem;
margin-bottom: -6px;
padding-bottom: 0.1rem;
border-radius: 1.3rem/30%;
@ -717,11 +715,27 @@ footer .logo {
#edit-pen {
width: 1rem;
height: 1rem;
margin-left: -1rem;
margin-bottom: -2px;
position: relative;
}
html:not([dir="rtl"]) {
#display-name,
#edit-pen {
margin-left: -1rem;
}
}
html[dir="rtl"] {
#display-name,
#edit-pen {
margin-right: -1rem;
}
#edit-pen {
transform: rotateY(180deg);
}
}
/* Dialog */
x-dialog x-background {
@ -829,8 +843,8 @@ x-dialog a {
justify-content: center;
}
.input-key-container > input + * {
margin-left: 6px;
.input-key-container > input {
margin: 0 3px;
}
.input-key-container.six-chars > input:nth-of-type(4) {
@ -841,11 +855,11 @@ x-dialog a {
-webkit-user-select: text;
-moz-user-select: text;
user-select: text;
font-size: 50px;
letter-spacing: min(calc((100vw - 80px - 99px) / 100 * 7), 23px);
display: inline-block;
text-indent: calc(0.5 * (11px + min(calc((100vw - 80px - 99px) / 100 * 6), 23px)));
margin: 15px -15px;
font-size: 50px;
letter-spacing: min(calc((100vw - 80px - 99px) / 100 * 7), 20px);
text-indent: calc(0.5 * (11px + min(calc((100vw - 80px - 99px) / 100 * 6), 28px)));
margin: 25px 0;
}
.key-qr-code {
@ -1001,12 +1015,28 @@ x-paper > .button-row > .button {
width: 100%;
}
x-paper > .button-row > .button:not(:first-child) {
border-right: solid 1.5px var(--border-color);
html:not([dir="rtl"]) {
& x-paper > .button-row > .button:not(:first-child) {
border-right: solid 1.5px var(--border-color);
}
& x-paper > .button-row > .button:not(:last-child) {
border-left: solid 1.5px var(--border-color);
}
}
x-paper > .button-row > .button:not(:last-child) {
border-left: solid 1.5px var(--border-color);
html[dir="rtl"] {
& x-paper > .button-row > .button:not(:first-child) {
border-left: solid 1.5px var(--border-color);
}
& x-paper > .button-row > .button:not(:last-child) {
border-right: solid 1.5px var(--border-color);
}
}
.language-buttons > button > span {
margin: 0 0.3em;
}
.file-description {
@ -1271,7 +1301,6 @@ button::-moz-focus-inner {
--size: max(max(230vw, 230vh), calc(150vh + 150vw));
--size-half: calc(var(--size)/2);
top: calc(28px - var(--size-half));
right: calc(36px - var(--size-half));
width: var(--size);
height: var(--size);
border-radius: 50%;
@ -1280,6 +1309,19 @@ button::-moz-focus-inner {
z-index: -1;
}
html:not([dir="rtl"]) {
#about x-background {
right: calc(36px - var(--size-half));
}
}
html[dir="rtl"] {
#about x-background {
left: calc(36px - var(--size-half));
}
}
/* Hack such that initial scale(0) isn't animated */
#about x-background {
will-change: transform;