Supporting non english languages and RTL languages

Hello everybody. How can I use non english languages like persian(farsi/and other RTL languages) in a game? Thanks

1 Like

Hi! Defold text labels and text nodes in a gui always present their content in a left-to-right order. You would have to reverse the string yourself before setting it on the text node or label. Like this:

local some_rtl_text = "...."
gui.set_text(node, some_rtl_text:reverse())
label.set_text("#mylabel",  some_rtl_text:reverse())

As for the actual font there are really no limitations to which characters to use. When you create a .font file it will by default include the standard ascii range, but you can either specify Extra Characters or more likely in the case of a whole new alphabet instead check the All Chars checkbox.


thanks to your reply.I will test it

1 Like

one week ago I wanted defold just to make html5 games in english but now I prefer to use it for my next mobile game in native language ( persian ) instead of unity ( if i can use persian )
anyone able to write persian in defold? Regardless of typing direction my problem is rendering persian text itself. I have tried some persian fonts using All Chars checked but I still can’t see any persian chars in my label.
i have tried these fonts unsuccessful: “LMN Homa”, “LMU Homa”, “B Homa”. ( all ttf format )
I’m not sure if it’s because of fonts or not, i just want to write some persian to start, not much different what font works for me.
Thanks (29.4 KB)
i made this bitmap font using Hiero, but still can’t see anything. does it mean my char id’s are not in “fnt” table? I’m not familiar with font system and condings.

edited 2 hours later: I’m getting some promising results. I’ll share if i get final result :grinning:

I’m not sure but maybe first time we see persian in defold:

I need more time to get used to persian in defold because of RTL and line breaks but it’s good point for me :+1: :smiley:


Happy to hear you got it working! What was the actual problem? And error with the font?

I have a note to investigate native RTL support. I can’t promise anything yet though.


I’m not sure yet but it seems char ids in persian typing are not those should be on fnt, or ttf.
when i write persian directly using my keyboard ( i see persian in text property field ) nothing happens on game label ( empty text or something strange). but if i write english using my keyboard and persian font i see some persian character, so i found i need a converter, look at text property of my label in that picture, those characters are not persian and not english too, i have used a converter to get them from persian text. ( i use that converter for poor texts in unity too, but in unity there is some persian plugins which i can write persian directly with my keyboard when i use them ) maybe you don’t understand what i mean and what happens because my english is not good enough and I’m not sure what happens yet, but i got that persian text using a converter and persian font.

thats great, I’m new to Defold and Lua, and it’s long time i have not used C++ too, so i can’t do it myself now, but I’m interested to learn more to do something usefull with defold.


Added ticket:


:+1: I Love You :smiley:

1 Like

Hi lovely guys
After about two years I’m here again with Defold. Anything usefull happend to Defold RTL from those days?

1 Like

Unfortunately as of 26 April 2021 not, as evidenced by this comment on GitHub and the silence of the ticket.
However, this user got some bodge working for Arabic (Which is also RTL), and I hope it might be useful.

1 Like

Correct, no work on RTL support unfortunately, but we recently talked about it a bit in the team after seeing this user sharing a project with RTL text in Defold:

1 Like

While RTL isn’t implemented as an option in components for Defold I use these few functions to work with RTL languages.

Maybe it will be useful for somebody.

First of all utf-8 lib needed. I use this one

Helper module fake_rtl.lua (with comments):

-- replace global `string` module with utf-8 for this local module
local utf8 = require("modules.utf8") 
local string = utf8

local function replace_pair_symbols_RTL(str, first_s, second_s)
  local first_n = {}
  local second_n = {}

  local find_all = function(str, symbol, arr)
    local pos = 0
    while true do
      pos = string.find(str, "%"..symbol, pos+1)
      if not pos then break end
      arr[#arr + 1] = pos

  local replace_all = function(str, symbol, arr)
    for k, v in ipairs(arr) do
      str = string.sub(str, 1, v - 1)..symbol..string.sub(str, v + 1)
    return str
  -- can't just use `gsub`in two steps because then we will have:
  -- `)reversed_text(` -gsub-> `(reversed_text(`  -gsub->  `)reversed_text)`
  -- so, first find all symbols we wanna replace, then replace them
  find_all(str, first_s, first_n)
  find_all(str, second_s, second_n)
  str = replace_all(str, second_s, first_n)
  str = replace_all(str, first_s, second_n)
  return str

-- numbers should stay LTR
local function fix_numbers(str)
  local replace_interval_with_reversed_word = function(str, word, at_pos)
    local word_len = #word
    local new_word = string.reverse(word)
    str = string.sub(str, 1, at_pos - 1)..new_word..string.sub(str, at_pos + word_len)
    return str
  local get_numbers = function(str)
    local arr = {}
    local pos, old_value_len = 0
    local value = " "
    while true do
      old_value_len = #value
      value = string.match(str, "([^., !?%s][%d,.]+)", pos + old_value_len)
      if value then
        pos = string.find(str, value, pos + old_value_len)
        arr[#arr + 1] = {["pos"] = pos, ["val"] = value}
        return arr
  local num_arr = get_numbers(str)
  for i, v in ipairs(num_arr) do
    str = replace_interval_with_reversed_word(str, v.val, v.pos)
  return str

local function fake_rtl(str)
    local lines = {}
    -- split into lines
    for s in string.gmatch(str, "[^\r\n]+") do
      table.insert(lines, s)
    -- reverse each line
    for k, v in ipairs(lines) do
      lines[k] = string.reverse(v)
    local result = ""
   -- find each paired symbol end swap them to avoid situations like `)reversed_text(`
    for k, v in ipairs(lines) do
      -- replace paired symbols () [] <> {} etc
      v = replace_pair_symbols_RTL(v, "(",")")
      v = replace_pair_symbols_RTL(v, "[","]")
      v = replace_pair_symbols_RTL(v, "<",">")
      v = replace_pair_symbols_RTL(v, "{","}")
      v = replace_pair_symbols_RTL(v, "«","»")
      v = replace_pair_symbols_RTL(v, "〝","〞")
      v = fix_numbers(v)
      result = result .. v
      if lines[k+1] then
        result = result .. "\n"
    return result

return fake_rtl


local fake_rtl = require("modules.fake_rtl")
local rtl_string = fake_rtl(my_string)

if youк Gui node or label has *West Pivot, change it to *East (for example South West to South East) if it’s Center, keep it as is.
Don’t forget to save еру initial pivot, to restore it after changing lang from RTL to LTR.

UPD: added fix_numbers function


Support rtl languages ​​in defold (The RTL issue is resolved in Godot 4.)