93 lines
4.9 KiB
Go
93 lines
4.9 KiB
Go
// Данная библиотека обеспечивает простую транслитерацию. Для этого достаточно только описать
|
|
// соответствующую таблицу подстановки символов, в которой буква проассоциирована с какой-либо
|
|
// строкой. В частности, такая ассоциация для транслитерации русского языка уже определена.
|
|
//
|
|
// Текущая реализация подразумевает только одностороннюю транслитерацию: обратное преобразование
|
|
// будет уже не так очевидно.
|
|
//
|
|
// Хоть кода в этой библиотеке и не очень много, но время на нее все-таки было потрачено, т.к.
|
|
// раньше я просто не задумывался о некоторых аспектах работы с транслитерацией.
|
|
//
|
|
// В общем, как и большинство других аналогичных библиотек, она перебирает все символы в строке
|
|
// и заменяет их по предложенному ей словарю. Отличие только в том, что, с моей точки зрения, она
|
|
// более корректно отрабатывает случаи с чередованием заглавных букв. Например:
|
|
//
|
|
// "ЧАЩА" -> "CHASCHA"
|
|
// "ЧаЩа" -> "ChaScha"
|
|
// "Чаща" -> "Chascha"
|
|
// "чаЩА" -> "chaSCHA"
|
|
//
|
|
// Для транслитерации русских букв в ней уже предусмотрен встроенный словарь. Для других языков
|
|
// вы можете задать свой. Все достаточно просто:
|
|
//
|
|
// import "github.com/mdigger/translit"
|
|
//
|
|
// tests := []string{
|
|
// "Проверочная СТРОКА для транслитерации",
|
|
// "ЧАЩА",
|
|
// "ЧаЩа",
|
|
// "Чаща",
|
|
// "чаЩА",
|
|
// }
|
|
// for _, text := range tests {
|
|
// fmt.Println(translit.Ru(text))
|
|
// }
|
|
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 = toTitle.String(str) // преобразуем в заглавную только первый символ замены
|
|
}
|
|
fallthrough // выполняем подмену
|
|
default:
|
|
result.WriteString(str) // подменяем символ на транслитерированный
|
|
}
|
|
}
|
|
|
|
return result.String()
|
|
}
|
|
|
|
// toTitle преобразует первую букву в заглавную.
|
|
var toTitle = cases.Title(language.Und)
|