mirror of
https://github.com/vide/matedroid.git
synced 2026-01-20 00:03:17 +08:00
* feat(i18n): add localization support for DashboardScreen - Set up localization infrastructure with values-it, values-es, values-ca folders - Extract all hardcoded strings from DashboardScreen to strings.xml - Add Italian, Spanish, and Catalan translations - Include contextual comments for translators Supported languages: English (default), Italian, Spanish, Catalan * feat(i18n): add localization for SettingsScreen - Extract all hardcoded strings from SettingsScreen - Add Italian, Spanish, and Catalan translations - Include contextual comments for server settings, display settings, and advanced options * feat(i18n): add localization for DrivesScreen - Extract all hardcoded strings from DrivesScreen - Add localized filter labels for date and distance filters - Add Italian, Spanish, and Catalan translations for: - Screen title and navigation - Summary card labels - Drive stat labels - Chart titles (drives/time/distance/speed per day/week/month) - Filter chip labels * feat(i18n): add localization for DriveDetailScreen - Extract all hardcoded strings from DriveDetailScreen - Add Italian, Spanish, and Catalan translations for: - Screen title and navigation - Route header (from/to, started/ended) - Stats section titles and labels - Chart titles (speed/power/battery/elevation profiles) * feat(i18n): localize ChargesScreen strings Extract and translate all user-facing strings from ChargesScreen: - Screen title and section headers - Summary card labels (Total Sessions, Total Energy, Total Cost, etc.) - Charge item stat labels (Added, Duration, Cost, Battery) - Empty state message - Chart titles for energy/cost/charges per day/week/month - Filter labels using helper functions for DateFilter and ChargeTypeFilter Translations provided for Italian (it), Spanish (es), and Catalan (ca). * feat(i18n): localize ChargeDetailScreen strings Extract and translate all user-facing strings from ChargeDetailScreen: - Screen title and header labels (Location, Started, Ended) - Stats section titles (Energy, Battery, Power, Charger, Temperature, Cost) - Stats labels (voltage/current max/min/avg, efficiency, etc.) - Chart titles (Power Profile, Voltage Profile, Current Profile, Battery Level) - Map marker title - AC/DC badge text Translations provided for Italian (it), Spanish (es), and Catalan (ca). * feat(i18n): localize BatteryScreen strings Extract and translate all user-facing strings from BatteryScreen: - Screen titles (Battery Health, Battery Detail) - Capacity section (Usable new/now, Rated) - Degradation section (Estimated degradation, Loss kWh/%) - Range section (Max Range new/now, Range loss) - Current charge section - Range information section (Estimated, Rated, Ideal ranges) - Estimated total capacity section - Info dialog titles and messages with explanatory content - Common dialog button text (Got it) Translations provided for Italian (it), Spanish (es), and Catalan (ca). * feat(i18n): localize StatsScreen - Add strings for stats title, sync messages, progress indicators - Localize drives overview and charges overview sections - Localize all record labels (longest drive, top speed, etc.) - Add category names (Drives, Battery, Weather & Altitude, Distances) - Localize temperature extremes and AC/DC ratio cards - Add dialog strings for sync logs, gap records, range records - Add translations for Italian, Spanish, and Catalan Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(i18n): localize MileageScreen - Add strings for mileage title, chart titles (by year/month/day) - Localize empty states (no data, no data for year) - Add summary labels (Total, Avg/Year, Avg/Month, # of drives) - Localize info dialog explaining average per year calculation - Add "Recent trips" and "Drives" section headers - Localize all "View details" content descriptions - Add translations for Italian, Spanish, and Catalan Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(i18n): localize SoftwareVersionsScreen - Add strings for software title, overview card labels - Localize date filter labels (Last 6 months, Last year, All time) - Add update history header and empty state message - Localize version card labels (Current version, Installed, Days, Duration) - Add strings for longest installed badge - Localize chart title and format strings - Add translations for Italian, Spanish, and Catalan Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(i18n): localize common components and weather card - Add fullscreen/exit fullscreen content descriptions - Localize WeatherAlongTheWayCard title, loading, and empty states - Localize weather table headers (Time, Distance, Weather) - Localize weather condition descriptions (Clear sky, Partly cloudy, etc.) - Localize distance markers (Start, End) - Add translations for Italian, Spanish, and Catalan Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: add localization instructions to DEVELOPMENT.md - Document supported languages (English, Italian, Spanish, Catalan) - Add string naming conventions (snake_case) - Explain how to add new strings with context comments - Document format strings with placeholders - Add instructions for adding new languages - Include testing tips for translations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(i18n): enable per-app language selection (Android 13+) - Add locale_config.xml declaring supported languages (en, it, es, ca) - Reference locale config in AndroidManifest.xml - Users can now change app language without changing system language Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(i18n): keep AC/DC untranslated in all languages Technical terms AC (Alternating Current) and DC (Direct Current) are universally understood and should not be translated to CA/CC. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * ci: add lint check for hardcoded strings - Configure Android Lint to treat HardcodedText and SetTextI18n as errors - Add CI workflow that runs lint on every push/PR to main - Build job depends on lint passing - Upload lint report as artifact on failure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: add localization rules to CLAUDE.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * ci: combine lint and build into single job Lint requires compilation anyway, so running them in one job allows Gradle to reuse artifacts and is more efficient than two separate jobs. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: increase JVM heap to prevent OOM in CI - Increase Gradle daemon heap from 2GB to 4GB - Add HeapDumpOnOutOfMemoryError for debugging - Set test JVM max heap to 1GB Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
190 lines
6.5 KiB
Markdown
190 lines
6.5 KiB
Markdown
# Development
|
|
|
|
## Notes on development methodology
|
|
|
|
**This project was completely vibe-coded**, 100%, with the help of Claude Code and Opus 4.5. There it is, I said it, the shame is now gone.
|
|
|
|
I am/was pretty skeptical on LLM-generated code and this was born as an experiment to learn how it actually was to *vibe-code* something from scratch.
|
|
|
|
Turns out it's pretty awesome and easy to follow the happy path for a stock, modern Android app which just displays data consumed from a JSON REST API.
|
|
I'm a DevOps guy and I have zero mobile development skills, so achieving this can be considered pretty awesome in my book. But I'm pretty sure in the eyes of a skilled Kotlin Android developer, this code might induce different feelings.
|
|
|
|
At the moment, I completely depend on CC to maintain the app, but I would like to take this opportunity as an excuse to learn more about the Android development ecosystem, beside learning how to tame an LLM agent.
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
matedroid/
|
|
├── app/src/main/java/com/matedroid/
|
|
│ ├── data/ # Data layer (API, repository, local storage)
|
|
│ ├── domain/ # Domain layer (models, use cases)
|
|
│ ├── ui/ # UI layer (screens, components, theme)
|
|
│ └── di/ # Dependency injection modules
|
|
├── gradle/ # Gradle wrapper and version catalog
|
|
├── util/ # Utility scripts
|
|
├── ASSETS.md # Tesla car image asset documentation
|
|
└── PLAN.md # Detailed implementation plan
|
|
```
|
|
|
|
### Tech Stack
|
|
|
|
- **Language**: Kotlin
|
|
- **UI**: Jetpack Compose with Material Design 3
|
|
- **Architecture**: MVVM + Clean Architecture
|
|
- **DI**: Hilt
|
|
- **Networking**: Retrofit + OkHttp + Moshi
|
|
- **Local Storage**: DataStore
|
|
- **Charts**: Vico
|
|
- **Maps**: osmdroid (OpenStreetMap)
|
|
|
|
### Localization (i18n)
|
|
|
|
The app supports multiple languages using Android's standard resource-based localization system. Currently supported languages:
|
|
|
|
- **English** (default) - `res/values/strings.xml`
|
|
- **Italian** - `res/values-it/strings.xml`
|
|
- **Spanish** - `res/values-es/strings.xml`
|
|
- **Catalan** - `res/values-ca/strings.xml`
|
|
|
|
#### Adding/Modifying Translations
|
|
|
|
1. **All user-visible strings must be in string resources** - never hardcode text in Kotlin files
|
|
2. **String naming convention**: Use `snake_case` (e.g., `settings_title`, `drive_history`)
|
|
3. **Add context comments** for translators above each string:
|
|
```xml
|
|
<!-- Dialog title when user has multiple vehicles -->
|
|
<string name="select_vehicle">Select Vehicle</string>
|
|
```
|
|
|
|
#### Adding a New String
|
|
|
|
1. Add the English string to `res/values/strings.xml`:
|
|
```xml
|
|
<!-- Description of what this string is for -->
|
|
<string name="new_feature_label">Feature Name</string>
|
|
```
|
|
|
|
2. Add translations to all locale files:
|
|
- `res/values-it/strings.xml`
|
|
- `res/values-es/strings.xml`
|
|
- `res/values-ca/strings.xml`
|
|
|
|
3. Use in Kotlin code:
|
|
```kotlin
|
|
import androidx.compose.ui.res.stringResource
|
|
import com.matedroid.R
|
|
|
|
Text(text = stringResource(R.string.new_feature_label))
|
|
```
|
|
|
|
#### Format Strings
|
|
|
|
For strings with dynamic values, use placeholders:
|
|
```xml
|
|
<!-- %d is the percentage -->
|
|
<string name="charge_limit_format">Limit: %d%%</string>
|
|
|
|
<!-- %1$s is the date, %2$d is the number of days -->
|
|
<string name="avg_year_message">Since %1$s (%2$d days ago)</string>
|
|
```
|
|
|
|
Usage:
|
|
```kotlin
|
|
stringResource(R.string.charge_limit_format, chargeLimit)
|
|
stringResource(R.string.avg_year_message, formattedDate, dayCount)
|
|
```
|
|
|
|
#### Adding a New Language
|
|
|
|
1. Create a new folder: `res/values-{language_code}/`
|
|
2. Copy `res/values/strings.xml` to the new folder
|
|
3. Translate all strings, keeping the same `name` attributes
|
|
4. Android will automatically use the correct language based on device settings
|
|
|
|
#### Testing Translations
|
|
|
|
Change your device/emulator language in Settings > System > Languages to test different locales.
|
|
|
|
### Utility Scripts
|
|
|
|
#### `util/fetch_tesla_assets.py`
|
|
|
|
Python script to download Tesla car 3D renders from Tesla's compositor service. Requires [uv](https://github.com/astral-sh/uv) for dependency management.
|
|
|
|
```bash
|
|
# Download all car images (Model 3 & Y, various colors/wheels)
|
|
./util/fetch_tesla_assets.py
|
|
|
|
# Preview what would be downloaded
|
|
./util/fetch_tesla_assets.py --dry-run
|
|
|
|
# Custom output directory
|
|
./util/fetch_tesla_assets.py --output-dir /path/to/assets
|
|
```
|
|
|
|
See [ASSETS.md](ASSETS.md) for detailed documentation on Tesla compositor APIs, color/wheel code mappings, and troubleshooting.
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Unit tests
|
|
./gradlew test
|
|
|
|
# Instrumented tests (requires emulator/device)
|
|
./gradlew connectedAndroidTest
|
|
```
|
|
|
|
### Releasing
|
|
|
|
Releases are automated via GitHub Actions. When a release is published, the workflow builds the APK and attaches it to the release.
|
|
|
|
```bash
|
|
# 1. Update version in app/build.gradle.kts (versionCode and versionName)
|
|
# 2. Update CHANGELOG.md with release notes
|
|
# 3. Commit and push
|
|
|
|
# 4. Create a release with GitHub CLI
|
|
gh release create v0.5.0 --generate-notes
|
|
|
|
# Or create a draft release to edit notes first
|
|
gh release create v0.5.0 --generate-notes --draft
|
|
```
|
|
|
|
#### Signing Configuration (Optional)
|
|
|
|
For release signing with a custom keystore, set these repository secrets:
|
|
- `KEYSTORE_BASE64`: Base64-encoded keystore file (`base64 -w0 your.keystore`)
|
|
- `KEYSTORE_PASSWORD`: Keystore password
|
|
- `KEY_ALIAS`: Key alias
|
|
- `KEY_PASSWORD`: Key password
|
|
|
|
Without secrets, the APK is signed with a debug keystore (fine for sideloading, not for Play Store).
|
|
|
|
### Development Workflow
|
|
|
|
1. Start your Android emulator or connect a device
|
|
2. Build and install: `make install`
|
|
3. View logs: `adb logcat | grep -i matedroid`
|
|
|
|
#### Makefile Targets
|
|
|
|
| Target | Description |
|
|
|----------------|-------------------------------------------------|
|
|
| `make build` | Build debug APK |
|
|
| `make install` | Build and install debug APK on connected device |
|
|
| `make run` | Build, install, and launch the app |
|
|
| `make clean` | Clean build artifacts |
|
|
| `make test` | Run unit tests |
|
|
|
|
Or use Android Studio:
|
|
1. Open the project folder
|
|
2. Wait for Gradle sync
|
|
3. Click Run (green play button)
|
|
|
|
## Configuration
|
|
|
|
On first launch, you'll be prompted to configure your TeslamateApi connection:
|
|
|
|
1. **Server URL**: Your TeslamateApi instance URL (e.g., `https://teslamate-api.example.com`)
|
|
2. **API Token**: (Optional) If your instance requires authentication
|