Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 175ae1a

Browse files
committed
misc
1 parent 46d0942 commit 175ae1a

10 files changed

+8122
-1
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
cpython
2-
locales
2+
locales
3+
.*
4+
__pycache__

check_untranslated.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python3
2+
import re
3+
import sys
4+
5+
def check_untranslated(filename):
6+
try:
7+
with open(filename, 'r', encoding='utf-8') as f:
8+
content = f.read()
9+
except FileNotFoundError:
10+
print(f'❌ ファイル {filename} が見つかりません')
11+
return
12+
13+
# POエントリを正確に分割
14+
entries = re.findall(r'#:.*?\nmsgid.*?\nmsgstr.*?(?=\n#:|$)', content, re.DOTALL)
15+
16+
untranslated_count = 0
17+
code_samples = 0
18+
translatable_untranslated = []
19+
20+
for i, entry in enumerate(entries):
21+
# msgidとmsgstrを抽出
22+
msgid_match = re.search(r'msgid\s+"(.*?)"', entry, re.DOTALL)
23+
msgstr_match = re.search(r'msgstr\s+"(.*?)"', entry, re.DOTALL)
24+
25+
if not msgid_match or not msgstr_match:
26+
continue
27+
28+
msgid_content = msgid_match.group(1)
29+
msgstr_content = msgstr_match.group(1)
30+
31+
# 空のmsgstrかチェック
32+
if msgstr_content.strip() == "":
33+
untranslated_count += 1
34+
35+
# コードサンプルまたは翻訳不要な内容かチェック
36+
is_code_or_no_translate = (
37+
# 空のmsgid
38+
msgid_content.strip() == "" or
39+
# プログラムコード
40+
'def ' in msgid_content or
41+
'class ' in msgid_content or
42+
'assert ' in msgid_content or
43+
'print(' in msgid_content or
44+
'return ' in msgid_content or
45+
'import ' in msgid_content or
46+
'>>>' in msgid_content or
47+
'raise ' in msgid_content or
48+
'if __name__' in msgid_content or
49+
'try:' in msgid_content or
50+
'except:' in msgid_content or
51+
# パス、URL、コマンド例
52+
('.py' in msgid_content and '/' in msgid_content) or
53+
('.txt' in msgid_content and '/' in msgid_content) or
54+
'http://' in msgid_content or
55+
'https://' in msgid_content or
56+
# バージョン番号のみ
57+
re.match(r'^\d+\.\d+$', msgid_content.strip()) or
58+
# PEPやissue番号のみ
59+
re.match(r'^:pep:`\d+`$', msgid_content.strip()) or
60+
re.match(r'^:gh:`\d+`$', msgid_content.strip()) or
61+
# 単一の技術用語(既に翻訳されているもの)
62+
msgid_content.strip() in ['Parameters', 'Examples:', 'Constant'] or
63+
# 改行のみの内容
64+
msgid_content.strip() == "\\n" or
65+
# 空白のみの内容
66+
re.match(r'^\\s*$', msgid_content)
67+
)
68+
69+
if is_code_or_no_translate:
70+
code_samples += 1
71+
else:
72+
# 翻訳可能だが未翻訳のエントリ
73+
translatable_untranslated.append({
74+
'entry_num': i + 1,
75+
'msgid': msgid_content[:100] + '...' if len(msgid_content) > 100 else msgid_content
76+
})
77+
78+
print(f'📊 翻訳状況レポート: {filename}')
79+
print(f'=' * 80)
80+
print(f'総未翻訳エントリ数: {untranslated_count}')
81+
print(f' - コードサンプル/翻訳不要: {code_samples}')
82+
print(f' - 翻訳が必要: {len(translatable_untranslated)}')
83+
84+
total_entries = len(entries)
85+
translated_entries = total_entries - untranslated_count
86+
translation_rate = (translated_entries / total_entries * 100) if total_entries > 0 else 0
87+
88+
print(f'翻訳完了率: {translation_rate:.1f}% ({translated_entries}/{total_entries})')
89+
90+
if len(translatable_untranslated) == 0:
91+
print('✅ すべての翻訳対象エントリが翻訳済みです!')
92+
else:
93+
print(f'⚠️ {len(translatable_untranslated)}個の翻訳対象エントリが未翻訳です')
94+
print()
95+
print('未翻訳エントリ一覧(最初の20個):')
96+
print('-' * 80)
97+
for entry in translatable_untranslated[:20]:
98+
print(f'{entry["entry_num"]:4d}: {entry["msgid"]}')
99+
100+
if len(translatable_untranslated) > 20:
101+
print(f'... 他 {len(translatable_untranslated) - 20}個')
102+
103+
print(f'=' * 80)
104+
105+
if __name__ == "__main__":
106+
filename = sys.argv[1] if len(sys.argv) > 1 else 'library/typing.po'
107+
check_untranslated(filename)

final_check_untranslated.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env python3
2+
import re
3+
import sys
4+
5+
def final_check_untranslated(filename):
6+
"""
7+
Final comprehensive check for untranslated entries
8+
"""
9+
with open(filename, 'r', encoding='utf-8') as f:
10+
content = f.read()
11+
12+
# Split into entries based on #: comments
13+
entries = re.split(r'\n(?=#:)', content)
14+
15+
untranslated_entries = []
16+
17+
for entry in entries:
18+
if not entry.strip() or '#: ../../library/typing.rst:' not in entry:
19+
continue
20+
21+
# Look for patterns: msgid ... msgstr ""
22+
# where msgstr is truly empty (no following quoted content)
23+
if 'msgid' in entry and 'msgstr' in entry:
24+
# Find the msgstr line and check if it's followed by actual translation
25+
lines = entry.split('\n')
26+
msgstr_found = False
27+
is_empty = True
28+
msgid_content = ""
29+
30+
for i, line in enumerate(lines):
31+
if line.startswith('msgid'):
32+
# Collect msgid content
33+
msgid_content = line
34+
j = i + 1
35+
while j < len(lines) and (lines[j].startswith('"') or lines[j].strip() == ''):
36+
if lines[j].startswith('"'):
37+
msgid_content += " " + lines[j]
38+
j += 1
39+
40+
if line.startswith('msgstr'):
41+
msgstr_found = True
42+
# Check if this msgstr line is just msgstr ""
43+
if line.strip() == 'msgstr ""':
44+
# Check if the next lines contain translation
45+
j = i + 1
46+
has_translation = False
47+
while j < len(lines) and not lines[j].startswith('#'):
48+
if lines[j].startswith('"') and lines[j].strip() != '""':
49+
has_translation = True
50+
break
51+
elif lines[j].startswith('msgid'):
52+
break
53+
j += 1
54+
55+
if not has_translation:
56+
# This is truly untranslated
57+
# But skip if it's clearly code
58+
msgid_clean = re.sub(r'"', '', msgid_content)
59+
if not any(x in msgid_clean for x in [
60+
'def ', 'class ', '>>>', 'import ', 'return ', 'print(',
61+
'assert ', 'raise ', 'try:', 'except:', 'if __name__'
62+
]) and msgid_clean.strip():
63+
untranslated_entries.append({
64+
'msgid': msgid_clean[:100] + '...' if len(msgid_clean) > 100 else msgid_clean,
65+
'location': re.search(r'#: (.*)', entry).group(1) if re.search(r'#: (.*)', entry) else 'unknown'
66+
})
67+
break
68+
69+
print(f'🔍 最終確認 - 未翻訳エントリ: {filename}')
70+
print(f'=' * 80)
71+
print(f'見つかった未翻訳エントリ: {len(untranslated_entries)}')
72+
73+
if untranslated_entries:
74+
print('\n未翻訳エントリ:')
75+
for i, entry in enumerate(untranslated_entries, 1):
76+
print(f'{i:3d}: {entry["location"]}')
77+
print(f' {entry["msgid"]}')
78+
print()
79+
else:
80+
print('✅ 未翻訳エントリは見つかりませんでした!')
81+
82+
print(f'=' * 80)
83+
84+
if __name__ == "__main__":
85+
filename = sys.argv[1] if len(sys.argv) > 1 else 'library/typing.po'
86+
final_check_untranslated(filename)

find_empty_msgstr.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python3
2+
import re
3+
import sys
4+
5+
def find_empty_msgstr(filename):
6+
"""Find entries with truly empty msgstr"""
7+
with open(filename, 'r', encoding='utf-8') as f:
8+
content = f.read()
9+
10+
# Pattern to match complete po entries
11+
pattern = r'(#:.*?\nmsgid.*?\nmsgstr[^\n]*(?:\n"[^"]*")*)'
12+
entries = re.findall(pattern, content, re.DOTALL)
13+
14+
empty_entries = []
15+
16+
for entry in entries:
17+
# Check if msgstr is truly empty (just msgstr "" with no following quoted strings)
18+
if re.search(r'msgstr ""\s*\n(?![\s]*")', entry):
19+
# Extract msgid content
20+
msgid_match = re.search(r'msgid\s+"([^"]*)"(?:\s*\n\s*"([^"]*)")*', entry)
21+
if msgid_match:
22+
msgid_content = msgid_match.group(1)
23+
if msgid_match.group(2):
24+
msgid_content += msgid_match.group(2)
25+
26+
# Skip obvious code examples
27+
if not any(x in msgid_content for x in ['def ', 'class ', '>>>', 'import ', 'return ']):
28+
if msgid_content.strip(): # Non-empty msgid
29+
empty_entries.append({
30+
'msgid': msgid_content,
31+
'entry': entry[:200] + '...' if len(entry) > 200 else entry
32+
})
33+
34+
print(f"Found {len(empty_entries)} truly empty msgstr entries:")
35+
for i, entry in enumerate(empty_entries[:10], 1):
36+
print(f"{i}: {entry['msgid']}")
37+
print(f" Entry: {entry['entry']}")
38+
print()
39+
40+
if __name__ == "__main__":
41+
filename = sys.argv[1] if len(sys.argv) > 1 else 'library/typing.po'
42+
find_empty_msgstr(filename)

0 commit comments

Comments
 (0)