@@ -303,11 +303,13 @@ def _clean_response(response: str) -> str:
303303 return response
304304
305305
306- def validate_coverage (files_arg : str ) -> int :
306+ def validate_coverage (files_arg : str , ignore_error : bool = False ) -> int :
307307 """Check that every msgstr in the given PO files is non-empty.
308308
309309 Prints a per-file summary and returns 0 when all files pass,
310- 1 when any file has untranslated entries.
310+ 1 when any file has untranslated entries (unless *ignore_error* is True,
311+ in which case untranslated entries only produce warnings and the exit
312+ code is always 0).
311313 """
312314 file_list = [f .strip () for f in files_arg .split ("," ) if f .strip ()]
313315 total_entries = 0
@@ -332,7 +334,8 @@ def validate_coverage(files_arg: str) -> int:
332334 untranslated += len (empty )
333335
334336 if empty :
335- print (f" FAIL: { path .name } — { len (empty )} /{ file_entries } untranslated" )
337+ label = "WARN" if ignore_error else "FAIL"
338+ print (f" { label } : { path .name } — { len (empty )} /{ file_entries } untranslated" )
336339 for e in empty [:5 ]:
337340 preview = e .msgid [:80 ].replace ("\n " , "\\ n" )
338341 print (f' msgid="{ preview } ..."' )
@@ -346,6 +349,10 @@ def validate_coverage(files_arg: str) -> int:
346349 f"\n Coverage: { total_entries - untranslated } /{ total_entries } translated "
347350 f"({ untranslated } missing) in { len (file_list )} file(s)"
348351 )
352+ if ignore_error :
353+ if failed_files :
354+ print ("Validation errors ignored (--ignore-validation-error)." )
355+ return 0
349356 return 1 if failed_files else 0
350357
351358
@@ -360,10 +367,16 @@ async def async_main():
360367 action = "store_true" ,
361368 help = "Only validate translation coverage, do not translate" ,
362369 )
370+ parser .add_argument (
371+ "--ignore-validation-error" ,
372+ action = "store_true" ,
373+ help = "When used with --validate-only, print warnings instead of failing on untranslated entries. "
374+ "When used without --validate-only, translation failures do not cause a non-zero exit code." ,
375+ )
363376 args = parser .parse_args ()
364377
365378 if args .validate_only :
366- return validate_coverage (args .files )
379+ return validate_coverage (args .files , ignore_error = args . ignore_validation_error )
367380
368381 api_key = args .api_key or os .getenv ("DEEPSEEK_API_KEY" )
369382 if not api_key :
@@ -391,6 +404,10 @@ async def async_main():
391404 out .write_text (json .dumps (results , indent = 2 , ensure_ascii = False ), encoding = "utf-8" )
392405
393406 print (f"\n Result: { len (success_files )} /{ len (file_list )} translated -> { args .output_json } " )
407+ if args .ignore_validation_error :
408+ if len (success_files ) < len (file_list ):
409+ print ("Translation errors ignored (--ignore-validation-error), continuing with successful files." )
410+ return 0
394411 return 0 if success_files else 1
395412
396413
0 commit comments