Skip to content

Commit c5d4a4f

Browse files
committed
Created sys-lang pkg
1 parent cf469b8 commit c5d4a4f

139 files changed

Lines changed: 2908 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ updates:
2222
- /project-markers
2323
- /prose-languages
2424
- /remove-json-keys
25+
- /sys-lang
2526
- /translate-messages
2627
schedule:
2728
interval: daily

docs/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@
141141
[CLI usage](https://github.com/adamlui/python-utils/tree/main/remove-json-keys/#usage) /
142142
[Discuss](https://github.com/adamlui/python-utils/discussions)
143143

144+
### <a href="https://github.com/adamlui/python-utils/tree/main/sys-lang/#readme">🗺 sys-lang</a>
145+
146+
> Detect the system language.
147+
<br>[Install](https://github.com/adamlui/python-utils/tree/main/sys-lang/#-installation) /
148+
[Readme](https://github.com/adamlui/python-utils/tree/main/sys-lang/#readme) /
149+
[API usage](https://github.com/adamlui/python-utils/tree/main/sys-lang/#-api-usage) /
150+
[CLI usage](https://github.com/adamlui/python-utils/tree/main/sys-lang/-command-line-usage) /
151+
[Discuss](https://github.com/adamlui/python-utils/discussions)
152+
144153
### <a href="https://github.com/adamlui/python-utils/tree/main/translate-messages/#readme">🌍 translate-messages</a>
145154

146155
> Translate `en/messages.json` (chrome.i18n format) to 100+ locales automatically.

sys-lang/docs/LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# 🏛️ MIT License
2+
3+
**Copyright © 2026 [Adam Lui](https://github.com/adamlui)**
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.

sys-lang/docs/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<a id="top"></a>
2+
3+
# > sys-lang
4+
5+
<a href="https://github.com/adamlui/python-utils/releases/tag/sys-lang-1.0.0">
6+
<img height=31 src="https://img.shields.io/badge/Latest_Build-1.0.0-32fcee.svg?logo=icinga&logoColor=white&labelColor=464646&style=for-the-badge"></a>
7+
<a href="https://github.com/adamlui/python-utils/blob/main/sys-lang/docs/LICENSE.md">
8+
<img height=31 src="https://img.shields.io/badge/License-MIT-f99b27.svg?logo=internetarchive&logoColor=white&labelColor=464646&style=for-the-badge"></a>
9+
<a href="https://www.codefactor.io/repository/github/adamlui/python-utils">
10+
<img height=31 src="https://img.shields.io/codefactor/grade/github/adamlui/python-utils?label=Code+Quality&logo=codefactor&logoColor=white&labelColor=464646&color=a0fc55&style=for-the-badge"></a>
11+
<a href="https://sonarcloud.io/component_measures?metric=vulnerabilities&selected=adamlui_python-utils%3Asys-lang&id=adamlui_python-utils">
12+
<img height=31 src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fsonarcloud.io%2Fapi%2Fmeasures%2Fcomponent%3Fcomponent%3Dadamlui_python-utils%26metricKeys%3Dvulnerabilities&query=%24.component.measures.0.value&style=for-the-badge&logo=sonar&logoColor=white&labelColor=464646&label=Vulnerabilities&color=fafc74"></a>
13+
14+
> ### _Detect the system language._
15+
16+
Returns ISO 639-1 (e.g. `en`) or ISO 3166-1 alpha-2-appended (`en_US`) code for user's preferred language. On Windows, queries `Get-Culture` via PowerShell. On *nix systems, reads `LC_ALL`, `LC_MESSAGES`, `LANG`, and `LANGUAGE`.
17+
18+
## ⚡ Installation
19+
20+
```bash
21+
pip install sys-lang
22+
```
23+
24+
## 💻 Command line usage
25+
26+
```bash
27+
sys-lang # or syslang
28+
# e.g. => 'en_US'
29+
```
30+
31+
CLI options:
32+
33+
| Option | Description
34+
| ------------------- | ------------------------------------
35+
| `-n`, `--no-region` | Don't include region when available
36+
| `-h`, `--help` | Show help screen
37+
| `-v`, `--version` | Show version
38+
| `--docs` | Open docs URL
39+
40+
## 🔌 API usage
41+
42+
```py
43+
from sys_lang import get_sys_lang
44+
45+
print(get_sys_lang()) # e.g. => 'zh_HK'
46+
print(get_sys_lang(region=False)) # e.g. => 'zh'
47+
```
48+
49+
## MIT License
50+
51+
Copyright © 2026 [Adam Lui](https://github.com/adamlui)
52+
53+
## Related
54+
55+
🇪🇸 [latin-locales](https://github.com/adamlui/python-utils/tree/main/latin-locales/#readme) - ISO 639-1 (2-letter) codes for Latin locales.
56+
<br>🇨🇳 [non-latin-locales](https://github.com/adamlui/python-utils/tree/main/non-latin-locales/#readme) - ISO 639-1 (2-letter) codes for non-Latin locales.
57+
<br>🌍 [translate-messages](https://github.com/adamlui/python-utils/tree/main/translate-messages/#readme) - Translate `en/messages.json` (chrome.i18n format) to 100+ locales automatically.
58+
<br>🈶 [is-unicode-supported](https://github.com/adamlui/python-utils/tree/main/is-unicode-supported/#readme) - Detect whether the terminal supports advanced Unicode.
59+
60+
#
61+
62+
<picture><source media="(prefers-color-scheme: dark)" srcset="https://cdn.jsdelivr.net/gh/adamlui/python-utils@760599e/assets/images/icons/home/white/icon32x27.png"><img height=13 src="https://cdn.jsdelivr.net/gh/adamlui/python-utils@760599e/assets/images/icons/home/dark-gray/icon32x27.png"></picture> <a href=https://github.com/adamlui/python-utils/#readme>**More Python utilities**</a> /
63+
<a href="#top">Back to top ↑</a>
64+

sys-lang/docs/SECURITY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 🛡️ Security Policy
2+
3+
If you find a vulnerability, please e-mail security@tidelift.com and a fix will be coordinated within 2 business days.

sys-lang/noxfile.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from pathlib import Path
2+
from types import SimpleNamespace as sn
3+
4+
import nox
5+
6+
pkg = sn(dir=Path(__file__).parent.name)
7+
pkg.name = pkg.dir.replace('-', '_')
8+
paths = sn(utils=sn(bump='utils/bump.py', clean='utils/clean.py', publish='utils/publish.sh'))
9+
10+
def session(func) : return nox.session(venv_backend='none', name=func.__name__.replace('_', '-'))(func)
11+
12+
@session
13+
def dev(session) : session.run('pip', 'install', '-e', '.') ; session.run(pkg.dir, '--help', *session.posargs)
14+
@session
15+
def debug(session) : session.run('py', '-m', pkg.name, '--debug', *session.posargs, env={ 'PYTHONPATH': 'src' })
16+
17+
@session
18+
def lint(session): # staged project files
19+
files = session.run('git', 'diff', '--cached', '--name-only', '--relative', silent=True, log=False).splitlines()
20+
if files : session.run('pre-commit', 'run', '--files', *files, *session.posargs)
21+
@session
22+
def lint_all(session): # all project files
23+
files = session.run('git', 'ls-files', '.', silent=True, log=False).splitlines()
24+
session.run('pre-commit', 'run', '--files', *files, *session.posargs)
25+
26+
bump_cmd_args = ('py', paths.utils.bump)
27+
@session
28+
def bump_patch(session, no_push=True):
29+
cmd_args = bump_cmd_args + ('--patch',)
30+
if no_push : cmd_args += ('--no-push',)
31+
session.run(*cmd_args, *session.posargs)
32+
@session
33+
def bump_minor(session, no_push=True):
34+
cmd_args = bump_cmd_args + ('--minor',)
35+
if no_push : cmd_args += ('--no-push',)
36+
session.run(*cmd_args, *session.posargs)
37+
@session
38+
def bump_feat(session, no_push=True):
39+
bump_minor(session, no_push)
40+
@session
41+
def bump_major(session, no_push=True):
42+
cmd_args = bump_cmd_args + ('--major',)
43+
if no_push : cmd_args += ('--no-push',)
44+
session.run(*cmd_args, *session.posargs)
45+
46+
@session
47+
def build(session) : clean(session) ; session.run('py', '-m', 'build') ; print('Build complete!')
48+
@session
49+
def publish(session) : session.run('bash', paths.utils.publish, *session.posargs)
50+
51+
@session
52+
def deploy_patch(session) : bump_patch(session, no_push=False) ; build(session) ; publish(session)
53+
@session
54+
def deploy_minor(session) : bump_minor(session, no_push=False) ; build(session) ; publish(session)
55+
@session
56+
def deploy_feat(session) : deploy_minor(session)
57+
@session
58+
def deploy_major(session) : bump_major(session, no_push=False) ; build(session) ; publish(session)
59+
60+
@session
61+
def clean(session, *args) : session.run('py', paths.utils.clean, *args)

sys-lang/pyproject.toml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
[build-system]
2+
requires = [
3+
"setuptools>=82.0.0,<83",
4+
"wheel",
5+
]
6+
build-backend = "setuptools.build_meta"
7+
8+
[project]
9+
name = "sys-lang"
10+
version = "1.0.0"
11+
description = "Detect the system language."
12+
authors = [
13+
{ name = "Adam Lui", email = "adam@kudoai.com" },
14+
]
15+
readme = "docs/README.md"
16+
license = "MIT"
17+
license-files = [
18+
"docs/LICENSE.md",
19+
]
20+
dependencies = [
21+
"colorama>=0.4.6,<1 ; platform_system == 'Windows'",
22+
"is_unicode_supported>=1.1.2,<2",
23+
"json5>=0.13.0,<1",
24+
"non-latin-locales>=1.0.1,<2",
25+
]
26+
requires-python = ">=3.8,<4"
27+
keywords = [
28+
"api",
29+
"cli",
30+
"console",
31+
"detect",
32+
"detection",
33+
"dev-tool",
34+
"environment",
35+
"language",
36+
"locale",
37+
"shell",
38+
"system-language",
39+
"system-locale",
40+
"terminal",
41+
"utility",
42+
]
43+
classifiers = [
44+
"Development Status :: 5 - Production/Stable",
45+
"Environment :: Console",
46+
"Intended Audience :: Developers",
47+
"Intended Audience :: End Users/Desktop",
48+
"Intended Audience :: Information Technology",
49+
"Intended Audience :: System Administrators",
50+
"Natural Language :: English",
51+
"Operating System :: OS Independent",
52+
"Programming Language :: Python",
53+
"Programming Language :: Python :: 3",
54+
"Programming Language :: Python :: 3 :: Only",
55+
"Programming Language :: Python :: 3.8",
56+
"Programming Language :: Python :: 3.9",
57+
"Programming Language :: Python :: 3.10",
58+
"Programming Language :: Python :: 3.11",
59+
"Programming Language :: Python :: 3.12",
60+
"Programming Language :: Python :: 3.13",
61+
"Programming Language :: Python :: 3.14",
62+
"Programming Language :: Python :: 3.15",
63+
"Topic :: Software Development",
64+
"Topic :: Software Development :: Libraries",
65+
"Topic :: Software Development :: Libraries :: Python Modules",
66+
"Topic :: Software Development :: Localization",
67+
"Topic :: System",
68+
"Topic :: System :: Shells",
69+
"Topic :: Terminals",
70+
"Topic :: Utilities",
71+
"Typing :: Typed",
72+
]
73+
74+
[project.urls]
75+
Changelog = "https://github.com/adamlui/python-utils/releases/tag/sys-lang-1.0.0"
76+
Documentation = "https://github.com/adamlui/python-utils/tree/main/sys-lang/docs"
77+
Funding = "https://github.com/sponsors/adamlui"
78+
Homepage = "https://github.com/adamlui/python-utils/tree/main/sys-lang/#readme"
79+
Issues = "https://github.com/adamlui/python-utils/issues"
80+
"PyPI Stats" = "https://pepy.tech/projects/sys-lang"
81+
Releases = "https://github.com/adamlui/python-utils/releases"
82+
Repository = "https://github.com/adamlui/python-utils"
83+
84+
[project.scripts]
85+
sys-lang = "sys_lang.cli.__main__:main"
86+
sys-language = "sys_lang.cli.__main__:main"
87+
system-lang = "sys_lang.cli.__main__:main"
88+
system-language = "sys_lang.cli.__main__:main"
89+
get-sys-lang = "sys_lang.cli.__main__:main"
90+
get-sys-language = "sys_lang.cli.__main__:main"
91+
get-system-lang = "sys_lang.cli.__main__:main"
92+
get-system-language = "sys_lang.cli.__main__:main"
93+
syslang = "sys_lang.cli.__main__:main"
94+
syslanguage = "sys_lang.cli.__main__:main"
95+
systemlang = "sys_lang.cli.__main__:main"
96+
systemlanguage = "sys_lang.cli.__main__:main"
97+
getsyslang = "sys_lang.cli.__main__:main"
98+
getsyslanguage = "sys_lang.cli.__main__:main"
99+
getsystemlang = "sys_lang.cli.__main__:main"
100+
getsystemlanguage = "sys_lang.cli.__main__:main"
101+
102+
[project.optional-dependencies]
103+
dev = [
104+
"nox>=2026.2.9",
105+
"remove-json-keys>=1.9.2,<2",
106+
"tomli>=2.4.0,<3",
107+
"tomli-w>=1.2.0,<2",
108+
"translate-messages>=1.9.1,<2",
109+
]
110+
111+
[tool.setuptools.packages.find]
112+
where = [
113+
"src",
114+
]
115+
116+
[tool.setuptools.package-data]
117+
sys_lang = [
118+
"data/*.json",
119+
"data/_locales/en/messages.json",
120+
]

sys-lang/src/sys_lang/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .api import get_sys_lang
2+
3+
__all__ = ['get_sys_lang']

sys-lang/src/sys_lang/api.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
def get_sys_lang(region: bool = True) -> str: # e.g. 'en_US'
2+
import sys
3+
4+
if sys.platform == 'win32':
5+
import subprocess
6+
lang_result = subprocess.run(
7+
['powershell', '-Command', '(Get-Culture).Name'], capture_output=True, text=True, check=True).stdout.strip()
8+
if not lang_result : raise RuntimeError('Could not detect Windows system language')
9+
lang_code = lang_result.replace('-', '_')
10+
return lang_code if region or '_' not in lang_code else lang_code.split('_')[0]
11+
12+
else: # *nix sys
13+
import os
14+
for lang_env_var in ('LC_ALL', 'LC_MESSAGES', 'LANG', 'LANGUAGE'):
15+
lang_val = os.environ.get(lang_env_var)
16+
if not lang_val : continue
17+
lang_val = lang_val.split(':')[0]
18+
lang_val = lang_val.split('.')[0]
19+
lang_val = lang_val.split('@')[0]
20+
if lang_val.upper() in ('C', 'POSIX') : return 'en'
21+
return lang_val if region or '_' not in lang_val else lang_val.split('_')[0]
22+
raise RuntimeError('Could not detect *nix system language')

sys-lang/src/sys_lang/cli/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)