mirror of
https://github.com/FirestormViewer/phoenix-firestorm.git
synced 2026-08-14 00:48:30 +00:00
General housekeeping in localisations
Signed-off-by: PanteraPolnocy <panterapolnocy@gmail.com>
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Remove or relocate locale XUI attributes that do not exist on matching EN elements."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
|
||||
from translation_strings_auditing_tool import ( # noqa: E402
|
||||
SKINS_ROOT,
|
||||
collect_files,
|
||||
compare_extra_attributes,
|
||||
extract_element_attrs,
|
||||
parse_xml,
|
||||
)
|
||||
|
||||
STRUCTURAL_ATTRS = frozenset({
|
||||
"relwidth", "follows", "font", "initial_value", "label_width", "vlabel",
|
||||
"unit_label",
|
||||
})
|
||||
|
||||
ATTR_RE = r'(\s{attr}="[^"]*"|\s{attr}=\'[^\']*\')'
|
||||
ATTR_RE_TMPL = r'(\s{attr}="[^"]*"|\s{attr}=\'[^\']*\')'
|
||||
|
||||
|
||||
@dataclass
|
||||
class FixAction:
|
||||
element: str
|
||||
attr: str
|
||||
value: str
|
||||
hint: str
|
||||
en_attrs: dict[str, str]
|
||||
|
||||
|
||||
def attr_pattern(attr: str) -> re.Pattern[str]:
|
||||
return re.compile(
|
||||
rf'\s+{re.escape(attr)}="[^"]*"|\s+{re.escape(attr)}=\'[^\']*\'',
|
||||
)
|
||||
|
||||
|
||||
def line_has_name(line: str, name: str) -> bool:
|
||||
return bool(re.search(rf'name\s*=\s*["\']{re.escape(name)}["\']', line))
|
||||
|
||||
|
||||
def remove_attr(line: str, attr: str) -> str:
|
||||
return attr_pattern(attr).sub("", line, count=1)
|
||||
|
||||
|
||||
def apply_line_fixes(line: str, actions: list[FixAction]) -> str:
|
||||
if not any(line_has_name(line, a.element[1:]) for a in actions):
|
||||
return line
|
||||
|
||||
for action in actions:
|
||||
name = action.element[1:]
|
||||
if not line_has_name(line, name):
|
||||
continue
|
||||
|
||||
attr = action.attr
|
||||
value = action.value
|
||||
hint = action.hint
|
||||
en_attrs = action.en_attrs
|
||||
|
||||
if attr == "gnoretext":
|
||||
line = remove_attr(line, "gnoretext")
|
||||
if value and "ignoretext=" not in line:
|
||||
line = line.replace(
|
||||
f'name="{name}"',
|
||||
f'ignoretext="{value.replace(chr(34), """)}" name="{name}"',
|
||||
1,
|
||||
)
|
||||
continue
|
||||
|
||||
if attr == "tooltip" and "tool_tip" in hint:
|
||||
line = remove_attr(line, "tooltip")
|
||||
if value and "tool_tip=" not in line:
|
||||
line = line.replace(
|
||||
f'name="{name}"',
|
||||
f'tool_tip="{value.replace(chr(34), """)}" name="{name}"',
|
||||
1,
|
||||
)
|
||||
continue
|
||||
|
||||
if attr == "text" and "EN uses label" in hint:
|
||||
line = remove_attr(line, "text")
|
||||
continue
|
||||
|
||||
if attr == "title" and "EN uses label" in hint:
|
||||
line = remove_attr(line, "title")
|
||||
if value and "label=" not in line:
|
||||
line = line.replace(
|
||||
f'name="{name}"',
|
||||
f'label="{value.replace(chr(34), """)}" name="{name}"',
|
||||
1,
|
||||
)
|
||||
continue
|
||||
|
||||
if attr == "label" and "EN uses title" in hint:
|
||||
line = remove_attr(line, "label")
|
||||
if value and "title=" not in line:
|
||||
line = line.replace(
|
||||
f'name="{name}"',
|
||||
f'title="{value.replace(chr(34), """)}" name="{name}"',
|
||||
1,
|
||||
)
|
||||
continue
|
||||
|
||||
if attr == "label" and "EN uses value" in hint:
|
||||
line = remove_attr(line, "label")
|
||||
if value and "value=" not in line:
|
||||
line = line.replace(
|
||||
f'name="{name}"',
|
||||
f'value="{value.replace(chr(34), """)}" name="{name}"',
|
||||
1,
|
||||
)
|
||||
continue
|
||||
|
||||
if attr == "ignoretext" and f'name="{name}"' in line and 'name="okcancelbuttons"' in line:
|
||||
line = line.replace('name="okcancelbuttons"', 'name="okcancelignore"', 1)
|
||||
continue
|
||||
|
||||
if attr == "label" and value and "tool_tip" in en_attrs and "label" not in en_attrs:
|
||||
en_tip = en_attrs.get("tool_tip", "")
|
||||
if "tool_tip=" in line:
|
||||
tip_m = re.search(r'tool_tip="([^"]*)"', line)
|
||||
loc_tip = tip_m.group(1) if tip_m else ""
|
||||
if not loc_tip or loc_tip == en_tip:
|
||||
line = re.sub(
|
||||
r'tool_tip="[^"]*"',
|
||||
f'tool_tip="{value.replace(chr(34), """)}"',
|
||||
line,
|
||||
count=1,
|
||||
)
|
||||
else:
|
||||
line = line.replace(
|
||||
f'name="{name}"',
|
||||
f'tool_tip="{value.replace(chr(34), """)}" name="{name}"',
|
||||
1,
|
||||
)
|
||||
line = remove_attr(line, "label")
|
||||
continue
|
||||
|
||||
line = remove_attr(line, attr)
|
||||
|
||||
return line
|
||||
|
||||
|
||||
def fix_file_content(content: str, actions: list[FixAction]) -> tuple[str, int]:
|
||||
by_name: dict[str, list[FixAction]] = defaultdict(list)
|
||||
for action in actions:
|
||||
by_name[action.element[1:]].append(action)
|
||||
|
||||
lines = content.splitlines(keepends=True)
|
||||
fixed = 0
|
||||
out: list[str] = []
|
||||
for line in lines:
|
||||
new_line = line
|
||||
for name, name_actions in by_name.items():
|
||||
if line_has_name(line, name):
|
||||
before = new_line
|
||||
new_line = apply_line_fixes(new_line, name_actions)
|
||||
if new_line != before:
|
||||
fixed += len(name_actions)
|
||||
out.append(new_line)
|
||||
return "".join(out), fixed
|
||||
|
||||
|
||||
def fix_file(skin: str, locale: str, rel: str, issues) -> int:
|
||||
locale_path = SKINS_ROOT / skin / "xui" / locale / rel
|
||||
en_path = SKINS_ROOT / skin / "xui" / "en" / rel
|
||||
en_root = parse_xml(en_path)
|
||||
if en_root is None or not locale_path.exists():
|
||||
return 0
|
||||
|
||||
en_elems = extract_element_attrs(en_root, rel)
|
||||
actions = [
|
||||
FixAction(
|
||||
element=i.element,
|
||||
attr=i.attr,
|
||||
value=i.value,
|
||||
hint=i.hint,
|
||||
en_attrs=en_elems.get(i.element, {}),
|
||||
)
|
||||
for i in issues
|
||||
]
|
||||
|
||||
original = locale_path.read_text(encoding="utf-8")
|
||||
updated, count = fix_file_content(original, actions)
|
||||
if updated != original:
|
||||
locale_path.write_text(updated, encoding="utf-8", newline="")
|
||||
return count
|
||||
|
||||
|
||||
def count_remaining() -> int:
|
||||
return len(collect_all_issues())
|
||||
|
||||
|
||||
def collect_all_issues() -> list[tuple[str, str, str, object]]:
|
||||
issues: list[tuple[str, str, str, object]] = []
|
||||
skins = sorted(
|
||||
p.name for p in SKINS_ROOT.iterdir()
|
||||
if p.is_dir() and (p / "xui" / "en").is_dir()
|
||||
)
|
||||
for skin in skins:
|
||||
en_files = collect_files(SKINS_ROOT / skin / "xui" / "en")
|
||||
for loc_dir in sorted((SKINS_ROOT / skin / "xui").iterdir()):
|
||||
if not loc_dir.is_dir() or loc_dir.name == "en":
|
||||
continue
|
||||
locale = loc_dir.name
|
||||
loc_files = collect_files(loc_dir)
|
||||
for rel in sorted(set(en_files) & set(loc_files)):
|
||||
en_root = parse_xml(en_files[rel])
|
||||
loc_root = parse_xml(loc_files[rel])
|
||||
if en_root is None or loc_root is None:
|
||||
continue
|
||||
file_issues = compare_extra_attributes(
|
||||
extract_element_attrs(en_root, rel),
|
||||
extract_element_attrs(loc_root, rel),
|
||||
)
|
||||
for issue in file_issues:
|
||||
issues.append((skin, locale, rel, issue))
|
||||
return issues
|
||||
|
||||
|
||||
def main() -> int:
|
||||
total_fixed = 0
|
||||
files_touched = 0
|
||||
|
||||
grouped: dict[tuple[str, str, str], list] = defaultdict(list)
|
||||
for skin, locale, rel, issue in collect_all_issues():
|
||||
grouped[(skin, locale, rel)].append(issue)
|
||||
|
||||
for (skin, locale, rel), issues in sorted(grouped.items()):
|
||||
count = fix_file(skin, locale, rel, issues)
|
||||
if count:
|
||||
files_touched += 1
|
||||
total_fixed += count
|
||||
print(f"fixed {count:3d} {skin}/{locale}/{rel}")
|
||||
|
||||
remaining = count_remaining()
|
||||
print(f"\nTotal attributes fixed: {total_fixed} in {files_touched} files")
|
||||
print(f"Remaining bad attributes: {remaining}")
|
||||
return 0 if remaining == 0 else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -2816,18 +2816,6 @@ Bu mesaj yenidən baş verərsə, kömək üçün http://support.secondlife.com
|
||||
<string name="PicksClassifiedsLoadingText">
|
||||
Yüklənir...
|
||||
</string>
|
||||
<string name="NoPicksText">
|
||||
Seçilmiş yarartmamızınız.
|
||||
</string>
|
||||
<string name="NoAvatarPicksText">
|
||||
İstifadəçinin seçilmişləri yoxdur
|
||||
</string>
|
||||
<string name="NoClassifiedsText">
|
||||
Heç bir elan yaartmamızınız. Elan etmək üçün Yarat düyməsini basın.
|
||||
</string>
|
||||
<string name="NoAvatarClassifiedsText">
|
||||
İstifadəçinin elanları yoxdur
|
||||
</string>
|
||||
<string name="MultiPreviewTitle">
|
||||
Önizləmə
|
||||
</string>
|
||||
|
||||
@@ -4915,12 +4915,6 @@ Erfahren Sie mehr unter https://second.life/scripted-agents.
|
||||
<string name="share_alert">
|
||||
Objekte aus dem Inventar hier her ziehen
|
||||
</string>
|
||||
<string name="facebook_post_success">
|
||||
Sie haben auf Facebook gepostet.
|
||||
</string>
|
||||
<string name="facebook_post_success">
|
||||
Sie haben auf Facebook gepostet.
|
||||
</string>
|
||||
<string name="flickr_post_success">
|
||||
Sie haben auf Flickr gepostet.
|
||||
</string>
|
||||
@@ -5907,9 +5901,6 @@ Setzen Sie den Editorpfad in Anführungszeichen
|
||||
<string name="Command_AboutLand_Label">
|
||||
Landinformationen
|
||||
</string>
|
||||
<string name="Command_AboutLand_Label">
|
||||
Landinformationen
|
||||
</string>
|
||||
<string name="Command_360_Capture_Label">
|
||||
360° Foto
|
||||
</string>
|
||||
|
||||
@@ -2615,10 +2615,6 @@ Si sigues recibiendo el mismo mensaje, solicita ayuda al personal de asistencia
|
||||
<string name="PicksClassifiedsLoadingText">
|
||||
Cargando...
|
||||
</string>
|
||||
<string name="NoPicksText">No has creado ningún destacado.</string>
|
||||
<string name="NoAvatarPicksText">El usuario no tiene destacados</string>
|
||||
<string name="NoClassifiedsText">No has creado ningún clasificado. Pulsa el botón '+' para crear uno.</string>
|
||||
<string name="NoAvatarClassifiedsText">El usuario no tiene clasificados</string>
|
||||
<string name="MultiPreviewTitle">
|
||||
Vista previa
|
||||
</string>
|
||||
@@ -4598,9 +4594,6 @@ Más información en https://second.life/scripted-agents.
|
||||
<string name="share_alert">
|
||||
Arrastra aquí items del inventario
|
||||
</string>
|
||||
<string name="facebook_post_success">
|
||||
Has publicado en Facebook.
|
||||
</string>
|
||||
<string name="flickr_post_success">
|
||||
Has publicado en Flickr.
|
||||
</string>
|
||||
|
||||
@@ -5391,7 +5391,7 @@ Vous ne pouvez pas annuler cette action.
|
||||
</notification>
|
||||
<notification name="RemoveContactsFromSet">
|
||||
Êtes-vous sûr de vouloir supprimer ces avatars [TARGET] de [SET_NAME] ?
|
||||
<usetemplate gnoretext="Confirmer avant de supprimer plusieurs avatars d'un groupe de contacts" name="okcancelignore" notext="Cancel" yestext="OK"/>
|
||||
<usetemplate ignoretext="Confirmer avant de supprimer plusieurs avatars d'un groupe de contacts" name="okcancelignore" notext="Cancel" yestext="OK"/>
|
||||
</notification>
|
||||
<notification name="AddToContactSetSingleSuccess">
|
||||
[NAME] a été ajouté à [SET].
|
||||
|
||||
@@ -2826,18 +2826,6 @@ Si vous continuez à recevoir ce message, veuillez contacter l'assistance de Sec
|
||||
<string name="PicksClassifiedsLoadingText">
|
||||
Chargement...
|
||||
</string>
|
||||
<string name="NoPicksText">
|
||||
Vous n'avez pas créé de favoris.
|
||||
</string>
|
||||
<string name="NoAvatarPicksText">
|
||||
L'utilisateur n'a pas de favoris.
|
||||
</string>
|
||||
<string name="NoClassifiedsText">
|
||||
Vous n'avez pas créé d'annonces. Cliquez sur le bouton Plus ci-dessous pour créer une annonce.
|
||||
</string>
|
||||
<string name="NoAvatarClassifiedsText">
|
||||
L'utilisateur n'a pas d'annonces
|
||||
</string>
|
||||
<string name="MultiPreviewTitle">
|
||||
Prévisualiser
|
||||
</string>
|
||||
@@ -4863,9 +4851,6 @@ Pour en savoir plus, rendez-vous sur https://second.life/scripted-agents.
|
||||
<string name="share_alert">
|
||||
Faire glisser les objets de l'inventaire ici
|
||||
</string>
|
||||
<string name="facebook_post_success">
|
||||
Vous avez publié sur Facebook.
|
||||
</string>
|
||||
<string name="flickr_post_success">
|
||||
Vous avez publié sur Flickr.
|
||||
</string>
|
||||
|
||||
@@ -4774,9 +4774,6 @@ Scopri di più su https://second.life/scripted-agents.
|
||||
<string name="share_alert">
|
||||
Trascinare qui oggetti da inventario
|
||||
</string>
|
||||
<string name="facebook_post_success">
|
||||
Hai pubblicato su Facebook.
|
||||
</string>
|
||||
<string name="flickr_post_success">
|
||||
Hai pubblicato su Flickr.
|
||||
</string>
|
||||
|
||||
@@ -465,9 +465,6 @@ https://secondlife.com/viewer-access-faq
|
||||
<string name="TooltipFlagNoEdit">
|
||||
編集禁止
|
||||
</string>
|
||||
<string name="TooltipFlagNoEdit">
|
||||
グループ作成
|
||||
</string>
|
||||
<string name="TooltipFlagNotSafe">
|
||||
危険
|
||||
</string>
|
||||
@@ -1320,9 +1317,6 @@ https://secondlife.com/viewer-access-faq
|
||||
<string name="xml_file">
|
||||
XMLファイル
|
||||
</string>
|
||||
<string name="csv_files">
|
||||
CSVファイル
|
||||
</string>
|
||||
<string name="raw_file">
|
||||
RAWファイル
|
||||
</string>
|
||||
@@ -2001,9 +1995,6 @@ https://support.secondlife.com よりSecond Lifeのサポートまでお問い
|
||||
<string name="InvFolder Materials">
|
||||
マテリアル
|
||||
</string>
|
||||
<string name="InvFolder Settings">
|
||||
自然環境の設定
|
||||
</string>
|
||||
<!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
|
||||
<string name="InvFolder Friends">
|
||||
フレンド
|
||||
@@ -2872,19 +2863,6 @@ https://support.secondlife.com よりSecond Lifeのサポートまでお問い
|
||||
<string name="PicksClassifiedsLoadingText">
|
||||
読み込んでいます…
|
||||
</string>
|
||||
<!-- FS:KC legacy profiles -->
|
||||
<string name="NoPicksText">
|
||||
ピックを作成していません。
|
||||
</string>
|
||||
<string name="NoAvatarPicksText">
|
||||
このユーザーにはピックがありません。
|
||||
</string>
|
||||
<string name="NoClassifiedsText">
|
||||
クラシファイド広告を作成していません。作成するには、下にある「+」ボタンをクリックします。
|
||||
</string>
|
||||
<string name="NoAvatarClassifiedsText">
|
||||
このユーザーにはクラシファイド広告がありません。
|
||||
</string>
|
||||
<!-- Multi Preview Floater -->
|
||||
<string name="MultiPreviewTitle">
|
||||
プレビュー
|
||||
@@ -5726,7 +5704,6 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
|
||||
<string name="Command_Move_Lock_Label">移動ロック</string>
|
||||
<string name="Command_Blocklist_Label">ブロックリスト</string>
|
||||
<string name="Command_ResyncAnimations_Label">アニメーション再同期</string>
|
||||
<string name="Command_RegionTracker_Label">リージョントラッカー</string>
|
||||
<string name="Command_Group_Titles_Label">グループのタイトル</string>
|
||||
<string name="Command_Wearable_Favorites_Label">お気に入りの着用物やHUD</string>
|
||||
<string name="Command_RFO_Label">フレンドのみ表示</string>
|
||||
@@ -5815,9 +5792,6 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
|
||||
<string name="Command_Profile_Tooltip">
|
||||
自分のプロフィールの表示や編集を行います。
|
||||
</string>
|
||||
<string name="Command_RegionTracker_Tooltip">
|
||||
様々なリージョンの状況を追跡します。
|
||||
</string>
|
||||
<string name="Command_Report_Abuse_Tooltip">
|
||||
嫌がらせを報告します。
|
||||
</string>
|
||||
@@ -6391,9 +6365,6 @@ Rez時間:[OBJECT_REZ_TIME]
|
||||
<string name="preproc_toggle_warning">プリプロセッサを切り替えても、このエディターを閉じて再度開くまで完全には有効になりません。</string>
|
||||
<!-- <FS:Cron> FIRE-9335 -->
|
||||
<!-- <LSL Preprocessor -->
|
||||
<string name="preproc_toggle_warning">
|
||||
プリプロセッサの切り替えは、このエディタを閉じて再度開くまで完全には有効になりません。
|
||||
</string>
|
||||
<string name="fs_preprocessor_starting">
|
||||
[APP_NAME]プリプロセッサを開始しています…
|
||||
</string>
|
||||
|
||||
@@ -5364,9 +5364,6 @@ https://wiki.firestormviewer.org/fs_voice
|
||||
<notification name="ExodusFlickrUploadComplete">
|
||||
Ваш снимок теперь может быть просмотрен [https://www.flickr.com/photos/me/[ID] тут].
|
||||
</notification>
|
||||
<notification name="ExodusFlickrUploadComplete">
|
||||
Ваш снимок теперь можно просмотреть [https://www.flickr.com/photos/me/[ID] здесь].
|
||||
</notification>
|
||||
<notification name="FSPrimfeedUploadComplete">
|
||||
Ваш пост Primfeed теперь можно просмотреть [[PF_POSTURL] здесь].
|
||||
</notification>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
</fs_scroll_list>
|
||||
<button name="add_needle" label="新增"/>
|
||||
<button name="remove_needle" label="刪除"/>
|
||||
<button name="up_needle" label="上移" tooltip="將規則上移 1 個位置。"/>
|
||||
<button name="down_needle" label="下移" tooltip="將規則下移 1 個位置。"/>
|
||||
<button name="up_needle" label="上移" tool_tip="將規則上移 1 個位置。"/>
|
||||
<button name="down_needle" label="下移" tool_tip="將規則下移 1 個位置。"/>
|
||||
</layout_panel>
|
||||
<layout_panel name="filter_log_layout">
|
||||
<fs_scroll_list name="filter_log">
|
||||
|
||||
Reference in New Issue
Block a user