2
0
Files
translit/translit.go
T
2024-02-28 17:33:28 +03:00

53 lines
2.4 KiB
Go

package translit
import (
"strings"
"unicode"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
// Map определяет таблицу подстановки символов при транслитерации.
type Map map[rune]string
// Translate выполняет транслитерацию в строке по указанной таблице и возвращает новую строку с
// результатом такого преобразования. Все символы, которые не указаны в таблице транслитерации,
// останутся без изменения.
//
// При транслитерации учитывается, что замена буквы может быть произведена на строку
// произвольной длины и корректно обрабатываются чередования заглавных и строчных букв. В частности,
// производится корректная транслитерация следующих случаев:
//
// "ЧАЩА" -> "CHASCHA"
// "ЧаЩа" -> "ChaScha"
// "Чаща" -> "Chascha"
// "чаЩА" -> "chaSCHA"
func (m Map) Translate(text string) string {
src := []rune(text) // преобразуем текст в набор символов
var result strings.Builder
result.Grow(len(src) * 3) // выделяем память под построение результирующего текста
for i, r := range src {
switch str, ok := m[unicode.ToLower(r)]; {
case !ok: // не входит в список символов для транслитерации
result.WriteRune(r)
case str == "": // игнорируется при транслитерации
continue
case unicode.IsUpper(r): // заглавная буква
if (i > 0 && unicode.IsUpper(src[i-1])) ||
(i < len(src)-1 && unicode.IsUpper(src[i+1])) {
str = strings.ToUpper(str) // преобразуем все буквы в заглавные
} else {
str = cases.Title(language.Und).String(str) // преобразуем в заглавную только первый символ замены
}
fallthrough // выполняем подмену
default:
result.WriteString(str) // подменяем символ на транслитерированный
}
}
return result.String()
}