String:lower() and string:upper() worked only once with non-english characters

I have “for i” cycle which creates screen keyboard from table with russian characters.

here’s my code:

local TweenService = game:GetService("TweenService")

-----------------------------------------------

local gui = script.Parent
local frame = gui.CharactersFrame

-----------------------------------------------

local englishCharacters = {
	"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
	"L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
	"W", "X", "Y", "Z"
}
local russianCharacters = {
	"A", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К",
	"Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х",
	"Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я"
}
local enteredColor = Color3.new(0.623529, 0.623529, 0.623529)
local pressedColor = Color3.new(1, 1, 0)

-----------------------------------------------

local function tweenColor(button: TextButton, color)
	TweenService:Create(button, TweenInfo.new(0.05), {BackgroundColor3 = color}):Play()
end

-----------------------------------------------

for i, v in pairs(russianCharacters) do
	local clone = script.CharacterButton:Clone()
	
	clone.Text = v:lower()
	
	local mainColor = clone.BackgroundColor3
	local enterFunction = clone.MouseEnter:Connect(function()
		tweenColor(clone, enteredColor)
	end)
	local leavedFunction = clone.MouseLeave:Connect(function()
		tweenColor(clone, mainColor)
	end)
	
	clone.MouseButton1Click:Connect(function()
		--enteredColor:Disconnect()
		--leavedFunction:Disconnect()
		
		clone.BackgroundColor3 = pressedColor
		task.delay(0.1, function()
			clone.BackgroundColor3 = mainColor
		end)
	end)
	
	clone.Parent = frame
end

And here’s the result:

Only first character was lowered (The :upper() method has the same result)
It looks like problems woth non-ASCII characters? but idk how to fix it.

You’re absolutely right: this issue is due to the way Lua (and Roblox’s implementation of Lua, Luau) handles string operations like :lower() and :upper()they only work reliably on ASCII characters. Non-ASCII characters (like Cyrillic letters) are not processed correctly by these methods, so calling v:lower() on "Б" or "Ж" doesn’t actually convert them to lowercase.

:white_check_mark: Solution

To properly convert Russian (Cyrillic) characters to lowercase in Roblox, you need to manually map uppercase to lowercase since Lua lacks built-in Unicode case conversion.

Here’s how you can do it:


:white_check_mark: Step-by-Step Fix

  1. Create a mapping table for uppercase-to-lowercase Cyrillic characters.
  2. Use the table instead of :lower() in your loop.

:wrench: Updated Code

local russianCharacters = {
	"А", "Б", "В", "Г", "Д", "Е", "Ж", "З", "И", "Й", "К",
	"Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х",
	"Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я"
}

-- Manual mapping of uppercase to lowercase Cyrillic letters
local cyrillicLowercaseMap = {
	["А"] = "а", ["Б"] = "б", ["В"] = "в", ["Г"] = "г", ["Д"] = "д", ["Е"] = "е",
	["Ж"] = "ж", ["З"] = "з", ["И"] = "и", ["Й"] = "й", ["К"] = "к", ["Л"] = "л",
	["М"] = "м", ["Н"] = "н", ["О"] = "о", ["П"] = "п", ["Р"] = "р", ["С"] = "с",
	["Т"] = "т", ["У"] = "у", ["Ф"] = "ф", ["Х"] = "х", ["Ц"] = "ц", ["Ч"] = "ч",
	["Ш"] = "ш", ["Щ"] = "щ", ["Ъ"] = "ъ", ["Ы"] = "ы", ["Ь"] = "ь", ["Э"] = "э",
	["Ю"] = "ю", ["Я"] = "я"
}

for i, v in pairs(russianCharacters) do
	local clone = script.CharacterButton:Clone()

	-- Use the mapping table
	local lowerChar = cyrillicLowercaseMap[v] or v -- fallback in case char is not found
	clone.Text = lowerChar

	local mainColor = clone.BackgroundColor3
	local enterFunction = clone.MouseEnter:Connect(function()
		tweenColor(clone, enteredColor)
	end)
	local leavedFunction = clone.MouseLeave:Connect(function()
		tweenColor(clone, mainColor)
	end)

	clone.MouseButton1Click:Connect(function()
		clone.BackgroundColor3 = pressedColor
		task.delay(0.1, function()
			clone.BackgroundColor3 = mainColor
		end)
	end)

	clone.Parent = frame
end

:white_check_mark: Result

This will correctly display all Cyrillic characters in lowercase, regardless of Lua’s :lower() limitations.

Let me know if you want the keyboard to switch dynamically between English and Russian too—happy to help with that!

1 Like

Thank you so much!
I had an idea to do something like this but I thought roblox had some special method in a library which I dont know.
Thank you again for spent time and solution of the problem

np, I just asked your question to chatGPT

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.