android-localisation 1.0.3__tar.gz → 1.0.5__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 (18) hide show
  1. {android_localisation-1.0.3/android_localisation.egg-info → android_localisation-1.0.5}/PKG-INFO +91 -15
  2. {android_localisation-1.0.3 → android_localisation-1.0.5}/README.md +90 -14
  3. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation/__init__.py +1 -1
  4. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation/cli.py +6 -1
  5. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation/fix.py +5 -1
  6. android_localisation-1.0.5/android_localisation/java/VerifyStrings.java +219 -0
  7. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation/translate.py +104 -68
  8. {android_localisation-1.0.3 → android_localisation-1.0.5/android_localisation.egg-info}/PKG-INFO +91 -15
  9. {android_localisation-1.0.3 → android_localisation-1.0.5}/pyproject.toml +1 -1
  10. android_localisation-1.0.3/android_localisation/java/VerifyStrings.java +0 -148
  11. {android_localisation-1.0.3 → android_localisation-1.0.5}/LICENSE +0 -0
  12. {android_localisation-1.0.3 → android_localisation-1.0.5}/MANIFEST.in +0 -0
  13. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation/verify.py +0 -0
  14. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation.egg-info/SOURCES.txt +0 -0
  15. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation.egg-info/dependency_links.txt +0 -0
  16. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation.egg-info/entry_points.txt +0 -0
  17. {android_localisation-1.0.3 → android_localisation-1.0.5}/android_localisation.egg-info/top_level.txt +0 -0
  18. {android_localisation-1.0.3 → android_localisation-1.0.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: android-localisation
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: Zero-dependency Android strings.xml translation and verification using LLMs (Gemini, OpenAI, Anthropic, Ollama).
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/BharathKmalviya/android-llm-localization
@@ -26,13 +26,15 @@ Description-Content-Type: text/markdown
26
26
  License-File: LICENSE
27
27
  Dynamic: license-file
28
28
 
29
- # android-llm-localization
29
+ # android-localisation
30
30
 
31
31
  [![PyPI version](https://img.shields.io/pypi/v/android-localisation.svg)](https://pypi.org/project/android-localisation/)
32
32
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://pypi.org/project/android-localisation/)
33
33
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
34
34
 
35
- Translate your Android `strings.xml` into multiple languages using AI — Gemini, OpenAI, Anthropic, or a local model via Ollama. No paid service, no CSV exports, no copy-paste.
35
+ **PyPI:** [`android-localisation`](https://pypi.org/project/android-localisation/) · **CLI:** `android-localise` · **Repo:** [android-llm-localization](https://github.com/BharathKmalviya/android-llm-localization)
36
+
37
+ Translate your Android `strings.xml` into multiple languages using AI — Gemini, OpenAI, Anthropic, or a local model via Ollama. No paid translation service, no CSV exports, no copy-paste.
36
38
 
37
39
  ---
38
40
 
@@ -86,7 +88,7 @@ When you run `android-localise translate --api-key YOUR_KEY`, here's exactly wha
86
88
  | What | Default |
87
89
  |---|---|
88
90
  | Provider | Gemini |
89
- | Model | `gemini-2.5-flash` |
91
+ | Model | `gemini-3.5-flash` |
90
92
  | Source directory | `app/src/main/res` |
91
93
  | Delay between requests | 5 seconds |
92
94
  | App context | none (generic prompt) |
@@ -150,6 +152,7 @@ android-localise translate \
150
152
  | `--res-dir` | Path to your `res/` folder | `app/src/main/res` |
151
153
  | `--base-url` | API endpoint for local/custom providers | — |
152
154
  | `--sleep` | Seconds to wait between language requests | `5.0` |
155
+ | `--timeout` | Seconds to wait for each API response (retries up to 3 times on timeout) | `180` |
153
156
 
154
157
  ---
155
158
 
@@ -157,10 +160,13 @@ android-localise translate \
157
160
 
158
161
  ```bash
159
162
  android-localise fix
163
+ android-localise fix --res-dir path/to/res
160
164
  ```
161
165
 
162
166
  LLMs occasionally produce output that looks correct but breaks the Android build — curly apostrophes (`'`) instead of escaped ones (`\'`), unescaped double quotes, or mangled `%` signs. This command scans every translated `strings.xml` and corrects these silently.
163
167
 
168
+ Strings marked `formatted="false"` are skipped — their `%` signs are literal, not format specifiers.
169
+
164
170
  Always run this before `verify` and before building.
165
171
 
166
172
  ---
@@ -169,11 +175,12 @@ Always run this before `verify` and before building.
169
175
 
170
176
  ```bash
171
177
  android-localise verify
178
+ android-localise verify --res-dir path/to/res
172
179
  ```
173
180
 
174
181
  Takes every translated string that contains a format specifier (`%1$s`, `%d`, `%1$f`, etc.) and calls `String.format()` on it using Java's actual runtime. If a translated string would throw `UnknownFormatConversionException` or `MissingFormatArgumentException` in your app, this catches it before your users do.
175
182
 
176
- Requires `javac` in your PATH. If you don't have it system-wide, run this from the Terminal tab inside Android Studio — it ships with a JDK.
183
+ Strings marked `formatted="false"` are skipped. Requires `javac` in your PATH. If you don't have it system-wide, run this from the Terminal tab inside Android Studio — it ships with a JDK.
177
184
 
178
185
  ---
179
186
 
@@ -190,21 +197,21 @@ Lists every available model and fallback for each provider.
190
197
 
191
198
  ## Providers
192
199
 
193
- By default the tool uses Gemini with `gemini-2.5-flash`. You can switch providers with `--provider` and optionally pin a specific model with `--model`.
200
+ By default the tool uses Gemini with `gemini-3.5-flash`. You can switch providers with `--provider` and optionally pin a specific model with `--model`.
194
201
 
195
202
  | Provider | Default model | Fallbacks | API key env var |
196
203
  |---|---|---|---|
197
- | `gemini` _(default)_ | `gemini-2.5-flash` | `gemini-2.0-flash` → `gemini-1.5-flash` → `gemini-1.5-pro` | `GEMINI_API_KEY` |
198
- | `openai` | `gpt-4o-mini` | `gpt-4o` → `gpt-3.5-turbo` | `OPENAI_API_KEY` |
199
- | `anthropic` | `claude-3-5-haiku-latest` | `claude-3-5-sonnet-latest` → `claude-3-opus-latest` | `ANTHROPIC_API_KEY` |
200
- | `custom` | set with `--model` | none | — |
204
+ | `gemini` _(default)_ | `gemini-3.5-flash` | `gemini-3.1-flash-lite` → `gemini-2.5-flash` → `gemini-2.5-flash-lite` | `GEMINI_API_KEY` |
205
+ | `openai` | `gpt-5.4-mini` | `gpt-5-mini` → `gpt-4o-mini` | `OPENAI_API_KEY` |
206
+ | `anthropic` | `claude-haiku-4-5` | `claude-sonnet-4-6` → `claude-opus-4-8` | `ANTHROPIC_API_KEY` |
207
+ | `custom` | set with `--model` | none | `OPENAI_API_KEY` (optional) |
201
208
 
202
209
  If the default model returns a "model not found" error (e.g. it was deprecated), the tool automatically retries with the next fallback. If you pin a model with `--model`, no fallback is used.
203
210
 
204
211
  **Using OpenAI:**
205
212
  ```bash
206
213
  android-localise translate --provider openai --api-key YOUR_KEY
207
- android-localise translate --provider openai --model gpt-4o --api-key YOUR_KEY
214
+ android-localise translate --provider openai --model gpt-5.4-mini --api-key YOUR_KEY
208
215
  ```
209
216
 
210
217
  **Using Anthropic:**
@@ -239,6 +246,9 @@ export GEMINI_API_KEY=your_key
239
246
 
240
247
  # Windows PowerShell
241
248
  $env:GEMINI_API_KEY = "your_key"
249
+
250
+ # Windows CMD
251
+ set GEMINI_API_KEY=your_key
242
252
  ```
243
253
 
244
254
  Then just run:
@@ -251,19 +261,25 @@ android-localise translate
251
261
  | `GEMINI_API_KEY` | `--provider gemini` |
252
262
  | `OPENAI_API_KEY` | `--provider openai` and `--provider custom` |
253
263
  | `ANTHROPIC_API_KEY` | `--provider anthropic` |
264
+ | `API_KEY` | fallback for any provider if the provider-specific var is not set |
254
265
 
255
266
  ---
256
267
 
257
268
  ## Full workflow example
258
269
 
259
270
  ```bash
260
- # First time setup — create locale folders
271
+ # First time setup — create locale folders (macOS / Linux)
261
272
  mkdir -p app/src/main/res/values-hi
262
273
  mkdir -p app/src/main/res/values-es
263
274
  mkdir -p app/src/main/res/values-de
264
275
 
276
+ # Windows PowerShell
277
+ New-Item -ItemType Directory -Force app/src/main/res/values-hi
278
+ New-Item -ItemType Directory -Force app/src/main/res/values-es
279
+ New-Item -ItemType Directory -Force app/src/main/res/values-de
280
+
265
281
  # Set your key once
266
- export GEMINI_API_KEY=your_key
282
+ export GEMINI_API_KEY=your_key # or $env:GEMINI_API_KEY on Windows
267
283
 
268
284
  # Translate, fix, verify
269
285
  android-localise translate --app-context "a habit tracking app"
@@ -278,23 +294,83 @@ After this, whenever you add or change strings in your English `strings.xml`, ru
278
294
 
279
295
  ---
280
296
 
297
+ ## Platform support
298
+
299
+ This project is developed and **manually tested on Windows only** at the moment. It is written in pure Python (stdlib only) and should run on macOS and Linux, but those platforms have **not been verified** by the maintainer yet.
300
+
301
+ We especially need help testing on:
302
+
303
+ - **macOS** — `translate`, `fix`, `verify` (including `javac` / Android Studio terminal)
304
+ - **Linux** — same workflow, plus common CI environments
305
+
306
+ If you use another OS, please try the [quick start](#quick-start) workflow and report what you find:
307
+
308
+ - **Works?** — open a [GitHub issue](https://github.com/BharathKmalviya/android-llm-localization/issues) titled e.g. `Confirmed working on macOS 14` with your OS, Python version, and provider used
309
+ - **Broken?** — open a [bug report](https://github.com/BharathKmalviya/android-llm-localization/issues/new?template=bug_report.md) with the full error output
310
+ - **Want to help more?** — see [Contributing](#contributing) and [CONTRIBUTING.md](CONTRIBUTING.md)
311
+
312
+ Cross-platform fixes and test notes in pull requests are very welcome.
313
+
314
+ ---
315
+
316
+ ## Limitations
317
+
318
+ | Topic | Detail |
319
+ |---|---|
320
+ | **Platform testing** | Maintainer-tested on **Windows only** — macOS and Linux need community verification (see [Platform support](#platform-support)) |
321
+ | **Scope** | Translates `values/strings.xml` only — not `plurals.xml`, `arrays.xml`, or other resource files |
322
+ | **Overwrite** | Each run replaces the entire `strings.xml` in each locale folder with a fresh LLM translation |
323
+ | **Folder scan** | Without `--languages`, every `values-*` folder is treated as a locale. Qualifier-only folders like `values-night` or `values-sw600dp` may be picked up incorrectly — prefer `--languages` or keep only locale folders in `res/` |
324
+ | **Network** | `translate` requires internet access to reach the LLM API (except local `custom` providers) |
325
+ | **JDK** | `verify` requires `javac` on your PATH |
326
+
327
+ ---
328
+
329
+ ## Troubleshooting
330
+
331
+ | Problem | What to try |
332
+ |---|---|
333
+ | `Could not find English strings.xml` | Check `--res-dir` points to your `res/` folder and `values/strings.xml` exists |
334
+ | `No locale directories found` | Add `--languages hi,es,fr` or create `values-<lang>/` folders manually |
335
+ | API auth errors | Confirm your key env var or `--api-key` matches the `--provider` |
336
+ | `javac` not found | Install a JDK or run `verify` from Android Studio's terminal |
337
+ | Build fails on apostrophes | Run `android-localise fix` before building |
338
+ | `%` crashes at runtime | Run `android-localise verify` — it catches bad format specifiers before release |
339
+ | Wrong folder translated | Use `--languages` to target exact locale codes instead of folder scan |
340
+
341
+ ---
342
+
281
343
  ## Roadmap
282
344
 
283
345
  - [ ] **iOS support** — translate `Localizable.strings` and `Localizable.xcstrings` for iOS/macOS apps. The LLM prompt and provider logic is already in place — it mainly needs a parser for Apple's strings format and the right folder structure (`<lang>.lproj/`). Good first contribution if you're familiar with iOS projects.
346
+ - [ ] **Smarter locale folder detection** — skip non-locale `values-*` qualifiers (`night`, `sw600dp`, `v21`, etc.) when scanning without `--languages`
347
+ - [ ] **Automated test suite** — unit tests for `fix`, XML parsing, and format-specifier edge cases
348
+ - [ ] **Cross-platform verification** — confirm `translate`, `fix`, and `verify` on macOS and Linux (Windows is maintainer-tested today)
284
349
 
285
350
  ---
286
351
 
287
352
  ## Contributing
288
353
 
289
- Bug reports and pull requests are welcome. For larger changes, open an issue first.
354
+ Bug reports, pull requests, and **cross-platform testing** are all welcome. For larger changes, open an issue first.
355
+
356
+ **No code required** — if you are on macOS or Linux, running the tool and filing an issue (pass or fail) is a real contribution. See [Platform support](#platform-support).
357
+
358
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development workflow, branch strategy, and release process.
290
359
 
291
360
  ```bash
292
361
  git clone https://github.com/BharathKmalviya/android-llm-localization
293
362
  cd android-llm-localization
363
+ git checkout dev
294
364
  pip install -e .
295
365
  ```
296
366
 
297
- Releases are automated via GitHub Actions — bump the version in `pyproject.toml` and `__init__.py`, update `CHANGELOG.md`, and push to `master`.
367
+ Day-to-day work happens on the `dev` branch. Releases are merged to `master` via pull request, which triggers automated PyPI publishing.
368
+
369
+ ---
370
+
371
+ ## Security
372
+
373
+ To report a security vulnerability, see [SECURITY.md](SECURITY.md). Please do not open public issues for security-sensitive reports.
298
374
 
299
375
  ---
300
376
 
@@ -1,10 +1,12 @@
1
- # android-llm-localization
1
+ # android-localisation
2
2
 
3
3
  [![PyPI version](https://img.shields.io/pypi/v/android-localisation.svg)](https://pypi.org/project/android-localisation/)
4
4
  [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://pypi.org/project/android-localisation/)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
6
 
7
- Translate your Android `strings.xml` into multiple languages using AI — Gemini, OpenAI, Anthropic, or a local model via Ollama. No paid service, no CSV exports, no copy-paste.
7
+ **PyPI:** [`android-localisation`](https://pypi.org/project/android-localisation/) · **CLI:** `android-localise` · **Repo:** [android-llm-localization](https://github.com/BharathKmalviya/android-llm-localization)
8
+
9
+ Translate your Android `strings.xml` into multiple languages using AI — Gemini, OpenAI, Anthropic, or a local model via Ollama. No paid translation service, no CSV exports, no copy-paste.
8
10
 
9
11
  ---
10
12
 
@@ -58,7 +60,7 @@ When you run `android-localise translate --api-key YOUR_KEY`, here's exactly wha
58
60
  | What | Default |
59
61
  |---|---|
60
62
  | Provider | Gemini |
61
- | Model | `gemini-2.5-flash` |
63
+ | Model | `gemini-3.5-flash` |
62
64
  | Source directory | `app/src/main/res` |
63
65
  | Delay between requests | 5 seconds |
64
66
  | App context | none (generic prompt) |
@@ -122,6 +124,7 @@ android-localise translate \
122
124
  | `--res-dir` | Path to your `res/` folder | `app/src/main/res` |
123
125
  | `--base-url` | API endpoint for local/custom providers | — |
124
126
  | `--sleep` | Seconds to wait between language requests | `5.0` |
127
+ | `--timeout` | Seconds to wait for each API response (retries up to 3 times on timeout) | `180` |
125
128
 
126
129
  ---
127
130
 
@@ -129,10 +132,13 @@ android-localise translate \
129
132
 
130
133
  ```bash
131
134
  android-localise fix
135
+ android-localise fix --res-dir path/to/res
132
136
  ```
133
137
 
134
138
  LLMs occasionally produce output that looks correct but breaks the Android build — curly apostrophes (`'`) instead of escaped ones (`\'`), unescaped double quotes, or mangled `%` signs. This command scans every translated `strings.xml` and corrects these silently.
135
139
 
140
+ Strings marked `formatted="false"` are skipped — their `%` signs are literal, not format specifiers.
141
+
136
142
  Always run this before `verify` and before building.
137
143
 
138
144
  ---
@@ -141,11 +147,12 @@ Always run this before `verify` and before building.
141
147
 
142
148
  ```bash
143
149
  android-localise verify
150
+ android-localise verify --res-dir path/to/res
144
151
  ```
145
152
 
146
153
  Takes every translated string that contains a format specifier (`%1$s`, `%d`, `%1$f`, etc.) and calls `String.format()` on it using Java's actual runtime. If a translated string would throw `UnknownFormatConversionException` or `MissingFormatArgumentException` in your app, this catches it before your users do.
147
154
 
148
- Requires `javac` in your PATH. If you don't have it system-wide, run this from the Terminal tab inside Android Studio — it ships with a JDK.
155
+ Strings marked `formatted="false"` are skipped. Requires `javac` in your PATH. If you don't have it system-wide, run this from the Terminal tab inside Android Studio — it ships with a JDK.
149
156
 
150
157
  ---
151
158
 
@@ -162,21 +169,21 @@ Lists every available model and fallback for each provider.
162
169
 
163
170
  ## Providers
164
171
 
165
- By default the tool uses Gemini with `gemini-2.5-flash`. You can switch providers with `--provider` and optionally pin a specific model with `--model`.
172
+ By default the tool uses Gemini with `gemini-3.5-flash`. You can switch providers with `--provider` and optionally pin a specific model with `--model`.
166
173
 
167
174
  | Provider | Default model | Fallbacks | API key env var |
168
175
  |---|---|---|---|
169
- | `gemini` _(default)_ | `gemini-2.5-flash` | `gemini-2.0-flash` → `gemini-1.5-flash` → `gemini-1.5-pro` | `GEMINI_API_KEY` |
170
- | `openai` | `gpt-4o-mini` | `gpt-4o` → `gpt-3.5-turbo` | `OPENAI_API_KEY` |
171
- | `anthropic` | `claude-3-5-haiku-latest` | `claude-3-5-sonnet-latest` → `claude-3-opus-latest` | `ANTHROPIC_API_KEY` |
172
- | `custom` | set with `--model` | none | — |
176
+ | `gemini` _(default)_ | `gemini-3.5-flash` | `gemini-3.1-flash-lite` → `gemini-2.5-flash` → `gemini-2.5-flash-lite` | `GEMINI_API_KEY` |
177
+ | `openai` | `gpt-5.4-mini` | `gpt-5-mini` → `gpt-4o-mini` | `OPENAI_API_KEY` |
178
+ | `anthropic` | `claude-haiku-4-5` | `claude-sonnet-4-6` → `claude-opus-4-8` | `ANTHROPIC_API_KEY` |
179
+ | `custom` | set with `--model` | none | `OPENAI_API_KEY` (optional) |
173
180
 
174
181
  If the default model returns a "model not found" error (e.g. it was deprecated), the tool automatically retries with the next fallback. If you pin a model with `--model`, no fallback is used.
175
182
 
176
183
  **Using OpenAI:**
177
184
  ```bash
178
185
  android-localise translate --provider openai --api-key YOUR_KEY
179
- android-localise translate --provider openai --model gpt-4o --api-key YOUR_KEY
186
+ android-localise translate --provider openai --model gpt-5.4-mini --api-key YOUR_KEY
180
187
  ```
181
188
 
182
189
  **Using Anthropic:**
@@ -211,6 +218,9 @@ export GEMINI_API_KEY=your_key
211
218
 
212
219
  # Windows PowerShell
213
220
  $env:GEMINI_API_KEY = "your_key"
221
+
222
+ # Windows CMD
223
+ set GEMINI_API_KEY=your_key
214
224
  ```
215
225
 
216
226
  Then just run:
@@ -223,19 +233,25 @@ android-localise translate
223
233
  | `GEMINI_API_KEY` | `--provider gemini` |
224
234
  | `OPENAI_API_KEY` | `--provider openai` and `--provider custom` |
225
235
  | `ANTHROPIC_API_KEY` | `--provider anthropic` |
236
+ | `API_KEY` | fallback for any provider if the provider-specific var is not set |
226
237
 
227
238
  ---
228
239
 
229
240
  ## Full workflow example
230
241
 
231
242
  ```bash
232
- # First time setup — create locale folders
243
+ # First time setup — create locale folders (macOS / Linux)
233
244
  mkdir -p app/src/main/res/values-hi
234
245
  mkdir -p app/src/main/res/values-es
235
246
  mkdir -p app/src/main/res/values-de
236
247
 
248
+ # Windows PowerShell
249
+ New-Item -ItemType Directory -Force app/src/main/res/values-hi
250
+ New-Item -ItemType Directory -Force app/src/main/res/values-es
251
+ New-Item -ItemType Directory -Force app/src/main/res/values-de
252
+
237
253
  # Set your key once
238
- export GEMINI_API_KEY=your_key
254
+ export GEMINI_API_KEY=your_key # or $env:GEMINI_API_KEY on Windows
239
255
 
240
256
  # Translate, fix, verify
241
257
  android-localise translate --app-context "a habit tracking app"
@@ -250,23 +266,83 @@ After this, whenever you add or change strings in your English `strings.xml`, ru
250
266
 
251
267
  ---
252
268
 
269
+ ## Platform support
270
+
271
+ This project is developed and **manually tested on Windows only** at the moment. It is written in pure Python (stdlib only) and should run on macOS and Linux, but those platforms have **not been verified** by the maintainer yet.
272
+
273
+ We especially need help testing on:
274
+
275
+ - **macOS** — `translate`, `fix`, `verify` (including `javac` / Android Studio terminal)
276
+ - **Linux** — same workflow, plus common CI environments
277
+
278
+ If you use another OS, please try the [quick start](#quick-start) workflow and report what you find:
279
+
280
+ - **Works?** — open a [GitHub issue](https://github.com/BharathKmalviya/android-llm-localization/issues) titled e.g. `Confirmed working on macOS 14` with your OS, Python version, and provider used
281
+ - **Broken?** — open a [bug report](https://github.com/BharathKmalviya/android-llm-localization/issues/new?template=bug_report.md) with the full error output
282
+ - **Want to help more?** — see [Contributing](#contributing) and [CONTRIBUTING.md](CONTRIBUTING.md)
283
+
284
+ Cross-platform fixes and test notes in pull requests are very welcome.
285
+
286
+ ---
287
+
288
+ ## Limitations
289
+
290
+ | Topic | Detail |
291
+ |---|---|
292
+ | **Platform testing** | Maintainer-tested on **Windows only** — macOS and Linux need community verification (see [Platform support](#platform-support)) |
293
+ | **Scope** | Translates `values/strings.xml` only — not `plurals.xml`, `arrays.xml`, or other resource files |
294
+ | **Overwrite** | Each run replaces the entire `strings.xml` in each locale folder with a fresh LLM translation |
295
+ | **Folder scan** | Without `--languages`, every `values-*` folder is treated as a locale. Qualifier-only folders like `values-night` or `values-sw600dp` may be picked up incorrectly — prefer `--languages` or keep only locale folders in `res/` |
296
+ | **Network** | `translate` requires internet access to reach the LLM API (except local `custom` providers) |
297
+ | **JDK** | `verify` requires `javac` on your PATH |
298
+
299
+ ---
300
+
301
+ ## Troubleshooting
302
+
303
+ | Problem | What to try |
304
+ |---|---|
305
+ | `Could not find English strings.xml` | Check `--res-dir` points to your `res/` folder and `values/strings.xml` exists |
306
+ | `No locale directories found` | Add `--languages hi,es,fr` or create `values-<lang>/` folders manually |
307
+ | API auth errors | Confirm your key env var or `--api-key` matches the `--provider` |
308
+ | `javac` not found | Install a JDK or run `verify` from Android Studio's terminal |
309
+ | Build fails on apostrophes | Run `android-localise fix` before building |
310
+ | `%` crashes at runtime | Run `android-localise verify` — it catches bad format specifiers before release |
311
+ | Wrong folder translated | Use `--languages` to target exact locale codes instead of folder scan |
312
+
313
+ ---
314
+
253
315
  ## Roadmap
254
316
 
255
317
  - [ ] **iOS support** — translate `Localizable.strings` and `Localizable.xcstrings` for iOS/macOS apps. The LLM prompt and provider logic is already in place — it mainly needs a parser for Apple's strings format and the right folder structure (`<lang>.lproj/`). Good first contribution if you're familiar with iOS projects.
318
+ - [ ] **Smarter locale folder detection** — skip non-locale `values-*` qualifiers (`night`, `sw600dp`, `v21`, etc.) when scanning without `--languages`
319
+ - [ ] **Automated test suite** — unit tests for `fix`, XML parsing, and format-specifier edge cases
320
+ - [ ] **Cross-platform verification** — confirm `translate`, `fix`, and `verify` on macOS and Linux (Windows is maintainer-tested today)
256
321
 
257
322
  ---
258
323
 
259
324
  ## Contributing
260
325
 
261
- Bug reports and pull requests are welcome. For larger changes, open an issue first.
326
+ Bug reports, pull requests, and **cross-platform testing** are all welcome. For larger changes, open an issue first.
327
+
328
+ **No code required** — if you are on macOS or Linux, running the tool and filing an issue (pass or fail) is a real contribution. See [Platform support](#platform-support).
329
+
330
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full development workflow, branch strategy, and release process.
262
331
 
263
332
  ```bash
264
333
  git clone https://github.com/BharathKmalviya/android-llm-localization
265
334
  cd android-llm-localization
335
+ git checkout dev
266
336
  pip install -e .
267
337
  ```
268
338
 
269
- Releases are automated via GitHub Actions — bump the version in `pyproject.toml` and `__init__.py`, update `CHANGELOG.md`, and push to `master`.
339
+ Day-to-day work happens on the `dev` branch. Releases are merged to `master` via pull request, which triggers automated PyPI publishing.
340
+
341
+ ---
342
+
343
+ ## Security
344
+
345
+ To report a security vulnerability, see [SECURITY.md](SECURITY.md). Please do not open public issues for security-sensitive reports.
270
346
 
271
347
  ---
272
348
 
@@ -2,4 +2,4 @@
2
2
  android-localisation: Zero-dependency Android strings.xml translation using LLMs.
3
3
  """
4
4
 
5
- __version__ = "1.0.3"
5
+ __version__ = "1.0.5"
@@ -31,6 +31,11 @@ def main():
31
31
  translate_parser.add_argument("--base-url", help="Custom OpenAI-compatible endpoint URL (required for 'custom' provider)")
32
32
  translate_parser.add_argument("--app-context", help="Short description of your app for better translations")
33
33
  translate_parser.add_argument("--sleep", type=float, default=5.0, help="Seconds between API requests (default: 5.0)")
34
+ from android_localisation.translate import DEFAULT_API_TIMEOUT
35
+ translate_parser.add_argument(
36
+ "--timeout", type=float, default=DEFAULT_API_TIMEOUT,
37
+ help=f"Seconds to wait for each API response (default: {DEFAULT_API_TIMEOUT})",
38
+ )
34
39
  translate_parser.add_argument("--languages", help="Comma-separated language codes, e.g. hi,es,fr,de — creates folders and strings.xml automatically")
35
40
 
36
41
  # --- fix ---
@@ -75,7 +80,7 @@ def main():
75
80
  print(" → Any model name your local server supports (must use --model)")
76
81
  print()
77
82
  print(" Tip: use --model to pick any model, e.g:")
78
- print(" android-localise translate --provider openai --model gpt-4o --api-key KEY")
83
+ print(" android-localise translate --provider openai --model gpt-5.4-mini --api-key KEY")
79
84
  print()
80
85
 
81
86
 
@@ -65,7 +65,11 @@ def main(args=None):
65
65
  content = f.read()
66
66
 
67
67
  def fix_match(m):
68
- return m.group(1) + _fix_text(m.group(2)) + m.group(3)
68
+ opening_tag = m.group(1)
69
+ # Skip strings marked formatted="false" — their % signs are literal, not specifiers
70
+ if 'formatted="false"' in opening_tag.lower() or "formatted='false'" in opening_tag.lower():
71
+ return m.group(0)
72
+ return opening_tag + _fix_text(m.group(2)) + m.group(3)
69
73
 
70
74
  new_content = re.sub(
71
75
  r'(<string[^>]*name="[^"]*"[^>]*>)(.*?)(</string>)',