quarto-dev / quarto-cli

Open-source scientific and technical publishing system built on Pandoc.
https://quarto.org
Other
3.77k stars 308 forks source link

Multilingual websites / books #275

Open maelle opened 2 years ago

maelle commented 2 years ago

I was wondering whether having multilingual outputs (e.g. a website that's in French, one in English, with some way to map the corresponding pages so that one can have a button to switch) is on the roadmap?

(I saw https://quarto.org/docs/authoring/language.html#translations but my question is about another aspect, at least I think so :sweat_smile: )

jjallaire commented 2 years ago

I think that this could in principle be done now with some orchestration of multiple render passes. To me the key ingredient is devising a scheme for identifying which files are localized and which files are shared across all languages. Perhaps a naming schema like this:

index.qmd
index.fr.qmd
styles.css

When the site is rendered in fr mode it would substitute any file with a language suffix for its base file that has no suffix. It would also write to the _site/fr directory.

This isn't currently a feature, but an orchestration script could implement the following behavior:

1) Determine the current the language mode 2) Make a temporary copy of the project directory with the appropriate language file substitutions 3) Render within the temporary directory 4) Copy the rendered _site to e.g. _site/fr

The final piece would be implementing language switcher UI. This could be done in a bunch of different ways -- the best way to inject this into the site is probably an include-after-body HTML file that has the switcher and then uses a <script> tag to move it into the optimal place in the UI (e.g. in the navbar, at the top right of the page, etc).

Note that this script could be written in TypeScript using the Deno standard library (https://quarto.org/docs/projects/quarto-projects.html#project-scripts). It would also be fine to write it in R or Python, but users would then need to make sure they have the right dependencies on their system to run it.

Those are some ideas on prototyping multilingual sites. I am sure we will implement this at some point but I'm not sure exactly when.

sbalci commented 2 years ago

Hi, I am also on doing a bilingual book. I have prepared two _quarto.yml files. With the below script in R I copy the English quarto file as the main one, define the language in a common R code then render the book. Then do the same process for Turkish.

In chapters the content is selected from asis engine based on the language.

```{asis, echo = (language == "TR")}
# Bakteriler
# Bacteria

Still working on it. Some points are not resolved.  Will try to run with github actions.

See [repository here](https://github.com/patolojiatlasi/patolojiatlasi.github.io).

```r
# prepare EN ----

fs::file_copy(path = "./_quarto_EN.yml",
              new_path = "./_quarto.yml",
              overwrite = TRUE)

fs::file_copy(path = "./R/languageEN.R",
              new_path = "./R/language.R",
              overwrite = TRUE)

# render EN ----

quarto::quarto_render(".")

# prepare TR ----

fs::file_copy(path = "./_quarto_TR.yml",
              new_path = "./_quarto.yml",
              overwrite = TRUE)

fs::file_copy(path = "./R/languageTR.R",
              new_path = "./R/language.R",
              overwrite = TRUE)

# render TR ----

quarto::quarto_render(".")
maelle commented 2 years ago

My own experiment: https://github.com/ropensci-review-tools/babelbook

sbalci commented 2 years ago

Still working on it. Some points are not resolved. Will try to run with github actions.

See repository here.

Now works with github actions: https://github.com/patolojiatlasi/patolojiatlasi.github.io/blob/main/.github/workflows/Quarto-Render-Bilingual-Book-Push-Tweet-Updates.yml

mcanouil commented 2 years ago

Mentioning the following Pandoc divs feature which can be of use here: https://pandoc.org/MANUAL.html#language-variables.

---
lang: en-GB
---

Text in the main document language (British English).

::: {lang=fr-CA}
> Cette citation est écrite en français canadien.
:::

More text in English. ['Zitat auf Deutsch.']{lang=de}

PS: I do not know how it plays with Quarto πŸ€·β€β™‚οΈ

mcanouil commented 2 years ago

Did you try to override the metadata with for example quarto render index.qmd --metadata lang:fr and use some conditional using the metadata (there is the {{< meta lang >}} shortcode)?

This is basically what I implemented in https://github.com/quarto-dev/quarto-r/pull/52.

cutterkom commented 2 years ago

Hello,

I have recently created a multi-language quarto website

I don't have a code level suggestion, my comments are more from real world project user testing perspective ...

So, first I had worked with @maelle's idea, however then the index.html of the English page (my second language) would not have been accessible, without explicit URL.

Example:

But I want my index page to be reachable without a specific html. At this point, I stopped working with babelbook because the deadline was approaching and I wanted a pragmatic, simple solution.

My final setup:

quarto-website
└── img
└── de
    └── quarto.yml
    └── index.qmd
    └── about.qmd
    └── docs
           └── index.html
           └── about.html
           └── site_libs
           └── search.json
└── en
    └── quarto.yml
    └── index.qmd
    └── about.qmd
    └── docs
           └── index.html
           └── about.html
           └── site_libs
           └── search.json

Main aspects:

Folder structure on webserver:

quarto-website
└── img
└── index.html                 # no folder for main language
└── about.html
└── site_libs
└── search.json
└── en                                # subfolder for second language
   └── index.html
   └── about.html
   └── site_libs        
   └── search.json

Downside:

Comment to @sbalci approach: Having language-specific blocks seemed very convincing for me at first. But I found it confusing on a longer text-heavy document just very few code blocks and switched back to completly different files. Probably the other way round in a code-heavy document with just short text paragraphs.

Okay, these are my 2 cents ...

Best Katharina

mghassany commented 2 years ago

Hello all, I also need to produce two versions of my quarto book, not in two langages, but one without solutions and with solutions. I was doing this easily in bookdown, by creating two .yml files, and then by choosing the config_file when rendering bookdown::render_book()

example: bookdown::render_book("index.Rmd", output_format = "bookdown::gitbook", encoding = 'UTF-8', config_file="_bookdown_corrections.yml", output_dir = "_book_corrections")

I see that we can precide the output-dir in the .yml with quarto.

Is possible to do the same way for quarto books ?

mcanouil commented 2 years ago

Maybe something like:

quarto create-project --type book

Edit for example index.qmd:

---
params:
  solution: false
---

# Preface {.unnumbered}

This is a Quarto book.

To learn more about Quarto books visit <https://quarto.org/docs/books>.

```{r}
#| echo: false
#| output: asis
#| eval: !expr as.logical(toupper(params[["solution"]]))
cat("::: {.solution}\nThe solution.\n:::")

Then you can run:

```sh
quarto render -P solution:false
quarto render -P solution:true
mghassany commented 2 years ago

Thanks for trying. It is workaround, I am not sure it works (tested in a qmd chapter and didn't work but maybe did something wrong). Anyway I see some limitations to your suggestion. Passing through a param that will be evaluated in eval forces that the solution is inside a R chunk then printed using cat(). In my solutions there are some codes to be executed and images and latex equations etc.. also the codes are sometimes in Python.

jjallaire commented 2 years ago

I think we need to create the possibility of configuration variations based on environment variables (or command line options, but the former is a bit more flexible). Then perhaps extend our existing conditional content directive (which is based on output format) to be a bit more general.

mcanouil commented 2 years ago

Thanks for trying. It is workaround, I am not sure it works (tested in a qmd chapter and didn't work but maybe did something wrong). Anyway I see some limitations to your suggestion. Passing through a param that will be evaluated in eval forces that the solution is inside a R chunk then printed using cat(). In my solutions there are some codes to be executed and images and latex equations etc.. also the codes are sometimes in Python.

Code works, I tested it as described.

For more complex code that need evaluation you can use knitr::knit_child() (still a workaround). See https://github.com/quarto-dev/quarto-cli/discussions/2094#discussioncomment-3465685 for an example.

mghassany commented 2 years ago

I think we need to create the possibility of configuration variations based on environment variables (or command line options, but the former is a bit more flexible). Then perhaps extend our existing conditional content directive (which is based on output format) to be a bit more general.

Could we add it to feature requests?

Thanks for trying. It is workaround, I am not sure it works (tested in a qmd chapter and didn't work but maybe did something wrong). Anyway I see some limitations to your suggestion. Passing through a param that will be evaluated in eval forces that the solution is inside a R chunk then printed using cat(). In my solutions there are some codes to be executed and images and latex equations etc.. also the codes are sometimes in Python.

Code works, I tested it as described.

For more complex code that need evaluation you can use knitr::knit_child() (still a workaround). See #2094 (reply in thread) for an example.

Thanks! didn't know about knit_child().

Is there a way (like params above) to hide a div when rendering ? More precisely, I'm putting the solutions in a collapsable callout-important (like suggested here and it works great. When rendering, can we choose to hide all these callouts?

mcanouil commented 2 years ago

Yes, it's possible, but it's going to be not as readable as a proper feature. Using params and knitr::knit_child(), you can do anything, as long as you don't want to use another kernel.

jjallaire commented 2 years ago

@mghassany Yes we will implement the configuration profile soon.

Note that I did another prototype of an approach to this here: https://github.com/jjallaire/multi-version-book

This relies on overlay configuration files that you use a script to switch between. The content is hidden using a Lua filter.

I think that once we implement the "configuration profiles" feature this will be able to be driven entirely by an environment variable or command line argument.

mghassany commented 2 years ago

@jjallaire That is excellent and does exactly what I need! Thank you.

jjallaire commented 2 years ago

Note that we now have a Project Profiles feature in v1.2 that formalizes this approach and makes it more straightforward: https://quarto.org/docs/projects/profiles.html

r-cheologist commented 2 years ago

@jjallaire: The project profiles feature is indeed very nice, but in the context of webpages at least it would benefit from two conceptual additions:

  1. a configuration switch enabling automatic simultanuous rendering of different profiles (think translations of the same page into multiple natural languages) into parallel structures and
  2. a rendered graphical element on every (multilingual) page to allow for seamless switching between the profiles/translations in the rendered result.

Is that a reasonable feature request?

jjallaire commented 1 year ago

@r-cheologist It's definitely a reasonable request, but given all of the other short term priorities we have, we probably won't explicitly tool this up as you outlined in the near term. There are enough hooks in the system though that you could probably rig something like this up manually.

Gospel367 commented 1 year ago

I am new to all this, so pardon my nativity

Is it not possible to put a kind of popup on the pages of the blog that prompts readers to choose a language of choice. If the reader chose the language like arabic, the blog serves blog posts from a folder containing posts written in Arabic

The only left would be to write a kind of logic to bootstrap the chosen language to the correct folder that will render the posts

Like I said, I am a noob with experience in python/Django with html, css ..I am an outreachy intern and want to contribute to the project but the whole idea of quarto seems new to me.

jjallaire commented 1 year ago

There isn't a feature like this right now. You could certainly build a feature like this with extensions but you would need to be pretty far down the extensions learning curve to sort out how. Definitely something we will revisit (higher levels support for this scenario) next year.

mcanouil commented 1 year ago

Would a simple dropdown menu or navbar text menu pointing to the path of the website (probably to the home page to make it relatively simple to implement by a user) in the desired language be enough for now as a workaround? πŸ€” (I still have to try out the profile feature, when I do, I'll try the above mentioned workaround)

eitsupi commented 1 year ago

(I'm not familiar with it, so I don't know if it's actually possible.) If we output it as a docusaurus website, is it possible to make it multilingual?

jjallaire commented 1 year ago

I think that Docusaurus does indeed have this feature (https://docusaurus.io/docs/i18n/introduction).

Tammy-Ajoko commented 1 year ago

Hi, I am fairly new to this but how about adding a button to either English or Arabic? Or adding a drop-down menu in the nav bar to switch between these two languages. we could use JS to switch between the two by translating every text and accounting for it. const language = { eng: { hello: "hello" }, arab: { hello: "Ψ£Ω‡Ω„Ψ§" }; }

maelle commented 1 year ago

Our rOpenSci workflow is now an R package: https://github.com/ropensci-review-tools/babelquarto (book example: https://devdevguide.netlify.app/)

allenmanning commented 1 year ago

Our rOpenSci workflow is now an R package: https://github.com/ropensci-review-tools/babelquarto (book example: https://devdevguide.netlify.app/)

Congrats! If you haven't already, you may want to consider cross-posting to our Show & Tell.