commit 96a255f2e649ff32b198c4fa675972431988562c Author: Dmitry Sedykh Date: Sun Aug 17 02:04:19 2014 +0400 Транслитерация diff --git a/README.md b/README.md new file mode 100644 index 0000000..d46281e --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# Библиотека для транслитерации строк + + import "github.com/mdigger/translit" + +Данная библиотека обеспечивает простую транслитерацию. Для этого достаточно +только описать соответствующую таблицу подстановки символов, в которой буква +проассоциирована с какой-либо строкой. В частности, такая ассоциация для +транслитерации русского языка уже определена. + +Текущая реализация подразумевает только одностороннюю транслитерацию: обратное +преобразование будет уже не так очевидно. + +## Использование + +```go +var RuTransiltMap = map[rune]string{ + 'а': "a", + 'б': "b", + 'в': "v", + ... + 'ю': "ju", + 'я': "ja", +} +``` +RuTransiltMap описывает замены русских букв на английские при транслитерации. +Некоторые буквы заменяются ни на одну, а на две или три буквы латинского +алфавита. А мягкий знак вообще исчезает. Но такова обычная распространенная +схема транслитерации. + +#### func RuTranslit + +```go +func RuTranslit(text string) string +``` +RuTranslit выполняет транслитерацию строки с учетом словаря для русской +транслитерации. + +#### func Translit + +```go +func Translit(text string, translitMap map[rune]string) string +``` +Translit выполняет транслитерацию в строке по указанной таблице и возвращает +новую строку с результатом такого преобразования. Все символы, которые не +указаны в таблице транслитерации, останутся без изменения. + +При транслитерировании учитывается, что замена буквы может быть произведена на +строку произвольной длины и корректно обрабатываются чередования заглавных и +строчных букв. В частности, производится корректная транслитерация следующих +случаев при использовании русского словаря: + + "ЧАЩА" -> "CHASCHA" + "ЧаЩа" -> "ChaScha" + "Чаща" -> "Chascha" + "чаЩА" -> "chaSCHA" + +При желании, вы можете указать любую таблицу в качестве второго параметра при +вызове функции, по которой и будет выполнено данное преобразование. diff --git a/translit.go b/translit.go new file mode 100644 index 0000000..387668e --- /dev/null +++ b/translit.go @@ -0,0 +1,100 @@ +// Данная библиотека обеспечивает простую транслитерацию. Для этого достаточно только описать +// соответствующую таблицу подстановки символов, в которой буква проассоциирована с какой-либо +// строкой. В частности, такая ассоциация для транслитерации русского языка уже определена. +// +// Текущая реализация подразумевает только одностороннюю транслитерацию: обратное преобразование +// будет уже не так очевидно. +package translit + +import ( + "bytes" + "code.google.com/p/go.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", +} + +// Translit выполняет транслитерацию в строке по указанной таблице и возвращает новую строку с +// результатом такого преобразования. Все символы, которые не указаны в таблице транслитерации, +// останутся без изменения. +// +// При транслитерировании учитывается, что замена буквы может быть произведена на строку +// произвольной длины и корректно обрабатываются чередования заглавных и строчных букв. В частности, +// производится корректная транслитерация следующих случаев: +// "ЧАЩА" -> "CHASCHA" +// "ЧаЩа" -> "ChaScha" +// "Чаща" -> "Chascha" +// "чаЩА" -> "chaSCHA" +// +// При желании, вы можете указать любую таблицу в качестве второго параметра при вызове функции, +// по которой и будет выполнено данное преобразование. +func Translit(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() +} + +// RuTranslit выполняет транслитерацию строки с учетом словаря для русской транслитерации. +func RuTranslit(text string) string { + return Translit(text, RuTransiltMap) +} diff --git a/translit_test.go b/translit_test.go new file mode 100644 index 0000000..a3d7015 --- /dev/null +++ b/translit_test.go @@ -0,0 +1,24 @@ +package translit_test + +import ( + "fmt" + "github.com/mdigger/translit" +) + +func ExampleRuTranslit() { + tests := []string{ + "Проверочная СТРОКА для транслитерации", + "ЧАЩА", + "ЧаЩа", + "Чаща", + "чаЩА", + } + for _, text := range tests { + fmt.Println(translit.RuTranslit(text)) + } + // Output: + // Proverochnaja STROKA dlja transliteracii + // CHASCHA + // ChaScha + // Chascha +}