> I have thought of a syntax that is as least intrusive as possible, so as
> not to make reading uncomfortable. I have tried the following:
>
> :fr{some text in French} :it{some text in Italian} :la{some text in Latin}

Sorry for joining the discussion a bit late. A long time ago I created a syntax to be able to mix languages in that way, and a program to separate each version into a different file.

Info: https://www.danielclemente.com/dislines/
Sample: https://www.danielclemente.com/dislines/perl.txt
Syntax: https://www.danielclemente.com/dislines/syntax.en.html
Syntax in practice: https://www.danielclemente.com/dislines/quick.en.txt

It's format-agnostic, and unrelated to org. I have used it in plain HTML and other file types.
Many times I tried to use it for org-mode, and while it works, the challenges are more. For instance I'd like to integrate it into the export process (so that a single command produces many files), I want to use it to translate headers (but where do you keep the translations of the header name? in the header itself? in a property?), I want the TOC to use the translated headers, and I want to keep links working (and making sure each language only links to files in the same language). More difficult yet: what if a particular language requires another header structure (more headers, fewer headers, or headers arranged in another way).
I tried several approaches (inline tasks, SRC blocks, my own syntax, tags in headers, one sub-header per language, selective export of tags, properties in headers, post-processing, exporting all and making language selection in JS, one manual TOC per language, …). But I didn't have time to think or discover a good system. Multi-language hypertext systems are hard.

Maybe you can get some ideas from this, if you're still working on mixing human languages in org paragraphs/headers/lines/files. I see the discussion may have shifted from multilingual texts (i.e. human languages) to multi-backend texts (e.g. export HTML/LaTeX/… differently); multi-backend variations might be an easier goal than dealing with multilingual texts and translations.

Thanks for implementing code for your ideas.

On Tue, 20 Feb 2024 at 20:36, Juan Manuel Macías <maciaschain@posteo.net> wrote:
Hi,

I'm dedicating a local branch to developing this proof of concept and
testing it in my workflow, so far with good results. The basic idea is
to provide Org with multilingual features and various methods for
selecting languages.

The inline-language-block is intended for small segments of text in a
language other than the main language. They can span several lines but
not more than a paragraph. They can be used for in-line textual quotes,
glosses, etc. They are constructions equivalent to, for example, LaTeX
\foreignlanguage{french}{text} or HTML <span lang=fr>text</span>.

I have thought of a syntax that is as least intrusive as possible, so as
not to make reading uncomfortable. I have tried the following:

:fr{some text in French} :it{some text in Italian} :la{some text in Latin}

You can also use a literal term instead of a language code:

:klingon!{some text in Klingon}

The blocks can be nested:

:klingon!{Some text in Klingon with :it{some text in Italian}}

And they may include other elements:

:el{Some text in Greek with a {{{macro}}} and a [[link]]}

To this end, I have defined the following element:

#+begin_src emacs-lisp
(defun org-element-inline-language-block-parser ()
  "Parse inline language block at point.

When at an inline language block, return a new syntax node of
`inline-language-block' type containing `:begin', `:end',
`:type', `:contents-begin', `:contents-end' and `:post-blank' as
properties.  Otherwise, return nil.

Assume point is at the beginning of the block."
  (save-excursion
    (when (looking-at ":\\([A-Za-z!]+\\){")
      (goto-char (match-end 0))
      (let* ((begin (match-beginning 0))
             (contents-begin (match-end 0))
             (type (org-element--get-cached-string
                    (match-string-no-properties 1)))
             (contents-end
              (progn
                (goto-char (- contents-begin 1))
                (org-element--parse-paired-brackets ?\{)
                (- (point) 1)))
             (post-blank (skip-chars-forward " \t"))
             (end (point)))
        (when contents-end
          (org-element-create
           'inline-language-block
           (list :type type
                 :contents-begin contents-begin
                 :contents-end contents-end
                 :begin begin
                 :end end
                 :post-blank post-blank)))))))

(defun org-element-inline-language-block-interpreter (inline-language-block contents)
  "Interpret INLINE LANGUAGE BLOCK object as Org syntax."
  (format ":%s{%s}"
          (org-element-property :type inline-language-block)
          contents))
#+end_src

And, for now, this function for ox-latex:

#+begin_src emacs-lisp
(defun org-latex-inline-language-block (inline-language-block contents info)
  "Transcode an INLINE LANGUAGE BLOCK element from Org to LaTeX.
CONTENTS holds the contents of the block.  INFO is a plist
holding contextual information."
  (let ((type (org-element-property :type inline-language-block)))
    (if (string-match-p "!" type)
        (format "\\foreignlanguage{%s}{%s}"
                (replace-regexp-in-string "!" "" type)
                contents)
      (let* ((plist (cdr
                     (assoc type org-latex-language-alist)))
             (language (plist-get plist :babel))
             (language-ini-only (plist-get plist :babel-ini-only))
             (language-ini-alt (plist-get plist :babel-ini-alt))
             (lang (or language language-ini-only language-ini-alt)))
        (format "\\foreignlanguage{%s}{%s}" lang contents)))))
#+end_src

Opinions, suggestions, feedback, ideas?

Best regards,

Juan Manuel

--
Juan Manuel Macías -- Composición tipográfica, tratamiento de datos, diseño editorial y ortotipografía