Merge pull request #70 from Goudarz/feature/bidirectional-support

Add RTL Support with Automatic HTML Attributes
This commit is contained in:
Dionisio Pozo
2026-02-08 13:42:47 +01:00
committed by GitHub
8 changed files with 132 additions and 1 deletions
+4
View File
@@ -60,6 +60,10 @@
.auth-form {
width: 100%;
text-align: left;
[dir='rtl'] & {
text-align: right;
}
}
.auth-input-group {
+10
View File
@@ -15,6 +15,11 @@
cursor: pointer;
z-index: 5;
transition: all 0.2s ease;
[dir='rtl'] & {
left: 10px;
right: unset;
}
}
.favorite-indicator:hover {
@@ -34,6 +39,11 @@
/* Ajustes para la vista de cuadrícula */
.file-card.favorite-item {
border-left: 3px solid #ffc107;
[dir='rtl'] & {
border-right: 3px solid #ffc107;
border-left: unset;
}
}
/* Ajustes para la vista de lista */
+10
View File
@@ -13,6 +13,11 @@
border-radius: 50%;
color: #6c757d;
z-index: 5;
[dir='rtl'] & {
left: 10px;
right: unset;
}
}
/* Estilos para los elementos de la vista de recientes */
@@ -23,6 +28,11 @@
/* Ajustes para la vista de cuadrícula */
.file-card.recent-item {
border-left: 3px solid #6c757d;
[dir='rtl'] & {
border-right: 3px solid #6c757d;
border-left: unset;
}
}
/* Ajustes para la vista de lista */
+70
View File
@@ -93,6 +93,11 @@ select:focus {
align-items: center;
justify-content: center;
margin-right: 10px;
[dir='rtl'] & {
margin-left: 10px;
margin-right: unset;
}
}
.logo svg {
@@ -137,6 +142,11 @@ select:focus {
margin-right: 15px;
width: 20px;
text-align: center;
[dir='rtl'] & {
margin-left: 15px;
margin-right: unset;
}
}
/* Storage indicator */
@@ -202,6 +212,11 @@ select:focus {
margin-right: 20px;
display: flex;
align-items: center;
[dir='rtl'] & {
margin-left: 20px;
margin-right: unset;
}
}
.search-container input {
@@ -241,6 +256,11 @@ select:focus {
font-size: 16px;
pointer-events: none;
transition: color 0.2s ease;
[dir='rtl'] & {
right: 16px;
left: unset;
}
}
.search-container input:focus + .search-icon,
@@ -265,6 +285,11 @@ select:focus {
justify-content: center;
transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(255, 94, 58, 0.3);
[dir='rtl'] & {
left: 6px;
right: unset;
}
}
.search-button:hover {
@@ -1058,6 +1083,11 @@ select:focus {
margin-right: 8px;
width: 16px;
text-align: center;
[dir='rtl'] & {
margin-left: 8px;
margin-right: unset;
}
}
/* Dialog */
@@ -1153,6 +1183,13 @@ select:focus {
border-left: 4px solid #ff5e3a;
z-index: 1000;
display: none;
[dir='rtl'] & {
left: 20px;
border-right: 4px solid #ff5e3a;
right: unset;
border-left: unset;
}
}
.notification-title {
@@ -1221,6 +1258,11 @@ select:focus {
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
[dir='rtl'] & {
margin-left: 14px;
margin-right: unset;
}
}
.modal-icon i {
@@ -1251,6 +1293,11 @@ select:focus {
justify-content: center;
color: #64748b;
transition: all 0.15s ease;
[dir='rtl'] & {
left: 16px;
right: unset;
}
}
.modal-close-btn:hover {
@@ -1571,6 +1618,10 @@ header {
background-repeat: no-repeat;
background-position: right 10px center;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
[dir='rtl'] & {
background-position: left 10px center;
}
}
.filter-group select:hover {
@@ -1990,11 +2041,21 @@ header {
.folder-select-item.selected {
background-color: #e6f7ff;
border-left: 3px solid #1890ff;
[dir='rtl'] & {
border-right: 3px solid #1890ff;
border-left: unset;
}
}
.folder-select-item i {
margin-right: 8px;
color: #ffc107;
[dir='rtl'] & {
margin-left: 8px;
margin-right: unset;
}
}
/* Styles for trash */
@@ -2241,3 +2302,12 @@ header {
.button.primary:hover {
background-color: #e64a29;
}
html[dir='rtl'] .fa-arrow-left::before {
content: "\f061";
}
html[dir='rtl'] .fa-sign-out-alt {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
+5
View File
@@ -34,6 +34,11 @@ const LANGUAGE_TEXTS = {
title: '欢迎使用 OxiCloud',
subtitle: '请选择您的语言',
continue: '继续'
},
fa: {
title: 'به OxiCloud خوش آمدید',
subtitle: 'لطفا زبان خود را انتخاب کنید',
continue: 'ادامه'
}
};
+25 -1
View File
@@ -11,6 +11,24 @@ const languages = [
{ code: 'fa', name: 'فارسی', flag: '🦁' }
];
// RTL languages
const rtlLanguages = ['fa']; // ['fa', 'ar']
// Update HTML lang attribute and dir for RTL languages
function updateHtmlAttributes(langCode) {
const htmlElement = document.documentElement;
// Set lang attribute
htmlElement.setAttribute('lang', langCode);
// Set dir attribute for RTL languages
if (rtlLanguages.includes(langCode)) {
htmlElement.setAttribute('dir', 'rtl');
} else {
htmlElement.removeAttribute('dir');
}
}
/**
* Creates and initializes a custom language selector component
* @param {string} containerId - ID of the container element
@@ -32,6 +50,9 @@ function createLanguageSelector(containerId = 'language-selector') {
const currentLocale = window.i18n ? window.i18n.getCurrentLocale() : 'en';
const currentLang = languages.find(l => l.code === currentLocale) || languages[0];
// Set initial HTML attributes
updateHtmlAttributes(currentLocale);
// Create toggle button
const toggle = document.createElement('div');
toggle.className = 'language-selector-toggle';
@@ -150,6 +171,9 @@ async function selectLanguage(langCode, container) {
await window.i18n.setLocale(langCode);
}
// Update HTML lang attribute and dir for RTL languages
updateHtmlAttributes(langCode);
updateSelectedLanguage(langCode, container);
closeDropdown(container);
}
@@ -178,4 +202,4 @@ function updateSelectedLanguage(langCode, container) {
// Create language selector when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
createLanguageSelector();
});
});
+7
View File
@@ -52,6 +52,13 @@
<span class="language-flag">🇨🇳</span>
<span class="language-name">中文</span>
</label>
<label class="language-option" data-lang="fa">
<input type="radio" name="language" value="fa">
<span class="language-radio"></span>
<span class="language-flag">🦁</span>
<span class="language-name">فارسی</span>
</label>
</div>
<button type="button" class="auth-button" id="language-continue" disabled>Continue</button>
+1
View File
@@ -7,6 +7,7 @@ const ASSETS_TO_CACHE = [
'/js/languageSelector.js',
'/locales/en.json',
'/locales/es.json',
'/locales/fa.json',
'/favicon.ico',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css',
'https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js'