Suggestions for a better title are welcome.

Essentially, I want to use Org to write in Ukrainian.

Yet, when I export it (pdf or odt) I get:

Figure 1: Контекстна діаграма

How can I customize Emacs to get the output, so that I could get Рисунок written instead of Figure ?:

Рисунок 1: Контекстна діаграма

or, to go even further, to get:

Рисунок 1 - Контекстна діаграма

True, I can do manual "replace all" in LibreOffice, but this is inconvenient and does not account for other cases when I need to influence Org export behavior. I am fairly new to Org mode (haven't read the whole manual yet), but which support does Org provide for other languages / locales?

Could you point me to where this is documented?

  • #+LANGUAGE: uk is part of the solution. The other part is to make sure that org-export-dictionary contains all the right entries: a cursory look shows e.g. that the "Figure" translation is missing. Once you have it done to your satisfaction, consider submitting a patch to the Org mode mailing list
    – NickD
    Mar 14 at 16:48

You need to add an entry to org-export-dictionary.

Down below you see a list of entries for russian language. (I chose russian because the ukrainian word for figure--Рисунок--matches with the russian word for it).

If you are happy with existing russian entries, the easiest way out for you will be to use #+LANGUAGE: ru.

  :html "Автор" 
  :utf-8 "Автор")
 ("Continued from previous page" 
  :html "(Продолжение)" 
  :utf-8 "(Продолжение)")
 ("Continued on next page" 
  :html "(Продолжение следует)" 
  :utf-8 "(Продолжение следует)")
  :html "Дата" 
  :utf-8 "Дата")
  :html "Уравнение" 
  :utf-8 "Уравнение")
  :html "Рисунок" 
  :utf-8 "Рисунок")
 ("Figure %d:" 
  :html "Рис. %d.:" 
  :utf-8 "Рис. %d.:")
  :html "Сноски" 
  :utf-8 "Сноски")
 ("List of Listings" 
  :html "Список распечаток" 
  :utf-8 "Список распечаток")
 ("List of Tables" 
  :html "Список таблиц" 
  :utf-8 "Список таблиц")
  :html "Распечатка" 
  :utf-8 "Распечатка")
 ("Listing %d:" 
  :html "Распечатка %d.:" 
  :utf-8 "Распечатка %d.:")
 ("See figure %s")
 ("See listing %s")
 ("See section %s" 
  :html "См. раздел %s" 
  :utf-8 "См. раздел %s")
 ("See table %s")
  :html "Таблица" 
  :utf-8 "Таблица")
 ("Table %d:" 
  :html "Таблица %d.:" 
  :utf-8 "Таблица %d.:")
 ("Table of Contents" 
  :html "Содержание" 
  :utf-8 "Содержание")
 ("Unknown reference" 
  :html "Неизвестная ссылка" 
  :utf-8 "Неизвестная ссылка"))

I generated the above list using

  (require 'cl-lib)
  (let ((lang "ru"))
    (cl-loop for (string . entry) in (cdr org-export-dictionary)
         collect (cons string (assoc-default lang entry)))))

Here is a list of English strings that may have to be translated to ukraininan

 "Continued from previous page"
 "Continued on next page"
 "Figure %d:"
 "List of Listings"
 "List of Tables"
 "Listing %d:"
 "See figure %s"
 "See listing %s"
 "See section %s"
 "See table %s"
 "Table %d:"
 "Table of Contents"
 "Unknown reference"

I generated above list with

  (require 'cl-lib)
  (cl-loop for (string . entry) in (cdr org-export-dictionary)
       collect string))

The code you are looking for is in ox.el. See https://github.com/emacsmirror/org/blob/49364f904b793513112fb8f71dd6b7f6274171cf/lisp/ox.el#L5720

If you are uncomfortable with Emacs Lisp, no need to worry. You can proceed intuitively.

Do the following

  1. C-h v org-export-dictionary. And click on ox.el link in the resulting help buffer.
  2. Copy-paste the "ru" lines and modify the russian strings to ukranian ones, and remembering to replace "ru" with "uk". (You may have to change the read-only status of ox.el file.). To keep things simpler, you don't have to add new ukraininan lines. Just modify the russian strings to your taste.
  3. Once you have done that do M-x load-library ox.el.
  4. Export your file.
  5. If you are happy with results, you can do C-x C-f ox.el and M-x byte-compile-file, and then restart Emacs.

If you provide me ukrainian translation for above English strings, I can give you a Elisp recipe for modifying org-export-dictionary with ukrainian entries. You can add this recipe to your .emacs.

Regarding using a hyphen instead of a colon in captions, I believe--I haven't looked at the code. The docstring of the variable is not that helpful--you need to alter the first entry in org-export-dictionary or provide a ukrainian one for it.

("%e %n: %c"
 ("fr":default "%e %n : %c"
  :html "%e %n : %c"))

Here is the recipe for adding a custom language.

(defun org-export-dictionary--add-language (lang data)
  (unless (boundp 'org-export-dictionary)
    (require 'ox))
  (cl-loop for (string . entry) in data do
       (let ((current-entry (assoc string org-export-dictionary))
         (new-entry (when entry (cons lang (if (stringp entry) (list :default entry) entry)))))
         (when (and new-entry current-entry)
           (nconc (cdr current-entry) (list new-entry))))))

Here I add a custom language called custom2. The translation strings here are quite elaborate.

 '(("%e %n: %c" :default "%e %n : %c" :html "%e %n : %c")
   ("junk" :default "test")
   ("Author" :default "Auteur")
   ("Continued from previous page" :default "Suite de la page précédente")
   ("Continued on next page" :default "Suite page suivante")
   ("Equation" :ascii "Equation" :default "Équation")
   ("Figure %d:" :default "Figure %d :" :html "Figure %d :")
   ("Footnotes" :default "Notes de bas de page")
   ("List of Listings" :default "Liste des programmes")
   ("List of Tables" :default "Liste des tableaux")
   ("Listing" :default "Programme" :html "Programme")
   ("Listing %d:" :default "Programme %d :" :html "Programme %d :")
   ("References" :ascii "References" :default "Références")
   ("See figure %s" :default "cf. figure %s" :html "cf. figure %s" :latex "cf.~figure~%s")
   ("See listing %s" :default "cf. programme %s" :html "cf. programme %s" :latex "cf.~programme~%s")
   ("See section %s" :default "cf. section %s")
   ("See table %s" :default "cf. tableau %s" :html "cf. tableau %s" :latex "cf.~tableau~%s")
   ("Table" :default "Tableau")
   ("Table %d:" :default "Tableau %d :")
   ("Table of Contents" :ascii "Sommaire" :default "Table des matières")
   ("Unknown reference" :ascii "Destination inconnue" :default "Référence inconnue")))

Here I add a custom language called "custom". The translation strings are simple. The snippet below is what you want to use. Replace, "custom" with "uk" and "FIGURE" with "Рисунок". Add translations for other entries.

 '(("%e %n: %c"                         . "%e %n - %c")
   ("Author"                            . "AUTHOR")
   ("Continued from previous page"      . "CONTINUED FROM PREVIOUS PAGE")
   ("Continued on next page"            . "CONTINUED ON NEXT PAGE")
   ("Created"                           . "CREATED")
   ("Date"                              . "DATE")
   ("Equation"                          . "EQUATION")
   ("Figure"                            . "FIGURE")
   ("Figure %d:"                        . "FIGURE %d:")
   ("Footnotes"                         . "FOOTNOTES")
   ("List of Listings"                  . "LIST OF LISTINGS")
   ("List of Tables"                    . "LIST OF TABLES")
   ("Listing"                           . "LISTING")
   ("Listing %d:"                       . "LISTING %d:")
   ("References"                        . "REFERENCES")
   ("See figure %s"                     . "SEE FIGURE %s")
   ("See listing %s"                    . "SEE LISTING %s")
   ("See section %s"                    . "SEE SECTION %s")
   ("See table %s"                      . "SEE TABLE %s")
   ("Table"                             . "TABLE")
   ("Table %d:"                         . "TABLE %d:")
   ("Table of Contents"                 . "TABLE OF CONTENTS")
   ("Unknown reference"                 . "UNKNOWN REFERENCE"))

For your specific query, here is the snippet in it's simplest form.

I obtained this snippet by replacing "custom" above with "uk", "FIGURE" with "Рисунок" and "%e %n: %c" with "%e %n - %c". I have also removed other entries you(?) don' care about. Note that colon is replaced with hyphen in the caption format.

 '(("%e %n: %c"                         . "%e %n - %c")
   ("Figure"                            . "Рисунок"))

Now when I export this snippet, I get the desired behaviour in ODT export.

# #+LANGUAGE: custom

This is some text

#+CAPTION: My Profile Photo

#+CAPTION: My Test Scores
| Physics   | 50 |
| Chemistry |  70 |

For the sake of completion, here is a list of strings used exclusively by ODT exporter.

 `("Table of Contents"
   ;; List of CATEGORY-NAMEs
   ,@(cl-loop for x in org-odt-category-map-alist collect (nth  3 x))
   ;; List of format specifiers in LABEL-STYLEs
   ,@(apply 'append (cl-loop for label-style in
                 (cl-loop for x in org-odt-category-map-alist
                      collect (nth  2 x))
                 collect (list (nth 1 (assoc-string label-style org-odt-label-styles t))
                       (nth 3 (assoc-string label-style org-odt-label-styles t)))))))

which gives the following list

("Table of Contents" "Table" "Figure" "Equation" "Listing" "%e %n: %c" "%n" "%c" "(%n)")

FWIW, ODT uses :utf-8 entries for translation.

A word of caution regarding org-export-dictionary--add-language: This will work when adding a new language. But you may run in to problems when you want to override the entries for a existing language or you want to augment an existing entry for a language. Read on for what this comments means ...

This is what the snippet does to value of org-export-dictionary

--- a.el    2021-03-27 13:52:11.108743913 +0530
+++ b.el    2021-03-27 13:52:47.721764029 +0530
@@ -1,5 +1,8 @@
 (("%e %n: %c"
-  ("fr" :default "%e %n : %c" :html "%e %n : %c"))
+  ("fr" :default "%e %n : %c" :html "%e %n : %c")
+  ("custom2" :default "%e %n : %c" :html "%e %n : %c")
+  ("custom" :default "%e %n - %c")
+  ("uk" :default "%e %n - %c"))
   ("ar" :default "تأليف")
   ("ca" :default "Autor")
@@ -27,7 +30,9 @@
   ("sv" :html "Författare")
   ("uk" :html "Автор" :utf-8 "Автор")
   ("zh-CN" :html "作者" :utf-8 "作者")
-  ("zh-TW" :html "作者" :utf-8 "作者"))
+  ("zh-TW" :html "作者" :utf-8 "作者")
+  ("custom2" :default "Auteur")
+  ("custom" :default "AUTHOR"))
  ("Continued from previous page"
   ("ar" :default "تتمة الصفحة السابقة")
   ("cs" :default "Pokračování z předchozí strany")
@@ -41,7 +46,9 @@
   ("pt_BR" :html "Continuação da página anterior" :ascii "Continuacao da pagina anterior" :default "Continuação da página anterior")
   ("ro" :default "Continuare de pe pagina precedentă")
   ("ru" :html "(Продолжение)" :utf-8 "(Продолжение)")
-  ("sl" :default "Nadaljevanje s prejšnje strani"))
+  ("sl" :default "Nadaljevanje s prejšnje strani")
+  ("custom2" :default "Suite de la page précédente")
+  ("custom" :default "CONTINUED FROM PREVIOUS PAGE"))
  ("Continued on next page"
   ("ar" :default "التتمة في الصفحة التالية")
   ("cs" :default "Pokračuje na další stránce")
@@ -55,13 +62,16 @@
   ("pt_BR" :html "Continua na próxima página" :ascii "Continua na proxima pagina" :default "Continua na próxima página")
   ("ro" :default "Continuare pe pagina următoare")
   ("ru" :html "(Продолжение следует)" :utf-8 "(Продолжение следует)")
-  ("sl" :default "Nadaljevanje na naslednji strani"))
+  ("sl" :default "Nadaljevanje na naslednji strani")
+  ("custom2" :default "Suite page suivante")
+  ("custom" :default "CONTINUED ON NEXT PAGE"))
   ("cs" :default "Vytvořeno")
   ("nl" :default "Gemaakt op")
   ("pt_BR" :default "Criado em")
   ("ro" :default "Creat")
-  ("sl" :default "Ustvarjeno"))
+  ("sl" :default "Ustvarjeno")
+  ("custom" :default "CREATED"))
   ("ar" :default "بتاريخ")
   ("ca" :default "Data")
@@ -88,7 +98,8 @@
   ("sv" :default "Datum")
   ("uk" :html "Дата" :utf-8 "Дата")
   ("zh-CN" :html "日期" :utf-8 "日期")
-  ("zh-TW" :html "日期" :utf-8 "日期"))
+  ("zh-TW" :html "日期" :utf-8 "日期")
+  ("custom" :default "DATE"))
   ("ar" :default "معادلة")
   ("cs" :default "Rovnice")
@@ -108,7 +119,9 @@
   ("ru" :html "Уравнение" :utf-8 "Уравнение")
   ("sl" :default "Enačba")
   ("sv" :default "Ekvation")
-  ("zh-CN" :html "方程" :utf-8 "方程"))
+  ("zh-CN" :html "方程" :utf-8 "方程")
+  ("custom2" :ascii "Equation" :default "Équation")
+  ("custom" :default "EQUATION"))
   ("ar" :default "شكل")
   ("cs" :default "Obrázek")
@@ -127,7 +140,9 @@
   ("ro" :default "Imaginea")
   ("ru" :html "Рисунок" :utf-8 "Рисунок")
   ("sv" :default "Illustration")
-  ("zh-CN" :html "图" :utf-8 "图"))
+  ("zh-CN" :html "图" :utf-8 "图")
+  ("custom" :default "FIGURE")
+  ("uk" :default "Рисунок"))
  ("Figure %d:"
   ("ar" :default "شكل %d:")
   ("cs" :default "Obrázek %d:")
@@ -148,7 +163,9 @@
   ("ru" :html "Рис. %d.:" :utf-8 "Рис. %d.:")
   ("sl" :default "Slika %d")
   ("sv" :default "Illustration %d")
-  ("zh-CN" :html "图%d " :utf-8 "图%d "))
+  ("zh-CN" :html "图%d " :utf-8 "图%d ")
+  ("custom2" :default "Figure %d :" :html "Figure %d :")
+  ("custom" :default "FIGURE %d:"))
   ("ar" :default "الهوامش")
   ("ca" :html "Peus de pàgina")
@@ -176,7 +193,9 @@
   ("sv" :default "Fotnoter")
   ("uk" :html "Примітки" :utf-8 "Примітки")
   ("zh-CN" :html "脚注" :utf-8 "脚注")
-  ("zh-TW" :html "腳註" :utf-8 "腳註"))
+  ("zh-TW" :html "腳註" :utf-8 "腳註")
+  ("custom2" :default "Notes de bas de page")
+  ("custom" :default "FOOTNOTES"))
  ("List of Listings"
   ("ar" :default "قائمة بالبرامج")
   ("cs" :default "Seznam programů")
@@ -192,7 +211,9 @@
   ("pt_BR" :html "Índice de Listagens" :default "Índice de Listagens" :ascii "Indice de Listagens")
   ("ru" :html "Список распечаток" :utf-8 "Список распечаток")
   ("sl" :default "Seznam programskih izpisov")
-  ("zh-CN" :html "代码目录" :utf-8 "代码目录"))
+  ("zh-CN" :html "代码目录" :utf-8 "代码目录")
+  ("custom2" :default "Liste des programmes")
+  ("custom" :default "LIST OF LISTINGS"))
  ("List of Tables"
   ("ar" :default "قائمة بالجداول")
   ("cs" :default "Seznam tabulek")
@@ -213,7 +234,9 @@
   ("ru" :html "Список таблиц" :utf-8 "Список таблиц")
   ("sl" :default "Seznam tabel")
   ("sv" :default "Tabeller")
-  ("zh-CN" :html "表格目录" :utf-8 "表格目录"))
+  ("zh-CN" :html "表格目录" :utf-8 "表格目录")
+  ("custom2" :default "Liste des tableaux")
+  ("custom" :default "LIST OF TABLES"))
   ("ar" :default "برنامج")
   ("cs" :default "Program")
@@ -231,7 +254,9 @@
   ("ro" :default "Lista")
   ("ru" :html "Распечатка" :utf-8 "Распечатка")
   ("sl" :default "Izpis programa")
-  ("zh-CN" :html "代码" :utf-8 "代码"))
+  ("zh-CN" :html "代码" :utf-8 "代码")
+  ("custom2" :default "Programme" :html "Programme")
+  ("custom" :default "LISTING"))
  ("Listing %d:"
   ("ar" :default "برنامج %d:")
   ("cs" :default "Program %d:")
@@ -249,7 +274,9 @@
   ("pt_BR" :default "Listagem %d:")
   ("ru" :html "Распечатка %d.:" :utf-8 "Распечатка %d.:")
   ("sl" :default "Izpis programa %d")
-  ("zh-CN" :html "代码%d " :utf-8 "代码%d "))
+  ("zh-CN" :html "代码%d " :utf-8 "代码%d ")
+  ("custom2" :default "Programme %d :" :html "Programme %d :")
+  ("custom" :default "LISTING %d:"))
   ("ar" :default "المراجع")
   ("cs" :default "Reference")
@@ -260,7 +287,9 @@
   ("nl" :default "Bronverwijzingen")
   ("pt_BR" :html "Referências" :default "Referências" :ascii "Referencias")
   ("ro" :default "Bibliografie")
-  ("sl" :default "Reference"))
+  ("sl" :default "Reference")
+  ("custom2" :ascii "References" :default "Références")
+  ("custom" :default "REFERENCES"))
  ("See figure %s"
   ("cs" :default "Viz obrázek %s")
   ("fr" :default "cf. figure %s" :html "cf. figure %s" :latex "cf.~figure~%s")
@@ -268,14 +297,18 @@
   ("nl" :default "Zie figuur %s" :html "Zie figuur %s" :latex "Zie figuur~%s")
   ("pt_BR" :default "Veja a figura %s")
   ("ro" :default "Vezi figura %s")
-  ("sl" :default "Glej sliko %s"))
+  ("sl" :default "Glej sliko %s")
+  ("custom2" :default "cf. figure %s" :html "cf. figure %s" :latex "cf.~figure~%s")
+  ("custom" :default "SEE FIGURE %s"))
  ("See listing %s"
   ("cs" :default "Viz program %s")
   ("fr" :default "cf. programme %s" :html "cf. programme %s" :latex "cf.~programme~%s")
   ("nl" :default "Zie programma %s" :html "Zie programma %s" :latex "Zie programma~%s")
   ("pt_BR" :default "Veja a listagem %s")
   ("ro" :default "Vezi tabelul %s")
-  ("sl" :default "Glej izpis programa %s"))
+  ("sl" :default "Glej izpis programa %s")
+  ("custom2" :default "cf. programme %s" :html "cf. programme %s" :latex "cf.~programme~%s")
+  ("custom" :default "SEE LISTING %s"))
  ("See section %s"
   ("ar" :default "انظر قسم %s")
   ("cs" :default "Viz sekce %s")
@@ -291,7 +324,9 @@
   ("ro" :default "Vezi secțiunea %s")
   ("ru" :html "См. раздел %s" :utf-8 "См. раздел %s")
   ("sl" :default "Glej poglavje %d")
-  ("zh-CN" :html "参见第%s节" :utf-8 "参见第%s节"))
+  ("zh-CN" :html "参见第%s节" :utf-8 "参见第%s节")
+  ("custom2" :default "cf. section %s")
+  ("custom" :default "SEE SECTION %s"))
  ("See table %s"
   ("cs" :default "Viz tabulka %s")
   ("fr" :default "cf. tableau %s" :html "cf. tableau %s" :latex "cf.~tableau~%s")
@@ -299,7 +334,9 @@
   ("nl" :default "Zie tabel %s" :html "Zie tabel %s" :latex "Zie tabel~%s")
   ("pt_BR" :default "Veja a tabela %s")
   ("ro" :default "Vezi tabelul %s")
-  ("sl" :default "Glej tabelo %s"))
+  ("sl" :default "Glej tabelo %s")
+  ("custom2" :default "cf. tableau %s" :html "cf. tableau %s" :latex "cf.~tableau~%s")
+  ("custom" :default "SEE TABLE %s"))
   ("ar" :default "جدول")
   ("cs" :default "Tabulka")
@@ -314,7 +351,9 @@
   ("pt_BR" :default "Tabela")
   ("ro" :default "Tabel")
   ("ru" :html "Таблица" :utf-8 "Таблица")
-  ("zh-CN" :html "表" :utf-8 "表"))
+  ("zh-CN" :html "表" :utf-8 "表")
+  ("custom2" :default "Tableau")
+  ("custom" :default "TABLE"))
  ("Table %d:"
   ("ar" :default "جدول %d:")
   ("cs" :default "Tabulka %d:")
@@ -335,7 +374,9 @@
   ("ru" :html "Таблица %d.:" :utf-8 "Таблица %d.:")
   ("sl" :default "Tabela %d")
   ("sv" :default "Tabell %d")
-  ("zh-CN" :html "表%d " :utf-8 "表%d "))
+  ("zh-CN" :html "表%d " :utf-8 "表%d ")
+  ("custom2" :default "Tableau %d :")
+  ("custom" :default "TABLE %d:"))
  ("Table of Contents"
   ("ar" :default "قائمة المحتويات")
   ("ca" :html "Índex")
@@ -363,7 +404,9 @@
   ("sv" :html "Innehåll")
   ("uk" :html "Зміст" :utf-8 "Зміст")
   ("zh-CN" :html "目录" :utf-8 "目录")
-  ("zh-TW" :html "目錄" :utf-8 "目錄"))
+  ("zh-TW" :html "目錄" :utf-8 "目錄")
+  ("custom2" :ascii "Sommaire" :default "Table des matières")
+  ("custom" :default "TABLE OF CONTENTS"))
  ("Unknown reference"
   ("ar" :default "مرجع غير معرّف")
   ("da" :default "ukendt reference")
@@ -378,4 +421,6 @@
   ("ro" :default "Referință necunoscută")
   ("ru" :html "Неизвестная ссылка" :utf-8 "Неизвестная ссылка")
   ("sl" :default "Neznana referenca")
-  ("zh-CN" :html "未知引用" :utf-8 "未知引用")))
+  ("zh-CN" :html "未知引用" :utf-8 "未知引用")
+  ("custom2" :ascii "Destination inconnue" :default "Référence inconnue")
+  ("custom" :default "UNKNOWN REFERENCE")))

As you can see from the diff above,

  1. The snippet appends new entries.
  2. It doesn't merge the plist values for a language. In the diff above, you can see that there are already some entries for "uk" language.

(1) and (2) will make the snippet not work under certain circumstances.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.