2
0
Files
translit/translit.go
T
alexber127 45b951ea0d Update translit.go
Исправление не рабочей зависимости
2019-03-19 17:33:48 +03:00

129 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Данная библиотека обеспечивает простую транслитерацию. Для этого достаточно только описать
// соответствующую таблицу подстановки символов, в которой буква проассоциирована с какой-либо
// строкой. В частности, такая ассоциация для транслитерации русского языка уже определена.
//
// Текущая реализация подразумевает только одностороннюю транслитерацию: обратное преобразование
// будет уже не так очевидно.
//
// Хоть кода в этой библиотеке и не очень много, но время на нее все-таки было потрачено, т.к.
// раньше я просто не задумывался о некоторых аспектах работы с транслитерацией.
//
// В общем, как и большинство других аналогичных библиотек, она перебирает все символы в строке
// и заменяет их по предложенному ей словарю. Отличие только в том, что, с моей точки зрения, она
// более корректно отрабатывает случаи с чередованием заглавных букв. Например:
//
// "ЧАЩА" -> "CHASCHA"
// "ЧаЩа" -> "ChaScha"
// "Чаща" -> "Chascha"
// "чаЩА" -> "chaSCHA"
//
// Для транслитерации русских букв в ней уже предусмотрен встроенный словарь. Для других языков
// вы можете задать свой. Все достаточно просто:
//
// import "github.com/mdigger/translit"
//
// tests := []string{
// "Проверочная СТРОКА для транслитерации",
// "ЧАЩА",
// "ЧаЩа",
// "Чаща",
// "чаЩА",
// }
// for _, text := range tests {
// fmt.Println(translit.Ru(text))
// }
package translit
import (
"bytes"
"golang.org/x/exp/utf8string"
"strings"
"unicode"
)
// RuTransiltMap описывает замены русских букв на английские при транслитерации. Некоторые буквы
// заменяются ни на одну, а на две или три буквы латинского алфавита. А мягкий знак вообще исчезает.
// Но такова обычная распространенная схема транслитерации.
var RuTransiltMap = map[rune]string{
'а': "a",
'б': "b",
'в': "v",
'г': "g",
'д': "d",
'е': "e",
'ё': "yo",
'ж': "zh",
'з': "z",
'и': "i",
'й': "j",
'к': "k",
'л': "l",
'м': "m",
'н': "n",
'о': "o",
'п': "p",
'р': "r",
'с': "s",
'т': "t",
'у': "u",
'ф': "f",
'х': "h",
'ц': "c",
'ч': "ch",
'ш': "sh",
'щ': "sch",
'ъ': "'",
'ы': "y",
'ь': "",
'э': "e",
'ю': "ju",
'я': "ja",
}
// Transliterate выполняет транслитерацию в строке по указанной таблице и возвращает новую строку с
// результатом такого преобразования. Все символы, которые не указаны в таблице транслитерации,
// останутся без изменения.
//
// При транслитерировании учитывается, что замена буквы может быть произведена на строку
// произвольной длины и корректно обрабатываются чередования заглавных и строчных букв. В частности,
// производится корректная транслитерация следующих случаев:
// "ЧАЩА" -> "CHASCHA"
// "ЧаЩа" -> "ChaScha"
// "Чаща" -> "Chascha"
// "чаЩА" -> "chaSCHA"
//
// При желании, вы можете указать любую таблицу в качестве второго параметра при вызове функции,
// по которой и будет выполнено данное преобразование.
func Transliterate(text string, translitMap map[rune]string) string {
var result bytes.Buffer
utf8text := utf8string.NewString(text)
length := utf8text.RuneCount()
for index := 0; index < length; index++ {
runeValue := utf8text.At(index)
switch str, ok := translitMap[unicode.ToLower(runeValue)]; {
case !ok:
result.WriteRune(runeValue)
case str == "":
continue
case unicode.IsUpper(runeValue):
// Если следующий или предыдущий символ тоже заглавная буква, то все буквы строки
// заглавные. Иначе, заглавная только первая буква.
if (length > index+1 && unicode.IsUpper(utf8text.At(index+1))) ||
(index > 0 && unicode.IsUpper(utf8text.At(index-1))) {
str = strings.ToUpper(str)
} else {
str = strings.Title(str)
}
fallthrough
default:
result.WriteString(str)
}
}
return result.String()
}
// Ru выполняет транслитерацию строки с учетом словаря для русской транслитерации.
func Ru(text string) string {
return Transliterate(text, RuTransiltMap)
}