fix translation script to adhere to placeholder types (#2097)
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
This commit is contained in:
parent
0128ac42cd
commit
e150a3b0a9
2 changed files with 99 additions and 12 deletions
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"@@last_modified": "2025-03-05 13:01:52.197829",
|
||||
"@@last_modified": "2025-03-10 10:26:28.474786",
|
||||
"about": "Giới thiệu",
|
||||
"@about": {
|
||||
"type": "String",
|
||||
|
|
@ -3304,7 +3304,7 @@
|
|||
},
|
||||
"botModeValidation": "Vui lòng chọn một chế độ trò chuyện",
|
||||
"clickBestOption": "Chọn phương án tốt nhất để dịch tin nhắn của bạn!",
|
||||
"completeActivitiesToUnlock": "Hoàn thành các hoạt động từ vựng để mở khóa phần âm thanh và bản dịch!",
|
||||
"completeActivitiesToUnlock": "Hoàn thành các hoạt động từ vựng được đánh dấu để mở khóa",
|
||||
"botSettingsSubtitle": "Mời bot kiểm duyệt hoặc khởi tạo hoạt động trò chuyện",
|
||||
"invitePeople": "Mời người dùng",
|
||||
"invitePeopleChatSubtitle": "Mời người dùng hoặc quản trị viên đến cuộc trò chuyện này",
|
||||
|
|
@ -3568,7 +3568,6 @@
|
|||
"video": "Video",
|
||||
"nan": "Không áp dụng",
|
||||
"activityPlannerOverviewInstructionsBody": "Chọn chủ đề, chế độ, mục tiêu học tập và tạo hoạt động cho cuộc trò chuyện!",
|
||||
"completeActivitiesToUnlock": "Hoàn thành các hoạt động từ vựng được đánh dấu để mở khóa",
|
||||
"myBookmarkedActivities": "Hoạt động đã đánh dấu",
|
||||
"noBookmarkedActivities": "Chưa có hoạt động nào được đánh dấu",
|
||||
"activityTitle": "Tiêu đề hoạt động",
|
||||
|
|
@ -3739,5 +3738,60 @@
|
|||
}
|
||||
},
|
||||
"downloadGboard": "Tải Gboard",
|
||||
"autocorrectNotAvailable": "Rất tiếc, nền tảng của bạn hiện không được hỗ trợ cho tính năng này. Hãy theo dõi để biết thêm thông tin phát triển!"
|
||||
}
|
||||
"autocorrectNotAvailable": "Rất tiếc, nền tảng của bạn hiện không được hỗ trợ cho tính năng này. Hãy theo dõi để biết thêm thông tin phát triển!",
|
||||
"takeAPhoto": "Chụp một bức ảnh",
|
||||
"recordAVideo": "Ghi lại một video",
|
||||
"optionalMessage": "(Tùy chọn) tin nhắn...",
|
||||
"notSupportedOnThisDevice": "Không được hỗ trợ trên thiết bị này",
|
||||
"pleaseUpdateApp": "Vui lòng cập nhật ứng dụng để tiếp tục.",
|
||||
"chooseEmojiInstructionsBody": "Chọn một biểu tượng cảm xúc cho từ này! Không có câu trả lời sai và bạn có thể chuyển đổi bất cứ lúc nào! 😄",
|
||||
"pickAnEmojiFor": "Chọn một biểu tượng cảm xúc cho ${lemma}",
|
||||
"knockSpaceSuccess": "Bạn đã yêu cầu tham gia không gian này! Một quản trị viên sẽ phản hồi yêu cầu của bạn khi họ nhận được nó 😄",
|
||||
"joinByCode": "Tham gia bằng mã",
|
||||
"createASpace": "Tạo một không gian",
|
||||
"@@locale": "vi",
|
||||
"@takeAPhoto": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@recordAVideo": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@optionalMessage": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@notSupportedOnThisDevice": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@pleaseUpdateApp": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@chooseEmojiInstructionsBody": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@pickAnEmojiFor": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
"lemma": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"@knockSpaceSuccess": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@joinByCode": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
},
|
||||
"@createASpace": {
|
||||
"type": "String",
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ Usage:
|
|||
python scripts/translate.py
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
def load_needed_translations() -> dict[str, list[str]]:
|
||||
import json
|
||||
|
|
@ -78,7 +80,11 @@ def save_translations(lang_code: str, translations: dict[str, str]) -> None:
|
|||
f.write(json.dumps(existing_data, indent=2, ensure_ascii=False))
|
||||
|
||||
|
||||
def reconcile_metadata(lang_code: str, translation_keys: list[str]) -> None:
|
||||
def reconcile_metadata(
|
||||
lang_code: str,
|
||||
translation_keys: list[str],
|
||||
english_translations_dict: dict[str, Any],
|
||||
) -> None:
|
||||
"""
|
||||
For each translation key, update its metadata (the key prefixed with '@') by merging
|
||||
any existing metadata with computed metadata. For basic translations, if no metadata exists,
|
||||
|
|
@ -95,7 +101,7 @@ def reconcile_metadata(lang_code: str, translation_keys: list[str]) -> None:
|
|||
# Case 1: Basic translations, no placeholders.
|
||||
if "{" not in translation:
|
||||
if not existing_meta:
|
||||
translations[meta_key] = {"type": "text", "placeholders": {}}
|
||||
translations[meta_key] = {"type": "String", "placeholders": {}}
|
||||
# if metadata exists, leave it as is.
|
||||
|
||||
# Case 2: Translations with placeholders (no pluralization).
|
||||
|
|
@ -109,14 +115,27 @@ def reconcile_metadata(lang_code: str, translation_keys: list[str]) -> None:
|
|||
for placeholder in translation.split("{")[1:]:
|
||||
placeholder_name = placeholder.split("}")[0]
|
||||
computed_placeholders[placeholder_name] = {}
|
||||
# Obtain placeholder type from english translation or default to {}
|
||||
placeholder_type = (
|
||||
english_translations_dict.get(meta_key, {})
|
||||
.get("placeholders", {})
|
||||
.get(placeholder_name, {})
|
||||
.get("type")
|
||||
)
|
||||
if placeholder_type:
|
||||
computed_placeholders[placeholder_name]["type"] = placeholder_type
|
||||
if existing_meta:
|
||||
# Merge computed placeholders into existing metadata.
|
||||
existing_meta.setdefault("type", "text")
|
||||
existing_meta.setdefault("type", "String")
|
||||
existing_meta["placeholders"] = computed_placeholders
|
||||
translations[meta_key] = existing_meta
|
||||
else:
|
||||
# Obtain type from english translation or default to "String".
|
||||
translation_type = english_translations_dict.get(meta_key, {}).get(
|
||||
"type", "String"
|
||||
)
|
||||
translations[meta_key] = {
|
||||
"type": "text",
|
||||
"type": translation_type,
|
||||
"placeholders": computed_placeholders,
|
||||
}
|
||||
|
||||
|
|
@ -130,13 +149,27 @@ def reconcile_metadata(lang_code: str, translation_keys: list[str]) -> None:
|
|||
p.strip() for p in prefix.split(",") if p.strip() != ""
|
||||
]
|
||||
computed_placeholders = {ph: {} for ph in placeholders_list}
|
||||
for ph in placeholders_list:
|
||||
# Obtain placeholder type from english translation or default to {}
|
||||
placeholder_type = (
|
||||
english_translations_dict.get(meta_key, {})
|
||||
.get("placeholders", {})
|
||||
.get(placeholder_name, {})
|
||||
.get("type")
|
||||
)
|
||||
if placeholder_type:
|
||||
computed_placeholders[ph]["type"] = placeholder_type
|
||||
if existing_meta:
|
||||
existing_meta.setdefault("type", "text")
|
||||
existing_meta.setdefault("type", "String")
|
||||
existing_meta["placeholders"] = computed_placeholders
|
||||
translations[meta_key] = existing_meta
|
||||
else:
|
||||
# Obtain type from english translation or default to "String".
|
||||
translation_type = english_translations_dict.get(meta_key, {}).get(
|
||||
"type", "String"
|
||||
)
|
||||
translations[meta_key] = {
|
||||
"type": "text",
|
||||
"type": "String",
|
||||
"placeholders": computed_placeholders,
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +292,7 @@ def translate(lang_code: str, lang_display_name: str) -> None:
|
|||
save_translations(lang_code, current_translations)
|
||||
|
||||
# reconcile metadata
|
||||
reconcile_metadata(lang_code, needed_translations)
|
||||
reconcile_metadata(lang_code, needed_translations, english_translations_dict)
|
||||
|
||||
|
||||
"""Example usage:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue