indic-language-utils 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. indic_language_utils-0.1.0/.env.example +4 -0
  2. indic_language_utils-0.1.0/.github/workflows/ci.yml +30 -0
  3. indic_language_utils-0.1.0/.github/workflows/publish.yml +31 -0
  4. indic_language_utils-0.1.0/.gitignore +10 -0
  5. indic_language_utils-0.1.0/.indic-language-utils.toml +31 -0
  6. indic_language_utils-0.1.0/.pre-commit-config.yaml +34 -0
  7. indic_language_utils-0.1.0/LICENSE +21 -0
  8. indic_language_utils-0.1.0/PKG-INFO +88 -0
  9. indic_language_utils-0.1.0/README.md +44 -0
  10. indic_language_utils-0.1.0/docs/adapter-author-guide.md +36 -0
  11. indic_language_utils-0.1.0/docs/configuration.md +187 -0
  12. indic_language_utils-0.1.0/docs/detection.md +325 -0
  13. indic_language_utils-0.1.0/docs/index.md +90 -0
  14. indic_language_utils-0.1.0/docs/processors.md +83 -0
  15. indic_language_utils-0.1.0/docs/translation.md +352 -0
  16. indic_language_utils-0.1.0/docs/user-guide.md +255 -0
  17. indic_language_utils-0.1.0/examples/langdetect/README.md +162 -0
  18. indic_language_utils-0.1.0/examples/langdetect/bhashini_demo.py +210 -0
  19. indic_language_utils-0.1.0/examples/langdetect/fasttext_demo.py +138 -0
  20. indic_language_utils-0.1.0/examples/langdetect/multi_service_demo.py +195 -0
  21. indic_language_utils-0.1.0/examples/translation/README.md +226 -0
  22. indic_language_utils-0.1.0/examples/translation/demo.py +116 -0
  23. indic_language_utils-0.1.0/examples/translation/googletrans_demo.py +124 -0
  24. indic_language_utils-0.1.0/mkdocs.yml +47 -0
  25. indic_language_utils-0.1.0/plans/architecture-proposal.md +387 -0
  26. indic_language_utils-0.1.0/pyproject.toml +67 -0
  27. indic_language_utils-0.1.0/src/indic_language_utils/__init__.py +178 -0
  28. indic_language_utils-0.1.0/src/indic_language_utils/cache.py +343 -0
  29. indic_language_utils-0.1.0/src/indic_language_utils/concurrency.py +30 -0
  30. indic_language_utils-0.1.0/src/indic_language_utils/config.py +389 -0
  31. indic_language_utils-0.1.0/src/indic_language_utils/detection/__init__.py +52 -0
  32. indic_language_utils-0.1.0/src/indic_language_utils/detection/bhashini_detect.py +202 -0
  33. indic_language_utils-0.1.0/src/indic_language_utils/detection/cache.py +171 -0
  34. indic_language_utils-0.1.0/src/indic_language_utils/detection/client.py +292 -0
  35. indic_language_utils-0.1.0/src/indic_language_utils/detection/fasttext.py +198 -0
  36. indic_language_utils-0.1.0/src/indic_language_utils/detection/helpers.py +178 -0
  37. indic_language_utils-0.1.0/src/indic_language_utils/detection/models.py +99 -0
  38. indic_language_utils-0.1.0/src/indic_language_utils/detection/protocols.py +19 -0
  39. indic_language_utils-0.1.0/src/indic_language_utils/detection/sync.py +93 -0
  40. indic_language_utils-0.1.0/src/indic_language_utils/errors.py +94 -0
  41. indic_language_utils-0.1.0/src/indic_language_utils/languages.py +138 -0
  42. indic_language_utils-0.1.0/src/indic_language_utils/models.py +75 -0
  43. indic_language_utils-0.1.0/src/indic_language_utils/processors.py +21 -0
  44. indic_language_utils-0.1.0/src/indic_language_utils/providers/__init__.py +29 -0
  45. indic_language_utils-0.1.0/src/indic_language_utils/providers/base.py +119 -0
  46. indic_language_utils-0.1.0/src/indic_language_utils/providers/bhashini.py +292 -0
  47. indic_language_utils-0.1.0/src/indic_language_utils/py.typed +0 -0
  48. indic_language_utils-0.1.0/src/indic_language_utils/retry.py +62 -0
  49. indic_language_utils-0.1.0/src/indic_language_utils/routing.py +70 -0
  50. indic_language_utils-0.1.0/src/indic_language_utils/telemetry.py +62 -0
  51. indic_language_utils-0.1.0/src/indic_language_utils/timing.py +32 -0
  52. indic_language_utils-0.1.0/src/indic_language_utils/translation/__init__.py +78 -0
  53. indic_language_utils-0.1.0/src/indic_language_utils/translation/bhashini_translate.py +206 -0
  54. indic_language_utils-0.1.0/src/indic_language_utils/translation/cache.py +142 -0
  55. indic_language_utils-0.1.0/src/indic_language_utils/translation/catalog.py +59 -0
  56. indic_language_utils-0.1.0/src/indic_language_utils/translation/client.py +418 -0
  57. indic_language_utils-0.1.0/src/indic_language_utils/translation/google_translate.py +419 -0
  58. indic_language_utils-0.1.0/src/indic_language_utils/translation/helpers.py +220 -0
  59. indic_language_utils-0.1.0/src/indic_language_utils/translation/models.py +95 -0
  60. indic_language_utils-0.1.0/src/indic_language_utils/translation/processing.py +290 -0
  61. indic_language_utils-0.1.0/src/indic_language_utils/translation/protocols.py +22 -0
  62. indic_language_utils-0.1.0/src/indic_language_utils/translation/sync.py +119 -0
  63. indic_language_utils-0.1.0/tests/__init__.py +0 -0
  64. indic_language_utils-0.1.0/tests/provider_contract.py +39 -0
  65. indic_language_utils-0.1.0/tests/support.py +36 -0
  66. indic_language_utils-0.1.0/tests/test_bhashini.py +244 -0
  67. indic_language_utils-0.1.0/tests/test_bhashini_detection.py +230 -0
  68. indic_language_utils-0.1.0/tests/test_cache.py +93 -0
  69. indic_language_utils-0.1.0/tests/test_config_telemetry_errors.py +39 -0
  70. indic_language_utils-0.1.0/tests/test_detection_cache.py +131 -0
  71. indic_language_utils-0.1.0/tests/test_detection_client.py +180 -0
  72. indic_language_utils-0.1.0/tests/test_detection_helpers.py +52 -0
  73. indic_language_utils-0.1.0/tests/test_detection_sync.py +58 -0
  74. indic_language_utils-0.1.0/tests/test_fasttext_detection.py +141 -0
  75. indic_language_utils-0.1.0/tests/test_file_config.py +187 -0
  76. indic_language_utils-0.1.0/tests/test_google_translate.py +373 -0
  77. indic_language_utils-0.1.0/tests/test_languages.py +25 -0
  78. indic_language_utils-0.1.0/tests/test_providers_routing.py +78 -0
  79. indic_language_utils-0.1.0/tests/test_retry_concurrency.py +93 -0
  80. indic_language_utils-0.1.0/tests/test_sqlite_cache.py +96 -0
  81. indic_language_utils-0.1.0/tests/test_translation_client.py +183 -0
  82. indic_language_utils-0.1.0/tests/test_translation_helpers.py +161 -0
  83. indic_language_utils-0.1.0/tests/test_translation_persistent_cache.py +87 -0
  84. indic_language_utils-0.1.0/tests/test_translation_processing.py +84 -0
  85. indic_language_utils-0.1.0/tests/test_translation_sync.py +37 -0
  86. indic_language_utils-0.1.0/tests/translation_support.py +82 -0
  87. indic_language_utils-0.1.0/uv.lock +933 -0
@@ -0,0 +1,4 @@
1
+ # Bhashini inference API credentials (required for live tests and translation)
2
+ BHASHINI_API_KEY="your-bhashini-api-key-here"
3
+ BHASHINI_ENDPOINT_URL="https://dhruva-api.bhashini.gov.in/services/inference/pipeline"
4
+ BHASHINI_TRANSLATION_SERVICE_ID="ai4bharat/indictrans-v2-all-gpu--t4"
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ python-version: ["3.11", "3.12"]
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: astral-sh/setup-uv@v6
16
+ with:
17
+ python-version: ${{ matrix.python-version }}
18
+ - run: uv sync --locked --dev
19
+ - run: uv run ruff format --check .
20
+ - run: uv run ruff check .
21
+ - run: uv run mypy
22
+ - run: uv run pytest
23
+ - run: uv build
24
+ - name: Test the built wheel
25
+ run: |
26
+ wheel_venv="$(mktemp -d)/venv"
27
+ uv venv "$wheel_venv"
28
+ uv pip install --python "$wheel_venv/bin/python" dist/*.whl
29
+ cd /tmp
30
+ "$wheel_venv/bin/python" -c 'import indic_language_utils; assert indic_language_utils.__version__ == "0.1.0"'
@@ -0,0 +1,31 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ pypi-publish:
10
+ name: Publish to PyPI
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/indic-language-utils
15
+ permissions:
16
+ id-token: write
17
+ contents: read
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v6
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Build package distributions
28
+ run: uv build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,10 @@
1
+ .venv/
2
+ .mypy_cache/
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ __pycache__/
6
+ *.py[cod]
7
+ dist/
8
+ site/
9
+ .env
10
+ .cache/
@@ -0,0 +1,31 @@
1
+ [cache]
2
+ enabled = true
3
+ backend = "sqlite"
4
+ path = ".cache/translations.sqlite3"
5
+ namespace = "language-utils"
6
+ max_entries = 50000
7
+ ttl_seconds = 86400
8
+
9
+ [retry]
10
+ max_attempts = 3
11
+ base_delay_seconds = 0.5
12
+ max_delay_seconds = 2.0
13
+
14
+ [telemetry]
15
+ logging_enabled = true
16
+ metrics_enabled = true
17
+ traces_enabled = true
18
+ include_content = false
19
+
20
+ [providers.bhashini]
21
+ endpoint = "https://dhruva-api.bhashini.gov.in/services/inference/pipeline"
22
+ translation_service_id = "ai4bharat/indictrans-v2-all-gpu--t4"
23
+ timeout_seconds = 20.0
24
+ max_concurrency = 8
25
+
26
+ [providers.googletrans]
27
+ timeout_seconds = 20.0
28
+ max_concurrency = 4
29
+
30
+ [routes]
31
+ translation = ["bhashini", "googletrans"]
@@ -0,0 +1,34 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ args: [--unsafe]
9
+ - id: check-toml
10
+ - id: check-added-large-files
11
+ args: [--maxkb=5120]
12
+
13
+ - repo: local
14
+ hooks:
15
+ - id: ruff-format
16
+ name: ruff format
17
+ entry: uv run ruff format
18
+ language: system
19
+ types_or: [python, markdown]
20
+ require_serial: true
21
+
22
+ - id: ruff-check
23
+ name: ruff check
24
+ entry: uv run ruff check --fix
25
+ language: system
26
+ types: [python]
27
+ require_serial: true
28
+
29
+ - id: mypy
30
+ name: mypy
31
+ entry: uv run mypy
32
+ language: system
33
+ types: [python]
34
+ pass_filenames: false
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Harikesh Kushwaha contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.5
2
+ Name: indic-language-utils
3
+ Version: 0.1.0
4
+ Summary: Provider-neutral foundations for Indian language applications
5
+ Project-URL: Documentation, https://github.com/indic-language-utils/indic-language-utils
6
+ Project-URL: Source, https://github.com/indic-language-utils/indic-language-utils
7
+ Author: indic-language-utils contributors
8
+ License: MIT License
9
+
10
+ Copyright (c) 2026 Harikesh Kushwaha contributors
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENSE
30
+ Keywords: indic,language,speech,translation
31
+ Classifier: Development Status :: 2 - Pre-Alpha
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Programming Language :: Python :: 3
34
+ Classifier: Programming Language :: Python :: 3.11
35
+ Classifier: Programming Language :: Python :: 3.12
36
+ Classifier: Typing :: Typed
37
+ Requires-Python: <3.13,>=3.11
38
+ Requires-Dist: httpx<1,>=0.28
39
+ Provides-Extra: googletrans
40
+ Requires-Dist: googletrans>=4.0.2; extra == 'googletrans'
41
+ Provides-Extra: local-tld
42
+ Requires-Dist: fasttext-langdetect>=1.1.1; extra == 'local-tld'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # indic-language-utils
46
+
47
+ A Python 3.11 and 3.12 library for Indian-language translation, text language detection, transliteration, speech-to-text, and text-to-speech. The project uses `uv` and will be published on PyPI as `indic-language-utils`. Its Python import is `indic_language_utils`. The code is licensed under the MIT License.
48
+
49
+ Phase 0 implements the shared library foundation, Phase 1 adds structured translation with Bhashini and Google Translate adapters, and Phase 2 adds text language detection with local FastText and cloud Bhashini adapters. Runtime caching can use bounded process memory or persistent SQLite storage. The architecture and ecosystem review is in [plans/architecture-proposal.md](plans/architecture-proposal.md).
50
+
51
+ The intended shape is a small core with optional provider packages. Applications should be able to start with local or low-cost providers during a proof of concept, then change routing configuration for production without rewriting text and audio handling.
52
+
53
+ Work will be delivered in this order:
54
+
55
+ - shared library foundation
56
+ - text translation
57
+ - text language detection, abbreviated as TLD
58
+ - transliteration
59
+ - non-streaming speech-to-text, abbreviated as STT
60
+ - non-streaming text-to-speech, abbreviated as TTS
61
+
62
+ Provider work starts with Bhashini and then Sarvam. Unofficial Google or Microsoft adapters can be added later as opt-in extras or external plugins. Optional dependency groups will keep translation-only installations free of speech and audio dependencies.
63
+
64
+ Cross-cutting requirements include structured-text preservation, bounded concurrency, retries, routing and fallback, versioned terminology, caching, logging, metrics, and explicit data-retention controls.
65
+
66
+ ## Development
67
+
68
+ Install the locked development environment with `uv sync --dev`. The usual checks are:
69
+
70
+ ```console
71
+ uv run pre-commit install
72
+ uv run ruff format .
73
+ uv run ruff check .
74
+ uv run mypy
75
+ uv run pytest
76
+ uv build
77
+ uv run mkdocs serve
78
+ uv run mkdocs build
79
+ ```
80
+
81
+ The runtime uses HTTPX for Bhashini's reusable asynchronous HTTP client. For usage and guides, see:
82
+
83
+ - [docs/user-guide.md](docs/user-guide.md) for system capabilities and getting started
84
+ - [docs/translation.md](docs/translation.md) for translation features and examples
85
+ - [docs/detection.md](docs/detection.md) for text language and script detection
86
+ - [docs/configuration.md](docs/configuration.md) for TOML and environment loading
87
+ - [docs/processors.md](docs/processors.md) for processor composition and markdown protection
88
+ - [docs/adapter-author-guide.md](docs/adapter-author-guide.md) for provider integration
@@ -0,0 +1,44 @@
1
+ # indic-language-utils
2
+
3
+ A Python 3.11 and 3.12 library for Indian-language translation, text language detection, transliteration, speech-to-text, and text-to-speech. The project uses `uv` and will be published on PyPI as `indic-language-utils`. Its Python import is `indic_language_utils`. The code is licensed under the MIT License.
4
+
5
+ Phase 0 implements the shared library foundation, Phase 1 adds structured translation with Bhashini and Google Translate adapters, and Phase 2 adds text language detection with local FastText and cloud Bhashini adapters. Runtime caching can use bounded process memory or persistent SQLite storage. The architecture and ecosystem review is in [plans/architecture-proposal.md](plans/architecture-proposal.md).
6
+
7
+ The intended shape is a small core with optional provider packages. Applications should be able to start with local or low-cost providers during a proof of concept, then change routing configuration for production without rewriting text and audio handling.
8
+
9
+ Work will be delivered in this order:
10
+
11
+ - shared library foundation
12
+ - text translation
13
+ - text language detection, abbreviated as TLD
14
+ - transliteration
15
+ - non-streaming speech-to-text, abbreviated as STT
16
+ - non-streaming text-to-speech, abbreviated as TTS
17
+
18
+ Provider work starts with Bhashini and then Sarvam. Unofficial Google or Microsoft adapters can be added later as opt-in extras or external plugins. Optional dependency groups will keep translation-only installations free of speech and audio dependencies.
19
+
20
+ Cross-cutting requirements include structured-text preservation, bounded concurrency, retries, routing and fallback, versioned terminology, caching, logging, metrics, and explicit data-retention controls.
21
+
22
+ ## Development
23
+
24
+ Install the locked development environment with `uv sync --dev`. The usual checks are:
25
+
26
+ ```console
27
+ uv run pre-commit install
28
+ uv run ruff format .
29
+ uv run ruff check .
30
+ uv run mypy
31
+ uv run pytest
32
+ uv build
33
+ uv run mkdocs serve
34
+ uv run mkdocs build
35
+ ```
36
+
37
+ The runtime uses HTTPX for Bhashini's reusable asynchronous HTTP client. For usage and guides, see:
38
+
39
+ - [docs/user-guide.md](docs/user-guide.md) for system capabilities and getting started
40
+ - [docs/translation.md](docs/translation.md) for translation features and examples
41
+ - [docs/detection.md](docs/detection.md) for text language and script detection
42
+ - [docs/configuration.md](docs/configuration.md) for TOML and environment loading
43
+ - [docs/processors.md](docs/processors.md) for processor composition and markdown protection
44
+ - [docs/adapter-author-guide.md](docs/adapter-author-guide.md) for provider integration
@@ -0,0 +1,36 @@
1
+ # Adapter author guide
2
+
3
+ An adapter is an object with a `ProviderIdentity` and a tuple of `CapabilityDeclaration` values. It implements only its concrete capability protocol. There is no shared provider base class.
4
+
5
+ Register an adapter explicitly with `ProviderRegistry.register`. Declare canonical `LanguageTag` values, supported pairs, required features, and named limits. Do not place provider-specific language codes in public models. Convert them inside the adapter.
6
+
7
+ Adapters that own reusable clients implement `start()` and `close()`. `ResourceManager` starts resources in order, closes them in reverse order, and supports `async with`.
8
+
9
+ Map provider failures to the matching exception in `indic_language_utils.errors`. Exception messages and structured fields must not contain request content, credentials, headers, or raw provider responses. Mark only rate limits, timeouts, and temporary provider failures as retryable.
10
+
11
+ This illustrative provider declares a fake operation. It is not a supported language capability:
12
+
13
+ ```python
14
+ from dataclasses import dataclass
15
+
16
+ from indic_language_utils.models import ProviderIdentity
17
+ from indic_language_utils.providers import CapabilityDeclaration, CapabilityId, ProviderRegistry
18
+
19
+
20
+ @dataclass
21
+ class ExampleProvider:
22
+ identity = ProviderIdentity("example")
23
+ capabilities = (CapabilityDeclaration(CapabilityId.TRANSLATION),)
24
+
25
+ async def start(self) -> None:
26
+ pass
27
+
28
+ async def close(self) -> None:
29
+ pass
30
+
31
+
32
+ registry = ProviderRegistry()
33
+ registry.register(ExampleProvider())
34
+ ```
35
+
36
+ Real translation models and provider methods arrive in Phase 1.
@@ -0,0 +1,187 @@
1
+ # Configuration
2
+
3
+ The library uses a tiered configuration system combining TOML project files, user configurations, environment variables, and programmatic overrides. Settings are validated strictly on load; unknown keys or invalid data types raise a `ConfigurationError`.
4
+
5
+ ## Configuration Precedence
6
+
7
+ `Settings.load()` evaluates configuration sources in the following order, from lowest to highest precedence:
8
+
9
+ - Library defaults
10
+ - User configuration at `~/.config/indic-language-utils/config.toml` (or `$XDG_CONFIG_HOME/indic-language-utils/config.toml`)
11
+ - The nearest `.indic-language-utils.toml` found by walking upward from the current working directory
12
+ - An explicit configuration file specified via `Settings.load(path=...)` or the `ILU_CONFIG_FILE` environment variable
13
+ - Environment variables (`ILU_*`, `BHASHINI_*`, and `TRANSLATION_SERVICE_PROVIDER`)
14
+ - Programmatic overrides passed via `Settings.load(overrides=...)`
15
+
16
+ Only existing discovered files are merged. If an explicit configuration path is provided, that file must exist.
17
+
18
+ ## Project Configuration File
19
+
20
+ A project configuration file (`.indic-language-utils.toml`) can be placed at the root of a project repository. The following example illustrates all supported configuration sections:
21
+
22
+ ```toml
23
+ [cache]
24
+ enabled = true
25
+ backend = "sqlite"
26
+ path = ".cache/translations.sqlite3"
27
+ namespace = "my-application"
28
+ max_entries = 50000
29
+ ttl_seconds = 86400
30
+
31
+ [retry]
32
+ max_attempts = 3
33
+ base_delay_seconds = 0.25
34
+ max_delay_seconds = 5.0
35
+
36
+ [telemetry]
37
+ logging_enabled = true
38
+ metrics_enabled = true
39
+ traces_enabled = true
40
+ include_content = false
41
+
42
+ [providers.bhashini]
43
+ endpoint = "https://dhruva-api.bhashini.gov.in/services/inference/pipeline"
44
+ translation_service_id = "default-translation-model-id"
45
+ detection_service_id = "default-tld-model-id"
46
+ timeout_seconds = 20.0
47
+ max_concurrency = 8
48
+
49
+ [providers.bhashini.translation_service_ids]
50
+ "hi-IN" = "service-for-any-source-to-hindi"
51
+ "en-IN>ta-IN" = "service-for-english-to-tamil"
52
+
53
+ [providers.googletrans]
54
+ timeout_seconds = 20.0
55
+ max_concurrency = 4
56
+
57
+ [routes]
58
+ translation = ["bhashini", "googletrans"]
59
+ text_language_detection = ["bhashini", "fasttext"]
60
+ ```
61
+
62
+ Relative cache paths resolve relative to the current working directory of the process. In production containers or multi-directory environments, specify an absolute path.
63
+
64
+ ## Secrets and Environment Variables
65
+
66
+ TOML files are strictly prohibited from storing credentials, passwords, tokens, or API keys. Attempting to define fields containing sensitive terms (such as `api_key`, `token`, `secret`, or `password`) raises a `ConfigurationError`.
67
+
68
+ All sensitive values must be supplied via environment variables.
69
+
70
+ ### Provider Credentials and Overrides
71
+
72
+ Bhashini credentials and service endpoints:
73
+
74
+ ```console
75
+ # Required for Bhashini live API calls
76
+ export BHASHINI_API_KEY="your-bhashini-api-key"
77
+
78
+ # Optional overrides for endpoints and service IDs
79
+ export BHASHINI_ENDPOINT_URL="https://dhruva-api.bhashini.gov.in/services/inference/pipeline"
80
+ export BHASHINI_TRANSLATION_SERVICE_ID="your-translation-service-id"
81
+ export BHASHINI_DETECTION_SERVICE_ID="your-tld-service-id"
82
+ export BHASHINI_TIMEOUT_SECONDS="20"
83
+ export BHASHINI_MAX_CONCURRENCY="8"
84
+ ```
85
+
86
+ To quickly select an active translation provider during development without editing configuration files:
87
+
88
+ ```console
89
+ export TRANSLATION_SERVICE_PROVIDER="googletrans"
90
+ ```
91
+
92
+ ### Shared System Settings
93
+
94
+ Global cache, retry, telemetry, and routing settings use the `ILU_` prefix:
95
+
96
+ ```console
97
+ # Caching settings
98
+ export ILU_CACHE_ENABLED="true"
99
+ export ILU_CACHE_BACKEND="sqlite"
100
+ export ILU_CACHE_PATH="/var/lib/indic-language-utils/cache.sqlite3"
101
+ export ILU_CACHE_NAMESPACE="my-app"
102
+ export ILU_CACHE_MAX_ENTRIES="50000"
103
+ export ILU_CACHE_TTL_SECONDS="86400"
104
+
105
+ # Retry settings
106
+ export ILU_RETRY_MAX_ATTEMPTS="3"
107
+ export ILU_RETRY_BASE_DELAY_SECONDS="0.25"
108
+ export ILU_RETRY_MAX_DELAY_SECONDS="5.0"
109
+
110
+ # Telemetry settings
111
+ export ILU_LOGGING_ENABLED="true"
112
+ export ILU_METRICS_ENABLED="true"
113
+ export ILU_TRACES_ENABLED="true"
114
+ export ILU_TELEMETRY_INCLUDE_CONTENT="false"
115
+
116
+ # Route overrides (comma-separated provider names in priority order)
117
+ export ILU_ROUTE_TRANSLATION="bhashini,googletrans"
118
+ export ILU_ROUTE_TEXT_LANGUAGE_DETECTION="bhashini,fasttext"
119
+ ```
120
+
121
+ ## Programmatic Loading and Overrides
122
+
123
+ ### Automatic Discovery
124
+
125
+ The easiest way to initialize a client is via the built-in factories, which call `Settings.load()` automatically:
126
+
127
+ ```python
128
+ from indic_language_utils import get_translation_client
129
+
130
+ # Automatically reads .indic-language-utils.toml and environment variables
131
+ client = get_translation_client()
132
+ ```
133
+
134
+ ### Explicit Settings Loading
135
+
136
+ For granular control over settings loading:
137
+
138
+ ```python
139
+ from pathlib import Path
140
+ from indic_language_utils import Settings
141
+
142
+ # Load settings from a specific TOML file
143
+ settings = Settings.load(path=Path("/etc/indic-language-utils/production.toml"))
144
+
145
+ # Load settings with test overrides
146
+ test_settings = Settings.load(
147
+ overrides={
148
+ "cache": {"enabled": False},
149
+ "retry": {"max_attempts": 1},
150
+ }
151
+ )
152
+ ```
153
+
154
+ ### Building Custom Clients from Settings
155
+
156
+ Assemble a client pipeline explicitly using loaded settings:
157
+
158
+ ```python
159
+ from indic_language_utils import (
160
+ BhashiniConfig,
161
+ BhashiniTranslationProvider,
162
+ CacheKeyBuilder,
163
+ CapabilityId,
164
+ GoogleTranslateProvider,
165
+ OrderedRouter,
166
+ ProviderRegistry,
167
+ Settings,
168
+ TranslationClient,
169
+ create_translation_cache,
170
+ )
171
+
172
+ settings = Settings.load()
173
+
174
+ registry = ProviderRegistry()
175
+ if "bhashini" in settings.providers:
176
+ registry.register(BhashiniTranslationProvider(BhashiniConfig.from_settings(settings)))
177
+ registry.register(GoogleTranslateProvider())
178
+
179
+ route = settings.routes.get("translation", ("bhashini", "googletrans"))
180
+ router = OrderedRouter(registry, {CapabilityId.TRANSLATION: route})
181
+
182
+ client = TranslationClient(
183
+ router=router,
184
+ cache=create_translation_cache(settings.cache),
185
+ cache_keys=CacheKeyBuilder(settings.cache.namespace),
186
+ )
187
+ ```