diff --git a/esbuild/esbuild.js b/esbuild/esbuild.js
index efa1959969..a0b07abe43 100644
--- a/esbuild/esbuild.js
+++ b/esbuild/esbuild.js
@@ -8,6 +8,7 @@ let yargs = require("yargs");
let cliui = require("cliui")();
let chalk = require("chalk");
let html_plugin = require("./frappe-html");
+let rtlcss = require('rtlcss');
let postCssPlugin = require("esbuild-plugin-postcss2").default;
let ignore_assets = require("./ignore-assets");
let sass_options = require("./sass_options");
@@ -99,6 +100,7 @@ async function execute() {
let result;
try {
result = await build_assets_for_apps(APPS, FILES_TO_BUILD);
+ result = await create_rtl_assets(result);
} catch (e) {
log_error("There were some problems during build");
log();
@@ -260,7 +262,8 @@ async function clean_dist_folders(apps) {
let public_path = get_public_path(app);
let paths = [
path.resolve(public_path, "dist", "js"),
- path.resolve(public_path, "dist", "css")
+ path.resolve(public_path, "dist", "css"),
+ path.resolve(public_path, "dist", "css-rtl")
];
for (let target of paths) {
if (fs.existsSync(target)) {
@@ -484,3 +487,23 @@ function log_rebuilt_assets(prev_assets, new_assets) {
}
log();
}
+
+async function create_rtl_assets(result) {
+ for (let file_path in result.metafile.outputs) {
+ if (file_path.endsWith('.css')) {
+ console.log(file_path);
+ let content = fs.readFileSync(file_path, {'encoding': 'utf-8'});
+ let rtl_content = rtlcss.process(content);
+ let rtl_file_path = file_path.replace('/css/', '/css-rtl/');
+ let rtl_folder_path = path.dirname(rtl_file_path);
+ if (fs.existsSync(rtl_file_path)) {
+ continue;
+ }
+ if (!fs.existsSync(rtl_folder_path)) {
+ fs.mkdirSync(rtl_folder_path);
+ }
+ fs.writeFileSync(rtl_file_path, rtl_content);
+ }
+ }
+ return result;
+}
\ No newline at end of file
diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js
index 65c0139b65..9d106f46f4 100644
--- a/frappe/public/js/frappe/desk.js
+++ b/frappe/public/js/frappe/desk.js
@@ -64,8 +64,6 @@ frappe.Application = class Application {
}
});
- this.set_rtl();
-
// page container
this.make_page_container();
this.set_route();
@@ -489,16 +487,6 @@ frappe.Application = class Application {
}, 100);
}
- set_rtl() {
- if (frappe.utils.is_rtl()) {
- var ls = document.createElement('link');
- ls.rel="stylesheet";
- ls.type = "text/css";
- ls.href= frappe.assets.bundled_asset("frappe-rtl.bundle.css");
- document.getElementsByTagName('head')[0].appendChild(ls);
- $('body').addClass('frappe-rtl');
- }
- }
show_change_log() {
var me = this;
diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py
index 2c14249672..30a0e46232 100644
--- a/frappe/utils/jinja_globals.py
+++ b/frappe/utils/jinja_globals.py
@@ -73,8 +73,13 @@ def include_script(path):
return f''
-def include_style(path):
+def include_style(path, rtl=None):
path = bundled_asset(path)
+ if rtl is None:
+ rtl = is_rtl()
+
+ if rtl:
+ path = path.replace('/css/', '/css-rtl/')
return f''
@@ -87,3 +92,7 @@ def bundled_asset(path):
path = bundled_assets.get(path) or path
return abs_url(path)
+
+def is_rtl():
+ from frappe import local
+ return local.lang in ["ar", "he", "fa", "ps"]
\ No newline at end of file
diff --git a/frappe/www/app.html b/frappe/www/app.html
index c8172693b9..8704ed2671 100644
--- a/frappe/www/app.html
+++ b/frappe/www/app.html
@@ -1,5 +1,5 @@
-
+
diff --git a/frappe/www/app.py b/frappe/www/app.py
index 27505c8131..55992b5a55 100644
--- a/frappe/www/app.py
+++ b/frappe/www/app.py
@@ -6,6 +6,7 @@ import os, re
import frappe
from frappe import _
import frappe.sessions
+from frappe.utils.jinja_globals import is_rtl
def get_context(context):
if frappe.session.user == "Guest":
@@ -40,6 +41,8 @@ def get_context(context):
"build_version": frappe.utils.get_build_version(),
"include_js": hooks["app_include_js"],
"include_css": hooks["app_include_css"],
+ "dir": "rtl" if is_rtl() else "ltr",
+ "lang": frappe.local.lang,
"sounds": hooks["sounds"],
"boot": boot if context.get("for_mobile") else boot_json,
"desk_theme": desk_theme or "Light",
diff --git a/frappe/www/printview.html b/frappe/www/printview.html
index 8bc6e0cb80..05e85730dd 100644
--- a/frappe/www/printview.html
+++ b/frappe/www/printview.html
@@ -6,9 +6,6 @@
{{ title }}
{{ include_style('print.bundle.css') }}
- {%- if has_rtl -%}
- {{ include_style('frappe-rtl.bundle.css') }}
- {%- endif -%}
diff --git a/package.json b/package.json
index 8b22a6e92c..e84fa1b581 100644
--- a/package.json
+++ b/package.json
@@ -67,6 +67,7 @@
"fast-glob": "^3.2.5",
"launch-editor": "^2.2.1",
"md5": "^2.3.0",
+ "rtlcss": "^3.2.1",
"yargs": "^16.2.0"
},
"snyk": true
diff --git a/yarn.lock b/yarn.lock
index 7b1fb981dd..d031f58685 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2420,6 +2420,14 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
follow-redirects@^1.10.0:
version "1.13.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
@@ -3697,6 +3705,13 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
lodash.assign@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
@@ -4234,6 +4249,11 @@ nanoid@^3.1.22:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==
+nanoid@^3.1.23:
+ version "3.1.23"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
+ integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
+
native-request@^1.0.5:
version "1.0.8"
resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.8.tgz#8f66bf606e0f7ea27c0e5995eb2f5d03e33ae6fb"
@@ -4583,6 +4603,13 @@ p-limit@^2.0.0:
dependencies:
p-try "^2.0.0"
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
@@ -4590,6 +4617,13 @@ p-locate@^3.0.0:
dependencies:
p-limit "^2.0.0"
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
p-map@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
@@ -4712,6 +4746,11 @@ path-exists@^3.0.0:
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -5170,6 +5209,15 @@ postcss@^7.0.32:
source-map "^0.6.1"
supports-color "^6.1.0"
+postcss@^8.2.4:
+ version "8.3.5"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709"
+ integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==
+ dependencies:
+ colorette "^1.2.2"
+ nanoid "^3.1.23"
+ source-map-js "^0.6.2"
+
prepend-http@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
@@ -5852,6 +5900,17 @@ roarr@^2.15.3:
semver-compare "^1.0.0"
sprintf-js "^1.1.2"
+rtlcss@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.2.1.tgz#654e55ea2f46991f9738d952ba77ba0aa94a670d"
+ integrity sha512-S9bh35JXwPIhfun7nFu/HjlNrwELL5nvTJqA1suLfbnqY/mauIL5sBkrJNHziVppX9PA2rJ7NV82+RtzB71mJA==
+ dependencies:
+ chalk "^4.1.0"
+ find-up "^5.0.0"
+ mkdirp "^1.0.4"
+ postcss "^8.2.4"
+ strip-json-comments "^3.1.1"
+
run-async@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@@ -6459,6 +6518,11 @@ sortablejs@^1.7.0:
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.8.3.tgz#5ae908ef96300966e95440a143340f5dd565a0df"
integrity sha512-AftvD4hdKcR5QlGi7L/JST506zGNGrysE8/QohDpwKXJarHWqCt+TUlrtoMk/wkECB607Q019/OZlJViyWiD6A==
+source-map-js@^0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
+ integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
+
source-map-resolve@^0.5.2:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@@ -6756,6 +6820,11 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
+strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
@@ -7568,3 +7637,8 @@ yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==