{"id":32178304,"url":"https://github.com/mpcabd/python-arabic-reshaper","last_synced_at":"2025-10-21T20:53:15.504Z","repository":{"id":3248952,"uuid":"4286622","full_name":"mpcabd/python-arabic-reshaper","owner":"mpcabd","description":"Reconstruct Arabic sentences to be used in applications that don't support Arabic","archived":false,"fork":false,"pushed_at":"2025-05-12T11:45:31.000Z","size":153,"stargazers_count":428,"open_issues_count":19,"forks_count":84,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-10-19T16:00:04.100Z","etag":null,"topics":["arabic","python","reshape"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mpcabd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-05-10T15:57:45.000Z","updated_at":"2025-09-20T12:26:20.000Z","dependencies_parsed_at":"2023-02-12T02:45:14.465Z","dependency_job_id":null,"html_url":"https://github.com/mpcabd/python-arabic-reshaper","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/mpcabd/python-arabic-reshaper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpcabd%2Fpython-arabic-reshaper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpcabd%2Fpython-arabic-reshaper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpcabd%2Fpython-arabic-reshaper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpcabd%2Fpython-arabic-reshaper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpcabd","download_url":"https://codeload.github.com/mpcabd/python-arabic-reshaper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpcabd%2Fpython-arabic-reshaper/sbom","scorecard":{"id":662683,"data":{"date":"2025-08-11","repo":{"name":"github.com/mpcabd/python-arabic-reshaper","commit":"c12b08f36810639af4106f501ef712077490a3ea"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":2,"reason":"Found 8/30 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.1.1 not signed: https://api.github.com/repos/mpcabd/python-arabic-reshaper/releases/33468045","Warn: release artifact v2.1.1 does not have provenance: https://api.github.com/repos/mpcabd/python-arabic-reshaper/releases/33468045"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T16:41:10.272Z","repository_id":3248952,"created_at":"2025-08-21T16:41:10.272Z","updated_at":"2025-08-21T16:41:10.272Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280333492,"owners_count":26312845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-21T02:00:06.614Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arabic","python","reshape"],"created_at":"2025-10-21T20:53:11.438Z","updated_at":"2025-10-21T20:53:15.495Z","avatar_url":"https://github.com/mpcabd.png","language":"Python","readme":"## Python Arabic Reshaper\n\n[![Build Status](https://app.travis-ci.com/mpcabd/python-arabic-reshaper.svg?branch=master)](https://app.travis-ci.com/mpcabd/python-arabic-reshaper)\n\nReconstruct Arabic sentences to be used in applications that don't support\nArabic script.\n\nWorks with Python 3.x\n\n## Description\n\nArabic script is very special with two essential features:\n\n1. It is written from right to left.\n2. The characters change shape according to their surrounding characters.\n\nSo when you try to print text written in Arabic script in an application\n– or a library – that doesn’t support Arabic you’re pretty likely to end up\nwith something that looks like this:\n\n![Arabic text written from left to right with no reshaping](https://mpcabd.xyz/wp-content/uploads/2012/05/arabic-1.png)\n\nWe have two problems here, first, the characters are in the isolated form,\nwhich means that every character is rendered regardless of its surroundings,\nand second is that the text is written from left to right.\n\nTo solve the latter issue all we have to do is to use the\n[Unicode bidirectional algorithm](http://unicode.org/reports/tr9/), which is\nimplemented purely in Python in\n[python-bidi](https://github.com/MeirKriheli/python-bidi).\nIf you use it you’ll end up with something that looks like this:\n\n![Arabic text written from right to left with no reshaping](https://mpcabd.xyz/wp-content/uploads/2012/05/arabic-6.png)\n\nThe only issue left to solve is to reshape those characters and replace them\nwith their correct shapes according to their surroundings. Using this library\nhelps with the reshaping so we can get the proper result like this:\n\n![Arabic text written from right to left with reshaping](https://mpcabd.xyz/wp-content/uploads/2012/05/arabic-3.png)\n\n## Installation\n\n    pip install --upgrade arabic-reshaper\n\nIf you're using Anaconda you can use\n\n    conda install -c mpcabd arabic-reshaper\n\n## Usage\n\n```python\nimport arabic_reshaper\n\ntext_to_be_reshaped = 'اللغة العربية رائعة'\nreshaped_text = arabic_reshaper.reshape(text_to_be_reshaped)\n```\n\n### Example using PIL Image\n\nPIL Image does not support reshaping out of the box, so to draw Arabic text on an `Image` instance you would need to reshape\nthe text for sure.\n\nFor this example to work you need to run `pip install --upgrade arabic-reshaper python-bidi pillow`\n\n```python\n\nimport arabic_reshaper\n\ntext_to_be_reshaped = 'اللغة العربية رائعة'\nreshaped_text = arabic_reshaper.reshape(text_to_be_reshaped)\n\n# At this stage the text is reshaped, all letters are in their correct form\n# based on their surroundings, but if you are going to print the text in a\n# left-to-right context, which usually happens in libraries/apps that do not\n# support Arabic and/or right-to-left text rendering, then you need to use\n# get_display from python-bidi.\n# Note that this is optional and depends on your usage of the reshaped text.\n\nfrom bidi.algorithm import get_display\nbidi_text = get_display(reshaped_text)\n\n# At this stage the text in bidi_text can be easily rendered in any library\n# that doesn't support Arabic and/or right-to-left, so use it as you'd use\n# any other string. For example if you're using PIL.ImageDraw.text to draw\n# text over an image you'd just use it like this...\n\nfrom PIL import Image, ImageDraw, ImageFont\n\n# We load Arial since it's a well known font that supports Arabic Unicode\nfont = ImageFont.truetype('Arial', 40)\n\nimage = Image.new('RGBA', (800, 600), (255,255,255,0))\nimage_draw = ImageDraw.Draw(image)\nimage_draw.text((10,10), bidi_text, fill=(255,255,255,128), font=font)\n\n# Now the text is rendered properly on the image, you can save it to a file or just call `show` to see it working\nimage.show()\n\n# For more details on PIL.Image and PIL.ImageDraw check the documentation\n# See http://pillow.readthedocs.io/en/5.1.x/reference/ImageDraw.html?#PIL.ImageDraw.PIL.ImageDraw.Draw.text\n\n```\n\n## Settings\n\nYou can configure the reshaper to your preferences, it has the following\nsettings defined:\n\n* `language` (Default: `'Arabic'`): Ignored, the reshaper works with Arabic,\nFarsi, and Urdu, and most probably all other languages that use Arabic script.\n* `support_ligatures` (Default: `True`): When this is set to `False`, the\nreshaper will not replace any ligatures, otherwise it will replace enabled\nligatures.\n* `delete_harakat` (Default: `True`): When this is set to `False` the reshaper\nwill not delete the harakat from the text, this will result in them showing up\nin the reshaped text, you should enable this option if you are going to pass\nthe reshaped text to `bidi.algorithm.get_display` because it will reverse the\ntext and you'd end up with harakat applied to the next letter instead of the\nprevious letter.\n* `delete_tatweel` (Default `False`): When this is set to `True` the reshaper\nwill delete the Tatweel character (U+0640) from the text before reshaping, this\ncan be useful when you want to support ligatures and don't care about Tatweel\ngetting deleted.\n* `shift_harakat_position` (Default `False`): Whether to shift the Harakat\n(Tashkeel) one position so they appear correctly when string is reversed, this\nmight solve the problem of Tashkeel in some systems, although for `PIL.Image`\nfor example, this is not needed.\n* `support_zwj` (Default `True`): Whether to support ZWJ (`U+200D`) or not.\n* `use_unshaped_instead_of_isolated` (Default `False`): Use unshaped form\ninstead of isolated form, useful in some fonts that are missing the isolated\nform of letters.\n\nBesides the settings above, you can enable/disable supported ligatures. For a\nfull list of supported ligatures and their default status check the file\n[default-config.ini](https://github.com/mpcabd/python-arabic-reshaper/blob/32f7497aa24a68ab880d0248b21715928f0ce212/arabic_reshaper/default-config.ini).\n\nThere are multiple ways that you can configure the reshaper in, choose the one\nthat suits your deployment:\n\n### Via ArabicReshaper instance `configuration`\n\nInstead of directly using `arabic_reshaper.reshape` function, define an\ninstance of `arabic_reshaper.ArabicReshaper`, and pass your config dictionary\nto its constructor's `configuration` parameter like this:\n\n```python\nfrom arabic_reshaper import ArabicReshaper\nconfiguration = {\n    'delete_harakat': False,\n    'support_ligatures': True,\n    'RIAL SIGN': True,  # Replace ر ي ا ل with ﷼\n}\nreshaper = ArabicReshaper(configuration=configuration)\ntext_to_be_reshaped = 'سعر المنتج ١٥٠ ر' + 'يال'  # had to split the string for display\nreshaped_text = reshaper.reshape(text_to_be_reshaped)\n```\n\n### Via ArabicReshaper instance `configuration_file`\n\nYou can separte the configuration from your code, by copying the file\n[default-config.ini](default-config.ini) and change its settings,\nthen save it somewhere in your project, and then you can tell the reshaper\nto use your new config file, just pass the path to your config file to its\nconstructor's `configuration_file` parameter like this:\n\n```python\nfrom arabic_reshaper import ArabicReshaper\nreshaper = ArabicReshaper(configuration_file='/path/to/your/config.ini')\ntext_to_be_reshaped = 'سعر المنتج ١٥٠ ر' + 'يال'  # had to split the string for display\nreshaped_text = reshaper.reshape(text_to_be_reshaped)\n```\n\nWhere in you `config.ini` you can have something like this:\n\n```\n[ArabicReshaper]\ndelete_harakat = no\nsupport_ligatures = yes\nRIAL SIGN = yes\n```\n\n### Via `PYTHON_ARABIC_RESHAPER_CONFIGURATION_FILE` environment variable\n\nInstead of having to rewrite your old code to configure it like above, you can\ndefine an environment variable with the name\n`PYTHON_ARABIC_RESHAPER_CONFIGURATION_FILE` and in its value put the full path\nto the configuration file. This way the reshape function will pick it\nautomatically, and you won't have to change your old code.\n\n## Settings based on a TrueType® font\n\nIf you intend to render the text in a TrueType® font, you can tell the library\nto generate its configuration by reading the font file to figure out what's\nsupported in the font and what's not.\n\nTo use this feature you need to install the library with an extra option\n(not necessary when you install it with conda):\n\n    pip install --upgrade arabic-reshaper[with-fonttools]\n\nThen you can use the reshaper like this:\n\n```python\nimport arabic_reshaper\n\nreshaper = arabic_reshaper.ArabicReshaper(\n    arabic_reshaper.config_for_true_type_font(\n        '/path/to/true-type-font.ttf',\n        arabic_reshaper.ENABLE_ALL_LIGATURES\n    )\n)\n```\n\nThis will parse the font file, and figure out what ligatures it supports and enable them,\nas well as whether it has isolated forms or `use_unshaped_instead_of_isolated` should be\nenabled.\n\nThe second parameter to `config_for_true_type_font` can be one of\n\n- `ENABLE_NO_LIGATURES`\n- `ENABLE_SENTENCES_LIGATURES`\n- `ENABLE_WORDS_LIGATURES`\n- `ENABLE_LETTERS_LIGATURES`\n- `ENABLE_ALL_LIGATURES` (default)\n\nwhich controls what ligatures to look for, depending on your usage,\nsee [default-config.ini](default-config.ini) to know what ligatures are there.\n\n## Tashkeel/Harakat issue\n\n[Harakat or Tashkeel](http://en.wikipedia.org/wiki/Arabic_diacritics#Tashkil_.28marks_used_as_phonetic_guides.29)\nmight not show up properly in their correct place, depending on the application\nor the library that is doing the rendering for you, so you might want to enable\nthe `shift_harakat_position` option if you face this problem.\n\n## License\n\nThis work is licensed under\n[MIT License](https://opensource.org/licenses/MIT).\n\n## Demo\n\nOnline Arabic Reshaper: http://pydj.mpcabd.xyz/arabic-reshaper/\n\n## Download\n\nhttps://github.com/mpcabd/python-arabic-reshaper/tarball/master\n\n## Version History\n\n### 3.0.0\n* Stop supporting Python 2.7\n* Remove dependency on `future`. See #88.\n\n### 2.1.4\n\n* Fix unparseable version bound for `fonttools` under Python 2\n\n### 2.1.3\n\n* Remove dependency on `__version__.py` and `default-config.ini` files, as they were causing problems for people who package their apps using pyinstaller or buildozer.\n\n### 2.1.1\n\n* Fix a warning. See #57. Thanks @fbernhart\n\n### 2.1.0\n\n* Added support for settings based on a TrueType® font\n\n### 2.0.14\n\n* New option `use_unshaped_instead_of_isolated` to get around some fonts missing the isolated form for letters.\n\n### 2.0.13\n\n**BROKEN** please make sure not to use this version.\n\n### 2.0.12\n\n* Updated letters and ligatures\n* New option `shift_harakat_position` to try to get around the Tashkeel problem\n\n### 2.0.11\n\n* Proper support for ZWJ\n\n### 2.0.10\n\n* Fix Shadda ligatures\n\n### 2.0.9\n\n* Added support for ZWJ (Zero-width Joiner) (U+200D)\n\n### 2.0.8\n\n* Added `delete_tatweel`\n* Added more test cases\n\n### 2.0.7\n\n* Fix tests for Python 2.7\n\n### 2.0.6\n\n* Fixed a bug with Harakat breaking the reshaping\n* Wrote two small unit tests, more to come\n* Moved letters and ligatures to separate files for readability/maintainability\n* Moved package to its own folder for readability/maintainability\n\n### 2.0.5\n\nFix error message formatting\n\n### 2.0.4\n\nFix error message formatting\n\n### 2.0.3\n\nUse `Exception` instead of `Error`.\n\n### 2.0.2\n\nUse `pkg_resources.resource_filename` instead of depending on `__file__` to access `default-config.ini`.\n\n### 2.0.1\n\nInclude default-config.ini in setup.py\n\n### 2.0.0\n\n* Totally rewrote the code;\n* Faster and better performance;\n* Added the ability to configure and customise the reshaper.\n\n### 1.0.1\n\n* New glyphs for Farsi;\n* Added setup.py;\n* Bugfixes.\n\n### 1.0\n\n* Ported [Better Arabic Reshaper](https://github.com/agawish/Better-Arabic-Reshaper/)\nto Python.\n\n## Contact\n\nAbdullah Diab (mpcabd)\nEmail:  mpcabd@gmail.com\nBlog:   http://mpcabd.xyz\n\nFor more info visit my blog\n[post here](http://mpcabd.xyz/python-arabic-text-reshaper/)\n","funding_links":[],"categories":["Programming Languages"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpcabd%2Fpython-arabic-reshaper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpcabd%2Fpython-arabic-reshaper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpcabd%2Fpython-arabic-reshaper/lists"}