├── .github └── workflows │ └── go.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── cmd └── main.go ├── go.mod ├── go.sum ├── helpers.go ├── helpers_test.go ├── iuliia.go ├── iuliia_test.go ├── schemas.go ├── schemas_generator └── gen.go └── schemas_test.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | 11 | build: 12 | name: Build 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - name: Set up Go 1.13 17 | uses: actions/setup-go@v1 18 | with: 19 | go-version: 1.13 20 | id: go 21 | 22 | - name: Check out code into the Go module directory 23 | uses: actions/checkout@v2 24 | 25 | - name: Get dependencies 26 | run: | 27 | go get -v -t -d ./... 28 | 29 | - name: Generate coverage report 30 | run: go test -race -coverprofile=coverage.txt -covermode=atomic 31 | 32 | - name: Upload coverage to Codecov 33 | uses: codecov/codecov-action@v5 34 | with: 35 | file: ./coverage.txt 36 | name: codecov-umbrella 37 | token: ${{ secrets.CODECOV_TOKEN }} 38 | fail_ci_if_error: true 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig 2 | 3 | # Created by https://www.gitignore.io/api/visualstudiocode,macos,go 4 | # Edit at https://www.gitignore.io/?templates=visualstudiocode,macos,go 5 | 6 | ### Go ### 7 | # Binaries for programs and plugins 8 | *.exe 9 | *.exe~ 10 | *.dll 11 | *.so 12 | *.dylib 13 | 14 | # Test binary, built with `go test -c` 15 | *.test 16 | 17 | # Output of the go coverage tool, specifically when used with LiteIDE 18 | *.out 19 | 20 | # Dependency directories (remove the comment below to include it) 21 | # vendor/ 22 | 23 | ### Go Patch ### 24 | /vendor/ 25 | /Godeps/ 26 | 27 | ### macOS ### 28 | # General 29 | .DS_Store 30 | .AppleDouble 31 | .LSOverride 32 | 33 | # Icon must end with two \r 34 | Icon 35 | 36 | # Thumbnails 37 | ._* 38 | 39 | # Files that might appear in the root of a volume 40 | .DocumentRevisions-V100 41 | .fseventsd 42 | .Spotlight-V100 43 | .TemporaryItems 44 | .Trashes 45 | .VolumeIcon.icns 46 | .com.apple.timemachine.donotpresent 47 | 48 | # Directories potentially created on remote AFP share 49 | .AppleDB 50 | .AppleDesktop 51 | Network Trash Folder 52 | Temporary Items 53 | .apdisk 54 | 55 | ### VisualStudioCode ### 56 | .vscode/* 57 | 58 | ### VisualStudioCode Patch ### 59 | # Ignore all local history of files 60 | .history 61 | 62 | # End of https://www.gitignore.io/api/visualstudiocode,macos,go 63 | 64 | # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) 65 | 66 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "schemas"] 2 | path = schemas 3 | url = git@github.com:nalgeon/iuliia.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mike Berezin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `Iuliia` 2 | > Transliterate Cyrillic → Latin in every possible way 3 | 4 | > This is the port of the incredible python library [iuliia](https://github.com/nalgeon/iuliia-py) made by @nalgeon 5 | 6 | [![GoDoc](https://godoc.org/github.com/mehanizm/iuliia-go?status.svg)](https://pkg.go.dev/github.com/mehanizm/iuliia-go) 7 | ![Go](https://github.com/mehanizm/iuliia-go/workflows/Go/badge.svg) 8 | [![codecov](https://codecov.io/gh/mehanizm/iuliia-go/branch/master/graph/badge.svg)](https://codecov.io/gh/mehanizm/iuliia-go) 9 | [![Go Report](https://goreportcard.com/badge/github.com/mehanizm/iuliia-go)](https://goreportcard.com/report/github.com/mehanizm/iuliia-go) 10 | 11 | Transliteration means representing Cyrillic data (mainly names and geographic locations) with Latin letters. It is used for international passports, visas, green cards, driving licenses, mail and goods delivery etc. 12 | 13 | `Iuliia` makes transliteration as easy as: 14 | 15 | ```go 16 | import iuliia "github.com/mehanizm/iuliia-go" 17 | 18 | func main() { 19 | translated := iuliia.Wikipedia.Translate("Юлия Щеглова") 20 | fmt.Println(translated) 21 | } 22 | 23 | >> 'Yuliya Shcheglova' 24 | ``` 25 | 26 | ## Why use `Iuliia` 27 | 28 | - [20 transliteration schemas](https://github.com/nalgeon/iuliia) (rule sets), including all main international and Russian standards. 29 | - Correctly implements not only the base mapping, but all the special rules for letter combinations and word endings (AFAIK, Iuliia is the only library which does so). 30 | - Simple API and zero third-party dependencies. 31 | 32 | ## Installation 33 | 34 | ```sh 35 | go get github.com/mehanizm/iuliia-go 36 | ``` 37 | 38 | `schemas` folder is the git submodule from [general repository](https://github.com/nalgeon/iuliia). You can add schemes manually and use generation to generate all code and tests: 39 | 40 | ```sh 41 | go generate 42 | ``` 43 | 44 | ## CLI interface 45 | 46 | In the folder `cmd` you can find CLI app to play with the transliteration. 47 | 48 | ```sh 49 | # run the app with help 50 | ./iuliia -h 51 | > Usage of ./iuliia: 52 | > -schema string 53 | > choose schema name (default "wikipedia") 54 | > -show 55 | > showing list of the schemas 56 | 57 | # simple run the program 58 | ./iuliia 59 | > type phrase to translate with schema wikipedia: 60 | > 'quit' to exit or 'help' to get help 61 | > > 62 | 63 | # show help 64 | > help 65 | >> * show - to show all schemas 66 | >> * change schema_name - to change schema 67 | >> * quit - to quit the program 68 | >> type phrase to translate with schema wikipedia: 69 | >> 'quit' to exit or 'help' to get help 70 | 71 | # translate 72 | > Привет. Как у тебя дела? 73 | >> Privet. Kak u tebya dela? 74 | 75 | # show all schemas 76 | > show 77 | >> ala_lc: ALA-LC transliteration schema. 78 | >> ala_lc_alt: ALA-LC transliteration schema. 79 | >> bgn_pcgn: BGN/PCGN transliteration schema 80 | >> bgn_pcgn_alt: BGN/PCGN transliteration schema 81 | >> bs_2979: British Standard 2979:1958 transliteration schema 82 | >> bs_2979_alt: British Standard 2979:1958 transliteration schema 83 | >> gost_16876: GOST 16876-71 (aka GOST 1983) transliteration schema 84 | >> gost_16876_alt: GOST 16876-71 (aka GOST 1983) transliteration schema 85 | >> gost_52290: GOST R 52290-2004 transliteration schema 86 | >> gost_52535: GOST R 52535.1-2006 transliteration schema 87 | >> gost_7034: GOST R 7.0.34-2014 transliteration schema 88 | >> gost_779: GOST 7.79-2000 (aka ISO 9:1995) transliteration schema 89 | >> gost_779_alt: GOST 7.79-2000 (aka ISO 9:1995) transliteration schema 90 | >> icao_doc_9303: ICAO DOC 9303 transliteration schema 91 | >> iso_9_1954: ISO/R 9:1954 transliteration schema 92 | >> iso_9_1968: ISO/R 9:1968 transliteration schema 93 | >> iso_9_1968_alt: ISO/R 9:1968 transliteration schema 94 | >> mosmetro: Moscow Metro map transliteration schema 95 | >> mvd_310: MVD 310-1997 transliteration schema 96 | >> mvd_310_fr: MVD 310-1997 transliteration schema 97 | >> mvd_782: MVD 782-2000 transliteration schema 98 | >> scientific: Scientific transliteration schema 99 | >> telegram: Telegram transliteration schema 100 | >> ungegn_1987: UNGEGN 1987 V/18 transliteration schema 101 | >> wikipedia: Wikipedia transliteration schema 102 | >> yandex_maps: Yandex.Maps transliteration schema 103 | >> yandex_money: Yandex.Money transliteration schema 104 | 105 | # change schema 106 | > change telegram 107 | >> schema was changed to telegram 108 | >> 109 | >> type phrase to translate with schema telegram: 110 | >> 'quit' to exit or 'help' to get help 111 | ``` 112 | 113 | ## Contributing 114 | 115 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 116 | 117 | Make sure to add or update tests as appropriate. 118 | 119 | ## License 120 | 121 | [MIT](https://choosealicense.com/licenses/mit/) 122 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | // go build -o iuliia 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "flag" 7 | "fmt" 8 | "os" 9 | "strings" 10 | 11 | iuliia "github.com/mehanizm/iuliia-go" 12 | ) 13 | 14 | var ( 15 | showShemas bool 16 | schemaName string 17 | ) 18 | 19 | func init() { 20 | // Parse flags 21 | flag.BoolVar(&showShemas, "show", false, "showing list of the schemas") 22 | flag.StringVar(&schemaName, "schema", "wikipedia", "choose schema name") 23 | flag.Parse() 24 | } 25 | 26 | func main() { 27 | if showShemas { 28 | fmt.Println(iuliia.SchemaPrinter(iuliia.SchemaMapping)) 29 | return 30 | } 31 | schema, schemaExist := iuliia.SchemaMapping[schemaName] 32 | if !schemaExist { 33 | fmt.Printf("schema name %v does not exist\n", schemaName) 34 | fmt.Printf("to see all schemas --show\n") 35 | return 36 | } 37 | 38 | LOOP: 39 | for { 40 | fmt.Printf("type phrase to translate with schema %v:\n'quit' to exit or 'help' to get help\n", schemaName) 41 | buf := bufio.NewReader(os.Stdin) 42 | fmt.Print("> ") 43 | sentence, err := buf.ReadBytes('\n') 44 | if err != nil { 45 | fmt.Println(err) 46 | fmt.Println("try again") 47 | continue LOOP 48 | } 49 | switch { 50 | case strings.Contains(string(sentence), "quit"): 51 | fmt.Println("buy!") 52 | return 53 | case strings.Contains(string(sentence), "show"): 54 | fmt.Println(iuliia.SchemaPrinter(iuliia.SchemaMapping)) 55 | case strings.Contains(string(sentence), "help"): 56 | fmt.Println("* show - to show all schemas\n* change schema_name - to change schema\n* quit - to quit the program") 57 | case strings.Contains(string(sentence), "change"): 58 | newSchemaName := strings.TrimSuffix(strings.Split(string(sentence), " ")[1], "\n") 59 | newSchema, schemaExist := iuliia.SchemaMapping[newSchemaName] 60 | if !schemaExist { 61 | fmt.Printf("schema name %v does not exist", newSchemaName) 62 | fmt.Printf("to see all schemas type 'show'\n\n") 63 | continue LOOP 64 | } 65 | fmt.Printf("schema was changed to %v\n\n", newSchemaName) 66 | schemaName = newSchemaName 67 | schema = newSchema 68 | default: 69 | translated := schema.Translate(string(sentence)) 70 | fmt.Print("> ") 71 | fmt.Println(translated) 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mehanizm/iuliia-go 2 | 3 | go 1.23 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehanizm/iuliia-go/2a2e9aba91254c07b023a784128a42655da40c05/go.sum -------------------------------------------------------------------------------- /helpers.go: -------------------------------------------------------------------------------- 1 | package iuliia 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strings" 7 | "unicode" 8 | "unicode/utf8" 9 | ) 10 | 11 | func isCyrillic(c rune) bool { 12 | return unicode.Is(unicode.Cyrillic, c) 13 | } 14 | 15 | // splitSentence splits the sentences 16 | // by only the words and non-words correctly 17 | func splitSentence(source string) []string { 18 | // first element "0" already in the slice 19 | chunks := make([]int, 1, 32) 20 | 21 | wasLetter := false 22 | for i, rune := range source { 23 | switch { 24 | case isCyrillic(rune) && !wasLetter: 25 | wasLetter = true 26 | if i == 0 { 27 | continue 28 | } 29 | chunks = append(chunks, i) 30 | case !isCyrillic(rune) && wasLetter: 31 | wasLetter = false 32 | chunks = append(chunks, i) 33 | default: 34 | continue 35 | } 36 | } 37 | 38 | // add last element 39 | chunks = append(chunks, len(source)) 40 | 41 | res := make([]string, len(chunks)-1) 42 | for i := 0; i < len(chunks)-1; i++ { 43 | res[i] = source[chunks[i]:chunks[i+1]] 44 | } 45 | return res 46 | } 47 | 48 | // splitWord to stem and ending 49 | func splitWord(word string) (string, string) { 50 | endingLength := 2 51 | lenOfWord := utf8.RuneCountInString(word) 52 | if lenOfWord <= endingLength { 53 | return word, "" 54 | } 55 | wordInRune := []rune(word) 56 | return string(wordInRune[:lenOfWord-endingLength]), 57 | string(wordInRune[lenOfWord-endingLength:]) 58 | } 59 | 60 | // capitalize uppers only first letter of the string 61 | func capitalize(in string) string { 62 | firstLetter, size := utf8.DecodeRuneInString(in) 63 | if firstLetter == utf8.RuneError { 64 | return in 65 | } 66 | return string(unicode.ToUpper(firstLetter)) + in[size:] 67 | } 68 | 69 | // sliding window 3 size on word 70 | func readLetters(in string) [][]rune { 71 | if in == "" { 72 | return [][]rune{make([]rune, 3)} 73 | } 74 | inRune := append([]rune(in), make([]rune, 2)...) 75 | copy(inRune[1:], inRune[:]) 76 | inRune[0] = rune(0) 77 | res := make([][]rune, 0, len(inRune)-2) 78 | for i := 0; i < len(inRune)-2; i++ { 79 | res = append(res, inRune[i:i+3]) 80 | } 81 | return res 82 | } 83 | 84 | // SchemaPrinter prints schemas line by line 85 | func SchemaPrinter(schemas map[string]*Schema) string { 86 | res := strings.Builder{} 87 | sortedKeys := make([]string, 0, len(schemas)) 88 | for k := range schemas { 89 | sortedKeys = append(sortedKeys, k) 90 | } 91 | sort.Strings(sortedKeys) 92 | for _, schemaName := range sortedKeys { 93 | schema := schemas[schemaName] 94 | num := 20 - utf8.RuneCountInString(schema.Name) 95 | res.WriteString( 96 | fmt.Sprintf( 97 | "%s:%s%s\n", 98 | schema.Name, 99 | strings.Repeat(" ", num), 100 | schema.Desc, 101 | ), 102 | ) 103 | 104 | } 105 | return res.String() 106 | } 107 | 108 | // Get pairs from rune slice 109 | func getPairs(in []rune) (prev, curr, next string) { 110 | if in[0] > rune(0) { 111 | prev += string(in[0]) 112 | } 113 | prev += string(in[1]) 114 | curr = string(in[1]) 115 | next += string(in[1]) 116 | if in[2] > rune(0) { 117 | next += string(in[2]) 118 | } 119 | return 120 | } 121 | -------------------------------------------------------------------------------- /helpers_test.go: -------------------------------------------------------------------------------- 1 | package iuliia 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func Test_splitSentence(t *testing.T) { 9 | tests := []struct { 10 | name string 11 | source string 12 | want []string 13 | }{ 14 | { 15 | "1", "Hello, mankind!", []string{"Hello, mankind!"}, 16 | }, 17 | { 18 | "2", "Привет человечество!", []string{"Привет", " ", "человечество", "!"}, 19 | }, 20 | { 21 | "3", "(привет) (привет...) привет? а", []string{"(", "привет", ") (", "привет", "...) ", "привет", "? ", "а"}, 22 | }, 23 | } 24 | funcs := []struct { 25 | name string 26 | fun func(source string) []string 27 | }{ 28 | {"regex", splitSentence}, 29 | } 30 | for _, tt := range tests { 31 | for _, fun := range funcs { 32 | t.Run(tt.name, func(t *testing.T) { 33 | got := fun.fun(tt.source) 34 | if !reflect.DeepEqual(got, tt.want) { 35 | t.Errorf("Test_splitSentence(), fun %s\ngot = %#v, want %#v", fun.name, got, tt.want) 36 | } 37 | }) 38 | } 39 | } 40 | } 41 | 42 | func Test_splitWord(t *testing.T) { 43 | tests := []struct { 44 | name string 45 | word string 46 | want string 47 | want1 string 48 | }{ 49 | { 50 | "1", "Миша", "Ми", "ша", 51 | }, 52 | { 53 | "2", "Ми", "Ми", "", 54 | }, 55 | { 56 | "3", "Ё", "Ё", "", 57 | }, 58 | } 59 | for _, tt := range tests { 60 | t.Run(tt.name, func(t *testing.T) { 61 | got, got1 := splitWord(tt.word) 62 | if got != tt.want { 63 | t.Errorf("splitWord() got = %v, want %v", got, tt.want) 64 | } 65 | if got1 != tt.want1 { 66 | t.Errorf("splitWord() got1 = %v, want %v", got1, tt.want1) 67 | } 68 | }) 69 | } 70 | } 71 | 72 | func Test_letterReader_readLetters(t *testing.T) { 73 | tests := []struct { 74 | name string 75 | in string 76 | out [][]rune 77 | }{ 78 | { 79 | name: "long", 80 | in: "abcde", 81 | out: [][]rune{ 82 | {rune(0), 'a', 'b'}, 83 | {'a', 'b', 'c'}, 84 | {'b', 'c', 'd'}, 85 | {'c', 'd', 'e'}, 86 | {'d', 'e', rune(0)}, 87 | }, 88 | }, 89 | { 90 | name: "short", 91 | in: "a", 92 | out: [][]rune{ 93 | {rune(0), 'a', rune(0)}, 94 | }, 95 | }, 96 | { 97 | name: "cyrillic", 98 | in: "съешь", 99 | out: [][]rune{ 100 | {rune(0), 'с', 'ъ'}, 101 | {'с', 'ъ', 'е'}, 102 | {'ъ', 'е', 'ш'}, 103 | {'е', 'ш', 'ь'}, 104 | {'ш', 'ь', rune(0)}, 105 | }, 106 | }, 107 | { 108 | name: "empty", 109 | in: "", 110 | out: [][]rune{ 111 | {rune(0), rune(0), rune(0)}, 112 | }, 113 | }, 114 | } 115 | for _, tt := range tests { 116 | t.Run(tt.name, func(t *testing.T) { 117 | res := readLetters(tt.in) 118 | if !reflect.DeepEqual(res, tt.out) { 119 | t.Errorf("wrong result: want: %v was: %v", tt.out, res) 120 | } 121 | 122 | }) 123 | } 124 | } 125 | 126 | func TestSchemaPrinter(t *testing.T) { 127 | tests := []struct { 128 | name string 129 | schemas map[string]*Schema 130 | want string 131 | }{ 132 | { 133 | name: "simple positive", 134 | schemas: map[string]*Schema{ 135 | "test schema": {Name: "schema name", Desc: "schema desc"}, 136 | "a test schema": {Name: "a test schema", Desc: "schema desc"}, 137 | }, 138 | want: "a test schema: schema desc\nschema name: schema desc\n", 139 | }, 140 | } 141 | for _, tt := range tests { 142 | t.Run(tt.name, func(t *testing.T) { 143 | if got := SchemaPrinter(tt.schemas); got != tt.want { 144 | t.Errorf("\nSchemaPrinter():\n%v\nwant:\n%v", got, tt.want) 145 | } 146 | }) 147 | } 148 | } 149 | 150 | func Test_getPairs(t *testing.T) { 151 | tests := []struct { 152 | name string 153 | in []rune 154 | wantPrev string 155 | wantCurr string 156 | wantNext string 157 | }{ 158 | { 159 | name: "all letters", 160 | in: []rune{'a', 'b', 'c'}, 161 | wantPrev: "ab", 162 | wantCurr: "b", 163 | wantNext: "bc", 164 | }, 165 | { 166 | name: "only middle", 167 | in: []rune{rune(0), 'b', rune(0)}, 168 | wantPrev: "b", 169 | wantCurr: "b", 170 | wantNext: "b", 171 | }, 172 | } 173 | for _, tt := range tests { 174 | t.Run(tt.name, func(t *testing.T) { 175 | gotPrev, gotCurr, gotNext := getPairs(tt.in) 176 | if gotPrev != tt.wantPrev { 177 | t.Errorf("getPairs() gotPrev = %v, want %v", gotPrev, tt.wantPrev) 178 | } 179 | if gotCurr != tt.wantCurr { 180 | t.Errorf("getPairs() gotCurr = %v, want %v", gotCurr, tt.wantCurr) 181 | } 182 | if gotNext != tt.wantNext { 183 | t.Errorf("getPairs() gotNext = %v, want %v", gotNext, tt.wantNext) 184 | } 185 | }) 186 | } 187 | } 188 | 189 | func Test_capitalize(t *testing.T) { 190 | tests := []struct { 191 | name string 192 | in string 193 | want string 194 | }{ 195 | { 196 | name: "positive", 197 | in: "hello", 198 | want: "Hello", 199 | }, 200 | { 201 | name: "empty", 202 | in: "", 203 | want: "", 204 | }, 205 | } 206 | for _, tt := range tests { 207 | t.Run(tt.name, func(t *testing.T) { 208 | if got := capitalize(tt.in); got != tt.want { 209 | t.Errorf("capitalize() = %v, want %v", got, tt.want) 210 | } 211 | }) 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /iuliia.go: -------------------------------------------------------------------------------- 1 | // Package iuliia main 2 | // Copyright © 2020 Mike Berezin 3 | // 4 | // Use of this source code is governed by an MIT license. 5 | // Details in the LICENSE file. 6 | // 7 | //go:generate go run schemas_generator/gen.go schemas schemas.go && gofmt -s . 8 | package iuliia 9 | 10 | import ( 11 | "strings" 12 | ) 13 | 14 | var baseMapping = map[string]string{ 15 | "а": "a", 16 | "б": "b", 17 | "в": "v", 18 | "г": "g", 19 | "д": "d", 20 | "е": "e", 21 | "з": "z", 22 | "и": "i", 23 | "к": "k", 24 | "л": "l", 25 | "м": "m", 26 | "н": "n", 27 | "о": "o", 28 | "п": "p", 29 | "р": "r", 30 | "с": "s", 31 | "т": "t", 32 | "у": "u", 33 | "ф": "f", 34 | } 35 | 36 | // Schema base Schema struct 37 | type Schema struct { 38 | Name string `json:"name"` 39 | Desc string `json:"description"` 40 | URL string `json:"url"` 41 | Mapping map[string]string `json:"mapping"` 42 | PrevMapping map[string]string `json:"prev_mapping"` 43 | NextMapping map[string]string `json:"next_mapping"` 44 | EndingMapping map[string]string `json:"ending_mapping"` 45 | Samples [][]string `json:"samples"` 46 | isBuilt bool 47 | } 48 | 49 | // build initiate schema from raw source 50 | func (s *Schema) build() *Schema { 51 | mapping := make(map[string]string) 52 | for key, value := range baseMapping { 53 | mapping[key] = value 54 | mapping[capitalize(key)] = capitalize(value) 55 | } 56 | for key, value := range s.Mapping { 57 | mapping[key] = value 58 | mapping[capitalize(key)] = capitalize(value) 59 | } 60 | s.Mapping = mapping 61 | 62 | for key, value := range s.PrevMapping { 63 | s.PrevMapping[capitalize(key)] = value 64 | s.PrevMapping[strings.ToUpper(key)] = capitalize(value) 65 | } 66 | 67 | for key, value := range s.NextMapping { 68 | s.NextMapping[strings.ToUpper(key)] = capitalize(value) 69 | s.NextMapping[capitalize(key)] = capitalize(value) 70 | } 71 | 72 | for key, value := range s.EndingMapping { 73 | s.EndingMapping[strings.ToUpper(key)] = strings.ToUpper(value) 74 | } 75 | 76 | s.isBuilt = true 77 | 78 | return s 79 | } 80 | 81 | // translateLetter translates one letter 82 | // with respect to neighbors 83 | func (s *Schema) translateLetter(res *strings.Builder, in []rune) { 84 | prev, next, curr := getPairs(in) 85 | if translated, existInPrev := s.PrevMapping[prev]; existInPrev { 86 | res.WriteString(translated) 87 | return 88 | } 89 | if translated, existInNext := s.NextMapping[curr]; existInNext { 90 | res.WriteString(translated) 91 | return 92 | } 93 | if translated, existInCurr := s.Mapping[next]; existInCurr { 94 | res.WriteString(translated) 95 | return 96 | } 97 | res.WriteString(string(in[1])) 98 | } 99 | 100 | // transalteEnding translates ending of the word 101 | // return result and true if ending was translated 102 | // return result and false if there is no ending in the schema 103 | func (s *Schema) translateEnding(res *strings.Builder, ending string) bool { 104 | if translated, existInEnding := s.EndingMapping[ending]; existInEnding { 105 | res.WriteString(translated) 106 | return true 107 | } 108 | res.WriteString(ending) 109 | return false 110 | } 111 | 112 | func (s *Schema) endingExist(ending string) bool { 113 | _, existInEnding := s.EndingMapping[ending] 114 | return existInEnding 115 | } 116 | 117 | // translateLetters translates stem of the word 118 | func (s *Schema) translateLetters(res *strings.Builder, word string) { 119 | for _, letters := range readLetters(word) { 120 | s.translateLetter(res, letters) 121 | } 122 | } 123 | 124 | // translateWord split the input 125 | // word to stem and ending 126 | // Translate parts and combine result 127 | func (s *Schema) translateWord(res *strings.Builder, word string) { 128 | if word == "" { 129 | return 130 | } 131 | if !isCyrillic([]rune(word)[0]) { 132 | res.WriteString(word) 133 | return 134 | } 135 | stem, ending := splitWord(word) 136 | if s.endingExist(ending) { 137 | s.translateLetters(res, stem) 138 | s.translateEnding(res, ending) 139 | return 140 | } 141 | s.translateLetters(res, word) 142 | } 143 | 144 | // Translate translates input strings with schema 145 | // return error if any of the word 146 | // was translated with error 147 | func (s *Schema) Translate(source string) string { 148 | if !s.isBuilt { 149 | s.build() 150 | } 151 | var res strings.Builder 152 | for _, word := range splitSentence(source) { 153 | s.translateWord(&res, word) 154 | } 155 | return res.String() 156 | } 157 | -------------------------------------------------------------------------------- /iuliia_test.go: -------------------------------------------------------------------------------- 1 | package iuliia 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | ) 7 | 8 | func TestSchema_translateWord(t *testing.T) { 9 | tests := []struct { 10 | name string 11 | in string 12 | out string 13 | wantErr bool 14 | }{ 15 | { 16 | name: "1", 17 | in: "Миша", 18 | out: "Misha", 19 | }, 20 | { 21 | name: "2", 22 | in: "съешь", 23 | out: "syesh", 24 | }, 25 | { 26 | name: "3", 27 | in: "ещё", 28 | out: "yeshchyo", 29 | }, 30 | { 31 | name: "with ending", 32 | in: "старый", 33 | out: "stary", 34 | }, 35 | { 36 | name: "special", 37 | in: "Ё", 38 | out: "Yo", 39 | }, 40 | { 41 | name: "empty", 42 | in: "", 43 | out: "", 44 | }, 45 | } 46 | for _, tt := range tests { 47 | t.Run(tt.name, func(t *testing.T) { 48 | var res strings.Builder 49 | Wikipedia.build().translateWord(&res, tt.in) 50 | got := res.String() 51 | if got != tt.out { 52 | t.Errorf("Schema.translateWord() = %v, want %v", got, tt.out) 53 | } 54 | }) 55 | } 56 | } 57 | 58 | func TestSchema_translateLetter(t *testing.T) { 59 | tests := []struct { 60 | name string 61 | args []rune 62 | want string 63 | }{ 64 | { 65 | "current", 66 | []rune{'ъ', 'е', 'ш'}, 67 | "ye", 68 | }, 69 | { 70 | "prev mapping", 71 | []rune{rune(0), 'е', 'щ'}, 72 | "ye", 73 | }, 74 | { 75 | "not cyrillic", 76 | []rune{rune(0), '😁', rune(0)}, 77 | "😁", 78 | }, 79 | { 80 | "next mapping", 81 | []rune{rune(0), 'ь', 'а'}, 82 | "y", 83 | }, 84 | { 85 | "special", 86 | []rune{rune(0), 'Ё', rune(0)}, 87 | "Yo", 88 | }, 89 | } 90 | for _, tt := range tests { 91 | t.Run(tt.name, func(t *testing.T) { 92 | var res strings.Builder 93 | Wikipedia.build().translateLetter(&res, tt.args) 94 | got := res.String() 95 | if got != tt.want { 96 | t.Errorf("Schema.translateLetter() = %v, want %v", got, tt.want) 97 | } 98 | }) 99 | } 100 | } 101 | 102 | func TestSchema_translateEnding(t *testing.T) { 103 | tests := []struct { 104 | name string 105 | ending string 106 | want string 107 | wantBool bool 108 | }{ 109 | { 110 | "translated", 111 | "ый", 112 | "y", 113 | true, 114 | }, 115 | { 116 | "translated", 117 | "уй", 118 | "уй", 119 | false, 120 | }, 121 | } 122 | for _, tt := range tests { 123 | t.Run(tt.name, func(t *testing.T) { 124 | var res strings.Builder 125 | Wikipedia.build().translateEnding(&res, tt.ending) 126 | got := res.String() 127 | if got != tt.want { 128 | t.Errorf("Schema.translateEnding() got = %v, want %v", got, tt.want) 129 | } 130 | }) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /schemas.go: -------------------------------------------------------------------------------- 1 | // Package iuliia do not edit, generated file 2 | package iuliia 3 | 4 | // ALA-LC transliteration schema. 5 | // https://iuliia.ru/ala-lc/ 6 | var Ala_lc = &Schema{ 7 | Name: "ala_lc", 8 | Desc: "ALA-LC transliteration schema.", 9 | Mapping: map[string]string{ 10 | "а": "a", 11 | "б": "b", 12 | "в": "v", 13 | "г": "g", 14 | "д": "d", 15 | "е": "e", 16 | "ж": "zh", 17 | "з": "z", 18 | "и": "i", 19 | "й": "ĭ", 20 | "к": "k", 21 | "л": "l", 22 | "м": "m", 23 | "н": "n", 24 | "о": "o", 25 | "п": "p", 26 | "р": "r", 27 | "с": "s", 28 | "т": "t", 29 | "у": "u", 30 | "ф": "f", 31 | "х": "kh", 32 | "ц": "t͡s", 33 | "ч": "ch", 34 | "ш": "sh", 35 | "щ": "shch", 36 | "ъ": "ʺ", 37 | "ы": "y", 38 | "ь": "ʹ", 39 | "э": "ė", 40 | "ю": "i͡u", 41 | "я": "i͡a", 42 | "ё": "ё", 43 | }, 44 | PrevMapping: map[string]string{}, 45 | NextMapping: map[string]string{}, 46 | EndingMapping: map[string]string{}, 47 | } 48 | 49 | // ALA-LC transliteration schema. 50 | // https://iuliia.ru/ala-lc/ 51 | var Ala_lc_alt = &Schema{ 52 | Name: "ala_lc_alt", 53 | Desc: "ALA-LC transliteration schema.", 54 | Mapping: map[string]string{ 55 | "а": "a", 56 | "б": "b", 57 | "в": "v", 58 | "г": "g", 59 | "д": "d", 60 | "е": "e", 61 | "ж": "zh", 62 | "з": "z", 63 | "и": "i", 64 | "й": "i", 65 | "к": "k", 66 | "л": "l", 67 | "м": "m", 68 | "н": "n", 69 | "о": "o", 70 | "п": "p", 71 | "р": "r", 72 | "с": "s", 73 | "т": "t", 74 | "у": "u", 75 | "ф": "f", 76 | "х": "kh", 77 | "ц": "ts", 78 | "ч": "ch", 79 | "ш": "sh", 80 | "щ": "shch", 81 | "ъ": "\"", 82 | "ы": "y", 83 | "ь": "'", 84 | "э": "e", 85 | "ю": "iu", 86 | "я": "ia", 87 | "ё": "e", 88 | }, 89 | PrevMapping: map[string]string{}, 90 | NextMapping: map[string]string{}, 91 | EndingMapping: map[string]string{}, 92 | } 93 | 94 | // BGN/PCGN transliteration schema 95 | // https://iuliia.ru/bgn-pcgn/ 96 | var Bgn_pcgn = &Schema{ 97 | Name: "bgn_pcgn", 98 | Desc: "BGN/PCGN transliteration schema", 99 | Mapping: map[string]string{ 100 | "а": "a", 101 | "б": "b", 102 | "в": "v", 103 | "г": "g", 104 | "д": "d", 105 | "е": "e", 106 | "ж": "zh", 107 | "з": "z", 108 | "и": "i", 109 | "й": "y", 110 | "к": "k", 111 | "л": "l", 112 | "м": "m", 113 | "н": "n", 114 | "о": "o", 115 | "п": "p", 116 | "р": "r", 117 | "с": "s", 118 | "т": "t", 119 | "у": "u", 120 | "ф": "f", 121 | "х": "kh", 122 | "ц": "ts", 123 | "ч": "ch", 124 | "ш": "sh", 125 | "щ": "shch", 126 | "ъ": "”", 127 | "ы": "y", 128 | "ь": "’", 129 | "э": "e", 130 | "ю": "yu", 131 | "я": "ya", 132 | "ё": "ё", 133 | }, 134 | PrevMapping: map[string]string{ 135 | "ае": "ye", 136 | "аы": "·y", 137 | "аё": "yё", 138 | "бэ": "·e", 139 | "вэ": "·e", 140 | "гэ": "·e", 141 | "дэ": "·e", 142 | "е": "ye", 143 | "ее": "ye", 144 | "еы": "·y", 145 | "её": "yё", 146 | "жэ": "·e", 147 | "зэ": "·e", 148 | "ие": "ye", 149 | "иы": "·y", 150 | "иё": "yё", 151 | "йе": "ye", 152 | "йё": "yё", 153 | "кэ": "·e", 154 | "лэ": "·e", 155 | "мэ": "·e", 156 | "нэ": "·e", 157 | "ое": "ye", 158 | "оы": "·y", 159 | "оё": "yё", 160 | "пэ": "·e", 161 | "рэ": "·e", 162 | "сэ": "·e", 163 | "тэ": "·e", 164 | "уе": "ye", 165 | "уы": "·y", 166 | "уё": "yё", 167 | "фэ": "·e", 168 | "хэ": "·e", 169 | "цэ": "·e", 170 | "чэ": "·e", 171 | "шэ": "·e", 172 | "щэ": "·e", 173 | "ъе": "ye", 174 | "ъё": "yё", 175 | "ые": "ye", 176 | "ыы": "·y", 177 | "ыё": "yё", 178 | "ье": "ye", 179 | "ьё": "yё", 180 | "эе": "ye", 181 | "эы": "·y", 182 | "эё": "yё", 183 | "юе": "ye", 184 | "юы": "·y", 185 | "юё": "yё", 186 | "яе": "ye", 187 | "яы": "·y", 188 | "яё": "yё", 189 | "ё": "yё", 190 | "ёе": "ye", 191 | "ёы": "·y", 192 | "ёё": "yё", 193 | }, 194 | NextMapping: map[string]string{ 195 | "йа": "y·", 196 | "йу": "y·", 197 | "йы": "y·", 198 | "йэ": "y·", 199 | "тс": "t·", 200 | "шч": "sh·", 201 | "ыа": "y·", 202 | "ыу": "y·", 203 | "ыы": "y·", 204 | "ыэ": "y·", 205 | }, 206 | EndingMapping: map[string]string{}, 207 | } 208 | 209 | // BGN/PCGN transliteration schema 210 | // https://iuliia.ru/bgn-pcgn/ 211 | var Bgn_pcgn_alt = &Schema{ 212 | Name: "bgn_pcgn_alt", 213 | Desc: "BGN/PCGN transliteration schema", 214 | Mapping: map[string]string{ 215 | "а": "a", 216 | "б": "b", 217 | "в": "v", 218 | "г": "g", 219 | "д": "d", 220 | "е": "e", 221 | "ж": "zh", 222 | "з": "z", 223 | "и": "i", 224 | "й": "y", 225 | "к": "k", 226 | "л": "l", 227 | "м": "m", 228 | "н": "n", 229 | "о": "o", 230 | "п": "p", 231 | "р": "r", 232 | "с": "s", 233 | "т": "t", 234 | "у": "u", 235 | "ф": "f", 236 | "х": "kh", 237 | "ц": "ts", 238 | "ч": "ch", 239 | "ш": "sh", 240 | "щ": "shch", 241 | "ъ": "”", 242 | "ы": "y", 243 | "ь": "’", 244 | "э": "e", 245 | "ю": "yu", 246 | "я": "ya", 247 | "ё": "ё", 248 | }, 249 | PrevMapping: map[string]string{ 250 | "ае": "ye", 251 | "аё": "yё", 252 | "е": "ye", 253 | "ее": "ye", 254 | "её": "yё", 255 | "ие": "ye", 256 | "иё": "yё", 257 | "йе": "ye", 258 | "йё": "yё", 259 | "ое": "ye", 260 | "оё": "yё", 261 | "уе": "ye", 262 | "уё": "yё", 263 | "ъе": "ye", 264 | "ъё": "yё", 265 | "ые": "ye", 266 | "ыё": "yё", 267 | "ье": "ye", 268 | "ьё": "yё", 269 | "эе": "ye", 270 | "эё": "yё", 271 | "юе": "ye", 272 | "юё": "yё", 273 | "яе": "ye", 274 | "яё": "yё", 275 | "ё": "yё", 276 | "ёе": "ye", 277 | "ёё": "yё", 278 | }, 279 | NextMapping: map[string]string{}, 280 | EndingMapping: map[string]string{}, 281 | } 282 | 283 | // British Standard 2979:1958 transliteration schema 284 | // https://iuliia.ru/bs-2979/ 285 | var Bs_2979 = &Schema{ 286 | Name: "bs_2979", 287 | Desc: "British Standard 2979:1958 transliteration schema", 288 | Mapping: map[string]string{ 289 | "а": "a", 290 | "б": "b", 291 | "в": "v", 292 | "г": "g", 293 | "д": "d", 294 | "е": "e", 295 | "ж": "zh", 296 | "з": "z", 297 | "и": "i", 298 | "й": "ĭ", 299 | "к": "k", 300 | "л": "l", 301 | "м": "m", 302 | "н": "n", 303 | "о": "o", 304 | "п": "p", 305 | "р": "r", 306 | "с": "s", 307 | "т": "t", 308 | "у": "u", 309 | "ф": "f", 310 | "х": "kh", 311 | "ц": "ts", 312 | "ч": "ch", 313 | "ш": "sh", 314 | "щ": "shch", 315 | "ъ": "ʺ", 316 | "ы": "ȳ", 317 | "ь": "ʹ", 318 | "э": "é", 319 | "ю": "yu", 320 | "я": "ya", 321 | "ё": "ё", 322 | }, 323 | PrevMapping: map[string]string{}, 324 | NextMapping: map[string]string{}, 325 | EndingMapping: map[string]string{ 326 | "ий": "y", 327 | "ый": "y", 328 | }, 329 | } 330 | 331 | // British Standard 2979:1958 transliteration schema 332 | // https://iuliia.ru/bs-2979/ 333 | var Bs_2979_alt = &Schema{ 334 | Name: "bs_2979_alt", 335 | Desc: "British Standard 2979:1958 transliteration schema", 336 | Mapping: map[string]string{ 337 | "а": "a", 338 | "б": "b", 339 | "в": "v", 340 | "г": "g", 341 | "д": "d", 342 | "е": "e", 343 | "ж": "zh", 344 | "з": "z", 345 | "и": "i", 346 | "й": "i", 347 | "к": "k", 348 | "л": "l", 349 | "м": "m", 350 | "н": "n", 351 | "о": "o", 352 | "п": "p", 353 | "р": "r", 354 | "с": "s", 355 | "т": "t", 356 | "у": "u", 357 | "ф": "f", 358 | "х": "kh", 359 | "ц": "ts", 360 | "ч": "ch", 361 | "ш": "sh", 362 | "щ": "shch", 363 | "ъ": "\"", 364 | "ы": "y", 365 | "ь": "'", 366 | "э": "e", 367 | "ю": "yu", 368 | "я": "ya", 369 | "ё": "e", 370 | }, 371 | PrevMapping: map[string]string{}, 372 | NextMapping: map[string]string{}, 373 | EndingMapping: map[string]string{ 374 | "ий": "y", 375 | "ый": "y", 376 | }, 377 | } 378 | 379 | // GOST 16876-71 (aka GOST 1983) transliteration schema 380 | // https://iuliia.ru/gost-16876/ 381 | var Gost_16876 = &Schema{ 382 | Name: "gost_16876", 383 | Desc: "GOST 16876-71 (aka GOST 1983) transliteration schema", 384 | Mapping: map[string]string{ 385 | "а": "a", 386 | "б": "b", 387 | "в": "v", 388 | "г": "g", 389 | "д": "d", 390 | "е": "e", 391 | "ж": "ž", 392 | "з": "z", 393 | "и": "i", 394 | "й": "j", 395 | "к": "k", 396 | "л": "l", 397 | "м": "m", 398 | "н": "n", 399 | "о": "o", 400 | "п": "p", 401 | "р": "r", 402 | "с": "s", 403 | "т": "t", 404 | "у": "u", 405 | "ф": "f", 406 | "х": "h", 407 | "ц": "c", 408 | "ч": "č", 409 | "ш": "š", 410 | "щ": "ŝ", 411 | "ъ": "ʺ", 412 | "ы": "y", 413 | "ь": "ʹ", 414 | "э": "è", 415 | "ю": "û", 416 | "я": "â", 417 | "ё": "ё", 418 | }, 419 | PrevMapping: map[string]string{}, 420 | NextMapping: map[string]string{}, 421 | EndingMapping: map[string]string{}, 422 | } 423 | 424 | // GOST 16876-71 (aka GOST 1983) transliteration schema 425 | // https://iuliia.ru/gost-16876/ 426 | var Gost_16876_alt = &Schema{ 427 | Name: "gost_16876_alt", 428 | Desc: "GOST 16876-71 (aka GOST 1983) transliteration schema", 429 | Mapping: map[string]string{ 430 | "а": "a", 431 | "б": "b", 432 | "в": "v", 433 | "г": "g", 434 | "д": "d", 435 | "е": "e", 436 | "ж": "zh", 437 | "з": "z", 438 | "и": "i", 439 | "й": "jj", 440 | "к": "k", 441 | "л": "l", 442 | "м": "m", 443 | "н": "n", 444 | "о": "o", 445 | "п": "p", 446 | "р": "r", 447 | "с": "s", 448 | "т": "t", 449 | "у": "u", 450 | "ф": "f", 451 | "х": "kh", 452 | "ц": "c", 453 | "ч": "ch", 454 | "ш": "sh", 455 | "щ": "shh", 456 | "ъ": "\"", 457 | "ы": "y", 458 | "ь": "'", 459 | "э": "eh", 460 | "ю": "ju", 461 | "я": "ja", 462 | "ё": "jo", 463 | }, 464 | PrevMapping: map[string]string{}, 465 | NextMapping: map[string]string{}, 466 | EndingMapping: map[string]string{}, 467 | } 468 | 469 | // GOST R 52290-2004 transliteration schema 470 | // https://iuliia.ru/gost-52290/ 471 | var Gost_52290 = &Schema{ 472 | Name: "gost_52290", 473 | Desc: "GOST R 52290-2004 transliteration schema", 474 | Mapping: map[string]string{ 475 | "а": "a", 476 | "б": "b", 477 | "в": "v", 478 | "г": "g", 479 | "д": "d", 480 | "е": "e", 481 | "ж": "zh", 482 | "з": "z", 483 | "и": "i", 484 | "й": "y", 485 | "к": "k", 486 | "л": "l", 487 | "м": "m", 488 | "н": "n", 489 | "о": "o", 490 | "п": "p", 491 | "р": "r", 492 | "с": "s", 493 | "т": "t", 494 | "у": "u", 495 | "ф": "f", 496 | "х": "kh", 497 | "ц": "ts", 498 | "ч": "ch", 499 | "ш": "sh", 500 | "щ": "shch", 501 | "ъ": "'", 502 | "ы": "y", 503 | "ь": "'", 504 | "э": "e", 505 | "ю": "yu", 506 | "я": "ya", 507 | "ё": "yo", 508 | }, 509 | PrevMapping: map[string]string{ 510 | "ае": "ye", 511 | "бё": "ye", 512 | "вё": "ye", 513 | "гё": "ye", 514 | "дё": "ye", 515 | "ее": "ye", 516 | "жё": "e", 517 | "зё": "ye", 518 | "ие": "ye", 519 | "кё": "ye", 520 | "лё": "ye", 521 | "мё": "ye", 522 | "нё": "ye", 523 | "ое": "ye", 524 | "пё": "ye", 525 | "рё": "ye", 526 | "сё": "ye", 527 | "тё": "ye", 528 | "уе": "ye", 529 | "фё": "ye", 530 | "хё": "ye", 531 | "цё": "ye", 532 | "чё": "e", 533 | "шё": "e", 534 | "щё": "e", 535 | "ъе": "ye", 536 | "ые": "ye", 537 | "ье": "ye", 538 | "эе": "ye", 539 | "юе": "ye", 540 | "яе": "ye", 541 | "ёе": "ye", 542 | }, 543 | NextMapping: map[string]string{ 544 | "ъе": "", 545 | "ъё": "", 546 | "ье": "", 547 | "ьё": "", 548 | }, 549 | EndingMapping: map[string]string{}, 550 | } 551 | 552 | // GOST R 52535.1-2006 transliteration schema 553 | // https://iuliia.ru/gost-52535/ 554 | var Gost_52535 = &Schema{ 555 | Name: "gost_52535", 556 | Desc: "GOST R 52535.1-2006 transliteration schema", 557 | Mapping: map[string]string{ 558 | "а": "a", 559 | "б": "b", 560 | "в": "v", 561 | "г": "g", 562 | "д": "d", 563 | "е": "e", 564 | "ж": "zh", 565 | "з": "z", 566 | "и": "i", 567 | "й": "i", 568 | "к": "k", 569 | "л": "l", 570 | "м": "m", 571 | "н": "n", 572 | "о": "o", 573 | "п": "p", 574 | "р": "r", 575 | "с": "s", 576 | "т": "t", 577 | "у": "u", 578 | "ф": "f", 579 | "х": "kh", 580 | "ц": "tc", 581 | "ч": "ch", 582 | "ш": "sh", 583 | "щ": "shch", 584 | "ъ": "", 585 | "ы": "y", 586 | "ь": "", 587 | "э": "e", 588 | "ю": "iu", 589 | "я": "ia", 590 | "ё": "e", 591 | }, 592 | PrevMapping: map[string]string{}, 593 | NextMapping: map[string]string{}, 594 | EndingMapping: map[string]string{}, 595 | } 596 | 597 | // GOST R 7.0.34-2014 transliteration schema 598 | // https://iuliia.ru/gost-7034/ 599 | var Gost_7034 = &Schema{ 600 | Name: "gost_7034", 601 | Desc: "GOST R 7.0.34-2014 transliteration schema", 602 | Mapping: map[string]string{ 603 | "а": "a", 604 | "б": "b", 605 | "в": "v", 606 | "г": "g", 607 | "д": "d", 608 | "е": "e", 609 | "ж": "zh", 610 | "з": "z", 611 | "и": "i", 612 | "й": "j", 613 | "к": "k", 614 | "л": "l", 615 | "м": "m", 616 | "н": "n", 617 | "о": "o", 618 | "п": "p", 619 | "р": "r", 620 | "с": "s", 621 | "т": "t", 622 | "у": "u", 623 | "ф": "f", 624 | "х": "x", 625 | "ц": "c", 626 | "ч": "ch", 627 | "ш": "sh", 628 | "щ": "shh", 629 | "ъ": "''", 630 | "ы": "y", 631 | "ь": "'", 632 | "э": "e", 633 | "ю": "yu", 634 | "я": "ya", 635 | "ё": "yo", 636 | }, 637 | PrevMapping: map[string]string{}, 638 | NextMapping: map[string]string{}, 639 | EndingMapping: map[string]string{}, 640 | } 641 | 642 | // GOST 7.79-2000 (aka ISO 9:1995) transliteration schema 643 | // https://iuliia.ru/gost-779/ 644 | var Gost_779 = &Schema{ 645 | Name: "gost_779", 646 | Desc: "GOST 7.79-2000 (aka ISO 9:1995) transliteration schema", 647 | Mapping: map[string]string{ 648 | "а": "a", 649 | "б": "b", 650 | "в": "v", 651 | "г": "g", 652 | "д": "d", 653 | "е": "e", 654 | "ж": "ž", 655 | "з": "z", 656 | "и": "i", 657 | "й": "j", 658 | "к": "k", 659 | "л": "l", 660 | "м": "m", 661 | "н": "n", 662 | "о": "o", 663 | "п": "p", 664 | "р": "r", 665 | "с": "s", 666 | "т": "t", 667 | "у": "u", 668 | "ф": "f", 669 | "х": "h", 670 | "ц": "c", 671 | "ч": "č", 672 | "ш": "š", 673 | "щ": "ŝ", 674 | "ъ": "ʺ", 675 | "ы": "y", 676 | "ь": "ʹ", 677 | "э": "è", 678 | "ю": "û", 679 | "я": "â", 680 | "ё": "ё", 681 | }, 682 | PrevMapping: map[string]string{}, 683 | NextMapping: map[string]string{}, 684 | EndingMapping: map[string]string{}, 685 | } 686 | 687 | // GOST 7.79-2000 (aka ISO 9:1995) transliteration schema 688 | // https://iuliia.ru/gost-779/ 689 | var Gost_779_alt = &Schema{ 690 | Name: "gost_779_alt", 691 | Desc: "GOST 7.79-2000 (aka ISO 9:1995) transliteration schema", 692 | Mapping: map[string]string{ 693 | "а": "a", 694 | "б": "b", 695 | "в": "v", 696 | "г": "g", 697 | "д": "d", 698 | "е": "e", 699 | "ж": "zh", 700 | "з": "z", 701 | "и": "i", 702 | "й": "j", 703 | "к": "k", 704 | "л": "l", 705 | "м": "m", 706 | "н": "n", 707 | "о": "o", 708 | "п": "p", 709 | "р": "r", 710 | "с": "s", 711 | "т": "t", 712 | "у": "u", 713 | "ф": "f", 714 | "х": "x", 715 | "ц": "cz", 716 | "ч": "ch", 717 | "ш": "sh", 718 | "щ": "shh", 719 | "ъ": "``", 720 | "ы": "y`", 721 | "ь": "`", 722 | "э": "e`", 723 | "ю": "yu", 724 | "я": "ya", 725 | "ё": "yo", 726 | }, 727 | PrevMapping: map[string]string{}, 728 | NextMapping: map[string]string{ 729 | "це": "c", 730 | "ци": "c", 731 | "цй": "c", 732 | "цы": "c", 733 | }, 734 | EndingMapping: map[string]string{}, 735 | } 736 | 737 | // ICAO DOC 9303 transliteration schema 738 | // https://iuliia.ru/icao-doc-9303/ 739 | var Icao_doc_9303 = &Schema{ 740 | Name: "icao_doc_9303", 741 | Desc: "ICAO DOC 9303 transliteration schema", 742 | Mapping: map[string]string{ 743 | "а": "a", 744 | "б": "b", 745 | "в": "v", 746 | "г": "g", 747 | "д": "d", 748 | "е": "e", 749 | "ж": "zh", 750 | "з": "z", 751 | "и": "i", 752 | "й": "i", 753 | "к": "k", 754 | "л": "l", 755 | "м": "m", 756 | "н": "n", 757 | "о": "o", 758 | "п": "p", 759 | "р": "r", 760 | "с": "s", 761 | "т": "t", 762 | "у": "u", 763 | "ф": "f", 764 | "х": "kh", 765 | "ц": "ts", 766 | "ч": "ch", 767 | "ш": "sh", 768 | "щ": "shch", 769 | "ъ": "ie", 770 | "ы": "y", 771 | "ь": "", 772 | "э": "e", 773 | "ю": "iu", 774 | "я": "ia", 775 | "ё": "e", 776 | }, 777 | PrevMapping: map[string]string{}, 778 | NextMapping: map[string]string{}, 779 | EndingMapping: map[string]string{}, 780 | } 781 | 782 | // ISO/R 9:1954 transliteration schema 783 | // https://iuliia.ru/iso-9-1954/ 784 | var Iso_9_1954 = &Schema{ 785 | Name: "iso_9_1954", 786 | Desc: "ISO/R 9:1954 transliteration schema", 787 | Mapping: map[string]string{ 788 | "а": "a", 789 | "б": "b", 790 | "в": "v", 791 | "г": "g", 792 | "д": "d", 793 | "е": "e", 794 | "ж": "ž", 795 | "з": "z", 796 | "и": "i", 797 | "й": "j", 798 | "к": "k", 799 | "л": "l", 800 | "м": "m", 801 | "н": "n", 802 | "о": "o", 803 | "п": "p", 804 | "р": "r", 805 | "с": "s", 806 | "т": "t", 807 | "у": "u", 808 | "ф": "f", 809 | "х": "h", 810 | "ц": "c", 811 | "ч": "č", 812 | "ш": "š", 813 | "щ": "šč", 814 | "ъ": "\"", 815 | "ы": "y", 816 | "ь": "ʹ", 817 | "э": "ė", 818 | "ю": "ju", 819 | "я": "ja", 820 | "ё": "ë", 821 | }, 822 | PrevMapping: map[string]string{}, 823 | NextMapping: map[string]string{}, 824 | EndingMapping: map[string]string{}, 825 | } 826 | 827 | // ISO/R 9:1968 transliteration schema 828 | // https://iuliia.ru/iso-9-1968/ 829 | var Iso_9_1968 = &Schema{ 830 | Name: "iso_9_1968", 831 | Desc: "ISO/R 9:1968 transliteration schema", 832 | Mapping: map[string]string{ 833 | "а": "a", 834 | "б": "b", 835 | "в": "v", 836 | "г": "g", 837 | "д": "d", 838 | "е": "e", 839 | "ж": "ž", 840 | "з": "z", 841 | "и": "i", 842 | "й": "j", 843 | "к": "k", 844 | "л": "l", 845 | "м": "m", 846 | "н": "n", 847 | "о": "o", 848 | "п": "p", 849 | "р": "r", 850 | "с": "s", 851 | "т": "t", 852 | "у": "u", 853 | "ф": "f", 854 | "х": "h", 855 | "ц": "c", 856 | "ч": "č", 857 | "ш": "š", 858 | "щ": "šč", 859 | "ъ": "ʺ", 860 | "ы": "y", 861 | "ь": "ʹ", 862 | "э": "ė", 863 | "ю": "ju", 864 | "я": "ja", 865 | "ё": "ë", 866 | }, 867 | PrevMapping: map[string]string{}, 868 | NextMapping: map[string]string{}, 869 | EndingMapping: map[string]string{}, 870 | } 871 | 872 | // ISO/R 9:1968 transliteration schema 873 | // https://iuliia.ru/iso-9-1968/ 874 | var Iso_9_1968_alt = &Schema{ 875 | Name: "iso_9_1968_alt", 876 | Desc: "ISO/R 9:1968 transliteration schema", 877 | Mapping: map[string]string{ 878 | "а": "a", 879 | "б": "b", 880 | "в": "v", 881 | "г": "g", 882 | "д": "d", 883 | "е": "e", 884 | "ж": "zh", 885 | "з": "z", 886 | "и": "y", 887 | "й": "ĭ", 888 | "к": "k", 889 | "л": "l", 890 | "м": "m", 891 | "н": "n", 892 | "о": "o", 893 | "п": "p", 894 | "р": "r", 895 | "с": "s", 896 | "т": "t", 897 | "у": "u", 898 | "ф": "f", 899 | "х": "kh", 900 | "ц": "ts", 901 | "ч": "ch", 902 | "ш": "sh", 903 | "щ": "shch", 904 | "ъ": "ʺ", 905 | "ы": "y", 906 | "ь": "ʹ", 907 | "э": "ė", 908 | "ю": "yu", 909 | "я": "ya", 910 | "ё": "ë", 911 | }, 912 | PrevMapping: map[string]string{}, 913 | NextMapping: map[string]string{}, 914 | EndingMapping: map[string]string{}, 915 | } 916 | 917 | // Moscow Metro map transliteration schema 918 | // https://iuliia.ru/mosmetro/ 919 | var Mosmetro = &Schema{ 920 | Name: "mosmetro", 921 | Desc: "Moscow Metro map transliteration schema", 922 | Mapping: map[string]string{ 923 | "а": "a", 924 | "б": "b", 925 | "в": "v", 926 | "г": "g", 927 | "д": "d", 928 | "е": "e", 929 | "ж": "zh", 930 | "з": "z", 931 | "и": "i", 932 | "й": "y", 933 | "к": "k", 934 | "л": "l", 935 | "м": "m", 936 | "н": "n", 937 | "о": "o", 938 | "п": "p", 939 | "р": "r", 940 | "с": "s", 941 | "т": "t", 942 | "у": "u", 943 | "ф": "f", 944 | "х": "kh", 945 | "ц": "ts", 946 | "ч": "ch", 947 | "ш": "sh", 948 | "щ": "sch", 949 | "ъ": "", 950 | "ы": "y", 951 | "ь": "", 952 | "э": "e", 953 | "ю": "yu", 954 | "я": "ya", 955 | "ё": "e", 956 | }, 957 | PrevMapping: map[string]string{ 958 | "тц": "s", 959 | "ъё": "o", 960 | "ьё": "o", 961 | }, 962 | NextMapping: map[string]string{ 963 | "ъа": "y", 964 | "ъе": "y", 965 | "ъи": "y", 966 | "ъо": "y", 967 | "ъу": "y", 968 | "ъэ": "y", 969 | "ъё": "y", 970 | "ьа": "y", 971 | "ье": "y", 972 | "ьи": "y", 973 | "ьо": "y", 974 | "ьу": "y", 975 | "ьэ": "y", 976 | "ьё": "y", 977 | }, 978 | EndingMapping: map[string]string{ 979 | "ий": "y", 980 | "ый": "y", 981 | }, 982 | } 983 | 984 | // MVD 310-1997 transliteration schema 985 | // https://iuliia.ru/mvd-310/ 986 | var Mvd_310 = &Schema{ 987 | Name: "mvd_310", 988 | Desc: "MVD 310-1997 transliteration schema", 989 | Mapping: map[string]string{ 990 | "а": "a", 991 | "б": "b", 992 | "в": "v", 993 | "г": "g", 994 | "д": "d", 995 | "е": "e", 996 | "ж": "zh", 997 | "з": "z", 998 | "и": "i", 999 | "й": "y", 1000 | "к": "k", 1001 | "л": "l", 1002 | "м": "m", 1003 | "н": "n", 1004 | "о": "o", 1005 | "п": "p", 1006 | "р": "r", 1007 | "с": "s", 1008 | "т": "t", 1009 | "у": "u", 1010 | "ф": "f", 1011 | "х": "kh", 1012 | "ц": "ts", 1013 | "ч": "ch", 1014 | "ш": "sh", 1015 | "щ": "shch", 1016 | "ъ": "\"", 1017 | "ы": "y", 1018 | "ь": "'", 1019 | "э": "e", 1020 | "ю": "yu", 1021 | "я": "ya", 1022 | "ё": "e", 1023 | }, 1024 | PrevMapping: map[string]string{ 1025 | "ъе": "ye", 1026 | "ье": "ye", 1027 | }, 1028 | NextMapping: map[string]string{ 1029 | "ъе": "", 1030 | "ье": "", 1031 | }, 1032 | EndingMapping: map[string]string{}, 1033 | } 1034 | 1035 | // MVD 310-1997 transliteration schema 1036 | // https://iuliia.ru/mvd-310/ 1037 | var Mvd_310_fr = &Schema{ 1038 | Name: "mvd_310_fr", 1039 | Desc: "MVD 310-1997 transliteration schema", 1040 | Mapping: map[string]string{ 1041 | "а": "a", 1042 | "б": "b", 1043 | "в": "v", 1044 | "г": "g", 1045 | "д": "d", 1046 | "е": "e", 1047 | "ж": "j", 1048 | "з": "z", 1049 | "и": "i", 1050 | "й": "i", 1051 | "к": "k", 1052 | "л": "l", 1053 | "м": "m", 1054 | "н": "n", 1055 | "о": "o", 1056 | "п": "p", 1057 | "р": "r", 1058 | "с": "s", 1059 | "т": "t", 1060 | "у": "ou", 1061 | "ф": "f", 1062 | "х": "kh", 1063 | "ц": "ts", 1064 | "ч": "tch", 1065 | "ш": "ch", 1066 | "щ": "chtch", 1067 | "ъ": "", 1068 | "ы": "y", 1069 | "ь": "", 1070 | "э": "e", 1071 | "ю": "iou", 1072 | "я": "ia", 1073 | "ё": "e", 1074 | }, 1075 | PrevMapping: map[string]string{ 1076 | "ге": "ue", 1077 | "ги": "ui", 1078 | "гы": "uy", 1079 | "кс": "x", 1080 | "ье": "ie", 1081 | }, 1082 | NextMapping: map[string]string{ 1083 | "кс": "", 1084 | }, 1085 | EndingMapping: map[string]string{ 1086 | "ин": "ine", 1087 | }, 1088 | } 1089 | 1090 | // MVD 782-2000 transliteration schema 1091 | // https://iuliia.ru/mvd-782/ 1092 | var Mvd_782 = &Schema{ 1093 | Name: "mvd_782", 1094 | Desc: "MVD 782-2000 transliteration schema", 1095 | Mapping: map[string]string{ 1096 | "а": "a", 1097 | "б": "b", 1098 | "в": "v", 1099 | "г": "g", 1100 | "д": "d", 1101 | "е": "e", 1102 | "ж": "zh", 1103 | "з": "z", 1104 | "и": "i", 1105 | "й": "y", 1106 | "к": "k", 1107 | "л": "l", 1108 | "м": "m", 1109 | "н": "n", 1110 | "о": "o", 1111 | "п": "p", 1112 | "р": "r", 1113 | "с": "s", 1114 | "т": "t", 1115 | "у": "u", 1116 | "ф": "f", 1117 | "х": "kh", 1118 | "ц": "ts", 1119 | "ч": "ch", 1120 | "ш": "sh", 1121 | "щ": "shch", 1122 | "ъ": "'", 1123 | "ы": "y", 1124 | "ь": "'", 1125 | "э": "e", 1126 | "ю": "yu", 1127 | "я": "ya", 1128 | "ё": "yo", 1129 | }, 1130 | PrevMapping: map[string]string{ 1131 | "ае": "ye", 1132 | "бё": "ye", 1133 | "вё": "ye", 1134 | "гё": "ye", 1135 | "дё": "ye", 1136 | "ее": "ye", 1137 | "жё": "e", 1138 | "зё": "ye", 1139 | "ие": "ye", 1140 | "кё": "ye", 1141 | "лё": "ye", 1142 | "мё": "ye", 1143 | "нё": "ye", 1144 | "ое": "ye", 1145 | "пё": "ye", 1146 | "рё": "ye", 1147 | "сё": "ye", 1148 | "тё": "ye", 1149 | "уе": "ye", 1150 | "фё": "ye", 1151 | "хё": "ye", 1152 | "цё": "ye", 1153 | "чё": "e", 1154 | "шё": "e", 1155 | "щё": "e", 1156 | "ъе": "ye", 1157 | "ые": "ye", 1158 | "ье": "ye", 1159 | "ьи": "yi", 1160 | "эе": "ye", 1161 | "юе": "ye", 1162 | "яе": "ye", 1163 | "ёе": "ye", 1164 | }, 1165 | NextMapping: map[string]string{ 1166 | "ъе": "", 1167 | "ъё": "", 1168 | "ье": "", 1169 | "ьи": "", 1170 | "ьё": "", 1171 | }, 1172 | EndingMapping: map[string]string{}, 1173 | } 1174 | 1175 | // Scientific transliteration schema 1176 | // https://iuliia.ru/scientific/ 1177 | var Scientific = &Schema{ 1178 | Name: "scientific", 1179 | Desc: "Scientific transliteration schema", 1180 | Mapping: map[string]string{ 1181 | "а": "a", 1182 | "б": "b", 1183 | "в": "v", 1184 | "г": "g", 1185 | "д": "d", 1186 | "е": "e", 1187 | "ж": "ž", 1188 | "з": "z", 1189 | "и": "i", 1190 | "й": "j", 1191 | "к": "k", 1192 | "л": "l", 1193 | "м": "m", 1194 | "н": "n", 1195 | "о": "o", 1196 | "п": "p", 1197 | "р": "r", 1198 | "с": "s", 1199 | "т": "t", 1200 | "у": "u", 1201 | "ф": "f", 1202 | "х": "x", 1203 | "ц": "c", 1204 | "ч": "č", 1205 | "ш": "š", 1206 | "щ": "šč", 1207 | "ъ": "ʺ", 1208 | "ы": "y", 1209 | "ь": "ʹ", 1210 | "э": "è", 1211 | "ю": "ju", 1212 | "я": "ja", 1213 | "ё": "ё", 1214 | }, 1215 | PrevMapping: map[string]string{}, 1216 | NextMapping: map[string]string{}, 1217 | EndingMapping: map[string]string{}, 1218 | } 1219 | 1220 | // Telegram transliteration schema 1221 | // https://iuliia.ru/telegram/ 1222 | var Telegram = &Schema{ 1223 | Name: "telegram", 1224 | Desc: "Telegram transliteration schema", 1225 | Mapping: map[string]string{ 1226 | "а": "a", 1227 | "б": "b", 1228 | "в": "v", 1229 | "г": "g", 1230 | "д": "d", 1231 | "е": "e", 1232 | "ж": "j", 1233 | "з": "z", 1234 | "и": "i", 1235 | "й": "i", 1236 | "к": "k", 1237 | "л": "l", 1238 | "м": "m", 1239 | "н": "n", 1240 | "о": "o", 1241 | "п": "p", 1242 | "р": "r", 1243 | "с": "s", 1244 | "т": "t", 1245 | "у": "u", 1246 | "ф": "f", 1247 | "х": "h", 1248 | "ц": "c", 1249 | "ч": "ch", 1250 | "ш": "sh", 1251 | "щ": "sc", 1252 | "ъ": "", 1253 | "ы": "y", 1254 | "ь": "", 1255 | "э": "e", 1256 | "ю": "iu", 1257 | "я": "ia", 1258 | "ё": "e", 1259 | }, 1260 | PrevMapping: map[string]string{}, 1261 | NextMapping: map[string]string{}, 1262 | EndingMapping: map[string]string{}, 1263 | } 1264 | 1265 | // UNGEGN 1987 V/18 transliteration schema 1266 | // https://iuliia.ru/ungegn-1987/ 1267 | var Ungegn_1987 = &Schema{ 1268 | Name: "ungegn_1987", 1269 | Desc: "UNGEGN 1987 V/18 transliteration schema", 1270 | Mapping: map[string]string{ 1271 | "а": "a", 1272 | "б": "b", 1273 | "в": "v", 1274 | "г": "g", 1275 | "д": "d", 1276 | "е": "e", 1277 | "ж": "ž", 1278 | "з": "z", 1279 | "и": "i", 1280 | "й": "j", 1281 | "к": "k", 1282 | "л": "l", 1283 | "м": "m", 1284 | "н": "n", 1285 | "о": "o", 1286 | "п": "p", 1287 | "р": "r", 1288 | "с": "s", 1289 | "т": "t", 1290 | "у": "u", 1291 | "ф": "f", 1292 | "х": "h", 1293 | "ц": "c", 1294 | "ч": "č", 1295 | "ш": "š", 1296 | "щ": "šč", 1297 | "ъ": "ʺ", 1298 | "ы": "y", 1299 | "ь": "ʹ", 1300 | "э": "è", 1301 | "ю": "ju", 1302 | "я": "ja", 1303 | "ё": "ё", 1304 | }, 1305 | PrevMapping: map[string]string{}, 1306 | NextMapping: map[string]string{}, 1307 | EndingMapping: map[string]string{}, 1308 | } 1309 | 1310 | // Uzbekistan cyr-lat transliteration schema 1311 | // https://en.wikipedia.org/wiki/Uzbek_alphabet 1312 | var Uz = &Schema{ 1313 | Name: "uz", 1314 | Desc: "Uzbekistan cyr-lat transliteration schema", 1315 | Mapping: map[string]string{ 1316 | "а": "a", 1317 | "б": "b", 1318 | "в": "v", 1319 | "г": "g", 1320 | "д": "d", 1321 | "е": "e", 1322 | "ж": "j", 1323 | "з": "z", 1324 | "и": "i", 1325 | "й": "y", 1326 | "к": "k", 1327 | "л": "l", 1328 | "м": "m", 1329 | "н": "n", 1330 | "о": "o", 1331 | "п": "p", 1332 | "р": "r", 1333 | "с": "s", 1334 | "т": "t", 1335 | "у": "u", 1336 | "ф": "f", 1337 | "х": "x", 1338 | "ц": "s", 1339 | "ч": "ch", 1340 | "ш": "sh", 1341 | "щ": "sh", 1342 | "ъ": "ʼ", 1343 | "ы": "i", 1344 | "э": "e", 1345 | "ю": "yu", 1346 | "я": "ya", 1347 | "ё": "yo", 1348 | "ў": "oʻ", 1349 | "ғ": "gʻ", 1350 | "қ": "q", 1351 | "ҳ": "h", 1352 | }, 1353 | PrevMapping: map[string]string{}, 1354 | NextMapping: map[string]string{}, 1355 | EndingMapping: map[string]string{}, 1356 | } 1357 | 1358 | // Wikipedia transliteration schema 1359 | // https://iuliia.ru/wikipedia/ 1360 | var Wikipedia = &Schema{ 1361 | Name: "wikipedia", 1362 | Desc: "Wikipedia transliteration schema", 1363 | Mapping: map[string]string{ 1364 | "а": "a", 1365 | "б": "b", 1366 | "в": "v", 1367 | "г": "g", 1368 | "д": "d", 1369 | "е": "e", 1370 | "ж": "zh", 1371 | "з": "z", 1372 | "и": "i", 1373 | "й": "y", 1374 | "к": "k", 1375 | "л": "l", 1376 | "м": "m", 1377 | "н": "n", 1378 | "о": "o", 1379 | "п": "p", 1380 | "р": "r", 1381 | "с": "s", 1382 | "т": "t", 1383 | "у": "u", 1384 | "ф": "f", 1385 | "х": "kh", 1386 | "ц": "ts", 1387 | "ч": "ch", 1388 | "ш": "sh", 1389 | "щ": "shch", 1390 | "ъ": "", 1391 | "ы": "y", 1392 | "ь": "", 1393 | "э": "e", 1394 | "ю": "yu", 1395 | "я": "ya", 1396 | "ё": "yo", 1397 | }, 1398 | PrevMapping: map[string]string{ 1399 | "ае": "ye", 1400 | "е": "ye", 1401 | "ие": "ye", 1402 | "ое": "ye", 1403 | "уе": "ye", 1404 | "ъе": "ye", 1405 | "ье": "ye", 1406 | "эе": "ye", 1407 | "юе": "ye", 1408 | "яе": "ye", 1409 | }, 1410 | NextMapping: map[string]string{ 1411 | "ъа": "y", 1412 | "ъи": "y", 1413 | "ъо": "y", 1414 | "ъу": "y", 1415 | "ъы": "y", 1416 | "ъэ": "y", 1417 | "ьа": "y", 1418 | "ьи": "y", 1419 | "ьо": "y", 1420 | "ьу": "y", 1421 | "ьы": "y", 1422 | "ьэ": "y", 1423 | }, 1424 | EndingMapping: map[string]string{ 1425 | "ий": "y", 1426 | "ый": "y", 1427 | }, 1428 | } 1429 | 1430 | // Yandex.Maps transliteration schema 1431 | // https://iuliia.ru/yandex-maps/ 1432 | var Yandex_maps = &Schema{ 1433 | Name: "yandex_maps", 1434 | Desc: "Yandex.Maps transliteration schema", 1435 | Mapping: map[string]string{ 1436 | "а": "a", 1437 | "б": "b", 1438 | "в": "v", 1439 | "г": "g", 1440 | "д": "d", 1441 | "е": "e", 1442 | "ж": "zh", 1443 | "з": "z", 1444 | "и": "i", 1445 | "й": "y", 1446 | "к": "k", 1447 | "л": "l", 1448 | "м": "m", 1449 | "н": "n", 1450 | "о": "o", 1451 | "п": "p", 1452 | "р": "r", 1453 | "с": "s", 1454 | "т": "t", 1455 | "у": "u", 1456 | "ф": "f", 1457 | "х": "kh", 1458 | "ц": "ts", 1459 | "ч": "ch", 1460 | "ш": "sh", 1461 | "щ": "sch", 1462 | "ъ": "", 1463 | "ы": "y", 1464 | "ь": "", 1465 | "э": "e", 1466 | "ю": "yu", 1467 | "я": "ya", 1468 | "ё": "yo", 1469 | }, 1470 | PrevMapping: map[string]string{ 1471 | "ае": "ye", 1472 | "е": "ye", 1473 | "ие": "ye", 1474 | "ое": "ye", 1475 | "уе": "ye", 1476 | "эе": "ye", 1477 | "юе": "ye", 1478 | "яе": "ye", 1479 | }, 1480 | NextMapping: map[string]string{ 1481 | "ъе": "y", 1482 | }, 1483 | EndingMapping: map[string]string{ 1484 | "ый": "iy", 1485 | }, 1486 | } 1487 | 1488 | // Yandex.Money transliteration schema 1489 | // https://iuliia.ru/yandex-money/ 1490 | var Yandex_money = &Schema{ 1491 | Name: "yandex_money", 1492 | Desc: "Yandex.Money transliteration schema", 1493 | Mapping: map[string]string{ 1494 | "а": "a", 1495 | "б": "b", 1496 | "в": "v", 1497 | "г": "g", 1498 | "д": "d", 1499 | "е": "e", 1500 | "ж": "zh", 1501 | "з": "z", 1502 | "и": "i", 1503 | "й": "i", 1504 | "к": "k", 1505 | "л": "l", 1506 | "м": "m", 1507 | "н": "n", 1508 | "о": "o", 1509 | "п": "p", 1510 | "р": "r", 1511 | "с": "s", 1512 | "т": "t", 1513 | "у": "u", 1514 | "ф": "f", 1515 | "х": "kh", 1516 | "ц": "ts", 1517 | "ч": "ch", 1518 | "ш": "sh", 1519 | "щ": "sch", 1520 | "ъ": "", 1521 | "ы": "y", 1522 | "ь": "", 1523 | "э": "e", 1524 | "ю": "yu", 1525 | "я": "ya", 1526 | "ё": "e", 1527 | }, 1528 | PrevMapping: map[string]string{}, 1529 | NextMapping: map[string]string{}, 1530 | EndingMapping: map[string]string{}, 1531 | } 1532 | 1533 | // SchemaMapping mapping of all schemas 1534 | var SchemaMapping = map[string]*Schema{ 1535 | "ala_lc": Ala_lc, 1536 | "ala_lc_alt": Ala_lc_alt, 1537 | "bgn_pcgn": Bgn_pcgn, 1538 | "bgn_pcgn_alt": Bgn_pcgn_alt, 1539 | "bs_2979": Bs_2979, 1540 | "bs_2979_alt": Bs_2979_alt, 1541 | "gost_16876": Gost_16876, 1542 | "gost_16876_alt": Gost_16876_alt, 1543 | "gost_52290": Gost_52290, 1544 | "gost_52535": Gost_52535, 1545 | "gost_7034": Gost_7034, 1546 | "gost_779": Gost_779, 1547 | "gost_779_alt": Gost_779_alt, 1548 | "icao_doc_9303": Icao_doc_9303, 1549 | "iso_9_1954": Iso_9_1954, 1550 | "iso_9_1968": Iso_9_1968, 1551 | "iso_9_1968_alt": Iso_9_1968_alt, 1552 | "mosmetro": Mosmetro, 1553 | "mvd_310": Mvd_310, 1554 | "mvd_310_fr": Mvd_310_fr, 1555 | "mvd_782": Mvd_782, 1556 | "scientific": Scientific, 1557 | "telegram": Telegram, 1558 | "ungegn_1987": Ungegn_1987, 1559 | "uz": Uz, 1560 | "wikipedia": Wikipedia, 1561 | "yandex_maps": Yandex_maps, 1562 | "yandex_money": Yandex_money, 1563 | } 1564 | -------------------------------------------------------------------------------- /schemas_generator/gen.go: -------------------------------------------------------------------------------- 1 | //go:generate go run schema_generator.go && gofmt -s ../* 2 | 3 | package main 4 | 5 | import ( 6 | "bytes" 7 | "encoding/json" 8 | "fmt" 9 | "go/format" 10 | "log" 11 | "os" 12 | "path/filepath" 13 | "strings" 14 | "text/template" 15 | 16 | "github.com/mehanizm/iuliia-go" 17 | ) 18 | 19 | const ( 20 | dirWithSchemasConst = "../schemas" 21 | fileToGenerateConst = "../schemas.go" 22 | ) 23 | 24 | func escapeQuotes(input string) string { 25 | return strings.Replace(input, "\"", "\\\"", -1) 26 | } 27 | 28 | var funcMap = template.FuncMap{ 29 | "escape": escapeQuotes, 30 | } 31 | 32 | var schemaTpl = template.Must(template.New("schemaTpl").Funcs(funcMap).Parse(` 33 | // {{ .Desc }} 34 | // {{ .URL }} 35 | var {{ .GetName }} = &Schema{ 36 | Name: "{{ .Name }}", 37 | Desc: "{{ .Desc }}", 38 | Mapping: map[string]string{ 39 | {{- range $key, $value := .Mapping }} 40 | "{{ escape $key }}": "{{ escape $value }}", 41 | {{- end }} 42 | }, 43 | PrevMapping: map[string]string{ 44 | {{- range $key, $value := .PrevMapping }} 45 | "{{ escape $key }}": "{{ escape $value }}", 46 | {{- end }} 47 | }, 48 | NextMapping: map[string]string{ 49 | {{- range $key, $value := .NextMapping }} 50 | "{{ escape $key }}": "{{ escape $value }}", 51 | {{- end }} 52 | }, 53 | EndingMapping: map[string]string{ 54 | {{- range $key, $value := .EndingMapping }} 55 | "{{ escape $key }}": "{{ escape $value }}", 56 | {{- end }} 57 | }, 58 | }`)) 59 | 60 | var schemaTestTpl = template.Must(template.New("schemaTestTpl").Funcs(funcMap).Parse(` 61 | // {{ .GetName }} schema 62 | func Test_{{ .GetName }}(t *testing.T) { 63 | tests := []struct { 64 | name string 65 | in string 66 | out string 67 | }{ 68 | {{- range $i, $sample := .Samples}} 69 | { 70 | name: "{{ $i }}", 71 | in: "{{ index $sample 0 | escape }}", 72 | out: "{{ index $sample 1 | escape }}", 73 | }, 74 | {{- end}} 75 | } 76 | for _, tt := range tests { 77 | t.Run(tt.name, func(t *testing.T) { 78 | {{ .GetName }}.isBuilt = false 79 | got := {{ .GetName }}.Translate(tt.in) 80 | if got != tt.out { 81 | fmt.Println({{ .GetName }}) 82 | t.Errorf("{{ .GetName }} got:\n%v\nbut want:\n%v\n", got, tt.out) 83 | } 84 | }) 85 | } 86 | }`)) 87 | 88 | var schemasTpl = template.Must(template.New("schemasTpl").Parse(` 89 | // SchemaMapping mapping of all schemas 90 | var SchemaMapping = map[string]*Schema{ 91 | {{- range $key, $value := . }} 92 | "{{ $key }}": {{ $value }}, 93 | {{- end }} 94 | }`)) 95 | 96 | type schemable interface { 97 | String() string 98 | StringTest() string 99 | GetName() string 100 | GetDictName() string 101 | } 102 | 103 | // SchemaGen composite type for generation 104 | type SchemaGen iuliia.Schema 105 | 106 | // GetName get title name of the schema 107 | func (s *SchemaGen) GetName() string { 108 | return strings.Title(s.Name) 109 | } 110 | 111 | // GetDictName get name of the schema 112 | func (s *SchemaGen) GetDictName() string { 113 | return s.Name 114 | } 115 | 116 | // String generate code for stucts 117 | func (s *SchemaGen) String() string { 118 | var res bytes.Buffer 119 | if err := schemaTpl.Execute(&res, s); err != nil { 120 | log.Fatal(err) 121 | } 122 | return res.String() 123 | } 124 | 125 | // StringTest generate code for tests 126 | func (s *SchemaGen) StringTest() string { 127 | var res bytes.Buffer 128 | if err := schemaTestTpl.Execute(&res, s); err != nil { 129 | log.Fatal(err) 130 | } 131 | return res.String() 132 | } 133 | 134 | func printSchemaToBuffer( 135 | fileToRead string, schema schemable, schemas map[string]string, 136 | destinationToWriteCode, destinationToWriteTest *bytes.Buffer, 137 | ) error { 138 | schemaFileData, err := os.ReadFile(fileToRead) 139 | if err != nil { 140 | return err 141 | } 142 | err = json.Unmarshal(schemaFileData, schema) 143 | if err != nil { 144 | return err 145 | } 146 | _, err = fmt.Fprint(destinationToWriteCode, schema.String()) 147 | if err != nil { 148 | return err 149 | } 150 | _, err = fmt.Fprint(destinationToWriteTest, schema.StringTest()) 151 | if err != nil { 152 | return err 153 | } 154 | schemas[schema.GetDictName()] = schema.GetName() 155 | return nil 156 | } 157 | 158 | func printToFileWithFmt(buffer *bytes.Buffer, fileToWrite *os.File) error { 159 | formatted, err := format.Source(buffer.Bytes()) 160 | if err != nil { 161 | return fmt.Errorf("error in go formatting: %w", err) 162 | } 163 | _, err = fmt.Fprintln(fileToWrite, string(formatted)) 164 | if err != nil { 165 | return err 166 | } 167 | return nil 168 | } 169 | 170 | func main() { 171 | dirWithSchemas := "" 172 | if len(os.Args) >= 2 { 173 | dirWithSchemas = os.Args[1] 174 | } 175 | if dirWithSchemas == "" { 176 | dirWithSchemas = dirWithSchemasConst 177 | } 178 | fileToGenerate := "" 179 | if len(os.Args) >= 3 { 180 | fileToGenerate = os.Args[2] 181 | } 182 | if fileToGenerate == "" { 183 | fileToGenerate = fileToGenerateConst 184 | } 185 | fileTestToGenerate := strings.Replace(fileToGenerate, ".go", "_test.go", -1) 186 | 187 | schemaFiles, err := os.ReadDir(dirWithSchemas) 188 | if err != nil { 189 | log.Fatal(err) 190 | } 191 | generatedFile, err := os.Create(fileToGenerate) 192 | if err != nil { 193 | log.Fatal(err) 194 | } 195 | generatedTestFile, err := os.Create(fileTestToGenerate) 196 | if err != nil { 197 | log.Fatal(err) 198 | } 199 | 200 | fmt.Fprintln(generatedFile, "// Package iuliia do not edit, generated file") 201 | fmt.Fprintln(generatedFile, "package iuliia") 202 | 203 | fmt.Fprintln(generatedTestFile, "// Package iuliia do not edit, generated file") 204 | fmt.Fprintln(generatedTestFile, "package iuliia") 205 | fmt.Fprintln(generatedTestFile) // empty line 206 | fmt.Fprintln(generatedTestFile, `import ( 207 | "fmt" 208 | "testing" 209 | )`) 210 | 211 | var b, bt []byte 212 | buffer := bytes.NewBuffer(b) 213 | bufferTest := bytes.NewBuffer(bt) 214 | schemas := make(map[string]string, 0) 215 | for _, schemaFile := range schemaFiles { 216 | if !strings.HasSuffix(schemaFile.Name(), ".json") { 217 | continue 218 | } 219 | var err error 220 | var schema schemable 221 | fileToRead := filepath.Join(dirWithSchemas, schemaFile.Name()) 222 | fmt.Println(fileToRead) 223 | schema = &SchemaGen{} 224 | err = printSchemaToBuffer(fileToRead, schema, schemas, buffer, bufferTest) 225 | if err != nil { 226 | log.Fatal(err) 227 | } 228 | } 229 | 230 | var res bytes.Buffer 231 | if err := schemasTpl.Execute(&res, schemas); err != nil { 232 | log.Panicln("error in gen template for all schemas", err) 233 | } 234 | _, err = fmt.Fprint(buffer, res.String()) 235 | if err != nil { 236 | log.Panicln("error in adding code for all schemas", err) 237 | } 238 | err = printToFileWithFmt(buffer, generatedFile) 239 | if err != nil { 240 | log.Panicln("error in printing to file result", err) 241 | } 242 | err = printToFileWithFmt(bufferTest, generatedTestFile) 243 | if err != nil { 244 | log.Panicln("error in printing to file test result", err) 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /schemas_test.go: -------------------------------------------------------------------------------- 1 | // Package iuliia do not edit, generated file 2 | package iuliia 3 | 4 | import ( 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | // Ala_lc schema 10 | func Test_Ala_lc(t *testing.T) { 11 | tests := []struct { 12 | name string 13 | in string 14 | out string 15 | }{ 16 | { 17 | name: "0", 18 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 19 | out: "I͡ulii͡a, sʺeshʹ eshchё ėtikh mi͡agkikh frant͡suzskikh bulok iz Ĭoshkar-Oly, da vypeĭ altaĭskogo chai͡u", 20 | }, 21 | } 22 | for _, tt := range tests { 23 | t.Run(tt.name, func(t *testing.T) { 24 | Ala_lc.isBuilt = false 25 | got := Ala_lc.Translate(tt.in) 26 | if got != tt.out { 27 | fmt.Println(Ala_lc) 28 | t.Errorf("Ala_lc got:\n%v\nbut want:\n%v\n", got, tt.out) 29 | } 30 | }) 31 | } 32 | } 33 | 34 | // Ala_lc_alt schema 35 | func Test_Ala_lc_alt(t *testing.T) { 36 | tests := []struct { 37 | name string 38 | in string 39 | out string 40 | }{ 41 | { 42 | name: "0", 43 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 44 | out: "Iuliia, s\"esh' eshche etikh miagkikh frantsuzskikh bulok iz Ioshkar-Oly, da vypei altaiskogo chaiu", 45 | }, 46 | } 47 | for _, tt := range tests { 48 | t.Run(tt.name, func(t *testing.T) { 49 | Ala_lc_alt.isBuilt = false 50 | got := Ala_lc_alt.Translate(tt.in) 51 | if got != tt.out { 52 | fmt.Println(Ala_lc_alt) 53 | t.Errorf("Ala_lc_alt got:\n%v\nbut want:\n%v\n", got, tt.out) 54 | } 55 | }) 56 | } 57 | } 58 | 59 | // Bgn_pcgn schema 60 | func Test_Bgn_pcgn(t *testing.T) { 61 | tests := []struct { 62 | name string 63 | in string 64 | out string 65 | }{ 66 | { 67 | name: "0", 68 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 69 | out: "Yuliya, s”yesh’ yeshchё etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 70 | }, 71 | { 72 | name: "1", 73 | in: "Россия, город Йошкар-Ола, улица Яна Крастыня", 74 | out: "Rossiya, gorod Yoshkar-Ola, ulitsa Yana Krastynya", 75 | }, 76 | { 77 | name: "2", 78 | in: "Елизово", 79 | out: "Yelizovo", 80 | }, 81 | { 82 | name: "3", 83 | in: "Чапаевск", 84 | out: "Chapayevsk", 85 | }, 86 | { 87 | name: "4", 88 | in: "Мейеровка", 89 | out: "Meyyerovka", 90 | }, 91 | { 92 | name: "5", 93 | in: "Юрьев объезд", 94 | out: "Yur’yev ob”yezd", 95 | }, 96 | { 97 | name: "6", 98 | in: "Белкино", 99 | out: "Belkino", 100 | }, 101 | { 102 | name: "7", 103 | in: "Ёдва", 104 | out: "Yёdva", 105 | }, 106 | { 107 | name: "8", 108 | in: "Змииёвка", 109 | out: "Zmiiyёvka", 110 | }, 111 | { 112 | name: "9", 113 | in: "Айёган", 114 | out: "Ayyёgan", 115 | }, 116 | { 117 | name: "10", 118 | in: "Воробьёво", 119 | out: "Vorob’yёvo", 120 | }, 121 | { 122 | name: "11", 123 | in: "Кебанъёль", 124 | out: "Keban”yёl’", 125 | }, 126 | { 127 | name: "12", 128 | in: "Озёрный", 129 | out: "Ozёrnyy", 130 | }, 131 | { 132 | name: "13", 133 | in: "Тыайа", 134 | out: "Ty·ay·a", 135 | }, 136 | { 137 | name: "14", 138 | in: "Сайылык", 139 | out: "Say·ylyk", 140 | }, 141 | { 142 | name: "15", 143 | in: "Ойусардах", 144 | out: "Oy·usardakh", 145 | }, 146 | { 147 | name: "16", 148 | in: "Йошкар-Ола", 149 | out: "Yoshkar-Ola", 150 | }, 151 | { 152 | name: "17", 153 | in: "Бийск", 154 | out: "Biysk", 155 | }, 156 | { 157 | name: "18", 158 | in: "Тыэкан", 159 | out: "Ty·ekan", 160 | }, 161 | { 162 | name: "19", 163 | in: "Суык-Су", 164 | out: "Su·yk-Su", 165 | }, 166 | { 167 | name: "20", 168 | in: "Тында", 169 | out: "Tynda", 170 | }, 171 | { 172 | name: "21", 173 | in: "Улан-Удэ", 174 | out: "Ulan-Ud·e", 175 | }, 176 | { 177 | name: "22", 178 | in: "Электрогорск", 179 | out: "Elektrogorsk", 180 | }, 181 | { 182 | name: "23", 183 | in: "Руэм", 184 | out: "Ruem", 185 | }, 186 | { 187 | name: "24", 188 | in: "Вяртсиля", 189 | out: "Vyart·silya", 190 | }, 191 | { 192 | name: "25", 193 | in: "Ташчишма", 194 | out: "Tash·chishma", 195 | }, 196 | } 197 | for _, tt := range tests { 198 | t.Run(tt.name, func(t *testing.T) { 199 | Bgn_pcgn.isBuilt = false 200 | got := Bgn_pcgn.Translate(tt.in) 201 | if got != tt.out { 202 | fmt.Println(Bgn_pcgn) 203 | t.Errorf("Bgn_pcgn got:\n%v\nbut want:\n%v\n", got, tt.out) 204 | } 205 | }) 206 | } 207 | } 208 | 209 | // Bgn_pcgn_alt schema 210 | func Test_Bgn_pcgn_alt(t *testing.T) { 211 | tests := []struct { 212 | name string 213 | in string 214 | out string 215 | }{ 216 | { 217 | name: "0", 218 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 219 | out: "Yuliya, s”yesh’ yeshchё etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 220 | }, 221 | { 222 | name: "1", 223 | in: "Россия, город Йошкар-Ола, улица Яна Крастыня", 224 | out: "Rossiya, gorod Yoshkar-Ola, ulitsa Yana Krastynya", 225 | }, 226 | { 227 | name: "2", 228 | in: "Елизово", 229 | out: "Yelizovo", 230 | }, 231 | { 232 | name: "3", 233 | in: "Чапаевск", 234 | out: "Chapayevsk", 235 | }, 236 | { 237 | name: "4", 238 | in: "Мейеровка", 239 | out: "Meyyerovka", 240 | }, 241 | { 242 | name: "5", 243 | in: "Юрьев объезд", 244 | out: "Yur’yev ob”yezd", 245 | }, 246 | { 247 | name: "6", 248 | in: "Белкино", 249 | out: "Belkino", 250 | }, 251 | { 252 | name: "7", 253 | in: "Ёдва", 254 | out: "Yёdva", 255 | }, 256 | { 257 | name: "8", 258 | in: "Змииёвка", 259 | out: "Zmiiyёvka", 260 | }, 261 | { 262 | name: "9", 263 | in: "Айёган", 264 | out: "Ayyёgan", 265 | }, 266 | { 267 | name: "10", 268 | in: "Воробьёво", 269 | out: "Vorob’yёvo", 270 | }, 271 | { 272 | name: "11", 273 | in: "Кебанъёль", 274 | out: "Keban”yёl’", 275 | }, 276 | { 277 | name: "12", 278 | in: "Озёрный", 279 | out: "Ozёrnyy", 280 | }, 281 | { 282 | name: "13", 283 | in: "Тыайа", 284 | out: "Tyaya", 285 | }, 286 | { 287 | name: "14", 288 | in: "Сайылык", 289 | out: "Sayylyk", 290 | }, 291 | { 292 | name: "15", 293 | in: "Ойусардах", 294 | out: "Oyusardakh", 295 | }, 296 | { 297 | name: "16", 298 | in: "Йошкар-Ола", 299 | out: "Yoshkar-Ola", 300 | }, 301 | { 302 | name: "17", 303 | in: "Бийск", 304 | out: "Biysk", 305 | }, 306 | { 307 | name: "18", 308 | in: "Тыэкан", 309 | out: "Tyekan", 310 | }, 311 | { 312 | name: "19", 313 | in: "Суык-Су", 314 | out: "Suyk-Su", 315 | }, 316 | { 317 | name: "20", 318 | in: "Тында", 319 | out: "Tynda", 320 | }, 321 | { 322 | name: "21", 323 | in: "Улан-Удэ", 324 | out: "Ulan-Ude", 325 | }, 326 | { 327 | name: "22", 328 | in: "Электрогорск", 329 | out: "Elektrogorsk", 330 | }, 331 | { 332 | name: "23", 333 | in: "Руэм", 334 | out: "Ruem", 335 | }, 336 | { 337 | name: "24", 338 | in: "Вяртсиля", 339 | out: "Vyartsilya", 340 | }, 341 | { 342 | name: "25", 343 | in: "Ташчишма", 344 | out: "Tashchishma", 345 | }, 346 | } 347 | for _, tt := range tests { 348 | t.Run(tt.name, func(t *testing.T) { 349 | Bgn_pcgn_alt.isBuilt = false 350 | got := Bgn_pcgn_alt.Translate(tt.in) 351 | if got != tt.out { 352 | fmt.Println(Bgn_pcgn_alt) 353 | t.Errorf("Bgn_pcgn_alt got:\n%v\nbut want:\n%v\n", got, tt.out) 354 | } 355 | }) 356 | } 357 | } 358 | 359 | // Bs_2979 schema 360 | func Test_Bs_2979(t *testing.T) { 361 | tests := []struct { 362 | name string 363 | in string 364 | out string 365 | }{ 366 | { 367 | name: "0", 368 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 369 | out: "Yuliya, sʺeshʹ eshchё étikh myagkikh frantsuzskikh bulok iz Ĭoshkar-Olȳ, da vȳpeĭ altaĭskogo chayu", 370 | }, 371 | } 372 | for _, tt := range tests { 373 | t.Run(tt.name, func(t *testing.T) { 374 | Bs_2979.isBuilt = false 375 | got := Bs_2979.Translate(tt.in) 376 | if got != tt.out { 377 | fmt.Println(Bs_2979) 378 | t.Errorf("Bs_2979 got:\n%v\nbut want:\n%v\n", got, tt.out) 379 | } 380 | }) 381 | } 382 | } 383 | 384 | // Bs_2979_alt schema 385 | func Test_Bs_2979_alt(t *testing.T) { 386 | tests := []struct { 387 | name string 388 | in string 389 | out string 390 | }{ 391 | { 392 | name: "0", 393 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 394 | out: "Yuliya, s\"esh' eshche etikh myagkikh frantsuzskikh bulok iz Ioshkar-Oly, da vypei altaiskogo chayu", 395 | }, 396 | } 397 | for _, tt := range tests { 398 | t.Run(tt.name, func(t *testing.T) { 399 | Bs_2979_alt.isBuilt = false 400 | got := Bs_2979_alt.Translate(tt.in) 401 | if got != tt.out { 402 | fmt.Println(Bs_2979_alt) 403 | t.Errorf("Bs_2979_alt got:\n%v\nbut want:\n%v\n", got, tt.out) 404 | } 405 | }) 406 | } 407 | } 408 | 409 | // Gost_16876 schema 410 | func Test_Gost_16876(t *testing.T) { 411 | tests := []struct { 412 | name string 413 | in string 414 | out string 415 | }{ 416 | { 417 | name: "0", 418 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 419 | out: "Ûliâ, sʺešʹ eŝё ètih mâgkih francuzskih bulok iz Joškar-Oly, da vypej altajskogo čaû", 420 | }, 421 | } 422 | for _, tt := range tests { 423 | t.Run(tt.name, func(t *testing.T) { 424 | Gost_16876.isBuilt = false 425 | got := Gost_16876.Translate(tt.in) 426 | if got != tt.out { 427 | fmt.Println(Gost_16876) 428 | t.Errorf("Gost_16876 got:\n%v\nbut want:\n%v\n", got, tt.out) 429 | } 430 | }) 431 | } 432 | } 433 | 434 | // Gost_16876_alt schema 435 | func Test_Gost_16876_alt(t *testing.T) { 436 | tests := []struct { 437 | name string 438 | in string 439 | out string 440 | }{ 441 | { 442 | name: "0", 443 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 444 | out: "Julija, s\"esh' eshhjo ehtikh mjagkikh francuzskikh bulok iz Jjoshkar-Oly, da vypejj altajjskogo chaju", 445 | }, 446 | } 447 | for _, tt := range tests { 448 | t.Run(tt.name, func(t *testing.T) { 449 | Gost_16876_alt.isBuilt = false 450 | got := Gost_16876_alt.Translate(tt.in) 451 | if got != tt.out { 452 | fmt.Println(Gost_16876_alt) 453 | t.Errorf("Gost_16876_alt got:\n%v\nbut want:\n%v\n", got, tt.out) 454 | } 455 | }) 456 | } 457 | } 458 | 459 | // Gost_52290 schema 460 | func Test_Gost_52290(t *testing.T) { 461 | tests := []struct { 462 | name string 463 | in string 464 | out string 465 | }{ 466 | { 467 | name: "0", 468 | in: "Россия, город Йошкар-Ола, улица Яна Крастыня", 469 | out: "Rossiya, gorod Yoshkar-Ola, ulitsa Yana Krastynya", 470 | }, 471 | { 472 | name: "1", 473 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 474 | out: "Yuliya, syesh' eshche etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 475 | }, 476 | { 477 | name: "2", 478 | in: "Ё Крё Мякоё", 479 | out: "Yo Krye Myakoyo", 480 | }, 481 | } 482 | for _, tt := range tests { 483 | t.Run(tt.name, func(t *testing.T) { 484 | Gost_52290.isBuilt = false 485 | got := Gost_52290.Translate(tt.in) 486 | if got != tt.out { 487 | fmt.Println(Gost_52290) 488 | t.Errorf("Gost_52290 got:\n%v\nbut want:\n%v\n", got, tt.out) 489 | } 490 | }) 491 | } 492 | } 493 | 494 | // Gost_52535 schema 495 | func Test_Gost_52535(t *testing.T) { 496 | tests := []struct { 497 | name string 498 | in string 499 | out string 500 | }{ 501 | { 502 | name: "0", 503 | in: "Юлия Щеглова", 504 | out: "Iuliia Shcheglova", 505 | }, 506 | { 507 | name: "1", 508 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 509 | out: "Iuliia, sesh eshche etikh miagkikh frantcuzskikh bulok iz Ioshkar-Oly, da vypei altaiskogo chaiu", 510 | }, 511 | } 512 | for _, tt := range tests { 513 | t.Run(tt.name, func(t *testing.T) { 514 | Gost_52535.isBuilt = false 515 | got := Gost_52535.Translate(tt.in) 516 | if got != tt.out { 517 | fmt.Println(Gost_52535) 518 | t.Errorf("Gost_52535 got:\n%v\nbut want:\n%v\n", got, tt.out) 519 | } 520 | }) 521 | } 522 | } 523 | 524 | // Gost_7034 schema 525 | func Test_Gost_7034(t *testing.T) { 526 | tests := []struct { 527 | name string 528 | in string 529 | out string 530 | }{ 531 | { 532 | name: "0", 533 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 534 | out: "Yuliya, s''esh' eshhyo etix myagkix francuzskix bulok iz Joshkar-Oly, da vypej altajskogo chayu", 535 | }, 536 | } 537 | for _, tt := range tests { 538 | t.Run(tt.name, func(t *testing.T) { 539 | Gost_7034.isBuilt = false 540 | got := Gost_7034.Translate(tt.in) 541 | if got != tt.out { 542 | fmt.Println(Gost_7034) 543 | t.Errorf("Gost_7034 got:\n%v\nbut want:\n%v\n", got, tt.out) 544 | } 545 | }) 546 | } 547 | } 548 | 549 | // Gost_779 schema 550 | func Test_Gost_779(t *testing.T) { 551 | tests := []struct { 552 | name string 553 | in string 554 | out string 555 | }{ 556 | { 557 | name: "0", 558 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 559 | out: "Ûliâ, sʺešʹ eŝё ètih mâgkih francuzskih bulok iz Joškar-Oly, da vypej altajskogo čaû", 560 | }, 561 | } 562 | for _, tt := range tests { 563 | t.Run(tt.name, func(t *testing.T) { 564 | Gost_779.isBuilt = false 565 | got := Gost_779.Translate(tt.in) 566 | if got != tt.out { 567 | fmt.Println(Gost_779) 568 | t.Errorf("Gost_779 got:\n%v\nbut want:\n%v\n", got, tt.out) 569 | } 570 | }) 571 | } 572 | } 573 | 574 | // Gost_779_alt schema 575 | func Test_Gost_779_alt(t *testing.T) { 576 | tests := []struct { 577 | name string 578 | in string 579 | out string 580 | }{ 581 | { 582 | name: "0", 583 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 584 | out: "Yuliya, s``esh` eshhyo e`tix myagkix franczuzskix bulok iz Joshkar-Oly`, da vy`pej altajskogo chayu", 585 | }, 586 | } 587 | for _, tt := range tests { 588 | t.Run(tt.name, func(t *testing.T) { 589 | Gost_779_alt.isBuilt = false 590 | got := Gost_779_alt.Translate(tt.in) 591 | if got != tt.out { 592 | fmt.Println(Gost_779_alt) 593 | t.Errorf("Gost_779_alt got:\n%v\nbut want:\n%v\n", got, tt.out) 594 | } 595 | }) 596 | } 597 | } 598 | 599 | // Icao_doc_9303 schema 600 | func Test_Icao_doc_9303(t *testing.T) { 601 | tests := []struct { 602 | name string 603 | in string 604 | out string 605 | }{ 606 | { 607 | name: "0", 608 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 609 | out: "Iuliia, sieesh eshche etikh miagkikh frantsuzskikh bulok iz Ioshkar-Oly, da vypei altaiskogo chaiu", 610 | }, 611 | { 612 | name: "1", 613 | in: "Юлия Щеглова", 614 | out: "Iuliia Shcheglova", 615 | }, 616 | { 617 | name: "2", 618 | in: "Гайа Васильева", 619 | out: "Gaia Vasileva", 620 | }, 621 | { 622 | name: "3", 623 | in: "Андрей Видный", 624 | out: "Andrei Vidnyi", 625 | }, 626 | { 627 | name: "4", 628 | in: "Артём Краевой", 629 | out: "Artem Kraevoi", 630 | }, 631 | { 632 | name: "5", 633 | in: "Мадыр Чёткий", 634 | out: "Madyr Chetkii", 635 | }, 636 | { 637 | name: "6", 638 | in: "Оксана Клеёнкина", 639 | out: "Oksana Kleenkina", 640 | }, 641 | { 642 | name: "7", 643 | in: "Игорь Ильин", 644 | out: "Igor Ilin", 645 | }, 646 | { 647 | name: "8", 648 | in: "Ян Разъездной", 649 | out: "Ian Razieezdnoi", 650 | }, 651 | } 652 | for _, tt := range tests { 653 | t.Run(tt.name, func(t *testing.T) { 654 | Icao_doc_9303.isBuilt = false 655 | got := Icao_doc_9303.Translate(tt.in) 656 | if got != tt.out { 657 | fmt.Println(Icao_doc_9303) 658 | t.Errorf("Icao_doc_9303 got:\n%v\nbut want:\n%v\n", got, tt.out) 659 | } 660 | }) 661 | } 662 | } 663 | 664 | // Iso_9_1954 schema 665 | func Test_Iso_9_1954(t *testing.T) { 666 | tests := []struct { 667 | name string 668 | in string 669 | out string 670 | }{ 671 | { 672 | name: "0", 673 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 674 | out: "Julija, s\"ešʹ eščë ėtih mjagkih francuzskih bulok iz Joškar-Oly, da vypej altajskogo čaju", 675 | }, 676 | } 677 | for _, tt := range tests { 678 | t.Run(tt.name, func(t *testing.T) { 679 | Iso_9_1954.isBuilt = false 680 | got := Iso_9_1954.Translate(tt.in) 681 | if got != tt.out { 682 | fmt.Println(Iso_9_1954) 683 | t.Errorf("Iso_9_1954 got:\n%v\nbut want:\n%v\n", got, tt.out) 684 | } 685 | }) 686 | } 687 | } 688 | 689 | // Iso_9_1968 schema 690 | func Test_Iso_9_1968(t *testing.T) { 691 | tests := []struct { 692 | name string 693 | in string 694 | out string 695 | }{ 696 | { 697 | name: "0", 698 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 699 | out: "Julija, sʺešʹ eščë ėtih mjagkih francuzskih bulok iz Joškar-Oly, da vypej altajskogo čaju", 700 | }, 701 | } 702 | for _, tt := range tests { 703 | t.Run(tt.name, func(t *testing.T) { 704 | Iso_9_1968.isBuilt = false 705 | got := Iso_9_1968.Translate(tt.in) 706 | if got != tt.out { 707 | fmt.Println(Iso_9_1968) 708 | t.Errorf("Iso_9_1968 got:\n%v\nbut want:\n%v\n", got, tt.out) 709 | } 710 | }) 711 | } 712 | } 713 | 714 | // Iso_9_1968_alt schema 715 | func Test_Iso_9_1968_alt(t *testing.T) { 716 | tests := []struct { 717 | name string 718 | in string 719 | out string 720 | }{ 721 | { 722 | name: "0", 723 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 724 | out: "Yulyya, sʺeshʹ eshchë ėtykh myagkykh frantsuzskykh bulok yz Ĭoshkar-Oly, da vypeĭ altaĭskogo chayu", 725 | }, 726 | } 727 | for _, tt := range tests { 728 | t.Run(tt.name, func(t *testing.T) { 729 | Iso_9_1968_alt.isBuilt = false 730 | got := Iso_9_1968_alt.Translate(tt.in) 731 | if got != tt.out { 732 | fmt.Println(Iso_9_1968_alt) 733 | t.Errorf("Iso_9_1968_alt got:\n%v\nbut want:\n%v\n", got, tt.out) 734 | } 735 | }) 736 | } 737 | } 738 | 739 | // Mosmetro schema 740 | func Test_Mosmetro(t *testing.T) { 741 | tests := []struct { 742 | name string 743 | in string 744 | out string 745 | }{ 746 | { 747 | name: "0", 748 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 749 | out: "Yuliya, syesh esche etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 750 | }, 751 | { 752 | name: "1", 753 | in: "Битцевский парк", 754 | out: "Bitsevsky park", 755 | }, 756 | { 757 | name: "2", 758 | in: "Верхние Лихоборы", 759 | out: "Verkhnie Likhobory", 760 | }, 761 | { 762 | name: "3", 763 | in: "Воробьёвы горы", 764 | out: "Vorobyovy gory", 765 | }, 766 | { 767 | name: "4", 768 | in: "Выхино", 769 | out: "Vykhino", 770 | }, 771 | { 772 | name: "5", 773 | in: "Зябликово", 774 | out: "Zyablikovo", 775 | }, 776 | { 777 | name: "6", 778 | in: "Измайловская", 779 | out: "Izmaylovskaya", 780 | }, 781 | { 782 | name: "7", 783 | in: "Кожуховская", 784 | out: "Kozhukhovskaya", 785 | }, 786 | { 787 | name: "8", 788 | in: "Крылатское", 789 | out: "Krylatskoe", 790 | }, 791 | { 792 | name: "9", 793 | in: "Марьина Роща", 794 | out: "Maryina Roscha", 795 | }, 796 | { 797 | name: "10", 798 | in: "Марьино", 799 | out: "Maryino", 800 | }, 801 | { 802 | name: "11", 803 | in: "Молодёжная", 804 | out: "Molodezhnaya", 805 | }, 806 | { 807 | name: "12", 808 | in: "Октябрьская", 809 | out: "Oktyabrskaya", 810 | }, 811 | { 812 | name: "13", 813 | in: "Ольховая", 814 | out: "Olkhovaya", 815 | }, 816 | { 817 | name: "14", 818 | in: "Парк Победы", 819 | out: "Park Pobedy", 820 | }, 821 | { 822 | name: "15", 823 | in: "Площадь Ильича", 824 | out: "Ploschad Ilyicha", 825 | }, 826 | { 827 | name: "16", 828 | in: "Площадь Революции", 829 | out: "Ploschad Revolyutsii", 830 | }, 831 | { 832 | name: "17", 833 | in: "Пятницкое шоссе", 834 | out: "Pyatnitskoe shosse", 835 | }, 836 | { 837 | name: "18", 838 | in: "Румянцево", 839 | out: "Rumyantsevo", 840 | }, 841 | { 842 | name: "19", 843 | in: "Саларьево", 844 | out: "Salaryevo", 845 | }, 846 | { 847 | name: "20", 848 | in: "Семёновская", 849 | out: "Semenovskaya", 850 | }, 851 | { 852 | name: "21", 853 | in: "Сходненская", 854 | out: "Skhodnenskaya", 855 | }, 856 | { 857 | name: "22", 858 | in: "Текстильщики", 859 | out: "Tekstilschiki", 860 | }, 861 | { 862 | name: "23", 863 | in: "Тёплый стан", 864 | out: "Teply stan", 865 | }, 866 | { 867 | name: "24", 868 | in: "Третьяковская", 869 | out: "Tretyakovskaya", 870 | }, 871 | { 872 | name: "25", 873 | in: "Тропарёво", 874 | out: "Troparevo", 875 | }, 876 | { 877 | name: "26", 878 | in: "Фонвизинская", 879 | out: "Fonvizinskaya", 880 | }, 881 | { 882 | name: "27", 883 | in: "Чистые пруды", 884 | out: "Chistye prudy", 885 | }, 886 | { 887 | name: "28", 888 | in: "Шоссе Энтузиастов", 889 | out: "Shosse Entuziastov", 890 | }, 891 | { 892 | name: "29", 893 | in: "Щёлковская", 894 | out: "Schelkovskaya", 895 | }, 896 | { 897 | name: "30", 898 | in: "Электрозаводская", 899 | out: "Elektrozavodskaya", 900 | }, 901 | { 902 | name: "31", 903 | in: "Юго-Западная", 904 | out: "Yugo-Zapadnaya", 905 | }, 906 | } 907 | for _, tt := range tests { 908 | t.Run(tt.name, func(t *testing.T) { 909 | Mosmetro.isBuilt = false 910 | got := Mosmetro.Translate(tt.in) 911 | if got != tt.out { 912 | fmt.Println(Mosmetro) 913 | t.Errorf("Mosmetro got:\n%v\nbut want:\n%v\n", got, tt.out) 914 | } 915 | }) 916 | } 917 | } 918 | 919 | // Mvd_310 schema 920 | func Test_Mvd_310(t *testing.T) { 921 | tests := []struct { 922 | name string 923 | in string 924 | out string 925 | }{ 926 | { 927 | name: "0", 928 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 929 | out: "Yuliya, syesh' eshche etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 930 | }, 931 | { 932 | name: "1", 933 | in: "Юлия Щеглова", 934 | out: "Yuliya Shcheglova", 935 | }, 936 | { 937 | name: "2", 938 | in: "Гайа Васильева", 939 | out: "Gaya Vasilyeva", 940 | }, 941 | { 942 | name: "3", 943 | in: "Андрей Видный", 944 | out: "Andrey Vidnyy", 945 | }, 946 | } 947 | for _, tt := range tests { 948 | t.Run(tt.name, func(t *testing.T) { 949 | Mvd_310.isBuilt = false 950 | got := Mvd_310.Translate(tt.in) 951 | if got != tt.out { 952 | fmt.Println(Mvd_310) 953 | t.Errorf("Mvd_310 got:\n%v\nbut want:\n%v\n", got, tt.out) 954 | } 955 | }) 956 | } 957 | } 958 | 959 | // Mvd_310_fr schema 960 | func Test_Mvd_310_fr(t *testing.T) { 961 | tests := []struct { 962 | name string 963 | in string 964 | out string 965 | }{ 966 | { 967 | name: "0", 968 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 969 | out: "Iouliia, sech echtche etikh miagkikh frantsouzskikh boulok iz Iochkar-Oly, da vypei altaiskogo tchaiou", 970 | }, 971 | { 972 | name: "1", 973 | in: "Юлия Щеглова", 974 | out: "Iouliia Chtcheglova", 975 | }, 976 | { 977 | name: "2", 978 | in: "Гайа Васильева", 979 | out: "Gaia Vasilieva", 980 | }, 981 | { 982 | name: "3", 983 | in: "Андрей Видный", 984 | out: "Andrei Vidnyi", 985 | }, 986 | { 987 | name: "4", 988 | in: "Оксана Снегирёва", 989 | out: "Oxana Sneguireva", 990 | }, 991 | { 992 | name: "5", 993 | in: "Юрий Васин", 994 | out: "Iourii Vasine", 995 | }, 996 | } 997 | for _, tt := range tests { 998 | t.Run(tt.name, func(t *testing.T) { 999 | Mvd_310_fr.isBuilt = false 1000 | got := Mvd_310_fr.Translate(tt.in) 1001 | if got != tt.out { 1002 | fmt.Println(Mvd_310_fr) 1003 | t.Errorf("Mvd_310_fr got:\n%v\nbut want:\n%v\n", got, tt.out) 1004 | } 1005 | }) 1006 | } 1007 | } 1008 | 1009 | // Mvd_782 schema 1010 | func Test_Mvd_782(t *testing.T) { 1011 | tests := []struct { 1012 | name string 1013 | in string 1014 | out string 1015 | }{ 1016 | { 1017 | name: "0", 1018 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1019 | out: "Yuliya, syesh' eshche etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 1020 | }, 1021 | { 1022 | name: "1", 1023 | in: "Юлия Щеглова", 1024 | out: "Yuliya Shcheglova", 1025 | }, 1026 | { 1027 | name: "2", 1028 | in: "Гайа Васильева", 1029 | out: "Gaya Vasilyeva", 1030 | }, 1031 | { 1032 | name: "3", 1033 | in: "Андрей Видный", 1034 | out: "Andrey Vidnyy", 1035 | }, 1036 | { 1037 | name: "4", 1038 | in: "Артём Краевой", 1039 | out: "Artyem Krayevoy", 1040 | }, 1041 | { 1042 | name: "5", 1043 | in: "Мадыр Чёткий", 1044 | out: "Madyr Chetkiy", 1045 | }, 1046 | { 1047 | name: "6", 1048 | in: "Оксана Клеёнкина", 1049 | out: "Oksana Kleyonkina", 1050 | }, 1051 | { 1052 | name: "7", 1053 | in: "Игорь Ильин", 1054 | out: "Igor' Ilyin", 1055 | }, 1056 | } 1057 | for _, tt := range tests { 1058 | t.Run(tt.name, func(t *testing.T) { 1059 | Mvd_782.isBuilt = false 1060 | got := Mvd_782.Translate(tt.in) 1061 | if got != tt.out { 1062 | fmt.Println(Mvd_782) 1063 | t.Errorf("Mvd_782 got:\n%v\nbut want:\n%v\n", got, tt.out) 1064 | } 1065 | }) 1066 | } 1067 | } 1068 | 1069 | // Scientific schema 1070 | func Test_Scientific(t *testing.T) { 1071 | tests := []struct { 1072 | name string 1073 | in string 1074 | out string 1075 | }{ 1076 | { 1077 | name: "0", 1078 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1079 | out: "Julija, sʺešʹ eščё ètix mjagkix francuzskix bulok iz Joškar-Oly, da vypej altajskogo čaju", 1080 | }, 1081 | } 1082 | for _, tt := range tests { 1083 | t.Run(tt.name, func(t *testing.T) { 1084 | Scientific.isBuilt = false 1085 | got := Scientific.Translate(tt.in) 1086 | if got != tt.out { 1087 | fmt.Println(Scientific) 1088 | t.Errorf("Scientific got:\n%v\nbut want:\n%v\n", got, tt.out) 1089 | } 1090 | }) 1091 | } 1092 | } 1093 | 1094 | // Telegram schema 1095 | func Test_Telegram(t *testing.T) { 1096 | tests := []struct { 1097 | name string 1098 | in string 1099 | out string 1100 | }{ 1101 | { 1102 | name: "0", 1103 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1104 | out: "Iuliia, sesh esce etih miagkih francuzskih bulok iz Ioshkar-Oly, da vypei altaiskogo chaiu", 1105 | }, 1106 | } 1107 | for _, tt := range tests { 1108 | t.Run(tt.name, func(t *testing.T) { 1109 | Telegram.isBuilt = false 1110 | got := Telegram.Translate(tt.in) 1111 | if got != tt.out { 1112 | fmt.Println(Telegram) 1113 | t.Errorf("Telegram got:\n%v\nbut want:\n%v\n", got, tt.out) 1114 | } 1115 | }) 1116 | } 1117 | } 1118 | 1119 | // Ungegn_1987 schema 1120 | func Test_Ungegn_1987(t *testing.T) { 1121 | tests := []struct { 1122 | name string 1123 | in string 1124 | out string 1125 | }{ 1126 | { 1127 | name: "0", 1128 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1129 | out: "Julija, sʺešʹ eščё ètih mjagkih francuzskih bulok iz Joškar-Oly, da vypej altajskogo čaju", 1130 | }, 1131 | { 1132 | name: "1", 1133 | in: "Россия, город Йошкар-Ола, улица Яна Крастыня", 1134 | out: "Rossija, gorod Joškar-Ola, ulica Jana Krastynja", 1135 | }, 1136 | } 1137 | for _, tt := range tests { 1138 | t.Run(tt.name, func(t *testing.T) { 1139 | Ungegn_1987.isBuilt = false 1140 | got := Ungegn_1987.Translate(tt.in) 1141 | if got != tt.out { 1142 | fmt.Println(Ungegn_1987) 1143 | t.Errorf("Ungegn_1987 got:\n%v\nbut want:\n%v\n", got, tt.out) 1144 | } 1145 | }) 1146 | } 1147 | } 1148 | 1149 | // Uz schema 1150 | func Test_Uz(t *testing.T) { 1151 | tests := []struct { 1152 | name string 1153 | in string 1154 | out string 1155 | }{ 1156 | { 1157 | name: "0", 1158 | in: "Юлия, Ёшкар-Оладан олинган бу юмшоқ франтсуз рулоларини кўпроқ истеъмол қилинг ва Олтой чойини ичинг", 1159 | out: "Yuliya, Yoshkar-Oladan olingan bu yumshoq frantsuz rulolarini koʻproq isteʼmol qiling va Oltoy choyini iching", 1160 | }, 1161 | } 1162 | for _, tt := range tests { 1163 | t.Run(tt.name, func(t *testing.T) { 1164 | Uz.isBuilt = false 1165 | got := Uz.Translate(tt.in) 1166 | if got != tt.out { 1167 | fmt.Println(Uz) 1168 | t.Errorf("Uz got:\n%v\nbut want:\n%v\n", got, tt.out) 1169 | } 1170 | }) 1171 | } 1172 | } 1173 | 1174 | // Wikipedia schema 1175 | func Test_Wikipedia(t *testing.T) { 1176 | tests := []struct { 1177 | name string 1178 | in string 1179 | out string 1180 | }{ 1181 | { 1182 | name: "0", 1183 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1184 | out: "Yuliya, syesh yeshchyo etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 1185 | }, 1186 | { 1187 | name: "1", 1188 | in: "Россия, город Йошкар-Ола, улица Яна Крастыня", 1189 | out: "Rossiya, gorod Yoshkar-Ola, ulitsa Yana Krastynya", 1190 | }, 1191 | { 1192 | name: "2", 1193 | in: "Ельцин", 1194 | out: "Yeltsin", 1195 | }, 1196 | { 1197 | name: "3", 1198 | in: "Раздольное", 1199 | out: "Razdolnoye", 1200 | }, 1201 | { 1202 | name: "4", 1203 | in: "Юрьев", 1204 | out: "Yuryev", 1205 | }, 1206 | { 1207 | name: "5", 1208 | in: "Белкин", 1209 | out: "Belkin", 1210 | }, 1211 | { 1212 | name: "6", 1213 | in: "Бийск", 1214 | out: "Biysk", 1215 | }, 1216 | { 1217 | name: "7", 1218 | in: "Подъярский", 1219 | out: "Podyarsky", 1220 | }, 1221 | { 1222 | name: "8", 1223 | in: "Мусийкъонгийкоте", 1224 | out: "Musiykyongiykote", 1225 | }, 1226 | { 1227 | name: "9", 1228 | in: "Давыдов", 1229 | out: "Davydov", 1230 | }, 1231 | { 1232 | name: "10", 1233 | in: "Усолье", 1234 | out: "Usolye", 1235 | }, 1236 | { 1237 | name: "11", 1238 | in: "Выхухоль", 1239 | out: "Vykhukhol", 1240 | }, 1241 | { 1242 | name: "12", 1243 | in: "Дальнегорск", 1244 | out: "Dalnegorsk", 1245 | }, 1246 | { 1247 | name: "13", 1248 | in: "Ильинский", 1249 | out: "Ilyinsky", 1250 | }, 1251 | { 1252 | name: "14", 1253 | in: "Красный", 1254 | out: "Krasny", 1255 | }, 1256 | { 1257 | name: "15", 1258 | in: "Великий", 1259 | out: "Veliky", 1260 | }, 1261 | { 1262 | name: "16", 1263 | in: "Набережные Челны", 1264 | out: "Naberezhnye Chelny", 1265 | }, 1266 | } 1267 | for _, tt := range tests { 1268 | t.Run(tt.name, func(t *testing.T) { 1269 | Wikipedia.isBuilt = false 1270 | got := Wikipedia.Translate(tt.in) 1271 | if got != tt.out { 1272 | fmt.Println(Wikipedia) 1273 | t.Errorf("Wikipedia got:\n%v\nbut want:\n%v\n", got, tt.out) 1274 | } 1275 | }) 1276 | } 1277 | } 1278 | 1279 | // Yandex_maps schema 1280 | func Test_Yandex_maps(t *testing.T) { 1281 | tests := []struct { 1282 | name string 1283 | in string 1284 | out string 1285 | }{ 1286 | { 1287 | name: "0", 1288 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1289 | out: "Yuliya, syesh yeschyo etikh myagkikh frantsuzskikh bulok iz Yoshkar-Oly, da vypey altayskogo chayu", 1290 | }, 1291 | { 1292 | name: "1", 1293 | in: "Россия, город Йошкар-Ола, улица Яна Крастыня", 1294 | out: "Rossiya, gorod Yoshkar-Ola, ulitsa Yana Krastynya", 1295 | }, 1296 | { 1297 | name: "2", 1298 | in: "Санкт-Петербург, Подъездной пер", 1299 | out: "Sankt-Peterburg, Podyezdnoy per", 1300 | }, 1301 | { 1302 | name: "3", 1303 | in: "Москва, ул Подъёмная", 1304 | out: "Moskva, ul Podyomnaya", 1305 | }, 1306 | { 1307 | name: "4", 1308 | in: "Астрахань, ул Подъяпольского", 1309 | out: "Astrakhan, ul Podyapolskogo", 1310 | }, 1311 | { 1312 | name: "5", 1313 | in: "Щегловитовка", 1314 | out: "Scheglovitovka", 1315 | }, 1316 | { 1317 | name: "6", 1318 | in: "Новый Уренгой", 1319 | out: "Noviy Urengoy", 1320 | }, 1321 | { 1322 | name: "7", 1323 | in: "Елабуга", 1324 | out: "Yelabuga", 1325 | }, 1326 | { 1327 | name: "8", 1328 | in: "Бабаево", 1329 | out: "Babayevo", 1330 | }, 1331 | { 1332 | name: "9", 1333 | in: "Белово", 1334 | out: "Belovo", 1335 | }, 1336 | } 1337 | for _, tt := range tests { 1338 | t.Run(tt.name, func(t *testing.T) { 1339 | Yandex_maps.isBuilt = false 1340 | got := Yandex_maps.Translate(tt.in) 1341 | if got != tt.out { 1342 | fmt.Println(Yandex_maps) 1343 | t.Errorf("Yandex_maps got:\n%v\nbut want:\n%v\n", got, tt.out) 1344 | } 1345 | }) 1346 | } 1347 | } 1348 | 1349 | // Yandex_money schema 1350 | func Test_Yandex_money(t *testing.T) { 1351 | tests := []struct { 1352 | name string 1353 | in string 1354 | out string 1355 | }{ 1356 | { 1357 | name: "0", 1358 | in: "Юлия, съешь ещё этих мягких французских булок из Йошкар-Олы, да выпей алтайского чаю", 1359 | out: "Yuliya, sesh esche etikh myagkikh frantsuzskikh bulok iz Ioshkar-Oly, da vypei altaiskogo chayu", 1360 | }, 1361 | { 1362 | name: "1", 1363 | in: "Юлия Щеглова", 1364 | out: "Yuliya Scheglova", 1365 | }, 1366 | { 1367 | name: "2", 1368 | in: "Иван Брызгальский", 1369 | out: "Ivan Bryzgalskii", 1370 | }, 1371 | { 1372 | name: "3", 1373 | in: "Ксения Стрый", 1374 | out: "Kseniya Stryi", 1375 | }, 1376 | } 1377 | for _, tt := range tests { 1378 | t.Run(tt.name, func(t *testing.T) { 1379 | Yandex_money.isBuilt = false 1380 | got := Yandex_money.Translate(tt.in) 1381 | if got != tt.out { 1382 | fmt.Println(Yandex_money) 1383 | t.Errorf("Yandex_money got:\n%v\nbut want:\n%v\n", got, tt.out) 1384 | } 1385 | }) 1386 | } 1387 | } 1388 | --------------------------------------------------------------------------------