)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"9863a4f2d09ee481974ba4fc6bc7555734bc9f85","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":6,"id":"10c92071_4b18c5d7","updated":"2025-09-25 14:50:58.000000000","message":"https://review.opendev.org/c/openstack/i18n/+/961075\n\nIn another patch handling migration tools, the contents were placed under the tools/migration folder. Please move this patch to the same location.","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"2039ed22_66be1d9b","in_reply_to":"10c92071_4b18c5d7","updated":"2025-10-14 11:01:11.000000000","message":"Done","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"77d753d7_d8c9a5a5","updated":"2025-10-11 18:50:42.000000000","message":"Thank you for the patch.\n\nAlso I think \"tools/migration\" needs to be moved to like \"tools/weblate/language\"","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"136d2179_ec713d89","in_reply_to":"77d753d7_d8c9a5a5","updated":"2025-10-14 11:01:11.000000000","message":"Seongsoo Cho requested to move it under tools/migration since other related patches are also located there, so I placed it in that directory. Would you still prefer that I move it to tools/weblate/language instead?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"3a0c635d61c1c81c34fd9522fea5dcdd2eb0ca05","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"d12dc665_52e2a7e2","updated":"2025-12-03 14:31:52.000000000","message":"I revised the overlapping parts with weblate_utils.py so that they now use the functionality provided by weblate_utils.py. I have incorporated all of your comments as well.\nPlease let me know if you have any additional feedback.","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"f054f0bc7608f580881fc47717078aea1d08b41b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":19,"id":"0c05b1ae_caa29f58","updated":"2025-12-16 11:02:11.000000000","message":"I have addressed the feedback from @SOokju and left comments accordingly.\nI would appreciate any additional feedback.\nFeedback from other reviewers would also be very welcome.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"}],"tools/migration/README.rst":[{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":1,"context_line":"Weblate Language Management Scripts"},{"line_number":2,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"This directory provides automation tools for aligning Weblate’s language set with Zanata."},{"line_number":5,"context_line":"They use the Weblate REST API to handle bulk operations efficiently, reducing manual work and"},{"line_number":6,"context_line":"keeping language configurations consistent."},{"line_number":7,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"63d2e770_6f018f24","line":4,"range":{"start_line":4,"start_character":45,"end_line":4,"end_character":54},"updated":"2025-10-11 18:50:42.000000000","message":"aligning for what? synchronizing with Zanata is right, or making consistent is right?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"a67d8f13408e58aae70169ab83e70f2130930604","unresolved":false,"context_lines":[{"line_number":1,"context_line":"Weblate Language Management Scripts"},{"line_number":2,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"This directory provides automation tools for aligning Weblate’s language set with Zanata."},{"line_number":5,"context_line":"They use the Weblate REST API to handle bulk operations efficiently, reducing manual work and"},{"line_number":6,"context_line":"keeping language configurations consistent."},{"line_number":7,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"7bf6885a_d8823086","line":4,"range":{"start_line":4,"start_character":45,"end_line":4,"end_character":54},"in_reply_to":"3f407b2a_9a34a910","updated":"2025-10-30 15:50:19.000000000","message":"Then please change the description. My intention of the initial comment that you need to better clarify the doc by answering my question, not just replying here.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":1,"context_line":"Weblate Language Management Scripts"},{"line_number":2,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"This directory provides automation tools for aligning Weblate’s language set with Zanata."},{"line_number":5,"context_line":"They use the Weblate REST API to handle bulk operations efficiently, reducing manual work and"},{"line_number":6,"context_line":"keeping language configurations consistent."},{"line_number":7,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"3f407b2a_9a34a910","line":4,"range":{"start_line":4,"start_character":45,"end_line":4,"end_character":54},"in_reply_to":"63d2e770_6f018f24","updated":"2025-10-14 11:01:11.000000000","message":"Making consistent is right","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":2,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"This directory provides automation tools for aligning Weblate’s language set with Zanata."},{"line_number":5,"context_line":"They use the Weblate REST API to handle bulk operations efficiently, reducing manual work and"},{"line_number":6,"context_line":"keeping language configurations consistent."},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"Files"}],"source_content_type":"text/x-rst","patch_set":9,"id":"ec0efe45_584b2979","line":5,"range":{"start_line":5,"start_character":13,"end_line":5,"end_character":30},"updated":"2025-10-11 18:50:42.000000000","message":"Can you specify which Weblate REST API calls the files are used?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"a67d8f13408e58aae70169ab83e70f2130930604","unresolved":false,"context_lines":[{"line_number":2,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"This directory provides automation tools for aligning Weblate’s language set with Zanata."},{"line_number":5,"context_line":"They use the Weblate REST API to handle bulk operations efficiently, reducing manual work and"},{"line_number":6,"context_line":"keeping language configurations consistent."},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"Files"}],"source_content_type":"text/x-rst","patch_set":9,"id":"599f0f41_f5d3c893","line":5,"range":{"start_line":5,"start_character":13,"end_line":5,"end_character":30},"in_reply_to":"7b52706e_55a6db23","updated":"2025-10-30 15:50:19.000000000","message":"Please reflect the clarification into the actual rst file, not commenting here.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":2,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"This directory provides automation tools for aligning Weblate’s language set with Zanata."},{"line_number":5,"context_line":"They use the Weblate REST API to handle bulk operations efficiently, reducing manual work and"},{"line_number":6,"context_line":"keeping language configurations consistent."},{"line_number":7,"context_line":""},{"line_number":8,"context_line":"Files"}],"source_content_type":"text/x-rst","patch_set":9,"id":"7b52706e_55a6db23","line":5,"range":{"start_line":5,"start_character":13,"end_line":5,"end_character":30},"in_reply_to":"ec0efe45_584b2979","updated":"2025-10-14 11:01:11.000000000","message":"This script interacts with the Weblate REST API’s language endpoints only:\nGET /api/languages/{code}/ – retrieve language details\nPOST /api/languages/ – create new languages\nPATCH /api/languages/{code}/ – update existing languages\nThese endpoints are used for synchronizing Zanata language definitions with Weblate during migration.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":16,"context_line":"- **Actions**: Calls Weblate API (``POST`` for create, ``PATCH`` for update)."},{"line_number":17,"context_line":"- **Mode**: Defaults to dry-run; use ``--apply`` to perform real changes."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"delete_languages.py"},{"line_number":20,"context_line":"~~~~~~~~~~~~~~~~~~~"},{"line_number":21,"context_line":"Deletes all or selected languages from Weblate in bulk."},{"line_number":22,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"711c4c05_db28eeb8","line":19,"range":{"start_line":19,"start_character":0,"end_line":19,"end_character":19},"updated":"2025-10-11 18:50:42.000000000","message":"I think it requires Weblate higher-level previleges.. which permission do we need to execute the file? Any user can delete languages on Weblate?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":16,"context_line":"- **Actions**: Calls Weblate API (``POST`` for create, ``PATCH`` for update)."},{"line_number":17,"context_line":"- **Mode**: Defaults to dry-run; use ``--apply`` to perform real changes."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"delete_languages.py"},{"line_number":20,"context_line":"~~~~~~~~~~~~~~~~~~~"},{"line_number":21,"context_line":"Deletes all or selected languages from Weblate in bulk."},{"line_number":22,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"b805217c_adb19b8e","line":19,"range":{"start_line":19,"start_character":0,"end_line":19,"end_character":19},"in_reply_to":"711c4c05_db28eeb8","updated":"2025-10-14 11:01:11.000000000","message":"No, it can only be executed with administrator privileges on Weblate.\nRegular users do not have permission to delete or modify languages through the API.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"a67d8f13408e58aae70169ab83e70f2130930604","unresolved":false,"context_lines":[{"line_number":16,"context_line":"- **Actions**: Calls Weblate API (``POST`` for create, ``PATCH`` for update)."},{"line_number":17,"context_line":"- **Mode**: Defaults to dry-run; use ``--apply`` to perform real changes."},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"delete_languages.py"},{"line_number":20,"context_line":"~~~~~~~~~~~~~~~~~~~"},{"line_number":21,"context_line":"Deletes all or selected languages from Weblate in bulk."},{"line_number":22,"context_line":""}],"source_content_type":"text/x-rst","patch_set":9,"id":"dc2ca179_4e2e1edc","line":19,"range":{"start_line":19,"start_character":0,"end_line":19,"end_character":19},"in_reply_to":"b805217c_adb19b8e","updated":"2025-10-30 15:50:19.000000000","message":"Then please add a note on L32 like:\n\n```\n.. note::\n\n  To execute the file, it requires administrator privileges on Weblate.\n```","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":9,"id":"747a17cf_7d033bfc","line":25,"range":{"start_line":10,"start_character":0,"end_line":25,"end_character":0},"updated":"2025-10-11 18:50:42.000000000","message":"Please also specify example command execution and results.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"e1486a836a0e8d0ecb2521e21a9a3d849639cfcd","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":9,"id":"db2a3cdc_07bf624c","line":25,"range":{"start_line":10,"start_character":0,"end_line":25,"end_character":0},"in_reply_to":"747a17cf_7d033bfc","updated":"2025-10-14 11:05:16.000000000","message":"I’ll add it. Thank you","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"3a0c635d61c1c81c34fd9522fea5dcdd2eb0ca05","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"c1194619_ff45ee01","line":25,"range":{"start_line":10,"start_character":0,"end_line":25,"end_character":0},"in_reply_to":"db2a3cdc_07bf624c","updated":"2025-12-03 14:31:52.000000000","message":"Done","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"}],"tools/migration/create_languages_weblate.py":[{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"# Code normalization"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"def normalize_code(code: str) -\u003e str:"},{"line_number":50,"context_line":"    if not code:"}],"source_content_type":"text/x-python","patch_set":9,"id":"474ab5f5_1d9c20bd","line":47,"range":{"start_line":47,"start_character":0,"end_line":47,"end_character":0},"updated":"2025-10-11 18:50:42.000000000","message":"Why L47-48 is blank?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":44,"context_line":""},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"# Code normalization"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"def normalize_code(code: str) -\u003e str:"},{"line_number":50,"context_line":"    if not code:"}],"source_content_type":"text/x-python","patch_set":9,"id":"a2bc87e1_57a8ed1e","line":47,"range":{"start_line":47,"start_character":0,"end_line":47,"end_character":0},"in_reply_to":"474ab5f5_1d9c20bd","updated":"2025-10-14 11:01:11.000000000","message":"Lines 47–48 are blank because of the PEP 8 style rule: “E302 – expected 2 blank lines, found 1.”\nAccording to PEP 8, top-level function or class definitions must be preceded by two blank lines, so the extra blank line was added to follow that convention.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":53,"context_line":"    return normalized[0].lower() + normalized[1:] if normalized else normalized"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"# Plural parser"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"def parse_plural_forms(pf: str) -\u003e Optional[Tuple[int, str]]:"},{"line_number":59,"context_line":"    if not pf:"}],"source_content_type":"text/x-python","patch_set":9,"id":"17ae829d_3a75cd53","line":56,"updated":"2025-10-11 18:50:42.000000000","message":"Why the two lines are blank?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":53,"context_line":"    return normalized[0].lower() + normalized[1:] if normalized else normalized"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"# Plural parser"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"def parse_plural_forms(pf: str) -\u003e Optional[Tuple[int, str]]:"},{"line_number":59,"context_line":"    if not pf:"}],"source_content_type":"text/x-python","patch_set":9,"id":"1143541a_f8920690","line":56,"in_reply_to":"17ae829d_3a75cd53","updated":"2025-10-14 11:01:11.000000000","message":"This lines are blank because of the PEP 8 style rule: “E302 – expected 2 blank lines, found 1.”\nAccording to PEP 8, top-level function or class definitions must be preceded by two blank lines, so the extra blank line was added to follow that convention.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":73,"context_line":"    return number, formula"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"# Input loaders"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"def load_plural_map(path: str) -\u003e Dict[str, str]:"},{"line_number":79,"context_line":"    with open(path, \"r\", encoding\u003d\"utf-8\") as f:"}],"source_content_type":"text/x-python","patch_set":9,"id":"f7863606_2a9813a9","line":76,"updated":"2025-10-11 18:50:42.000000000","message":"Why the two lines are blank?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":73,"context_line":"    return number, formula"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"# Input loaders"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"def load_plural_map(path: str) -\u003e Dict[str, str]:"},{"line_number":79,"context_line":"    with open(path, \"r\", encoding\u003d\"utf-8\") as f:"}],"source_content_type":"text/x-python","patch_set":9,"id":"e60fa778_1307e796","line":76,"in_reply_to":"f7863606_2a9813a9","updated":"2025-10-14 11:01:11.000000000","message":"This lines are blank because of the PEP 8 style rule: “E302 – expected 2 blank lines, found 1.”\nAccording to PEP 8, top-level function or class definitions must be preceded by two blank lines, so the extra blank line was added to follow that convention.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":100,"context_line":"    return out"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def load_zanata_locales(path: str) -\u003e Dict[str, Dict[str, Any]]:"},{"line_number":104,"context_line":"    with open(path, \"r\", encoding\u003d\"utf-8\") as f:"},{"line_number":105,"context_line":"        arr \u003d json.load(f)"},{"line_number":106,"context_line":"    if not isinstance(arr, list):"}],"source_content_type":"text/x-python","patch_set":9,"id":"02579c65_26e51e73","line":103,"updated":"2025-10-11 18:50:42.000000000","message":"What does the function do?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    return out"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def load_zanata_locales(path: str) -\u003e Dict[str, Dict[str, Any]]:"},{"line_number":104,"context_line":"    with open(path, \"r\", encoding\u003d\"utf-8\") as f:"},{"line_number":105,"context_line":"        arr \u003d json.load(f)"},{"line_number":106,"context_line":"    if not isinstance(arr, list):"}],"source_content_type":"text/x-python","patch_set":9,"id":"87e574d8_cdb1cb94","line":103,"in_reply_to":"02579c65_26e51e73","updated":"2025-10-14 11:01:11.000000000","message":"The function reads a JSON file that contains the list of languages exported from Zanata (previously retrieved via the Zanata API).\nIt then converts this data into a structured Python dictionary, preparing it for later use when creating or updating corresponding languages in Weblate.\nThe corresponding zanata.json file will be included together in this repository.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"a67d8f13408e58aae70169ab83e70f2130930604","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    return out"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def load_zanata_locales(path: str) -\u003e Dict[str, Dict[str, Any]]:"},{"line_number":104,"context_line":"    with open(path, \"r\", encoding\u003d\"utf-8\") as f:"},{"line_number":105,"context_line":"        arr \u003d json.load(f)"},{"line_number":106,"context_line":"    if not isinstance(arr, list):"}],"source_content_type":"text/x-python","patch_set":9,"id":"bf2af215_eef44116","line":103,"in_reply_to":"87e574d8_cdb1cb94","updated":"2025-10-30 15:50:19.000000000","message":"Please add the explanation into the Python file, not here.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":37966,"name":"DaGyeong Kim","display_name":"S0okJu","email":"damekyung98@gmail.com","username":"S0okJu"},"change_message_id":"e1add0d19a3fe9573bc822c9879840e99a7d40ae","unresolved":true,"context_lines":[{"line_number":106,"context_line":"    if not isinstance(arr, list):"},{"line_number":107,"context_line":"        raise ValueError(\"Zanata JSON must be an array.\")"},{"line_number":108,"context_line":"    out: Dict[str, Dict[str, Any]] \u003d {}"},{"line_number":109,"context_line":"    rtl_langs \u003d {\"ar\", \"fa\", \"he\", \"ur\", \"ug\", \"dv\", \"ps\", \"ku_Arab\"}"},{"line_number":110,"context_line":"    for it in arr:"},{"line_number":111,"context_line":"        if not isinstance(it, dict):"},{"line_number":112,"context_line":"            continue"}],"source_content_type":"text/x-python","patch_set":9,"id":"1948759c_f4b17253","line":109,"updated":"2025-10-12 03:18:44.000000000","message":"Q. What does \u0027rtl_langs\u0027 mean?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":106,"context_line":"    if not isinstance(arr, list):"},{"line_number":107,"context_line":"        raise ValueError(\"Zanata JSON must be an array.\")"},{"line_number":108,"context_line":"    out: Dict[str, Dict[str, Any]] \u003d {}"},{"line_number":109,"context_line":"    rtl_langs \u003d {\"ar\", \"fa\", \"he\", \"ur\", \"ug\", \"dv\", \"ps\", \"ku_Arab\"}"},{"line_number":110,"context_line":"    for it in arr:"},{"line_number":111,"context_line":"        if not isinstance(it, dict):"},{"line_number":112,"context_line":"            continue"}],"source_content_type":"text/x-python","patch_set":9,"id":"bbf1c74f_a0e8ad97","line":109,"in_reply_to":"1948759c_f4b17253","updated":"2025-10-14 11:01:11.000000000","message":"rtl_langs is a predefined set of language codes that use right-to-left (RTL) writing systems, such as Arabic (ar), Hebrew (he), and Persian (fa).\nIt is used to mark whether a language should be displayed from right to left in Weblate.\nCurrently, none of the languages in Zanata’s exported list belong to this RTL group.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"a67d8f13408e58aae70169ab83e70f2130930604","unresolved":false,"context_lines":[{"line_number":106,"context_line":"    if not isinstance(arr, list):"},{"line_number":107,"context_line":"        raise ValueError(\"Zanata JSON must be an array.\")"},{"line_number":108,"context_line":"    out: Dict[str, Dict[str, Any]] \u003d {}"},{"line_number":109,"context_line":"    rtl_langs \u003d {\"ar\", \"fa\", \"he\", \"ur\", \"ug\", \"dv\", \"ps\", \"ku_Arab\"}"},{"line_number":110,"context_line":"    for it in arr:"},{"line_number":111,"context_line":"        if not isinstance(it, dict):"},{"line_number":112,"context_line":"            continue"}],"source_content_type":"text/x-python","patch_set":9,"id":"d1389d39_1ed24311","line":109,"in_reply_to":"bbf1c74f_a0e8ad97","updated":"2025-10-30 15:50:19.000000000","message":"Please add the explanation into the Python file as comment, not here.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":128,"context_line":""},{"line_number":129,"context_line":"# Weblate API"},{"line_number":130,"context_line":""},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"class WeblateClient:"},{"line_number":133,"context_line":"    def __init__(self, base_url: str, api_key: str, timeout: int \u003d 30):"},{"line_number":134,"context_line":"        self.base \u003d base_url.rstrip(\"/\")"},{"line_number":135,"context_line":"        self.session \u003d requests.Session()"},{"line_number":136,"context_line":"        self.session.headers.update({"},{"line_number":137,"context_line":"            \"Authorization\": f\"Token {api_key}\","},{"line_number":138,"context_line":"            \"Accept\": \"application/json\","},{"line_number":139,"context_line":"            \"Content-Type\": \"application/json\","},{"line_number":140,"context_line":"        })"},{"line_number":141,"context_line":"        self.timeout \u003d timeout"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def _lang_url(self, code: str) -\u003e str:"},{"line_number":144,"context_line":"        return ("},{"line_number":145,"context_line":"            f\"{self.base}/api/languages/\""},{"line_number":146,"context_line":"            f\"{urllib.parse.quote(code, safe\u003d\u0027\u0027)}/\""},{"line_number":147,"context_line":"        )"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def get_language(self, code: str) -\u003e Tuple[int, Dict[str, Any]]:"},{"line_number":150,"context_line":"        r \u003d self.session.get(self._lang_url(code), timeout\u003dself.timeout)"},{"line_number":151,"context_line":"        if r.status_code \u003d\u003d 200:"},{"line_number":152,"context_line":"            return 200, r.json()"},{"line_number":153,"context_line":"        return r.status_code, {}"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"    def create_language("},{"line_number":156,"context_line":"        self, code: str, name: str, plural_number: int,"},{"line_number":157,"context_line":"        plural_formula: str, direction: Optional[str],"},{"line_number":158,"context_line":"    ) -\u003e Tuple[int, str]:"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"        payload \u003d {"},{"line_number":161,"context_line":"            \"code\": code,"},{"line_number":162,"context_line":"            \"name\": name or code,"},{"line_number":163,"context_line":"            \"plural\": {\"number\": plural_number, \"formula\": plural_formula},"},{"line_number":164,"context_line":"        }"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        if direction in (\"ltr\", \"rtl\"):"},{"line_number":167,"context_line":"            payload[\"direction\"] \u003d direction"},{"line_number":168,"context_line":"        r \u003d self.session.post(f\"{self.base}/api/languages/\","},{"line_number":169,"context_line":"                              json\u003dpayload, timeout\u003dself.timeout)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"        try:"},{"line_number":172,"context_line":"            r.raise_for_status()"},{"line_number":173,"context_line":"            return r.status_code, \"\""},{"line_number":174,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":175,"context_line":"            return r.status_code, r.text"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"    def update_language(self, code: str, name: Optional[str],"},{"line_number":178,"context_line":"                        plural_number: Optional[int], plural_formula:"},{"line_number":179,"context_line":"                            Optional[str]) -\u003e Tuple[int, str]:"},{"line_number":180,"context_line":"        payload: Dict[str, Any] \u003d {}"},{"line_number":181,"context_line":"        if name:"},{"line_number":182,"context_line":"            payload[\"name\"] \u003d name"},{"line_number":183,"context_line":"        if plural_number is not None and plural_formula:"},{"line_number":184,"context_line":"            payload[\"plural\"] \u003d {\"number\": plural_number,"},{"line_number":185,"context_line":"                                 \"formula\": plural_formula}"},{"line_number":186,"context_line":"        if not payload:"},{"line_number":187,"context_line":"            return 200, \"\"  # no changes"},{"line_number":188,"context_line":"        r \u003d self.session.patch(self._lang_url(code), json\u003dpayload,"},{"line_number":189,"context_line":"                               timeout\u003dself.timeout)"},{"line_number":190,"context_line":"        try:"},{"line_number":191,"context_line":"            r.raise_for_status()"},{"line_number":192,"context_line":"            return r.status_code, \"\""},{"line_number":193,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":194,"context_line":"            return r.status_code, r.text"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"# Main"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"eac9e499_147dfe79","line":195,"range":{"start_line":131,"start_character":0,"end_line":195,"end_character":0},"updated":"2025-10-11 18:50:42.000000000","message":"Why did you declare? Can we leverage a file https://opendev.org/openstack/i18n/src/branch/master/tools/weblate/weblate_utils.py ?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"5d840101ec2ad205cafff9d3878686e36b3015f3","unresolved":false,"context_lines":[{"line_number":128,"context_line":""},{"line_number":129,"context_line":"# Weblate API"},{"line_number":130,"context_line":""},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"class WeblateClient:"},{"line_number":133,"context_line":"    def __init__(self, base_url: str, api_key: str, timeout: int \u003d 30):"},{"line_number":134,"context_line":"        self.base \u003d base_url.rstrip(\"/\")"},{"line_number":135,"context_line":"        self.session \u003d requests.Session()"},{"line_number":136,"context_line":"        self.session.headers.update({"},{"line_number":137,"context_line":"            \"Authorization\": f\"Token {api_key}\","},{"line_number":138,"context_line":"            \"Accept\": \"application/json\","},{"line_number":139,"context_line":"            \"Content-Type\": \"application/json\","},{"line_number":140,"context_line":"        })"},{"line_number":141,"context_line":"        self.timeout \u003d timeout"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def _lang_url(self, code: str) -\u003e str:"},{"line_number":144,"context_line":"        return ("},{"line_number":145,"context_line":"            f\"{self.base}/api/languages/\""},{"line_number":146,"context_line":"            f\"{urllib.parse.quote(code, safe\u003d\u0027\u0027)}/\""},{"line_number":147,"context_line":"        )"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def get_language(self, code: str) -\u003e Tuple[int, Dict[str, Any]]:"},{"line_number":150,"context_line":"        r \u003d self.session.get(self._lang_url(code), timeout\u003dself.timeout)"},{"line_number":151,"context_line":"        if r.status_code \u003d\u003d 200:"},{"line_number":152,"context_line":"            return 200, r.json()"},{"line_number":153,"context_line":"        return r.status_code, {}"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"    def create_language("},{"line_number":156,"context_line":"        self, code: str, name: str, plural_number: int,"},{"line_number":157,"context_line":"        plural_formula: str, direction: Optional[str],"},{"line_number":158,"context_line":"    ) -\u003e Tuple[int, str]:"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"        payload \u003d {"},{"line_number":161,"context_line":"            \"code\": code,"},{"line_number":162,"context_line":"            \"name\": name or code,"},{"line_number":163,"context_line":"            \"plural\": {\"number\": plural_number, \"formula\": plural_formula},"},{"line_number":164,"context_line":"        }"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        if direction in (\"ltr\", \"rtl\"):"},{"line_number":167,"context_line":"            payload[\"direction\"] \u003d direction"},{"line_number":168,"context_line":"        r \u003d self.session.post(f\"{self.base}/api/languages/\","},{"line_number":169,"context_line":"                              json\u003dpayload, timeout\u003dself.timeout)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"        try:"},{"line_number":172,"context_line":"            r.raise_for_status()"},{"line_number":173,"context_line":"            return r.status_code, \"\""},{"line_number":174,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":175,"context_line":"            return r.status_code, r.text"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"    def update_language(self, code: str, name: Optional[str],"},{"line_number":178,"context_line":"                        plural_number: Optional[int], plural_formula:"},{"line_number":179,"context_line":"                            Optional[str]) -\u003e Tuple[int, str]:"},{"line_number":180,"context_line":"        payload: Dict[str, Any] \u003d {}"},{"line_number":181,"context_line":"        if name:"},{"line_number":182,"context_line":"            payload[\"name\"] \u003d name"},{"line_number":183,"context_line":"        if plural_number is not None and plural_formula:"},{"line_number":184,"context_line":"            payload[\"plural\"] \u003d {\"number\": plural_number,"},{"line_number":185,"context_line":"                                 \"formula\": plural_formula}"},{"line_number":186,"context_line":"        if not payload:"},{"line_number":187,"context_line":"            return 200, \"\"  # no changes"},{"line_number":188,"context_line":"        r \u003d self.session.patch(self._lang_url(code), json\u003dpayload,"},{"line_number":189,"context_line":"                               timeout\u003dself.timeout)"},{"line_number":190,"context_line":"        try:"},{"line_number":191,"context_line":"            r.raise_for_status()"},{"line_number":192,"context_line":"            return r.status_code, \"\""},{"line_number":193,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":194,"context_line":"            return r.status_code, r.text"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"# Main"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"4c4b46a2_f78cbe63","line":195,"range":{"start_line":131,"start_character":0,"end_line":195,"end_character":0},"in_reply_to":"3a8a3146_12044bf2","updated":"2025-11-09 08:56:47.000000000","message":"Acknowledged","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"a67d8f13408e58aae70169ab83e70f2130930604","unresolved":true,"context_lines":[{"line_number":128,"context_line":""},{"line_number":129,"context_line":"# Weblate API"},{"line_number":130,"context_line":""},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"class WeblateClient:"},{"line_number":133,"context_line":"    def __init__(self, base_url: str, api_key: str, timeout: int \u003d 30):"},{"line_number":134,"context_line":"        self.base \u003d base_url.rstrip(\"/\")"},{"line_number":135,"context_line":"        self.session \u003d requests.Session()"},{"line_number":136,"context_line":"        self.session.headers.update({"},{"line_number":137,"context_line":"            \"Authorization\": f\"Token {api_key}\","},{"line_number":138,"context_line":"            \"Accept\": \"application/json\","},{"line_number":139,"context_line":"            \"Content-Type\": \"application/json\","},{"line_number":140,"context_line":"        })"},{"line_number":141,"context_line":"        self.timeout \u003d timeout"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def _lang_url(self, code: str) -\u003e str:"},{"line_number":144,"context_line":"        return ("},{"line_number":145,"context_line":"            f\"{self.base}/api/languages/\""},{"line_number":146,"context_line":"            f\"{urllib.parse.quote(code, safe\u003d\u0027\u0027)}/\""},{"line_number":147,"context_line":"        )"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def get_language(self, code: str) -\u003e Tuple[int, Dict[str, Any]]:"},{"line_number":150,"context_line":"        r \u003d self.session.get(self._lang_url(code), timeout\u003dself.timeout)"},{"line_number":151,"context_line":"        if r.status_code \u003d\u003d 200:"},{"line_number":152,"context_line":"            return 200, r.json()"},{"line_number":153,"context_line":"        return r.status_code, {}"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"    def create_language("},{"line_number":156,"context_line":"        self, code: str, name: str, plural_number: int,"},{"line_number":157,"context_line":"        plural_formula: str, direction: Optional[str],"},{"line_number":158,"context_line":"    ) -\u003e Tuple[int, str]:"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"        payload \u003d {"},{"line_number":161,"context_line":"            \"code\": code,"},{"line_number":162,"context_line":"            \"name\": name or code,"},{"line_number":163,"context_line":"            \"plural\": {\"number\": plural_number, \"formula\": plural_formula},"},{"line_number":164,"context_line":"        }"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        if direction in (\"ltr\", \"rtl\"):"},{"line_number":167,"context_line":"            payload[\"direction\"] \u003d direction"},{"line_number":168,"context_line":"        r \u003d self.session.post(f\"{self.base}/api/languages/\","},{"line_number":169,"context_line":"                              json\u003dpayload, timeout\u003dself.timeout)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"        try:"},{"line_number":172,"context_line":"            r.raise_for_status()"},{"line_number":173,"context_line":"            return r.status_code, \"\""},{"line_number":174,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":175,"context_line":"            return r.status_code, r.text"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"    def update_language(self, code: str, name: Optional[str],"},{"line_number":178,"context_line":"                        plural_number: Optional[int], plural_formula:"},{"line_number":179,"context_line":"                            Optional[str]) -\u003e Tuple[int, str]:"},{"line_number":180,"context_line":"        payload: Dict[str, Any] \u003d {}"},{"line_number":181,"context_line":"        if name:"},{"line_number":182,"context_line":"            payload[\"name\"] \u003d name"},{"line_number":183,"context_line":"        if plural_number is not None and plural_formula:"},{"line_number":184,"context_line":"            payload[\"plural\"] \u003d {\"number\": plural_number,"},{"line_number":185,"context_line":"                                 \"formula\": plural_formula}"},{"line_number":186,"context_line":"        if not payload:"},{"line_number":187,"context_line":"            return 200, \"\"  # no changes"},{"line_number":188,"context_line":"        r \u003d self.session.patch(self._lang_url(code), json\u003dpayload,"},{"line_number":189,"context_line":"                               timeout\u003dself.timeout)"},{"line_number":190,"context_line":"        try:"},{"line_number":191,"context_line":"            r.raise_for_status()"},{"line_number":192,"context_line":"            return r.status_code, \"\""},{"line_number":193,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":194,"context_line":"            return r.status_code, r.text"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"# Main"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3a8a3146_12044bf2","line":195,"range":{"start_line":131,"start_character":0,"end_line":195,"end_character":0},"in_reply_to":"63c6ce31_98be8a29","updated":"2025-10-30 15:50:19.000000000","message":"I would rather advise you to change the part by leveraging weblate_utils.py file.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":true,"context_lines":[{"line_number":128,"context_line":""},{"line_number":129,"context_line":"# Weblate API"},{"line_number":130,"context_line":""},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"class WeblateClient:"},{"line_number":133,"context_line":"    def __init__(self, base_url: str, api_key: str, timeout: int \u003d 30):"},{"line_number":134,"context_line":"        self.base \u003d base_url.rstrip(\"/\")"},{"line_number":135,"context_line":"        self.session \u003d requests.Session()"},{"line_number":136,"context_line":"        self.session.headers.update({"},{"line_number":137,"context_line":"            \"Authorization\": f\"Token {api_key}\","},{"line_number":138,"context_line":"            \"Accept\": \"application/json\","},{"line_number":139,"context_line":"            \"Content-Type\": \"application/json\","},{"line_number":140,"context_line":"        })"},{"line_number":141,"context_line":"        self.timeout \u003d timeout"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def _lang_url(self, code: str) -\u003e str:"},{"line_number":144,"context_line":"        return ("},{"line_number":145,"context_line":"            f\"{self.base}/api/languages/\""},{"line_number":146,"context_line":"            f\"{urllib.parse.quote(code, safe\u003d\u0027\u0027)}/\""},{"line_number":147,"context_line":"        )"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"    def get_language(self, code: str) -\u003e Tuple[int, Dict[str, Any]]:"},{"line_number":150,"context_line":"        r \u003d self.session.get(self._lang_url(code), timeout\u003dself.timeout)"},{"line_number":151,"context_line":"        if r.status_code \u003d\u003d 200:"},{"line_number":152,"context_line":"            return 200, r.json()"},{"line_number":153,"context_line":"        return r.status_code, {}"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"    def create_language("},{"line_number":156,"context_line":"        self, code: str, name: str, plural_number: int,"},{"line_number":157,"context_line":"        plural_formula: str, direction: Optional[str],"},{"line_number":158,"context_line":"    ) -\u003e Tuple[int, str]:"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"        payload \u003d {"},{"line_number":161,"context_line":"            \"code\": code,"},{"line_number":162,"context_line":"            \"name\": name or code,"},{"line_number":163,"context_line":"            \"plural\": {\"number\": plural_number, \"formula\": plural_formula},"},{"line_number":164,"context_line":"        }"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        if direction in (\"ltr\", \"rtl\"):"},{"line_number":167,"context_line":"            payload[\"direction\"] \u003d direction"},{"line_number":168,"context_line":"        r \u003d self.session.post(f\"{self.base}/api/languages/\","},{"line_number":169,"context_line":"                              json\u003dpayload, timeout\u003dself.timeout)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"        try:"},{"line_number":172,"context_line":"            r.raise_for_status()"},{"line_number":173,"context_line":"            return r.status_code, \"\""},{"line_number":174,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":175,"context_line":"            return r.status_code, r.text"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"    def update_language(self, code: str, name: Optional[str],"},{"line_number":178,"context_line":"                        plural_number: Optional[int], plural_formula:"},{"line_number":179,"context_line":"                            Optional[str]) -\u003e Tuple[int, str]:"},{"line_number":180,"context_line":"        payload: Dict[str, Any] \u003d {}"},{"line_number":181,"context_line":"        if name:"},{"line_number":182,"context_line":"            payload[\"name\"] \u003d name"},{"line_number":183,"context_line":"        if plural_number is not None and plural_formula:"},{"line_number":184,"context_line":"            payload[\"plural\"] \u003d {\"number\": plural_number,"},{"line_number":185,"context_line":"                                 \"formula\": plural_formula}"},{"line_number":186,"context_line":"        if not payload:"},{"line_number":187,"context_line":"            return 200, \"\"  # no changes"},{"line_number":188,"context_line":"        r \u003d self.session.patch(self._lang_url(code), json\u003dpayload,"},{"line_number":189,"context_line":"                               timeout\u003dself.timeout)"},{"line_number":190,"context_line":"        try:"},{"line_number":191,"context_line":"            r.raise_for_status()"},{"line_number":192,"context_line":"            return r.status_code, \"\""},{"line_number":193,"context_line":"        except requests.exceptions.HTTPError:"},{"line_number":194,"context_line":"            return r.status_code, r.text"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"# Main"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"63c6ce31_98be8a29","line":195,"range":{"start_line":131,"start_character":0,"end_line":195,"end_character":0},"in_reply_to":"eac9e499_147dfe79","updated":"2025-10-14 11:01:11.000000000","message":"I initially wrote this as a one-off script focused on the migration itself, without considering dependencies with other repositories. While there seem to be some overlapping parts with weblate_utils.py, there are also many unique logics that are not included there. Therefore, it may be better to either keep the current implementation as is or add the necessary logic to that file. However, since this code is intended for one-time use, I believe it is fine to leave it as it is.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":194,"context_line":"            return r.status_code, r.text"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"# Main"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"def main():"},{"line_number":200,"context_line":"    p \u003d argparse.ArgumentParser(description\u003d\"Weblate language create/update\")"}],"source_content_type":"text/x-python","patch_set":9,"id":"0c14d374_db3dd1a4","line":197,"updated":"2025-10-11 18:50:42.000000000","message":"Two lines are blank","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":194,"context_line":"            return r.status_code, r.text"},{"line_number":195,"context_line":""},{"line_number":196,"context_line":"# Main"},{"line_number":197,"context_line":""},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"def main():"},{"line_number":200,"context_line":"    p \u003d argparse.ArgumentParser(description\u003d\"Weblate language create/update\")"}],"source_content_type":"text/x-python","patch_set":9,"id":"57167638_b619b73e","line":197,"in_reply_to":"0c14d374_db3dd1a4","updated":"2025-10-14 11:01:11.000000000","message":"This lines are blank because of the PEP 8 style rule: “E302 – expected 2 blank lines, found 1.”\nAccording to PEP 8, top-level function or class definitions must be preceded by two blank lines, so the extra blank line was added to follow that convention.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":198,"context_line":""},{"line_number":199,"context_line":"def main():"},{"line_number":200,"context_line":"    p \u003d argparse.ArgumentParser(description\u003d\"Weblate language create/update\")"},{"line_number":201,"context_line":"    p.add_argument(\"-i\", \"--input\", required\u003dTrue, help\u003d\"Plural-Form map JSON\")"},{"line_number":202,"context_line":"    p.add_argument(\"-z\", \"--zanata\", required\u003dTrue, help\u003d\"Zanata locales JSON\")"},{"line_number":203,"context_line":"    p.add_argument(\"--apply\", action\u003d\"store_true\", help\u003d\"Changes to Weblate\")"},{"line_number":204,"context_line":"    args \u003d p.parse_args()"}],"source_content_type":"text/x-python","patch_set":9,"id":"470e2e94_2643c557","line":201,"range":{"start_line":201,"start_character":19,"end_line":201,"end_character":79},"updated":"2025-10-11 18:50:42.000000000","message":"Do you have a sample file for the JSON?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":198,"context_line":""},{"line_number":199,"context_line":"def main():"},{"line_number":200,"context_line":"    p \u003d argparse.ArgumentParser(description\u003d\"Weblate language create/update\")"},{"line_number":201,"context_line":"    p.add_argument(\"-i\", \"--input\", required\u003dTrue, help\u003d\"Plural-Form map JSON\")"},{"line_number":202,"context_line":"    p.add_argument(\"-z\", \"--zanata\", required\u003dTrue, help\u003d\"Zanata locales JSON\")"},{"line_number":203,"context_line":"    p.add_argument(\"--apply\", action\u003d\"store_true\", help\u003d\"Changes to Weblate\")"},{"line_number":204,"context_line":"    args \u003d p.parse_args()"}],"source_content_type":"text/x-python","patch_set":9,"id":"b546705c_11aeb189","line":201,"range":{"start_line":201,"start_character":19,"end_line":201,"end_character":79},"in_reply_to":"470e2e94_2643c557","updated":"2025-10-14 11:01:11.000000000","message":"I\u0027ll put it up","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":199,"context_line":"def main():"},{"line_number":200,"context_line":"    p \u003d argparse.ArgumentParser(description\u003d\"Weblate language create/update\")"},{"line_number":201,"context_line":"    p.add_argument(\"-i\", \"--input\", required\u003dTrue, help\u003d\"Plural-Form map JSON\")"},{"line_number":202,"context_line":"    p.add_argument(\"-z\", \"--zanata\", required\u003dTrue, help\u003d\"Zanata locales JSON\")"},{"line_number":203,"context_line":"    p.add_argument(\"--apply\", action\u003d\"store_true\", help\u003d\"Changes to Weblate\")"},{"line_number":204,"context_line":"    args \u003d p.parse_args()"},{"line_number":205,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"53e3b324_5974c16e","line":202,"range":{"start_line":202,"start_character":4,"end_line":202,"end_character":79},"updated":"2025-10-11 18:50:42.000000000","message":"Where is a sample file for Zanata locales JSON?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":199,"context_line":"def main():"},{"line_number":200,"context_line":"    p \u003d argparse.ArgumentParser(description\u003d\"Weblate language create/update\")"},{"line_number":201,"context_line":"    p.add_argument(\"-i\", \"--input\", required\u003dTrue, help\u003d\"Plural-Form map JSON\")"},{"line_number":202,"context_line":"    p.add_argument(\"-z\", \"--zanata\", required\u003dTrue, help\u003d\"Zanata locales JSON\")"},{"line_number":203,"context_line":"    p.add_argument(\"--apply\", action\u003d\"store_true\", help\u003d\"Changes to Weblate\")"},{"line_number":204,"context_line":"    args \u003d p.parse_args()"},{"line_number":205,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"f8dd6cf8_5055a9d4","line":202,"range":{"start_line":202,"start_character":4,"end_line":202,"end_character":79},"in_reply_to":"53e3b324_5974c16e","updated":"2025-10-14 11:01:11.000000000","message":"I\u0027ll put it up","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":37966,"name":"DaGyeong Kim","display_name":"S0okJu","email":"damekyung98@gmail.com","username":"S0okJu"},"change_message_id":"e1add0d19a3fe9573bc822c9879840e99a7d40ae","unresolved":true,"context_lines":[{"line_number":235,"context_line":"        if not parsed:"},{"line_number":236,"context_line":"            print(f\"- {code}: plural unresolved (neither {code}\")"},{"line_number":237,"context_line":"            print(f\" nor {code.split(\u0027_\u0027, 1)[0]} in input JSON)→skip\")"},{"line_number":238,"context_line":"            skipped +\u003d 1"},{"line_number":239,"context_line":"            continue"},{"line_number":240,"context_line":"        num, formula \u003d parsed"},{"line_number":241,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"63a5a6ea_baea7447","line":238,"updated":"2025-10-12 03:18:44.000000000","message":"Q. Can you explain when the result is \"skipped\"?","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":235,"context_line":"        if not parsed:"},{"line_number":236,"context_line":"            print(f\"- {code}: plural unresolved (neither {code}\")"},{"line_number":237,"context_line":"            print(f\" nor {code.split(\u0027_\u0027, 1)[0]} in input JSON)→skip\")"},{"line_number":238,"context_line":"            skipped +\u003d 1"},{"line_number":239,"context_line":"            continue"},{"line_number":240,"context_line":"        num, formula \u003d parsed"},{"line_number":241,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"4b0c0d84_dd65d01d","line":238,"in_reply_to":"63a5a6ea_baea7447","updated":"2025-10-14 11:01:11.000000000","message":"The result is marked as “skipped” when no plural-forms information can be resolved for a given language code.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"}],"tools/migration/delete_languages.py":[{"author":{"_account_id":14482,"name":"Ian Y. Choi","email":"ianyrchoi@gmail.com","username":"ianychoi"},"change_message_id":"f8695d59cbf9f45fa89ae83327f3af55b5cec8b8","unresolved":true,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"class WeblateLanguageDeleter:"},{"line_number":28,"context_line":"    def __init__(self, base_url: str, api_key: str):"},{"line_number":29,"context_line":"        self.base_url \u003d base_url.rstrip(\u0027/\u0027)"},{"line_number":30,"context_line":"        self.api_key \u003d api_key"},{"line_number":31,"context_line":"        self.session \u003d requests.Session()"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        # Set API key authentication headers"},{"line_number":34,"context_line":"        self.session.headers.update({"},{"line_number":35,"context_line":"            \u0027Authorization\u0027: f\u0027Token {api_key}\u0027,"},{"line_number":36,"context_line":"            \u0027Content-Type\u0027: \u0027application/json\u0027"},{"line_number":37,"context_line":"        })"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def get_all_languages(self) -\u003e List[Dict]:"},{"line_number":40,"context_line":"        all_languages \u003d []"},{"line_number":41,"context_line":"        url \u003d f\"{self.base_url}/api/languages/\""}],"source_content_type":"text/x-python","patch_set":9,"id":"4778f913_bf04bc36","line":38,"range":{"start_line":29,"start_character":6,"end_line":38,"end_character":0},"updated":"2025-10-11 18:50:42.000000000","message":"This part also seems dup with https://opendev.org/openstack/i18n/src/branch/master/tools/weblate/weblate_utils.py","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":true,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"class WeblateLanguageDeleter:"},{"line_number":28,"context_line":"    def __init__(self, base_url: str, api_key: str):"},{"line_number":29,"context_line":"        self.base_url \u003d base_url.rstrip(\u0027/\u0027)"},{"line_number":30,"context_line":"        self.api_key \u003d api_key"},{"line_number":31,"context_line":"        self.session \u003d requests.Session()"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        # Set API key authentication headers"},{"line_number":34,"context_line":"        self.session.headers.update({"},{"line_number":35,"context_line":"            \u0027Authorization\u0027: f\u0027Token {api_key}\u0027,"},{"line_number":36,"context_line":"            \u0027Content-Type\u0027: \u0027application/json\u0027"},{"line_number":37,"context_line":"        })"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def get_all_languages(self) -\u003e List[Dict]:"},{"line_number":40,"context_line":"        all_languages \u003d []"},{"line_number":41,"context_line":"        url \u003d f\"{self.base_url}/api/languages/\""}],"source_content_type":"text/x-python","patch_set":9,"id":"688534dc_06d4919b","line":38,"range":{"start_line":29,"start_character":6,"end_line":38,"end_character":0},"in_reply_to":"4778f913_bf04bc36","updated":"2025-10-14 11:01:11.000000000","message":"This task was initially intended as a one-off operation. Therefore, the goal was to make it simple and self-contained, allowing it to be executed easily using only these tools without relying on other files in the repository. For that reason, I defined and used this separate logic.","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"3a0c635d61c1c81c34fd9522fea5dcdd2eb0ca05","unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":"class WeblateLanguageDeleter:"},{"line_number":28,"context_line":"    def __init__(self, base_url: str, api_key: str):"},{"line_number":29,"context_line":"        self.base_url \u003d base_url.rstrip(\u0027/\u0027)"},{"line_number":30,"context_line":"        self.api_key \u003d api_key"},{"line_number":31,"context_line":"        self.session \u003d requests.Session()"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"        # Set API key authentication headers"},{"line_number":34,"context_line":"        self.session.headers.update({"},{"line_number":35,"context_line":"            \u0027Authorization\u0027: f\u0027Token {api_key}\u0027,"},{"line_number":36,"context_line":"            \u0027Content-Type\u0027: \u0027application/json\u0027"},{"line_number":37,"context_line":"        })"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def get_all_languages(self) -\u003e List[Dict]:"},{"line_number":40,"context_line":"        all_languages \u003d []"},{"line_number":41,"context_line":"        url \u003d f\"{self.base_url}/api/languages/\""}],"source_content_type":"text/x-python","patch_set":9,"id":"07af5e7d_0fb6a8ad","line":38,"range":{"start_line":29,"start_character":6,"end_line":38,"end_character":0},"in_reply_to":"688534dc_06d4919b","updated":"2025-12-03 14:31:52.000000000","message":"Done","commit_id":"16d09643f05a991ab4630b0f2e0174bde7c268a6"}],"tools/migration/language/README.rst":[{"author":{"_account_id":37966,"name":"DaGyeong Kim","display_name":"S0okJu","email":"damekyung98@gmail.com","username":"S0okJu"},"change_message_id":"f9515ad9756163ca1f8ba4ad164e6b40f6f311e5","unresolved":true,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":".. code-block:: bash"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"   python delete_languages.py --apply"}],"source_content_type":"text/x-rst","patch_set":15,"id":"03bd7d69_2d919c1a","line":59,"updated":"2025-12-06 07:15:36.000000000","message":"Please explain the `--ini` argument for the `create_languages` and `delete_langauges` cases.\n\nInclude the following details:\n- Where is the `weblate.ini` file stored in default?\n- How is `.ini` structured?","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"f054f0bc7608f580881fc47717078aea1d08b41b","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":".. code-block:: bash"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"   python delete_languages.py --apply"}],"source_content_type":"text/x-rst","patch_set":15,"id":"7cb28693_919ff0c1","line":59,"in_reply_to":"03bd7d69_2d919c1a","updated":"2025-12-16 11:02:11.000000000","message":"I have added a detailed explanation of the --ini argument to the RST documentation, covering the default location of weblate.ini and the expected INI file structure.","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":21,"context_line":""},{"line_number":22,"context_line":"- ``GET /api/languages/{code}/`` – Retrieve language details  "},{"line_number":23,"context_line":"- ``POST /api/languages/`` – Create new languages  "},{"line_number":24,"context_line":"- ``PATCH /api/languages/{code}/`` – Update existing languages  "},{"line_number":25,"context_line":""},{"line_number":26,"context_line":".. note::"},{"line_number":27,"context_line":"   Administrator privileges on Weblate are required to execute this script."}],"source_content_type":"text/x-rst","patch_set":19,"id":"d161f99a_a97894d2","line":24,"range":{"start_line":24,"start_character":62,"end_line":24,"end_character":64},"updated":"2026-04-21 20:29:22.000000000","message":"You can remove trailing spaces in your list.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":27,"context_line":"   Administrator privileges on Weblate are required to execute this script."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"Example command"},{"line_number":30,"context_line":"~~~~~~~~~~~~~~~"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":".. code-block:: bash"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-rst","patch_set":19,"id":"098d662f_7c071dab","line":30,"updated":"2026-04-21 20:29:22.000000000","message":"Maybe this line should not be a header, because it is on the same level than the previous one. And there is another section below with the same title.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":36,"context_line":"       -z /home/ubuntu/zanata.json \\"},{"line_number":37,"context_line":"       --apply"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"delete_languages.py"},{"line_number":40,"context_line":"~~~~~~~~~~~~~~~~~~~"},{"line_number":41,"context_line":"Deletes all or selected languages from Weblate in bulk."},{"line_number":42,"context_line":""}],"source_content_type":"text/x-rst","patch_set":19,"id":"daf3dcb8_479e52e2","line":39,"updated":"2026-04-21 20:29:22.000000000","message":"For this file, you are not using the `_weblate` suffix. You may want to either no suffix for the previous one or the same suffix for this one.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":46,"context_line":"This script also interacts with the Weblate REST API’s **language endpoints**:"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"- ``GET /api/languages/`` – Retrieve all languages  "},{"line_number":49,"context_line":"- ``DELETE /api/languages/{code}/`` – Delete specific languages  "},{"line_number":50,"context_line":""},{"line_number":51,"context_line":".. note::"},{"line_number":52,"context_line":"   Administrator privileges on Weblate are required to execute this script."}],"source_content_type":"text/x-rst","patch_set":19,"id":"7599ebc2_0d996d4e","line":49,"range":{"start_line":49,"start_character":63,"end_line":49,"end_character":65},"updated":"2026-04-21 20:29:22.000000000","message":"You can remove trailing spaces in your list.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":52,"context_line":"   Administrator privileges on Weblate are required to execute this script."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"Example command"},{"line_number":55,"context_line":"~~~~~~~~~~~~~~~"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":".. code-block:: bash"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-rst","patch_set":19,"id":"45a37f9f_7bc5ba71","line":55,"updated":"2026-04-21 20:29:22.000000000","message":"Maybe this line should not be a header too.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"5b65673dc74b48ba6799b69ecf0a4694dd7d05ab","unresolved":true,"context_lines":[{"line_number":84,"context_line":""},{"line_number":85,"context_line":".. code-block:: ini"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"   [weblate]"},{"line_number":88,"context_line":"   url \u003d https://weblate.example.com/"},{"line_number":89,"context_line":"   key \u003d YOUR_WEBLATE_API_TOKEN"},{"line_number":90,"context_line":""}],"source_content_type":"text/x-rst","patch_set":19,"id":"76ac556b_5ce44c71","line":87,"updated":"2026-01-28 12:48:36.000000000","message":"This configuration is no longer supported starting from wlc 1.17. It would be better to either pin the wlc version in requirements.txt or update the code to use the current supported approach.\n\nAnd, According to the official Weblate documentation, the URL must include /api, and with that configuration, your code does not work. \nhttps://docs.weblate.org/en/latest/wlc.html#getting-started","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"}],"tools/migration/language/create_languages_weblate.py":[{"author":{"_account_id":37966,"name":"DaGyeong Kim","display_name":"S0okJu","email":"damekyung98@gmail.com","username":"S0okJu"},"change_message_id":"717020dd586d0167a3868269d7c55064bc061fd9","unresolved":true,"context_lines":[{"line_number":201,"context_line":"                }"},{"line_number":202,"context_line":"                if direction:"},{"line_number":203,"context_line":"                    payload[\"direction\"] \u003d direction"},{"line_number":204,"context_line":"                r3 \u003d svc.push(\"/api/languages/\", payload)"},{"line_number":205,"context_line":"                if r3.status_code in (200, 201):"},{"line_number":206,"context_line":"                    created +\u003d 1"},{"line_number":207,"context_line":"                else:"}],"source_content_type":"text/x-python","patch_set":15,"id":"6475cdb3_e8e061ba","line":204,"updated":"2025-12-06 08:32:01.000000000","message":"If the language does not exist, it should create a new one.\n\nBut since the `push()` uses PUT method, we should change to **POST** method.\n- https://docs.weblate.org/en/latest/api.html#post--api-languages-","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"f054f0bc7608f580881fc47717078aea1d08b41b","unresolved":false,"context_lines":[{"line_number":201,"context_line":"                }"},{"line_number":202,"context_line":"                if direction:"},{"line_number":203,"context_line":"                    payload[\"direction\"] \u003d direction"},{"line_number":204,"context_line":"                r3 \u003d svc.push(\"/api/languages/\", payload)"},{"line_number":205,"context_line":"                if r3.status_code in (200, 201):"},{"line_number":206,"context_line":"                    created +\u003d 1"},{"line_number":207,"context_line":"                else:"}],"source_content_type":"text/x-python","patch_set":15,"id":"4449c6b3_d93c6caf","line":204,"in_reply_to":"6475cdb3_e8e061ba","updated":"2025-12-16 11:02:11.000000000","message":"If the language does not exist, it should be created. Since push() uses PUT, the logic has been updated to use POST instead. A POST method was added to weblate_utils.py. Feedback would be appreciated.","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":1,"context_line":"#!/usr/bin/env python3"},{"line_number":2,"context_line":"# -*- coding: utf-8 -*-"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"# a copy of the License at"}],"source_content_type":"text/x-python","patch_set":19,"id":"0c9d191f_030eed3c","line":2,"updated":"2026-04-21 20:29:22.000000000","message":"Python 3 doesn\u0027t need encoding anymore, it defaults to utf8.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":33,"context_line":"import json"},{"line_number":34,"context_line":"import re"},{"line_number":35,"context_line":"from typing import Any"},{"line_number":36,"context_line":"from typing import Dict"},{"line_number":37,"context_line":"from typing import Optional"},{"line_number":38,"context_line":"from typing import Tuple"},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"e31e7639_5b02bff8","line":36,"updated":"2026-04-21 20:29:22.000000000","message":"You can remove this import and use `dict` instead.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":35,"context_line":"from typing import Any"},{"line_number":36,"context_line":"from typing import Dict"},{"line_number":37,"context_line":"from typing import Optional"},{"line_number":38,"context_line":"from typing import Tuple"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"from weblate.weblate_utils import IniConfig"},{"line_number":41,"context_line":"from weblate.weblate_utils import WeblateRestService"}],"source_content_type":"text/x-python","patch_set":19,"id":"009203f6_68ee2d48","line":38,"updated":"2026-04-21 20:29:22.000000000","message":"You can remove this import and use tuple` instead.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":93,"context_line":""},{"line_number":94,"context_line":"def load_zanata_locales(path: str) -\u003e Dict[str, Dict[str, Any]]:"},{"line_number":95,"context_line":"    with open(path, \"r\", encoding\u003d\"utf-8\") as f:"},{"line_number":96,"context_line":"        arr \u003d json.load(f)"},{"line_number":97,"context_line":"    if not isinstance(arr, list):"},{"line_number":98,"context_line":"        raise ValueError(\"Zanata JSON must be an array.\")"},{"line_number":99,"context_line":"    out: Dict[str, Dict[str, Any]] \u003d {}"}],"source_content_type":"text/x-python","patch_set":19,"id":"9b353643_db11076e","line":96,"updated":"2026-04-21 20:29:22.000000000","message":"Can you use descriptive names for your variables, please?","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":102,"context_line":"        if not isinstance(it, dict):"},{"line_number":103,"context_line":"            continue"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"        raw \u003d it.get(\"localeId\") or it.get(\"id\") or \"\""},{"line_number":106,"context_line":"        code \u003d normalize_code(raw)"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        if not code:"}],"source_content_type":"text/x-python","patch_set":19,"id":"6f131a8a_36ac774e","line":105,"updated":"2026-04-21 20:29:22.000000000","message":"`raw \u003d it.get(\"localeId\", it.get(\"id\", \"\"))`","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":148,"context_line":"    failures \u003d []"},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"    for code, zinfo in zanata_map.items():"},{"line_number":151,"context_line":"        name \u003d (zinfo.get(\"name\") or code).strip()"},{"line_number":152,"context_line":"        direction \u003d \"rtl\" if zinfo.get(\"rtl\") else None"},{"line_number":153,"context_line":"        pf_str \u003d plural_map.get(code)"},{"line_number":154,"context_line":"        if not pf_str:"}],"source_content_type":"text/x-python","patch_set":19,"id":"05498bc9_2099c05d","line":151,"updated":"2026-04-21 20:29:22.000000000","message":"`name \u003d zinfo.get(\"name\", code).strip()`","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"}],"tools/migration/language/delete_languages.py":[{"author":{"_account_id":37966,"name":"DaGyeong Kim","display_name":"S0okJu","email":"damekyung98@gmail.com","username":"S0okJu"},"change_message_id":"915945bd00137f6f0e86f942975c250c75b813b9","unresolved":true,"context_lines":[{"line_number":207,"context_line":"        return"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"    # Create backup"},{"line_number":210,"context_line":"    if args.backup:"},{"line_number":211,"context_line":"        deleter.backup_languages()"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"    # Preview languages to delete"}],"source_content_type":"text/x-python","patch_set":15,"id":"22f13427_94b2b516","line":210,"updated":"2025-12-06 07:33:13.000000000","message":"The backup argument is missing in `ArgumentParser`","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"f054f0bc7608f580881fc47717078aea1d08b41b","unresolved":false,"context_lines":[{"line_number":207,"context_line":"        return"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"    # Create backup"},{"line_number":210,"context_line":"    if args.backup:"},{"line_number":211,"context_line":"        deleter.backup_languages()"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"    # Preview languages to delete"}],"source_content_type":"text/x-python","patch_set":15,"id":"4bb1decc_d17bd834","line":210,"in_reply_to":"22f13427_94b2b516","updated":"2025-12-16 11:02:11.000000000","message":"The backup argument was missing from the ArgumentParser.\nThis functionality is no longer used, so the code has been updated accordingly.","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":37966,"name":"DaGyeong Kim","display_name":"S0okJu","email":"damekyung98@gmail.com","username":"S0okJu"},"change_message_id":"710f39021596b2e0a4673ca235aa83054146d1cb","unresolved":true,"context_lines":[{"line_number":224,"context_line":""},{"line_number":225,"context_line":"    deleter.delete_all_languages("},{"line_number":226,"context_line":"        dry_run\u003dnot args.apply,"},{"line_number":227,"context_line":"        exclude_languages\u003dargs.exclude"},{"line_number":228,"context_line":"    )"},{"line_number":229,"context_line":""},{"line_number":230,"context_line":"    # Final summary"}],"source_content_type":"text/x-python","patch_set":15,"id":"08917276_482a4215","line":227,"updated":"2025-12-06 07:37:05.000000000","message":"The exclude argument is missing in `ArgumentParser`.","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"f054f0bc7608f580881fc47717078aea1d08b41b","unresolved":false,"context_lines":[{"line_number":224,"context_line":""},{"line_number":225,"context_line":"    deleter.delete_all_languages("},{"line_number":226,"context_line":"        dry_run\u003dnot args.apply,"},{"line_number":227,"context_line":"        exclude_languages\u003dargs.exclude"},{"line_number":228,"context_line":"    )"},{"line_number":229,"context_line":""},{"line_number":230,"context_line":"    # Final summary"}],"source_content_type":"text/x-python","patch_set":15,"id":"c9bc3b84_a5638954","line":227,"in_reply_to":"08917276_482a4215","updated":"2025-12-16 11:02:11.000000000","message":"The argument was missing from the ArgumentParser.\nThis functionality is no longer used, so the code has been updated accordingly.","commit_id":"870e5f85f3671bca231a810e4c77f88e42a0e9be"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":1,"context_line":"#!/usr/bin/env python3"},{"line_number":2,"context_line":"# -*- coding: utf-8 -*-"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"},{"line_number":4,"context_line":"# you may not use this file except in compliance with the License."},{"line_number":5,"context_line":"# You may obtain a copy of the License at"}],"source_content_type":"text/x-python","patch_set":19,"id":"b664ded4_a160ebcb","line":2,"updated":"2026-04-21 20:29:22.000000000","message":"Python 3 doesn\u0027t need encoding anymore, it defaults to utf8.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":18,"context_line":"import argparse"},{"line_number":19,"context_line":"import json"},{"line_number":20,"context_line":"import requests"},{"line_number":21,"context_line":"from typing import Dict"},{"line_number":22,"context_line":"from typing import List"},{"line_number":23,"context_line":"from weblate.weblate_utils import IniConfig"},{"line_number":24,"context_line":"from weblate.weblate_utils import WeblateRestService"}],"source_content_type":"text/x-python","patch_set":19,"id":"5fe49098_fae55ece","line":21,"updated":"2026-04-21 20:29:22.000000000","message":"You can remove this import and use `dict` instead.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":12015,"name":"François Magimel","email":"magimel.francois@gmail.com","username":"linkid"},"change_message_id":"5a37c97150ec1dd59475e076920fdab0f6318d7f","unresolved":true,"context_lines":[{"line_number":19,"context_line":"import json"},{"line_number":20,"context_line":"import requests"},{"line_number":21,"context_line":"from typing import Dict"},{"line_number":22,"context_line":"from typing import List"},{"line_number":23,"context_line":"from weblate.weblate_utils import IniConfig"},{"line_number":24,"context_line":"from weblate.weblate_utils import WeblateRestService"},{"line_number":25,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"06ff1af3_24a0e35a","line":22,"updated":"2026-04-21 20:29:22.000000000","message":"You can remove this import and use `list` instead.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"c98a8331df65f1f4d5d6ad87ba7d157e09911340","unresolved":true,"context_lines":[{"line_number":20,"context_line":"import requests"},{"line_number":21,"context_line":"from typing import Dict"},{"line_number":22,"context_line":"from typing import List"},{"line_number":23,"context_line":"from weblate.weblate_utils import IniConfig"},{"line_number":24,"context_line":"from weblate.weblate_utils import WeblateRestService"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"59c358ac_8d888899","line":23,"updated":"2026-01-28 11:54:42.000000000","message":"When I ran the this script, it reported that the weblate package could not be found. I believe this is not the Weblate package that is installed via pip3 install weblate, but rather a package located under tools/weblate.\n\nThe naming overlaps with the official Weblate package, which can cause confusion. In addition, with this approach, it is not possible to reference the tools/weblate package.","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"},{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"c98a8331df65f1f4d5d6ad87ba7d157e09911340","unresolved":true,"context_lines":[{"line_number":30,"context_line":"        self.svc \u003d WeblateRestService(config)"},{"line_number":31,"context_line":"        self.base_url \u003d self.svc.url.rstrip(\u0027/\u0027)"},{"line_number":32,"context_line":"        self.headers \u003d self.svc.headers"},{"line_number":33,"context_line":"        self.verify \u003d self.svc.verify"},{"line_number":34,"context_line":"        self.session \u003d requests.Session()"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    def get_all_languages(self) -\u003e List[Dict]:"}],"source_content_type":"text/x-python","patch_set":19,"id":"ff3db012_5579556d","line":33,"updated":"2026-01-28 11:54:42.000000000","message":"This option seems to be related to SSL verification in requests. Is there a need to make this configurable?","commit_id":"8704dec17661bb8aad2ccde62e2d96e152f08a31"}],"tools/weblate_languages_tools/README.md":[{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"7dd843353b23873f50663120407dc098a0db37b8","unresolved":true,"context_lines":[{"line_number":1,"context_line":"This folder show weblate_languages_tools for weblate migration"}],"source_content_type":"text/x-gfm","patch_set":6,"id":"fa4a405f_1bd22602","line":1,"updated":"2025-09-25 14:54:29.000000000","message":"It would be helpful to include a brief description of the purpose of each file rather than just this text.","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":1,"context_line":"This folder show weblate_languages_tools for weblate migration"}],"source_content_type":"text/x-gfm","patch_set":6,"id":"b26f5e4e_f3cccbbd","line":1,"in_reply_to":"fa4a405f_1bd22602","updated":"2025-10-14 11:01:11.000000000","message":"I’ve reviewed your feedback and made the updates. Thank you!","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"}],"tools/weblate_languages_tools/create_languages_weblate.py":[{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"7dd843353b23873f50663120407dc098a0db37b8","unresolved":true,"context_lines":[{"line_number":196,"context_line":"    p.add_argument(\"--apply\", action\u003d\"store_true\", help\u003d\"Changes to Weblate\")"},{"line_number":197,"context_line":"    args \u003d p.parse_args()"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    url \u003d os.getenv(\"WEBLATE_URL\", \"\")"},{"line_number":200,"context_line":"    token \u003d os.getenv(\"WEBLATE_API_KEY\", \"\")"},{"line_number":201,"context_line":"    if not token:"},{"line_number":202,"context_line":"        print(\"ERROR: Specify WEBLATE_API_KEY environment variable.\","}],"source_content_type":"text/x-python","patch_set":6,"id":"a6bc7e72_9e015414","line":199,"updated":"2025-09-25 14:54:29.000000000","message":"Use the same approach as delete_language.py to get this value.","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":196,"context_line":"    p.add_argument(\"--apply\", action\u003d\"store_true\", help\u003d\"Changes to Weblate\")"},{"line_number":197,"context_line":"    args \u003d p.parse_args()"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"    url \u003d os.getenv(\"WEBLATE_URL\", \"\")"},{"line_number":200,"context_line":"    token \u003d os.getenv(\"WEBLATE_API_KEY\", \"\")"},{"line_number":201,"context_line":"    if not token:"},{"line_number":202,"context_line":"        print(\"ERROR: Specify WEBLATE_API_KEY environment variable.\","}],"source_content_type":"text/x-python","patch_set":6,"id":"16f1cb3b_45dd8ae0","line":199,"in_reply_to":"a6bc7e72_9e015414","updated":"2025-10-14 11:01:11.000000000","message":"I’ve reviewed your feedback and made the updates. Thank you!","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"}],"tools/weblate_languages_tools/delete_languages.py":[{"author":{"_account_id":23279,"name":"Seongsoo Cho","display_name":"Seongsoo Cho","email":"ppiyakk2@printf.kr","username":"seongsoo.cho"},"change_message_id":"7dd843353b23873f50663120407dc098a0db37b8","unresolved":true,"context_lines":[{"line_number":185,"context_line":"    print(\"\u003d\u003d\u003d Weblate Language Deletion Tool \u003d\u003d\u003d\\n\")"},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"    # Weblate settings"},{"line_number":188,"context_line":"    weblate_url \u003d \"\""},{"line_number":189,"context_line":"    weblate_api_key \u003d \"\""},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    print(f\"Weblate server: {weblate_url}\")"}],"source_content_type":"text/x-python","patch_set":6,"id":"f2f84eb6_8bf4c187","line":188,"updated":"2025-09-25 14:54:29.000000000","message":"It would be better to modify the code so that the URL and API key are passed as arguments or retrieved from environment variables.","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"},{"author":{"_account_id":38225,"name":"KIM KWANG IL","display_name":"kwangil","email":"rhkddlf7911@naver.com","username":"kwangil"},"change_message_id":"279401078406b4c7e7a6d945e2046a795fedba41","unresolved":false,"context_lines":[{"line_number":185,"context_line":"    print(\"\u003d\u003d\u003d Weblate Language Deletion Tool \u003d\u003d\u003d\\n\")"},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"    # Weblate settings"},{"line_number":188,"context_line":"    weblate_url \u003d \"\""},{"line_number":189,"context_line":"    weblate_api_key \u003d \"\""},{"line_number":190,"context_line":""},{"line_number":191,"context_line":"    print(f\"Weblate server: {weblate_url}\")"}],"source_content_type":"text/x-python","patch_set":6,"id":"f624e88e_9d280b57","line":188,"in_reply_to":"f2f84eb6_8bf4c187","updated":"2025-10-14 11:01:11.000000000","message":"I’ve reviewed your feedback and made the updates. Thank you!","commit_id":"0f960b8b93fc8f17dc25cedc54395ad47476435b"}]}
