android-localisation 1.0.5__tar.gz → 1.0.7__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 (17) hide show
  1. {android_localisation-1.0.5/android_localisation.egg-info → android_localisation-1.0.7}/PKG-INFO +2 -2
  2. {android_localisation-1.0.5 → android_localisation-1.0.7}/README.md +1 -1
  3. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation/__init__.py +1 -1
  4. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation/cli.py +2 -2
  5. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation/fix.py +1 -1
  6. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation/translate.py +22 -9
  7. {android_localisation-1.0.5 → android_localisation-1.0.7/android_localisation.egg-info}/PKG-INFO +2 -2
  8. {android_localisation-1.0.5 → android_localisation-1.0.7}/pyproject.toml +1 -1
  9. {android_localisation-1.0.5 → android_localisation-1.0.7}/LICENSE +0 -0
  10. {android_localisation-1.0.5 → android_localisation-1.0.7}/MANIFEST.in +0 -0
  11. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation/java/VerifyStrings.java +0 -0
  12. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation/verify.py +0 -0
  13. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation.egg-info/SOURCES.txt +0 -0
  14. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation.egg-info/dependency_links.txt +0 -0
  15. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation.egg-info/entry_points.txt +0 -0
  16. {android_localisation-1.0.5 → android_localisation-1.0.7}/android_localisation.egg-info/top_level.txt +0 -0
  17. {android_localisation-1.0.5 → android_localisation-1.0.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: android-localisation
3
- Version: 1.0.5
3
+ Version: 1.0.7
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
@@ -152,7 +152,7 @@ android-localise translate \
152
152
  | `--res-dir` | Path to your `res/` folder | `app/src/main/res` |
153
153
  | `--base-url` | API endpoint for local/custom providers | — |
154
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` |
155
+ | `--timeout` | Seconds to wait for each API response (up to 3 attempts on timeout) | `180` |
156
156
 
157
157
  ---
158
158
 
@@ -124,7 +124,7 @@ android-localise translate \
124
124
  | `--res-dir` | Path to your `res/` folder | `app/src/main/res` |
125
125
  | `--base-url` | API endpoint for local/custom providers | — |
126
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` |
127
+ | `--timeout` | Seconds to wait for each API response (up to 3 attempts on timeout) | `180` |
128
128
 
129
129
  ---
130
130
 
@@ -2,4 +2,4 @@
2
2
  android-localisation: Zero-dependency Android strings.xml translation using LLMs.
3
3
  """
4
4
 
5
- __version__ = "1.0.5"
5
+ __version__ = "1.0.7"
@@ -31,10 +31,10 @@ 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
34
+ from android_localisation.translate import DEFAULT_API_TIMEOUT, MAX_TIMEOUT_RETRIES
35
35
  translate_parser.add_argument(
36
36
  "--timeout", type=float, default=DEFAULT_API_TIMEOUT,
37
- help=f"Seconds to wait for each API response (default: {DEFAULT_API_TIMEOUT})",
37
+ help=f"Seconds to wait for each API response, up to {MAX_TIMEOUT_RETRIES + 1} attempts on timeout (default: {DEFAULT_API_TIMEOUT})",
38
38
  )
39
39
  translate_parser.add_argument("--languages", help="Comma-separated language codes, e.g. hi,es,fr,de — creates folders and strings.xml automatically")
40
40
 
@@ -67,7 +67,7 @@ def main(args=None):
67
67
  def fix_match(m):
68
68
  opening_tag = m.group(1)
69
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():
70
+ if re.search(r"\bformatted\s*=\s*['\"]false['\"]", opening_tag, flags=re.IGNORECASE):
71
71
  return m.group(0)
72
72
  return opening_tag + _fix_text(m.group(2)) + m.group(3)
73
73
 
@@ -79,7 +79,7 @@ Translate the English `strings.xml` below for {context_str} into the language fo
79
79
  For example, `values-hi` is Hindi, `values-es-rES` is Spanish (Spain), `values-zh-rTW` is Traditional Chinese, `values-ar` is Arabic, etc.
80
80
 
81
81
  STRICT GUIDELINES:
82
- 1. Translate only the string values — never the keys, XML tags, or attributes.
82
+ 1. Translate only the string values — preserve keys, tags, and attributes (name, translatable, formatted) exactly as in the source.
83
83
  2. Use natural, human-sounding language. Simple everyday mobile UI tone. Not robotic or word-for-word.
84
84
  3. Preserve ALL placeholders exactly as-is: %s, %d, %1$s, %1$d, %2$s, etc.
85
85
  4. Preserve ALL escape sequences exactly as-is: \\n, \\', \\", \\\\.
@@ -89,7 +89,7 @@ STRICT GUIDELINES:
89
89
  - Start with: <?xml version="1.0" encoding="utf-8"?>
90
90
  - Use plain <resources> with NO namespace attributes (no xmlns:xliff or any other xmlns)
91
91
  - Every string on its own line: <string name="key">translated value</string>
92
- - No CDATA, no extra attributes on <string> tags except name and translatable
92
+ - No CDATA, no extra attributes on <string> tags except name, translatable, and formatted
93
93
  8. Return ONLY the raw XML. No markdown, no code fences, no explanation.
94
94
 
95
95
  SOURCE XML:
@@ -111,8 +111,12 @@ def clean_xml_response(result):
111
111
  result = result[:-3]
112
112
  result = result.strip()
113
113
 
114
- # Strip any xmlns namespace attributes from <resources> tag — not valid in standard Android strings.xml
115
- result = re.sub(r'(<resources)\s+[^>]*?(>)', r'\1\2', result)
114
+ # Strip xmlns namespace declarations from <resources> (leave other attributes intact)
115
+ def _strip_xmlns(m):
116
+ attrs = re.sub(r"""\s+xmlns(?::\w+)?\s*=\s*(['"]).*?\1""", "", m.group(2))
117
+ return m.group(1) + attrs + m.group(3)
118
+
119
+ result = re.sub(r"(<resources)([^>]*)(>)", _strip_xmlns, result, count=1)
116
120
 
117
121
  return result
118
122
 
@@ -135,6 +139,15 @@ def _is_model_not_found(http_code, body):
135
139
  ])
136
140
 
137
141
 
142
+ def _is_timeout_error(exc):
143
+ """True for direct timeouts and URLError wrappers (common from urllib.request.urlopen)."""
144
+ if isinstance(exc, (TimeoutError, socket.timeout)):
145
+ return True
146
+ return isinstance(exc, urllib.error.URLError) and isinstance(
147
+ exc.reason, (TimeoutError, socket.timeout)
148
+ )
149
+
150
+
138
151
  def _urlopen_with_retries(req, provider_label, timeout):
139
152
  """
140
153
  Execute an HTTP request with timeout/network error handling and retries on timeout.
@@ -153,14 +166,14 @@ def _urlopen_with_retries(req, provider_label, timeout):
153
166
  model_gone = _is_model_not_found(e.code, body)
154
167
  print(f" ❌ {provider_label} API Error: {e.code} - {body}")
155
168
  return None, model_gone
156
- except (TimeoutError, socket.timeout):
169
+ except (TimeoutError, socket.timeout, urllib.error.URLError) as e:
170
+ if not _is_timeout_error(e):
171
+ print(f" ❌ {provider_label} network error: {e.reason}")
172
+ return None, False
157
173
  if attempt < MAX_TIMEOUT_RETRIES:
158
174
  continue
159
175
  print(f" ❌ {provider_label} API timed out after {timeout}s ({MAX_TIMEOUT_RETRIES + 1} attempts)")
160
176
  return None, False
161
- except urllib.error.URLError as e:
162
- print(f" ❌ {provider_label} network error: {e.reason}")
163
- return None, False
164
177
  return None, False
165
178
 
166
179
 
@@ -274,7 +287,7 @@ def _parse_args(args=None):
274
287
  parser.add_argument("--app-context")
275
288
  parser.add_argument("--sleep", type=float, default=5.0)
276
289
  parser.add_argument("--timeout", type=float, default=DEFAULT_API_TIMEOUT,
277
- help=f"Seconds to wait for each API response (default: {DEFAULT_API_TIMEOUT})")
290
+ help=f"Seconds to wait for each API response, up to {MAX_TIMEOUT_RETRIES + 1} attempts on timeout (default: {DEFAULT_API_TIMEOUT})")
278
291
  parser.add_argument("--languages", help="Comma-separated language codes to translate into, e.g. hi,es,fr,de. Creates folders automatically if they don't exist.")
279
292
  return parser.parse_args(args)
280
293
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: android-localisation
3
- Version: 1.0.5
3
+ Version: 1.0.7
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
@@ -152,7 +152,7 @@ android-localise translate \
152
152
  | `--res-dir` | Path to your `res/` folder | `app/src/main/res` |
153
153
  | `--base-url` | API endpoint for local/custom providers | — |
154
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` |
155
+ | `--timeout` | Seconds to wait for each API response (up to 3 attempts on timeout) | `180` |
156
156
 
157
157
  ---
158
158
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "android-localisation"
7
- version = "1.0.5"
7
+ version = "1.0.7"
8
8
  description = "Zero-dependency Android strings.xml translation and verification using LLMs (Gemini, OpenAI, Anthropic, Ollama)."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }