mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-29 07:52:50 -05:00
switch hto monorepo structure
This commit is contained in:
64
quickshell/translations/README.md
Normal file
64
quickshell/translations/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# DankMaterialShell Translations
|
||||
|
||||
This directory contains translation files for DankMaterialShell extracted from all qsTr() calls in the QML codebase.
|
||||
|
||||
## Files
|
||||
|
||||
- **en.json** - Source language file with English strings and file references
|
||||
- **template.json** - Empty template for creating new translations
|
||||
- **extract_translations.py** - Script to regenerate translation files
|
||||
|
||||
## POEditor Format
|
||||
|
||||
The JSON files follow POEditor's import format:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"term": "string to translate",
|
||||
"context": "file:line",
|
||||
"reference": "Modules/Settings/AboutTab.qml:45",
|
||||
"comment": ""
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Field Descriptions
|
||||
|
||||
- **term**: The source string in English (from qsTr() calls)
|
||||
- **context**: Primary location where the string appears (file:line)
|
||||
- **reference**: All locations where this string is used (comma-separated)
|
||||
- **comment**: Additional notes for translators (currently empty)
|
||||
|
||||
## How to Create a New Translation
|
||||
|
||||
1. Copy `template.json` to your language code (e.g., `es.json` for Spanish)
|
||||
2. Fill in the `translation` field for each entry:
|
||||
```json
|
||||
{
|
||||
"term": "Settings",
|
||||
"translation": "Configuración",
|
||||
"context": "Modals/Settings/SettingsModal.qml:147",
|
||||
"reference": "Modals/Settings/SettingsModal.qml:147",
|
||||
"comment": ""
|
||||
}
|
||||
```
|
||||
3. Import to POEditor or use directly in your translation workflow
|
||||
|
||||
## Regenerating Translation Files
|
||||
|
||||
To update the translation files after code changes:
|
||||
|
||||
```bash
|
||||
cd /home/brandon/.config/quickshell/DankMaterialShellGit/translations
|
||||
./extract_translations.py
|
||||
```
|
||||
|
||||
This will scan all QML files and regenerate `en.json` and `template.json`.
|
||||
|
||||
## Notes
|
||||
|
||||
- Strings are deduplicated - if the same string appears in multiple locations, references are merged
|
||||
- File paths are relative to the project root
|
||||
- Line numbers are preserved for accurate context
|
||||
- Empty strings and comments are reserved for translator notes
|
||||
185
quickshell/translations/WORKFLOW.md
Normal file
185
quickshell/translations/WORKFLOW.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# Translation Workflow for DankMaterialShell
|
||||
|
||||
## POEditor Integration Guide
|
||||
|
||||
### Initial Setup
|
||||
|
||||
1. **Create POEditor Project**
|
||||
- Go to https://poeditor.com
|
||||
- Create new project "DankMaterialShell"
|
||||
- Add languages you want to support (es, fr, de, etc.)
|
||||
|
||||
2. **Import Source Strings**
|
||||
- Upload `en.json` as the source language
|
||||
- POEditor will detect 336 translatable strings
|
||||
- Format: Key-Value JSON
|
||||
|
||||
### Translation Workflow
|
||||
|
||||
#### Method 1: Using POEditor (Recommended)
|
||||
|
||||
1. **Upload source file**
|
||||
```bash
|
||||
# Upload en.json to POEditor
|
||||
```
|
||||
|
||||
2. **Translate in POEditor**
|
||||
- Use POEditor's web interface
|
||||
- Invite translators
|
||||
- Track progress per language
|
||||
|
||||
3. **Export translations**
|
||||
```bash
|
||||
# Download from POEditor as JSON
|
||||
# Save to translations/{language_code}.json
|
||||
# Example: translations/es.json, translations/fr.json
|
||||
```
|
||||
|
||||
4. **Test translations**
|
||||
```bash
|
||||
# Set your locale and restart shell
|
||||
export LANG=es_ES.UTF-8
|
||||
qs -p .
|
||||
```
|
||||
|
||||
#### Method 2: Manual Translation
|
||||
|
||||
1. **Copy template**
|
||||
```bash
|
||||
cp translations/template.json translations/es.json
|
||||
```
|
||||
|
||||
2. **Fill in translations**
|
||||
```json
|
||||
{
|
||||
"term": "Settings",
|
||||
"context": "Modals/Settings/SettingsModal.qml:147",
|
||||
"reference": "Modals/Settings/SettingsModal.qml:147",
|
||||
"comment": "",
|
||||
"translation": "Configuración"
|
||||
}
|
||||
```
|
||||
|
||||
3. **Upload to POEditor** (optional)
|
||||
|
||||
### Updating Translations After Code Changes
|
||||
|
||||
1. **Re-extract strings**
|
||||
```bash
|
||||
cd translations
|
||||
python3 extract_translations.py
|
||||
```
|
||||
|
||||
2. **Upload updated en.json to POEditor**
|
||||
- POEditor will detect new/removed strings
|
||||
- Preserves existing translations
|
||||
|
||||
3. **Download updated translations**
|
||||
|
||||
### Translation File Format
|
||||
|
||||
POEditor-compatible JSON format:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"term": "source string in English",
|
||||
"context": "file:line where it appears",
|
||||
"reference": "full/path/to/file.qml:123",
|
||||
"comment": "optional context for translators",
|
||||
"translation": "translated string"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Supported Languages
|
||||
|
||||
The shell will auto-detect your system locale. Supported format:
|
||||
- `es.json` → Spanish (es_ES, es_MX, etc.)
|
||||
- `fr.json` → French (fr_FR, fr_CA, etc.)
|
||||
- `de.json` → German
|
||||
- `zh.json` → Chinese
|
||||
- `ja.json` → Japanese
|
||||
- `pt.json` → Portuguese
|
||||
- etc.
|
||||
|
||||
### Testing Translations
|
||||
|
||||
1. **Change system locale**
|
||||
```bash
|
||||
export LANG=es_ES.UTF-8
|
||||
export LC_ALL=es_ES.UTF-8
|
||||
```
|
||||
|
||||
2. **Restart shell**
|
||||
```bash
|
||||
qs -p .
|
||||
```
|
||||
|
||||
3. **Verify translations appear correctly**
|
||||
|
||||
### File Structure
|
||||
|
||||
```
|
||||
translations/
|
||||
├── en.json # Source language (English)
|
||||
├── template.json # Empty template for new languages
|
||||
├── es.json # Spanish translation
|
||||
├── fr.json # French translation
|
||||
├── extract_translations.py # Auto-extraction script
|
||||
├── README.md # Technical documentation
|
||||
└── WORKFLOW.md # This file
|
||||
```
|
||||
|
||||
### Translation Statistics
|
||||
|
||||
- **Total strings:** 336 unique terms
|
||||
- **Most translated components:**
|
||||
- Settings UI: 202 strings (60%)
|
||||
- Weather: 25 strings (7%)
|
||||
- System monitors: Various
|
||||
- Modals: 43 strings (13%)
|
||||
|
||||
### POEditor API Integration (Advanced)
|
||||
|
||||
For automated sync, use POEditor's API:
|
||||
|
||||
```bash
|
||||
# Export from POEditor
|
||||
curl -X POST https://api.poeditor.com/v2/projects/export \
|
||||
-d api_token="YOUR_TOKEN" \
|
||||
-d id="PROJECT_ID" \
|
||||
-d language="es" \
|
||||
-d type="key_value_json"
|
||||
|
||||
# Import to POEditor
|
||||
curl -X POST https://api.poeditor.com/v2/projects/upload \
|
||||
-d api_token="YOUR_TOKEN" \
|
||||
-d id="PROJECT_ID" \
|
||||
-d updating="terms_translations" \
|
||||
-d language="es" \
|
||||
-F file=@"translations/es.json"
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Context matters:** Use the reference field to understand where strings appear
|
||||
2. **Test before committing:** Always test translations in the actual UI
|
||||
3. **Keep synchronized:** Re-extract after significant UI changes
|
||||
4. **Preserve formatting:** Keep placeholders like `%1`, `{0}` intact
|
||||
5. **Cultural adaptation:** Some strings may need cultural context, not just literal translation
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**Translations not loading?**
|
||||
- Check file exists: `~/.config/DankMaterialShell/translations/{language_code}.json`
|
||||
- Verify JSON syntax: `python3 -m json.tool translations/es.json`
|
||||
- Check console for errors: `qs -v -p .`
|
||||
|
||||
**Wrong language loading?**
|
||||
- Check system locale: `echo $LANG`
|
||||
- Verify file naming: Must match locale prefix (es_ES → es.json)
|
||||
|
||||
**Missing strings?**
|
||||
- Re-run extraction: `python3 extract_translations.py`
|
||||
- Compare with en.json to find new strings
|
||||
4352
quickshell/translations/en.json
Normal file
4352
quickshell/translations/en.json
Normal file
File diff suppressed because it is too large
Load Diff
98
quickshell/translations/extract_translations.py
Executable file
98
quickshell/translations/extract_translations.py
Executable file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
from pathlib import Path
|
||||
from collections import defaultdict
|
||||
|
||||
def extract_qstr_strings(root_dir):
|
||||
translations = defaultdict(list)
|
||||
qstr_pattern = re.compile(r'qsTr\(["\']([^"\']+)["\']\)')
|
||||
i18n_pattern = re.compile(r'I18n\.tr\(["\']([^"\']+)["\']\)')
|
||||
|
||||
for qml_file in Path(root_dir).rglob('*.qml'):
|
||||
relative_path = qml_file.relative_to(root_dir)
|
||||
|
||||
with open(qml_file, 'r', encoding='utf-8') as f:
|
||||
for line_num, line in enumerate(f, 1):
|
||||
qstr_matches = qstr_pattern.findall(line)
|
||||
for match in qstr_matches:
|
||||
translations[match].append({
|
||||
'file': str(relative_path),
|
||||
'line': line_num
|
||||
})
|
||||
|
||||
i18n_matches = i18n_pattern.findall(line)
|
||||
for match in i18n_matches:
|
||||
translations[match].append({
|
||||
'file': str(relative_path),
|
||||
'line': line_num
|
||||
})
|
||||
|
||||
return translations
|
||||
|
||||
def create_poeditor_json(translations):
|
||||
poeditor_data = []
|
||||
|
||||
for term, occurrences in sorted(translations.items()):
|
||||
references = []
|
||||
|
||||
for occ in occurrences:
|
||||
ref = f"{occ['file']}:{occ['line']}"
|
||||
references.append(ref)
|
||||
|
||||
entry = {
|
||||
"term": term,
|
||||
"context": term,
|
||||
"reference": ", ".join(references),
|
||||
"comment": ""
|
||||
}
|
||||
poeditor_data.append(entry)
|
||||
|
||||
return poeditor_data
|
||||
|
||||
def create_template_json(translations):
|
||||
template_data = []
|
||||
|
||||
for term in sorted(translations.keys()):
|
||||
entry = {
|
||||
"term": term,
|
||||
"translation": "",
|
||||
"context": "",
|
||||
"reference": "",
|
||||
"comment": ""
|
||||
}
|
||||
template_data.append(entry)
|
||||
|
||||
return template_data
|
||||
|
||||
def main():
|
||||
script_dir = Path(__file__).parent
|
||||
root_dir = script_dir.parent
|
||||
translations_dir = script_dir
|
||||
|
||||
print("Extracting qsTr() strings from QML files...")
|
||||
translations = extract_qstr_strings(root_dir)
|
||||
|
||||
print(f"Found {len(translations)} unique strings")
|
||||
|
||||
poeditor_data = create_poeditor_json(translations)
|
||||
en_json_path = translations_dir / 'en.json'
|
||||
with open(en_json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(poeditor_data, f, indent=2, ensure_ascii=False)
|
||||
print(f"Created source language file: {en_json_path}")
|
||||
|
||||
template_data = create_template_json(translations)
|
||||
template_json_path = translations_dir / 'template.json'
|
||||
with open(template_json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(template_data, f, indent=2, ensure_ascii=False)
|
||||
print(f"Created template file: {template_json_path}")
|
||||
|
||||
print("\nSummary:")
|
||||
print(f" - Unique strings: {len(translations)}")
|
||||
print(f" - Total occurrences: {sum(len(occs) for occs in translations.values())}")
|
||||
print(f" - Source file: {en_json_path}")
|
||||
print(f" - Template file: {template_json_path}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
2180
quickshell/translations/poexports/it.json
Normal file
2180
quickshell/translations/poexports/it.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
quickshell/translations/poexports/ja.json
Normal file
2180
quickshell/translations/poexports/ja.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
quickshell/translations/poexports/pl.json
Normal file
2180
quickshell/translations/poexports/pl.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
quickshell/translations/poexports/pt.json
Normal file
2180
quickshell/translations/poexports/pt.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
quickshell/translations/poexports/tr.json
Normal file
2180
quickshell/translations/poexports/tr.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
quickshell/translations/poexports/zh_CN.json
Normal file
2180
quickshell/translations/poexports/zh_CN.json
Normal file
File diff suppressed because it is too large
Load Diff
2180
quickshell/translations/poexports/zh_TW.json
Normal file
2180
quickshell/translations/poexports/zh_TW.json
Normal file
File diff suppressed because it is too large
Load Diff
48
quickshell/translations/replace_qstr.py
Executable file
48
quickshell/translations/replace_qstr.py
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
def replace_qstr_in_file(file_path, root_dir):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
original_content = content
|
||||
relative_path = file_path.relative_to(root_dir)
|
||||
|
||||
qstr_pattern = re.compile(r'qsTr\("([^"]+)"\)')
|
||||
|
||||
def replacement(match):
|
||||
term = match.group(1)
|
||||
context = term
|
||||
return f'I18n.tr("{term}", "{context}")'
|
||||
|
||||
content = qstr_pattern.sub(replacement, content)
|
||||
|
||||
if content != original_content:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
return True
|
||||
return False
|
||||
|
||||
def main():
|
||||
script_dir = Path(__file__).parent
|
||||
root_dir = script_dir.parent
|
||||
|
||||
modified_count = 0
|
||||
|
||||
for qml_file in root_dir.rglob('*.qml'):
|
||||
if 'translations' in str(qml_file):
|
||||
continue
|
||||
|
||||
try:
|
||||
if replace_qstr_in_file(qml_file, root_dir):
|
||||
modified_count += 1
|
||||
print(f"Modified: {qml_file.relative_to(root_dir)}")
|
||||
except Exception as e:
|
||||
print(f"Error processing {qml_file}: {e}")
|
||||
|
||||
print(f"\nTotal files modified: {modified_count}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
5077
quickshell/translations/template.json
Normal file
5077
quickshell/translations/template.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user