├── .travis.yml ├── examples └── test.rs ├── .gitignore ├── Cargo.toml ├── .vscode └── tasks.json ├── src ├── avro.rs ├── lib.rs ├── parser.rs └── AvroPhonetic.json ├── README.md └── LICENSE /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - 1.31.0 4 | - stable 5 | - beta 6 | - nightly 7 | matrix: 8 | allow_failures: 9 | - rust: nightly 10 | notifications: 11 | email: false 12 | -------------------------------------------------------------------------------- /examples/test.rs: -------------------------------------------------------------------------------- 1 | use rupantor::parser::PhoneticParser; 2 | 3 | fn main() { 4 | // Parse the rule file 5 | let js = serde_json::from_str(include_str!("../src/AvroPhonetic.json")).unwrap(); 6 | 7 | let cvt = PhoneticParser::new(&js); 8 | println!("{}", cvt.convert("ami banglay gan gai")); 9 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rupantor" 3 | version = "0.3.0" 4 | description = "A Bengali Phonetic Parser which is very flexible and supports Avro Phonetic" 5 | authors = ["Muhammad Mominul Huque "] 6 | categories = ["text-processing"] 7 | keywords = ["avro-phonetic", "bangla", "bengali", "avro"] 8 | license = "MPL-2.0" 9 | readme = "README.md" 10 | repository = "https://github.com/OpenBangla/rupantor-rs" 11 | edition = "2018" 12 | 13 | [dependencies] 14 | serde_json = "1.0" 15 | stringplus = "0.1" 16 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "cargo", 4 | "isShellCommand": true, 5 | "showOutput": "always", 6 | "suppressTaskName": true, 7 | "tasks": [ 8 | { 9 | "taskName": "cargo build", 10 | "args": [ 11 | "build" 12 | ], 13 | "isBuildCommand": true 14 | }, 15 | { 16 | "taskName": "cargo run", 17 | "args": [ 18 | "run" 19 | ] 20 | }, 21 | { 22 | "taskName": "cargo test", 23 | "args": [ 24 | "test" 25 | ], 26 | "isTestCommand": true 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /src/avro.rs: -------------------------------------------------------------------------------- 1 | use serde_json; 2 | use crate::parser::PhoneticParser; 3 | 4 | /// Converts text into Bengali by using Avro Phonetic 5 | /// transliteration method. 6 | pub struct AvroPhonetic { 7 | parser: PhoneticParser, 8 | } 9 | 10 | impl AvroPhonetic { 11 | /// Creates a new AvroPhonetic instance. 12 | pub fn new() -> AvroPhonetic { 13 | let rule = serde_json::from_str(include_str!("AvroPhonetic.json")).unwrap(); 14 | AvroPhonetic { parser: PhoneticParser::new(&rule) } 15 | } 16 | 17 | /// Converts the input text into Bengali by using Avro Phonetic method. 18 | /// 19 | /// # Example 20 | /// ```rust 21 | /// # use rupantor::avro::AvroPhonetic; 22 | /// assert_eq!(AvroPhonetic::new().convert("rasT"), "রাস্ট"); 23 | /// ``` 24 | pub fn convert(&self, input: &str) -> String { 25 | self.parser.convert(input) 26 | } 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::AvroPhonetic; 32 | 33 | #[test] 34 | fn test_avro() { 35 | let parser = AvroPhonetic::new(); 36 | assert_eq!(parser.convert("amader valObasa hoye gel ghas, kheye gel goru ar diye gelo ba^sh"), "আমাদের ভালোবাসা হয়ে গেল ঘাস, খেয়ে গেল গরু আর দিয়ে গেল বাঁশ"); 37 | } 38 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rupantor-rs 2 | [![Build Status](https://travis-ci.org/OpenBangla/rupantor-rs.svg?branch=master)](https://travis-ci.org/OpenBangla/rupantor-rs) 3 | [![Rust](https://img.shields.io/badge/rust-1.31.0%2B-blue.svg?maxAge=3600)](https://github.com/OpenBangla/rupantor-rs) 4 | [![crates.io](https://img.shields.io/crates/v/rupantor.svg)](https://crates.io/crates/rupantor) 5 | [![DOCS.rs](https://docs.rs/rupantor/badge.svg)](https://docs.rs/rupantor) 6 | 7 | A Bengali Phonetic Parser which is very flexible and converts text into Bengali according to a json formatted grammar. 8 | 9 | `rupantor` supports **Avro Phonetic** out of the box, which is a very popular phonetic based transliteration method for writing Bengali. 10 | `rupantor` is very flexible as it is possible to control the conversion by specifying the *grammar*/*conversion rules*. So it is possible 11 | by the user to create a phonetic method by specifying a custom grammar. 12 | 13 | ## Usage 14 | Add this to your `Cargo.toml`: 15 | ```toml 16 | [dependencies] 17 | rupantor = "0.3" 18 | ``` 19 | 20 | ## Example 21 | This example shows how to use Avro Phonetic: 22 | ```rust 23 | use rupantor::avro::AvroPhonetic; 24 | 25 | let avro = AvroPhonetic::new(); 26 | let bengali = avro.convert("ami banglay gan gai"); 27 | assert_eq!(bengali, "আমি বাংলায় গান গাই"); 28 | ``` 29 | 30 | ## License 31 | `rupantor` is distributed under the terms of MPL License (Version 2.0). 32 | 33 | See [LICENSE](https://github.com/OpenBangla/rupantor-rs/blob/master/LICENSE) for details. -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! **Rupantor** is a very flexible Bengali phonetic parser 2 | //! written in Rust. 3 | //! 4 | //! `rupantor` converts text into Bengali text by obeying the _rules_ 5 | //! given in a _grammar_. A grammar is actually a Json formated data. 6 | //! 7 | //! **Avro Phonetic** is a very popular phonetic based transliteration method 8 | //! for writing Bengali. `rupantor` supports Avro Phonetic writing method out of the box. 9 | //! User can use Avro Phonetic by using the [`AvroPhonetic`](avro/struct.AvroPhonetic.html). 10 | //! 11 | //! # Example: Using Avro Phonetic to convert text into Bengali 12 | //! ```rust 13 | //! use rupantor::avro::AvroPhonetic; 14 | //! 15 | //! let avro = AvroPhonetic::new(); 16 | //! let bengali = avro.convert("ami banglay gan gai"); 17 | //! assert_eq!(bengali, "আমি বাংলায় গান গাই"); 18 | //! ``` 19 | //! 20 | //! `rupantor` is very flexible as the conversion is driven by a __grammar__ file. Actually 21 | //! the [`AvroPhonetic`](avro/struct.AvroPhonetic.html) struct uses [`PhoneticParser`](parser/struct.PhoneticParser.html) 22 | //! struct and a Avro Phonetic [grammar file](https://github.com/OpenBangla/rupantor-rs/blob/master/src/AvroPhonetic.json) 23 | //! internally to do the conversion. 24 | //! 25 | //! The phonetic conversion algorithm was actually implemented by 26 | //! [Rifat Nabi](https://github.com/torifat) in [JavaScript](https://github.com/torifat/jsAvroPhonetic) 27 | //! and [ObjectiveC](https://github.com/torifat/iAvro/blob/master/AvroParser.m). 28 | //! This crate is the Rust port of that phonetic conversion algorithm. 29 | 30 | pub mod parser; 31 | pub mod avro; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /src/parser.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_assignments)] 2 | use std::cmp::Ordering; 3 | use serde_json::Value; 4 | use stringplus::StringPlus; 5 | 6 | /// Parses and converts text into Bengali according to given grammar. 7 | pub struct PhoneticParser { 8 | patterns: Vec, 9 | vowel: String, 10 | consonant: String, 11 | numbers: String, 12 | case_sensitive: String, 13 | max_pattern_len: usize, 14 | } 15 | 16 | impl PhoneticParser { 17 | /// Creates a new `PhoneticParser` instance from the given Json 18 | /// value. The Json value must need to be a Json Object containing 19 | /// the required values, otherwise a panic would occur. 20 | pub fn new(rule: &Value) -> PhoneticParser { 21 | PhoneticParser { 22 | patterns: rule["patterns"].as_array().unwrap().clone(), 23 | vowel: rule["vowel"].as_str().unwrap().to_string(), 24 | consonant: rule["consonant"].as_str().unwrap().to_string(), 25 | numbers: rule["number"].as_str().unwrap().to_string(), 26 | case_sensitive: rule["casesensitive"].as_str().unwrap().to_string(), 27 | max_pattern_len: rule["patterns"][0]["find"].as_str().unwrap().len(), 28 | } 29 | } 30 | 31 | /// Converts the given input string into Bengali according to the grammar. 32 | pub fn convert(&self, input: &str) -> String { 33 | let fixed = self.fix_string(input); 34 | let len = fixed.len(); 35 | let mut output = String::with_capacity(len * 3); 36 | 37 | let mut cur = 0; 38 | while cur < len { 39 | let start = cur as i32; 40 | let mut end: i32 = 0; 41 | let mut matched = false; 42 | 43 | for chunk_len in (1..=self.max_pattern_len).rev() { 44 | end = start + chunk_len as i32; 45 | if end <= len as i32 { 46 | let chunk = fixed.substring(start as usize, chunk_len as usize); 47 | 48 | // Binary Search 49 | let mut left: i32 = 0; 50 | let mut right = self.patterns.len() as i32 - 1; 51 | let mut mid: i32 = 0; 52 | while right >= left { 53 | mid = (right + left) / 2; 54 | let pattern = &self.patterns[mid as usize]; 55 | let find = pattern["find"].as_str().unwrap(); 56 | if find == chunk { 57 | let rules = pattern["rules"].as_array().unwrap(); 58 | if !rules.is_empty() { 59 | for rule in rules { 60 | let mut replace = true; 61 | let mut chk = 0; 62 | let matches = rule["matches"].as_array().unwrap(); 63 | for _match in matches { 64 | let value = _match["value"].as_str().unwrap_or_default(); 65 | let _type = _match["type"].as_str().unwrap(); 66 | let mut scope = _match["scope"].as_str().unwrap(); 67 | let mut is_negative = false; 68 | 69 | // Handle Negative 70 | if &scope[0..1] == "!" { 71 | is_negative = true; 72 | scope = &scope[1..]; 73 | } 74 | 75 | if _type == "suffix" { 76 | chk = end; 77 | } else { 78 | chk = start - 1; 79 | } 80 | 81 | // Beginning 82 | match scope { 83 | "punctuation" => if ((chk < 0 && (_type == "prefix")) 84 | || (chk >= len as i32 && (_type == "suffix")) 85 | || self.is_punctuation(fixed.at(chk as usize))) 86 | == is_negative 87 | { 88 | replace = false; 89 | break; 90 | }, 91 | "vowel" => if (((chk >= 0 && (_type == "prefix")) 92 | || (chk < len as i32 && (_type == "suffix"))) 93 | && self.is_vowel(fixed.at(chk as usize))) 94 | == is_negative 95 | { 96 | replace = false; 97 | break; 98 | }, 99 | 100 | "consonant" => if (((chk >= 0 && (_type == "prefix")) 101 | || (chk < len as i32 && (_type == "suffix"))) 102 | && self.is_consonant(fixed.at(chk as usize))) 103 | == is_negative 104 | { 105 | replace = false; 106 | break; 107 | }, 108 | 109 | "number" => if (((chk >= 0 && (_type == "prefix")) 110 | || (chk < len as i32 && (_type == "suffix"))) 111 | && self.is_number(fixed.at(chk as usize))) 112 | == is_negative 113 | { 114 | replace = false; 115 | break; 116 | }, 117 | 118 | "exact" => { 119 | let mut s: i32 = 0; 120 | let mut e: i32 = 0; 121 | if _type == "suffix" { 122 | s = end; 123 | e = end + value.len() as i32; 124 | } else { 125 | // Prefix 126 | s = start - value.len() as i32; 127 | e = start; 128 | } 129 | if !self.is_exact(value, &fixed, s, e, is_negative) 130 | { 131 | replace = false; 132 | break; 133 | } 134 | } 135 | _ => panic!("Unknown scope"), 136 | }; 137 | } 138 | 139 | if replace { 140 | output += rule["replace"].as_str().unwrap(); 141 | cur = (end - 1) as usize; 142 | matched = true; 143 | break; 144 | } 145 | } 146 | } 147 | 148 | if matched { 149 | break; 150 | } 151 | 152 | // Default 153 | output += pattern["replace"].as_str().unwrap(); 154 | cur = (end - 1) as usize; 155 | matched = true; 156 | break; 157 | } else if find.len() > chunk.len() 158 | || (find.len() == chunk.len() && find.cmp(&chunk) == Ordering::Less) 159 | { 160 | left = mid + 1; 161 | } else { 162 | right = mid - 1; 163 | } 164 | } 165 | if matched { 166 | break; 167 | } 168 | } 169 | } 170 | 171 | if !matched { 172 | output += &fixed[cur..cur + 1]; 173 | } 174 | cur += 1; 175 | } 176 | 177 | output 178 | } 179 | 180 | fn fix_string(&self, string: &str) -> String { 181 | string 182 | .chars() 183 | .map(|character| { 184 | if self.is_case_sensitive(character) { 185 | character 186 | } else { 187 | character.to_ascii_lowercase() 188 | } 189 | }) 190 | .collect() 191 | } 192 | 193 | fn is_vowel(&self, string: &str) -> bool { 194 | self.vowel.contains(&string.to_ascii_lowercase()) 195 | } 196 | 197 | fn is_consonant(&self, string: &str) -> bool { 198 | self.consonant.contains(&string.to_ascii_lowercase()) 199 | } 200 | 201 | fn is_case_sensitive(&self, character: char) -> bool { 202 | self.case_sensitive 203 | .contains(character.to_ascii_lowercase()) 204 | } 205 | 206 | fn is_number(&self, character: &str) -> bool { 207 | self.numbers.contains(character) 208 | } 209 | 210 | fn is_exact(&self, needle: &str, heystack: &str, start: i32, end: i32, not: bool) -> bool { 211 | let len = end - start; 212 | (start >= 0 && end < heystack.len() as i32 213 | && (heystack.substring(start as usize, len as usize) == needle)) != not 214 | } 215 | 216 | fn is_punctuation(&self, character: &str) -> bool { 217 | !(self.is_vowel(character) || self.is_consonant(character)) 218 | } 219 | } 220 | 221 | #[cfg(test)] 222 | mod tests { 223 | use serde_json; 224 | use super::PhoneticParser; 225 | 226 | #[test] 227 | fn test_helpers() { 228 | let json = serde_json::from_str(include_str!("AvroPhonetic.json")).unwrap(); 229 | let parser = PhoneticParser::new(&json); 230 | 231 | assert!(parser.is_vowel("A")); 232 | assert_eq!(parser.is_vowel("b"), false); 233 | assert!(parser.is_consonant("B")); 234 | assert_eq!(parser.is_consonant("e"), false); 235 | assert_eq!(parser.fix_string("ODEr AMAr"), "ODer amar"); 236 | assert!(parser.is_number("1")); 237 | } 238 | 239 | #[test] 240 | fn test_basic() { 241 | let json = serde_json::from_str(include_str!("AvroPhonetic.json")).unwrap(); 242 | let parser = PhoneticParser::new(&json); 243 | 244 | assert_eq!(parser.convert("bhl"), "ভ্ল"); 245 | assert_eq!(parser.convert("bj"), "ব্জ"); 246 | assert_eq!(parser.convert("bd"), "ব্দ"); 247 | assert_eq!(parser.convert("bb"), "ব্ব"); 248 | assert_eq!(parser.convert("bl"), "ব্ল"); 249 | assert_eq!(parser.convert("bh"), "ভ"); 250 | assert_eq!(parser.convert("vl"), "ভ্ল"); 251 | assert_eq!(parser.convert("b"), "ব"); 252 | assert_eq!(parser.convert("v"), "ভ"); 253 | assert_eq!(parser.convert("cNG"), "চ্ঞ"); 254 | assert_eq!(parser.convert("cch"), "চ্ছ"); 255 | assert_eq!(parser.convert("cc"), "চ্চ"); 256 | assert_eq!(parser.convert("ch"), "ছ"); 257 | assert_eq!(parser.convert("c"), "চ"); 258 | assert_eq!(parser.convert("dhn"), "ধ্ন"); 259 | assert_eq!(parser.convert("dhm"), "ধ্ম"); 260 | assert_eq!(parser.convert("dgh"), "দ্ঘ"); 261 | assert_eq!(parser.convert("ddh"), "দ্ধ"); 262 | assert_eq!(parser.convert("dbh"), "দ্ভ"); 263 | assert_eq!(parser.convert("dv"), "দ্ভ"); 264 | assert_eq!(parser.convert("dm"), "দ্ম"); 265 | assert_eq!(parser.convert("DD"), "ড্ড"); 266 | assert_eq!(parser.convert("Dh"), "ঢ"); 267 | assert_eq!(parser.convert("dh"), "ধ"); 268 | assert_eq!(parser.convert("dg"), "দ্গ"); 269 | assert_eq!(parser.convert("dd"), "দ্দ"); 270 | assert_eq!(parser.convert("D"), "ড"); 271 | assert_eq!(parser.convert("d"), "দ"); 272 | assert_eq!(parser.convert("..."), "..."); 273 | assert_eq!(parser.convert(".`"), "."); 274 | assert_eq!(parser.convert(".."), "।।"); 275 | assert_eq!(parser.convert("."), "।"); 276 | assert_eq!(parser.convert("ghn"), "ঘ্ন"); 277 | assert_eq!(parser.convert("Ghn"), "ঘ্ন"); 278 | assert_eq!(parser.convert("gdh"), "গ্ধ"); 279 | assert_eq!(parser.convert("gN"), "গ্ণ"); 280 | assert_eq!(parser.convert("GN"), "গ্ণ"); 281 | assert_eq!(parser.convert("gn"), "গ্ন"); 282 | assert_eq!(parser.convert("gm"), "গ্ম"); 283 | assert_eq!(parser.convert("Gm"), "গ্ম"); 284 | assert_eq!(parser.convert("gl"), "গ্ল"); 285 | assert_eq!(parser.convert("Gl"), "গ্ল"); 286 | assert_eq!(parser.convert("gg"), "জ্ঞ"); 287 | assert_eq!(parser.convert("GG"), "জ্ঞ"); 288 | assert_eq!(parser.convert("Gg"), "জ্ঞ"); 289 | assert_eq!(parser.convert("gG"), "জ্ঞ"); 290 | assert_eq!(parser.convert("gh"), "ঘ"); 291 | assert_eq!(parser.convert("Gh"), "ঘ"); 292 | assert_eq!(parser.convert("g"), "গ"); 293 | assert_eq!(parser.convert("hN"), "হ্ণ"); 294 | assert_eq!(parser.convert("hn"), "হ্ন"); 295 | assert_eq!(parser.convert("hm"), "হ্ম"); 296 | assert_eq!(parser.convert("hl"), "হ্ল"); 297 | assert_eq!(parser.convert("h"), "হ"); 298 | assert_eq!(parser.convert("jjh"), "জ্ঝ"); 299 | assert_eq!(parser.convert("jNG"), "জ্ঞ"); 300 | assert_eq!(parser.convert("jh"), "ঝ"); 301 | assert_eq!(parser.convert("jj"), "জ্জ"); 302 | assert_eq!(parser.convert("j"), "জ"); 303 | assert_eq!(parser.convert("J"), "জ"); 304 | assert_eq!(parser.convert("kkhN"), "ক্ষ্ণ"); 305 | assert_eq!(parser.convert("kShN"), "ক্ষ্ণ"); 306 | assert_eq!(parser.convert("kkhm"), "ক্ষ্ম"); 307 | assert_eq!(parser.convert("kShm"), "ক্ষ্ম"); 308 | assert_eq!(parser.convert("kxN"), "ক্ষ্ণ"); 309 | assert_eq!(parser.convert("kxm"), "ক্ষ্ম"); 310 | assert_eq!(parser.convert("kkh"), "ক্ষ"); 311 | assert_eq!(parser.convert("kSh"), "ক্ষ"); 312 | assert_eq!(parser.convert("ksh"), "কশ"); 313 | assert_eq!(parser.convert("kx"), "ক্ষ"); 314 | assert_eq!(parser.convert("kk"), "ক্ক"); 315 | assert_eq!(parser.convert("kT"), "ক্ট"); 316 | assert_eq!(parser.convert("kt"), "ক্ত"); 317 | assert_eq!(parser.convert("kl"), "ক্ল"); 318 | assert_eq!(parser.convert("ks"), "ক্স"); 319 | assert_eq!(parser.convert("kh"), "খ"); 320 | assert_eq!(parser.convert("k"), "ক"); 321 | assert_eq!(parser.convert("lbh"), "ল্ভ"); 322 | assert_eq!(parser.convert("ldh"), "ল্ধ"); 323 | assert_eq!(parser.convert("lkh"), "লখ"); 324 | assert_eq!(parser.convert("lgh"), "লঘ"); 325 | assert_eq!(parser.convert("lph"), "লফ"); 326 | assert_eq!(parser.convert("lk"), "ল্ক"); 327 | assert_eq!(parser.convert("lg"), "ল্গ"); 328 | assert_eq!(parser.convert("lT"), "ল্ট"); 329 | assert_eq!(parser.convert("lD"), "ল্ড"); 330 | assert_eq!(parser.convert("lp"), "ল্প"); 331 | assert_eq!(parser.convert("lv"), "ল্ভ"); 332 | assert_eq!(parser.convert("lm"), "ল্ম"); 333 | assert_eq!(parser.convert("ll"), "ল্ল"); 334 | assert_eq!(parser.convert("lb"), "ল্ব"); 335 | assert_eq!(parser.convert("l"), "ল"); 336 | assert_eq!(parser.convert("mth"), "ম্থ"); 337 | assert_eq!(parser.convert("mph"), "ম্ফ"); 338 | assert_eq!(parser.convert("mbh"), "ম্ভ"); 339 | assert_eq!(parser.convert("mpl"), "মপ্ল"); 340 | assert_eq!(parser.convert("mn"), "ম্ন"); 341 | assert_eq!(parser.convert("mp"), "ম্প"); 342 | assert_eq!(parser.convert("mv"), "ম্ভ"); 343 | assert_eq!(parser.convert("mm"), "ম্ম"); 344 | assert_eq!(parser.convert("ml"), "ম্ল"); 345 | assert_eq!(parser.convert("mb"), "ম্ব"); 346 | assert_eq!(parser.convert("mf"), "ম্ফ"); 347 | assert_eq!(parser.convert("m"), "ম"); 348 | assert_eq!(parser.convert("0"), "০"); 349 | assert_eq!(parser.convert("1"), "১"); 350 | assert_eq!(parser.convert("2"), "২"); 351 | assert_eq!(parser.convert("3"), "৩"); 352 | assert_eq!(parser.convert("4"), "৪"); 353 | assert_eq!(parser.convert("5"), "৫"); 354 | assert_eq!(parser.convert("6"), "৬"); 355 | assert_eq!(parser.convert("7"), "৭"); 356 | assert_eq!(parser.convert("8"), "৮"); 357 | assert_eq!(parser.convert("9"), "৯"); 358 | assert_eq!(parser.convert("NgkSh"), "ঙ্ক্ষ"); 359 | assert_eq!(parser.convert("Ngkkh"), "ঙ্ক্ষ"); 360 | assert_eq!(parser.convert("NGch"), "ঞ্ছ"); 361 | assert_eq!(parser.convert("Nggh"), "ঙ্ঘ"); 362 | assert_eq!(parser.convert("Ngkh"), "ঙ্খ"); 363 | assert_eq!(parser.convert("NGjh"), "ঞ্ঝ"); 364 | assert_eq!(parser.convert("ngOU"), "ঙ্গৌ"); 365 | assert_eq!(parser.convert("ngOI"), "ঙ্গৈ"); 366 | assert_eq!(parser.convert("Ngkx"), "ঙ্ক্ষ"); 367 | assert_eq!(parser.convert("NGc"), "ঞ্চ"); 368 | assert_eq!(parser.convert("nch"), "ঞ্ছ"); 369 | assert_eq!(parser.convert("njh"), "ঞ্ঝ"); 370 | assert_eq!(parser.convert("ngh"), "ঙ্ঘ"); 371 | assert_eq!(parser.convert("Ngk"), "ঙ্ক"); 372 | assert_eq!(parser.convert("Ngx"), "ঙ্ষ"); 373 | assert_eq!(parser.convert("Ngg"), "ঙ্গ"); 374 | assert_eq!(parser.convert("Ngm"), "ঙ্ম"); 375 | assert_eq!(parser.convert("NGj"), "ঞ্জ"); 376 | assert_eq!(parser.convert("ndh"), "ন্ধ"); 377 | assert_eq!(parser.convert("nTh"), "ন্ঠ"); 378 | assert_eq!(parser.convert("NTh"), "ণ্ঠ"); 379 | assert_eq!(parser.convert("nth"), "ন্থ"); 380 | assert_eq!(parser.convert("nkh"), "ঙ্খ"); 381 | assert_eq!(parser.convert("ngo"), "ঙ্গ"); 382 | assert_eq!(parser.convert("nga"), "ঙ্গা"); 383 | assert_eq!(parser.convert("ngi"), "ঙ্গি"); 384 | assert_eq!(parser.convert("ngI"), "ঙ্গী"); 385 | assert_eq!(parser.convert("ngu"), "ঙ্গু"); 386 | assert_eq!(parser.convert("ngU"), "ঙ্গূ"); 387 | assert_eq!(parser.convert("nge"), "ঙ্গে"); 388 | assert_eq!(parser.convert("ngO"), "ঙ্গো"); 389 | assert_eq!(parser.convert("NDh"), "ণ্ঢ"); 390 | assert_eq!(parser.convert("nsh"), "নশ"); 391 | assert_eq!(parser.convert("Ngr"), "ঙর"); 392 | assert_eq!(parser.convert("NGr"), "ঞর"); 393 | assert_eq!(parser.convert("ngr"), "ংর"); 394 | assert_eq!(parser.convert("nj"), "ঞ্জ"); 395 | assert_eq!(parser.convert("Ng"), "ঙ"); 396 | assert_eq!(parser.convert("NG"), "ঞ"); 397 | assert_eq!(parser.convert("nk"), "ঙ্ক"); 398 | assert_eq!(parser.convert("ng"), "ং"); 399 | assert_eq!(parser.convert("nn"), "ন্ন"); 400 | assert_eq!(parser.convert("NN"), "ণ্ণ"); 401 | assert_eq!(parser.convert("Nn"), "ণ্ন"); 402 | assert_eq!(parser.convert("nm"), "ন্ম"); 403 | assert_eq!(parser.convert("Nm"), "ণ্ম"); 404 | assert_eq!(parser.convert("nd"), "ন্দ"); 405 | assert_eq!(parser.convert("nT"), "ন্ট"); 406 | assert_eq!(parser.convert("NT"), "ণ্ট"); 407 | assert_eq!(parser.convert("nD"), "ন্ড"); 408 | assert_eq!(parser.convert("ND"), "ণ্ড"); 409 | assert_eq!(parser.convert("nt"), "ন্ত"); 410 | assert_eq!(parser.convert("ns"), "ন্স"); 411 | assert_eq!(parser.convert("nc"), "ঞ্চ"); 412 | assert_eq!(parser.convert("n"), "ন"); 413 | assert_eq!(parser.convert("N"), "ণ"); 414 | assert_eq!(parser.convert("OI`"), "ৈ"); 415 | assert_eq!(parser.convert("OU`"), "ৌ"); 416 | assert_eq!(parser.convert("O`"), "ো"); 417 | assert_eq!(parser.convert("OI"), "ঐ"); 418 | assert_eq!(parser.convert("kOI"), "কৈ"); 419 | assert_eq!(parser.convert(" OI"), " ঐ"); 420 | assert_eq!(parser.convert("(OI"), "(ঐ"); 421 | assert_eq!(parser.convert(".OI"), "।ঐ"); 422 | assert_eq!(parser.convert("OU"), "ঔ"); 423 | assert_eq!(parser.convert("kOU"), "কৌ"); 424 | assert_eq!(parser.convert(" OU"), " ঔ"); 425 | assert_eq!(parser.convert("-OU"), "-ঔ"); 426 | assert_eq!(parser.convert(",,OU"), "্‌ঔ"); 427 | assert_eq!(parser.convert("O"), "ও"); 428 | assert_eq!(parser.convert("pO"), "পো"); 429 | assert_eq!(parser.convert(" O"), " ও"); 430 | assert_eq!(parser.convert("iO"), "ইও"); 431 | assert_eq!(parser.convert("`O"), "ও"); 432 | assert_eq!(parser.convert("phl"), "ফ্ল"); 433 | assert_eq!(parser.convert("pT"), "প্ট"); 434 | assert_eq!(parser.convert("pt"), "প্ত"); 435 | assert_eq!(parser.convert("pn"), "প্ন"); 436 | assert_eq!(parser.convert("pp"), "প্প"); 437 | assert_eq!(parser.convert("pl"), "প্ল"); 438 | assert_eq!(parser.convert("ps"), "প্স"); 439 | assert_eq!(parser.convert("ph"), "ফ"); 440 | assert_eq!(parser.convert("fl"), "ফ্ল"); 441 | assert_eq!(parser.convert("f"), "ফ"); 442 | assert_eq!(parser.convert("p"), "প"); 443 | assert_eq!(parser.convert("rri`"), "ৃ"); 444 | assert_eq!(parser.convert("rri"), "ঋ"); 445 | assert_eq!(parser.convert("krri"), "কৃ"); 446 | assert_eq!(parser.convert("Irri"), "ঈঋ"); 447 | assert_eq!(parser.convert("^rri"), "ঁঋ"); 448 | assert_eq!(parser.convert(":rri"), "ঃঋ"); 449 | assert_eq!(parser.convert("rZ"), "র‍্য"); 450 | assert_eq!(parser.convert("krZ"), "ক্র্য"); 451 | assert_eq!(parser.convert("rrZ"), "রর‍্য"); 452 | assert_eq!(parser.convert("yrZ"), "ইয়র‍্য"); 453 | assert_eq!(parser.convert("wrZ"), "ওর‍্য"); 454 | assert_eq!(parser.convert("xrZ"), "এক্সর‍্য"); 455 | assert_eq!(parser.convert("irZ"), "ইর‍্য"); 456 | assert_eq!(parser.convert("-rZ"), "-র‍্য"); 457 | assert_eq!(parser.convert("rrrZ"), "ররর‍্য"); 458 | assert_eq!(parser.convert("ry"), "র‍্য"); 459 | assert_eq!(parser.convert("qry"), "ক্র্য"); 460 | assert_eq!(parser.convert("rry"), "রর‍্য"); 461 | assert_eq!(parser.convert("yry"), "ইয়র‍্য"); 462 | assert_eq!(parser.convert("wry"), "ওর‍্য"); 463 | assert_eq!(parser.convert("xry"), "এক্সর‍্য"); 464 | assert_eq!(parser.convert("0ry"), "০র‍্য"); 465 | assert_eq!(parser.convert("rrrry"), "রররর‍্য"); 466 | assert_eq!(parser.convert("Rry"), "ড়্র্য"); 467 | assert_eq!(parser.convert("rr"), "রর"); 468 | assert_eq!(parser.convert("arr"), "আরর"); 469 | assert_eq!(parser.convert("arrk"), "আর্ক"); 470 | assert_eq!(parser.convert("arra"), "আররা"); 471 | assert_eq!(parser.convert("arr"), "আরর"); 472 | assert_eq!(parser.convert("arr!"), "আরর!"); 473 | assert_eq!(parser.convert("krr"), "ক্রর"); 474 | assert_eq!(parser.convert("krra"), "ক্ররা"); 475 | assert_eq!(parser.convert("Rg"), "ড়্গ"); 476 | assert_eq!(parser.convert("Rh"), "ঢ়"); 477 | assert_eq!(parser.convert("R"), "ড়"); 478 | assert_eq!(parser.convert("r"), "র"); 479 | assert_eq!(parser.convert("or"), "অর"); 480 | assert_eq!(parser.convert("mr"), "ম্র"); 481 | assert_eq!(parser.convert("1r"), "১র"); 482 | assert_eq!(parser.convert("+r"), "+র"); 483 | assert_eq!(parser.convert("rr"), "রর"); 484 | assert_eq!(parser.convert("yr"), "ইয়র"); 485 | assert_eq!(parser.convert("wr"), "ওর"); 486 | assert_eq!(parser.convert("xr"), "এক্সর"); 487 | assert_eq!(parser.convert("zr"), "য্র"); 488 | assert_eq!(parser.convert("mri"), "ম্রি"); 489 | assert_eq!(parser.convert("shch"), "শ্ছ"); 490 | assert_eq!(parser.convert("ShTh"), "ষ্ঠ"); 491 | assert_eq!(parser.convert("Shph"), "ষ্ফ"); 492 | assert_eq!(parser.convert("Sch"), "শ্ছ"); 493 | assert_eq!(parser.convert("skl"), "স্ক্ল"); 494 | assert_eq!(parser.convert("skh"), "স্খ"); 495 | assert_eq!(parser.convert("sth"), "স্থ"); 496 | assert_eq!(parser.convert("sph"), "স্ফ"); 497 | assert_eq!(parser.convert("shc"), "শ্চ"); 498 | assert_eq!(parser.convert("sht"), "শ্ত"); 499 | assert_eq!(parser.convert("shn"), "শ্ন"); 500 | assert_eq!(parser.convert("shm"), "শ্ম"); 501 | assert_eq!(parser.convert("shl"), "শ্ল"); 502 | assert_eq!(parser.convert("Shk"), "ষ্ক"); 503 | assert_eq!(parser.convert("ShT"), "ষ্ট"); 504 | assert_eq!(parser.convert("ShN"), "ষ্ণ"); 505 | assert_eq!(parser.convert("Shp"), "ষ্প"); 506 | assert_eq!(parser.convert("Shf"), "ষ্ফ"); 507 | assert_eq!(parser.convert("Shm"), "ষ্ম"); 508 | assert_eq!(parser.convert("spl"), "স্প্ল"); 509 | assert_eq!(parser.convert("sk"), "স্ক"); 510 | assert_eq!(parser.convert("Sc"), "শ্চ"); 511 | assert_eq!(parser.convert("sT"), "স্ট"); 512 | assert_eq!(parser.convert("st"), "স্ত"); 513 | assert_eq!(parser.convert("sn"), "স্ন"); 514 | assert_eq!(parser.convert("sp"), "স্প"); 515 | assert_eq!(parser.convert("sf"), "স্ফ"); 516 | assert_eq!(parser.convert("sm"), "স্ম"); 517 | assert_eq!(parser.convert("sl"), "স্ল"); 518 | assert_eq!(parser.convert("sh"), "শ"); 519 | assert_eq!(parser.convert("Sc"), "শ্চ"); 520 | assert_eq!(parser.convert("St"), "শ্ত"); 521 | assert_eq!(parser.convert("Sn"), "শ্ন"); 522 | assert_eq!(parser.convert("Sm"), "শ্ম"); 523 | assert_eq!(parser.convert("Sl"), "শ্ল"); 524 | assert_eq!(parser.convert("Sh"), "ষ"); 525 | assert_eq!(parser.convert("s"), "স"); 526 | assert_eq!(parser.convert("S"), "শ"); 527 | assert_eq!(parser.convert("oo"), "উ"); 528 | assert_eq!(parser.convert("OO"), "ওও"); 529 | assert_eq!(parser.convert("oo`"), "ু"); 530 | assert_eq!(parser.convert("koo"), "কু"); 531 | assert_eq!(parser.convert("ooo"), "উঅ"); 532 | assert_eq!(parser.convert("!oo"), "!উ"); 533 | assert_eq!(parser.convert("!ooo"), "!উঅ"); 534 | assert_eq!(parser.convert("aoo"), "আউ"); 535 | assert_eq!(parser.convert("oop"), "উপ"); 536 | assert_eq!(parser.convert("ooo`"), "উ"); 537 | assert_eq!(parser.convert("o`"), ""); 538 | assert_eq!(parser.convert("oZ"), "অ্য"); 539 | assert_eq!(parser.convert("oY"), "অয়"); 540 | assert_eq!(parser.convert("o"), "অ"); 541 | assert_eq!(parser.convert("!o"), "!অ"); 542 | assert_eq!(parser.convert("^o"), "ঁঅ"); 543 | assert_eq!(parser.convert("*o"), "*অ"); 544 | assert_eq!(parser.convert("io"), "ইও"); 545 | assert_eq!(parser.convert("yo"), "ইয়"); 546 | assert_eq!(parser.convert("no"), "ন"); 547 | assert_eq!(parser.convert("tth"), "ত্থ"); 548 | assert_eq!(parser.convert("t``"), "ৎ"); 549 | assert_eq!(parser.convert("`t``"), "ৎ"); 550 | assert_eq!(parser.convert("t``t``"), "ৎৎ"); 551 | assert_eq!(parser.convert("t```"), "ৎ"); 552 | assert_eq!(parser.convert("TT"), "ট্ট"); 553 | assert_eq!(parser.convert("Tm"), "ট্ম"); 554 | assert_eq!(parser.convert("Th"), "ঠ"); 555 | assert_eq!(parser.convert("tn"), "ত্ন"); 556 | assert_eq!(parser.convert("tm"), "ত্ম"); 557 | assert_eq!(parser.convert("th"), "থ"); 558 | assert_eq!(parser.convert("tt"), "ত্ত"); 559 | assert_eq!(parser.convert("T"), "ট"); 560 | assert_eq!(parser.convert("t"), "ত"); 561 | assert_eq!(parser.convert("aZ"), "অ্যা"); 562 | assert_eq!(parser.convert("aaZ"), "আঅ্যা"); 563 | assert_eq!(parser.convert("AZ"), "অ্যা"); 564 | assert_eq!(parser.convert("a`"), "া"); 565 | assert_eq!(parser.convert("a``"), "া"); 566 | assert_eq!(parser.convert("ka`"), "কা"); 567 | assert_eq!(parser.convert("A`"), "া"); 568 | assert_eq!(parser.convert("a"), "আ"); 569 | assert_eq!(parser.convert("`a"), "আ"); 570 | assert_eq!(parser.convert("k`a"), "কআ"); 571 | assert_eq!(parser.convert("ia"), "ইয়া"); 572 | assert_eq!(parser.convert("aaaa`"), "আআআা"); 573 | assert_eq!(parser.convert("i`"), "ি"); 574 | assert_eq!(parser.convert("i"), "ই"); 575 | assert_eq!(parser.convert("`i"), "ই"); 576 | assert_eq!(parser.convert("hi"), "হি"); 577 | assert_eq!(parser.convert("ih"), "ইহ"); 578 | assert_eq!(parser.convert("i`h"), "িহ"); 579 | assert_eq!(parser.convert("I`"), "ী"); 580 | assert_eq!(parser.convert("I"), "ঈ"); 581 | assert_eq!(parser.convert("cI"), "চী"); 582 | assert_eq!(parser.convert("Ix"), "ঈক্স"); 583 | assert_eq!(parser.convert("II"), "ঈঈ"); 584 | assert_eq!(parser.convert("0I"), "০ঈ"); 585 | assert_eq!(parser.convert("oI"), "অঈ"); 586 | assert_eq!(parser.convert("u`"), "ু"); 587 | assert_eq!(parser.convert("u"), "উ"); 588 | assert_eq!(parser.convert("ku"), "কু"); 589 | assert_eq!(parser.convert("uk"), "উক"); 590 | assert_eq!(parser.convert("uu"), "উউ"); 591 | assert_eq!(parser.convert("iu"), "ইউ"); 592 | assert_eq!(parser.convert("&u"), "&উ"); 593 | assert_eq!(parser.convert("u&"), "উ&"); 594 | assert_eq!(parser.convert("U`"), "ূ"); 595 | assert_eq!(parser.convert("U"), "ঊ"); 596 | assert_eq!(parser.convert("yU"), "ইয়ূ"); 597 | assert_eq!(parser.convert("Uy"), "ঊয়"); 598 | assert_eq!(parser.convert("^U"), "ঁঊ"); 599 | assert_eq!(parser.convert("U^"), "ঊঁ"); 600 | assert_eq!(parser.convert("EE"), "ঈ"); 601 | assert_eq!(parser.convert("ee"), "ঈ"); 602 | assert_eq!(parser.convert("Ee"), "ঈ"); 603 | assert_eq!(parser.convert("eE"), "ঈ"); 604 | assert_eq!(parser.convert("ee`"), "ী"); 605 | assert_eq!(parser.convert("kee"), "কী"); 606 | assert_eq!(parser.convert("eek"), "ঈক"); 607 | assert_eq!(parser.convert("0ee"), "০ঈ"); 608 | assert_eq!(parser.convert("ee8"), "ঈ৮"); 609 | assert_eq!(parser.convert("(ee)"), "(ঈ)"); 610 | assert_eq!(parser.convert("e`"), "ে"); 611 | assert_eq!(parser.convert("e"), "এ"); 612 | assert_eq!(parser.convert("ke"), "কে"); 613 | assert_eq!(parser.convert("we"), "ওয়ে"); 614 | assert_eq!(parser.convert("#e#"), "#এ#"); 615 | assert_eq!(parser.convert("`e`"), "ে"); 616 | assert_eq!(parser.convert("z"), "য"); 617 | assert_eq!(parser.convert("Z"), "্য"); 618 | assert_eq!(parser.convert("rZ"), "র‍্য"); 619 | assert_eq!(parser.convert("kZS"), "ক্যশ"); 620 | assert_eq!(parser.convert("y"), "ইয়"); 621 | assert_eq!(parser.convert("oy"), "অয়"); 622 | assert_eq!(parser.convert("ky"), "ক্য"); 623 | assert_eq!(parser.convert("ya"), "ইয়া"); 624 | assert_eq!(parser.convert("yaa"), "ইয়াআ"); 625 | assert_eq!(parser.convert("Y"), "য়"); 626 | assert_eq!(parser.convert("YY"), "য়য়"); 627 | assert_eq!(parser.convert("iY"), "ইয়"); 628 | assert_eq!(parser.convert("kY"), "কয়"); 629 | assert_eq!(parser.convert("q"), "ক"); 630 | assert_eq!(parser.convert("Q"), "ক"); 631 | assert_eq!(parser.convert("w"), "ও"); 632 | assert_eq!(parser.convert("wa"), "ওয়া"); 633 | assert_eq!(parser.convert("-wa-"), "-ওয়া-"); 634 | assert_eq!(parser.convert("woo"), "ওয়ু"); 635 | assert_eq!(parser.convert("wre"), "ওরে"); 636 | assert_eq!(parser.convert("kw"), "ক্ব"); 637 | assert_eq!(parser.convert("x"), "এক্স"); 638 | assert_eq!(parser.convert("ex"), "এক্স"); 639 | assert_eq!(parser.convert("bx"), "বক্স"); 640 | assert_eq!(parser.convert(":`"), ":"); 641 | assert_eq!(parser.convert(":"), "ঃ"); 642 | assert_eq!(parser.convert("^`"), "^"); 643 | assert_eq!(parser.convert("^"), "ঁ"); 644 | assert_eq!(parser.convert("k^"), "কঁ"); 645 | assert_eq!(parser.convert("k^i"), "কঁই"); 646 | assert_eq!(parser.convert("ki^"), "কিঁ"); 647 | assert_eq!(parser.convert(",,"), "্‌"); 648 | assert_eq!(parser.convert(",,,"), "্‌,"); 649 | assert_eq!(parser.convert(",,`,"), "্‌,"); 650 | assert_eq!(parser.convert("`,,"), "্‌"); 651 | assert_eq!(parser.convert(",`,"), ",,"); 652 | assert_eq!(parser.convert("$"), "৳"); 653 | assert_eq!(parser.convert("`"), ""); 654 | assert_eq!(parser.convert("bdh"), "ব্ধ"); 655 | } 656 | 657 | #[test] 658 | fn test_sentence() { 659 | let json = serde_json::from_str(include_str!("AvroPhonetic.json")).unwrap(); 660 | let parser = PhoneticParser::new(&json); 661 | 662 | assert_eq!(parser.convert("ami banglay gan gai"), "আমি বাংলায় গান গাই"); 663 | assert_eq!(parser.convert("amader valObasa hoye gel ghas, kheye gel goru ar diye gelo ba^sh"), "আমাদের ভালোবাসা হয়ে গেল ঘাস, খেয়ে গেল গরু আর দিয়ে গেল বাঁশ"); 664 | } 665 | } -------------------------------------------------------------------------------- /src/AvroPhonetic.json: -------------------------------------------------------------------------------- 1 | { 2 | "casesensitive":"oiudgjnrstyz", 3 | "consonant":"bcdfghjklmnpqrstvwxyz", 4 | "number":"1234567890", 5 | "patterns":[ 6 | { 7 | "find":"NgkSh", 8 | "replace":"ঙ্ক্ষ", 9 | "rules":[ 10 | 11 | ] 12 | }, 13 | { 14 | "find":"Ngkkh", 15 | "replace":"ঙ্ক্ষ", 16 | "rules":[ 17 | 18 | ] 19 | }, 20 | { 21 | "find":"NGch", 22 | "replace":"ঞ্ছ", 23 | "rules":[ 24 | 25 | ] 26 | }, 27 | { 28 | "find":"NGjh", 29 | "replace":"ঞ্ঝ", 30 | "rules":[ 31 | 32 | ] 33 | }, 34 | { 35 | "find":"Nggh", 36 | "replace":"ঙ্ঘ", 37 | "rules":[ 38 | 39 | ] 40 | }, 41 | { 42 | "find":"Ngkh", 43 | "replace":"ঙ্খ", 44 | "rules":[ 45 | 46 | ] 47 | }, 48 | { 49 | "find":"Ngkx", 50 | "replace":"ঙ্ক্ষ", 51 | "rules":[ 52 | 53 | ] 54 | }, 55 | { 56 | "find":"ShTh", 57 | "replace":"ষ্ঠ", 58 | "rules":[ 59 | 60 | ] 61 | }, 62 | { 63 | "find":"Shph", 64 | "replace":"ষ্ফ", 65 | "rules":[ 66 | 67 | ] 68 | }, 69 | { 70 | "find":"kShN", 71 | "replace":"ক্ষ্ণ", 72 | "rules":[ 73 | 74 | ] 75 | }, 76 | { 77 | "find":"kShm", 78 | "replace":"ক্ষ্ম", 79 | "rules":[ 80 | 81 | ] 82 | }, 83 | { 84 | "find":"kkhN", 85 | "replace":"ক্ষ্ণ", 86 | "rules":[ 87 | 88 | ] 89 | }, 90 | { 91 | "find":"kkhm", 92 | "replace":"ক্ষ্ম", 93 | "rules":[ 94 | 95 | ] 96 | }, 97 | { 98 | "find":"ngOI", 99 | "replace":"ঙ্গৈ", 100 | "rules":[ 101 | 102 | ] 103 | }, 104 | { 105 | "find":"ngOU", 106 | "replace":"ঙ্গৌ", 107 | "rules":[ 108 | 109 | ] 110 | }, 111 | { 112 | "find":"rri`", 113 | "replace":"ৃ", 114 | "rules":[ 115 | 116 | ] 117 | }, 118 | { 119 | "find":"shch", 120 | "replace":"শ্ছ", 121 | "rules":[ 122 | 123 | ] 124 | }, 125 | { 126 | "find":"...", 127 | "replace":"...", 128 | "rules":[ 129 | 130 | ] 131 | }, 132 | { 133 | "find":"Gdh", 134 | "replace":"গ্ধ", 135 | "rules":[ 136 | 137 | ] 138 | }, 139 | { 140 | "find":"Ghn", 141 | "replace":"ঘ্ন", 142 | "rules":[ 143 | 144 | ] 145 | }, 146 | { 147 | "find":"NDh", 148 | "replace":"ণ্ঢ", 149 | "rules":[ 150 | 151 | ] 152 | }, 153 | { 154 | "find":"NGc", 155 | "replace":"ঞ্চ", 156 | "rules":[ 157 | 158 | ] 159 | }, 160 | { 161 | "find":"NGj", 162 | "replace":"ঞ্জ", 163 | "rules":[ 164 | 165 | ] 166 | }, 167 | { 168 | "find":"NGr", 169 | "replace":"ঞর", 170 | "rules":[ 171 | 172 | ] 173 | }, 174 | { 175 | "find":"NTh", 176 | "replace":"ণ্ঠ", 177 | "rules":[ 178 | 179 | ] 180 | }, 181 | { 182 | "find":"Ngg", 183 | "replace":"ঙ্গ", 184 | "rules":[ 185 | 186 | ] 187 | }, 188 | { 189 | "find":"Ngk", 190 | "replace":"ঙ্ক", 191 | "rules":[ 192 | 193 | ] 194 | }, 195 | { 196 | "find":"Ngm", 197 | "replace":"ঙ্ম", 198 | "rules":[ 199 | 200 | ] 201 | }, 202 | { 203 | "find":"Ngr", 204 | "replace":"ঙর", 205 | "rules":[ 206 | 207 | ] 208 | }, 209 | { 210 | "find":"Ngx", 211 | "replace":"ঙ্ষ", 212 | "rules":[ 213 | 214 | ] 215 | }, 216 | { 217 | "find":"OI`", 218 | "replace":"ৈ", 219 | "rules":[ 220 | 221 | ] 222 | }, 223 | { 224 | "find":"OU`", 225 | "replace":"ৌ", 226 | "rules":[ 227 | 228 | ] 229 | }, 230 | { 231 | "find":"Sch", 232 | "replace":"শ্ছ", 233 | "rules":[ 234 | 235 | ] 236 | }, 237 | { 238 | "find":"ShN", 239 | "replace":"ষ্ণ", 240 | "rules":[ 241 | 242 | ] 243 | }, 244 | { 245 | "find":"ShT", 246 | "replace":"ষ্ট", 247 | "rules":[ 248 | 249 | ] 250 | }, 251 | { 252 | "find":"Shf", 253 | "replace":"ষ্ফ", 254 | "rules":[ 255 | 256 | ] 257 | }, 258 | { 259 | "find":"Shk", 260 | "replace":"ষ্ক", 261 | "rules":[ 262 | 263 | ] 264 | }, 265 | { 266 | "find":"Shm", 267 | "replace":"ষ্ম", 268 | "rules":[ 269 | 270 | ] 271 | }, 272 | { 273 | "find":"Shp", 274 | "replace":"ষ্প", 275 | "rules":[ 276 | 277 | ] 278 | }, 279 | { 280 | "find":"bdh", 281 | "replace":"ব্ধ", 282 | "rules":[ 283 | 284 | ] 285 | }, 286 | { 287 | "find":"bhl", 288 | "replace":"ভ্ল", 289 | "rules":[ 290 | 291 | ] 292 | }, 293 | { 294 | "find":"cNG", 295 | "replace":"চ্ঞ", 296 | "rules":[ 297 | 298 | ] 299 | }, 300 | { 301 | "find":"cch", 302 | "replace":"চ্ছ", 303 | "rules":[ 304 | 305 | ] 306 | }, 307 | { 308 | "find":"dbh", 309 | "replace":"দ্ভ", 310 | "rules":[ 311 | 312 | ] 313 | }, 314 | { 315 | "find":"ddh", 316 | "replace":"দ্ধ", 317 | "rules":[ 318 | 319 | ] 320 | }, 321 | { 322 | "find":"dgh", 323 | "replace":"দ্ঘ", 324 | "rules":[ 325 | 326 | ] 327 | }, 328 | { 329 | "find":"dhm", 330 | "replace":"ধ্ম", 331 | "rules":[ 332 | 333 | ] 334 | }, 335 | { 336 | "find":"dhn", 337 | "replace":"ধ্ন", 338 | "rules":[ 339 | 340 | ] 341 | }, 342 | { 343 | "find":"ee`", 344 | "replace":"ী", 345 | "rules":[ 346 | 347 | ] 348 | }, 349 | { 350 | "find":"gdh", 351 | "replace":"গ্ধ", 352 | "rules":[ 353 | 354 | ] 355 | }, 356 | { 357 | "find":"ghn", 358 | "replace":"ঘ্ন", 359 | "rules":[ 360 | 361 | ] 362 | }, 363 | { 364 | "find":"jNG", 365 | "replace":"জ্ঞ", 366 | "rules":[ 367 | 368 | ] 369 | }, 370 | { 371 | "find":"jjh", 372 | "replace":"জ্ঝ", 373 | "rules":[ 374 | 375 | ] 376 | }, 377 | { 378 | "find":"kSh", 379 | "replace":"ক্ষ", 380 | "rules":[ 381 | 382 | ] 383 | }, 384 | { 385 | "find":"kkh", 386 | "replace":"ক্ষ", 387 | "rules":[ 388 | 389 | ] 390 | }, 391 | { 392 | "find":"ksh", 393 | "replace":"কশ", 394 | "rules":[ 395 | 396 | ] 397 | }, 398 | { 399 | "find":"kxN", 400 | "replace":"ক্ষ্ণ", 401 | "rules":[ 402 | 403 | ] 404 | }, 405 | { 406 | "find":"kxm", 407 | "replace":"ক্ষ্ম", 408 | "rules":[ 409 | 410 | ] 411 | }, 412 | { 413 | "find":"lbh", 414 | "replace":"ল্ভ", 415 | "rules":[ 416 | 417 | ] 418 | }, 419 | { 420 | "find":"ldh", 421 | "replace":"ল্ধ", 422 | "rules":[ 423 | 424 | ] 425 | }, 426 | { 427 | "find":"lgh", 428 | "replace":"লঘ", 429 | "rules":[ 430 | 431 | ] 432 | }, 433 | { 434 | "find":"lkh", 435 | "replace":"লখ", 436 | "rules":[ 437 | 438 | ] 439 | }, 440 | { 441 | "find":"lph", 442 | "replace":"লফ", 443 | "rules":[ 444 | 445 | ] 446 | }, 447 | { 448 | "find":"mbh", 449 | "replace":"ম্ভ", 450 | "rules":[ 451 | 452 | ] 453 | }, 454 | { 455 | "find":"mph", 456 | "replace":"ম্ফ", 457 | "rules":[ 458 | 459 | ] 460 | }, 461 | { 462 | "find":"mpl", 463 | "replace":"মপ্ল", 464 | "rules":[ 465 | 466 | ] 467 | }, 468 | { 469 | "find":"mth", 470 | "replace":"ম্থ", 471 | "rules":[ 472 | 473 | ] 474 | }, 475 | { 476 | "find":"nTh", 477 | "replace":"ন্ঠ", 478 | "rules":[ 479 | 480 | ] 481 | }, 482 | { 483 | "find":"nch", 484 | "replace":"ঞ্ছ", 485 | "rules":[ 486 | 487 | ] 488 | }, 489 | { 490 | "find":"ndh", 491 | "replace":"ন্ধ", 492 | "rules":[ 493 | 494 | ] 495 | }, 496 | { 497 | "find":"ngI", 498 | "replace":"ঙ্গী", 499 | "rules":[ 500 | 501 | ] 502 | }, 503 | { 504 | "find":"ngO", 505 | "replace":"ঙ্গো", 506 | "rules":[ 507 | 508 | ] 509 | }, 510 | { 511 | "find":"ngU", 512 | "replace":"ঙ্গূ", 513 | "rules":[ 514 | 515 | ] 516 | }, 517 | { 518 | "find":"nga", 519 | "replace":"ঙ্গা", 520 | "rules":[ 521 | 522 | ] 523 | }, 524 | { 525 | "find":"nge", 526 | "replace":"ঙ্গে", 527 | "rules":[ 528 | 529 | ] 530 | }, 531 | { 532 | "find":"ngh", 533 | "replace":"ঙ্ঘ", 534 | "rules":[ 535 | 536 | ] 537 | }, 538 | { 539 | "find":"ngi", 540 | "replace":"ঙ্গি", 541 | "rules":[ 542 | 543 | ] 544 | }, 545 | { 546 | "find":"ngo", 547 | "replace":"ঙ্গ", 548 | "rules":[ 549 | 550 | ] 551 | }, 552 | { 553 | "find":"ngr", 554 | "replace":"ংর", 555 | "rules":[ 556 | 557 | ] 558 | }, 559 | { 560 | "find":"ngu", 561 | "replace":"ঙ্গু", 562 | "rules":[ 563 | 564 | ] 565 | }, 566 | { 567 | "find":"njh", 568 | "replace":"ঞ্ঝ", 569 | "rules":[ 570 | 571 | ] 572 | }, 573 | { 574 | "find":"nkh", 575 | "replace":"ঙ্খ", 576 | "rules":[ 577 | 578 | ] 579 | }, 580 | { 581 | "find":"nsh", 582 | "replace":"নশ", 583 | "rules":[ 584 | 585 | ] 586 | }, 587 | { 588 | "find":"nth", 589 | "replace":"ন্থ", 590 | "rules":[ 591 | 592 | ] 593 | }, 594 | { 595 | "find":"oo`", 596 | "replace":"ু", 597 | "rules":[ 598 | 599 | ] 600 | }, 601 | { 602 | "find":"phl", 603 | "replace":"ফ্ল", 604 | "rules":[ 605 | 606 | ] 607 | }, 608 | { 609 | "find":"psh", 610 | "replace":"পশ", 611 | "rules":[ 612 | 613 | ] 614 | }, 615 | { 616 | "find":"rrZ", 617 | "replace":"রর‍্য", 618 | "rules":[ 619 | 620 | ] 621 | }, 622 | { 623 | "find":"rri", 624 | "replace":"ৃ", 625 | "rules":[ 626 | { 627 | "matches":[ 628 | { 629 | "scope":"!consonant", 630 | "type":"prefix" 631 | } 632 | ], 633 | "replace":"ঋ" 634 | }, 635 | { 636 | "matches":[ 637 | { 638 | "scope":"punctuation", 639 | "type":"prefix" 640 | } 641 | ], 642 | "replace":"ঋ" 643 | } 644 | ] 645 | }, 646 | { 647 | "find":"rry", 648 | "replace":"রর‍্য", 649 | "rules":[ 650 | 651 | ] 652 | }, 653 | { 654 | "find":"shc", 655 | "replace":"শ্চ", 656 | "rules":[ 657 | 658 | ] 659 | }, 660 | { 661 | "find":"shl", 662 | "replace":"শ্ল", 663 | "rules":[ 664 | 665 | ] 666 | }, 667 | { 668 | "find":"shm", 669 | "replace":"শ্ম", 670 | "rules":[ 671 | 672 | ] 673 | }, 674 | { 675 | "find":"shn", 676 | "replace":"শ্ন", 677 | "rules":[ 678 | 679 | ] 680 | }, 681 | { 682 | "find":"sht", 683 | "replace":"শ্ত", 684 | "rules":[ 685 | 686 | ] 687 | }, 688 | { 689 | "find":"skh", 690 | "replace":"স্খ", 691 | "rules":[ 692 | 693 | ] 694 | }, 695 | { 696 | "find":"skl", 697 | "replace":"স্ক্ল", 698 | "rules":[ 699 | 700 | ] 701 | }, 702 | { 703 | "find":"sph", 704 | "replace":"স্ফ", 705 | "rules":[ 706 | 707 | ] 708 | }, 709 | { 710 | "find":"spl", 711 | "replace":"স্প্ল", 712 | "rules":[ 713 | 714 | ] 715 | }, 716 | { 717 | "find":"sth", 718 | "replace":"স্থ", 719 | "rules":[ 720 | 721 | ] 722 | }, 723 | { 724 | "find":"t``", 725 | "replace":"ৎ", 726 | "rules":[ 727 | 728 | ] 729 | }, 730 | { 731 | "find":"tth", 732 | "replace":"ত্থ", 733 | "rules":[ 734 | 735 | ] 736 | }, 737 | { 738 | "find":",,", 739 | "replace":"্‌", 740 | "rules":[ 741 | 742 | ] 743 | }, 744 | { 745 | "find":"..", 746 | "replace":"।।", 747 | "rules":[ 748 | 749 | ] 750 | }, 751 | { 752 | "find":".`", 753 | "replace":".", 754 | "rules":[ 755 | 756 | ] 757 | }, 758 | { 759 | "find":":`", 760 | "replace":":", 761 | "rules":[ 762 | 763 | ] 764 | }, 765 | { 766 | "find":"AZ", 767 | "replace":"অ্যা", 768 | "rules":[ 769 | 770 | ] 771 | }, 772 | { 773 | "find":"A`", 774 | "replace":"া", 775 | "rules":[ 776 | 777 | ] 778 | }, 779 | { 780 | "find":"DD", 781 | "replace":"ড্ড", 782 | "rules":[ 783 | 784 | ] 785 | }, 786 | { 787 | "find":"Dh", 788 | "replace":"ঢ", 789 | "rules":[ 790 | 791 | ] 792 | }, 793 | { 794 | "find":"GG", 795 | "replace":"জ্ঞ", 796 | "rules":[ 797 | 798 | ] 799 | }, 800 | { 801 | "find":"GN", 802 | "replace":"গ্ণ", 803 | "rules":[ 804 | 805 | ] 806 | }, 807 | { 808 | "find":"Gg", 809 | "replace":"জ্ঞ", 810 | "rules":[ 811 | 812 | ] 813 | }, 814 | { 815 | "find":"Gh", 816 | "replace":"ঘ", 817 | "rules":[ 818 | 819 | ] 820 | }, 821 | { 822 | "find":"Gl", 823 | "replace":"গ্ল", 824 | "rules":[ 825 | 826 | ] 827 | }, 828 | { 829 | "find":"Gm", 830 | "replace":"গ্ম", 831 | "rules":[ 832 | 833 | ] 834 | }, 835 | { 836 | "find":"Gn", 837 | "replace":"গ্ন", 838 | "rules":[ 839 | 840 | ] 841 | }, 842 | { 843 | "find":"I`", 844 | "replace":"ী", 845 | "rules":[ 846 | 847 | ] 848 | }, 849 | { 850 | "find":"ND", 851 | "replace":"ণ্ড", 852 | "rules":[ 853 | 854 | ] 855 | }, 856 | { 857 | "find":"NG", 858 | "replace":"ঞ", 859 | "rules":[ 860 | 861 | ] 862 | }, 863 | { 864 | "find":"NN", 865 | "replace":"ণ্ণ", 866 | "rules":[ 867 | 868 | ] 869 | }, 870 | { 871 | "find":"NT", 872 | "replace":"ণ্ট", 873 | "rules":[ 874 | 875 | ] 876 | }, 877 | { 878 | "find":"Ng", 879 | "replace":"ঙ", 880 | "rules":[ 881 | 882 | ] 883 | }, 884 | { 885 | "find":"Nm", 886 | "replace":"ণ্ম", 887 | "rules":[ 888 | 889 | ] 890 | }, 891 | { 892 | "find":"Nn", 893 | "replace":"ণ্ন", 894 | "rules":[ 895 | 896 | ] 897 | }, 898 | { 899 | "find":"OI", 900 | "replace":"ৈ", 901 | "rules":[ 902 | { 903 | "matches":[ 904 | { 905 | "scope":"!consonant", 906 | "type":"prefix" 907 | } 908 | ], 909 | "replace":"ঐ" 910 | }, 911 | { 912 | "matches":[ 913 | { 914 | "scope":"punctuation", 915 | "type":"prefix" 916 | } 917 | ], 918 | "replace":"ঐ" 919 | } 920 | ] 921 | }, 922 | { 923 | "find":"OU", 924 | "replace":"ৌ", 925 | "rules":[ 926 | { 927 | "matches":[ 928 | { 929 | "scope":"!consonant", 930 | "type":"prefix" 931 | } 932 | ], 933 | "replace":"ঔ" 934 | }, 935 | { 936 | "matches":[ 937 | { 938 | "scope":"punctuation", 939 | "type":"prefix" 940 | } 941 | ], 942 | "replace":"ঔ" 943 | } 944 | ] 945 | }, 946 | { 947 | "find":"O`", 948 | "replace":"ো", 949 | "rules":[ 950 | 951 | ] 952 | }, 953 | { 954 | "find":"Rg", 955 | "replace":"ড়্গ", 956 | "rules":[ 957 | 958 | ] 959 | }, 960 | { 961 | "find":"Rh", 962 | "replace":"ঢ়", 963 | "rules":[ 964 | 965 | ] 966 | }, 967 | { 968 | "find":"Sc", 969 | "replace":"শ্চ", 970 | "rules":[ 971 | 972 | ] 973 | }, 974 | { 975 | "find":"Sc", 976 | "replace":"শ্চ", 977 | "rules":[ 978 | 979 | ] 980 | }, 981 | { 982 | "find":"Sh", 983 | "replace":"ষ", 984 | "rules":[ 985 | 986 | ] 987 | }, 988 | { 989 | "find":"Sl", 990 | "replace":"শ্ল", 991 | "rules":[ 992 | 993 | ] 994 | }, 995 | { 996 | "find":"Sm", 997 | "replace":"শ্ম", 998 | "rules":[ 999 | 1000 | ] 1001 | }, 1002 | { 1003 | "find":"Sn", 1004 | "replace":"শ্ন", 1005 | "rules":[ 1006 | 1007 | ] 1008 | }, 1009 | { 1010 | "find":"St", 1011 | "replace":"শ্ত", 1012 | "rules":[ 1013 | 1014 | ] 1015 | }, 1016 | { 1017 | "find":"TT", 1018 | "replace":"ট্ট", 1019 | "rules":[ 1020 | 1021 | ] 1022 | }, 1023 | { 1024 | "find":"Th", 1025 | "replace":"ঠ", 1026 | "rules":[ 1027 | 1028 | ] 1029 | }, 1030 | { 1031 | "find":"Tm", 1032 | "replace":"ট্ম", 1033 | "rules":[ 1034 | 1035 | ] 1036 | }, 1037 | { 1038 | "find":"U`", 1039 | "replace":"ূ", 1040 | "rules":[ 1041 | 1042 | ] 1043 | }, 1044 | { 1045 | "find":"^`", 1046 | "replace":"^", 1047 | "rules":[ 1048 | 1049 | ] 1050 | }, 1051 | { 1052 | "find":"aZ", 1053 | "replace":"অ্যা", 1054 | "rules":[ 1055 | 1056 | ] 1057 | }, 1058 | { 1059 | "find":"a`", 1060 | "replace":"া", 1061 | "rules":[ 1062 | 1063 | ] 1064 | }, 1065 | { 1066 | "find":"bb", 1067 | "replace":"ব্ব", 1068 | "rules":[ 1069 | 1070 | ] 1071 | }, 1072 | { 1073 | "find":"bd", 1074 | "replace":"ব্দ", 1075 | "rules":[ 1076 | 1077 | ] 1078 | }, 1079 | { 1080 | "find":"bh", 1081 | "replace":"ভ", 1082 | "rules":[ 1083 | 1084 | ] 1085 | }, 1086 | { 1087 | "find":"bj", 1088 | "replace":"ব্জ", 1089 | "rules":[ 1090 | 1091 | ] 1092 | }, 1093 | { 1094 | "find":"bl", 1095 | "replace":"ব্ল", 1096 | "rules":[ 1097 | 1098 | ] 1099 | }, 1100 | { 1101 | "find":"cc", 1102 | "replace":"চ্চ", 1103 | "rules":[ 1104 | 1105 | ] 1106 | }, 1107 | { 1108 | "find":"ch", 1109 | "replace":"ছ", 1110 | "rules":[ 1111 | 1112 | ] 1113 | }, 1114 | { 1115 | "find":"dd", 1116 | "replace":"দ্দ", 1117 | "rules":[ 1118 | 1119 | ] 1120 | }, 1121 | { 1122 | "find":"dg", 1123 | "replace":"দ্গ", 1124 | "rules":[ 1125 | 1126 | ] 1127 | }, 1128 | { 1129 | "find":"dh", 1130 | "replace":"ধ", 1131 | "rules":[ 1132 | 1133 | ] 1134 | }, 1135 | { 1136 | "find":"dm", 1137 | "replace":"দ্ম", 1138 | "rules":[ 1139 | 1140 | ] 1141 | }, 1142 | { 1143 | "find":"dv", 1144 | "replace":"দ্ভ", 1145 | "rules":[ 1146 | 1147 | ] 1148 | }, 1149 | { 1150 | "find":"e`", 1151 | "replace":"ে", 1152 | "rules":[ 1153 | 1154 | ] 1155 | }, 1156 | { 1157 | "find":"ee", 1158 | "replace":"ী", 1159 | "rules":[ 1160 | { 1161 | "matches":[ 1162 | { 1163 | "scope":"!consonant", 1164 | "type":"prefix" 1165 | }, 1166 | { 1167 | "scope":"!exact", 1168 | "type":"suffix", 1169 | "value":"`" 1170 | } 1171 | ], 1172 | "replace":"ঈ" 1173 | }, 1174 | { 1175 | "matches":[ 1176 | { 1177 | "scope":"punctuation", 1178 | "type":"prefix" 1179 | }, 1180 | { 1181 | "scope":"!exact", 1182 | "type":"suffix", 1183 | "value":"`" 1184 | } 1185 | ], 1186 | "replace":"ঈ" 1187 | } 1188 | ] 1189 | }, 1190 | { 1191 | "find":"fl", 1192 | "replace":"ফ্ল", 1193 | "rules":[ 1194 | 1195 | ] 1196 | }, 1197 | { 1198 | "find":"gG", 1199 | "replace":"জ্ঞ", 1200 | "rules":[ 1201 | 1202 | ] 1203 | }, 1204 | { 1205 | "find":"gN", 1206 | "replace":"গ্ণ", 1207 | "rules":[ 1208 | 1209 | ] 1210 | }, 1211 | { 1212 | "find":"gg", 1213 | "replace":"জ্ঞ", 1214 | "rules":[ 1215 | 1216 | ] 1217 | }, 1218 | { 1219 | "find":"gh", 1220 | "replace":"ঘ", 1221 | "rules":[ 1222 | 1223 | ] 1224 | }, 1225 | { 1226 | "find":"gl", 1227 | "replace":"গ্ল", 1228 | "rules":[ 1229 | 1230 | ] 1231 | }, 1232 | { 1233 | "find":"gm", 1234 | "replace":"গ্ম", 1235 | "rules":[ 1236 | 1237 | ] 1238 | }, 1239 | { 1240 | "find":"gn", 1241 | "replace":"গ্ন", 1242 | "rules":[ 1243 | 1244 | ] 1245 | }, 1246 | { 1247 | "find":"hN", 1248 | "replace":"হ্ণ", 1249 | "rules":[ 1250 | 1251 | ] 1252 | }, 1253 | { 1254 | "find":"hl", 1255 | "replace":"হ্ল", 1256 | "rules":[ 1257 | 1258 | ] 1259 | }, 1260 | { 1261 | "find":"hm", 1262 | "replace":"হ্ম", 1263 | "rules":[ 1264 | 1265 | ] 1266 | }, 1267 | { 1268 | "find":"hn", 1269 | "replace":"হ্ন", 1270 | "rules":[ 1271 | 1272 | ] 1273 | }, 1274 | { 1275 | "find":"i`", 1276 | "replace":"ি", 1277 | "rules":[ 1278 | 1279 | ] 1280 | }, 1281 | { 1282 | "find":"jh", 1283 | "replace":"ঝ", 1284 | "rules":[ 1285 | 1286 | ] 1287 | }, 1288 | { 1289 | "find":"jj", 1290 | "replace":"জ্জ", 1291 | "rules":[ 1292 | 1293 | ] 1294 | }, 1295 | { 1296 | "find":"kT", 1297 | "replace":"ক্ট", 1298 | "rules":[ 1299 | 1300 | ] 1301 | }, 1302 | { 1303 | "find":"kh", 1304 | "replace":"খ", 1305 | "rules":[ 1306 | 1307 | ] 1308 | }, 1309 | { 1310 | "find":"kk", 1311 | "replace":"ক্ক", 1312 | "rules":[ 1313 | 1314 | ] 1315 | }, 1316 | { 1317 | "find":"kl", 1318 | "replace":"ক্ল", 1319 | "rules":[ 1320 | 1321 | ] 1322 | }, 1323 | { 1324 | "find":"ks", 1325 | "replace":"ক্স", 1326 | "rules":[ 1327 | 1328 | ] 1329 | }, 1330 | { 1331 | "find":"kt", 1332 | "replace":"ক্ত", 1333 | "rules":[ 1334 | 1335 | ] 1336 | }, 1337 | { 1338 | "find":"kx", 1339 | "replace":"ক্ষ", 1340 | "rules":[ 1341 | 1342 | ] 1343 | }, 1344 | { 1345 | "find":"lD", 1346 | "replace":"ল্ড", 1347 | "rules":[ 1348 | 1349 | ] 1350 | }, 1351 | { 1352 | "find":"lT", 1353 | "replace":"ল্ট", 1354 | "rules":[ 1355 | 1356 | ] 1357 | }, 1358 | { 1359 | "find":"lb", 1360 | "replace":"ল্ব", 1361 | "rules":[ 1362 | 1363 | ] 1364 | }, 1365 | { 1366 | "find":"lg", 1367 | "replace":"ল্গ", 1368 | "rules":[ 1369 | 1370 | ] 1371 | }, 1372 | { 1373 | "find":"lk", 1374 | "replace":"ল্ক", 1375 | "rules":[ 1376 | 1377 | ] 1378 | }, 1379 | { 1380 | "find":"ll", 1381 | "replace":"ল্ল", 1382 | "rules":[ 1383 | 1384 | ] 1385 | }, 1386 | { 1387 | "find":"lm", 1388 | "replace":"ল্ম", 1389 | "rules":[ 1390 | 1391 | ] 1392 | }, 1393 | { 1394 | "find":"lp", 1395 | "replace":"ল্প", 1396 | "rules":[ 1397 | 1398 | ] 1399 | }, 1400 | { 1401 | "find":"lv", 1402 | "replace":"ল্ভ", 1403 | "rules":[ 1404 | 1405 | ] 1406 | }, 1407 | { 1408 | "find":"mb", 1409 | "replace":"ম্ব", 1410 | "rules":[ 1411 | 1412 | ] 1413 | }, 1414 | { 1415 | "find":"mf", 1416 | "replace":"ম্ফ", 1417 | "rules":[ 1418 | 1419 | ] 1420 | }, 1421 | { 1422 | "find":"ml", 1423 | "replace":"ম্ল", 1424 | "rules":[ 1425 | 1426 | ] 1427 | }, 1428 | { 1429 | "find":"mm", 1430 | "replace":"ম্ম", 1431 | "rules":[ 1432 | 1433 | ] 1434 | }, 1435 | { 1436 | "find":"mn", 1437 | "replace":"ম্ন", 1438 | "rules":[ 1439 | 1440 | ] 1441 | }, 1442 | { 1443 | "find":"mp", 1444 | "replace":"ম্প", 1445 | "rules":[ 1446 | 1447 | ] 1448 | }, 1449 | { 1450 | "find":"mv", 1451 | "replace":"ম্ভ", 1452 | "rules":[ 1453 | 1454 | ] 1455 | }, 1456 | { 1457 | "find":"nD", 1458 | "replace":"ন্ড", 1459 | "rules":[ 1460 | 1461 | ] 1462 | }, 1463 | { 1464 | "find":"nT", 1465 | "replace":"ন্ট", 1466 | "rules":[ 1467 | 1468 | ] 1469 | }, 1470 | { 1471 | "find":"nc", 1472 | "replace":"ঞ্চ", 1473 | "rules":[ 1474 | 1475 | ] 1476 | }, 1477 | { 1478 | "find":"nd", 1479 | "replace":"ন্দ", 1480 | "rules":[ 1481 | 1482 | ] 1483 | }, 1484 | { 1485 | "find":"ng", 1486 | "replace":"ং", 1487 | "rules":[ 1488 | 1489 | ] 1490 | }, 1491 | { 1492 | "find":"nj", 1493 | "replace":"ঞ্জ", 1494 | "rules":[ 1495 | 1496 | ] 1497 | }, 1498 | { 1499 | "find":"nk", 1500 | "replace":"ঙ্ক", 1501 | "rules":[ 1502 | 1503 | ] 1504 | }, 1505 | { 1506 | "find":"nm", 1507 | "replace":"ন্ম", 1508 | "rules":[ 1509 | 1510 | ] 1511 | }, 1512 | { 1513 | "find":"nn", 1514 | "replace":"ন্ন", 1515 | "rules":[ 1516 | 1517 | ] 1518 | }, 1519 | { 1520 | "find":"ns", 1521 | "replace":"ন্স", 1522 | "rules":[ 1523 | 1524 | ] 1525 | }, 1526 | { 1527 | "find":"nt", 1528 | "replace":"ন্ত", 1529 | "rules":[ 1530 | 1531 | ] 1532 | }, 1533 | { 1534 | "find":"oZ", 1535 | "replace":"অ্য", 1536 | "rules":[ 1537 | 1538 | ] 1539 | }, 1540 | { 1541 | "find":"o`", 1542 | "replace":"", 1543 | "rules":[ 1544 | 1545 | ] 1546 | }, 1547 | { 1548 | "find":"oo", 1549 | "replace":"ু", 1550 | "rules":[ 1551 | { 1552 | "matches":[ 1553 | { 1554 | "scope":"!consonant", 1555 | "type":"prefix" 1556 | }, 1557 | { 1558 | "scope":"!exact", 1559 | "type":"suffix", 1560 | "value":"`" 1561 | } 1562 | ], 1563 | "replace":"উ" 1564 | }, 1565 | { 1566 | "matches":[ 1567 | { 1568 | "scope":"punctuation", 1569 | "type":"prefix" 1570 | }, 1571 | { 1572 | "scope":"!exact", 1573 | "type":"suffix", 1574 | "value":"`" 1575 | } 1576 | ], 1577 | "replace":"উ" 1578 | } 1579 | ] 1580 | }, 1581 | { 1582 | "find":"pT", 1583 | "replace":"প্ট", 1584 | "rules":[ 1585 | 1586 | ] 1587 | }, 1588 | { 1589 | "find":"ph", 1590 | "replace":"ফ", 1591 | "rules":[ 1592 | 1593 | ] 1594 | }, 1595 | { 1596 | "find":"pl", 1597 | "replace":"প্ল", 1598 | "rules":[ 1599 | 1600 | ] 1601 | }, 1602 | { 1603 | "find":"pn", 1604 | "replace":"প্ন", 1605 | "rules":[ 1606 | 1607 | ] 1608 | }, 1609 | { 1610 | "find":"pp", 1611 | "replace":"প্প", 1612 | "rules":[ 1613 | 1614 | ] 1615 | }, 1616 | { 1617 | "find":"ps", 1618 | "replace":"প্স", 1619 | "rules":[ 1620 | 1621 | ] 1622 | }, 1623 | { 1624 | "find":"pt", 1625 | "replace":"প্ত", 1626 | "rules":[ 1627 | 1628 | ] 1629 | }, 1630 | { 1631 | "find":"rZ", 1632 | "replace":"র‍্য", 1633 | "rules":[ 1634 | { 1635 | "matches":[ 1636 | { 1637 | "scope":"consonant", 1638 | "type":"prefix" 1639 | }, 1640 | { 1641 | "scope":"!exact", 1642 | "type":"prefix", 1643 | "value":"r" 1644 | }, 1645 | { 1646 | "scope":"!exact", 1647 | "type":"prefix", 1648 | "value":"y" 1649 | }, 1650 | { 1651 | "scope":"!exact", 1652 | "type":"prefix", 1653 | "value":"w" 1654 | }, 1655 | { 1656 | "scope":"!exact", 1657 | "type":"prefix", 1658 | "value":"x" 1659 | } 1660 | ], 1661 | "replace":"্র্য" 1662 | } 1663 | ] 1664 | }, 1665 | { 1666 | "find":"rr", 1667 | "replace":"রর", 1668 | "rules":[ 1669 | { 1670 | "matches":[ 1671 | { 1672 | "scope":"!consonant", 1673 | "type":"prefix" 1674 | }, 1675 | { 1676 | "scope":"!vowel", 1677 | "type":"suffix" 1678 | }, 1679 | { 1680 | "scope":"!exact", 1681 | "type":"suffix", 1682 | "value":"r" 1683 | }, 1684 | { 1685 | "scope":"!punctuation", 1686 | "type":"suffix" 1687 | } 1688 | ], 1689 | "replace":"র্" 1690 | }, 1691 | { 1692 | "matches":[ 1693 | { 1694 | "scope":"consonant", 1695 | "type":"prefix" 1696 | }, 1697 | { 1698 | "scope":"!exact", 1699 | "type":"prefix", 1700 | "value":"r" 1701 | } 1702 | ], 1703 | "replace":"্রর" 1704 | } 1705 | ] 1706 | }, 1707 | { 1708 | "find":"ry", 1709 | "replace":"র‍্য", 1710 | "rules":[ 1711 | { 1712 | "matches":[ 1713 | { 1714 | "scope":"consonant", 1715 | "type":"prefix" 1716 | }, 1717 | { 1718 | "scope":"!exact", 1719 | "type":"prefix", 1720 | "value":"r" 1721 | }, 1722 | { 1723 | "scope":"!exact", 1724 | "type":"prefix", 1725 | "value":"y" 1726 | }, 1727 | { 1728 | "scope":"!exact", 1729 | "type":"prefix", 1730 | "value":"w" 1731 | }, 1732 | { 1733 | "scope":"!exact", 1734 | "type":"prefix", 1735 | "value":"x" 1736 | } 1737 | ], 1738 | "replace":"্র্য" 1739 | } 1740 | ] 1741 | }, 1742 | { 1743 | "find":"sT", 1744 | "replace":"স্ট", 1745 | "rules":[ 1746 | 1747 | ] 1748 | }, 1749 | { 1750 | "find":"sf", 1751 | "replace":"স্ফ", 1752 | "rules":[ 1753 | 1754 | ] 1755 | }, 1756 | { 1757 | "find":"sh", 1758 | "replace":"শ", 1759 | "rules":[ 1760 | 1761 | ] 1762 | }, 1763 | { 1764 | "find":"sk", 1765 | "replace":"স্ক", 1766 | "rules":[ 1767 | 1768 | ] 1769 | }, 1770 | { 1771 | "find":"sl", 1772 | "replace":"স্ল", 1773 | "rules":[ 1774 | 1775 | ] 1776 | }, 1777 | { 1778 | "find":"sm", 1779 | "replace":"স্ম", 1780 | "rules":[ 1781 | 1782 | ] 1783 | }, 1784 | { 1785 | "find":"sn", 1786 | "replace":"স্ন", 1787 | "rules":[ 1788 | 1789 | ] 1790 | }, 1791 | { 1792 | "find":"sp", 1793 | "replace":"স্প", 1794 | "rules":[ 1795 | 1796 | ] 1797 | }, 1798 | { 1799 | "find":"st", 1800 | "replace":"স্ত", 1801 | "rules":[ 1802 | 1803 | ] 1804 | }, 1805 | { 1806 | "find":"th", 1807 | "replace":"থ", 1808 | "rules":[ 1809 | 1810 | ] 1811 | }, 1812 | { 1813 | "find":"tm", 1814 | "replace":"ত্ম", 1815 | "rules":[ 1816 | 1817 | ] 1818 | }, 1819 | { 1820 | "find":"tn", 1821 | "replace":"ত্ন", 1822 | "rules":[ 1823 | 1824 | ] 1825 | }, 1826 | { 1827 | "find":"tt", 1828 | "replace":"ত্ত", 1829 | "rules":[ 1830 | 1831 | ] 1832 | }, 1833 | { 1834 | "find":"u`", 1835 | "replace":"ু", 1836 | "rules":[ 1837 | 1838 | ] 1839 | }, 1840 | { 1841 | "find":"vl", 1842 | "replace":"ভ্ল", 1843 | "rules":[ 1844 | 1845 | ] 1846 | }, 1847 | { 1848 | "find":"$", 1849 | "replace":"৳", 1850 | "rules":[ 1851 | 1852 | ] 1853 | }, 1854 | { 1855 | "find":",", 1856 | "replace":",", 1857 | "rules":[ 1858 | 1859 | ] 1860 | }, 1861 | { 1862 | "find":".", 1863 | "replace":"।", 1864 | "rules":[ 1865 | { 1866 | "matches":[ 1867 | { 1868 | "scope":"number", 1869 | "type":"suffix" 1870 | } 1871 | ], 1872 | "replace":"." 1873 | } 1874 | ] 1875 | }, 1876 | { 1877 | "find":"0", 1878 | "replace":"০", 1879 | "rules":[ 1880 | 1881 | ] 1882 | }, 1883 | { 1884 | "find":"1", 1885 | "replace":"১", 1886 | "rules":[ 1887 | 1888 | ] 1889 | }, 1890 | { 1891 | "find":"2", 1892 | "replace":"২", 1893 | "rules":[ 1894 | 1895 | ] 1896 | }, 1897 | { 1898 | "find":"3", 1899 | "replace":"৩", 1900 | "rules":[ 1901 | 1902 | ] 1903 | }, 1904 | { 1905 | "find":"4", 1906 | "replace":"৪", 1907 | "rules":[ 1908 | 1909 | ] 1910 | }, 1911 | { 1912 | "find":"5", 1913 | "replace":"৫", 1914 | "rules":[ 1915 | 1916 | ] 1917 | }, 1918 | { 1919 | "find":"6", 1920 | "replace":"৬", 1921 | "rules":[ 1922 | 1923 | ] 1924 | }, 1925 | { 1926 | "find":"7", 1927 | "replace":"৭", 1928 | "rules":[ 1929 | 1930 | ] 1931 | }, 1932 | { 1933 | "find":"8", 1934 | "replace":"৮", 1935 | "rules":[ 1936 | 1937 | ] 1938 | }, 1939 | { 1940 | "find":"9", 1941 | "replace":"৯", 1942 | "rules":[ 1943 | 1944 | ] 1945 | }, 1946 | { 1947 | "find":":", 1948 | "replace":"ঃ", 1949 | "rules":[ 1950 | { 1951 | "matches":[ 1952 | { 1953 | "scope":"number", 1954 | "type":"suffix" 1955 | } 1956 | ], 1957 | "replace":":" 1958 | } 1959 | ] 1960 | }, 1961 | { 1962 | "find":"D", 1963 | "replace":"ড", 1964 | "rules":[ 1965 | 1966 | ] 1967 | }, 1968 | { 1969 | "find":"G", 1970 | "replace":"গ", 1971 | "rules":[ 1972 | 1973 | ] 1974 | }, 1975 | { 1976 | "find":"I", 1977 | "replace":"ী", 1978 | "rules":[ 1979 | { 1980 | "matches":[ 1981 | { 1982 | "scope":"!consonant", 1983 | "type":"prefix" 1984 | }, 1985 | { 1986 | "scope":"!exact", 1987 | "type":"suffix", 1988 | "value":"`" 1989 | } 1990 | ], 1991 | "replace":"ঈ" 1992 | }, 1993 | { 1994 | "matches":[ 1995 | { 1996 | "scope":"punctuation", 1997 | "type":"prefix" 1998 | }, 1999 | { 2000 | "scope":"!exact", 2001 | "type":"suffix", 2002 | "value":"`" 2003 | } 2004 | ], 2005 | "replace":"ঈ" 2006 | } 2007 | ] 2008 | }, 2009 | { 2010 | "find":"J", 2011 | "replace":"জ", 2012 | "rules":[ 2013 | 2014 | ] 2015 | }, 2016 | { 2017 | "find":"N", 2018 | "replace":"ণ", 2019 | "rules":[ 2020 | 2021 | ] 2022 | }, 2023 | { 2024 | "find":"O", 2025 | "replace":"ো", 2026 | "rules":[ 2027 | { 2028 | "matches":[ 2029 | { 2030 | "scope":"!consonant", 2031 | "type":"prefix" 2032 | } 2033 | ], 2034 | "replace":"ও" 2035 | }, 2036 | { 2037 | "matches":[ 2038 | { 2039 | "scope":"punctuation", 2040 | "type":"prefix" 2041 | } 2042 | ], 2043 | "replace":"ও" 2044 | } 2045 | ] 2046 | }, 2047 | { 2048 | "find":"R", 2049 | "replace":"ড়", 2050 | "rules":[ 2051 | 2052 | ] 2053 | }, 2054 | { 2055 | "find":"S", 2056 | "replace":"শ", 2057 | "rules":[ 2058 | 2059 | ] 2060 | }, 2061 | { 2062 | "find":"T", 2063 | "replace":"ট", 2064 | "rules":[ 2065 | 2066 | ] 2067 | }, 2068 | { 2069 | "find":"U", 2070 | "replace":"ূ", 2071 | "rules":[ 2072 | { 2073 | "matches":[ 2074 | { 2075 | "scope":"!consonant", 2076 | "type":"prefix" 2077 | }, 2078 | { 2079 | "scope":"!exact", 2080 | "type":"suffix", 2081 | "value":"`" 2082 | } 2083 | ], 2084 | "replace":"ঊ" 2085 | }, 2086 | { 2087 | "matches":[ 2088 | { 2089 | "scope":"punctuation", 2090 | "type":"prefix" 2091 | }, 2092 | { 2093 | "scope":"!exact", 2094 | "type":"suffix", 2095 | "value":"`" 2096 | } 2097 | ], 2098 | "replace":"ঊ" 2099 | } 2100 | ] 2101 | }, 2102 | { 2103 | "find":"Y", 2104 | "replace":"য়", 2105 | "rules":[ 2106 | 2107 | ] 2108 | }, 2109 | { 2110 | "find":"Z", 2111 | "replace":"্য", 2112 | "rules":[ 2113 | 2114 | ] 2115 | }, 2116 | { 2117 | "find":"^", 2118 | "replace":"ঁ", 2119 | "rules":[ 2120 | 2121 | ] 2122 | }, 2123 | { 2124 | "find":"`", 2125 | "replace":"", 2126 | "rules":[ 2127 | 2128 | ] 2129 | }, 2130 | { 2131 | "find":"a", 2132 | "replace":"া", 2133 | "rules":[ 2134 | { 2135 | "matches":[ 2136 | { 2137 | "scope":"punctuation", 2138 | "type":"prefix" 2139 | }, 2140 | { 2141 | "scope":"!exact", 2142 | "type":"suffix", 2143 | "value":"`" 2144 | } 2145 | ], 2146 | "replace":"আ" 2147 | }, 2148 | { 2149 | "matches":[ 2150 | { 2151 | "scope":"!consonant", 2152 | "type":"prefix" 2153 | }, 2154 | { 2155 | "scope":"!exact", 2156 | "type":"prefix", 2157 | "value":"a" 2158 | }, 2159 | { 2160 | "scope":"!exact", 2161 | "type":"suffix", 2162 | "value":"`" 2163 | } 2164 | ], 2165 | "replace":"য়া" 2166 | }, 2167 | { 2168 | "matches":[ 2169 | { 2170 | "scope":"exact", 2171 | "type":"prefix", 2172 | "value":"a" 2173 | }, 2174 | { 2175 | "scope":"!exact", 2176 | "type":"suffix", 2177 | "value":"`" 2178 | } 2179 | ], 2180 | "replace":"আ" 2181 | } 2182 | ] 2183 | }, 2184 | { 2185 | "find":"b", 2186 | "replace":"ব", 2187 | "rules":[ 2188 | 2189 | ] 2190 | }, 2191 | { 2192 | "find":"c", 2193 | "replace":"চ", 2194 | "rules":[ 2195 | 2196 | ] 2197 | }, 2198 | { 2199 | "find":"d", 2200 | "replace":"দ", 2201 | "rules":[ 2202 | 2203 | ] 2204 | }, 2205 | { 2206 | "find":"e", 2207 | "replace":"ে", 2208 | "rules":[ 2209 | { 2210 | "matches":[ 2211 | { 2212 | "scope":"!consonant", 2213 | "type":"prefix" 2214 | }, 2215 | { 2216 | "scope":"!exact", 2217 | "type":"suffix", 2218 | "value":"`" 2219 | } 2220 | ], 2221 | "replace":"এ" 2222 | }, 2223 | { 2224 | "matches":[ 2225 | { 2226 | "scope":"punctuation", 2227 | "type":"prefix" 2228 | }, 2229 | { 2230 | "scope":"!exact", 2231 | "type":"suffix", 2232 | "value":"`" 2233 | } 2234 | ], 2235 | "replace":"এ" 2236 | } 2237 | ] 2238 | }, 2239 | { 2240 | "find":"f", 2241 | "replace":"ফ", 2242 | "rules":[ 2243 | 2244 | ] 2245 | }, 2246 | { 2247 | "find":"g", 2248 | "replace":"গ", 2249 | "rules":[ 2250 | 2251 | ] 2252 | }, 2253 | { 2254 | "find":"h", 2255 | "replace":"হ", 2256 | "rules":[ 2257 | 2258 | ] 2259 | }, 2260 | { 2261 | "find":"i", 2262 | "replace":"ি", 2263 | "rules":[ 2264 | { 2265 | "matches":[ 2266 | { 2267 | "scope":"!consonant", 2268 | "type":"prefix" 2269 | }, 2270 | { 2271 | "scope":"!exact", 2272 | "type":"suffix", 2273 | "value":"`" 2274 | } 2275 | ], 2276 | "replace":"ই" 2277 | }, 2278 | { 2279 | "matches":[ 2280 | { 2281 | "scope":"punctuation", 2282 | "type":"prefix" 2283 | }, 2284 | { 2285 | "scope":"!exact", 2286 | "type":"suffix", 2287 | "value":"`" 2288 | } 2289 | ], 2290 | "replace":"ই" 2291 | } 2292 | ] 2293 | }, 2294 | { 2295 | "find":"j", 2296 | "replace":"জ", 2297 | "rules":[ 2298 | 2299 | ] 2300 | }, 2301 | { 2302 | "find":"k", 2303 | "replace":"ক", 2304 | "rules":[ 2305 | 2306 | ] 2307 | }, 2308 | { 2309 | "find":"l", 2310 | "replace":"ল", 2311 | "rules":[ 2312 | 2313 | ] 2314 | }, 2315 | { 2316 | "find":"m", 2317 | "replace":"ম", 2318 | "rules":[ 2319 | 2320 | ] 2321 | }, 2322 | { 2323 | "find":"n", 2324 | "replace":"ন", 2325 | "rules":[ 2326 | 2327 | ] 2328 | }, 2329 | { 2330 | "find":"o", 2331 | "replace":"", 2332 | "rules":[ 2333 | { 2334 | "matches":[ 2335 | { 2336 | "scope":"vowel", 2337 | "type":"prefix" 2338 | }, 2339 | { 2340 | "scope":"!exact", 2341 | "type":"prefix", 2342 | "value":"o" 2343 | } 2344 | ], 2345 | "replace":"ও" 2346 | }, 2347 | { 2348 | "matches":[ 2349 | { 2350 | "scope":"vowel", 2351 | "type":"prefix" 2352 | }, 2353 | { 2354 | "scope":"exact", 2355 | "type":"prefix", 2356 | "value":"o" 2357 | } 2358 | ], 2359 | "replace":"অ" 2360 | }, 2361 | { 2362 | "matches":[ 2363 | { 2364 | "scope":"punctuation", 2365 | "type":"prefix" 2366 | } 2367 | ], 2368 | "replace":"অ" 2369 | } 2370 | ] 2371 | }, 2372 | { 2373 | "find":"p", 2374 | "replace":"প", 2375 | "rules":[ 2376 | 2377 | ] 2378 | }, 2379 | { 2380 | "find":"q", 2381 | "replace":"ক", 2382 | "rules":[ 2383 | 2384 | ] 2385 | }, 2386 | { 2387 | "find":"r", 2388 | "replace":"র", 2389 | "rules":[ 2390 | { 2391 | "matches":[ 2392 | { 2393 | "scope":"consonant", 2394 | "type":"prefix" 2395 | }, 2396 | { 2397 | "scope":"!exact", 2398 | "type":"prefix", 2399 | "value":"r" 2400 | }, 2401 | { 2402 | "scope":"!exact", 2403 | "type":"prefix", 2404 | "value":"y" 2405 | }, 2406 | { 2407 | "scope":"!exact", 2408 | "type":"prefix", 2409 | "value":"w" 2410 | }, 2411 | { 2412 | "scope":"!exact", 2413 | "type":"prefix", 2414 | "value":"x" 2415 | }, 2416 | { 2417 | "scope":"!exact", 2418 | "type":"prefix", 2419 | "value":"Z" 2420 | } 2421 | ], 2422 | "replace":"্র" 2423 | } 2424 | ] 2425 | }, 2426 | { 2427 | "find":"s", 2428 | "replace":"স", 2429 | "rules":[ 2430 | 2431 | ] 2432 | }, 2433 | { 2434 | "find":"t", 2435 | "replace":"ত", 2436 | "rules":[ 2437 | 2438 | ] 2439 | }, 2440 | { 2441 | "find":"u", 2442 | "replace":"ু", 2443 | "rules":[ 2444 | { 2445 | "matches":[ 2446 | { 2447 | "scope":"!consonant", 2448 | "type":"prefix" 2449 | }, 2450 | { 2451 | "scope":"!exact", 2452 | "type":"suffix", 2453 | "value":"`" 2454 | } 2455 | ], 2456 | "replace":"উ" 2457 | }, 2458 | { 2459 | "matches":[ 2460 | { 2461 | "scope":"punctuation", 2462 | "type":"prefix" 2463 | }, 2464 | { 2465 | "scope":"!exact", 2466 | "type":"suffix", 2467 | "value":"`" 2468 | } 2469 | ], 2470 | "replace":"উ" 2471 | } 2472 | ] 2473 | }, 2474 | { 2475 | "find":"v", 2476 | "replace":"ভ", 2477 | "rules":[ 2478 | 2479 | ] 2480 | }, 2481 | { 2482 | "find":"w", 2483 | "replace":"ও", 2484 | "rules":[ 2485 | { 2486 | "matches":[ 2487 | { 2488 | "scope":"punctuation", 2489 | "type":"prefix" 2490 | }, 2491 | { 2492 | "scope":"vowel", 2493 | "type":"suffix" 2494 | } 2495 | ], 2496 | "replace":"ওয়" 2497 | }, 2498 | { 2499 | "matches":[ 2500 | { 2501 | "scope":"consonant", 2502 | "type":"prefix" 2503 | } 2504 | ], 2505 | "replace":"্ব" 2506 | } 2507 | ] 2508 | }, 2509 | { 2510 | "find":"x", 2511 | "replace":"ক্স", 2512 | "rules":[ 2513 | { 2514 | "matches":[ 2515 | { 2516 | "scope":"punctuation", 2517 | "type":"prefix" 2518 | } 2519 | ], 2520 | "replace":"এক্স" 2521 | } 2522 | ] 2523 | }, 2524 | { 2525 | "find":"y", 2526 | "replace":"্য", 2527 | "rules":[ 2528 | { 2529 | "matches":[ 2530 | { 2531 | "scope":"!consonant", 2532 | "type":"prefix" 2533 | }, 2534 | { 2535 | "scope":"!punctuation", 2536 | "type":"prefix" 2537 | } 2538 | ], 2539 | "replace":"য়" 2540 | }, 2541 | { 2542 | "matches":[ 2543 | { 2544 | "scope":"punctuation", 2545 | "type":"prefix" 2546 | } 2547 | ], 2548 | "replace":"ইয়" 2549 | } 2550 | ] 2551 | }, 2552 | { 2553 | "find":"z", 2554 | "replace":"য", 2555 | "rules":[ 2556 | 2557 | ] 2558 | } 2559 | ], 2560 | "vowel":"aeiou" 2561 | } --------------------------------------------------------------------------------