2
0

update library

This commit is contained in:
Dmitry Sedykh
2023-06-11 12:12:54 +03:00
parent 8422236384
commit 93f647e1c7
6 changed files with 123 additions and 84 deletions
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2023 Dmitry Sedykh <sedykh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+5
View File
@@ -0,0 +1,5 @@
module github.com/mdigger/translit
go 1.20
require golang.org/x/text v0.9.0
+2
View File
@@ -0,0 +1,2 @@
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+45
View File
@@ -0,0 +1,45 @@
package translit
// RuMap описывает замены русских букв на английские при транслитерации. Некоторые буквы
// заменяются ни на одну, а на две или три буквы латинского алфавита. А мягкий знак вообще исчезает.
// Но такова обычная распространенная схема транслитерации.
var RuMap = Map{
'а': "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",
}
// Ru выполняет транслитерацию строки с учетом словаря для русской транслитерации.
func Ru(text string) string {
return RuMap.Translate(text)
}
+48 -84
View File
@@ -12,117 +12,81 @@
// и заменяет их по предложенному ей словарю. Отличие только в том, что, с моей точки зрения, она
// более корректно отрабатывает случаи с чередованием заглавных букв. Например:
//
// "ЧАЩА" -> "CHASCHA"
// "ЧаЩа" -> "ChaScha"
// "Чаща" -> "Chascha"
// "чаЩА" -> "chaSCHA"
// "ЧАЩА" -> "CHASCHA"
// "ЧаЩа" -> "ChaScha"
// "Чаща" -> "Chascha"
// "чаЩА" -> "chaSCHA"
//
// Для транслитерации русских букв в ней уже предусмотрен встроенный словарь. Для других языков
// вы можете задать свой. Все достаточно просто:
//
// import "github.com/mdigger/translit"
// import "github.com/mdigger/translit"
//
// tests := []string{
// "Проверочная СТРОКА для транслитерации",
// "ЧАЩА",
// "ЧаЩа",
// "Чаща",
// "чаЩА",
// }
// for _, text := range tests {
// fmt.Println(translit.Ru(text))
// }
// tests := []string{
// "Проверочная СТРОКА для транслитерации",
// "ЧАЩА",
// "ЧаЩа",
// "Чаща",
// "чаЩА",
// }
// for _, text := range tests {
// fmt.Println(translit.Ru(text))
// }
package translit
import (
"bytes"
"golang.org/x/exp/utf8string"
"strings"
"unicode"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
// 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",
}
// Map определяет таблицу подстановки символов при транслитерации.
type Map map[rune]string
// Transliterate выполняет транслитерацию в строке по указанной таблице и возвращает новую строку с
// Translate выполняет транслитерацию в строке по указанной таблице и возвращает новую строку с
// результатом такого преобразования. Все символы, которые не указаны в таблице транслитерации,
// останутся без изменения.
//
// При транслитерировании учитывается, что замена буквы может быть произведена на строку
// При транслитерации учитывается, что замена буквы может быть произведена на строку
// произвольной длины и корректно обрабатываются чередования заглавных и строчных букв. В частности,
// производится корректная транслитерация следующих случаев:
// "ЧАЩА" -> "CHASCHA"
// "ЧаЩа" -> "ChaScha"
// "Чаща" -> "Chascha"
// "чаЩА" -> "chaSCHA"
//
// "ЧАЩА" -> "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 == "":
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(runeValue):
// Если следующий или предыдущий символ тоже заглавная буква, то все буквы строки
// заглавные. Иначе, заглавная только первая буква.
if (length > index+1 && unicode.IsUpper(utf8text.At(index+1))) ||
(index > 0 && unicode.IsUpper(utf8text.At(index-1))) {
str = strings.ToUpper(str)
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 = strings.Title(str)
str = toTitle.String(str) // преобразуем в заглавную только первый символ замены
}
fallthrough
fallthrough // выполняем подмену
default:
result.WriteString(str)
result.WriteString(str) // подменяем символ на транслитерированный
}
}
return result.String()
}
// Ru выполняет транслитерацию строки с учетом словаря для русской транслитерации.
func Ru(text string) string {
return Transliterate(text, RuTransiltMap)
}
// toTitle преобразует первую букву в заглавную.
var toTitle = cases.Title(language.Und)
+1
View File
@@ -2,6 +2,7 @@ package translit_test
import (
"fmt"
"github.com/mdigger/translit"
)