Skip to content

Commit 32cef70

Browse files
authored
feat: expose available languages and add developer tooling (#14)
Add availableLocales and availableLocaleTags properties to the Tolgee class, allowing apps to dynamically query which languages are available from the CDN manifest without hardcoding them. Also consolidate AI agent guidelines into AGENTS.md, add CLAUDE.md, and create a /release command for version publishing.
1 parent 28cba7b commit 32cef70

File tree

7 files changed

+264
-158
lines changed

7 files changed

+264
-158
lines changed

.claude/commands/release.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
allowed-tools: Bash(grep:*), Bash(git describe:*), Bash(git branch:*), Bash(git log:*), Bash(git diff:*), Bash(git status:*), Bash(git tag:*), Bash(git add:*), Bash(git commit:*), Bash(git reset:*), Bash(gh repo view:*), Bash(gh release view:*), Bash(gh run:*), Bash(gh run list:*), Bash(gh run watch:*), Bash(gh run rerun:*), Bash(gh workflow run:*), Bash(./gradlew:*), Edit, Read
3+
description: Release a new version - bump version, commit, tag, push, publish to Maven Central, create GitHub release
4+
argument-hint: "[major|minor|patch|<explicit-version>]"
5+
---
6+
7+
# Release
8+
9+
## Current State
10+
11+
- Current version: !`grep '^library' gradle/libs.versions.toml`
12+
- Latest git tag: !`git describe --tags --abbrev=0 2>/dev/null || echo "(no tags)"`
13+
- Current branch: !`git branch --show-current`
14+
- GitHub repo: !`gh repo view --json nameWithOwner -q .nameWithOwner`
15+
16+
## Instructions
17+
18+
Follow these steps precisely to create a new release.
19+
20+
### Step 1: Preflight checks
21+
22+
1. Verify we are on the `master` branch. If not, **stop** and warn the user.
23+
2. Verify the working tree is clean (`git status --porcelain`). If not, **stop** and warn the user.
24+
3. Pull latest: `git pull --ff-only`. If this fails, **stop** and warn the user.
25+
26+
### Step 2: Determine version bump
27+
28+
The current version uses pre-release identifiers (e.g., `1.0.0-alpha03`). Version bumping rules:
29+
30+
If `$ARGUMENTS` is one of `major`, `minor`, or `patch`:
31+
- **patch**: increment the last numeric segment (e.g., `1.0.0-alpha03``1.0.0-alpha04`, or `1.2.3``1.2.4`)
32+
- **minor**: `X.Y.Z``X.Y+1.0` (drops any pre-release suffix)
33+
- **major**: `X.Y.Z``X+1.0.0` (drops any pre-release suffix) — always confirm with user first
34+
35+
If `$ARGUMENTS` is an explicit version string (e.g., `1.0.0-beta01` or `1.0.0`), use it directly.
36+
37+
Otherwise, analyze the commits since the last tag and suggest an appropriate bump. Present the proposed new version to the user and ask them to confirm using `AskUserQuestion`.
38+
39+
### Step 3: Summarize changes
40+
41+
List the commits since the last tag using `git log <last-tag>..HEAD --oneline`. Write concise, user-facing bullet points for each meaningful change. These will be used in the GitHub release body alongside the auto-generated changelog.
42+
43+
### Step 4: Execute the release
44+
45+
Do all of the following in order:
46+
47+
1. Edit `gradle/libs.versions.toml` to update the `library` version on line 9 to the new version
48+
2. Build to verify nothing is broken:
49+
```
50+
./gradlew apiDump
51+
./gradlew :core:build
52+
```
53+
If the build fails, **stop** and help the user fix the issue before continuing.
54+
3. Stage and commit:
55+
```
56+
git add gradle/libs.versions.toml core/api/
57+
git commit -m "release: vX.Y.Z"
58+
```
59+
4. Tag: `git tag vX.Y.Z`
60+
5. Push: `git push && git push --tags`
61+
62+
### Step 5: Wait for CI
63+
64+
After pushing, monitor the CI workflows triggered by the push:
65+
66+
1. Wait a moment for workflows to trigger, then use `gh run list --branch master --limit 5` to find the runs
67+
2. Use `gh run watch <run-id>` on the test workflow run
68+
69+
If all checks pass, proceed to Step 6.
70+
71+
If any check fails:
72+
- **Flaky/random failure**: Rerun with `gh run rerun <run-id> --failed`, then wait again
73+
- **Real failure**: We need to roll back and fix the issue:
74+
1. Delete the remote tag: `git push --delete origin vX.Y.Z`
75+
2. Delete the local tag: `git tag -d vX.Y.Z`
76+
3. Revert the release commit: `git reset --hard HEAD~1 && git push --force`
77+
4. Help the user fix the issue, then re-release
78+
79+
### Step 6: Create GitHub release
80+
81+
Create the release on GitHub using the auto-generated changelog:
82+
83+
```
84+
gh release create vX.Y.Z --title "vX.Y.Z" --generate-notes
85+
```
86+
87+
This will:
88+
- Create a GitHub release with auto-generated PR-based changelog
89+
- Automatically trigger the `apple-binaries.yml` workflow (attaches XCFramework archives to the release)
90+
91+
### Step 7: Trigger Maven Central publish
92+
93+
Trigger the publish workflow manually:
94+
95+
```
96+
gh workflow run publish.yml
97+
```
98+
99+
### Step 8: Monitor post-release workflows
100+
101+
1. Use `gh run list --limit 5` to find the publish and apple-binaries workflow runs
102+
2. Watch both with `gh run watch <run-id>`
103+
3. If the publish workflow fails, inform the user — they may need to check Maven Central / Sonatype credentials
104+
4. If apple-binaries fails, it can be re-triggered: `gh workflow run apple-binaries.yml`
105+
106+
Once all workflows complete successfully, report:
107+
- Link to the GitHub release
108+
- Confirm Maven Central publish status
109+
- Confirm Apple XCFramework archives attached to release

.junie/guidelines.md

Lines changed: 0 additions & 158 deletions
This file was deleted.

AGENTS.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# AGENTS.md
2+
3+
Guidance for AI coding agents working on the Tolgee Mobile Kotlin SDK.
4+
5+
Main branch: `master`
6+
7+
## Project Structure
8+
9+
```
10+
tolgee-mobile-kotlin-sdk/
11+
├── core/ # KMP base library (translations, caching, CDN API)
12+
├── compose/ # Compose Multiplatform integration
13+
├── compiler-plugin/ # Kotlin compiler plugin (currently disabled)
14+
├── gradle-plugin/ # Gradle plugin for project integration
15+
└── demo/ # Example apps (Android Views, Jetpack Compose, KMP Compose)
16+
```
17+
18+
The compiler plugin is commented out in `settings.gradle.kts` (broken after Kotlin 2.2).
19+
20+
## Building
21+
22+
```bash
23+
./gradlew :core:build
24+
./gradlew :compose:build
25+
./gradlew :gradle-plugin:build
26+
```
27+
28+
## Testing
29+
30+
Only the gradle-plugin module has tests currently:
31+
32+
```bash
33+
./gradlew :gradle-plugin:test
34+
./gradlew :gradle-plugin:test --tests "TolgeeTest"
35+
```
36+
37+
CI (`test.yml`) runs gradle-plugin tests on every push. Requires Tolgee CLI (`npm install --global @tolgee/cli`).
38+
39+
## API Compatibility
40+
41+
The project uses the Binary Compatibility Validator plugin. After any changes to public APIs, run:
42+
43+
```bash
44+
./gradlew apiDump
45+
```
46+
47+
This updates `.api` dump files in each module's `api/` directory. These files **must be committed** with the change. The build will fail (`apiCheck`) if the dump is out of date.
48+
49+
## Module Architecture
50+
51+
### Core Module
52+
53+
Main entry point: `Tolgee` singleton class in `core/src/commonMain/kotlin/io/tolgee/Tolgee.kt`
54+
55+
Key components:
56+
- `Tolgee` — Singleton with locale management, translation resolution, and configuration
57+
- `TolgeeApi` — CDN communication and local caching
58+
- `TolgeeTranslation` — Interface with ICU and sprintf formatting implementations
59+
- `TolgeeStorageProvider` — Platform-specific persistent caching interface
60+
- `TolgeeManifest` — Available locales metadata from CDN (internal)
61+
62+
Data flow:
63+
```
64+
tFlow("key", params)
65+
→ localeFlow emits locale
66+
→ loadManifest() fetches available locales from CDN
67+
→ resolveLocale() applies progressive BCP 47 fallback (zh-Hans-CN → zh-Hans → zh)
68+
→ loadTranslations() fetches from CDN or cache (LRU in-memory + persistent storage)
69+
→ Translation formatted and emitted via Flow
70+
```
71+
72+
Thread safety: `Mutex` for translation loading, `AtomicFU` for manifest cache.
73+
74+
### Compose Module
75+
76+
Composable wrappers around Core with graceful fallback to default Compose resources when Tolgee is not initialized. Provides `stringResource()`, `pluralStringResource()`, `stringArrayResource()`.
77+
78+
### Gradle Plugin
79+
80+
Build-time configuration DSL bridging Gradle with the compiler plugin. Configures replacement of `getString()` and `stringResource()` calls.
81+
82+
### Compiler Plugin (disabled)
83+
84+
Kotlin IR transformations to replace standard resource calls with Tolgee calls at compile-time. Currently disabled in `settings.gradle.kts`.
85+
86+
## Multiplatform
87+
88+
The core module targets 20+ platforms:
89+
90+
| Category | Targets |
91+
|----------|---------|
92+
| Android | androidTarget, androidNativeX64/X86/Arm64/Arm32 |
93+
| JVM | jvm (toolchain 21) |
94+
| Apple | iOS (x64, arm64, simulatorArm64), tvOS (×3), watchOS (×4), macOS (x64, arm64) |
95+
| Other | linuxX64, linuxArm64, mingwX64, js (IR), wasmJs |
96+
97+
Source set hierarchy follows `applyDefaultHierarchyTemplate()`:
98+
- `commonMain` — All shared code
99+
- `androidMain` — Android-specific (Views integration, storage)
100+
- `appleMain` — Apple platforms (iOS/macOS/tvOS/watchOS)
101+
- `jvmMain` — JVM-specific
102+
- `jsMain` / `wasmJsMain` — JS/WASM
103+
104+
## Key Design Patterns
105+
106+
- **Builder pattern** for configuration: `Tolgee.Config.Builder`, `ContentDelivery.Builder`, `Network.Builder`
107+
- **Sealed interfaces** for type safety: `Formatter` (ICU/Sprintf), `TolgeeMessageParams` (None/Indexed/Mapped)
108+
- **Reactive Flows**: `localeFlow`, `changeFlow`, `tFlow()` returning `Flow<String>`
109+
- **Expect/actual** for platform-specific implementations (`platformHttpClient`, `platformStorage`, etc.)
110+
111+
## Dependencies
112+
113+
Managed via Version Catalog in `gradle/libs.versions.toml`. Add new dependencies there, not directly in build scripts.
114+
115+
Key libraries: Ktor (HTTP), kotlinx-serialization (JSON), kotlinx-coroutines (async), i18n4k (locale handling), AtomicFU (thread safety), SKIE (Swift interop for Apple targets).
116+
117+
## Publishing
118+
119+
Manual trigger via `publish.yml` workflow on macOS. Publishes to Maven Central via `publishAllPublicationsToMavenCentralRepository`. Requires signing keys and Sonatype credentials.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@AGENTS.md

core/api/android/core.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ public class io/tolgee/Tolgee {
22
public static final field Companion Lio/tolgee/Tolgee$Companion;
33
public fun <init> (Lio/tolgee/Tolgee$Config;)V
44
public final fun addChangeListener (Lio/tolgee/Tolgee$ChangeListener;)V
5+
public fun getAvailableLocaleTags ()Ljava/util/List;
6+
public fun getAvailableLocales ()Ljava/util/List;
57
public final fun getChangeFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
68
public fun getConfig ()Lio/tolgee/Tolgee$Config;
79
public static final fun getInstance ()Lio/tolgee/TolgeeAndroid;

0 commit comments

Comments
 (0)