feat: add rtl support (#2178)
parent
a49105db1d
commit
2c14146a31
|
@ -16,6 +16,10 @@
|
||||||
transition: .2s ease transform;
|
transition: .2s ease transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl .shell {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
.shell__result {
|
.shell__result {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
|
@ -5,6 +5,10 @@ body {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +62,11 @@ nav {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl nav {
|
||||||
|
left: unset;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
nav .action {
|
nav .action {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -69,6 +78,11 @@ nav .action {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl .action {
|
||||||
|
direction: rtl;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
nav > div {
|
nav > div {
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
@ -101,6 +115,10 @@ main {
|
||||||
border-radius: 0.125em;
|
border-radius: 0.125em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl .breadcrumbs a {
|
||||||
|
transform: translateX(-16em);
|
||||||
|
}
|
||||||
|
|
||||||
.breadcrumbs a:hover {
|
.breadcrumbs a:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl .dashboard .row {
|
||||||
|
margin-right: 16em;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard .row .column {
|
.dashboard .row .column {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 .5em;
|
padding: 0 .5em;
|
||||||
|
@ -60,6 +64,10 @@ p code {
|
||||||
border-bottom: 2px solid rgba(0, 0, 0, 0.05);
|
border-bottom: 2px solid rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #nav .wrapper {
|
||||||
|
margin-right: 16em;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard #nav ul {
|
.dashboard #nav ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -138,6 +146,13 @@ table tr>*:first-child {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl table tr>* {
|
||||||
|
padding-left: unset;
|
||||||
|
padding-right: 1em;
|
||||||
|
text-align: right;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
table tr>*:last-child {
|
table tr>*:last-child {
|
||||||
padding-right: 1em;
|
padding-right: 1em;
|
||||||
}
|
}
|
||||||
|
@ -181,6 +196,11 @@ table tr>*:last-child {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl .card .card-title>*:first-child {
|
||||||
|
margin-right: 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
.card>div {
|
.card>div {
|
||||||
padding: 1em 1em;
|
padding: 1em 1em;
|
||||||
}
|
}
|
||||||
|
@ -462,3 +482,9 @@ table tr>*:last-child {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** RTL - Fix disk usage information (in english) ***/
|
||||||
|
body.rtl .credits {
|
||||||
|
text-align: right;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
|
@ -135,10 +135,25 @@ header .menu-button {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #search #result {
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
#search #result>div>*:first-child {
|
#search #result>div>*:first-child {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #search #result {
|
||||||
|
direction: rtl;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** RTL - Keep search result LTR because it has paths (in english) ***/
|
||||||
|
body.rtl #search #result ul>* {
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
#search.active #result {
|
#search.active #result {
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
height: calc(100% - 4em);
|
height: calc(100% - 4em);
|
||||||
|
@ -224,6 +239,10 @@ header .menu-button {
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #search .boxes h3 {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
#search .boxes>div {
|
#search .boxes>div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
--item-selected: white;
|
--item-selected: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #listing {
|
||||||
|
margin-right: 16em;
|
||||||
|
}
|
||||||
|
|
||||||
#listing h2 {
|
#listing h2 {
|
||||||
margin: 0 0 0 0.5em;
|
margin: 0 0 0 0.5em;
|
||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
|
|
|
@ -40,6 +40,13 @@
|
||||||
transform-origin: top right;
|
transform-origin: top right;
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #dropdown {
|
||||||
|
right: unset;
|
||||||
|
left: 1em;
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
||||||
|
|
||||||
#dropdown > div {
|
#dropdown > div {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -95,9 +102,20 @@
|
||||||
transition: .1s ease left;
|
transition: .1s ease left;
|
||||||
left: -17em;
|
left: -17em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl nav {
|
||||||
|
left: unset;
|
||||||
|
right: -17em;
|
||||||
|
}
|
||||||
nav.active {
|
nav.active {
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl nav.active {
|
||||||
|
left: unset;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
header .search-button,
|
header .search-button,
|
||||||
header .menu-button {
|
header .menu-button {
|
||||||
display: inherit;
|
display: inherit;
|
||||||
|
@ -108,6 +126,23 @@
|
||||||
#listing {
|
#listing {
|
||||||
margin-bottom: 5em;
|
margin-bottom: 5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.rtl #listing {
|
||||||
|
margin-right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.rtl .breadcrumbs {
|
||||||
|
transform: translateX(16em);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.rtl #nav .wrapper {
|
||||||
|
margin-right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.rtl .dashboard .row {
|
||||||
|
margin-right: unset;
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
margin: 0 1em;
|
margin: 0 1em;
|
||||||
width: calc(100% - 2em);
|
width: calc(100% - 2em);
|
||||||
|
|
|
@ -315,6 +315,11 @@ main .spinner .bounce2 {
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** RTL - flip and position arrow of path ***/
|
||||||
|
body.rtl .breadcrumbs .chevron {
|
||||||
|
transform: scaleX(-1) translateX(16em);
|
||||||
|
}
|
||||||
|
|
||||||
#editor-container .breadcrumbs span {
|
#editor-container .breadcrumbs span {
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
}
|
}
|
||||||
|
@ -404,3 +409,22 @@ main .spinner .bounce2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@import './mobile.css';
|
@import './mobile.css';
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * *
|
||||||
|
* RTL overrides *
|
||||||
|
* * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
body.rtl .card-content textarea {
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.rtl .card-content .small + input {
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.rtl .card.floating .card-content .file-list {
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
|
@ -100,6 +100,8 @@ const removeEmpty = (obj) =>
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const rtlLanguages = ["he", "ar"];
|
||||||
|
|
||||||
const i18n = new VueI18n({
|
const i18n = new VueI18n({
|
||||||
locale: detectLocale(),
|
locale: detectLocale(),
|
||||||
fallbackLocale: "en",
|
fallbackLocale: "en",
|
||||||
|
|
|
@ -13,7 +13,7 @@ import Shares from "@/views/settings/Shares";
|
||||||
import Errors from "@/views/Errors";
|
import Errors from "@/views/Errors";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { baseURL, name } from "@/utils/constants";
|
import { baseURL, name } from "@/utils/constants";
|
||||||
import i18n from "@/i18n";
|
import i18n, { rtlLanguages } from "@/i18n";
|
||||||
|
|
||||||
Vue.use(Router);
|
Vue.use(Router);
|
||||||
|
|
||||||
|
@ -158,6 +158,18 @@ router.beforeEach((to, from, next) => {
|
||||||
const title = i18n.t(titles[to.name]);
|
const title = i18n.t(titles[to.name]);
|
||||||
document.title = title + " - " + name;
|
document.title = title + " - " + name;
|
||||||
|
|
||||||
|
/*** RTL related settings per route ****/
|
||||||
|
const rtlSet = document.querySelector("body").classList.contains("rtl");
|
||||||
|
const shouldSetRtl = rtlLanguages.includes(i18n.locale);
|
||||||
|
switch (true) {
|
||||||
|
case shouldSetRtl && !rtlSet:
|
||||||
|
document.querySelector("body").classList.add("rtl");
|
||||||
|
break;
|
||||||
|
case !shouldSetRtl && rtlSet:
|
||||||
|
document.querySelector("body").classList.remove("rtl");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (to.matched.some((record) => record.meta.requiresAuth)) {
|
if (to.matched.some((record) => record.meta.requiresAuth)) {
|
||||||
if (!store.getters.isLogged) {
|
if (!store.getters.isLogged) {
|
||||||
next({
|
next({
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
import { mapState, mapMutations } from "vuex";
|
import { mapState, mapMutations } from "vuex";
|
||||||
import { users as api } from "@/api";
|
import { users as api } from "@/api";
|
||||||
import Languages from "@/components/settings/Languages";
|
import Languages from "@/components/settings/Languages";
|
||||||
|
import i18n, { rtlLanguages } from "@/i18n";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "settings",
|
name: "settings",
|
||||||
|
@ -143,6 +144,9 @@ export default {
|
||||||
singleClick: this.singleClick,
|
singleClick: this.singleClick,
|
||||||
dateFormat: this.dateFormat,
|
dateFormat: this.dateFormat,
|
||||||
};
|
};
|
||||||
|
const shouldReload =
|
||||||
|
rtlLanguages.includes(data.locale) !==
|
||||||
|
rtlLanguages.includes(i18n.locale);
|
||||||
await api.update(data, [
|
await api.update(data, [
|
||||||
"locale",
|
"locale",
|
||||||
"hideDotfiles",
|
"hideDotfiles",
|
||||||
|
@ -150,6 +154,9 @@ export default {
|
||||||
"dateFormat",
|
"dateFormat",
|
||||||
]);
|
]);
|
||||||
this.updateUser(data);
|
this.updateUser(data);
|
||||||
|
if (shouldReload) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
this.$showSuccess(this.$t("settings.settingsUpdated"));
|
this.$showSuccess(this.$t("settings.settingsUpdated"));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$showError(e);
|
this.$showError(e);
|
||||||
|
|
Loading…
Reference in New Issue