wilkelab / ggtext

Improved text rendering support for ggplot2
https://wilkelab.org/ggtext/
GNU General Public License v2.0
650 stars 37 forks source link

[Feature Request] Support for rtl languages (ex: Arabic) #115

Open riyadh-radhi opened 3 months ago

riyadh-radhi commented 3 months ago

Hello, First, thanks for the great package! I have tried to use ggtext::element_markdown() with a title that is written in a rtl language (Arabic), but I'm seeing the result of the text becoming into reversed order. Below is a reprex with two ggplot2 plots, one using ggplot2::element_text() which renders the title in the correct order, a second is using ggtext::element_markdown() that renders the title in reverse order.

Requested Feature: Adding support to rtl languages in ggtext. Thanks a lot again!

library(ggplot2)
library(ggtext)

# Title is rendered in correct order when using ggplot2::element_text()
ggplot2::ggplot(datasets::mtcars) +
  ggplot2::labs(
    title = "عنوان في اللغة العربية",
    subtitle = "Title is rendered in the correct order"
  ) +
  ggplot2::theme(
    plot.title = ggplot2::element_text(size = 20),
    plot.subtitle = ggplot2::element_text(size = 20)
  )


# Title is rendered in reverse order when using ggtext::element_markdown()
ggplot2::ggplot(datasets::mtcars) +
  ggplot2::labs(
    title = "عنوان في اللغة العربية",
    subtitle = "Title is rendered in reverse order"
  ) +
  ggplot2::theme(
    plot.title = ggtext::element_markdown(size = 20),
    plot.subtitle = ggtext::element_markdown(size = 20)
  )

Created on 2024-03-19 with reprex v2.1.0

Session info ``` r sessionInfo() #> R version 4.3.3 (2024-02-29) #> Platform: x86_64-pc-linux-gnu (64-bit) #> Running under: Ubuntu 22.04.4 LTS #> #> Matrix products: default #> BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 #> LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0 #> #> locale: #> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C #> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 #> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 #> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C #> [9] LC_ADDRESS=C LC_TELEPHONE=C #> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C #> #> time zone: Europe/Istanbul #> tzcode source: system (glibc) #> #> attached base packages: #> [1] stats graphics grDevices utils datasets methods base #> #> other attached packages: #> [1] ggtext_0.1.2 ggplot2_3.5.0 #> #> loaded via a namespace (and not attached): #> [1] gtable_0.3.4 highr_0.10 dplyr_1.1.4 compiler_4.3.3 #> [5] reprex_2.1.0 tidyselect_1.2.1 Rcpp_1.0.12 stringr_1.5.1 #> [9] xml2_1.3.6 scales_1.3.0 yaml_2.3.8 fastmap_1.1.1 #> [13] R6_2.5.1 commonmark_1.9.1 generics_0.1.3 curl_5.2.1 #> [17] knitr_1.45 tibble_3.2.1 munsell_0.5.0 R.cache_0.16.0 #> [21] pillar_1.9.0 R.utils_2.12.3 rlang_1.1.3 utf8_1.2.4 #> [25] stringi_1.8.3 xfun_0.42 fs_1.6.3 cli_3.6.2 #> [29] withr_3.0.0 magrittr_2.0.3 digest_0.6.35 grid_4.3.3 #> [33] gridtext_0.1.5 rstudioapi_0.15.0 markdown_1.12 lifecycle_1.0.4 #> [37] R.methodsS3_1.8.2 R.oo_1.26.0 vctrs_0.6.5 evaluate_0.23 #> [41] glue_1.7.0 styler_1.10.2 fansi_1.0.6 colorspace_2.1-0 #> [45] rmarkdown_2.26 purrr_1.0.2 tools_4.3.3 pkgconfig_2.0.3 #> [49] htmltools_0.5.7 ```
clauswilke commented 3 months ago

Yes, I'm aware. Unfortunately there is no easy way to fix this except via a complete rewrite of ggtext. I tried this a while back but those efforts are currently abandoned and I don't see myself picking them back up anytime soon.

The fundamental problem is that ggtext breaks the input text into individual words and then renders them one by one, from left to right. Consequently, a simple fix that you can employ is to just change the order of the words in the input string and the output should be correct. I know it's annoying, but it might be as simple as breaking string into individual tokens and assembling back in reverse order. Something like this:

reverse_string <- function(x) { paste(rev(strsplit(x, " +")[[1]]), collapse = " ") }

ggplot2::ggplot(datasets::mtcars) + ggplot2::labs( title = reverse_string("عنوان في اللغة العربية") ) + ggplot2::theme( plot.title = ggtext::element_markdown(size = 20), plot.subtitle = ggtext::element_markdown(size = 20) )

riyadh-radhi commented 3 months ago

Thank you for the quick and detailed explanation. I will do the reverse input fix, as suggested!